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>
14 /* Function which prints out usage message. */
15 static void dst_help(void)
18 "dst match options:\n"
19 " --dst-len [!] length total length of this header\n"
20 " --dst-opts TYPE[:LEN][,TYPE[:LEN]...]\n"
21 " Options and its length (list, max: %d)\n",
25 static const struct option dst_opts[] = {
26 { .name = "dst-len", .has_arg = 1, .val = '1' },
27 { .name = "dst-opts", .has_arg = 1, .val = '2' },
28 { .name = "dst-not-strict", .has_arg = 1, .val = '3' },
33 parse_opts_num(const char *idstr, const char *typestr)
38 id = strtoul(idstr, &ep, 0);
41 exit_error(PARAMETER_PROBLEM,
42 "dst: no valid digits in %s `%s'", typestr, idstr);
44 if ( id == ULONG_MAX && errno == ERANGE ) {
45 exit_error(PARAMETER_PROBLEM,
46 "%s `%s' specified too big: would overflow",
49 if ( *idstr != '\0' && *ep != '\0' ) {
50 exit_error(PARAMETER_PROBLEM,
51 "dst: error parsing %s `%s'", typestr, idstr);
53 return (u_int32_t) id;
57 parse_options(const char *optsstr, u_int16_t *opts)
59 char *buffer, *cp, *next, *range;
62 buffer = strdup(optsstr);
64 exit_error(OTHER_PROBLEM, "strdup failed");
66 for (cp = buffer, i = 0; cp && i < IP6T_OPTS_OPTSNR; cp = next, i++)
68 next = strchr(cp, ',');
73 range = strchr(cp, ':');
76 if (i == IP6T_OPTS_OPTSNR-1)
77 exit_error(PARAMETER_PROBLEM,
78 "too many ports specified");
82 opts[i] = (u_int16_t)((parse_opts_num(cp,"opt") & 0x000000FF)<<8);
85 exit_error(PARAMETER_PROBLEM,
86 "PAD0 hasn't got length");
87 opts[i] |= (u_int16_t)(parse_opts_num(range,"length") &
93 printf("opts str: %s %s\n", cp, range);
94 printf("opts opt: %04X\n", opts[i]);
99 exit_error(PARAMETER_PROBLEM, "too many addresses specified");
104 printf("addr nr: %d\n", i);
110 /* Initialize the match. */
111 static void dst_init(struct xt_entry_match *m)
113 struct ip6t_opts *optinfo = (struct ip6t_opts *)m->data;
117 optinfo->invflags = 0;
121 /* Function which parses command options; returns true if it
123 static int dst_parse(int c, char **argv, int invert, unsigned int *flags,
124 const void *entry, struct xt_entry_match **match)
126 struct ip6t_opts *optinfo = (struct ip6t_opts *)(*match)->data;
130 if (*flags & IP6T_OPTS_LEN)
131 exit_error(PARAMETER_PROBLEM,
132 "Only one `--dst-len' allowed");
133 check_inverse(optarg, &invert, &optind, 0);
134 optinfo->hdrlen = parse_opts_num(argv[optind-1], "length");
136 optinfo->invflags |= IP6T_OPTS_INV_LEN;
137 optinfo->flags |= IP6T_OPTS_LEN;
138 *flags |= IP6T_OPTS_LEN;
141 if (*flags & IP6T_OPTS_OPTS)
142 exit_error(PARAMETER_PROBLEM,
143 "Only one `--dst-opts' allowed");
144 check_inverse(optarg, &invert, &optind, 0);
146 exit_error(PARAMETER_PROBLEM,
147 " '!' not allowed with `--dst-opts'");
148 optinfo->optsnr = parse_options(argv[optind-1], optinfo->opts);
149 optinfo->flags |= IP6T_OPTS_OPTS;
150 *flags |= IP6T_OPTS_OPTS;
153 if (*flags & IP6T_OPTS_NSTRICT)
154 exit_error(PARAMETER_PROBLEM,
155 "Only one `--dst-not-strict' allowed");
156 if ( !(*flags & IP6T_OPTS_OPTS) )
157 exit_error(PARAMETER_PROBLEM,
158 "`--dst-opts ...' required before "
159 "`--dst-not-strict'");
160 optinfo->flags |= IP6T_OPTS_NSTRICT;
161 *flags |= IP6T_OPTS_NSTRICT;
171 print_options(unsigned int optsnr, u_int16_t *optsp)
175 for(i = 0; i < optsnr; i++) {
176 printf("%d", (optsp[i] & 0xFF00) >> 8);
178 if ((optsp[i] & 0x00FF) != 0x00FF)
179 printf(":%d", (optsp[i] & 0x00FF));
181 printf("%c", (i != optsnr - 1) ? ',' : ' ');
185 /* Prints out the union ip6t_matchinfo. */
186 static void dst_print(const void *ip, const struct xt_entry_match *match,
189 const struct ip6t_opts *optinfo = (struct ip6t_opts *)match->data;
192 if (optinfo->flags & IP6T_OPTS_LEN)
193 printf("length:%s%u ",
194 optinfo->invflags & IP6T_OPTS_INV_LEN ? "!" : "",
197 if (optinfo->flags & IP6T_OPTS_OPTS)
200 print_options(optinfo->optsnr, (u_int16_t *)optinfo->opts);
202 if (optinfo->flags & IP6T_OPTS_NSTRICT)
203 printf("not-strict ");
205 if (optinfo->invflags & ~IP6T_OPTS_INV_MASK)
206 printf("Unknown invflags: 0x%X ",
207 optinfo->invflags & ~IP6T_OPTS_INV_MASK);
210 /* Saves the union ip6t_matchinfo in parsable form to stdout. */
211 static void dst_save(const void *ip, const struct xt_entry_match *match)
213 const struct ip6t_opts *optinfo = (struct ip6t_opts *)match->data;
215 if (optinfo->flags & IP6T_OPTS_LEN) {
216 printf("--dst-len %s%u ",
217 (optinfo->invflags & IP6T_OPTS_INV_LEN) ? "! " : "",
221 if (optinfo->flags & IP6T_OPTS_OPTS)
222 printf("--dst-opts ");
224 print_options(optinfo->optsnr, (u_int16_t *)optinfo->opts);
226 if (optinfo->flags & IP6T_OPTS_NSTRICT)
227 printf("--dst-not-strict ");
230 static struct xtables_match dst_mt6_reg = {
232 .version = XTABLES_VERSION,
234 .size = XT_ALIGN(sizeof(struct ip6t_opts)),
235 .userspacesize = XT_ALIGN(sizeof(struct ip6t_opts)),
241 .extra_opts = dst_opts,
247 xtables_register_match(&dst_mt6_reg);