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