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(struct iptc_handle
*h
)
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
)
85 void fwd_xt_parse_frag(
86 struct fwd_xt_rule
*r
, int frag
, int inv
90 r
->entry
->ip
.flags
|= IPT_F_FRAG
;
93 r
->entry
->ip
.invflags
|= IPT_INV_FRAG
;
97 void fwd_xt_parse_proto(
98 struct fwd_xt_rule
*r
, struct fwd_proto
*p
, int inv
105 r
->entry
->ip
.proto
= 6;
109 r
->entry
->ip
.proto
= 17;
113 r
->entry
->ip
.proto
= 1;
117 r
->entry
->ip
.proto
= p
->proto
;
122 r
->entry
->ip
.proto
= 0;
127 r
->entry
->ip
.invflags
|= IPT_INV_PROTO
;
131 void fwd_xt_parse_in(
132 struct fwd_xt_rule
*r
, struct fwd_network_list
*n
, int inv
136 strncpy(r
->entry
->ip
.iniface
, n
->ifname
, IFNAMSIZ
);
139 r
->entry
->ip
.invflags
|= IPT_INV_VIA_IN
;
143 void fwd_xt_parse_out(
144 struct fwd_xt_rule
*r
, struct fwd_network_list
*n
, int inv
148 strncpy(r
->entry
->ip
.outiface
, n
->ifname
, IFNAMSIZ
);
151 r
->entry
->ip
.invflags
|= IPT_INV_VIA_OUT
;
155 void fwd_xt_parse_src(
156 struct fwd_xt_rule
*r
, struct fwd_cidr
*c
, int inv
160 r
->entry
->ip
.src
.s_addr
= c
->addr
.s_addr
;
161 r
->entry
->ip
.smsk
.s_addr
= htonl(~((1 << (32 - c
->prefix
)) - 1));
164 r
->entry
->ip
.invflags
|= IPT_INV_SRCIP
;
168 void fwd_xt_parse_dest(
169 struct fwd_xt_rule
*r
, struct fwd_cidr
*c
, int inv
173 r
->entry
->ip
.dst
.s_addr
= c
->addr
.s_addr
;
174 r
->entry
->ip
.dmsk
.s_addr
= htonl(~((1 << (32 - c
->prefix
)) - 1));
177 r
->entry
->ip
.invflags
|= IPT_INV_DSTIP
;
182 struct xtables_match
* fwd_xt_get_match(
183 struct fwd_xt_rule
*r
, const char *name
185 struct xtables_match
*m
= xtables_find_match(name
, XTF_TRY_LOAD
, &r
->matches
);
190 s
= IPT_ALIGN(sizeof(struct ipt_entry_match
)) + m
->size
;
192 if( (m
->m
= malloc(s
)) != NULL
)
195 strcpy(m
->m
->u
.user
.name
, m
->name
);
196 m
->m
->u
.match_size
= s
;
208 void __fwd_xt_parse_match(
209 struct fwd_xt_rule
*r
, struct xtables_match
*m
, ...
219 opts
= malloc(len
* sizeof(*opts
));
222 while( (s
= (char *)va_arg(ap
, char *)) != NULL
)
224 opts
= realloc(opts
, ++len
* sizeof(*opts
));
234 while( (optc
= getopt_long(len
, opts
, "", m
->extra_opts
, NULL
)) > -1 )
236 if( (optc
== '?') && (optarg
[0] == '!') && (optarg
[1] == '\0') )
242 m
->parse(optc
, opts
, inv
, &m
->mflags
, r
->entry
, &m
->m
);
251 struct xtables_target
* fwd_xt_get_target(
252 struct fwd_xt_rule
*r
, const char *name
254 struct xtables_target
*t
= xtables_find_target(name
, XTF_TRY_LOAD
);
258 t
= xtables_find_target(IPT_STANDARD_TARGET
, XTF_LOAD_MUST_SUCCEED
);
262 s
= IPT_ALIGN(sizeof(struct ipt_entry_target
)) + t
->size
;
264 if( (t
->t
= malloc(s
)) != NULL
)
267 strcpy(t
->t
->u
.user
.name
, name
);
268 t
->t
->u
.target_size
= s
;
269 xtables_set_revision(t
->t
->u
.user
.name
, t
->revision
);
283 void __fwd_xt_parse_target(
284 struct fwd_xt_rule
*r
, struct xtables_target
*t
, ...
294 opts
= malloc(len
* sizeof(*opts
));
297 while( (s
= (char *)va_arg(ap
, char *)) != NULL
)
299 opts
= realloc(opts
, ++len
* sizeof(*opts
));
309 while( (optc
= getopt_long(len
, opts
, "", t
->extra_opts
, NULL
)) > -1 )
311 if( (optc
== '?') && (optarg
[0] == '!') && (optarg
[1] == '\0') )
317 t
->parse(optc
, opts
, inv
, &t
->tflags
, r
->entry
, &t
->t
);
326 static int fwd_xt_exec_rule(struct fwd_xt_rule
*r
, const char *chain
, int pos
)
329 struct xtables_rule_match
*m
, *next
;
330 struct xtables_match
*em
;
331 struct xtables_target
*et
;
335 s
= IPT_ALIGN(sizeof(struct ipt_entry
));
337 for( m
= r
->matches
; m
; m
= m
->next
)
338 s
+= m
->match
->m
->u
.match_size
;
340 if( (e
= malloc(s
+ r
->target
->t
->u
.target_size
)) != NULL
)
342 memset(e
, 0, s
+ r
->target
->t
->u
.target_size
);
343 memcpy(e
, r
->entry
, sizeof(struct ipt_entry
));
345 e
->target_offset
= s
;
346 e
->next_offset
= s
+ r
->target
->t
->u
.target_size
;
350 for( m
= r
->matches
; m
; m
= m
->next
)
352 memcpy(e
->elems
+ s
, m
->match
->m
, m
->match
->m
->u
.match_size
);
353 s
+= m
->match
->m
->u
.match_size
;
356 memcpy(e
->elems
+ s
, r
->target
->t
, r
->target
->t
->u
.target_size
);
359 ? iptc_insert_entry(chain
, e
, (unsigned int) pos
, r
->iptc
)
360 : iptc_append_entry(chain
, e
, r
->iptc
)
370 fwd_free_ptr(r
->entry
);
371 fwd_free_ptr(r
->target
->t
);
373 for( m
= r
->matches
; m
; )
376 fwd_free_ptr(m
->match
->m
);
378 if( m
->match
== m
->match
->next
)
379 fwd_free_ptr(m
->match
);
387 /* reset all targets and matches */
388 for (em
= xtables_matches
; em
; em
= em
->next
)
391 for (et
= xtables_targets
; et
; et
= et
->next
)
400 int fwd_xt_insert_rule(
401 struct fwd_xt_rule
*r
, const char *chain
, unsigned int pos
403 return fwd_xt_exec_rule(r
, chain
, pos
);
406 int fwd_xt_append_rule(
407 struct fwd_xt_rule
*r
, const char *chain
409 return fwd_xt_exec_rule(r
, chain
, -1);