Fork for IVI and add .changes file
[profile/ivi/iptables.git] / extensions / libxt_esp.c
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 <limits.h>
9
10 #include <xtables.h>
11 #include <linux/netfilter/xt_esp.h>
12
13 static void esp_help(void)
14 {
15         printf(
16 "esp match options:\n"
17 "[!] --espspi spi[:spi]\n"
18 "                               match spi (range)\n");
19 }
20
21 static const struct option esp_opts[] = {
22         { "espspi", 1, NULL, '1' },
23         { .name = NULL }
24 };
25
26 static u_int32_t
27 parse_esp_spi(const char *spistr)
28 {
29         unsigned long int spi;
30         char* ep;
31
32         spi =  strtoul(spistr,&ep,0) ;
33
34         if ( spistr == ep ) {
35                 xtables_error(PARAMETER_PROBLEM,
36                            "ESP no valid digits in spi `%s'", spistr);
37         }
38         if ( spi == ULONG_MAX  && errno == ERANGE ) {
39                 xtables_error(PARAMETER_PROBLEM,
40                            "spi `%s' specified too big: would overflow", spistr);
41         }       
42         if ( *spistr != '\0'  && *ep != '\0' ) {
43                 xtables_error(PARAMETER_PROBLEM,
44                            "ESP error parsing spi `%s'", spistr);
45         }
46         return spi;
47 }
48
49 static void
50 parse_esp_spis(const char *spistring, u_int32_t *spis)
51 {
52         char *buffer;
53         char *cp;
54
55         buffer = strdup(spistring);
56         if ((cp = strchr(buffer, ':')) == NULL)
57                 spis[0] = spis[1] = parse_esp_spi(buffer);
58         else {
59                 *cp = '\0';
60                 cp++;
61
62                 spis[0] = buffer[0] ? parse_esp_spi(buffer) : 0;
63                 spis[1] = cp[0] ? parse_esp_spi(cp) : 0xFFFFFFFF;
64                 if (spis[0] > spis[1])
65                         xtables_error(PARAMETER_PROBLEM,
66                                    "Invalid ESP spi range: %s", spistring);
67         }
68         free(buffer);
69 }
70
71 static void esp_init(struct xt_entry_match *m)
72 {
73         struct xt_esp *espinfo = (struct xt_esp *)m->data;
74
75         espinfo->spis[1] = 0xFFFFFFFF;
76 }
77
78 #define ESP_SPI 0x01
79
80 static int
81 esp_parse(int c, char **argv, int invert, unsigned int *flags,
82           const void *entry, struct xt_entry_match **match)
83 {
84         struct xt_esp *espinfo = (struct xt_esp *)(*match)->data;
85
86         switch (c) {
87         case '1':
88                 if (*flags & ESP_SPI)
89                         xtables_error(PARAMETER_PROBLEM,
90                                    "Only one `--espspi' allowed");
91                 xtables_check_inverse(optarg, &invert, &optind, 0, argv);
92                 parse_esp_spis(optarg, espinfo->spis);
93                 if (invert)
94                         espinfo->invflags |= XT_ESP_INV_SPI;
95                 *flags |= ESP_SPI;
96                 break;
97         default:
98                 return 0;
99         }
100
101         return 1;
102 }
103
104 static void
105 print_spis(const char *name, u_int32_t min, u_int32_t max,
106             int invert)
107 {
108         const char *inv = invert ? "!" : "";
109
110         if (min != 0 || max != 0xFFFFFFFF || invert) {
111                 if (min == max)
112                         printf("%s:%s%u ", name, inv, min);
113                 else
114                         printf("%ss:%s%u:%u ", name, inv, min, max);
115         }
116 }
117
118 static void
119 esp_print(const void *ip, const struct xt_entry_match *match, int numeric)
120 {
121         const struct xt_esp *esp = (struct xt_esp *)match->data;
122
123         printf("esp ");
124         print_spis("spi", esp->spis[0], esp->spis[1],
125                     esp->invflags & XT_ESP_INV_SPI);
126         if (esp->invflags & ~XT_ESP_INV_MASK)
127                 printf("Unknown invflags: 0x%X ",
128                        esp->invflags & ~XT_ESP_INV_MASK);
129 }
130
131 static void esp_save(const void *ip, const struct xt_entry_match *match)
132 {
133         const struct xt_esp *espinfo = (struct xt_esp *)match->data;
134
135         if (!(espinfo->spis[0] == 0
136             && espinfo->spis[1] == 0xFFFFFFFF)) {
137                 printf("%s--espspi ",
138                         (espinfo->invflags & XT_ESP_INV_SPI) ? "! " : "");
139                 if (espinfo->spis[0]
140                     != espinfo->spis[1])
141                         printf("%u:%u ",
142                                espinfo->spis[0],
143                                espinfo->spis[1]);
144                 else
145                         printf("%u ",
146                                espinfo->spis[0]);
147         }
148
149 }
150
151 static struct xtables_match esp_match = {
152         .family         = NFPROTO_UNSPEC,
153         .name           = "esp",
154         .version        = XTABLES_VERSION,
155         .size           = XT_ALIGN(sizeof(struct xt_esp)),
156         .userspacesize  = XT_ALIGN(sizeof(struct xt_esp)),
157         .help           = esp_help,
158         .init           = esp_init,
159         .parse          = esp_parse,
160         .print          = esp_print,
161         .save           = esp_save,
162         .extra_opts     = esp_opts,
163 };
164
165 void
166 _init(void)
167 {
168         xtables_register_match(&esp_match);
169 }