1 /* Shared library add-on to ip6tables to add Hop-by-Hop and Dst headers 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 #define UNAME (HOPBYHOP ? "HBH" : "DST")
18 #define LNAME (HOPBYHOP ? "hbh" : "dst")
20 /* Function which prints out usage message. */
26 " --%s-len [!] length total length of this header\n"
27 " --%s-opts TYPE[:LEN][,TYPE[:LEN]...] \n"
28 " Options and its length (list, max: %d)\n",
29 UNAME
, IPTABLES_VERSION
, LNAME
, LNAME
, IP6T_OPTS_OPTSNR
);
33 static struct option opts
[] = {
34 { "hbh-len", 1, 0, '1' },
35 { "hbh-opts", 1, 0, '2' },
36 { "hbh-not-strict", 1, 0, '3' },
40 static struct option opts
[] = {
41 { "dst-len", 1, 0, '1' },
42 { "dst-opts", 1, 0, '2' },
43 { "dst-not-strict", 1, 0, '3' },
49 parse_opts_num(const char *idstr
, const char *typestr
)
54 id
= strtoul(idstr
,&ep
,0) ;
57 exit_error(PARAMETER_PROBLEM
,
58 "%s no valid digits in %s `%s'", UNAME
, typestr
, idstr
);
60 if ( id
== ULONG_MAX
&& errno
== ERANGE
) {
61 exit_error(PARAMETER_PROBLEM
,
62 "%s `%s' specified too big: would overflow",
65 if ( *idstr
!= '\0' && *ep
!= '\0' ) {
66 exit_error(PARAMETER_PROBLEM
,
67 "%s error parsing %s `%s'", UNAME
, typestr
, idstr
);
69 return (u_int32_t
) id
;
73 parse_options(const char *optsstr
, u_int16_t
*opts
)
75 char *buffer
, *cp
, *next
, *range
;
78 buffer
= strdup(optsstr
);
79 if (!buffer
) exit_error(OTHER_PROBLEM
, "strdup failed");
81 for (cp
=buffer
, i
=0; cp
&& i
<IP6T_OPTS_OPTSNR
; cp
=next
,i
++)
84 if (next
) *next
++='\0';
85 range
= strchr(cp
, ':');
87 if (i
== IP6T_OPTS_OPTSNR
-1)
88 exit_error(PARAMETER_PROBLEM
,
89 "too many ports specified");
92 opts
[i
] = (u_int16_t
)((parse_opts_num(cp
,"opt") & 0x000000FF)<<8);
95 exit_error(PARAMETER_PROBLEM
, "PAD0 hasn't got length");
96 opts
[i
] |= (u_int16_t
)(parse_opts_num(range
,"length") &
103 printf("opts str: %s %s\n", cp
, range
);
104 printf("opts opt: %04X\n", opts
[i
]);
107 if (cp
) exit_error(PARAMETER_PROBLEM
, "too many addresses specified");
112 printf("addr nr: %d\n", i
);
118 /* Initialize the match. */
120 init(struct ip6t_entry_match
*m
, unsigned int *nfcache
)
122 struct ip6t_opts
*optinfo
= (struct ip6t_opts
*)m
->data
;
126 optinfo
->invflags
= 0;
130 /* Function which parses command options; returns true if it
133 parse(int c
, char **argv
, int invert
, unsigned int *flags
,
134 const struct ip6t_entry
*entry
,
135 unsigned int *nfcache
,
136 struct ip6t_entry_match
**match
)
138 struct ip6t_opts
*optinfo
= (struct ip6t_opts
*)(*match
)->data
;
142 if (*flags
& IP6T_OPTS_LEN
)
143 exit_error(PARAMETER_PROBLEM
,
144 "Only one `--%s-len' allowed", LNAME
);
145 check_inverse(optarg
, &invert
, &optind
, 0);
146 optinfo
->hdrlen
= parse_opts_num(argv
[optind
-1], "length");
148 optinfo
->invflags
|= IP6T_OPTS_INV_LEN
;
149 optinfo
->flags
|= IP6T_OPTS_LEN
;
150 *flags
|= IP6T_OPTS_LEN
;
153 if (*flags
& IP6T_OPTS_OPTS
)
154 exit_error(PARAMETER_PROBLEM
,
155 "Only one `--%s-opts' allowed", LNAME
);
156 check_inverse(optarg
, &invert
, &optind
, 0);
158 exit_error(PARAMETER_PROBLEM
,
159 " '!' not allowed with `--%s-opts'", LNAME
);
160 optinfo
->optsnr
= parse_options(argv
[optind
-1], optinfo
->opts
);
161 optinfo
->flags
|= IP6T_OPTS_OPTS
;
162 *flags
|= IP6T_OPTS_OPTS
;
165 if (*flags
& IP6T_OPTS_NSTRICT
)
166 exit_error(PARAMETER_PROBLEM
,
167 "Only one `--%s-not-strict' allowed", LNAME
);
168 if ( !(*flags
& IP6T_OPTS_OPTS
) )
169 exit_error(PARAMETER_PROBLEM
,
170 "`--%s-opts ...' required before `--%s-not-strict'", LNAME
, LNAME
);
171 optinfo
->flags
|= IP6T_OPTS_NSTRICT
;
172 *flags
|= IP6T_OPTS_NSTRICT
;
181 /* Final check; we don't care. */
183 final_check(unsigned int flags
)
188 print_options(int optsnr
, u_int16_t
*optsp
)
192 for(i
=0; i
<optsnr
; i
++){
193 printf("%d", (optsp
[i
] & 0xFF00)>>8);
194 if ((optsp
[i
] & 0x00FF) != 0x00FF){
195 printf(":%d", (optsp
[i
] & 0x00FF));
197 printf("%c", (i
!=optsnr
-1)?',':' ');
201 /* Prints out the union ip6t_matchinfo. */
203 print(const struct ip6t_ip6
*ip
,
204 const struct ip6t_entry_match
*match
, int numeric
)
206 const struct ip6t_opts
*optinfo
= (struct ip6t_opts
*)match
->data
;
208 printf("%s ", LNAME
);
209 if (optinfo
->flags
& IP6T_OPTS_LEN
) {
211 printf(":%s", optinfo
->invflags
& IP6T_OPTS_INV_LEN
? "!" : "");
212 printf("%u", optinfo
->hdrlen
);
215 if (optinfo
->flags
& IP6T_OPTS_OPTS
) printf("opts ");
216 print_options(optinfo
->optsnr
, (u_int16_t
*)optinfo
->opts
);
217 if (optinfo
->flags
& IP6T_OPTS_NSTRICT
) printf("not-strict ");
218 if (optinfo
->invflags
& ~IP6T_OPTS_INV_MASK
)
219 printf("Unknown invflags: 0x%X ",
220 optinfo
->invflags
& ~IP6T_OPTS_INV_MASK
);
223 /* Saves the union ip6t_matchinfo in parsable form to stdout. */
224 static void save(const struct ip6t_ip6
*ip
, const struct ip6t_entry_match
*match
)
226 const struct ip6t_opts
*optinfo
= (struct ip6t_opts
*)match
->data
;
228 if (optinfo
->flags
& IP6T_OPTS_LEN
) {
229 printf("--%s-len %s%u ", LNAME
,
230 (optinfo
->invflags
& IP6T_OPTS_INV_LEN
) ? "! " : "",
234 if (optinfo
->flags
& IP6T_OPTS_OPTS
) printf("--%s-opts ", LNAME
);
235 print_options(optinfo
->optsnr
, (u_int16_t
*)optinfo
->opts
);
236 if (optinfo
->flags
& IP6T_OPTS_NSTRICT
) printf("--%s-not-strict ", LNAME
);
240 static struct ip6tables_match optstruct
= {
246 .version
= IPTABLES_VERSION
,
247 .size
= IP6T_ALIGN(sizeof(struct ip6t_opts
)),
248 .userspacesize
= IP6T_ALIGN(sizeof(struct ip6t_opts
)),
252 .final_check
= &final_check
,
261 register_match6(&optstruct
);