1 /* Shared library add-on to ip6tables to add Routing header support. */
9 /*#include <linux/in6.h>*/
10 #include <linux/netfilter_ipv6/ip6t_rt.h>
11 #include <sys/types.h>
12 #include <sys/socket.h>
13 #include <arpa/inet.h>
17 static void rt_help(void)
21 "[!] --rt-type type match the type\n"
22 "[!] --rt-segsleft num[:num] match the Segments Left field (range)\n"
23 "[!] --rt-len length total length of this header\n"
24 " --rt-0-res check the reserved filed, too (type 0)\n"
25 " --rt-0-addrs ADDR[,ADDR...] Type=0 addresses (list, max: %d)\n"
26 " --rt-0-not-strict List of Type=0 addresses not a strict list\n",
30 static const struct option rt_opts
[] = {
31 { "rt-type", 1, NULL
, '1' },
32 { "rt-segsleft", 1, NULL
, '2' },
33 { "rt-len", 1, NULL
, '3' },
34 { "rt-0-res", 0, NULL
, '4' },
35 { "rt-0-addrs", 1, NULL
, '5' },
36 { "rt-0-not-strict", 0, NULL
, '6' },
41 parse_rt_num(const char *idstr
, const char *typestr
)
46 id
= strtoul(idstr
,&ep
,0) ;
49 xtables_error(PARAMETER_PROBLEM
,
50 "RT no valid digits in %s `%s'", typestr
, idstr
);
52 if ( id
== ULONG_MAX
&& errno
== ERANGE
) {
53 xtables_error(PARAMETER_PROBLEM
,
54 "%s `%s' specified too big: would overflow",
57 if ( *idstr
!= '\0' && *ep
!= '\0' ) {
58 xtables_error(PARAMETER_PROBLEM
,
59 "RT error parsing %s `%s'", typestr
, idstr
);
65 parse_rt_segsleft(const char *idstring
, u_int32_t
*ids
)
70 buffer
= strdup(idstring
);
71 if ((cp
= strchr(buffer
, ':')) == NULL
)
72 ids
[0] = ids
[1] = parse_rt_num(buffer
,"segsleft");
77 ids
[0] = buffer
[0] ? parse_rt_num(buffer
,"segsleft") : 0;
78 ids
[1] = cp
[0] ? parse_rt_num(cp
,"segsleft") : 0xFFFFFFFF;
84 addr_to_numeric(const struct in6_addr
*addrp
)
86 static char buf
[50+1];
87 return (char *)inet_ntop(AF_INET6
, addrp
, buf
, sizeof(buf
));
90 static struct in6_addr
*
91 numeric_to_addr(const char *num
)
93 static struct in6_addr ap
;
96 if ((err
=inet_pton(AF_INET6
, num
, &ap
)) == 1)
99 fprintf(stderr
, "\nnumeric2addr: %d\n", err
);
101 xtables_error(PARAMETER_PROBLEM
, "bad address: %s", num
);
103 return (struct in6_addr
*)NULL
;
108 parse_addresses(const char *addrstr
, struct in6_addr
*addrp
)
110 char *buffer
, *cp
, *next
;
113 buffer
= strdup(addrstr
);
114 if (!buffer
) xtables_error(OTHER_PROBLEM
, "strdup failed");
116 for (cp
=buffer
, i
=0; cp
&& i
<IP6T_RT_HOPS
; cp
=next
,i
++)
118 next
=strchr(cp
, ',');
119 if (next
) *next
++='\0';
120 memcpy(&(addrp
[i
]), numeric_to_addr(cp
), sizeof(struct in6_addr
));
122 printf("addr str: %s\n", cp
);
123 printf("addr ip6: %s\n", addr_to_numeric((numeric_to_addr(cp
))));
124 printf("addr [%d]: %s\n", i
, addr_to_numeric(&(addrp
[i
])));
127 if (cp
) xtables_error(PARAMETER_PROBLEM
, "too many addresses specified");
132 printf("addr nr: %d\n", i
);
138 static void rt_init(struct xt_entry_match
*m
)
140 struct ip6t_rt
*rtinfo
= (struct ip6t_rt
*)m
->data
;
142 rtinfo
->rt_type
= 0x0L
;
143 rtinfo
->segsleft
[0] = 0x0L
;
144 rtinfo
->segsleft
[1] = 0xFFFFFFFF;
147 rtinfo
->invflags
= 0;
151 static int rt_parse(int c
, char **argv
, int invert
, unsigned int *flags
,
152 const void *entry
, struct xt_entry_match
**match
)
154 struct ip6t_rt
*rtinfo
= (struct ip6t_rt
*)(*match
)->data
;
158 if (*flags
& IP6T_RT_TYP
)
159 xtables_error(PARAMETER_PROBLEM
,
160 "Only one `--rt-type' allowed");
161 xtables_check_inverse(optarg
, &invert
, &optind
, 0);
162 rtinfo
->rt_type
= parse_rt_num(argv
[optind
-1], "type");
164 rtinfo
->invflags
|= IP6T_RT_INV_TYP
;
165 rtinfo
->flags
|= IP6T_RT_TYP
;
166 *flags
|= IP6T_RT_TYP
;
169 if (*flags
& IP6T_RT_SGS
)
170 xtables_error(PARAMETER_PROBLEM
,
171 "Only one `--rt-segsleft' allowed");
172 xtables_check_inverse(optarg
, &invert
, &optind
, 0);
173 parse_rt_segsleft(argv
[optind
-1], rtinfo
->segsleft
);
175 rtinfo
->invflags
|= IP6T_RT_INV_SGS
;
176 rtinfo
->flags
|= IP6T_RT_SGS
;
177 *flags
|= IP6T_RT_SGS
;
180 if (*flags
& IP6T_RT_LEN
)
181 xtables_error(PARAMETER_PROBLEM
,
182 "Only one `--rt-len' allowed");
183 xtables_check_inverse(optarg
, &invert
, &optind
, 0);
184 rtinfo
->hdrlen
= parse_rt_num(argv
[optind
-1], "length");
186 rtinfo
->invflags
|= IP6T_RT_INV_LEN
;
187 rtinfo
->flags
|= IP6T_RT_LEN
;
188 *flags
|= IP6T_RT_LEN
;
191 if (*flags
& IP6T_RT_RES
)
192 xtables_error(PARAMETER_PROBLEM
,
193 "Only one `--rt-0-res' allowed");
194 if ( !(*flags
& IP6T_RT_TYP
) || (rtinfo
->rt_type
!= 0) || (rtinfo
->invflags
& IP6T_RT_INV_TYP
) )
195 xtables_error(PARAMETER_PROBLEM
,
196 "`--rt-type 0' required before `--rt-0-res'");
197 rtinfo
->flags
|= IP6T_RT_RES
;
198 *flags
|= IP6T_RT_RES
;
201 if (*flags
& IP6T_RT_FST
)
202 xtables_error(PARAMETER_PROBLEM
,
203 "Only one `--rt-0-addrs' allowed");
204 if ( !(*flags
& IP6T_RT_TYP
) || (rtinfo
->rt_type
!= 0) || (rtinfo
->invflags
& IP6T_RT_INV_TYP
) )
205 xtables_error(PARAMETER_PROBLEM
,
206 "`--rt-type 0' required before `--rt-0-addrs'");
207 xtables_check_inverse(optarg
, &invert
, &optind
, 0);
209 xtables_error(PARAMETER_PROBLEM
,
210 " '!' not allowed with `--rt-0-addrs'");
211 rtinfo
->addrnr
= parse_addresses(argv
[optind
-1], rtinfo
->addrs
);
212 rtinfo
->flags
|= IP6T_RT_FST
;
213 *flags
|= IP6T_RT_FST
;
216 if (*flags
& IP6T_RT_FST_NSTRICT
)
217 xtables_error(PARAMETER_PROBLEM
,
218 "Only one `--rt-0-not-strict' allowed");
219 if ( !(*flags
& IP6T_RT_FST
) )
220 xtables_error(PARAMETER_PROBLEM
,
221 "`--rt-0-addr ...' required before `--rt-0-not-strict'");
222 rtinfo
->flags
|= IP6T_RT_FST_NSTRICT
;
223 *flags
|= IP6T_RT_FST_NSTRICT
;
233 print_nums(const char *name
, u_int32_t min
, u_int32_t max
,
236 const char *inv
= invert
? "!" : "";
238 if (min
!= 0 || max
!= 0xFFFFFFFF || invert
) {
254 print_addresses(unsigned int addrnr
, struct in6_addr
*addrp
)
258 for(i
=0; i
<addrnr
; i
++){
259 printf("%s%c", addr_to_numeric(&(addrp
[i
])), (i
!=addrnr
-1)?',':' ');
263 static void rt_print(const void *ip
, const struct xt_entry_match
*match
,
266 const struct ip6t_rt
*rtinfo
= (struct ip6t_rt
*)match
->data
;
269 if (rtinfo
->flags
& IP6T_RT_TYP
)
270 printf("type:%s%d ", rtinfo
->invflags
& IP6T_RT_INV_TYP
? "!" : "",
272 print_nums("segsleft", rtinfo
->segsleft
[0], rtinfo
->segsleft
[1],
273 rtinfo
->invflags
& IP6T_RT_INV_SGS
);
274 if (rtinfo
->flags
& IP6T_RT_LEN
) {
276 printf(":%s", rtinfo
->invflags
& IP6T_RT_INV_LEN
? "!" : "");
277 printf("%u", rtinfo
->hdrlen
);
280 if (rtinfo
->flags
& IP6T_RT_RES
) printf("reserved ");
281 if (rtinfo
->flags
& IP6T_RT_FST
) printf("0-addrs ");
282 print_addresses(rtinfo
->addrnr
, (struct in6_addr
*)rtinfo
->addrs
);
283 if (rtinfo
->flags
& IP6T_RT_FST_NSTRICT
) printf("0-not-strict ");
284 if (rtinfo
->invflags
& ~IP6T_RT_INV_MASK
)
285 printf("Unknown invflags: 0x%X ",
286 rtinfo
->invflags
& ~IP6T_RT_INV_MASK
);
289 static void rt_save(const void *ip
, const struct xt_entry_match
*match
)
291 const struct ip6t_rt
*rtinfo
= (struct ip6t_rt
*)match
->data
;
293 if (rtinfo
->flags
& IP6T_RT_TYP
) {
294 printf("%s--rt-type %u ",
295 (rtinfo
->invflags
& IP6T_RT_INV_TYP
) ? "! " : "",
299 if (!(rtinfo
->segsleft
[0] == 0
300 && rtinfo
->segsleft
[1] == 0xFFFFFFFF)) {
301 printf("%s--rt-segsleft ",
302 (rtinfo
->invflags
& IP6T_RT_INV_SGS
) ? "! " : "");
303 if (rtinfo
->segsleft
[0]
304 != rtinfo
->segsleft
[1])
307 rtinfo
->segsleft
[1]);
310 rtinfo
->segsleft
[0]);
313 if (rtinfo
->flags
& IP6T_RT_LEN
) {
314 printf("%s--rt-len %u ",
315 (rtinfo
->invflags
& IP6T_RT_INV_LEN
) ? "! " : "",
319 if (rtinfo
->flags
& IP6T_RT_RES
) printf("--rt-0-res ");
320 if (rtinfo
->flags
& IP6T_RT_FST
) printf("--rt-0-addrs ");
321 print_addresses(rtinfo
->addrnr
, (struct in6_addr
*)rtinfo
->addrs
);
322 if (rtinfo
->flags
& IP6T_RT_FST_NSTRICT
) printf("--rt-0-not-strict ");
326 static struct xtables_match rt_mt6_reg
= {
328 .version
= XTABLES_VERSION
,
329 .family
= NFPROTO_IPV6
,
330 .size
= XT_ALIGN(sizeof(struct ip6t_rt
)),
331 .userspacesize
= XT_ALIGN(sizeof(struct ip6t_rt
)),
337 .extra_opts
= rt_opts
,
343 xtables_register_match(&rt_mt6_reg
);