1/* Shared library add-on to iptables 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 <iptables.h> 9#include <linux/netfilter_ipv4/ipt_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]\n" 18" match spi (range)\n", 19IPTABLES_VERSION); 20} 21 22static struct option opts[] = { 23 { "ahspi", 1, 0, '1' }, 24 {0} 25}; 26 27static u_int32_t 28parse_ah_spi(const char *spistr) 29{ 30 unsigned long int spi; 31 char* ep; 32 33 spi = strtoul(spistr,&ep,0) ; 34 35 if ( spistr == ep ) { 36 exit_error(PARAMETER_PROBLEM, 37 "AH no valid digits in spi `%s'", spistr); 38 } 39 if ( spi == ULONG_MAX && errno == ERANGE ) { 40 exit_error(PARAMETER_PROBLEM, 41 "spi `%s' specified too big: would overflow", spistr); 42 } 43 if ( *spistr != '\0' && *ep != '\0' ) { 44 exit_error(PARAMETER_PROBLEM, 45 "AH error parsing spi `%s'", spistr); 46 } 47 return (u_int32_t) spi; 48} 49 50static void 51parse_ah_spis(const char *spistring, u_int32_t *spis) 52{ 53 char *buffer; 54 char *cp; 55 56 buffer = strdup(spistring); 57 if ((cp = strchr(buffer, ':')) == NULL) 58 spis[0] = spis[1] = parse_ah_spi(buffer); 59 else { 60 *cp = '\0'; 61 cp++; 62 63 spis[0] = buffer[0] ? parse_ah_spi(buffer) : 0; 64 spis[1] = cp[0] ? parse_ah_spi(cp) : 0xFFFFFFFF; 65 } 66 free(buffer); 67} 68 69/* Initialize the match. */ 70static void 71init(struct ipt_entry_match *m, unsigned int *nfcache) 72{ 73 struct ipt_ah *ahinfo = (struct ipt_ah *)m->data; 74 75 ahinfo->spis[1] = 0xFFFFFFFF; 76} 77 78#define AH_SPI 0x01 79 80/* Function which parses command options; returns true if it 81 ate an option */ 82static int 83parse(int c, char **argv, int invert, unsigned int *flags, 84 const struct ipt_entry *entry, 85 unsigned int *nfcache, 86 struct ipt_entry_match **match) 87{ 88 struct ipt_ah *ahinfo = (struct ipt_ah *)(*match)->data; 89 90 switch (c) { 91 case '1': 92 if (*flags & AH_SPI) 93 exit_error(PARAMETER_PROBLEM, 94 "Only one `--ahspi' allowed"); 95 check_inverse(optarg, &invert, &optind, 0); 96 parse_ah_spis(argv[optind-1], ahinfo->spis); 97 if (invert) 98 ahinfo->invflags |= IPT_AH_INV_SPI; 99 *flags |= AH_SPI; 100 break; 101 default: 102 return 0; 103 } 104 105 return 1; 106} 107 108/* Final check; we don't care. */ 109static void 110final_check(unsigned int flags) 111{ 112} 113 114static void 115print_spis(const char *name, u_int32_t min, u_int32_t max, 116 int invert) 117{ 118 const char *inv = invert ? "!" : ""; 119 120 if (min != 0 || max != 0xFFFFFFFF || invert) { 121 printf("%s", name); 122 if (min == max) { 123 printf(":%s", inv); 124 printf("%u", min); 125 } else { 126 printf("s:%s", inv); 127 printf("%u",min); 128 printf(":"); 129 printf("%u",max); 130 } 131 printf(" "); 132 } 133} 134 135/* Prints out the union ipt_matchinfo. */ 136static void 137print(const struct ipt_ip *ip, 138 const struct ipt_entry_match *match, int numeric) 139{ 140 const struct ipt_ah *ah = (struct ipt_ah *)match->data; 141 142 printf("ah "); 143 print_spis("spi", ah->spis[0], ah->spis[1], 144 ah->invflags & IPT_AH_INV_SPI); 145 if (ah->invflags & ~IPT_AH_INV_MASK) 146 printf("Unknown invflags: 0x%X ", 147 ah->invflags & ~IPT_AH_INV_MASK); 148} 149 150/* Saves the union ipt_matchinfo in parsable form to stdout. */ 151static void save(const struct ipt_ip *ip, const struct ipt_entry_match *match) 152{ 153 const struct ipt_ah *ahinfo = (struct ipt_ah *)match->data; 154 155 if (!(ahinfo->spis[0] == 0 156 && ahinfo->spis[1] == 0xFFFFFFFF)) { 157 printf("--ahspi %s", 158 (ahinfo->invflags & IPT_AH_INV_SPI) ? "! " : ""); 159 if (ahinfo->spis[0] 160 != ahinfo->spis[1]) 161 printf("%u:%u ", 162 ahinfo->spis[0], 163 ahinfo->spis[1]); 164 else 165 printf("%u ", 166 ahinfo->spis[0]); 167 } 168 169} 170 171static struct iptables_match ah = { 172 .next = NULL, 173 .name = "ah", 174 .version = IPTABLES_VERSION, 175 .size = IPT_ALIGN(sizeof(struct ipt_ah)), 176 .userspacesize = IPT_ALIGN(sizeof(struct ipt_ah)), 177 .help = &help, 178 .init = &init, 179 .parse = &parse, 180 .final_check = &final_check, 181 .print = &print, 182 .save = &save, 183 .extra_opts = opts 184}; 185 186void 187_init(void) 188{ 189 register_match(&ah); 190} 191