1 /* Shared library add-on to ip6tables to add Hop-by-Hop and Dst headers support. */
9 #include <linux/netfilter_ipv6/ip6t_opts.h>
10 #include <sys/types.h>
11 #include <sys/socket.h>
12 #include <arpa/inet.h>
22 /* Function which prints out usage message. */
27 UNAME
" v%s options:\n"
28 " --" LNAME
"-len [!] length total length of this header\n"
29 " --" LNAME
"-opts TYPE[:LEN][,TYPE[:LEN]...] \n"
30 " Options and its length (list, max: %d)\n",
31 IPTABLES_VERSION
, IP6T_OPTS_OPTSNR
);
34 static struct option opts
[] = {
35 { .name
= LNAME
"-len", .has_arg
= 1, .flag
= 0, .val
= '1' },
36 { .name
= LNAME
"-opts", .has_arg
= 1, .flag
= 0, .val
= '2' },
37 { .name
= LNAME
"-not-strict", .has_arg
= 1, .flag
= 0, .val
= '3' },
42 parse_opts_num(const char *idstr
, const char *typestr
)
47 id
= strtoul(idstr
, &ep
, 0);
50 exit_error(PARAMETER_PROBLEM
,
51 UNAME
" no valid digits in %s `%s'", typestr
, idstr
);
53 if ( id
== ULONG_MAX
&& errno
== ERANGE
) {
54 exit_error(PARAMETER_PROBLEM
,
55 "%s `%s' specified too big: would overflow",
58 if ( *idstr
!= '\0' && *ep
!= '\0' ) {
59 exit_error(PARAMETER_PROBLEM
,
60 UNAME
" error parsing %s `%s'", typestr
, idstr
);
62 return (u_int32_t
) id
;
66 parse_options(const char *optsstr
, u_int16_t
*opts
)
68 char *buffer
, *cp
, *next
, *range
;
71 buffer
= strdup(optsstr
);
73 exit_error(OTHER_PROBLEM
, "strdup failed");
75 for (cp
= buffer
, i
= 0; cp
&& i
< IP6T_OPTS_OPTSNR
; cp
= next
, i
++)
77 next
= strchr(cp
, ',');
82 range
= strchr(cp
, ':');
85 if (i
== IP6T_OPTS_OPTSNR
-1)
86 exit_error(PARAMETER_PROBLEM
,
87 "too many ports specified");
91 opts
[i
] = (u_int16_t
)((parse_opts_num(cp
,"opt") & 0x000000FF)<<8);
94 exit_error(PARAMETER_PROBLEM
,
95 "PAD0 hasn't got length");
96 opts
[i
] |= (u_int16_t
)(parse_opts_num(range
,"length") &
102 printf("opts str: %s %s\n", cp
, range
);
103 printf("opts opt: %04X\n", opts
[i
]);
108 exit_error(PARAMETER_PROBLEM
, "too many addresses specified");
113 printf("addr nr: %d\n", i
);
119 /* Initialize the match. */
121 init(struct ip6t_entry_match
*m
, unsigned int *nfcache
)
123 struct ip6t_opts
*optinfo
= (struct ip6t_opts
*)m
->data
;
127 optinfo
->invflags
= 0;
131 /* Function which parses command options; returns true if it
134 parse(int c
, char **argv
, int invert
, unsigned int *flags
,
135 const struct ip6t_entry
*entry
,
136 unsigned int *nfcache
,
137 struct ip6t_entry_match
**match
)
139 struct ip6t_opts
*optinfo
= (struct ip6t_opts
*)(*match
)->data
;
143 if (*flags
& IP6T_OPTS_LEN
)
144 exit_error(PARAMETER_PROBLEM
,
145 "Only one `--" LNAME
"-len' allowed");
146 check_inverse(optarg
, &invert
, &optind
, 0);
147 optinfo
->hdrlen
= parse_opts_num(argv
[optind
-1], "length");
149 optinfo
->invflags
|= IP6T_OPTS_INV_LEN
;
150 optinfo
->flags
|= IP6T_OPTS_LEN
;
151 *flags
|= IP6T_OPTS_LEN
;
154 if (*flags
& IP6T_OPTS_OPTS
)
155 exit_error(PARAMETER_PROBLEM
,
156 "Only one `--" LNAME
"-opts' allowed");
157 check_inverse(optarg
, &invert
, &optind
, 0);
159 exit_error(PARAMETER_PROBLEM
,
160 " '!' not allowed with `--" LNAME
"-opts'");
161 optinfo
->optsnr
= parse_options(argv
[optind
-1], optinfo
->opts
);
162 optinfo
->flags
|= IP6T_OPTS_OPTS
;
163 *flags
|= IP6T_OPTS_OPTS
;
166 if (*flags
& IP6T_OPTS_NSTRICT
)
167 exit_error(PARAMETER_PROBLEM
,
168 "Only one `--" LNAME
"-not-strict' allowed");
169 if ( !(*flags
& IP6T_OPTS_OPTS
) )
170 exit_error(PARAMETER_PROBLEM
,
171 "`--" LNAME
"-opts ...' required before `--"
172 LNAME
"-not-strict'");
173 optinfo
->flags
|= IP6T_OPTS_NSTRICT
;
174 *flags
|= IP6T_OPTS_NSTRICT
;
183 /* Final check; we don't care. */
185 final_check(unsigned int flags
)
190 print_options(int optsnr
, u_int16_t
*optsp
)
194 for(i
= 0; i
< optsnr
; i
++) {
195 printf("%d", (optsp
[i
] & 0xFF00) >> 8);
197 if ((optsp
[i
] & 0x00FF) != 0x00FF)
198 printf(":%d", (optsp
[i
] & 0x00FF));
200 printf("%c", (i
!= optsnr
- 1) ? ',' : ' ');
204 /* Prints out the union ip6t_matchinfo. */
206 print(const struct ip6t_ip6
*ip
,
207 const struct ip6t_entry_match
*match
, int numeric
)
209 const struct ip6t_opts
*optinfo
= (struct ip6t_opts
*)match
->data
;
212 if (optinfo
->flags
& IP6T_OPTS_LEN
)
213 printf("length:%s%u ",
214 optinfo
->invflags
& IP6T_OPTS_INV_LEN
? "!" : "",
217 if (optinfo
->flags
& IP6T_OPTS_OPTS
)
220 print_options(optinfo
->optsnr
, (u_int16_t
*)optinfo
->opts
);
222 if (optinfo
->flags
& IP6T_OPTS_NSTRICT
)
223 printf("not-strict ");
225 if (optinfo
->invflags
& ~IP6T_OPTS_INV_MASK
)
226 printf("Unknown invflags: 0x%X ",
227 optinfo
->invflags
& ~IP6T_OPTS_INV_MASK
);
230 /* Saves the union ip6t_matchinfo in parsable form to stdout. */
231 static void save(const struct ip6t_ip6
*ip
, const struct ip6t_entry_match
*match
)
233 const struct ip6t_opts
*optinfo
= (struct ip6t_opts
*)match
->data
;
235 if (optinfo
->flags
& IP6T_OPTS_LEN
) {
236 printf("--" LNAME
"-len %s%u ",
237 (optinfo
->invflags
& IP6T_OPTS_INV_LEN
) ? "! " : "",
241 if (optinfo
->flags
& IP6T_OPTS_OPTS
)
242 printf("--" LNAME
"-opts ");
244 print_options(optinfo
->optsnr
, (u_int16_t
*)optinfo
->opts
);
246 if (optinfo
->flags
& IP6T_OPTS_NSTRICT
)
247 printf("--" LNAME
"-not-strict ");
251 struct ip6tables_match optstruct
= {
253 .version
= IPTABLES_VERSION
,
254 .size
= IP6T_ALIGN(sizeof(struct ip6t_opts
)),
255 .userspacesize
= IP6T_ALIGN(sizeof(struct ip6t_opts
)),
259 .final_check
= &final_check
,
268 register_match6(&optstruct
);