libip6t_dst.c revision 73866357e4a7a0fdc1b293bf8863fee2bd56da9e
15b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov/* Shared library add-on to ip6tables to add Dst header support. */
25b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov#include <stdbool.h>
35b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov#include <stdio.h>
45b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov#include <netdb.h>
55b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov#include <string.h>
65b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov#include <stdlib.h>
75b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov#include <getopt.h>
85b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov#include <errno.h>
95b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov#include <xtables.h>
105b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov#include <linux/netfilter_ipv6/ip6t_opts.h>
115b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov#include <sys/types.h>
125b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov#include <sys/socket.h>
135b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov#include <arpa/inet.h>
145b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov
155b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonovstatic void dst_help(void)
165b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov{
175b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov	printf(
185b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov"dst match options:\n"
195b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov"[!] --dst-len length            total length of this header\n"
205b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov"  --dst-opts TYPE[:LEN][,TYPE[:LEN]...]\n"
215b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov"                                Options and its length (list, max: %d)\n",
22216719b23134b9719bbf3e1de4a7d5d351c21fa8Alexey SamsonovIP6T_OPTS_OPTSNR);
236afa1b0406f5cce7256d4f8717bfe394a16999b5Kostya Serebryany}
246afa1b0406f5cce7256d4f8717bfe394a16999b5Kostya Serebryany
256afa1b0406f5cce7256d4f8717bfe394a16999b5Kostya Serebryanystatic const struct option dst_opts[] = {
266fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany	{.name = "dst-len",        .has_arg = true, .val = '1'},
276fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany	{.name = "dst-opts",       .has_arg = true, .val = '2'},
286fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany	{.name = "dst-not-strict", .has_arg = true, .val = '3'},
296fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany	XT_GETOPT_TABLEEND,
306fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany};
316fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany
326afa1b0406f5cce7256d4f8717bfe394a16999b5Kostya Serebryanystatic uint32_t
335b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonovparse_opts_num(const char *idstr, const char *typestr)
345b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov{
355b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov	unsigned long int id;
365b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov	char* ep;
375b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov
386a659dfd8e717a598f54867aa36c2e4af09d031bAlexander Potapenko	id = strtoul(idstr, &ep, 0);
396a659dfd8e717a598f54867aa36c2e4af09d031bAlexander Potapenko
405b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov	if ( idstr == ep ) {
415b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov		xtables_error(PARAMETER_PROBLEM,
425b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov		           "dst: no valid digits in %s `%s'", typestr, idstr);
435b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov	}
445b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov	if ( id == ULONG_MAX  && errno == ERANGE ) {
455b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov		xtables_error(PARAMETER_PROBLEM,
46b4fefa713da3dabda1cd83ae4182c71f1683f02cAlexey Samsonov			   "%s `%s' specified too big: would overflow",
475b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov			   typestr, idstr);
485b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov	}
495b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov	if ( *idstr != '\0'  && *ep != '\0' ) {
50b4fefa713da3dabda1cd83ae4182c71f1683f02cAlexey Samsonov		xtables_error(PARAMETER_PROBLEM,
515b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov		           "dst: error parsing %s `%s'", typestr, idstr);
525b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov	}
5350a002ecad3f0a10c136496e5b6289bd3c71590eAlexander Potapenko	return id;
54b4fefa713da3dabda1cd83ae4182c71f1683f02cAlexey Samsonov}
5550a002ecad3f0a10c136496e5b6289bd3c71590eAlexander Potapenko
565b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonovstatic int
575b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonovparse_options(const char *optsstr, uint16_t *opts)
58b4fefa713da3dabda1cd83ae4182c71f1683f02cAlexey Samsonov{
595b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov        char *buffer, *cp, *next, *range;
6050a002ecad3f0a10c136496e5b6289bd3c71590eAlexander Potapenko        unsigned int i;
615b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov
626a659dfd8e717a598f54867aa36c2e4af09d031bAlexander Potapenko	buffer = strdup(optsstr);
636a659dfd8e717a598f54867aa36c2e4af09d031bAlexander Potapenko        if (!buffer)
646a659dfd8e717a598f54867aa36c2e4af09d031bAlexander Potapenko		xtables_error(OTHER_PROBLEM, "strdup failed");
656a659dfd8e717a598f54867aa36c2e4af09d031bAlexander Potapenko
666a659dfd8e717a598f54867aa36c2e4af09d031bAlexander Potapenko        for (cp = buffer, i = 0; cp && i < IP6T_OPTS_OPTSNR; cp = next, i++)
675b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov        {
685b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov                next = strchr(cp, ',');
69580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov
705b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov                if (next)
71580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov			*next++='\0';
72580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov
73f54c0e3321e2381fca3f02faefaaa6639d59c7cfDmitry Vyukov                range = strchr(cp, ':');
74f54c0e3321e2381fca3f02faefaaa6639d59c7cfDmitry Vyukov
75580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov                if (range) {
7650a002ecad3f0a10c136496e5b6289bd3c71590eAlexander Potapenko                        if (i == IP6T_OPTS_OPTSNR-1)
77580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov				xtables_error(PARAMETER_PROBLEM,
785b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov                                           "too many ports specified");
795b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov                        *range++ = '\0';
8069563986ca570ce750111a82264d51ddbf4107baAlexander Potapenko                }
8169563986ca570ce750111a82264d51ddbf4107baAlexander Potapenko
8269563986ca570ce750111a82264d51ddbf4107baAlexander Potapenko		opts[i] = (parse_opts_num(cp, "opt") & 0xFF) << 8;
8369563986ca570ce750111a82264d51ddbf4107baAlexander Potapenko                if (range) {
8469563986ca570ce750111a82264d51ddbf4107baAlexander Potapenko			if (opts[i] == 0)
8569563986ca570ce750111a82264d51ddbf4107baAlexander Potapenko				xtables_error(PARAMETER_PROBLEM,
8650a002ecad3f0a10c136496e5b6289bd3c71590eAlexander Potapenko					"PAD0 hasn't got length");
8750a002ecad3f0a10c136496e5b6289bd3c71590eAlexander Potapenko			opts[i] |= parse_opts_num(range, "length") & 0xFF;
885b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov                } else
895b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov                        opts[i] |= (0x00FF);
906a659dfd8e717a598f54867aa36c2e4af09d031bAlexander Potapenko
9150a002ecad3f0a10c136496e5b6289bd3c71590eAlexander Potapenko#ifdef DEBUG
9250a002ecad3f0a10c136496e5b6289bd3c71590eAlexander Potapenko		printf("opts str: %s %s\n", cp, range);
9350a002ecad3f0a10c136496e5b6289bd3c71590eAlexander Potapenko		printf("opts opt: %04X\n", opts[i]);
9450a002ecad3f0a10c136496e5b6289bd3c71590eAlexander Potapenko#endif
9550a002ecad3f0a10c136496e5b6289bd3c71590eAlexander Potapenko	}
9650a002ecad3f0a10c136496e5b6289bd3c71590eAlexander Potapenko
9750a002ecad3f0a10c136496e5b6289bd3c71590eAlexander Potapenko        if (cp)
9850a002ecad3f0a10c136496e5b6289bd3c71590eAlexander Potapenko		xtables_error(PARAMETER_PROBLEM, "too many addresses specified");
9950a002ecad3f0a10c136496e5b6289bd3c71590eAlexander Potapenko
10050a002ecad3f0a10c136496e5b6289bd3c71590eAlexander Potapenko	free(buffer);
10150a002ecad3f0a10c136496e5b6289bd3c71590eAlexander Potapenko
10250a002ecad3f0a10c136496e5b6289bd3c71590eAlexander Potapenko#ifdef DEBUG
10350a002ecad3f0a10c136496e5b6289bd3c71590eAlexander Potapenko	printf("addr nr: %d\n", i);
10450a002ecad3f0a10c136496e5b6289bd3c71590eAlexander Potapenko#endif
10550a002ecad3f0a10c136496e5b6289bd3c71590eAlexander Potapenko
10650a002ecad3f0a10c136496e5b6289bd3c71590eAlexander Potapenko	return i;
10750a002ecad3f0a10c136496e5b6289bd3c71590eAlexander Potapenko}
10850a002ecad3f0a10c136496e5b6289bd3c71590eAlexander Potapenko
10950a002ecad3f0a10c136496e5b6289bd3c71590eAlexander Potapenkostatic void dst_init(struct xt_entry_match *m)
11050a002ecad3f0a10c136496e5b6289bd3c71590eAlexander Potapenko{
11150a002ecad3f0a10c136496e5b6289bd3c71590eAlexander Potapenko	struct ip6t_opts *optinfo = (struct ip6t_opts *)m->data;
11250a002ecad3f0a10c136496e5b6289bd3c71590eAlexander Potapenko
11350a002ecad3f0a10c136496e5b6289bd3c71590eAlexander Potapenko	optinfo->hdrlen = 0;
11450a002ecad3f0a10c136496e5b6289bd3c71590eAlexander Potapenko	optinfo->flags = 0;
11550a002ecad3f0a10c136496e5b6289bd3c71590eAlexander Potapenko	optinfo->invflags = 0;
11650a002ecad3f0a10c136496e5b6289bd3c71590eAlexander Potapenko	optinfo->optsnr = 0;
11750a002ecad3f0a10c136496e5b6289bd3c71590eAlexander Potapenko}
1185b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov
1195b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonovstatic int dst_parse(int c, char **argv, int invert, unsigned int *flags,
1205b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov                     const void *entry, struct xt_entry_match **match)
121b66bfd1e28776f0a350b9c197926c2c172678603Alexey Samsonov{
12250a002ecad3f0a10c136496e5b6289bd3c71590eAlexander Potapenko	struct ip6t_opts *optinfo = (struct ip6t_opts *)(*match)->data;
1235b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov
1242716a61d085a8fdf13a099822720e320414cc4dcTimur Iskhodzhanov	switch (c) {
1252716a61d085a8fdf13a099822720e320414cc4dcTimur Iskhodzhanov	case '1':
1262716a61d085a8fdf13a099822720e320414cc4dcTimur Iskhodzhanov		if (*flags & IP6T_OPTS_LEN)
1272716a61d085a8fdf13a099822720e320414cc4dcTimur Iskhodzhanov			xtables_error(PARAMETER_PROBLEM,
1282716a61d085a8fdf13a099822720e320414cc4dcTimur Iskhodzhanov				   "Only one `--dst-len' allowed");
1292716a61d085a8fdf13a099822720e320414cc4dcTimur Iskhodzhanov		xtables_check_inverse(optarg, &invert, &optind, 0, argv);
1302716a61d085a8fdf13a099822720e320414cc4dcTimur Iskhodzhanov		optinfo->hdrlen = parse_opts_num(optarg, "length");
1312716a61d085a8fdf13a099822720e320414cc4dcTimur Iskhodzhanov		if (invert)
1322716a61d085a8fdf13a099822720e320414cc4dcTimur Iskhodzhanov			optinfo->invflags |= IP6T_OPTS_INV_LEN;
1339213e07a7f95b3e634b97a7bba70849badcf2c8aTimur Iskhodzhanov		optinfo->flags |= IP6T_OPTS_LEN;
1349213e07a7f95b3e634b97a7bba70849badcf2c8aTimur Iskhodzhanov		*flags |= IP6T_OPTS_LEN;
1359213e07a7f95b3e634b97a7bba70849badcf2c8aTimur Iskhodzhanov		break;
1369213e07a7f95b3e634b97a7bba70849badcf2c8aTimur Iskhodzhanov	case '2':
1375b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov		if (*flags & IP6T_OPTS_OPTS)
138f54c0e3321e2381fca3f02faefaaa6639d59c7cfDmitry Vyukov			xtables_error(PARAMETER_PROBLEM,
139f54c0e3321e2381fca3f02faefaaa6639d59c7cfDmitry Vyukov				   "Only one `--dst-opts' allowed");
1405b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov                xtables_check_inverse(optarg, &invert, &optind, 0, argv);
141b66bfd1e28776f0a350b9c197926c2c172678603Alexey Samsonov                if (invert)
142b66bfd1e28776f0a350b9c197926c2c172678603Alexey Samsonov			xtables_error(PARAMETER_PROBLEM,
143ba362a7f0e98b369758f07aec8794c61e688b82dAlexey Samsonov				" '!' not allowed with `--dst-opts'");
1445b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov		optinfo->optsnr = parse_options(optarg, optinfo->opts);
1455b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov		optinfo->flags |= IP6T_OPTS_OPTS;
14669563986ca570ce750111a82264d51ddbf4107baAlexander Potapenko		*flags |= IP6T_OPTS_OPTS;
1470ef531054fc25c11e372cbab1384f10954984219Alexander Potapenko		break;
1480ef531054fc25c11e372cbab1384f10954984219Alexander Potapenko	case '3':
1490ef531054fc25c11e372cbab1384f10954984219Alexander Potapenko		if (*flags & IP6T_OPTS_NSTRICT)
1500ef531054fc25c11e372cbab1384f10954984219Alexander Potapenko			xtables_error(PARAMETER_PROBLEM,
1510ef531054fc25c11e372cbab1384f10954984219Alexander Potapenko				   "Only one `--dst-not-strict' allowed");
1520ef531054fc25c11e372cbab1384f10954984219Alexander Potapenko		if ( !(*flags & IP6T_OPTS_OPTS) )
1530ef531054fc25c11e372cbab1384f10954984219Alexander Potapenko			xtables_error(PARAMETER_PROBLEM,
1540ef531054fc25c11e372cbab1384f10954984219Alexander Potapenko				   "`--dst-opts ...' required before "
1550ef531054fc25c11e372cbab1384f10954984219Alexander Potapenko				   "`--dst-not-strict'");
15669563986ca570ce750111a82264d51ddbf4107baAlexander Potapenko		optinfo->flags |= IP6T_OPTS_NSTRICT;
1570ef531054fc25c11e372cbab1384f10954984219Alexander Potapenko		*flags |= IP6T_OPTS_NSTRICT;
1580ef531054fc25c11e372cbab1384f10954984219Alexander Potapenko		break;
1590ef531054fc25c11e372cbab1384f10954984219Alexander Potapenko	}
16069563986ca570ce750111a82264d51ddbf4107baAlexander Potapenko
1615b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov	return 1;
1626bae39d1db13f60d3e9b8393e5b9d9eb2ab1b5c0Chandler Carruth}
163c27279a4a08e0661f204c3e5dc65aafce79dec8aAlexey Samsonov
1645b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonovstatic void
1655b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonovprint_options(unsigned int optsnr, uint16_t *optsp)
166b66bfd1e28776f0a350b9c197926c2c172678603Alexey Samsonov{
167b66bfd1e28776f0a350b9c197926c2c172678603Alexey Samsonov	unsigned int i;
168b66bfd1e28776f0a350b9c197926c2c172678603Alexey Samsonov
169b66bfd1e28776f0a350b9c197926c2c172678603Alexey Samsonov	printf(" ");
17069563986ca570ce750111a82264d51ddbf4107baAlexander Potapenko	for(i = 0; i < optsnr; i++) {
171b66bfd1e28776f0a350b9c197926c2c172678603Alexey Samsonov		printf("%d", (optsp[i] & 0xFF00) >> 8);
172b66bfd1e28776f0a350b9c197926c2c172678603Alexey Samsonov
1730ef531054fc25c11e372cbab1384f10954984219Alexander Potapenko		if ((optsp[i] & 0x00FF) != 0x00FF)
1740ef531054fc25c11e372cbab1384f10954984219Alexander Potapenko			printf(":%d", (optsp[i] & 0x00FF));
1750ef531054fc25c11e372cbab1384f10954984219Alexander Potapenko
1760ef531054fc25c11e372cbab1384f10954984219Alexander Potapenko		printf("%c", (i != optsnr - 1) ? ',' : ' ');
177b66bfd1e28776f0a350b9c197926c2c172678603Alexey Samsonov	}
1780ef531054fc25c11e372cbab1384f10954984219Alexander Potapenko}
179600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov
18050a002ecad3f0a10c136496e5b6289bd3c71590eAlexander Potapenkostatic void dst_print(const void *ip, const struct xt_entry_match *match,
181b66bfd1e28776f0a350b9c197926c2c172678603Alexey Samsonov                      int numeric)
182b66bfd1e28776f0a350b9c197926c2c172678603Alexey Samsonov{
183b66bfd1e28776f0a350b9c197926c2c172678603Alexey Samsonov	const struct ip6t_opts *optinfo = (struct ip6t_opts *)match->data;
1845b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov
1855b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov	printf(" dst");
186b66bfd1e28776f0a350b9c197926c2c172678603Alexey Samsonov	if (optinfo->flags & IP6T_OPTS_LEN)
1876a659dfd8e717a598f54867aa36c2e4af09d031bAlexander Potapenko		printf(" length:%s%u",
1886a659dfd8e717a598f54867aa36c2e4af09d031bAlexander Potapenko			optinfo->invflags & IP6T_OPTS_INV_LEN ? "!" : "",
1896a659dfd8e717a598f54867aa36c2e4af09d031bAlexander Potapenko			optinfo->hdrlen);
1906a659dfd8e717a598f54867aa36c2e4af09d031bAlexander Potapenko
1916a659dfd8e717a598f54867aa36c2e4af09d031bAlexander Potapenko	if (optinfo->flags & IP6T_OPTS_OPTS)
19250a002ecad3f0a10c136496e5b6289bd3c71590eAlexander Potapenko		printf(" opts");
1936a659dfd8e717a598f54867aa36c2e4af09d031bAlexander Potapenko
1946a659dfd8e717a598f54867aa36c2e4af09d031bAlexander Potapenko	print_options(optinfo->optsnr, (uint16_t *)optinfo->opts);
1956a659dfd8e717a598f54867aa36c2e4af09d031bAlexander Potapenko
19650a002ecad3f0a10c136496e5b6289bd3c71590eAlexander Potapenko	if (optinfo->flags & IP6T_OPTS_NSTRICT)
19750a002ecad3f0a10c136496e5b6289bd3c71590eAlexander Potapenko		printf(" not-strict");
19850a002ecad3f0a10c136496e5b6289bd3c71590eAlexander Potapenko
19950a002ecad3f0a10c136496e5b6289bd3c71590eAlexander Potapenko	if (optinfo->invflags & ~IP6T_OPTS_INV_MASK)
2006a659dfd8e717a598f54867aa36c2e4af09d031bAlexander Potapenko		printf(" Unknown invflags: 0x%X",
2016a659dfd8e717a598f54867aa36c2e4af09d031bAlexander Potapenko		       optinfo->invflags & ~IP6T_OPTS_INV_MASK);
2026a659dfd8e717a598f54867aa36c2e4af09d031bAlexander Potapenko}
2036a659dfd8e717a598f54867aa36c2e4af09d031bAlexander Potapenko
2046a659dfd8e717a598f54867aa36c2e4af09d031bAlexander Potapenkostatic void dst_save(const void *ip, const struct xt_entry_match *match)
2056a659dfd8e717a598f54867aa36c2e4af09d031bAlexander Potapenko{
20650a002ecad3f0a10c136496e5b6289bd3c71590eAlexander Potapenko	const struct ip6t_opts *optinfo = (struct ip6t_opts *)match->data;
20750a002ecad3f0a10c136496e5b6289bd3c71590eAlexander Potapenko
20850a002ecad3f0a10c136496e5b6289bd3c71590eAlexander Potapenko	if (optinfo->flags & IP6T_OPTS_LEN) {
20950a002ecad3f0a10c136496e5b6289bd3c71590eAlexander Potapenko		printf("%s --dst-len %u",
210600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov			(optinfo->invflags & IP6T_OPTS_INV_LEN) ? " !" : "",
211600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov			optinfo->hdrlen);
212600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov	}
213b66bfd1e28776f0a350b9c197926c2c172678603Alexey Samsonov
214b66bfd1e28776f0a350b9c197926c2c172678603Alexey Samsonov	if (optinfo->flags & IP6T_OPTS_OPTS)
215b66bfd1e28776f0a350b9c197926c2c172678603Alexey Samsonov		printf(" --dst-opts");
216b66bfd1e28776f0a350b9c197926c2c172678603Alexey Samsonov
2179213e07a7f95b3e634b97a7bba70849badcf2c8aTimur Iskhodzhanov	print_options(optinfo->optsnr, (uint16_t *)optinfo->opts);
218b66bfd1e28776f0a350b9c197926c2c172678603Alexey Samsonov
219b66bfd1e28776f0a350b9c197926c2c172678603Alexey Samsonov	if (optinfo->flags & IP6T_OPTS_NSTRICT)
220b66bfd1e28776f0a350b9c197926c2c172678603Alexey Samsonov		printf(" --dst-not-strict");
221600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov}
2225b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov
223592d3f707e02968c75fd6e90d06d24f5df99c8b9Alexey Samsonovstatic struct xtables_match dst_mt6_reg = {
224592d3f707e02968c75fd6e90d06d24f5df99c8b9Alexey Samsonov	.name          = "dst",
225592d3f707e02968c75fd6e90d06d24f5df99c8b9Alexey Samsonov	.version       = XTABLES_VERSION,
226592d3f707e02968c75fd6e90d06d24f5df99c8b9Alexey Samsonov	.family        = NFPROTO_IPV6,
227592d3f707e02968c75fd6e90d06d24f5df99c8b9Alexey Samsonov	.size          = XT_ALIGN(sizeof(struct ip6t_opts)),
228592d3f707e02968c75fd6e90d06d24f5df99c8b9Alexey Samsonov	.userspacesize = XT_ALIGN(sizeof(struct ip6t_opts)),
229b46941a1d23012491a7a8a52718cacbde3c19ba1Alexey Samsonov	.help          = dst_help,
230b46941a1d23012491a7a8a52718cacbde3c19ba1Alexey Samsonov	.init          = dst_init,
231b46941a1d23012491a7a8a52718cacbde3c19ba1Alexey Samsonov	.parse         = dst_parse,
232592d3f707e02968c75fd6e90d06d24f5df99c8b9Alexey Samsonov	.print         = dst_print,
233b46941a1d23012491a7a8a52718cacbde3c19ba1Alexey Samsonov	.save          = dst_save,
234592d3f707e02968c75fd6e90d06d24f5df99c8b9Alexey Samsonov	.extra_opts    = dst_opts,
235592d3f707e02968c75fd6e90d06d24f5df99c8b9Alexey Samsonov};
2365b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov
2375b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonovvoid
2385b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov_init(void)
2395b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov{
2405b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov	xtables_register_match(&dst_mt6_reg);
2415b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov}
2425b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov