libip6t_ah.c revision 967279231a9ecfa99f26694a954afc535c63db1d
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( 158b7c64d6ba156a99008fcd810cba874c73294333Jan Engelhardt"ah match options:\n" 16967279231a9ecfa99f26694a954afc535c63db1dJan Engelhardt"[!] --ahspi spi[:spi] match spi (range)\n" 17967279231a9ecfa99f26694a954afc535c63db1dJan Engelhardt"[!] --ahlen length total length of this header\n" 188b7c64d6ba156a99008fcd810cba874c73294333Jan Engelhardt" --ahres check the reserved filed, too\n"); 19d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte} 20d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte 21997045f536026c0d643bf884da5ff5de2605197fJan Engelhardtstatic const struct option ah_opts[] = { 22500f483fff529dcd88ec96b9d5054be6cd6363a0Patrick McHardy { .name = "ahspi", .has_arg = 1, .val = '1' }, 23500f483fff529dcd88ec96b9d5054be6cd6363a0Patrick McHardy { .name = "ahlen", .has_arg = 1, .val = '2' }, 24500f483fff529dcd88ec96b9d5054be6cd6363a0Patrick McHardy { .name = "ahres", .has_arg = 0, .val = '3' }, 259ee386a1b6d7704b259460152c959ab0e79e02aaMax Kellermann { .name = NULL } 26d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte}; 27d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte 28d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Weltestatic u_int32_t 29d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welteparse_ah_spi(const char *spistr, const char *typestr) 30d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte{ 31d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte unsigned long int spi; 32d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte char* ep; 33d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte 34703575d4b45d15996ee2ca0b13d958a22cd78f4fStephane Ouellette spi = strtoul(spistr, &ep, 0); 35d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte 36703575d4b45d15996ee2ca0b13d958a22cd78f4fStephane Ouellette if ( spistr == ep ) 37d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte exit_error(PARAMETER_PROBLEM, 38d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte "AH no valid digits in %s `%s'", typestr, spistr); 39703575d4b45d15996ee2ca0b13d958a22cd78f4fStephane Ouellette 40703575d4b45d15996ee2ca0b13d958a22cd78f4fStephane Ouellette if ( spi == ULONG_MAX && errno == ERANGE ) 41d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte exit_error(PARAMETER_PROBLEM, 42d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte "%s `%s' specified too big: would overflow", 43d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte typestr, spistr); 44703575d4b45d15996ee2ca0b13d958a22cd78f4fStephane Ouellette 45703575d4b45d15996ee2ca0b13d958a22cd78f4fStephane Ouellette if ( *spistr != '\0' && *ep != '\0' ) 46d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte exit_error(PARAMETER_PROBLEM, 47d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte "AH error parsing %s `%s'", typestr, spistr); 48703575d4b45d15996ee2ca0b13d958a22cd78f4fStephane Ouellette 49d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte return (u_int32_t) spi; 50d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte} 51d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte 52d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Weltestatic void 53d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welteparse_ah_spis(const char *spistring, u_int32_t *spis) 54d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte{ 55d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte char *buffer; 56d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte char *cp; 57d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte 58d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte buffer = strdup(spistring); 59d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte if ((cp = strchr(buffer, ':')) == NULL) 60703575d4b45d15996ee2ca0b13d958a22cd78f4fStephane Ouellette spis[0] = spis[1] = parse_ah_spi(buffer, "spi"); 61d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte else { 62d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte *cp = '\0'; 63d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte cp++; 64d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte 65703575d4b45d15996ee2ca0b13d958a22cd78f4fStephane Ouellette spis[0] = buffer[0] ? parse_ah_spi(buffer, "spi") : 0; 66703575d4b45d15996ee2ca0b13d958a22cd78f4fStephane Ouellette spis[1] = cp[0] ? parse_ah_spi(cp, "spi") : 0xFFFFFFFF; 67d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte } 68d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte free(buffer); 69d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte} 70d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte 71d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte/* Initialize the match. */ 72997045f536026c0d643bf884da5ff5de2605197fJan Engelhardtstatic void ah_init(struct xt_entry_match *m) 73d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte{ 74d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte struct ip6t_ah *ahinfo = (struct ip6t_ah *)m->data; 75d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte 76d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte ahinfo->spis[1] = 0xFFFFFFFF; 77d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte ahinfo->hdrlen = 0; 78d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte ahinfo->hdrres = 0; 79d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte} 80d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte 81d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte/* Function which parses command options; returns true if it 82d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte ate an option */ 83997045f536026c0d643bf884da5ff5de2605197fJan Engelhardtstatic int ah_parse(int c, char **argv, int invert, unsigned int *flags, 84997045f536026c0d643bf884da5ff5de2605197fJan Engelhardt const void *entry, struct xt_entry_match **match) 85d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte{ 86d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte struct ip6t_ah *ahinfo = (struct ip6t_ah *)(*match)->data; 87d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte 88d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte switch (c) { 89d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte case '1': 90d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte if (*flags & IP6T_AH_SPI) 91d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte exit_error(PARAMETER_PROBLEM, 92d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte "Only one `--ahspi' allowed"); 93d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte check_inverse(optarg, &invert, &optind, 0); 94d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte parse_ah_spis(argv[optind-1], ahinfo->spis); 95d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte if (invert) 96d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte ahinfo->invflags |= IP6T_AH_INV_SPI; 97d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte *flags |= IP6T_AH_SPI; 98d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte break; 99d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte case '2': 100d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte if (*flags & IP6T_AH_LEN) 101d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte exit_error(PARAMETER_PROBLEM, 102d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte "Only one `--ahlen' allowed"); 103d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte check_inverse(optarg, &invert, &optind, 0); 104d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte ahinfo->hdrlen = parse_ah_spi(argv[optind-1], "length"); 105d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte if (invert) 106d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte ahinfo->invflags |= IP6T_AH_INV_LEN; 107d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte *flags |= IP6T_AH_LEN; 108d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte break; 109d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte case '3': 110d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte if (*flags & IP6T_AH_RES) 111d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte exit_error(PARAMETER_PROBLEM, 112d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte "Only one `--ahres' allowed"); 113d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte ahinfo->hdrres = 1; 114d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte *flags |= IP6T_AH_RES; 115d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte break; 116d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte default: 117d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte return 0; 118d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte } 119d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte 120d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte return 1; 121d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte} 122d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte 123d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Weltestatic void 124d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welteprint_spis(const char *name, u_int32_t min, u_int32_t max, 125d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte int invert) 126d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte{ 127d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte const char *inv = invert ? "!" : ""; 128d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte 129d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte if (min != 0 || max != 0xFFFFFFFF || invert) { 130703575d4b45d15996ee2ca0b13d958a22cd78f4fStephane Ouellette if (min == max) 131703575d4b45d15996ee2ca0b13d958a22cd78f4fStephane Ouellette printf("%s:%s%u ", name, inv, min); 132703575d4b45d15996ee2ca0b13d958a22cd78f4fStephane Ouellette else 133703575d4b45d15996ee2ca0b13d958a22cd78f4fStephane Ouellette printf("%ss:%s%u:%u ", name, inv, min, max); 134d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte } 135d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte} 136d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte 137d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Weltestatic void 138d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welteprint_len(const char *name, u_int32_t len, int invert) 139d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte{ 140d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte const char *inv = invert ? "!" : ""; 141d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte 142703575d4b45d15996ee2ca0b13d958a22cd78f4fStephane Ouellette if (len != 0 || invert) 143703575d4b45d15996ee2ca0b13d958a22cd78f4fStephane Ouellette printf("%s:%s%u ", name, inv, len); 144d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte} 145d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte 146d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte/* Prints out the union ip6t_matchinfo. */ 147997045f536026c0d643bf884da5ff5de2605197fJan Engelhardtstatic void ah_print(const void *ip, const struct xt_entry_match *match, 148997045f536026c0d643bf884da5ff5de2605197fJan Engelhardt int numeric) 149d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte{ 150d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte const struct ip6t_ah *ah = (struct ip6t_ah *)match->data; 151d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte 152d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte printf("ah "); 153d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte print_spis("spi", ah->spis[0], ah->spis[1], 154d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte ah->invflags & IP6T_AH_INV_SPI); 155d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte print_len("length", ah->hdrlen, 156d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte ah->invflags & IP6T_AH_INV_LEN); 157703575d4b45d15996ee2ca0b13d958a22cd78f4fStephane Ouellette 158703575d4b45d15996ee2ca0b13d958a22cd78f4fStephane Ouellette if (ah->hdrres) 159703575d4b45d15996ee2ca0b13d958a22cd78f4fStephane Ouellette printf("reserved "); 160703575d4b45d15996ee2ca0b13d958a22cd78f4fStephane Ouellette 161d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte if (ah->invflags & ~IP6T_AH_INV_MASK) 162d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte printf("Unknown invflags: 0x%X ", 163d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte ah->invflags & ~IP6T_AH_INV_MASK); 164d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte} 165d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte 166d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte/* Saves the union ip6t_matchinfo in parsable form to stdout. */ 167997045f536026c0d643bf884da5ff5de2605197fJan Engelhardtstatic void ah_save(const void *ip, const struct xt_entry_match *match) 168d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte{ 169d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte const struct ip6t_ah *ahinfo = (struct ip6t_ah *)match->data; 170d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte 171d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte if (!(ahinfo->spis[0] == 0 172d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte && ahinfo->spis[1] == 0xFFFFFFFF)) { 173d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte printf("--ahspi %s", 174d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte (ahinfo->invflags & IP6T_AH_INV_SPI) ? "! " : ""); 175d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte if (ahinfo->spis[0] 176d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte != ahinfo->spis[1]) 177d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte printf("%u:%u ", 178d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte ahinfo->spis[0], 179d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte ahinfo->spis[1]); 180d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte else 181d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte printf("%u ", 182d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte ahinfo->spis[0]); 183d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte } 184d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte 185d8a12a841de648bd38dc52ba624d1ed1810a6333András Kis-Szabó if (ahinfo->hdrlen != 0 || (ahinfo->invflags & IP6T_AH_INV_LEN) ) { 186d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte printf("--ahlen %s%u ", 187d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte (ahinfo->invflags & IP6T_AH_INV_LEN) ? "! " : "", 188d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte ahinfo->hdrlen); 189d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte } 190d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte 191703575d4b45d15996ee2ca0b13d958a22cd78f4fStephane Ouellette if (ahinfo->hdrres != 0 ) 192d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte printf("--ahres "); 193d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte} 194d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte 1958b7c64d6ba156a99008fcd810cba874c73294333Jan Engelhardtstatic struct xtables_match ah_mt6_reg = { 196703575d4b45d15996ee2ca0b13d958a22cd78f4fStephane Ouellette .name = "ah", 1978b7c64d6ba156a99008fcd810cba874c73294333Jan Engelhardt .version = XTABLES_VERSION, 1988b7c64d6ba156a99008fcd810cba874c73294333Jan Engelhardt .family = PF_INET6, 1998b7c64d6ba156a99008fcd810cba874c73294333Jan Engelhardt .size = XT_ALIGN(sizeof(struct ip6t_ah)), 2008b7c64d6ba156a99008fcd810cba874c73294333Jan Engelhardt .userspacesize = XT_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{ 2128b7c64d6ba156a99008fcd810cba874c73294333Jan Engelhardt xtables_register_match(&ah_mt6_reg); 213d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte} 214