firewall-util.c revision a8fbdf5424be099ba1b2b1ec261c02b8759d6b0c
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
/***
This file is part of systemd.
Copyright 2015 Lennart Poettering
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
systemd is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <alloca.h>
#include <endian.h>
#include <errno.h>
#include <stddef.h>
#include <string.h>
#include "alloc-util.h"
#include "firewall-util.h"
#include "in-addr-util.h"
#include "macro.h"
static int entry_fill_basics(
int protocol,
const char *in_interface,
const union in_addr_union *source,
unsigned source_prefixlen,
const char *out_interface,
const union in_addr_union *destination,
unsigned destination_prefixlen) {
return -EINVAL;
return -EINVAL;
if (in_interface) {
}
if (source) {
}
if (out_interface) {
}
if (destination) {
}
return 0;
}
int fw_add_masquerade(
bool add,
int af,
int protocol,
const union in_addr_union *source,
unsigned source_prefixlen,
const char *out_interface,
const union in_addr_union *destination,
unsigned destination_prefixlen) {
struct ipt_entry_target *t;
struct nf_nat_ipv4_multi_range_compat *mr;
int r;
return -EOPNOTSUPP;
return -EOPNOTSUPP;
h = iptc_init("nat");
if (!h)
return -errno;
XT_ALIGN(sizeof(struct ipt_entry_target)) +
XT_ALIGN(sizeof(struct nf_nat_ipv4_multi_range_compat));
/* Put together the entry we want to add or remove */
r = entry_fill_basics(entry, protocol, NULL, source, source_prefixlen, out_interface, destination, destination_prefixlen);
if (r < 0)
return r;
/* Fill in target part */
t = ipt_get_target(entry);
t->u.target_size =
XT_ALIGN(sizeof(struct ipt_entry_target)) +
XT_ALIGN(sizeof(struct nf_nat_ipv4_multi_range_compat));
/* Create a search mask entry */
if (add) {
return 0;
return -errno;
return -errno;
} else {
return 0;
return -errno;
}
}
if (!iptc_commit(h))
return -errno;
return 0;
}
int fw_add_local_dnat(
bool add,
int af,
int protocol,
const char *in_interface,
const union in_addr_union *source,
unsigned source_prefixlen,
const union in_addr_union *destination,
unsigned destination_prefixlen,
const union in_addr_union *remote,
const union in_addr_union *previous_remote) {
struct ipt_entry_target *t;
struct ipt_entry_match *m;
struct xt_addrtype_info_v1 *at;
struct nf_nat_ipv4_multi_range_compat *mr;
int r;
return -EOPNOTSUPP;
return -EOPNOTSUPP;
if (local_port <= 0)
return -EINVAL;
if (remote_port <= 0)
return -EINVAL;
h = iptc_init("nat");
if (!h)
return -errno;
XT_ALIGN(sizeof(struct ipt_entry_match)) +
XT_ALIGN(sizeof(struct xt_addrtype_info_v1)) +
XT_ALIGN(sizeof(struct ipt_entry_target)) +
XT_ALIGN(sizeof(struct nf_nat_ipv4_multi_range_compat));
if (protocol == IPPROTO_TCP)
else
/* Fill in basic part */
XT_ALIGN(sizeof(struct ipt_entry_match)) +
XT_ALIGN(sizeof(struct xt_addrtype_info_v1)) +
msz;
r = entry_fill_basics(entry, protocol, in_interface, source, source_prefixlen, NULL, destination, destination_prefixlen);
if (r < 0)
return r;
/* Fill in first match */
m->u.match_size = msz;
if (protocol == IPPROTO_TCP) {
} else {
}
/* Fill in second match */
m->u.match_size =
XT_ALIGN(sizeof(struct ipt_entry_match)) +
XT_ALIGN(sizeof(struct xt_addrtype_info_v1));
/* Fill in target part */
t = ipt_get_target(entry);
t->u.target_size =
XT_ALIGN(sizeof(struct ipt_entry_target)) +
XT_ALIGN(sizeof(struct nf_nat_ipv4_multi_range_compat));
if (protocol == IPPROTO_TCP)
else
if (add) {
/* Add the PREROUTING rule, if it is missing so far */
return -EINVAL;
return -errno;
}
/* If a previous remote is set, remove its entry */
return -errno;
}
}
/* Add the OUTPUT rule, if it is missing so far */
if (!in_interface) {
/* Don't apply onto loopback addresses */
if (!destination) {
}
return -errno;
return -errno;
}
/* If a previous remote is set, remove its entry */
return -errno;
}
}
}
} else {
return -errno;
}
if (!in_interface) {
if (!destination) {
}
return -errno;
}
}
}
if (!iptc_commit(h))
return -errno;
return 0;
}