2 * fwd - OpenWrt firewall daemon - libiptc/libxtables interface
4 * Copyright (C) 2009 Jo-Philipp Wich <xm@subsignal.org>
6 * The fwd program is free software: you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License version 2
8 * as published by the Free Software Foundation.
10 * The fwd program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 * See the GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with the fwd program. If not, see http://www.gnu.org/licenses/.
21 #include "fwd_xtables.h"
22 #include "fwd_utils.h"
25 /* Required by certain extensions like SNAT and DNAT */
29 get_kernel_version(void) {
30 static struct utsname uts;
31 int x = 0, y = 0, z = 0;
33 if (uname(&uts) == -1) {
34 fprintf(stderr, "Unable to retrieve kernel version.\n");
39 sscanf(uts.release, "%d.%d.%d", &x, &y, &z);
40 kernel_version = LINUX_VERSION(x, y, z);
44 static void xt_exit_error(enum xtables_exittype status, const char *msg, ...)
53 void fwd_xt_init(void)
55 struct xtables_globals xt_globals = {
57 .program_version = IPTABLES_VERSION,
60 .exit_err = (void *)&xt_exit_error,
64 xtables_set_nfproto(NFPROTO_IPV4);
65 xtables_set_params(&xt_globals);
69 struct fwd_xt_rule * fwd_xt_init_rule(struct iptc_handle *h)
71 struct fwd_xt_rule *r;
73 if( (r = fwd_alloc_ptr(struct fwd_xt_rule)) != NULL )
75 if( (r->entry = fwd_alloc_ptr(struct ipt_entry)) != NULL )
86 void fwd_xt_parse_frag(
87 struct fwd_xt_rule *r, int frag, int inv
91 r->entry->ip.flags |= IPT_F_FRAG;
94 r->entry->ip.invflags |= IPT_INV_FRAG;
98 void fwd_xt_parse_proto(
99 struct fwd_xt_rule *r, struct fwd_proto *p, int inv
106 r->entry->ip.proto = 6;
110 r->entry->ip.proto = 17;
114 r->entry->ip.proto = 1;
118 r->entry->ip.proto = p->proto;
123 r->entry->ip.proto = 0;
128 r->entry->ip.invflags |= IPT_INV_PROTO;
132 void fwd_xt_parse_in(
133 struct fwd_xt_rule *r, struct fwd_network *n, int inv
137 strncpy(r->entry->ip.iniface, n->ifname, IFNAMSIZ);
140 r->entry->ip.invflags |= IPT_INV_VIA_IN;
144 void fwd_xt_parse_out(
145 struct fwd_xt_rule *r, struct fwd_network *n, int inv
149 strncpy(r->entry->ip.outiface, n->ifname, IFNAMSIZ);
152 r->entry->ip.invflags |= IPT_INV_VIA_OUT;
156 void fwd_xt_parse_src(
157 struct fwd_xt_rule *r, struct fwd_cidr *c, int inv
161 r->entry->ip.src.s_addr = c->addr.s_addr;
162 r->entry->ip.smsk.s_addr = htonl(~((1 << (32 - c->prefix)) - 1));
165 r->entry->ip.invflags |= IPT_INV_SRCIP;
169 void fwd_xt_parse_dest(
170 struct fwd_xt_rule *r, struct fwd_cidr *c, int inv
174 r->entry->ip.dst.s_addr = c->addr.s_addr;
175 r->entry->ip.dmsk.s_addr = htonl(~((1 << (32 - c->prefix)) - 1));
178 r->entry->ip.invflags |= IPT_INV_DSTIP;
183 struct xtables_match * fwd_xt_get_match(
184 struct fwd_xt_rule *r, const char *name
186 struct xtables_match *m = xtables_find_match(name, XTF_TRY_LOAD, &r->matches);
191 s = IPT_ALIGN(sizeof(struct ipt_entry_match)) + m->size;
193 if( (m->m = malloc(s)) != NULL )
196 strcpy(m->m->u.user.name, m->name);
197 m->m->u.match_size = s;
209 void __fwd_xt_parse_match(
210 struct fwd_xt_rule *r, struct xtables_match *m, ...
220 opts = malloc(len * sizeof(*opts));
223 while( (s = (char *)va_arg(ap, char *)) != NULL )
225 opts = realloc(opts, ++len * sizeof(*opts));
235 while( (optc = getopt_long(len, opts, "", m->extra_opts, NULL)) > -1 )
237 if( (optc == '?') && (optarg[0] == '!') && (optarg[1] == '\0') )
243 m->parse(optc, opts, inv, &m->mflags, r->entry, &m->m);
252 struct xtables_target * fwd_xt_get_target(
253 struct fwd_xt_rule *r, const char *name
255 struct xtables_target *t = xtables_find_target(name, XTF_TRY_LOAD);
259 t = xtables_find_target(IPT_STANDARD_TARGET, XTF_LOAD_MUST_SUCCEED);
263 s = IPT_ALIGN(sizeof(struct ipt_entry_target)) + t->size;
265 if( (t->t = malloc(s)) != NULL )
268 strcpy(t->t->u.user.name, name);
269 t->t->u.target_size = s;
270 xtables_set_revision(t->t->u.user.name, t->revision);
284 void __fwd_xt_parse_target(
285 struct fwd_xt_rule *r, struct xtables_target *t, ...
295 opts = malloc(len * sizeof(*opts));
298 while( (s = (char *)va_arg(ap, char *)) != NULL )
300 opts = realloc(opts, ++len * sizeof(*opts));
310 while( (optc = getopt_long(len, opts, "", t->extra_opts, NULL)) > -1 )
312 if( (optc == '?') && (optarg[0] == '!') && (optarg[1] == '\0') )
318 t->parse(optc, opts, inv, &t->tflags, r->entry, &t->t);
327 static int fwd_xt_exec_rule(struct fwd_xt_rule *r, const char *chain, int pos)
330 struct xtables_rule_match *m, *next;
331 struct xtables_match *em;
332 struct xtables_target *et;
336 s = IPT_ALIGN(sizeof(struct ipt_entry));
338 for( m = r->matches; m; m = m->next )
339 s += m->match->m->u.match_size;
341 if( (e = malloc(s + r->target->t->u.target_size)) != NULL )
343 memset(e, 0, s + r->target->t->u.target_size);
344 memcpy(e, r->entry, sizeof(struct ipt_entry));
346 e->target_offset = s;
347 e->next_offset = s + r->target->t->u.target_size;
351 for( m = r->matches; m; m = m->next )
353 memcpy(e->elems + s, m->match->m, m->match->m->u.match_size);
354 s += m->match->m->u.match_size;
357 memcpy(e->elems + s, r->target->t, r->target->t->u.target_size);
360 ? iptc_insert_entry(chain, e, (unsigned int) pos, r->iptc)
361 : iptc_append_entry(chain, e, r->iptc)
371 fwd_free_ptr(r->entry);
372 fwd_free_ptr(r->target->t);
374 for( m = r->matches; m; )
377 fwd_free_ptr(m->match->m);
379 if( m->match == m->match->next )
380 fwd_free_ptr(m->match);
388 /* reset all targets and matches */
389 for (em = xtables_matches; em; em = em->next)
392 for (et = xtables_targets; et; et = et->next)
401 int fwd_xt_insert_rule(
402 struct fwd_xt_rule *r, const char *chain, unsigned int pos
404 return fwd_xt_exec_rule(r, chain, pos);
407 int fwd_xt_append_rule(
408 struct fwd_xt_rule *r, const char *chain
410 return fwd_xt_exec_rule(r, chain, -1);