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