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
)
86 void fwd_xt_parse_proto(
87 struct fwd_xt_rule
*r
, struct fwd_proto
*p
, int inv
94 r
->entry
->ip
.proto
= 6;
98 r
->entry
->ip
.proto
= 17;
102 r
->entry
->ip
.proto
= 1;
106 r
->entry
->ip
.proto
= p
->proto
;
111 r
->entry
->ip
.proto
= 0;
116 r
->entry
->ip
.invflags
|= IPT_INV_PROTO
;
120 void fwd_xt_parse_in(
121 struct fwd_xt_rule
*r
, struct fwd_network_list
*n
, int inv
125 strncpy(r
->entry
->ip
.iniface
, n
->ifname
, IFNAMSIZ
);
128 r
->entry
->ip
.invflags
|= IPT_INV_VIA_IN
;
132 void fwd_xt_parse_out(
133 struct fwd_xt_rule
*r
, struct fwd_network_list
*n
, int inv
137 strncpy(r
->entry
->ip
.outiface
, n
->ifname
, IFNAMSIZ
);
140 r
->entry
->ip
.invflags
|= IPT_INV_VIA_OUT
;
144 void fwd_xt_parse_src(
145 struct fwd_xt_rule
*r
, struct fwd_cidr
*c
, int inv
149 r
->entry
->ip
.src
.s_addr
= c
->addr
.s_addr
;
150 r
->entry
->ip
.smsk
.s_addr
= htonl(~((1 << (32 - c
->prefix
)) - 1));
153 r
->entry
->ip
.invflags
|= IPT_INV_SRCIP
;
157 void fwd_xt_parse_dest(
158 struct fwd_xt_rule
*r
, struct fwd_cidr
*c
, int inv
162 r
->entry
->ip
.dst
.s_addr
= c
->addr
.s_addr
;
163 r
->entry
->ip
.dmsk
.s_addr
= htonl(~((1 << (32 - c
->prefix
)) - 1));
166 r
->entry
->ip
.invflags
|= IPT_INV_DSTIP
;
171 struct xtables_match
* fwd_xt_get_match(
172 struct fwd_xt_rule
*r
, const char *name
174 struct xtables_match
*m
= xtables_find_match(name
, XTF_TRY_LOAD
, &r
->matches
);
179 s
= IPT_ALIGN(sizeof(struct ipt_entry_match
)) + m
->size
;
181 if( (m
->m
= malloc(s
)) != NULL
)
184 strcpy(m
->m
->u
.user
.name
, m
->name
);
185 m
->m
->u
.match_size
= s
;
197 void __fwd_xt_parse_match(
198 struct fwd_xt_rule
*r
, struct xtables_match
*m
, ...
208 opts
= malloc(len
* sizeof(*opts
));
211 while( (s
= (char *)va_arg(ap
, char *)) != NULL
)
213 opts
= realloc(opts
, ++len
* sizeof(*opts
));
223 while( (optc
= getopt_long(len
, opts
, "", m
->extra_opts
, NULL
)) > -1 )
225 if( (optc
== '?') && (optarg
[0] == '!') && (optarg
[1] == '\0') )
231 m
->parse(optc
, opts
, inv
, &m
->mflags
, r
->entry
, &m
->m
);
239 struct xtables_target
* fwd_xt_get_target(
240 struct fwd_xt_rule
*r
, const char *name
242 struct xtables_target
*t
= xtables_find_target(name
, XTF_TRY_LOAD
);
246 t
= xtables_find_target(IPT_STANDARD_TARGET
, XTF_LOAD_MUST_SUCCEED
);
250 s
= IPT_ALIGN(sizeof(struct ipt_entry_target
)) + t
->size
;
252 if( (t
->t
= malloc(s
)) != NULL
)
255 strcpy(t
->t
->u
.user
.name
, name
);
256 t
->t
->u
.target_size
= s
;
257 xtables_set_revision(t
->t
->u
.user
.name
, t
->revision
);
271 void __fwd_xt_parse_target(
272 struct fwd_xt_rule
*r
, struct xtables_target
*t
, ...
282 opts
= malloc(len
* sizeof(*opts
));
285 while( (s
= (char *)va_arg(ap
, char *)) != NULL
)
287 opts
= realloc(opts
, ++len
* sizeof(*opts
));
297 while( (optc
= getopt_long(len
, opts
, "", t
->extra_opts
, NULL
)) > -1 )
299 if( (optc
== '?') && (optarg
[0] == '!') && (optarg
[1] == '\0') )
305 t
->parse(optc
, opts
, inv
, &t
->tflags
, r
->entry
, &t
->t
);
313 int fwd_xt_exec_rule(struct fwd_xt_rule
*r
, const char *chain
)
316 struct xtables_rule_match
*m
, *next
;
317 struct xtables_match
*em
;
318 struct xtables_target
*et
;
322 s
= IPT_ALIGN(sizeof(struct ipt_entry
));
324 for( m
= r
->matches
; m
; m
= m
->next
)
325 s
+= m
->match
->m
->u
.match_size
;
327 if( (e
= malloc(s
+ r
->target
->t
->u
.target_size
)) != NULL
)
329 memset(e
, 0, s
+ r
->target
->t
->u
.target_size
);
330 memcpy(e
, r
->entry
, sizeof(struct ipt_entry
));
332 e
->target_offset
= s
;
333 e
->next_offset
= s
+ r
->target
->t
->u
.target_size
;
337 for( m
= r
->matches
; m
; m
= m
->next
)
339 memcpy(e
->elems
+ s
, m
->match
->m
, m
->match
->m
->u
.match_size
);
340 s
+= m
->match
->m
->u
.match_size
;
343 memcpy(e
->elems
+ s
, r
->target
->t
, r
->target
->t
->u
.target_size
);
345 rv
= iptc_append_entry(chain
, e
, r
->iptc
);
354 fwd_free_ptr(r
->entry
);
355 fwd_free_ptr(r
->target
->t
);
357 for( m
= r
->matches
; m
; )
360 fwd_free_ptr(m
->match
->m
);
362 if( m
->match
== m
->match
->next
)
363 fwd_free_ptr(m
->match
);
371 /* reset all targets and matches */
372 for (em
= xtables_matches
; em
; em
= em
->next
)
375 for (et
= xtables_targets
; et
; et
= et
->next
)