libxt_esp.c revision d09b6d591ca7d7d7575cb6aa20384c9830f777ab
11d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert/* Shared library add-on to iptables to add ESP support. */ 21d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#include <stdbool.h> 31d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#include <stdio.h> 41d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#include <netdb.h> 51d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#include <string.h> 61d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#include <stdlib.h> 71d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#include <getopt.h> 81d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#include <errno.h> 91d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#include <limits.h> 101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#include <xtables.h> 121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#include <linux/netfilter/xt_esp.h> 131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertstatic void esp_help(void) 151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert{ 161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert printf( 171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert"esp match options:\n" 181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert"[!] --espspi spi[:spi]\n" 191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert" match spi (range)\n"); 201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert} 211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertstatic const struct option esp_opts[] = { 231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert {.name = "espspi", .has_arg = true, .val = '1'}, 241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert XT_GETOPT_TABLEEND, 251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert}; 261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertstatic uint32_t 281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertparse_esp_spi(const char *spistr) 291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert{ 301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert unsigned long int spi; 311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert char* ep; 321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert spi = strtoul(spistr,&ep,0) ; 341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert if ( spistr == ep ) { 361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert xtables_error(PARAMETER_PROBLEM, 371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert "ESP no valid digits in spi `%s'", spistr); 381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert if ( spi == ULONG_MAX && errno == ERANGE ) { 401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert xtables_error(PARAMETER_PROBLEM, 411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert "spi `%s' specified too big: would overflow", spistr); 421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert if ( *spistr != '\0' && *ep != '\0' ) { 441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert xtables_error(PARAMETER_PROBLEM, 451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert "ESP error parsing spi `%s'", spistr); 461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return spi; 481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert} 49 50static void 51parse_esp_spis(const char *spistring, uint32_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 xtables_error(PARAMETER_PROBLEM, 67 "Invalid ESP spi range: %s", spistring); 68 } 69 free(buffer); 70} 71 72static void esp_init(struct xt_entry_match *m) 73{ 74 struct xt_esp *espinfo = (struct xt_esp *)m->data; 75 76 espinfo->spis[1] = 0xFFFFFFFF; 77} 78 79#define ESP_SPI 0x01 80 81static int 82esp_parse(int c, char **argv, int invert, unsigned int *flags, 83 const void *entry, struct xt_entry_match **match) 84{ 85 struct xt_esp *espinfo = (struct xt_esp *)(*match)->data; 86 87 switch (c) { 88 case '1': 89 if (*flags & ESP_SPI) 90 xtables_error(PARAMETER_PROBLEM, 91 "Only one `--espspi' allowed"); 92 xtables_check_inverse(optarg, &invert, &optind, 0, argv); 93 parse_esp_spis(optarg, espinfo->spis); 94 if (invert) 95 espinfo->invflags |= XT_ESP_INV_SPI; 96 *flags |= ESP_SPI; 97 break; 98 } 99 100 return 1; 101} 102 103static void 104print_spis(const char *name, uint32_t min, uint32_t max, 105 int invert) 106{ 107 const char *inv = invert ? "!" : ""; 108 109 if (min != 0 || max != 0xFFFFFFFF || invert) { 110 if (min == max) 111 printf("%s:%s%u ", name, inv, min); 112 else 113 printf("%ss:%s%u:%u ", name, inv, min, max); 114 } 115} 116 117static void 118esp_print(const void *ip, const struct xt_entry_match *match, int numeric) 119{ 120 const struct xt_esp *esp = (struct xt_esp *)match->data; 121 122 printf("esp "); 123 print_spis("spi", esp->spis[0], esp->spis[1], 124 esp->invflags & XT_ESP_INV_SPI); 125 if (esp->invflags & ~XT_ESP_INV_MASK) 126 printf("Unknown invflags: 0x%X ", 127 esp->invflags & ~XT_ESP_INV_MASK); 128} 129 130static void esp_save(const void *ip, const struct xt_entry_match *match) 131{ 132 const struct xt_esp *espinfo = (struct xt_esp *)match->data; 133 134 if (!(espinfo->spis[0] == 0 135 && espinfo->spis[1] == 0xFFFFFFFF)) { 136 printf("%s--espspi ", 137 (espinfo->invflags & XT_ESP_INV_SPI) ? "! " : ""); 138 if (espinfo->spis[0] 139 != espinfo->spis[1]) 140 printf("%u:%u ", 141 espinfo->spis[0], 142 espinfo->spis[1]); 143 else 144 printf("%u ", 145 espinfo->spis[0]); 146 } 147 148} 149 150static struct xtables_match esp_match = { 151 .family = NFPROTO_UNSPEC, 152 .name = "esp", 153 .version = XTABLES_VERSION, 154 .size = XT_ALIGN(sizeof(struct xt_esp)), 155 .userspacesize = XT_ALIGN(sizeof(struct xt_esp)), 156 .help = esp_help, 157 .init = esp_init, 158 .parse = esp_parse, 159 .print = esp_print, 160 .save = esp_save, 161 .extra_opts = esp_opts, 162}; 163 164void 165_init(void) 166{ 167 xtables_register_match(&esp_match); 168} 169