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_parse(struct xt_option_call *cb) 32 { 33 struct ip6t_ah *ahinfo = cb->data; 34 35 xtables_option_parse(cb); 36 switch (cb->entry->id) { 37 case O_AHSPI: 38 if (cb->nvals == 1) 39 ahinfo->spis[1] = ahinfo->spis[0]; 40 if (cb->invert) 41 ahinfo->invflags |= IP6T_AH_INV_SPI; 42 break; 43 case O_AHLEN: 44 if (cb->invert) 45 ahinfo->invflags |= IP6T_AH_INV_LEN; 46 break; 47 case O_AHRES: 48 ahinfo->hdrres = 1; 49 break; 50 } 51 } 52 53 static void 54 print_spis(const char *name, uint32_t min, uint32_t max, 55 int invert) 56 { 57 const char *inv = invert ? "!" : ""; 58 59 if (min != 0 || max != 0xFFFFFFFF || invert) { 60 if (min == max) 61 printf("%s:%s%u", name, inv, min); 62 else 63 printf("%ss:%s%u:%u", name, inv, min, max); 64 } 65 } 66 67 static void 68 print_len(const char *name, uint32_t len, int invert) 69 { 70 const char *inv = invert ? "!" : ""; 71 72 if (len != 0 || invert) 73 printf("%s:%s%u", name, inv, len); 74 } 75 76 static void ah_print(const void *ip, const struct xt_entry_match *match, 77 int numeric) 78 { 79 const struct ip6t_ah *ah = (struct ip6t_ah *)match->data; 80 81 printf(" ah "); 82 print_spis("spi", ah->spis[0], ah->spis[1], 83 ah->invflags & IP6T_AH_INV_SPI); 84 print_len("length", ah->hdrlen, 85 ah->invflags & IP6T_AH_INV_LEN); 86 87 if (ah->hdrres) 88 printf(" reserved"); 89 90 if (ah->invflags & ~IP6T_AH_INV_MASK) 91 printf(" Unknown invflags: 0x%X", 92 ah->invflags & ~IP6T_AH_INV_MASK); 93 } 94 95 static void ah_save(const void *ip, const struct xt_entry_match *match) 96 { 97 const struct ip6t_ah *ahinfo = (struct ip6t_ah *)match->data; 98 99 if (!(ahinfo->spis[0] == 0 100 && ahinfo->spis[1] == 0xFFFFFFFF)) { 101 printf("%s --ahspi ", 102 (ahinfo->invflags & IP6T_AH_INV_SPI) ? " !" : ""); 103 if (ahinfo->spis[0] 104 != ahinfo->spis[1]) 105 printf("%u:%u", 106 ahinfo->spis[0], 107 ahinfo->spis[1]); 108 else 109 printf("%u", 110 ahinfo->spis[0]); 111 } 112 113 if (ahinfo->hdrlen != 0 || (ahinfo->invflags & IP6T_AH_INV_LEN) ) { 114 printf("%s --ahlen %u", 115 (ahinfo->invflags & IP6T_AH_INV_LEN) ? " !" : "", 116 ahinfo->hdrlen); 117 } 118 119 if (ahinfo->hdrres != 0 ) 120 printf(" --ahres"); 121 } 122 123 static struct xtables_match ah_mt6_reg = { 124 .name = "ah", 125 .version = XTABLES_VERSION, 126 .family = NFPROTO_IPV6, 127 .size = XT_ALIGN(sizeof(struct ip6t_ah)), 128 .userspacesize = XT_ALIGN(sizeof(struct ip6t_ah)), 129 .help = ah_help, 130 .print = ah_print, 131 .save = ah_save, 132 .x6_parse = ah_parse, 133 .x6_options = ah_opts, 134 }; 135 136 void 137 _init(void) 138 { 139 xtables_register_match(&ah_mt6_reg); 140 } 141