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
,
199 const char *opt
, const char *val
, int inv
202 const char *opts
[3] = { "x", opt
, val
};
205 optcode
= getopt_long(val
? 3 : 2, (char **)opts
, "", m
->extra_opts
, NULL
);
207 if( (optcode
> -1) && (optcode
!= '?') )
208 m
->parse(optcode
, (char **)opts
, inv
, &m
->mflags
, r
->entry
, &m
->m
);
212 struct xtables_target
* fwd_xt_get_target(
213 struct fwd_xt_rule
*r
, const char *name
215 struct xtables_target
*t
= xtables_find_target(name
, XTF_TRY_LOAD
);
219 t
= xtables_find_target(IPT_STANDARD_TARGET
, XTF_LOAD_MUST_SUCCEED
);
223 s
= IPT_ALIGN(sizeof(struct ipt_entry_target
)) + t
->size
;
225 if( (t
->t
= malloc(s
)) != NULL
)
228 strcpy(t
->t
->u
.user
.name
, name
);
229 t
->t
->u
.target_size
= s
;
230 xtables_set_revision(t
->t
->u
.user
.name
, t
->revision
);
244 void fwd_xt_parse_target(
245 struct fwd_xt_rule
*r
, struct xtables_target
*t
,
246 const char *opt
, const char *val
, int inv
249 const char *opts
[3] = { "x", opt
, val
};
252 optcode
= getopt_long(val
? 3 : 2, (char **)opts
, "", t
->extra_opts
, NULL
);
254 if( (optcode
> -1) && (optcode
!= '?') )
255 t
->parse(optcode
, (char **)opts
, inv
, &t
->tflags
, r
->entry
, &t
->t
);
258 int fwd_xt_exec_rule(struct fwd_xt_rule
*r
, const char *chain
)
261 struct xtables_rule_match
*m
, *next
;
262 struct xtables_match
*em
;
263 struct xtables_target
*et
;
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 rv
= iptc_append_entry(chain
, e
, r
->iptc
);
299 fwd_free_ptr(r
->entry
);
300 fwd_free_ptr(r
->target
->t
);
302 for( m
= r
->matches
; m
; )
305 fwd_free_ptr(m
->match
->m
);
307 if( m
->match
== m
->match
->next
)
308 fwd_free_ptr(m
->match
);
316 /* reset all targets and matches */
317 for (em
= xtables_matches
; em
; em
= em
->next
)
320 for (et
= xtables_targets
; et
; et
= et
->next
)