Home | History | Annotate | Download | only in extensions
      1 #include <stdio.h>
      2 #include <xtables.h>
      3 #include <linux/netfilter_ipv6/ip6t_ah.h>
      4 
      5 enum {
      6 	O_AHSPI = 0,
      7 	O_AHLEN,
      8 	O_AHRES,
      9 };
     10 
     11 static void ah_help(void)
     12 {
     13 	printf(
     14 "ah match options:\n"
     15 "[!] --ahspi spi[:spi]          match spi (range)\n"
     16 "[!] --ahlen length             total length of this header\n"
     17 " --ahres                       check the reserved field too\n");
     18 }
     19 
     20 #define s struct ip6t_ah
     21 static const struct xt_option_entry ah_opts[] = {
     22 	{.name = "ahspi", .id = O_AHSPI, .type = XTTYPE_UINT32RC,
     23 	 .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, spis)},
     24 	{.name = "ahlen", .id = O_AHLEN, .type = XTTYPE_UINT32,
     25 	 .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, hdrlen)},
     26 	{.name = "ahres", .id = O_AHRES, .type = XTTYPE_NONE},
     27 	XTOPT_TABLEEND,
     28 };
     29 #undef s
     30 
     31 static void ah_init(struct xt_entry_match *m)
     32 {
     33 	struct ip6t_ah *ahinfo = (void *)m->data;
     34 
     35 	/* Defaults for when no --ahspi is used at all */
     36 	ahinfo->spis[1] = ~0U;
     37 }
     38 
     39 static void ah_parse(struct xt_option_call *cb)
     40 {
     41 	struct ip6t_ah *ahinfo = cb->data;
     42 
     43 	xtables_option_parse(cb);
     44 	switch (cb->entry->id) {
     45 	case O_AHSPI:
     46 		if (cb->nvals == 1)
     47 			ahinfo->spis[1] = ahinfo->spis[0];
     48 		if (cb->invert)
     49 			ahinfo->invflags |= IP6T_AH_INV_SPI;
     50 		break;
     51 	case O_AHLEN:
     52 		if (cb->invert)
     53 			ahinfo->invflags |= IP6T_AH_INV_LEN;
     54 		break;
     55 	case O_AHRES:
     56 		ahinfo->hdrres = 1;
     57 		break;
     58 	}
     59 }
     60 
     61 static void
     62 print_spis(const char *name, uint32_t min, uint32_t max,
     63 	    int invert)
     64 {
     65 	const char *inv = invert ? "!" : "";
     66 
     67 	if (min != 0 || max != 0xFFFFFFFF || invert) {
     68 		if (min == max)
     69 			printf("%s:%s%u", name, inv, min);
     70 		else
     71 			printf("%ss:%s%u:%u", name, inv, min, max);
     72 	}
     73 }
     74 
     75 static void
     76 print_len(const char *name, uint32_t len, int invert)
     77 {
     78 	const char *inv = invert ? "!" : "";
     79 
     80 	if (len != 0 || invert)
     81 		printf("%s:%s%u", name, inv, len);
     82 }
     83 
     84 static void ah_print(const void *ip, const struct xt_entry_match *match,
     85                      int numeric)
     86 {
     87 	const struct ip6t_ah *ah = (struct ip6t_ah *)match->data;
     88 
     89 	printf(" ah ");
     90 	print_spis("spi", ah->spis[0], ah->spis[1],
     91 		    ah->invflags & IP6T_AH_INV_SPI);
     92 	print_len("length", ah->hdrlen,
     93 		    ah->invflags & IP6T_AH_INV_LEN);
     94 
     95 	if (ah->hdrres)
     96 		printf(" reserved");
     97 
     98 	if (ah->invflags & ~IP6T_AH_INV_MASK)
     99 		printf(" Unknown invflags: 0x%X",
    100 		       ah->invflags & ~IP6T_AH_INV_MASK);
    101 }
    102 
    103 static void ah_save(const void *ip, const struct xt_entry_match *match)
    104 {
    105 	const struct ip6t_ah *ahinfo = (struct ip6t_ah *)match->data;
    106 
    107 	if (!(ahinfo->spis[0] == 0
    108 	    && ahinfo->spis[1] == 0xFFFFFFFF)) {
    109 		printf("%s --ahspi ",
    110 			(ahinfo->invflags & IP6T_AH_INV_SPI) ? " !" : "");
    111 		if (ahinfo->spis[0]
    112 		    != ahinfo->spis[1])
    113 			printf("%u:%u",
    114 			       ahinfo->spis[0],
    115 			       ahinfo->spis[1]);
    116 		else
    117 			printf("%u",
    118 			       ahinfo->spis[0]);
    119 	}
    120 
    121 	if (ahinfo->hdrlen != 0 || (ahinfo->invflags & IP6T_AH_INV_LEN) ) {
    122 		printf("%s --ahlen %u",
    123 			(ahinfo->invflags & IP6T_AH_INV_LEN) ? " !" : "",
    124 			ahinfo->hdrlen);
    125 	}
    126 
    127 	if (ahinfo->hdrres != 0 )
    128 		printf(" --ahres");
    129 }
    130 
    131 static int ah_xlate(struct xt_xlate *xl,
    132 		    const struct xt_xlate_mt_params *params)
    133 {
    134 	const struct ip6t_ah *ahinfo = (struct ip6t_ah *)params->match->data;
    135 	char *space = "";
    136 
    137 	if (!(ahinfo->spis[0] == 0 && ahinfo->spis[1] == 0xFFFFFFFF)) {
    138 		xt_xlate_add(xl, "ah spi%s ",
    139 			(ahinfo->invflags & IP6T_AH_INV_SPI) ? " !=" : "");
    140 		if (ahinfo->spis[0] != ahinfo->spis[1])
    141 			xt_xlate_add(xl, "%u-%u", ahinfo->spis[0],
    142 				     ahinfo->spis[1]);
    143 		else
    144 			xt_xlate_add(xl, "%u", ahinfo->spis[0]);
    145 		space = " ";
    146 	}
    147 
    148 	if (ahinfo->hdrlen != 0 || (ahinfo->invflags & IP6T_AH_INV_LEN)) {
    149 		xt_xlate_add(xl, "%sah hdrlength%s %u", space,
    150 			     (ahinfo->invflags & IP6T_AH_INV_LEN) ? " !=" : "",
    151 			     ahinfo->hdrlen);
    152 		space = " ";
    153 	}
    154 
    155 	if (ahinfo->hdrres != 0) {
    156 		xt_xlate_add(xl, "%sah reserved %u", space, ahinfo->hdrres);
    157 		space = " ";
    158 	}
    159 
    160 	if (!space[0]) /* plain '-m ah' */
    161 		xt_xlate_add(xl, "meta l4proto ah");
    162 
    163 	return 1;
    164 }
    165 
    166 static struct xtables_match ah_mt6_reg = {
    167 	.name          = "ah",
    168 	.version       = XTABLES_VERSION,
    169 	.family        = NFPROTO_IPV6,
    170 	.size          = XT_ALIGN(sizeof(struct ip6t_ah)),
    171 	.userspacesize = XT_ALIGN(sizeof(struct ip6t_ah)),
    172 	.help          = ah_help,
    173 	.init          = ah_init,
    174 	.print         = ah_print,
    175 	.save          = ah_save,
    176 	.x6_parse      = ah_parse,
    177 	.x6_options    = ah_opts,
    178 	.xlate	       = ah_xlate,
    179 };
    180 
    181 void
    182 _init(void)
    183 {
    184 	xtables_register_match(&ah_mt6_reg);
    185 }
    186