1 /* Shared library add-on to ip6tables to add Hop-by-Hop header support. */
9 /*#include <linux/in6.h>*/
10 #include <linux/netfilter_ipv6/ip6t_opts.h>
11 #include <sys/types.h>
12 #include <sys/socket.h>
13 #include <arpa/inet.h>
17 static void hbh_help(void)
20 "hbh match options:\n"
21 "[!] --hbh-len length total length of this header\n"
22 " --hbh-opts TYPE[:LEN][,TYPE[:LEN]...] \n"
23 " Options and its length (list, max: %d)\n",
27 static const struct option hbh_opts
[] = {
28 { "hbh-len", 1, NULL
, '1' },
29 { "hbh-opts", 1, NULL
, '2' },
30 { "hbh-not-strict", 1, NULL
, '3' },
35 parse_opts_num(const char *idstr
, const char *typestr
)
40 id
= strtoul(idstr
,&ep
,0) ;
43 xtables_error(PARAMETER_PROBLEM
,
44 "hbh: no valid digits in %s `%s'", typestr
, idstr
);
46 if ( id
== ULONG_MAX
&& errno
== ERANGE
) {
47 xtables_error(PARAMETER_PROBLEM
,
48 "%s `%s' specified too big: would overflow",
51 if ( *idstr
!= '\0' && *ep
!= '\0' ) {
52 xtables_error(PARAMETER_PROBLEM
,
53 "hbh: error parsing %s `%s'", typestr
, idstr
);
59 parse_options(const char *optsstr
, u_int16_t
*opts
)
61 char *buffer
, *cp
, *next
, *range
;
64 buffer
= strdup(optsstr
);
65 if (!buffer
) xtables_error(OTHER_PROBLEM
, "strdup failed");
67 for (cp
=buffer
, i
=0; cp
&& i
<IP6T_OPTS_OPTSNR
; cp
=next
,i
++)
70 if (next
) *next
++='\0';
71 range
= strchr(cp
, ':');
73 if (i
== IP6T_OPTS_OPTSNR
-1)
74 xtables_error(PARAMETER_PROBLEM
,
75 "too many ports specified");
78 opts
[i
] = (parse_opts_num(cp
, "opt") & 0xFF) << 8;
81 xtables_error(PARAMETER_PROBLEM
, "PAD0 has not got length");
82 opts
[i
] |= parse_opts_num(range
, "length") & 0xFF;
88 printf("opts str: %s %s\n", cp
, range
);
89 printf("opts opt: %04X\n", opts
[i
]);
92 if (cp
) xtables_error(PARAMETER_PROBLEM
, "too many addresses specified");
97 printf("addr nr: %d\n", i
);
103 static void hbh_init(struct xt_entry_match
*m
)
105 struct ip6t_opts
*optinfo
= (struct ip6t_opts
*)m
->data
;
109 optinfo
->invflags
= 0;
113 static int hbh_parse(int c
, char **argv
, int invert
, unsigned int *flags
,
114 const void *entry
, struct xt_entry_match
**match
)
116 struct ip6t_opts
*optinfo
= (struct ip6t_opts
*)(*match
)->data
;
120 if (*flags
& IP6T_OPTS_LEN
)
121 xtables_error(PARAMETER_PROBLEM
,
122 "Only one `--hbh-len' allowed");
123 xtables_check_inverse(optarg
, &invert
, &optind
, 0);
124 optinfo
->hdrlen
= parse_opts_num(argv
[optind
-1], "length");
126 optinfo
->invflags
|= IP6T_OPTS_INV_LEN
;
127 optinfo
->flags
|= IP6T_OPTS_LEN
;
128 *flags
|= IP6T_OPTS_LEN
;
131 if (*flags
& IP6T_OPTS_OPTS
)
132 xtables_error(PARAMETER_PROBLEM
,
133 "Only one `--hbh-opts' allowed");
134 xtables_check_inverse(optarg
, &invert
, &optind
, 0);
136 xtables_error(PARAMETER_PROBLEM
,
137 " '!' not allowed with `--hbh-opts'");
138 optinfo
->optsnr
= parse_options(argv
[optind
-1], optinfo
->opts
);
139 optinfo
->flags
|= IP6T_OPTS_OPTS
;
140 *flags
|= IP6T_OPTS_OPTS
;
143 if (*flags
& IP6T_OPTS_NSTRICT
)
144 xtables_error(PARAMETER_PROBLEM
,
145 "Only one `--hbh-not-strict' allowed");
146 if ( !(*flags
& IP6T_OPTS_OPTS
) )
147 xtables_error(PARAMETER_PROBLEM
,
148 "`--hbh-opts ...' required before `--hbh-not-strict'");
149 optinfo
->flags
|= IP6T_OPTS_NSTRICT
;
150 *flags
|= IP6T_OPTS_NSTRICT
;
160 print_options(unsigned int optsnr
, u_int16_t
*optsp
)
164 for(i
=0; i
<optsnr
; i
++){
165 printf("%d", (optsp
[i
] & 0xFF00)>>8);
166 if ((optsp
[i
] & 0x00FF) != 0x00FF){
167 printf(":%d", (optsp
[i
] & 0x00FF));
169 printf("%c", (i
!=optsnr
-1)?',':' ');
173 static void hbh_print(const void *ip
, const struct xt_entry_match
*match
,
176 const struct ip6t_opts
*optinfo
= (struct ip6t_opts
*)match
->data
;
179 if (optinfo
->flags
& IP6T_OPTS_LEN
) {
181 printf(":%s", optinfo
->invflags
& IP6T_OPTS_INV_LEN
? "!" : "");
182 printf("%u", optinfo
->hdrlen
);
185 if (optinfo
->flags
& IP6T_OPTS_OPTS
) printf("opts ");
186 print_options(optinfo
->optsnr
, (u_int16_t
*)optinfo
->opts
);
187 if (optinfo
->flags
& IP6T_OPTS_NSTRICT
) printf("not-strict ");
188 if (optinfo
->invflags
& ~IP6T_OPTS_INV_MASK
)
189 printf("Unknown invflags: 0x%X ",
190 optinfo
->invflags
& ~IP6T_OPTS_INV_MASK
);
193 static void hbh_save(const void *ip
, const struct xt_entry_match
*match
)
195 const struct ip6t_opts
*optinfo
= (struct ip6t_opts
*)match
->data
;
197 if (optinfo
->flags
& IP6T_OPTS_LEN
) {
198 printf("%s--hbh-len %u ",
199 (optinfo
->invflags
& IP6T_OPTS_INV_LEN
) ? "! " : "",
203 if (optinfo
->flags
& IP6T_OPTS_OPTS
)
204 printf("--hbh-opts ");
205 print_options(optinfo
->optsnr
, (u_int16_t
*)optinfo
->opts
);
206 if (optinfo
->flags
& IP6T_OPTS_NSTRICT
)
207 printf("--hbh-not-strict ");
210 static struct xtables_match hbh_mt6_reg
= {
212 .version
= XTABLES_VERSION
,
213 .family
= NFPROTO_IPV6
,
214 .size
= XT_ALIGN(sizeof(struct ip6t_opts
)),
215 .userspacesize
= XT_ALIGN(sizeof(struct ip6t_opts
)),
221 .extra_opts
= hbh_opts
,
227 xtables_register_match(&hbh_mt6_reg
);