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);