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"
24 /* Required by certain extensions like SNAT and DNAT */
28 get_kernel_version(void) {
29 static struct utsname uts;
30 int x = 0, y = 0, z = 0;
32 if (uname(&uts) == -1) {
33 fprintf(stderr, "Unable to retrieve kernel version.\n");
38 sscanf(uts.release, "%d.%d.%d", &x, &y, &z);
39 kernel_version = LINUX_VERSION(x, y, z);
43 static void xt_exit_error(enum xtables_exittype status, const char *msg, ...)
52 void fwd_xt_init(void)
54 struct xtables_globals xt_globals = {
56 .program_version = IPTABLES_VERSION,
59 .exit_err = (void *)&xt_exit_error,
63 xtables_set_nfproto(NFPROTO_IPV4);
64 xtables_set_params(&xt_globals);
68 struct fwd_xt_rule * fwd_xt_init_rule(const char *table)
70 struct fwd_xt_rule *r;
72 if( (r = fwd_alloc_ptr(struct fwd_xt_rule)) != NULL )
74 if( (r->entry = fwd_alloc_ptr(struct ipt_entry)) != NULL )
76 if( (r->iptc = iptc_init(table)) != NULL )
88 void fwd_xt_parse_proto(
89 struct fwd_xt_rule *r, struct fwd_proto *p, int inv
96 r->entry->ip.proto = 6;
100 r->entry->ip.proto = 17;
104 r->entry->ip.proto = 1;
108 r->entry->ip.proto = p->proto;
113 r->entry->ip.proto = 0;
118 r->entry->ip.invflags |= IPT_INV_PROTO;
122 void fwd_xt_parse_in(
123 struct fwd_xt_rule *r, struct fwd_network_list *n, int inv
127 strncpy(r->entry->ip.iniface, n->ifname, IFNAMSIZ);
130 r->entry->ip.invflags |= IPT_INV_VIA_IN;
134 void fwd_xt_parse_out(
135 struct fwd_xt_rule *r, struct fwd_network_list *n, int inv
139 strncpy(r->entry->ip.outiface, n->ifname, IFNAMSIZ);
142 r->entry->ip.invflags |= IPT_INV_VIA_OUT;
146 void fwd_xt_parse_src(
147 struct fwd_xt_rule *r, struct fwd_cidr *c, int inv
151 r->entry->ip.src.s_addr = c->addr.s_addr;
152 r->entry->ip.smsk.s_addr = htonl(~((1 << (32 - c->prefix)) - 1));
155 r->entry->ip.invflags |= IPT_INV_SRCIP;
159 void fwd_xt_parse_dest(
160 struct fwd_xt_rule *r, struct fwd_cidr *c, int inv
164 r->entry->ip.dst.s_addr = c->addr.s_addr;
165 r->entry->ip.dmsk.s_addr = htonl(~((1 << (32 - c->prefix)) - 1));
168 r->entry->ip.invflags |= IPT_INV_DSTIP;
173 struct xtables_match * fwd_xt_get_match(
174 struct fwd_xt_rule *r, const char *name
176 struct xtables_match *m = xtables_find_match(name, XTF_TRY_LOAD, &r->matches);
181 s = IPT_ALIGN(sizeof(struct ipt_entry_match)) + m->size;
183 if( (m->m = malloc(s)) != NULL )
186 strcpy(m->m->u.user.name, m->name);
187 m->m->u.match_size = s;
199 void fwd_xt_parse_match(
200 struct fwd_xt_rule *r, struct xtables_match *m,
201 const char *opt, const char *val
204 const char *opts[3] = { "x", opt, val };
207 optcode = getopt_long(val ? 3 : 2, (char **)opts, "", m->extra_opts, NULL);
209 if( (optcode > -1) && (optcode != '?') )
210 m->parse(optcode, (char **)opts, 0, &m->mflags, r->entry, &m->m);
214 struct xtables_target * fwd_xt_get_target(
215 struct fwd_xt_rule *r, const char *name
217 struct xtables_target *t = xtables_find_target(name, XTF_TRY_LOAD);
221 t = xtables_find_target(IPT_STANDARD_TARGET, XTF_LOAD_MUST_SUCCEED);
225 s = IPT_ALIGN(sizeof(struct ipt_entry_target)) + t->size;
227 if( (t->t = malloc(s)) != NULL )
230 strcpy(t->t->u.user.name, name);
231 t->t->u.target_size = s;
232 xtables_set_revision(t->t->u.user.name, t->revision);
246 void fwd_xt_parse_target(
247 struct fwd_xt_rule *r, struct xtables_target *t,
248 const char *opt, const char *val
251 const char *opts[3] = { "x", opt, val };
254 optcode = getopt_long(val ? 3 : 2, (char **)opts, "", t->extra_opts, NULL);
256 if( (optcode > -1) && (optcode != '?') )
257 t->parse(optcode, (char **)opts, 0, &t->tflags, r->entry, &t->t);
260 int fwd_xt_exec_rule(struct fwd_xt_rule *r, const char *chain)
263 struct xtables_rule_match *m, *next;
267 s = IPT_ALIGN(sizeof(struct ipt_entry));
269 for( m = r->matches; m; m = m->next )
270 s += m->match->m->u.match_size;
272 if( (e = malloc(s + r->target->t->u.target_size)) != NULL )
274 memset(e, 0, s + r->target->t->u.target_size);
275 memcpy(e, r->entry, sizeof(struct ipt_entry));
277 e->target_offset = s;
278 e->next_offset = s + r->target->t->u.target_size;
282 for( m = r->matches; m; m = m->next )
284 memcpy(e->elems + s, m->match->m, m->match->m->u.match_size);
285 s += m->match->m->u.match_size;
288 memcpy(e->elems + s, r->target->t, r->target->t->u.target_size);
290 if( (rv = iptc_append_entry(chain, e, r->iptc)) > 0 )
291 iptc_commit(r->iptc);
300 fwd_free_ptr(r->entry);
301 fwd_free_ptr(r->target->t);
303 for( m = r->matches; m; )
306 fwd_free_ptr(m->match->m);