libip6t_ah.c revision 32b8e61e4e5bd405d9ad07bf9468498dfbb19f9e
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 filed, 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 u_int32_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, u_int32_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 default: 114 return 0; 115 } 116 117 return 1; 118} 119 120static void 121print_spis(const char *name, u_int32_t min, u_int32_t max, 122 int invert) 123{ 124 const char *inv = invert ? "!" : ""; 125 126 if (min != 0 || max != 0xFFFFFFFF || invert) { 127 if (min == max) 128 printf("%s:%s%u ", name, inv, min); 129 else 130 printf("%ss:%s%u:%u ", name, inv, min, max); 131 } 132} 133 134static void 135print_len(const char *name, u_int32_t len, int invert) 136{ 137 const char *inv = invert ? "!" : ""; 138 139 if (len != 0 || invert) 140 printf("%s:%s%u ", name, inv, len); 141} 142 143static void ah_print(const void *ip, const struct xt_entry_match *match, 144 int numeric) 145{ 146 const struct ip6t_ah *ah = (struct ip6t_ah *)match->data; 147 148 printf("ah "); 149 print_spis("spi", ah->spis[0], ah->spis[1], 150 ah->invflags & IP6T_AH_INV_SPI); 151 print_len("length", ah->hdrlen, 152 ah->invflags & IP6T_AH_INV_LEN); 153 154 if (ah->hdrres) 155 printf("reserved "); 156 157 if (ah->invflags & ~IP6T_AH_INV_MASK) 158 printf("Unknown invflags: 0x%X ", 159 ah->invflags & ~IP6T_AH_INV_MASK); 160} 161 162static void ah_save(const void *ip, const struct xt_entry_match *match) 163{ 164 const struct ip6t_ah *ahinfo = (struct ip6t_ah *)match->data; 165 166 if (!(ahinfo->spis[0] == 0 167 && ahinfo->spis[1] == 0xFFFFFFFF)) { 168 printf("%s--ahspi ", 169 (ahinfo->invflags & IP6T_AH_INV_SPI) ? "! " : ""); 170 if (ahinfo->spis[0] 171 != ahinfo->spis[1]) 172 printf("%u:%u ", 173 ahinfo->spis[0], 174 ahinfo->spis[1]); 175 else 176 printf("%u ", 177 ahinfo->spis[0]); 178 } 179 180 if (ahinfo->hdrlen != 0 || (ahinfo->invflags & IP6T_AH_INV_LEN) ) { 181 printf("%s--ahlen %u ", 182 (ahinfo->invflags & IP6T_AH_INV_LEN) ? "! " : "", 183 ahinfo->hdrlen); 184 } 185 186 if (ahinfo->hdrres != 0 ) 187 printf("--ahres "); 188} 189 190static struct xtables_match ah_mt6_reg = { 191 .name = "ah", 192 .version = XTABLES_VERSION, 193 .family = NFPROTO_IPV6, 194 .size = XT_ALIGN(sizeof(struct ip6t_ah)), 195 .userspacesize = XT_ALIGN(sizeof(struct ip6t_ah)), 196 .help = ah_help, 197 .init = ah_init, 198 .parse = ah_parse, 199 .print = ah_print, 200 .save = ah_save, 201 .extra_opts = ah_opts, 202}; 203 204void 205_init(void) 206{ 207 xtables_register_match(&ah_mt6_reg); 208} 209