libip6t_hbh.c revision 967279231a9ecfa99f26694a954afc535c63db1d
12ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó/* Shared library add-on to ip6tables to add Hop-by-Hop and Dst headers support. */
22ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó#include <stdio.h>
32ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó#include <netdb.h>
42ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó#include <string.h>
52ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó#include <stdlib.h>
62ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó#include <getopt.h>
72ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó#include <errno.h>
82ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó#include <ip6tables.h>
92ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó/*#include <linux/in6.h>*/
102ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó#include <linux/netfilter_ipv6/ip6t_opts.h>
112ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó#include <sys/types.h>
122ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó#include <sys/socket.h>
132ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó#include <arpa/inet.h>
142ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó
152ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó#define DEBUG		0
162ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó
172ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó/* Function which prints out usage message. */
18997045f536026c0d643bf884da5ff5de2605197fJan Engelhardtstatic void hbh_help(void)
192ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó{
202ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó	printf(
218b7c64d6ba156a99008fcd810cba874c73294333Jan Engelhardt"hbh match options:\n"
22967279231a9ecfa99f26694a954afc535c63db1dJan Engelhardt"[!] --hbh-len length            total length of this header\n"
23e2f588ab7481760f069cd30d3146569f074721aaJan Engelhardt"  --hbh-opts TYPE[:LEN][,TYPE[:LEN]...] \n"
24e2f588ab7481760f069cd30d3146569f074721aaJan Engelhardt"                                Options and its length (list, max: %d)\n",
258b7c64d6ba156a99008fcd810cba874c73294333Jan EngelhardtIP6T_OPTS_OPTSNR);
262ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó}
272ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó
28997045f536026c0d643bf884da5ff5de2605197fJan Engelhardtstatic const struct option hbh_opts[] = {
29500f483fff529dcd88ec96b9d5054be6cd6363a0Patrick McHardy	{ "hbh-len", 1, NULL, '1' },
30500f483fff529dcd88ec96b9d5054be6cd6363a0Patrick McHardy	{ "hbh-opts", 1, NULL, '2' },
31500f483fff529dcd88ec96b9d5054be6cd6363a0Patrick McHardy	{ "hbh-not-strict", 1, NULL, '3' },
329ee386a1b6d7704b259460152c959ab0e79e02aaMax Kellermann	{ .name = NULL }
332ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó};
342ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó
352ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabóstatic u_int32_t
362ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabóparse_opts_num(const char *idstr, const char *typestr)
372ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó{
382ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó	unsigned long int id;
392ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó	char* ep;
402ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó
412ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó	id =  strtoul(idstr,&ep,0) ;
422ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó
432ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó	if ( idstr == ep ) {
442ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó		exit_error(PARAMETER_PROBLEM,
45e2f588ab7481760f069cd30d3146569f074721aaJan Engelhardt			   "hbh: no valid digits in %s `%s'", typestr, idstr);
462ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó	}
472ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó	if ( id == ULONG_MAX  && errno == ERANGE ) {
482ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó		exit_error(PARAMETER_PROBLEM,
492ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó			   "%s `%s' specified too big: would overflow",
502ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó			   typestr, idstr);
512ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó	}
522ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó	if ( *idstr != '\0'  && *ep != '\0' ) {
532ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó		exit_error(PARAMETER_PROBLEM,
54e2f588ab7481760f069cd30d3146569f074721aaJan Engelhardt			   "hbh: error parsing %s `%s'", typestr, idstr);
552ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó	}
562ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó	return (u_int32_t) id;
572ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó}
582ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó
592ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabóstatic int
602ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabóparse_options(const char *optsstr, u_int16_t *opts)
612ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó{
622ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó        char *buffer, *cp, *next, *range;
632ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó        unsigned int i;
642ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó
652ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó	buffer = strdup(optsstr);
662ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó        if (!buffer) exit_error(OTHER_PROBLEM, "strdup failed");
672ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó
682ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó        for (cp=buffer, i=0; cp && i<IP6T_OPTS_OPTSNR; cp=next,i++)
692ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó        {
702ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó                next=strchr(cp, ',');
712ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó                if (next) *next++='\0';
722ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó                range = strchr(cp, ':');
732ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó                if (range) {
742ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó                        if (i == IP6T_OPTS_OPTSNR-1)
752ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó                                exit_error(PARAMETER_PROBLEM,
762ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó                                           "too many ports specified");
772ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó                        *range++ = '\0';
782ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó                }
792ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó                opts[i] = (u_int16_t)((parse_opts_num(cp,"opt") & 0x000000FF)<<8);
802ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó                if (range) {
812ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó			if (opts[i] == 0)
822ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó        			exit_error(PARAMETER_PROBLEM, "PAD0 hasn't got length");
832ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó                        opts[i] |= (u_int16_t)(parse_opts_num(range,"length") &
842ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó					0x000000FF);
852ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó                } else {
862ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó                        opts[i] |= (0x00FF);
872ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó		}
882ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó
892ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó#if DEBUG
902ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó		printf("opts str: %s %s\n", cp, range);
912ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó		printf("opts opt: %04X\n", opts[i]);
922ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó#endif
932ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó	}
942ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó        if (cp) exit_error(PARAMETER_PROBLEM, "too many addresses specified");
952ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó
962ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó	free(buffer);
972ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó
982ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó#if DEBUG
992ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó	printf("addr nr: %d\n", i);
1002ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó#endif
1012ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó
1022ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó	return i;
1032ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó}
1042ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó
1052ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó/* Initialize the match. */
106997045f536026c0d643bf884da5ff5de2605197fJan Engelhardtstatic void hbh_init(struct xt_entry_match *m)
1072ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó{
1082ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó	struct ip6t_opts *optinfo = (struct ip6t_opts *)m->data;
1092ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó
1102ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó	optinfo->hdrlen = 0;
1112ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó	optinfo->flags = 0;
1122ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó	optinfo->invflags = 0;
1132ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó	optinfo->optsnr = 0;
1142ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó}
1152ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó
1162ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó/* Function which parses command options; returns true if it
1172ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó   ate an option */
118997045f536026c0d643bf884da5ff5de2605197fJan Engelhardtstatic int hbh_parse(int c, char **argv, int invert, unsigned int *flags,
119997045f536026c0d643bf884da5ff5de2605197fJan Engelhardt                     const void *entry, struct xt_entry_match **match)
1202ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó{
1212ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó	struct ip6t_opts *optinfo = (struct ip6t_opts *)(*match)->data;
1222ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó
1232ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó	switch (c) {
1242ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó	case '1':
1252ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó		if (*flags & IP6T_OPTS_LEN)
1262ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó			exit_error(PARAMETER_PROBLEM,
127e2f588ab7481760f069cd30d3146569f074721aaJan Engelhardt				   "Only one `--hbh-len' allowed");
1282ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó		check_inverse(optarg, &invert, &optind, 0);
1292ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó		optinfo->hdrlen = parse_opts_num(argv[optind-1], "length");
1302ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó		if (invert)
1312ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó			optinfo->invflags |= IP6T_OPTS_INV_LEN;
1322ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó		optinfo->flags |= IP6T_OPTS_LEN;
1332ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó		*flags |= IP6T_OPTS_LEN;
1342ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó		break;
1352ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó	case '2':
1362ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó		if (*flags & IP6T_OPTS_OPTS)
1372ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó			exit_error(PARAMETER_PROBLEM,
138e2f588ab7481760f069cd30d3146569f074721aaJan Engelhardt				   "Only one `--hbh-opts' allowed");
1392ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó                check_inverse(optarg, &invert, &optind, 0);
1402ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó                if (invert)
1412ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó                        exit_error(PARAMETER_PROBLEM,
142e2f588ab7481760f069cd30d3146569f074721aaJan Engelhardt				" '!' not allowed with `--hbh-opts'");
1432ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó		optinfo->optsnr = parse_options(argv[optind-1], optinfo->opts);
1442ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó		optinfo->flags |= IP6T_OPTS_OPTS;
1452ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó		*flags |= IP6T_OPTS_OPTS;
1462ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó		break;
1472ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó	case '3':
1482ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó		if (*flags & IP6T_OPTS_NSTRICT)
1492ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó			exit_error(PARAMETER_PROBLEM,
150e2f588ab7481760f069cd30d3146569f074721aaJan Engelhardt				   "Only one `--hbh-not-strict' allowed");
1512ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó		if ( !(*flags & IP6T_OPTS_OPTS) )
1522ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó			exit_error(PARAMETER_PROBLEM,
153e2f588ab7481760f069cd30d3146569f074721aaJan Engelhardt				   "`--hbh-opts ...' required before `--hbh-not-strict'");
1542ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó		optinfo->flags |= IP6T_OPTS_NSTRICT;
1552ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó		*flags |= IP6T_OPTS_NSTRICT;
1562ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó		break;
1572ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó	default:
1582ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó		return 0;
1592ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó	}
1602ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó
1612ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó	return 1;
1622ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó}
1632ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó
1642ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabóstatic void
1657a236f4cc685a420c1a782a5db614a93baf37ccfJan Engelhardtprint_options(unsigned int optsnr, u_int16_t *optsp)
1662ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó{
1672ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó	unsigned int i;
1682ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó
1692ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó	for(i=0; i<optsnr; i++){
1702ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó		printf("%d", (optsp[i] & 0xFF00)>>8);
1712ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó		if ((optsp[i] & 0x00FF) != 0x00FF){
1722ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó			printf(":%d", (optsp[i] & 0x00FF));
1732ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó		}
1742ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó		printf("%c", (i!=optsnr-1)?',':' ');
1752ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó	}
1762ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó}
1772ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó
1782ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó/* Prints out the union ip6t_matchinfo. */
179997045f536026c0d643bf884da5ff5de2605197fJan Engelhardtstatic void hbh_print(const void *ip, const struct xt_entry_match *match,
180997045f536026c0d643bf884da5ff5de2605197fJan Engelhardt                      int numeric)
1812ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó{
1822ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó	const struct ip6t_opts *optinfo = (struct ip6t_opts *)match->data;
1832ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó
184e2f588ab7481760f069cd30d3146569f074721aaJan Engelhardt	printf("hbh ");
1852ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó	if (optinfo->flags & IP6T_OPTS_LEN) {
1862ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó		printf("length");
1872ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó		printf(":%s", optinfo->invflags & IP6T_OPTS_INV_LEN ? "!" : "");
1882ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó		printf("%u", optinfo->hdrlen);
1892ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó		printf(" ");
1902ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó	}
1912ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó	if (optinfo->flags & IP6T_OPTS_OPTS) printf("opts ");
192ae31bb6bac68f800a1e4b30cf2548dacaaf76102Fabrice MARIE	print_options(optinfo->optsnr, (u_int16_t *)optinfo->opts);
1932ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó	if (optinfo->flags & IP6T_OPTS_NSTRICT) printf("not-strict ");
1942ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó	if (optinfo->invflags & ~IP6T_OPTS_INV_MASK)
1952ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó		printf("Unknown invflags: 0x%X ",
1962ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó		       optinfo->invflags & ~IP6T_OPTS_INV_MASK);
1972ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó}
1982ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó
1992ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó/* Saves the union ip6t_matchinfo in parsable form to stdout. */
200997045f536026c0d643bf884da5ff5de2605197fJan Engelhardtstatic void hbh_save(const void *ip, const struct xt_entry_match *match)
2012ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó{
2022ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó	const struct ip6t_opts *optinfo = (struct ip6t_opts *)match->data;
2032ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó
2042ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó	if (optinfo->flags & IP6T_OPTS_LEN) {
205e2f588ab7481760f069cd30d3146569f074721aaJan Engelhardt		printf("--hbh-len %s%u ",
2062ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó			(optinfo->invflags & IP6T_OPTS_INV_LEN) ? "! " : "",
2072ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó			optinfo->hdrlen);
2082ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó	}
2092ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó
210e2f588ab7481760f069cd30d3146569f074721aaJan Engelhardt	if (optinfo->flags & IP6T_OPTS_OPTS)
211e2f588ab7481760f069cd30d3146569f074721aaJan Engelhardt		printf("--hbh-opts ");
212ae31bb6bac68f800a1e4b30cf2548dacaaf76102Fabrice MARIE	print_options(optinfo->optsnr, (u_int16_t *)optinfo->opts);
213e2f588ab7481760f069cd30d3146569f074721aaJan Engelhardt	if (optinfo->flags & IP6T_OPTS_NSTRICT)
214e2f588ab7481760f069cd30d3146569f074721aaJan Engelhardt		printf("--hbh-not-strict ");
2152ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó}
2162ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó
2178b7c64d6ba156a99008fcd810cba874c73294333Jan Engelhardtstatic struct xtables_match hbh_mt6_reg = {
21802aa73312d6078b6de26757d5a558e0085ec20b5Harald Welte	.name 		= "hbh",
2198b7c64d6ba156a99008fcd810cba874c73294333Jan Engelhardt	.version	= XTABLES_VERSION,
2208b7c64d6ba156a99008fcd810cba874c73294333Jan Engelhardt	.family		= PF_INET6,
2218b7c64d6ba156a99008fcd810cba874c73294333Jan Engelhardt	.size		= XT_ALIGN(sizeof(struct ip6t_opts)),
2228b7c64d6ba156a99008fcd810cba874c73294333Jan Engelhardt	.userspacesize	= XT_ALIGN(sizeof(struct ip6t_opts)),
223997045f536026c0d643bf884da5ff5de2605197fJan Engelhardt	.help		= hbh_help,
224997045f536026c0d643bf884da5ff5de2605197fJan Engelhardt	.init		= hbh_init,
225997045f536026c0d643bf884da5ff5de2605197fJan Engelhardt	.parse		= hbh_parse,
226997045f536026c0d643bf884da5ff5de2605197fJan Engelhardt	.print		= hbh_print,
227997045f536026c0d643bf884da5ff5de2605197fJan Engelhardt	.save		= hbh_save,
228997045f536026c0d643bf884da5ff5de2605197fJan Engelhardt	.extra_opts	= hbh_opts,
2292ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó};
2302ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó
2312ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabóvoid
2322ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó_init(void)
2332ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó{
2348b7c64d6ba156a99008fcd810cba874c73294333Jan Engelhardt	xtables_register_match(&hbh_mt6_reg);
2352ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó}
236