libip6t_ah.c revision 9ee386a1b6d7704b259460152c959ab0e79e02aa
1d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte/* Shared library add-on to ip6tables to add AH support. */ 2d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte#include <stdio.h> 3d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte#include <netdb.h> 4d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte#include <string.h> 5d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte#include <stdlib.h> 6d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte#include <getopt.h> 7d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte#include <errno.h> 8d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte#include <ip6tables.h> 9d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte#include <linux/netfilter_ipv6/ip6t_ah.h> 10d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte 11d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte/* Function which prints out usage message. */ 12997045f536026c0d643bf884da5ff5de2605197fJan Engelhardtstatic void ah_help(void) 13d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte{ 14d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte printf( 15d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte"AH v%s options:\n" 16d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte" --ahspi [!] spi[:spi] match spi (range)\n" 17d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte" --ahlen [!] length total length of this header\n" 18d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte" --ahres check the reserved filed, too\n", 1980fe35d6339b53a12ddaec41885613e4e37ed031Harald WelteIPTABLES_VERSION); 20d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte} 21d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte 22997045f536026c0d643bf884da5ff5de2605197fJan Engelhardtstatic const struct option ah_opts[] = { 23500f483fff529dcd88ec96b9d5054be6cd6363a0Patrick McHardy { .name = "ahspi", .has_arg = 1, .val = '1' }, 24500f483fff529dcd88ec96b9d5054be6cd6363a0Patrick McHardy { .name = "ahlen", .has_arg = 1, .val = '2' }, 25500f483fff529dcd88ec96b9d5054be6cd6363a0Patrick McHardy { .name = "ahres", .has_arg = 0, .val = '3' }, 269ee386a1b6d7704b259460152c959ab0e79e02aaMax Kellermann { .name = NULL } 27d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte}; 28d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte 29d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Weltestatic u_int32_t 30d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welteparse_ah_spi(const char *spistr, const char *typestr) 31d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte{ 32d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte unsigned long int spi; 33d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte char* ep; 34d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte 35703575d4b45d15996ee2ca0b13d958a22cd78f4fStephane Ouellette spi = strtoul(spistr, &ep, 0); 36d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte 37703575d4b45d15996ee2ca0b13d958a22cd78f4fStephane Ouellette if ( spistr == ep ) 38d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte exit_error(PARAMETER_PROBLEM, 39d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte "AH no valid digits in %s `%s'", typestr, spistr); 40703575d4b45d15996ee2ca0b13d958a22cd78f4fStephane Ouellette 41703575d4b45d15996ee2ca0b13d958a22cd78f4fStephane Ouellette if ( spi == ULONG_MAX && errno == ERANGE ) 42d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte exit_error(PARAMETER_PROBLEM, 43d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte "%s `%s' specified too big: would overflow", 44d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte typestr, spistr); 45703575d4b45d15996ee2ca0b13d958a22cd78f4fStephane Ouellette 46703575d4b45d15996ee2ca0b13d958a22cd78f4fStephane Ouellette if ( *spistr != '\0' && *ep != '\0' ) 47d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte exit_error(PARAMETER_PROBLEM, 48d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte "AH error parsing %s `%s'", typestr, spistr); 49703575d4b45d15996ee2ca0b13d958a22cd78f4fStephane Ouellette 50d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte return (u_int32_t) spi; 51d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte} 52d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte 53d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Weltestatic void 54d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welteparse_ah_spis(const char *spistring, u_int32_t *spis) 55d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte{ 56d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte char *buffer; 57d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte char *cp; 58d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte 59d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte buffer = strdup(spistring); 60d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte if ((cp = strchr(buffer, ':')) == NULL) 61703575d4b45d15996ee2ca0b13d958a22cd78f4fStephane Ouellette spis[0] = spis[1] = parse_ah_spi(buffer, "spi"); 62d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte else { 63d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte *cp = '\0'; 64d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte cp++; 65d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte 66703575d4b45d15996ee2ca0b13d958a22cd78f4fStephane Ouellette spis[0] = buffer[0] ? parse_ah_spi(buffer, "spi") : 0; 67703575d4b45d15996ee2ca0b13d958a22cd78f4fStephane Ouellette spis[1] = cp[0] ? parse_ah_spi(cp, "spi") : 0xFFFFFFFF; 68d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte } 69d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte free(buffer); 70d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte} 71d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte 72d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte/* Initialize the match. */ 73997045f536026c0d643bf884da5ff5de2605197fJan Engelhardtstatic void ah_init(struct xt_entry_match *m) 74d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte{ 75d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte struct ip6t_ah *ahinfo = (struct ip6t_ah *)m->data; 76d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte 77d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte ahinfo->spis[1] = 0xFFFFFFFF; 78d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte ahinfo->hdrlen = 0; 79d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte ahinfo->hdrres = 0; 80d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte} 81d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte 82d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte/* Function which parses command options; returns true if it 83d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte ate an option */ 84997045f536026c0d643bf884da5ff5de2605197fJan Engelhardtstatic int ah_parse(int c, char **argv, int invert, unsigned int *flags, 85997045f536026c0d643bf884da5ff5de2605197fJan Engelhardt const void *entry, struct xt_entry_match **match) 86d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte{ 87d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte struct ip6t_ah *ahinfo = (struct ip6t_ah *)(*match)->data; 88d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte 89d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte switch (c) { 90d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte case '1': 91d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte if (*flags & IP6T_AH_SPI) 92d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte exit_error(PARAMETER_PROBLEM, 93d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte "Only one `--ahspi' allowed"); 94d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte check_inverse(optarg, &invert, &optind, 0); 95d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte parse_ah_spis(argv[optind-1], ahinfo->spis); 96d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte if (invert) 97d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte ahinfo->invflags |= IP6T_AH_INV_SPI; 98d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte *flags |= IP6T_AH_SPI; 99d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte break; 100d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte case '2': 101d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte if (*flags & IP6T_AH_LEN) 102d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte exit_error(PARAMETER_PROBLEM, 103d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte "Only one `--ahlen' allowed"); 104d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte check_inverse(optarg, &invert, &optind, 0); 105d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte ahinfo->hdrlen = parse_ah_spi(argv[optind-1], "length"); 106d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte if (invert) 107d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte ahinfo->invflags |= IP6T_AH_INV_LEN; 108d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte *flags |= IP6T_AH_LEN; 109d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte break; 110d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte case '3': 111d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte if (*flags & IP6T_AH_RES) 112d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte exit_error(PARAMETER_PROBLEM, 113d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte "Only one `--ahres' allowed"); 114d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte ahinfo->hdrres = 1; 115d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte *flags |= IP6T_AH_RES; 116d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte break; 117d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte default: 118d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte return 0; 119d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte } 120d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte 121d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte return 1; 122d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte} 123d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte 124d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Weltestatic void 125d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welteprint_spis(const char *name, u_int32_t min, u_int32_t max, 126d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte int invert) 127d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte{ 128d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte const char *inv = invert ? "!" : ""; 129d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte 130d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte if (min != 0 || max != 0xFFFFFFFF || invert) { 131703575d4b45d15996ee2ca0b13d958a22cd78f4fStephane Ouellette if (min == max) 132703575d4b45d15996ee2ca0b13d958a22cd78f4fStephane Ouellette printf("%s:%s%u ", name, inv, min); 133703575d4b45d15996ee2ca0b13d958a22cd78f4fStephane Ouellette else 134703575d4b45d15996ee2ca0b13d958a22cd78f4fStephane Ouellette printf("%ss:%s%u:%u ", name, inv, min, max); 135d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte } 136d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte} 137d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte 138d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Weltestatic void 139d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welteprint_len(const char *name, u_int32_t len, int invert) 140d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte{ 141d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte const char *inv = invert ? "!" : ""; 142d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte 143703575d4b45d15996ee2ca0b13d958a22cd78f4fStephane Ouellette if (len != 0 || invert) 144703575d4b45d15996ee2ca0b13d958a22cd78f4fStephane Ouellette printf("%s:%s%u ", name, inv, len); 145d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte} 146d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte 147d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte/* Prints out the union ip6t_matchinfo. */ 148997045f536026c0d643bf884da5ff5de2605197fJan Engelhardtstatic void ah_print(const void *ip, const struct xt_entry_match *match, 149997045f536026c0d643bf884da5ff5de2605197fJan Engelhardt int numeric) 150d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte{ 151d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte const struct ip6t_ah *ah = (struct ip6t_ah *)match->data; 152d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte 153d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte printf("ah "); 154d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte print_spis("spi", ah->spis[0], ah->spis[1], 155d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte ah->invflags & IP6T_AH_INV_SPI); 156d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte print_len("length", ah->hdrlen, 157d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte ah->invflags & IP6T_AH_INV_LEN); 158703575d4b45d15996ee2ca0b13d958a22cd78f4fStephane Ouellette 159703575d4b45d15996ee2ca0b13d958a22cd78f4fStephane Ouellette if (ah->hdrres) 160703575d4b45d15996ee2ca0b13d958a22cd78f4fStephane Ouellette printf("reserved "); 161703575d4b45d15996ee2ca0b13d958a22cd78f4fStephane Ouellette 162d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte if (ah->invflags & ~IP6T_AH_INV_MASK) 163d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte printf("Unknown invflags: 0x%X ", 164d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte ah->invflags & ~IP6T_AH_INV_MASK); 165d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte} 166d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte 167d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte/* Saves the union ip6t_matchinfo in parsable form to stdout. */ 168997045f536026c0d643bf884da5ff5de2605197fJan Engelhardtstatic void ah_save(const void *ip, const struct xt_entry_match *match) 169d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte{ 170d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte const struct ip6t_ah *ahinfo = (struct ip6t_ah *)match->data; 171d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte 172d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte if (!(ahinfo->spis[0] == 0 173d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte && ahinfo->spis[1] == 0xFFFFFFFF)) { 174d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte printf("--ahspi %s", 175d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte (ahinfo->invflags & IP6T_AH_INV_SPI) ? "! " : ""); 176d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte if (ahinfo->spis[0] 177d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte != ahinfo->spis[1]) 178d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte printf("%u:%u ", 179d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte ahinfo->spis[0], 180d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte ahinfo->spis[1]); 181d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte else 182d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte printf("%u ", 183d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte ahinfo->spis[0]); 184d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte } 185d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte 186d8a12a841de648bd38dc52ba624d1ed1810a6333András Kis-Szabó if (ahinfo->hdrlen != 0 || (ahinfo->invflags & IP6T_AH_INV_LEN) ) { 187d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte printf("--ahlen %s%u ", 188d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte (ahinfo->invflags & IP6T_AH_INV_LEN) ? "! " : "", 189d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte ahinfo->hdrlen); 190d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte } 191d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte 192703575d4b45d15996ee2ca0b13d958a22cd78f4fStephane Ouellette if (ahinfo->hdrres != 0 ) 193d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte printf("--ahres "); 194d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte} 195d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte 196997045f536026c0d643bf884da5ff5de2605197fJan Engelhardtstatic struct ip6tables_match ah_match6 = { 197703575d4b45d15996ee2ca0b13d958a22cd78f4fStephane Ouellette .name = "ah", 198703575d4b45d15996ee2ca0b13d958a22cd78f4fStephane Ouellette .version = IPTABLES_VERSION, 199703575d4b45d15996ee2ca0b13d958a22cd78f4fStephane Ouellette .size = IP6T_ALIGN(sizeof(struct ip6t_ah)), 200703575d4b45d15996ee2ca0b13d958a22cd78f4fStephane Ouellette .userspacesize = IP6T_ALIGN(sizeof(struct ip6t_ah)), 201997045f536026c0d643bf884da5ff5de2605197fJan Engelhardt .help = ah_help, 202997045f536026c0d643bf884da5ff5de2605197fJan Engelhardt .init = ah_init, 203997045f536026c0d643bf884da5ff5de2605197fJan Engelhardt .parse = ah_parse, 204997045f536026c0d643bf884da5ff5de2605197fJan Engelhardt .print = ah_print, 205997045f536026c0d643bf884da5ff5de2605197fJan Engelhardt .save = ah_save, 206997045f536026c0d643bf884da5ff5de2605197fJan Engelhardt .extra_opts = ah_opts, 207d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte}; 208d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte 209d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Weltevoid 210d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte_init(void) 211d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte{ 212997045f536026c0d643bf884da5ff5de2605197fJan Engelhardt register_match6(&ah_match6); 213d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte} 214