libxt_esp.c revision 661f112072bc13a1625c4eb5983695e122ea97da
1/* Shared library add-on to iptables to add ESP 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 <xtables.h> 9#include <linux/netfilter/xt_esp.h> 10 11/* Function which prints out usage message. */ 12static void 13help(void) 14{ 15 printf( 16"ESP v%s options:\n" 17" --espspi [!] spi[:spi]\n" 18" match spi (range)\n", 19IPTABLES_VERSION); 20} 21 22static const struct option opts[] = { 23 { "espspi", 1, 0, '1' }, 24 {0} 25}; 26 27static u_int32_t 28parse_esp_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 "ESP 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 "ESP error parsing spi `%s'", spistr); 46 } 47 return (u_int32_t) spi; 48} 49 50static void 51parse_esp_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_esp_spi(buffer); 59 else { 60 *cp = '\0'; 61 cp++; 62 63 spis[0] = buffer[0] ? parse_esp_spi(buffer) : 0; 64 spis[1] = cp[0] ? parse_esp_spi(cp) : 0xFFFFFFFF; 65 if (spis[0] > spis[1]) 66 exit_error(PARAMETER_PROBLEM, 67 "Invalid ESP spi range: %s", spistring); 68 } 69 free(buffer); 70} 71 72/* Initialize the match. */ 73static void 74init(struct xt_entry_match *m, unsigned int *nfcache) 75{ 76 struct xt_esp *espinfo = (struct xt_esp *)m->data; 77 78 espinfo->spis[1] = 0xFFFFFFFF; 79} 80 81#define ESP_SPI 0x01 82 83/* Function which parses command options; returns true if it 84 ate an option */ 85static int 86parse(int c, char **argv, int invert, unsigned int *flags, 87 const void *entry, 88 unsigned int *nfcache, 89 struct xt_entry_match **match) 90{ 91 struct xt_esp *espinfo = (struct xt_esp *)(*match)->data; 92 93 switch (c) { 94 case '1': 95 if (*flags & ESP_SPI) 96 exit_error(PARAMETER_PROBLEM, 97 "Only one `--espspi' allowed"); 98 check_inverse(optarg, &invert, &optind, 0); 99 parse_esp_spis(argv[optind-1], espinfo->spis); 100 if (invert) 101 espinfo->invflags |= XT_ESP_INV_SPI; 102 *flags |= ESP_SPI; 103 break; 104 default: 105 return 0; 106 } 107 108 return 1; 109} 110 111/* Final check; we don't care. */ 112static void 113final_check(unsigned int flags) 114{ 115} 116 117static void 118print_spis(const char *name, u_int32_t min, u_int32_t max, 119 int invert) 120{ 121 const char *inv = invert ? "!" : ""; 122 123 if (min != 0 || max != 0xFFFFFFFF || invert) { 124 if (min == max) 125 printf("%s:%s%u ", name, inv, min); 126 else 127 printf("%ss:%s%u:%u ", name, inv, min, max); 128 } 129} 130 131/* Prints out the union ipt_matchinfo. */ 132static void 133print(const void *ip, 134 const struct xt_entry_match *match, int numeric) 135{ 136 const struct xt_esp *esp = (struct xt_esp *)match->data; 137 138 printf("esp "); 139 print_spis("spi", esp->spis[0], esp->spis[1], 140 esp->invflags & XT_ESP_INV_SPI); 141 if (esp->invflags & ~XT_ESP_INV_MASK) 142 printf("Unknown invflags: 0x%X ", 143 esp->invflags & ~XT_ESP_INV_MASK); 144} 145 146/* Saves the union ipt_matchinfo in parsable form to stdout. */ 147static void save(const void *ip, const struct xt_entry_match *match) 148{ 149 const struct xt_esp *espinfo = (struct xt_esp *)match->data; 150 151 if (!(espinfo->spis[0] == 0 152 && espinfo->spis[1] == 0xFFFFFFFF)) { 153 printf("--espspi %s", 154 (espinfo->invflags & XT_ESP_INV_SPI) ? "! " : ""); 155 if (espinfo->spis[0] 156 != espinfo->spis[1]) 157 printf("%u:%u ", 158 espinfo->spis[0], 159 espinfo->spis[1]); 160 else 161 printf("%u ", 162 espinfo->spis[0]); 163 } 164 165} 166 167static struct xtables_match esp = { 168 .family = AF_INET, 169 .name = "esp", 170 .version = IPTABLES_VERSION, 171 .size = XT_ALIGN(sizeof(struct xt_esp)), 172 .userspacesize = XT_ALIGN(sizeof(struct xt_esp)), 173 .help = &help, 174 .init = &init, 175 .parse = &parse, 176 .final_check = &final_check, 177 .print = &print, 178 .save = &save, 179 .extra_opts = opts 180}; 181 182static struct xtables_match esp6 = { 183 .family = AF_INET6, 184 .name = "esp", 185 .version = IPTABLES_VERSION, 186 .size = XT_ALIGN(sizeof(struct xt_esp)), 187 .userspacesize = XT_ALIGN(sizeof(struct xt_esp)), 188 .help = &help, 189 .init = &init, 190 .parse = &parse, 191 .final_check = &final_check, 192 .print = &print, 193 .save = &save, 194 .extra_opts = opts 195}; 196 197void 198_init(void) 199{ 200 xtables_register_match(&esp); 201 xtables_register_match(&esp6); 202} 203