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