libip6t_ah.c revision d32980df1da9d81a93280b4f0e023c58055c4b0c
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. */ 12d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Weltestatic void 13d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Weltehelp(void) 14d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte{ 15d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte printf( 16d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte"AH v%s options:\n" 17d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte" --ahspi [!] spi[:spi] match spi (range)\n" 18d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte" --ahlen [!] length total length of this header\n" 19d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte" --ahres check the reserved filed, too\n", 20d32980df1da9d81a93280b4f0e023c58055c4b0cHarald WelteNETFILTER_VERSION); 21d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte} 22d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte 23d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Weltestatic struct option opts[] = { 24d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte { "ahspi", 1, 0, '1' }, 25d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte { "ahlen", 1, 0, '2' }, 26d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte { "ahres", 0, 0, '3' }, 27d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte {0} 28d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte}; 29d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte 30d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Weltestatic u_int32_t 31d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welteparse_ah_spi(const char *spistr, const char *typestr) 32d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte{ 33d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte unsigned long int spi; 34d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte char* ep; 35d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte 36d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte spi = strtoul(spistr,&ep,0) ; 37d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte 38d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte if ( spistr == ep ) { 39d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte exit_error(PARAMETER_PROBLEM, 40d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte "AH no valid digits in %s `%s'", typestr, spistr); 41d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte } 42d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte if ( spi == ULONG_MAX && errno == ERANGE ) { 43d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte exit_error(PARAMETER_PROBLEM, 44d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte "%s `%s' specified too big: would overflow", 45d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte typestr, spistr); 46d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte } 47d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte if ( *spistr != '\0' && *ep != '\0' ) { 48d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte exit_error(PARAMETER_PROBLEM, 49d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte "AH error parsing %s `%s'", typestr, spistr); 50d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte } 51d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte return (u_int32_t) spi; 52d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte} 53d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte 54d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Weltestatic void 55d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welteparse_ah_spis(const char *spistring, u_int32_t *spis) 56d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte{ 57d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte char *buffer; 58d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte char *cp; 59d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte 60d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte buffer = strdup(spistring); 61d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte if ((cp = strchr(buffer, ':')) == NULL) 62d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte spis[0] = spis[1] = parse_ah_spi(buffer,"spi"); 63d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte else { 64d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte *cp = '\0'; 65d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte cp++; 66d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte 67d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte spis[0] = buffer[0] ? parse_ah_spi(buffer,"spi") : 0; 68d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte spis[1] = cp[0] ? parse_ah_spi(cp,"spi") : 0xFFFFFFFF; 69d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte } 70d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte free(buffer); 71d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte} 72d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte 73d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte/* Initialize the match. */ 74d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Weltestatic void 75d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welteinit(struct ip6t_entry_match *m, unsigned int *nfcache) 76d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte{ 77d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte struct ip6t_ah *ahinfo = (struct ip6t_ah *)m->data; 78d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte 79d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte ahinfo->spis[1] = 0xFFFFFFFF; 80d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte ahinfo->hdrlen = 0; 81d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte ahinfo->hdrres = 0; 82d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte} 83d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte 84d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte/* Function which parses command options; returns true if it 85d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte ate an option */ 86d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Weltestatic int 87d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welteparse(int c, char **argv, int invert, unsigned int *flags, 88d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte const struct ip6t_entry *entry, 89d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte unsigned int *nfcache, 90d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte struct ip6t_entry_match **match) 91d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte{ 92d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte struct ip6t_ah *ahinfo = (struct ip6t_ah *)(*match)->data; 93d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte 94d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte switch (c) { 95d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte case '1': 96d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte if (*flags & IP6T_AH_SPI) 97d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte exit_error(PARAMETER_PROBLEM, 98d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte "Only one `--ahspi' allowed"); 99d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte check_inverse(optarg, &invert, &optind, 0); 100d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte parse_ah_spis(argv[optind-1], ahinfo->spis); 101d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte if (invert) 102d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte ahinfo->invflags |= IP6T_AH_INV_SPI; 103d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte *flags |= IP6T_AH_SPI; 104d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte break; 105d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte case '2': 106d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte if (*flags & IP6T_AH_LEN) 107d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte exit_error(PARAMETER_PROBLEM, 108d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte "Only one `--ahlen' allowed"); 109d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte check_inverse(optarg, &invert, &optind, 0); 110d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte ahinfo->hdrlen = parse_ah_spi(argv[optind-1], "length"); 111d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte if (invert) 112d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte ahinfo->invflags |= IP6T_AH_INV_LEN; 113d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte *flags |= IP6T_AH_LEN; 114d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte break; 115d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte case '3': 116d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte if (*flags & IP6T_AH_RES) 117d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte exit_error(PARAMETER_PROBLEM, 118d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte "Only one `--ahres' allowed"); 119d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte ahinfo->hdrres = 1; 120d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte *flags |= IP6T_AH_RES; 121d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte break; 122d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte default: 123d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte return 0; 124d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte } 125d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte 126d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte return 1; 127d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte} 128d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte 129d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte/* Final check; we don't care. */ 130d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Weltestatic void 131d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Weltefinal_check(unsigned int flags) 132d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte{ 133d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte} 134d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte 135d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Weltestatic void 136d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welteprint_spis(const char *name, u_int32_t min, u_int32_t max, 137d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte int invert) 138d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte{ 139d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte const char *inv = invert ? "!" : ""; 140d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte 141d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte if (min != 0 || max != 0xFFFFFFFF || invert) { 142d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte printf("%s", name); 143d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte if (min == max) { 144d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte printf(":%s", inv); 145d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte printf("%u", min); 146d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte } else { 147d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte printf("s:%s", inv); 148d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte printf("%u",min); 149d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte printf(":"); 150d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte printf("%u",max); 151d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte } 152d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte printf(" "); 153d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte } 154d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte} 155d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte 156d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Weltestatic void 157d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welteprint_len(const char *name, u_int32_t len, int invert) 158d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte{ 159d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte const char *inv = invert ? "!" : ""; 160d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte 161d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte if (len != 0 || invert) { 162d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte printf("%s", name); 163d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte printf(":%s", inv); 164d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte printf("%u", len); 165d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte printf(" "); 166d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte } 167d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte} 168d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte 169d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte/* Prints out the union ip6t_matchinfo. */ 170d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Weltestatic void 171d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welteprint(const struct ip6t_ip6 *ip, 172d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte const struct ip6t_entry_match *match, int numeric) 173d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte{ 174d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte const struct ip6t_ah *ah = (struct ip6t_ah *)match->data; 175d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte 176d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte printf("ah "); 177d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte print_spis("spi", ah->spis[0], ah->spis[1], 178d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte ah->invflags & IP6T_AH_INV_SPI); 179d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte print_len("length", ah->hdrlen, 180d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte ah->invflags & IP6T_AH_INV_LEN); 181d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte if (ah->hdrres) printf("reserved "); 182d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte if (ah->invflags & ~IP6T_AH_INV_MASK) 183d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte printf("Unknown invflags: 0x%X ", 184d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte ah->invflags & ~IP6T_AH_INV_MASK); 185d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte} 186d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte 187d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte/* Saves the union ip6t_matchinfo in parsable form to stdout. */ 188d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Weltestatic void save(const struct ip6t_ip6 *ip, const struct ip6t_entry_match *match) 189d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte{ 190d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte const struct ip6t_ah *ahinfo = (struct ip6t_ah *)match->data; 191d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte 192d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte if (!(ahinfo->spis[0] == 0 193d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte && ahinfo->spis[1] == 0xFFFFFFFF)) { 194d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte printf("--ahspi %s", 195d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte (ahinfo->invflags & IP6T_AH_INV_SPI) ? "! " : ""); 196d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte if (ahinfo->spis[0] 197d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte != ahinfo->spis[1]) 198d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte printf("%u:%u ", 199d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte ahinfo->spis[0], 200d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte ahinfo->spis[1]); 201d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte else 202d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte printf("%u ", 203d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte ahinfo->spis[0]); 204d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte } 205d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte 206d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte if (ahinfo->hdrlen != 0 ) { 207d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte printf("--ahlen %s%u ", 208d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte (ahinfo->invflags & IP6T_AH_INV_LEN) ? "! " : "", 209d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte ahinfo->hdrlen); 210d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte } 211d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte 212d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte if (ahinfo->hdrres != 0 ) { 213d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte printf("--ahres "); 214d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte } 215d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte 216d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte} 217d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte 218d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Weltestatic 219d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Weltestruct ip6tables_match ah 220d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte= { NULL, 221d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte "ah", 222d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte NETFILTER_VERSION, 223d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte IP6T_ALIGN(sizeof(struct ip6t_ah)), 224d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte IP6T_ALIGN(sizeof(struct ip6t_ah)), 225d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte &help, 226d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte &init, 227d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte &parse, 228d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte &final_check, 229d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte &print, 230d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte &save, 231d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte opts 232d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte}; 233d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte 234d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Weltevoid 235d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte_init(void) 236d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte{ 237d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte register_match6(&ah); 238d32980df1da9d81a93280b4f0e023c58055c4b0cHarald Welte} 239