libip6t_ah.c revision 12a18d6043092bd2574b2bced635259b16317e57
1/* Shared library add-on to ip6tables to add AH support. */ 2#include <stdbool.h> 3#include <stdio.h> 4#include <netdb.h> 5#include <string.h> 6#include <stdlib.h> 7#include <getopt.h> 8#include <errno.h> 9#include <xtables.h> 10#include <linux/netfilter_ipv6/ip6t_ah.h> 11 12static void ah_help(void) 13{ 14 printf( 15"ah match options:\n" 16"[!] --ahspi spi[:spi] match spi (range)\n" 17"[!] --ahlen length total length of this header\n" 18" --ahres check the reserved field too\n"); 19} 20 21static const struct option ah_opts[] = { 22 {.name = "ahspi", .has_arg = true, .val = '1'}, 23 {.name = "ahlen", .has_arg = true, .val = '2'}, 24 {.name = "ahres", .has_arg = false, .val = '3'}, 25 XT_GETOPT_TABLEEND, 26}; 27 28static uint32_t 29parse_ah_spi(const char *spistr, const char *typestr) 30{ 31 unsigned long int spi; 32 char* ep; 33 34 spi = strtoul(spistr, &ep, 0); 35 36 if ( spistr == ep ) 37 xtables_error(PARAMETER_PROBLEM, 38 "AH no valid digits in %s `%s'", typestr, spistr); 39 40 if ( spi == ULONG_MAX && errno == ERANGE ) 41 xtables_error(PARAMETER_PROBLEM, 42 "%s `%s' specified too big: would overflow", 43 typestr, spistr); 44 45 if ( *spistr != '\0' && *ep != '\0' ) 46 xtables_error(PARAMETER_PROBLEM, 47 "AH error parsing %s `%s'", typestr, spistr); 48 49 return spi; 50} 51 52static void 53parse_ah_spis(const char *spistring, uint32_t *spis) 54{ 55 char *buffer; 56 char *cp; 57 58 buffer = strdup(spistring); 59 if ((cp = strchr(buffer, ':')) == NULL) 60 spis[0] = spis[1] = parse_ah_spi(buffer, "spi"); 61 else { 62 *cp = '\0'; 63 cp++; 64 65 spis[0] = buffer[0] ? parse_ah_spi(buffer, "spi") : 0; 66 spis[1] = cp[0] ? parse_ah_spi(cp, "spi") : 0xFFFFFFFF; 67 } 68 free(buffer); 69} 70 71static void ah_init(struct xt_entry_match *m) 72{ 73 struct ip6t_ah *ahinfo = (struct ip6t_ah *)m->data; 74 75 ahinfo->spis[1] = 0xFFFFFFFF; 76 ahinfo->hdrlen = 0; 77 ahinfo->hdrres = 0; 78} 79 80static int ah_parse(int c, char **argv, int invert, unsigned int *flags, 81 const void *entry, struct xt_entry_match **match) 82{ 83 struct ip6t_ah *ahinfo = (struct ip6t_ah *)(*match)->data; 84 85 switch (c) { 86 case '1': 87 if (*flags & IP6T_AH_SPI) 88 xtables_error(PARAMETER_PROBLEM, 89 "Only one `--ahspi' allowed"); 90 xtables_check_inverse(optarg, &invert, &optind, 0, argv); 91 parse_ah_spis(optarg, ahinfo->spis); 92 if (invert) 93 ahinfo->invflags |= IP6T_AH_INV_SPI; 94 *flags |= IP6T_AH_SPI; 95 break; 96 case '2': 97 if (*flags & IP6T_AH_LEN) 98 xtables_error(PARAMETER_PROBLEM, 99 "Only one `--ahlen' allowed"); 100 xtables_check_inverse(optarg, &invert, &optind, 0, argv); 101 ahinfo->hdrlen = parse_ah_spi(optarg, "length"); 102 if (invert) 103 ahinfo->invflags |= IP6T_AH_INV_LEN; 104 *flags |= IP6T_AH_LEN; 105 break; 106 case '3': 107 if (*flags & IP6T_AH_RES) 108 xtables_error(PARAMETER_PROBLEM, 109 "Only one `--ahres' allowed"); 110 ahinfo->hdrres = 1; 111 *flags |= IP6T_AH_RES; 112 break; 113 } 114 115 return 1; 116} 117 118static void 119print_spis(const char *name, uint32_t min, uint32_t max, 120 int invert) 121{ 122 const char *inv = invert ? "!" : ""; 123 124 if (min != 0 || max != 0xFFFFFFFF || invert) { 125 if (min == max) 126 printf("%s:%s%u", name, inv, min); 127 else 128 printf("%ss:%s%u:%u", name, inv, min, max); 129 } 130} 131 132static void 133print_len(const char *name, uint32_t len, int invert) 134{ 135 const char *inv = invert ? "!" : ""; 136 137 if (len != 0 || invert) 138 printf("%s:%s%u", name, inv, len); 139} 140 141static void ah_print(const void *ip, const struct xt_entry_match *match, 142 int numeric) 143{ 144 const struct ip6t_ah *ah = (struct ip6t_ah *)match->data; 145 146 printf(" ah "); 147 print_spis("spi", ah->spis[0], ah->spis[1], 148 ah->invflags & IP6T_AH_INV_SPI); 149 print_len("length", ah->hdrlen, 150 ah->invflags & IP6T_AH_INV_LEN); 151 152 if (ah->hdrres) 153 printf(" reserved"); 154 155 if (ah->invflags & ~IP6T_AH_INV_MASK) 156 printf(" Unknown invflags: 0x%X", 157 ah->invflags & ~IP6T_AH_INV_MASK); 158} 159 160static void ah_save(const void *ip, const struct xt_entry_match *match) 161{ 162 const struct ip6t_ah *ahinfo = (struct ip6t_ah *)match->data; 163 164 if (!(ahinfo->spis[0] == 0 165 && ahinfo->spis[1] == 0xFFFFFFFF)) { 166 printf("%s --ahspi ", 167 (ahinfo->invflags & IP6T_AH_INV_SPI) ? " !" : ""); 168 if (ahinfo->spis[0] 169 != ahinfo->spis[1]) 170 printf("%u:%u", 171 ahinfo->spis[0], 172 ahinfo->spis[1]); 173 else 174 printf("%u", 175 ahinfo->spis[0]); 176 } 177 178 if (ahinfo->hdrlen != 0 || (ahinfo->invflags & IP6T_AH_INV_LEN) ) { 179 printf("%s --ahlen %u", 180 (ahinfo->invflags & IP6T_AH_INV_LEN) ? " !" : "", 181 ahinfo->hdrlen); 182 } 183 184 if (ahinfo->hdrres != 0 ) 185 printf(" --ahres"); 186} 187 188static struct xtables_match ah_mt6_reg = { 189 .name = "ah", 190 .version = XTABLES_VERSION, 191 .family = NFPROTO_IPV6, 192 .size = XT_ALIGN(sizeof(struct ip6t_ah)), 193 .userspacesize = XT_ALIGN(sizeof(struct ip6t_ah)), 194 .help = ah_help, 195 .init = ah_init, 196 .parse = ah_parse, 197 .print = ah_print, 198 .save = ah_save, 199 .extra_opts = ah_opts, 200}; 201 202void 203_init(void) 204{ 205 xtables_register_match(&ah_mt6_reg); 206} 207