contrib/fwd: rewrite rule generate to use xtables api
This commit is contained in:
parent
a833e120b7
commit
0f791a7fb6
6 changed files with 363 additions and 327 deletions
|
@ -1,4 +1,4 @@
|
|||
CFLAGS := -g -Wall -I./uci -I./iptables-1.4.5/include
|
||||
CFLAGS := -ggdb3 -O0 -Wall -I./uci -I./iptables-1.4.5/include
|
||||
LDFLAGS := -luci -liptc -lxtables -ldl -L./iptables-1.4.5/libiptc/.libs -L./iptables-1.4.5/.libs -Wl,--export-dynamic
|
||||
|
||||
fwd:
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include <unistd.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <getopt.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#if 0
|
||||
|
@ -103,6 +104,9 @@ struct fwd_defaults {
|
|||
struct fwd_zone {
|
||||
char *name;
|
||||
struct fwd_network_list *networks;
|
||||
struct fwd_data *forwardings;
|
||||
struct fwd_data *redirects;
|
||||
struct fwd_data *rules;
|
||||
enum fwd_policy input;
|
||||
enum fwd_policy forward;
|
||||
enum fwd_policy output;
|
||||
|
@ -127,6 +131,7 @@ struct fwd_redirect {
|
|||
struct fwd_cidr *dest_ip;
|
||||
struct fwd_portrange *dest_port;
|
||||
struct fwd_proto *proto;
|
||||
int clone; /* true if rule is cloned (tcpudp -> tcp + udp) */
|
||||
};
|
||||
|
||||
struct fwd_rule {
|
||||
|
@ -140,6 +145,7 @@ struct fwd_rule {
|
|||
struct fwd_proto *proto;
|
||||
struct fwd_icmptype *icmp_type;
|
||||
enum fwd_policy target;
|
||||
int clone; /* true if rule is cloned (tcpudp -> tcp + udp) */
|
||||
};
|
||||
|
||||
struct fwd_include {
|
||||
|
|
|
@ -95,8 +95,8 @@ struct fwd_addr_list * fwd_get_addrs(int fd, int family)
|
|||
{
|
||||
if( rtatp->rta_type == IFA_ADDRESS )
|
||||
{
|
||||
memcpy(&entry->ipaddr, (char *) RTA_DATA(rtatp), rtatp->rta_len);
|
||||
entry->prefix = rtmp->ifa_prefixlen;
|
||||
memcpy(&entry->ipaddr.addr, (char *) RTA_DATA(rtatp), rtatp->rta_len);
|
||||
entry->ipaddr.prefix = rtmp->ifa_prefixlen;
|
||||
entry->family = family;
|
||||
}
|
||||
else if( rtatp->rta_type == IFA_LABEL)
|
||||
|
|
|
@ -33,11 +33,7 @@ struct fwd_addr_list {
|
|||
char label[IFNAMSIZ];
|
||||
int family;
|
||||
int index;
|
||||
unsigned int prefix;
|
||||
union {
|
||||
struct in_addr v4;
|
||||
struct in6_addr v6;
|
||||
} ipaddr;
|
||||
struct fwd_cidr ipaddr;
|
||||
struct fwd_addr_list *next;
|
||||
};
|
||||
|
||||
|
|
|
@ -163,11 +163,17 @@ fwd_read_mac(struct uci_context *uci, const char *s, const char *o, struct fwd_m
|
|||
{
|
||||
if( (*m = fwd_alloc_ptr(struct fwd_mac)) != NULL )
|
||||
{
|
||||
unsigned int i1, i2, i3, i4, i5, i6;
|
||||
|
||||
if( sscanf(val, "%2x:%2x:%2x:%2x:%2x:%2x",
|
||||
(unsigned int *)&(*m)->mac[0], (unsigned int *)&(*m)->mac[1],
|
||||
(unsigned int *)&(*m)->mac[2], (unsigned int *)&(*m)->mac[3],
|
||||
(unsigned int *)&(*m)->mac[4], (unsigned int *)&(*m)->mac[5]) == 6
|
||||
&i1, &i2, &i3, &i4, &i5, &i6) == 6
|
||||
) {
|
||||
(*m)->mac[0] = (unsigned char)i1;
|
||||
(*m)->mac[1] = (unsigned char)i2;
|
||||
(*m)->mac[2] = (unsigned char)i3;
|
||||
(*m)->mac[3] = (unsigned char)i4;
|
||||
(*m)->mac[4] = (unsigned char)i5;
|
||||
(*m)->mac[5] = (unsigned char)i6;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -470,17 +476,14 @@ static void fwd_read_forwards_cb(
|
|||
struct fwd_zone *zsrc = NULL;
|
||||
struct fwd_zone *zdest = NULL;
|
||||
|
||||
if( (src = fwd_read_string(uci, s, "src")) != NULL )
|
||||
{
|
||||
if( !(zsrc = fwd_lookup_zone(cv->head, src)) )
|
||||
if( !(src = fwd_read_string(uci, s, "src")) )
|
||||
fwd_read_error("section '%s' is missing 'src' option!", s);
|
||||
else if( !(zsrc = fwd_lookup_zone(cv->head, src)) )
|
||||
fwd_read_error("section '%s' references unknown src zone '%s'!", s, src);
|
||||
}
|
||||
|
||||
if( (dest = fwd_read_string(uci, s, "dest")) != NULL )
|
||||
{
|
||||
if( !(zdest = fwd_lookup_zone(cv->head, dest)) )
|
||||
else if( !(dest = fwd_read_string(uci, s, "dest")) )
|
||||
fwd_read_error("section '%s' is missing 'dest' option!", s);
|
||||
else if( !(zdest = fwd_lookup_zone(cv->head, dest)) )
|
||||
fwd_read_error("section '%s' references unknown dest zone '%s'!", s, dest);
|
||||
}
|
||||
|
||||
if( (dtn = fwd_alloc_ptr(struct fwd_data)) != NULL )
|
||||
{
|
||||
|
@ -490,9 +493,18 @@ static void fwd_read_forwards_cb(
|
|||
dtn->section.forwarding.masq = fwd_read_bool(uci, s, "masq", 0);
|
||||
|
||||
dtn->type = FWD_S_FORWARD;
|
||||
|
||||
if( zsrc )
|
||||
{
|
||||
dtn->next = zsrc->forwardings;
|
||||
zsrc->forwardings = dtn;
|
||||
}
|
||||
else
|
||||
{
|
||||
dtn->next = cv->cursor;
|
||||
cv->cursor = dtn;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fwd_read_error("out of memory while parsing config!");
|
||||
|
@ -560,8 +572,8 @@ static void fwd_read_redirects_cb(
|
|||
dtn->section.redirect.dest_port = dest_port;
|
||||
|
||||
dtn->type = FWD_S_REDIRECT;
|
||||
dtn->next = cv->cursor;
|
||||
cv->cursor = dtn;
|
||||
dtn->next = zsrc->redirects;
|
||||
zsrc->redirects = dtn;
|
||||
|
||||
if( (proto != NULL) && (proto->type == FWD_PR_TCPUDP) )
|
||||
{
|
||||
|
@ -582,10 +594,11 @@ static void fwd_read_redirects_cb(
|
|||
dtn2->section.redirect.src_dport = src_dport;
|
||||
dtn2->section.redirect.dest_ip = dest_ip;
|
||||
dtn2->section.redirect.dest_port = dest_port;
|
||||
dtn2->section.redirect.clone = 1;
|
||||
|
||||
dtn2->type = FWD_S_REDIRECT;
|
||||
dtn2->next = cv->cursor;
|
||||
cv->cursor = dtn2;
|
||||
dtn2->next = zsrc->redirects;
|
||||
zsrc->redirects = dtn2;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -665,8 +678,8 @@ static void fwd_read_rules_cb(
|
|||
dtn->section.rule.target = fwd_read_policy(uci, s, "target");
|
||||
|
||||
dtn->type = FWD_S_RULE;
|
||||
dtn->next = cv->cursor;
|
||||
cv->cursor = dtn;
|
||||
dtn->next = zsrc->rules;
|
||||
zsrc->rules = dtn;
|
||||
|
||||
if( (proto != NULL) && (proto->type == FWD_PR_TCPUDP) )
|
||||
{
|
||||
|
@ -688,10 +701,11 @@ static void fwd_read_rules_cb(
|
|||
dtn2->section.rule.dest_ip = dest_ip;
|
||||
dtn2->section.rule.dest_port = dest_port;
|
||||
dtn2->section.rule.target = dtn->section.rule.target;
|
||||
dtn2->section.rule.clone = 1;
|
||||
|
||||
dtn2->type = FWD_S_RULE;
|
||||
dtn2->next = cv->cursor;
|
||||
cv->cursor = dtn2;
|
||||
dtn2->next = zsrc->rules;
|
||||
zsrc->rules = dtn2;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -868,26 +882,39 @@ void fwd_free_config(struct fwd_data *h)
|
|||
case FWD_S_ZONE:
|
||||
fwd_free_ptr(h->section.zone.name);
|
||||
fwd_free_networks(h->section.zone.networks);
|
||||
fwd_free_config(h->section.zone.rules);
|
||||
fwd_free_config(h->section.zone.redirects);
|
||||
fwd_free_config(h->section.zone.forwardings);
|
||||
break;
|
||||
|
||||
case FWD_S_REDIRECT:
|
||||
/* Clone rules share all pointers except proto.
|
||||
Prevent a double-free here */
|
||||
if( ! h->section.redirect.clone )
|
||||
{
|
||||
fwd_free_ptr(h->section.redirect.src_ip);
|
||||
fwd_free_ptr(h->section.redirect.src_mac);
|
||||
fwd_free_ptr(h->section.redirect.src_port);
|
||||
fwd_free_ptr(h->section.redirect.src_dport);
|
||||
fwd_free_ptr(h->section.redirect.dest_ip);
|
||||
fwd_free_ptr(h->section.redirect.dest_port);
|
||||
}
|
||||
fwd_free_ptr(h->section.redirect.proto);
|
||||
break;
|
||||
|
||||
case FWD_S_RULE:
|
||||
/* Clone rules share all pointers except proto.
|
||||
Prevent a double-free here */
|
||||
if( ! h->section.rule.clone )
|
||||
{
|
||||
fwd_free_ptr(h->section.rule.src_ip);
|
||||
fwd_free_ptr(h->section.rule.src_mac);
|
||||
fwd_free_ptr(h->section.rule.src_port);
|
||||
fwd_free_ptr(h->section.rule.dest_ip);
|
||||
fwd_free_ptr(h->section.rule.dest_port);
|
||||
fwd_free_ptr(h->section.rule.proto);
|
||||
fwd_free_ptr(h->section.rule.icmp_type);
|
||||
}
|
||||
fwd_free_ptr(h->section.rule.proto);
|
||||
break;
|
||||
|
||||
case FWD_S_DEFAULTS:
|
||||
|
@ -896,7 +923,7 @@ void fwd_free_config(struct fwd_data *h)
|
|||
break;
|
||||
}
|
||||
|
||||
free(h);
|
||||
fwd_free_ptr(h);
|
||||
h = e;
|
||||
}
|
||||
|
||||
|
|
|
@ -22,199 +22,6 @@
|
|||
#include "fwd_rules.h"
|
||||
#include "fwd_xtables.h"
|
||||
|
||||
static void
|
||||
fwd_ipt_rule_append(struct fwd_ipt_rulebuf *r, const char *fmt, ...)
|
||||
{
|
||||
int len = 0;
|
||||
char buf[256]; buf[0] = 0;
|
||||
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
len = vsnprintf(buf, sizeof(buf), fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
if( len > 0 )
|
||||
{
|
||||
r->buf = realloc(r->buf, r->len + len + 1);
|
||||
memcpy(&r->buf[r->len], buf, len);
|
||||
r->buf[r->len + len] = 0;
|
||||
r->len += len;
|
||||
}
|
||||
}
|
||||
|
||||
static struct fwd_ipt_rulebuf * fwd_ipt_init(const char *table)
|
||||
{
|
||||
struct fwd_ipt_rulebuf *r;
|
||||
|
||||
if( (r = fwd_alloc_ptr(struct fwd_ipt_rulebuf)) != NULL )
|
||||
{
|
||||
fwd_ipt_rule_append(r, IPT " -t %s", table);
|
||||
return r;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void fwd_ipt_add_srcport(
|
||||
struct fwd_ipt_rulebuf *r, struct fwd_portrange *p
|
||||
) {
|
||||
if( p != NULL )
|
||||
{
|
||||
if( p->min < p->max )
|
||||
fwd_ipt_rule_append(r, " --sport %u:%u", p->min, p->max);
|
||||
else
|
||||
fwd_ipt_rule_append(r, " --sport %u", p->min);
|
||||
}
|
||||
}
|
||||
|
||||
static void fwd_ipt_add_destport(
|
||||
struct fwd_ipt_rulebuf *r, struct fwd_portrange *p
|
||||
) {
|
||||
if( p != NULL )
|
||||
{
|
||||
if( p->min < p->max )
|
||||
fwd_ipt_rule_append(r, " --dport %u:%u", p->min, p->max);
|
||||
else
|
||||
fwd_ipt_rule_append(r, " --dport %u", p->min);
|
||||
}
|
||||
}
|
||||
|
||||
static void fwd_ipt_add_proto(
|
||||
struct fwd_ipt_rulebuf *r, struct fwd_proto *p
|
||||
) {
|
||||
if( p != NULL )
|
||||
{
|
||||
switch( p->type )
|
||||
{
|
||||
case FWD_PR_TCPUDP:
|
||||
fwd_ipt_rule_append(r, " -p tcp -p udp");
|
||||
break;
|
||||
|
||||
case FWD_PR_TCP:
|
||||
fwd_ipt_rule_append(r, " -p tcp");
|
||||
break;
|
||||
|
||||
case FWD_PR_UDP:
|
||||
fwd_ipt_rule_append(r, " -p udp");
|
||||
break;
|
||||
|
||||
case FWD_PR_ICMP:
|
||||
fwd_ipt_rule_append(r, " -p icmp");
|
||||
break;
|
||||
|
||||
case FWD_PR_ALL:
|
||||
fwd_ipt_rule_append(r, " -p all");
|
||||
break;
|
||||
|
||||
case FWD_PR_CUSTOM:
|
||||
fwd_ipt_rule_append(r, " -p %u", p->proto);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void fwd_ipt_add_srcaddr(
|
||||
struct fwd_ipt_rulebuf *r, struct fwd_cidr *c
|
||||
) {
|
||||
if( c != NULL )
|
||||
{
|
||||
if( c->prefix < 32 )
|
||||
fwd_ipt_rule_append(r, " -s %s/%u",
|
||||
inet_ntoa(c->addr), c->prefix);
|
||||
else
|
||||
fwd_ipt_rule_append(r, " -s %s", inet_ntoa(c->addr));
|
||||
}
|
||||
}
|
||||
|
||||
static void fwd_ipt_add_destaddr(
|
||||
struct fwd_ipt_rulebuf *r, struct fwd_cidr *c
|
||||
) {
|
||||
if( c != NULL )
|
||||
{
|
||||
if( c->prefix < 32 )
|
||||
fwd_ipt_rule_append(r, " -d %s/%u",
|
||||
inet_ntoa(c->addr), c->prefix);
|
||||
else
|
||||
fwd_ipt_rule_append(r, " -d %s", inet_ntoa(c->addr));
|
||||
}
|
||||
}
|
||||
|
||||
static void fwd_ipt_add_srcmac(
|
||||
struct fwd_ipt_rulebuf *r, struct fwd_mac *m
|
||||
) {
|
||||
if( m != NULL )
|
||||
{
|
||||
fwd_ipt_rule_append(r,
|
||||
" -m mac --mac-source %02x:%02x:%02x:%02x:%02x:%02x",
|
||||
m->mac[0], m->mac[1], m->mac[2],
|
||||
m->mac[3], m->mac[4], m->mac[5]);
|
||||
}
|
||||
}
|
||||
|
||||
static void fwd_ipt_add_icmptype(
|
||||
struct fwd_ipt_rulebuf *r, struct fwd_icmptype *i
|
||||
) {
|
||||
if( i != NULL )
|
||||
{
|
||||
if( i->name )
|
||||
fwd_ipt_rule_append(r, " --icmp-type %s", i->name);
|
||||
else if( i->code > -1 )
|
||||
fwd_ipt_rule_append(r, " --icmp-type %u/%u", i->type, i->code);
|
||||
else
|
||||
fwd_ipt_rule_append(r, " --icmp-type %u", i->type);
|
||||
}
|
||||
}
|
||||
|
||||
static void fwd_ipt_add_dnat_target(
|
||||
struct fwd_ipt_rulebuf *r, struct fwd_cidr *c, struct fwd_portrange *p
|
||||
) {
|
||||
if( c != NULL )
|
||||
{
|
||||
fwd_ipt_rule_append(r, " -j DNAT --to-destination %s",
|
||||
inet_ntoa(c->addr));
|
||||
|
||||
if( (p != NULL) && (p->min < p->max) )
|
||||
fwd_ipt_rule_append(r, ":%u-%u", p->min, p->max);
|
||||
else if( p != NULL )
|
||||
fwd_ipt_rule_append(r, ":%u", p->min);
|
||||
}
|
||||
}
|
||||
|
||||
static void fwd_ipt_add_policy_target(
|
||||
struct fwd_ipt_rulebuf *r, enum fwd_policy p
|
||||
) {
|
||||
fwd_ipt_rule_append(r, " -j %s",
|
||||
(p == FWD_P_ACCEPT)
|
||||
? "handle_accept"
|
||||
: (p == FWD_P_REJECT)
|
||||
? "handle_reject"
|
||||
: "handle_drop"
|
||||
);
|
||||
}
|
||||
|
||||
static void fwd_ipt_add_comment(
|
||||
struct fwd_ipt_rulebuf *r, const char *t, struct fwd_zone *z,
|
||||
struct fwd_network_list *n, struct fwd_network_list *n2
|
||||
) {
|
||||
if( (n != NULL) && (n2 != NULL) )
|
||||
fwd_ipt_add_format(r, " -m comment --comment '%s:%s src:%s dest:%s'",
|
||||
t, z->name, n->name, n2->name);
|
||||
else if( (n == NULL) && (n2 != NULL) )
|
||||
fwd_ipt_add_format(r, " -m comment --comment '%s:%s dest:%s'",
|
||||
t, z->name, n2->name);
|
||||
else
|
||||
fwd_ipt_add_format(r, " -m comment --comment '%s:%s src:%s'",
|
||||
t, z->name, n->name);
|
||||
}
|
||||
|
||||
static void fwd_ipt_exec(struct fwd_ipt_rulebuf *r)
|
||||
{
|
||||
if( r->len )
|
||||
printf("%s\n", r->buf);
|
||||
|
||||
fwd_free_ptr(r->buf);
|
||||
fwd_free_ptr(r);
|
||||
}
|
||||
|
||||
/* -P <chain> <policy> */
|
||||
static void fwd_r_set_policy(
|
||||
|
@ -252,7 +59,7 @@ static void fwd_r_drop_invalid(struct iptc_handle *h, const char *chain)
|
|||
{
|
||||
if( (m = fwd_xt_get_match(r, "state")) != NULL )
|
||||
{
|
||||
fwd_xt_parse_match(r, m, "--state", "INVALID", 0);
|
||||
fwd_xt_parse_match(r, m, "--state", "INVALID");
|
||||
fwd_xt_get_target(r, "DROP");
|
||||
fwd_xt_exec_rule(r, chain);
|
||||
}
|
||||
|
@ -269,7 +76,7 @@ static void fwd_r_accept_related(struct iptc_handle *h, const char *chain)
|
|||
{
|
||||
if( (m = fwd_xt_get_match(r, "state")) != NULL )
|
||||
{
|
||||
fwd_xt_parse_match(r, m, "--state", "RELATED,ESTABLISHED", 0);
|
||||
fwd_xt_parse_match(r, m, "--state", "RELATED,ESTABLISHED");
|
||||
fwd_xt_get_target(r, "ACCEPT");
|
||||
fwd_xt_exec_rule(r, chain);
|
||||
}
|
||||
|
@ -320,17 +127,17 @@ static void fwd_r_add_synflood(struct iptc_handle *h, struct fwd_defaults *def)
|
|||
/* -m tcp --syn */
|
||||
if( (m = fwd_xt_get_match(r, "tcp")) != NULL )
|
||||
{
|
||||
fwd_xt_parse_match(r, m, "--syn", NULL, 0);
|
||||
fwd_xt_parse_match(r, m, "--syn");
|
||||
}
|
||||
|
||||
/* -m limit --limit x/second --limit-burst y */
|
||||
if( (m = fwd_xt_get_match(r, "limit")) != NULL )
|
||||
{
|
||||
sprintf(buf, "%i/second", def->syn_rate);
|
||||
fwd_xt_parse_match(r, m, "--limit", buf, 0);
|
||||
fwd_xt_parse_match(r, m, "--limit", buf);
|
||||
|
||||
sprintf(buf, "%i", def->syn_burst);
|
||||
fwd_xt_parse_match(r, m, "--limit-burst", buf, 0);
|
||||
fwd_xt_parse_match(r, m, "--limit-burst", buf);
|
||||
}
|
||||
|
||||
/* -j RETURN; -A syn_flood */
|
||||
|
@ -356,7 +163,7 @@ static void fwd_r_add_synflood(struct iptc_handle *h, struct fwd_defaults *def)
|
|||
/* -m tcp --syn */
|
||||
if( (m = fwd_xt_get_match(r, "tcp")) != NULL )
|
||||
{
|
||||
fwd_xt_parse_match(r, m, "--syn", NULL, 0);
|
||||
fwd_xt_parse_match(r, m, "--syn");
|
||||
}
|
||||
|
||||
/* -j syn_flood; -A INPUT */
|
||||
|
@ -385,7 +192,7 @@ static void fwd_r_handle_reject(struct iptc_handle *h)
|
|||
/* -j REJECT --reject-with tcp-reset */
|
||||
if( (t = fwd_xt_get_target(r, "REJECT")) != NULL )
|
||||
{
|
||||
fwd_xt_parse_target(r, t, "--reject-with", "tcp-reset", 0);
|
||||
fwd_xt_parse_target(r, t, "--reject-with", "tcp-reset");
|
||||
}
|
||||
|
||||
/* -A handle_reject */
|
||||
|
@ -399,7 +206,7 @@ static void fwd_r_handle_reject(struct iptc_handle *h)
|
|||
if( (t = fwd_xt_get_target(r, "REJECT")) != NULL )
|
||||
{
|
||||
fwd_xt_parse_target(r, t, "--reject-with",
|
||||
"icmp-port-unreachable", 0);
|
||||
"icmp-port-unreachable");
|
||||
}
|
||||
|
||||
/* -A handle_reject */
|
||||
|
@ -441,6 +248,155 @@ static void fwd_r_handle_accept(struct iptc_handle *h)
|
|||
}
|
||||
}
|
||||
|
||||
/* add comment match */
|
||||
static void fwd_r_add_comment(
|
||||
struct fwd_xt_rule *r, const char *t, struct fwd_zone *z,
|
||||
struct fwd_network_list *n, struct fwd_network_list *n2
|
||||
) {
|
||||
struct xtables_match *m;
|
||||
char buf[256];
|
||||
|
||||
if( (m = fwd_xt_get_match(r, "comment")) != NULL )
|
||||
{
|
||||
if( (n != NULL) && (n2 != NULL) )
|
||||
snprintf(buf, sizeof(buf), "%s:%s src:%s dest:%s",
|
||||
t, z->name, n->name, n2->name);
|
||||
else if( (n == NULL) && (n2 != NULL) )
|
||||
snprintf(buf, sizeof(buf), "%s:%s dest:%s", t, z->name, n2->name);
|
||||
else
|
||||
snprintf(buf, sizeof(buf), "%s:%s src:%s", t, z->name, n->name);
|
||||
|
||||
fwd_xt_parse_match(r, m, "--comment", buf);
|
||||
}
|
||||
}
|
||||
|
||||
/* add --sport (if applicable) */
|
||||
static void fwd_r_add_sport(
|
||||
struct fwd_xt_rule *r, struct fwd_portrange *p
|
||||
) {
|
||||
int proto = r->entry->ip.proto;
|
||||
char buf[12];
|
||||
struct xtables_match *m;
|
||||
|
||||
/* have portrange and proto is tcp or udp ... */
|
||||
if( (p != NULL) && ((proto == 6) || (proto == 17)) )
|
||||
{
|
||||
/* get match ... */
|
||||
if( (m = fwd_xt_get_match(r, (proto == 6) ? "tcp" : "udp")) != NULL )
|
||||
{
|
||||
snprintf(buf, sizeof(buf), "%u:%u", p->min, p->max);
|
||||
fwd_xt_parse_match(r, m, "--sport", buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* add --dport (if applicable) */
|
||||
static void fwd_r_add_dport(
|
||||
struct fwd_xt_rule *r, struct fwd_portrange *p
|
||||
) {
|
||||
int proto = r->entry->ip.proto;
|
||||
char buf[12];
|
||||
struct xtables_match *m;
|
||||
|
||||
/* have portrange and proto is tcp or udp ... */
|
||||
if( (p != NULL) && ((proto == 6) || (proto == 17)) )
|
||||
{
|
||||
/* get match ... */
|
||||
if( (m = fwd_xt_get_match(r, (proto == 6) ? "tcp" : "udp")) != NULL )
|
||||
{
|
||||
snprintf(buf, sizeof(buf), "%u:%u", p->min, p->max);
|
||||
fwd_xt_parse_match(r, m, "--dport", buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* add --icmp-type (of applicable) */
|
||||
static void fwd_r_add_icmptype(
|
||||
struct fwd_xt_rule *r, struct fwd_icmptype *i
|
||||
) {
|
||||
int proto = r->entry->ip.proto;
|
||||
struct xtables_match *m;
|
||||
char buf[32];
|
||||
|
||||
/* have icmp-type and proto is icmp ... */
|
||||
if( (i != NULL) && (proto == 1) )
|
||||
{
|
||||
/* get match ... */
|
||||
if( (m = fwd_xt_get_match(r, "icmp")) != NULL )
|
||||
{
|
||||
if( i->name[0] )
|
||||
snprintf(buf, sizeof(buf), "%s", i->name);
|
||||
else
|
||||
snprintf(buf, sizeof(buf), "%u/%u", i->type, i->code);
|
||||
|
||||
fwd_xt_parse_match(r, m, "--icmp-type", buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* add -m mac --mac-source ... */
|
||||
static void fwd_r_add_srcmac(
|
||||
struct fwd_xt_rule *r, struct fwd_mac *mac
|
||||
) {
|
||||
struct xtables_match *m;
|
||||
char buf[18];
|
||||
|
||||
if( mac != NULL )
|
||||
{
|
||||
if( (m = fwd_xt_get_match(r, "mac")) != NULL )
|
||||
{
|
||||
snprintf(buf, sizeof(buf), "%02x:%02x:%02x:%02x:%02x:%02x",
|
||||
mac->mac[0], mac->mac[1], mac->mac[2],
|
||||
mac->mac[3], mac->mac[4], mac->mac[5]);
|
||||
|
||||
fwd_xt_parse_match(r, m, "--mac-source", buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* add policy target */
|
||||
static void fwd_r_add_policytarget(
|
||||
struct fwd_xt_rule *r, enum fwd_policy pol
|
||||
) {
|
||||
switch(pol)
|
||||
{
|
||||
case FWD_P_ACCEPT:
|
||||
fwd_xt_get_target(r, "handle_accept");
|
||||
break;
|
||||
|
||||
case FWD_P_REJECT:
|
||||
fwd_xt_get_target(r, "handle_reject");
|
||||
break;
|
||||
|
||||
case FWD_P_DROP:
|
||||
case FWD_P_UNSPEC:
|
||||
fwd_xt_get_target(r, "handle_drop");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* add dnat target */
|
||||
static void fwd_r_add_dnattarget(
|
||||
struct fwd_xt_rule *r, struct fwd_cidr *c, struct fwd_portrange *p
|
||||
) {
|
||||
struct xtables_target *t;
|
||||
char buf[32];
|
||||
|
||||
if( c != NULL )
|
||||
{
|
||||
if( (t = fwd_xt_get_target(r, "DNAT")) != NULL )
|
||||
{
|
||||
if( p != NULL )
|
||||
snprintf(buf, sizeof(buf), "%s:%u-%u",
|
||||
inet_ntoa(c->addr), p->min, p->max);
|
||||
else
|
||||
snprintf(buf, sizeof(buf), "%s", inet_ntoa(c->addr));
|
||||
|
||||
fwd_xt_parse_target(r, t, "--to-destination", buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void fwd_ipt_defaults_create(struct fwd_data *d)
|
||||
{
|
||||
|
@ -494,9 +450,10 @@ static void fwd_ipt_defaults_create(struct fwd_data *d)
|
|||
fwd_r_jump_chain(h_filter, "FORWARD", "forwardings");
|
||||
fwd_r_new_chain(h_nat, "zonemasq");
|
||||
fwd_r_new_chain(h_nat, "redirects");
|
||||
fwd_r_new_chain(h_nat, "loopback");
|
||||
fwd_r_jump_chain(h_nat, "POSTROUTING", "zonemasq");
|
||||
fwd_r_jump_chain(h_nat, "PREROUTING", "redirects");
|
||||
fwd_r_jump_chain(h_nat, "POSTROUTING", "redirects");
|
||||
fwd_r_jump_chain(h_nat, "POSTROUTING", "loopback");
|
||||
|
||||
/* standard drop, accept, reject chain */
|
||||
fwd_r_handle_drop(h_filter);
|
||||
|
@ -589,12 +546,22 @@ void fwd_ipt_addif(struct fwd_handle *h, const char *net)
|
|||
{
|
||||
struct fwd_data *e;
|
||||
struct fwd_zone *z;
|
||||
struct fwd_ipt_rulebuf *b;
|
||||
struct fwd_rule *c;
|
||||
struct fwd_redirect *r;
|
||||
struct fwd_forwarding *f;
|
||||
struct fwd_addr_list *a, *a2;
|
||||
struct fwd_network_list *n, *n2;
|
||||
struct fwd_proto p;
|
||||
|
||||
struct fwd_xt_rule *x;
|
||||
struct xtables_match *m;
|
||||
struct xtables_target *t;
|
||||
|
||||
struct iptc_handle *h_filter, *h_nat;
|
||||
|
||||
if( !(h_filter = iptc_init("filter")) || !(h_nat = iptc_init("nat")) )
|
||||
fwd_fatal("Unable to obtain libiptc handle");
|
||||
|
||||
|
||||
if( !(z = fwd_lookup_zone(h, net)) )
|
||||
return;
|
||||
|
@ -612,10 +579,13 @@ void fwd_ipt_addif(struct fwd_handle *h, const char *net)
|
|||
{
|
||||
printf("\n# Net %s (%s) - masq\n", n->name, n->ifname);
|
||||
|
||||
b = fwd_ipt_init("nat");
|
||||
fwd_ipt_add_format(b, " -A zonemasq -o %s -j MASQUERADE", n->ifname);
|
||||
fwd_ipt_add_comment(b, "masq", z, NULL, n);
|
||||
fwd_ipt_exec(b);
|
||||
if( (x = fwd_xt_init_rule(h_nat)) != NULL )
|
||||
{
|
||||
fwd_xt_parse_out(x, n, 0); /* -o ... */
|
||||
fwd_xt_get_target(x, "MASQUERADE"); /* -j MASQUERADE */
|
||||
fwd_r_add_comment(x, "masq", z, NULL, n); /* -m comment ... */
|
||||
fwd_xt_exec_rule(x, "zonemasq"); /* -A zonemasq */
|
||||
}
|
||||
}
|
||||
|
||||
/* Build MSS fix rule */
|
||||
|
@ -623,12 +593,26 @@ void fwd_ipt_addif(struct fwd_handle *h, const char *net)
|
|||
{
|
||||
printf("\n# Net %s (%s) - mtu_fix\n", n->name, n->ifname);
|
||||
|
||||
b = fwd_ipt_init("filter");
|
||||
fwd_ipt_add_format(b,
|
||||
" -A mssfix -o %s -p tcp --tcp-flags SYN,RST SYN"
|
||||
" -j TCPMSS --clamp-mss-to-pmtu", n->ifname);
|
||||
fwd_ipt_add_comment(b, "mssfix", z, NULL, n);
|
||||
fwd_ipt_exec(b);
|
||||
if( (x = fwd_xt_init_rule(h_filter)) != NULL )
|
||||
{
|
||||
p.type = FWD_PR_TCP;
|
||||
fwd_xt_parse_out(x, n, 0); /* -o ... */
|
||||
fwd_xt_parse_proto(x, &p, 0); /* -p tcp */
|
||||
|
||||
/* -m tcp --tcp-flags SYN,RST SYN */
|
||||
if( (m = fwd_xt_get_match(x, "tcp")) != NULL )
|
||||
fwd_xt_parse_match(x, m, "--tcp-flags", "SYN,RST", "SYN");
|
||||
|
||||
/* -j TCPMSS --clamp-mss-to-pmtu */
|
||||
if( (t = fwd_xt_get_target(x, "TCPMSS")) != NULL )
|
||||
fwd_xt_parse_target(x, t, "--clamp-mss-to-pmtu");
|
||||
|
||||
/* -m comment ... */
|
||||
fwd_r_add_comment(x, "mssfix", z, NULL, n);
|
||||
|
||||
/* -A mssfix */
|
||||
fwd_xt_exec_rule(x, "mssfix");
|
||||
}
|
||||
}
|
||||
|
||||
/* Build intra-zone forwarding rules */
|
||||
|
@ -641,12 +625,14 @@ void fwd_ipt_addif(struct fwd_handle *h, const char *net)
|
|||
n->name, n->ifname, z->name, n->name, n->ifname,
|
||||
z->name, n2->name, n2->ifname);
|
||||
|
||||
b = fwd_ipt_init("filter");
|
||||
fwd_ipt_add_format(b, " -A zones -i %s -o %s",
|
||||
n->ifname, n2->ifname);
|
||||
fwd_ipt_add_policy_target(b, z->forward);
|
||||
fwd_ipt_add_comment(b, "zone", z, n, n2);
|
||||
fwd_ipt_exec(b);
|
||||
if( (x = fwd_xt_init_rule(h_filter)) != NULL )
|
||||
{
|
||||
fwd_xt_parse_in(x, n, 0); /* -i ... */
|
||||
fwd_xt_parse_out(x, n2, 0); /* -o ... */
|
||||
fwd_r_add_policytarget(x, z->forward); /* -j handle_... */
|
||||
fwd_r_add_comment(x, "zone", z, n, n2); /* -m comment ... */
|
||||
fwd_xt_exec_rule(x, "zones"); /* -A zones */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -661,12 +647,14 @@ void fwd_ipt_addif(struct fwd_handle *h, const char *net)
|
|||
f->dest->name, n2->name, n2->ifname);
|
||||
|
||||
/* Build forwarding rule */
|
||||
b = fwd_ipt_init("filter");
|
||||
fwd_ipt_add_format(b, " -A forwardings -i %s -o %s",
|
||||
n->ifname, n2->ifname);
|
||||
fwd_ipt_add_policy_target(b, FWD_P_ACCEPT);
|
||||
fwd_ipt_add_comment(b, "forward", z, n, n2);
|
||||
fwd_ipt_exec(b);
|
||||
if( (x = fwd_xt_init_rule(h_filter)) != NULL )
|
||||
{
|
||||
fwd_xt_parse_in(x, n, 0); /* -i ... */
|
||||
fwd_xt_parse_out(x, n2, 0); /* -o ... */
|
||||
fwd_r_add_policytarget(x, FWD_P_ACCEPT); /* -j handle_... */
|
||||
fwd_r_add_comment(x, "forward", z, n, n2); /* -m comment ... */
|
||||
fwd_xt_exec_rule(x, "forwardings"); /* -A forwardings */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -677,43 +665,49 @@ void fwd_ipt_addif(struct fwd_handle *h, const char *net)
|
|||
n->name, n->ifname, z->name, n->name, n->ifname);
|
||||
|
||||
/* DNAT */
|
||||
b = fwd_ipt_init("nat");
|
||||
fwd_ipt_add_format(b, " -A redirects -i %s -d %s",
|
||||
n->ifname, inet_ntoa(a->ipaddr.v4));
|
||||
fwd_ipt_add_proto(b, r->proto);
|
||||
fwd_ipt_add_srcaddr(b, r->src_ip);
|
||||
fwd_ipt_add_srcport(b, r->src_port);
|
||||
fwd_ipt_add_destport(b, r->src_dport);
|
||||
fwd_ipt_add_srcmac(b, r->src_mac);
|
||||
fwd_ipt_add_dnat_target(b, r->dest_ip, r->dest_port);
|
||||
fwd_ipt_add_comment(b, "redir", z, n, NULL);
|
||||
fwd_ipt_exec(b);
|
||||
if( (x = fwd_xt_init_rule(h_nat)) != NULL )
|
||||
{
|
||||
fwd_xt_parse_in(x, n, 0); /* -i ... */
|
||||
fwd_xt_parse_src(x, r->src_ip, 0); /* -s ... */
|
||||
fwd_xt_parse_dest(x, &a->ipaddr, 0); /* -d ... */
|
||||
fwd_xt_parse_proto(x, r->proto, 0); /* -p ... */
|
||||
fwd_r_add_sport(x, r->src_port); /* --sport ... */
|
||||
fwd_r_add_dport(x, r->src_dport); /* --dport ... */
|
||||
fwd_r_add_srcmac(x, r->src_mac); /* -m mac --mac-source ... */
|
||||
fwd_r_add_dnattarget(x, r->dest_ip, r->dest_port); /* -j DNAT ... */
|
||||
fwd_r_add_comment(x, "redir", z, n, NULL); /* -m comment ... */
|
||||
fwd_xt_exec_rule(x, "redirects"); /* -A redirects */
|
||||
}
|
||||
|
||||
/* Forward */
|
||||
b = fwd_ipt_init("filter");
|
||||
fwd_ipt_add_format(b, " -A redirects -i %s", n->ifname);
|
||||
fwd_ipt_add_proto(b, r->proto);
|
||||
fwd_ipt_add_srcmac(b, r->src_mac);
|
||||
fwd_ipt_add_srcaddr(b, r->src_ip);
|
||||
fwd_ipt_add_srcport(b, r->src_port);
|
||||
fwd_ipt_add_destaddr(b, r->dest_ip);
|
||||
fwd_ipt_add_destport(b, r->dest_port);
|
||||
fwd_ipt_add_policy_target(b, FWD_P_ACCEPT);
|
||||
fwd_ipt_add_comment(b, "redir", z, n, NULL);
|
||||
fwd_ipt_exec(b);
|
||||
if( (x = fwd_xt_init_rule(h_filter)) != NULL )
|
||||
{
|
||||
fwd_xt_parse_in(x, n, 0); /* -i ... */
|
||||
fwd_xt_parse_src(x, r->src_ip, 0); /* -s ... */
|
||||
fwd_xt_parse_dest(x, r->dest_ip, 0); /* -d ... */
|
||||
fwd_xt_parse_proto(x, r->proto, 0); /* -p ... */
|
||||
fwd_r_add_srcmac(x, r->src_mac); /* -m mac --mac-source ... */
|
||||
fwd_r_add_sport(x, r->src_port); /* --sport ... */
|
||||
fwd_r_add_dport(x, r->dest_port); /* --dport ... */
|
||||
fwd_r_add_policytarget(x, FWD_P_ACCEPT); /* -j handle_accept */
|
||||
fwd_r_add_comment(x, "redir", z, n, NULL); /* -m comment ... */
|
||||
fwd_xt_exec_rule(x, "redirects"); /* -A redirects */
|
||||
}
|
||||
|
||||
/* Add loopback rule if neither src_ip nor src_mac are defined */
|
||||
if( !r->src_ip && !r->src_mac )
|
||||
{
|
||||
b = fwd_ipt_init("nat");
|
||||
fwd_ipt_add_format(b, " -A redirects -i ! %s -d %s",
|
||||
n->ifname, inet_ntoa(r->dest_ip->addr));
|
||||
fwd_ipt_add_proto(b, r->proto);
|
||||
fwd_ipt_add_srcport(b, r->src_port);
|
||||
fwd_ipt_add_destport(b, r->src_dport);
|
||||
fwd_ipt_add_format(b, " -j MASQUERADE");
|
||||
fwd_ipt_add_comment(b, "redir", z, n, NULL);
|
||||
fwd_ipt_exec(b);
|
||||
if( (x = fwd_xt_init_rule(h_nat)) != NULL )
|
||||
{
|
||||
fwd_xt_parse_in(x, n, 1); /* -i ! ... */
|
||||
fwd_xt_parse_dest(x, r->dest_ip, 0); /* -d ... */
|
||||
fwd_xt_parse_proto(x, r->proto, 0); /* -p ... */
|
||||
fwd_r_add_sport(x, r->src_port); /* --sport ... */
|
||||
fwd_r_add_dport(x, r->src_dport); /* --dport ... */
|
||||
fwd_xt_get_target(x, "MASQUERADE"); /* -j MASQUERADE */
|
||||
fwd_r_add_comment(x, "redir", z, n, NULL); /* -m comment ... */
|
||||
fwd_xt_exec_rule(x, "loopback"); /* -A loopback */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -730,19 +724,21 @@ void fwd_ipt_addif(struct fwd_handle *h, const char *net)
|
|||
n->name, n->ifname, z->name, n->name, n->ifname,
|
||||
f->dest->name, n2->name, n2->ifname);
|
||||
|
||||
b = fwd_ipt_init("filter");
|
||||
fwd_ipt_add_format(b, " -A rules -i %s -o %s",
|
||||
n->ifname, n2->ifname);
|
||||
fwd_ipt_add_proto(b, c->proto);
|
||||
fwd_ipt_add_icmptype(b, c->icmp_type);
|
||||
fwd_ipt_add_srcmac(b, c->src_mac);
|
||||
fwd_ipt_add_srcaddr(b, c->src_ip);
|
||||
fwd_ipt_add_srcport(b, c->src_port);
|
||||
fwd_ipt_add_destaddr(b, c->dest_ip);
|
||||
fwd_ipt_add_destport(b, c->dest_port);
|
||||
fwd_ipt_add_policy_target(b, c->target);
|
||||
fwd_ipt_add_comment(b, "rule", z, n, n2);
|
||||
fwd_ipt_exec(b);
|
||||
if( (x = fwd_xt_init_rule(h_filter)) != NULL )
|
||||
{
|
||||
fwd_xt_parse_in(x, n, 0); /* -i ... */
|
||||
fwd_xt_parse_out(x, n2, 0); /* -o ... */
|
||||
fwd_xt_parse_src(x, c->src_ip, 0); /* -s ... */
|
||||
fwd_xt_parse_dest(x, c->dest_ip, 0); /* -d ... */
|
||||
fwd_xt_parse_proto(x, c->proto, 0); /* -p ... */
|
||||
fwd_r_add_icmptype(x, c->icmp_type); /* --icmp-type ... */
|
||||
fwd_r_add_srcmac(x, c->src_mac); /* --mac-source ... */
|
||||
fwd_r_add_sport(x, c->src_port); /* --sport ... */
|
||||
fwd_r_add_dport(x, c->dest_port); /* --dport ... */
|
||||
fwd_r_add_policytarget(x, c->target); /* -j handle_... */
|
||||
fwd_r_add_comment(x, "rule", z, n, n2); /* -m comment ... */
|
||||
fwd_xt_exec_rule(x, "rules"); /* -A rules */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -752,19 +748,30 @@ void fwd_ipt_addif(struct fwd_handle *h, const char *net)
|
|||
printf("\n# Net %s (%s) - rule Z:%s N:%s I:%s\n",
|
||||
n->name, n->ifname, z->name, n->name, n->ifname);
|
||||
|
||||
b = fwd_ipt_init("filter");
|
||||
fwd_ipt_add_format(b, " -A rules -i %s", n->ifname);
|
||||
fwd_ipt_add_proto(b, c->proto);
|
||||
fwd_ipt_add_icmptype(b, c->icmp_type);
|
||||
fwd_ipt_add_srcmac(b, c->src_mac);
|
||||
fwd_ipt_add_srcaddr(b, c->src_ip);
|
||||
fwd_ipt_add_srcport(b, c->src_port);
|
||||
fwd_ipt_add_destaddr(b, c->dest_ip);
|
||||
fwd_ipt_add_destport(b, c->dest_port);
|
||||
fwd_ipt_add_policy_target(b, c->target);
|
||||
fwd_ipt_add_comment(b, "rule", z, n, n2);
|
||||
fwd_ipt_exec(b);
|
||||
if( (x = fwd_xt_init_rule(h_filter)) != NULL )
|
||||
{
|
||||
fwd_xt_parse_in(x, n, 0); /* -i ... */
|
||||
fwd_xt_parse_src(x, c->src_ip, 0); /* -s ... */
|
||||
fwd_xt_parse_dest(x, c->dest_ip, 0); /* -d ... */
|
||||
fwd_xt_parse_proto(x, c->proto, 0); /* -p ... */
|
||||
fwd_r_add_icmptype(x, c->icmp_type); /* --icmp-type ... */
|
||||
fwd_r_add_srcmac(x, c->src_mac); /* --mac-source ... */
|
||||
fwd_r_add_sport(x, c->src_port); /* --sport ... */
|
||||
fwd_r_add_dport(x, c->dest_port); /* --dport ... */
|
||||
fwd_r_add_policytarget(x, c->target); /* -j handle_... */
|
||||
fwd_r_add_comment(x, "rule", z, n, NULL); /* -m comment ... */
|
||||
fwd_xt_exec_rule(x, "rules"); /* -A rules */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( !iptc_commit(h_nat) )
|
||||
fwd_fatal("Cannot commit nat table: %s", iptc_strerror(errno));
|
||||
|
||||
if( !iptc_commit(h_filter) )
|
||||
fwd_fatal("Cannot commit filter table: %s", iptc_strerror(errno));
|
||||
|
||||
iptc_free(h_nat);
|
||||
iptc_free(h_filter);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue