Don't use 'release' macro.
[platform/upstream/ebtables.git] / useful_functions.c
1 /*
2  * useful_functions.c, January 2004
3  *
4  * Random collection of functions that can be used by extensions.
5  *
6  * Author: Bart De Schuymer
7  *
8  *  This code is stongly inspired on the iptables code which is
9  *  Copyright (C) 1999 Paul `Rusty' Russell & Michael J. Neuling
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License as
13  * published by the Free Software Foundation; either version 2 of the
14  * License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful, but
17  * WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19  * General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24  */
25 #include "include/ebtables_u.h"
26 #include "include/ethernetdb.h"
27 #include <stdio.h>
28 #include <netinet/ether.h>
29 #include <string.h>
30 #include <stdlib.h>
31 #include <getopt.h>
32 #include <errno.h>
33 #include <sys/types.h>
34 #include <sys/socket.h>
35 #include <arpa/inet.h>
36
37 const unsigned char mac_type_unicast[ETH_ALEN] =   {0,0,0,0,0,0};
38 const unsigned char msk_type_unicast[ETH_ALEN] =   {1,0,0,0,0,0};
39 const unsigned char mac_type_multicast[ETH_ALEN] = {1,0,0,0,0,0};
40 const unsigned char msk_type_multicast[ETH_ALEN] = {1,0,0,0,0,0};
41 const unsigned char mac_type_broadcast[ETH_ALEN] = {255,255,255,255,255,255};
42 const unsigned char msk_type_broadcast[ETH_ALEN] = {255,255,255,255,255,255};
43 const unsigned char mac_type_bridge_group[ETH_ALEN] = {0x01,0x80,0xc2,0,0,0};
44 const unsigned char msk_type_bridge_group[ETH_ALEN] = {255,255,255,255,255,255};
45
46 /* 0: default, print only 2 digits if necessary
47  * 2: always print 2 digits, a printed mac address
48  * then always has the same length */
49 int ebt_printstyle_mac;
50
51 void ebt_print_mac(const unsigned char *mac)
52 {
53         if (ebt_printstyle_mac == 2) {
54                 int j;
55                 for (j = 0; j < ETH_ALEN; j++)
56                         printf("%02x%s", mac[j],
57                                 (j==ETH_ALEN-1) ? "" : ":");
58         } else
59                 printf("%s", ether_ntoa((struct ether_addr *) mac));
60 }
61
62 void ebt_print_mac_and_mask(const unsigned char *mac, const unsigned char *mask)
63 {
64         char hlpmsk[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
65
66         if (!memcmp(mac, mac_type_unicast, 6) &&
67             !memcmp(mask, msk_type_unicast, 6))
68                 printf("Unicast");
69         else if (!memcmp(mac, mac_type_multicast, 6) &&
70                  !memcmp(mask, msk_type_multicast, 6))
71                 printf("Multicast");
72         else if (!memcmp(mac, mac_type_broadcast, 6) &&
73                  !memcmp(mask, msk_type_broadcast, 6))
74                 printf("Broadcast");
75         else if (!memcmp(mac, mac_type_bridge_group, 6) &&
76                  !memcmp(mask, msk_type_bridge_group, 6))
77                 printf("BGA");
78         else {
79                 ebt_print_mac(mac);
80                 if (memcmp(mask, hlpmsk, 6)) {
81                         printf("/");
82                         ebt_print_mac(mask);
83                 }
84         }
85 }
86
87 /* Checks the type for validity and calls getethertypebynumber(). */
88 struct ethertypeent *parseethertypebynumber(int type)
89 {
90         if (type < 1536)
91                 ebt_print_error("Ethernet protocols have values >= 0x0600");
92         if (type > 0xffff)
93                 ebt_print_error("Ethernet protocols have values <= 0xffff");
94         return getethertypebynumber(type);
95 }
96
97 /* Put the mac address into 6 (ETH_ALEN) bytes returns 0 on success. */
98 int ebt_get_mac_and_mask(const char *from, unsigned char *to,
99   unsigned char *mask)
100 {
101         char *p;
102         int i;
103         struct ether_addr *addr;
104
105         if (strcasecmp(from, "Unicast") == 0) {
106                 memcpy(to, mac_type_unicast, ETH_ALEN);
107                 memcpy(mask, msk_type_unicast, ETH_ALEN);
108                 return 0;
109         }
110         if (strcasecmp(from, "Multicast") == 0) {
111                 memcpy(to, mac_type_multicast, ETH_ALEN);
112                 memcpy(mask, msk_type_multicast, ETH_ALEN);
113                 return 0;
114         }
115         if (strcasecmp(from, "Broadcast") == 0) {
116                 memcpy(to, mac_type_broadcast, ETH_ALEN);
117                 memcpy(mask, msk_type_broadcast, ETH_ALEN);
118                 return 0;
119         }
120         if (strcasecmp(from, "BGA") == 0) {
121                 memcpy(to, mac_type_bridge_group, ETH_ALEN);
122                 memcpy(mask, msk_type_bridge_group, ETH_ALEN);
123                 return 0;
124         }
125         if ( (p = strrchr(from, '/')) != NULL) {
126                 *p = '\0';
127                 if (!(addr = ether_aton(p + 1)))
128                         return -1;
129                 memcpy(mask, addr, ETH_ALEN);
130         } else
131                 memset(mask, 0xff, ETH_ALEN);
132         if (!(addr = ether_aton(from)))
133                 return -1;
134         memcpy(to, addr, ETH_ALEN);
135         for (i = 0; i < ETH_ALEN; i++)
136                 to[i] &= mask[i];
137         return 0;
138 }
139
140 /* 0: default
141  * 1: the inverse '!' of the option has already been specified */
142 int ebt_invert = 0;
143
144 /*
145  * Check if the inverse of the option is specified. This is used
146  * in the parse functions of the extensions and ebtables.c
147  */
148 int _ebt_check_inverse(const char option[], int argc, char **argv)
149 {
150         if (!option)
151                 return ebt_invert;
152         if (strcmp(option, "!") == 0) {
153                 if (ebt_invert == 1)
154                         ebt_print_error("Double use of '!' not allowed");
155                 if (optind >= argc)
156                         optarg = NULL;
157                 else
158                         optarg = argv[optind];
159                 optind++;
160                 ebt_invert = 1;
161                 return 1;
162         }
163         return ebt_invert;
164 }
165
166 /* Make sure the same option wasn't specified twice. This is used
167  * in the parse functions of the extensions and ebtables.c */
168 void ebt_check_option(unsigned int *flags, unsigned int mask)
169 {
170         if (*flags & mask)
171                 ebt_print_error("Multiple use of same option not allowed");
172         *flags |= mask;
173 }
174
175 /* Put the ip string into 4 bytes. */
176 static int undot_ip(char *ip, unsigned char *ip2)
177 {
178         char *p, *q, *end;
179         long int onebyte;
180         int i;
181         char buf[20];
182
183         strncpy(buf, ip, sizeof(buf) - 1);
184
185         p = buf;
186         for (i = 0; i < 3; i++) {
187                 if ((q = strchr(p, '.')) == NULL)
188                         return -1;
189                 *q = '\0';
190                 onebyte = strtol(p, &end, 10);
191                 if (*end != '\0' || onebyte > 255 || onebyte < 0)   
192                         return -1;
193                 ip2[i] = (unsigned char)onebyte;
194                 p = q + 1;
195         }
196
197         onebyte = strtol(p, &end, 10);
198         if (*end != '\0' || onebyte > 255 || onebyte < 0)
199                 return -1;
200         ip2[3] = (unsigned char)onebyte;
201
202         return 0;
203 }
204
205 /* Put the mask into 4 bytes. */
206 static int ip_mask(char *mask, unsigned char *mask2)
207 {
208         char *end;
209         long int bits;
210         uint32_t mask22;
211
212         if (undot_ip(mask, mask2)) {
213                 /* not the /a.b.c.e format, maybe the /x format */
214                 bits = strtol(mask, &end, 10);
215                 if (*end != '\0' || bits > 32 || bits < 0)
216                         return -1;
217                 if (bits != 0) {
218                         mask22 = htonl(0xFFFFFFFF << (32 - bits));
219                         memcpy(mask2, &mask22, 4);
220                 } else {
221                         mask22 = 0xFFFFFFFF;
222                         memcpy(mask2, &mask22, 4);
223                 }
224         }
225         return 0;
226 }
227
228 /* Set the ip mask and ip address. Callers should check ebt_errormsg[0].
229  * The string pointed to by address can be altered. */
230 void ebt_parse_ip_address(char *address, uint32_t *addr, uint32_t *msk)
231 {
232         char *p;
233
234         /* first the mask */
235         if ((p = strrchr(address, '/')) != NULL) {
236                 *p = '\0';
237                 if (ip_mask(p + 1, (unsigned char *)msk)) {
238                         ebt_print_error("Problem with the IP mask '%s'", p + 1);
239                         return;
240                 }
241         } else
242                 *msk = 0xFFFFFFFF;
243
244         if (undot_ip(address, (unsigned char *)addr)) {
245                 ebt_print_error("Problem with the IP address '%s'", address);
246                 return;
247         }
248         *addr = *addr & *msk;
249 }
250
251
252 /* Transform the ip mask into a string ready for output. */
253 char *ebt_mask_to_dotted(uint32_t mask)
254 {
255         int i;
256         static char buf[20];
257         uint32_t maskaddr, bits;
258
259         maskaddr = ntohl(mask);
260
261         /* don't print /32 */
262         if (mask == 0xFFFFFFFFL) {
263                 *buf = '\0';
264                 return buf;
265         }
266
267         i = 32;
268         bits = 0xFFFFFFFEL; /* Case 0xFFFFFFFF has just been dealt with */
269         while (--i >= 0 && maskaddr != bits)
270                 bits <<= 1;
271
272         if (i > 0)
273                 sprintf(buf, "/%d", i);
274         else if (!i)
275                 *buf = '\0';
276         else
277                 /* Mask was not a decent combination of 1's and 0's */
278                 sprintf(buf, "/%d.%d.%d.%d", ((unsigned char *)&mask)[0], 
279                    ((unsigned char *)&mask)[1], ((unsigned char *)&mask)[2],
280                    ((unsigned char *)&mask)[3]);
281
282         return buf;
283 }
284
285 /* Most of the following code is derived from iptables */
286 static void
287 in6addrcpy(struct in6_addr *dst, struct in6_addr *src)
288 {
289         memcpy(dst, src, sizeof(struct in6_addr));
290 }
291
292 int string_to_number_ll(const char *s, unsigned long long min,
293             unsigned long long max, unsigned long long *ret)
294 {
295         unsigned long long number;
296         char *end;
297
298         /* Handle hex, octal, etc. */
299         errno = 0;
300         number = strtoull(s, &end, 0);
301         if (*end == '\0' && end != s) {
302                 /* we parsed a number, let's see if we want this */
303                 if (errno != ERANGE && min <= number && (!max || number <= max)) {
304                         *ret = number;
305                         return 0;
306                 }
307         }
308         return -1;
309 }
310
311 int string_to_number_l(const char *s, unsigned long min, unsigned long max,
312                        unsigned long *ret)
313 {
314         int result;
315         unsigned long long number;
316
317         result = string_to_number_ll(s, min, max, &number);
318         *ret = (unsigned long)number;
319
320         return result;
321 }
322
323 int string_to_number(const char *s, unsigned int min, unsigned int max,
324                      unsigned int *ret)
325 {
326         int result;
327         unsigned long number;
328
329         result = string_to_number_l(s, min, max, &number);
330         *ret = (unsigned int)number;
331
332         return result;
333 }
334
335 static struct in6_addr *numeric_to_addr(const char *num)
336 {
337         static struct in6_addr ap;
338         int err;
339
340         if ((err=inet_pton(AF_INET6, num, &ap)) == 1)
341                 return &ap;
342         return (struct in6_addr *)NULL;
343 }
344
345 static struct in6_addr *parse_ip6_mask(char *mask)
346 {
347         static struct in6_addr maskaddr;
348         struct in6_addr *addrp;
349         unsigned int bits;
350
351         if (mask == NULL) {
352                 /* no mask at all defaults to 128 bits */
353                 memset(&maskaddr, 0xff, sizeof maskaddr);
354                 return &maskaddr;
355         }
356         if ((addrp = numeric_to_addr(mask)) != NULL)
357                 return addrp;
358         if (string_to_number(mask, 0, 128, &bits) == -1)
359                 ebt_print_error("Invalid IPv6 Mask '%s' specified", mask);
360         if (bits != 0) {
361                 char *p = (char *)&maskaddr;
362                 memset(p, 0xff, bits / 8);
363                 memset(p + (bits / 8) + 1, 0, (128 - bits) / 8);
364                 p[bits / 8] = 0xff << (8 - (bits & 7));
365                 return &maskaddr;
366         }
367
368         memset(&maskaddr, 0, sizeof maskaddr);
369         return &maskaddr;
370 }
371
372 /* Set the ipv6 mask and address. Callers should check ebt_errormsg[0].
373  * The string pointed to by address can be altered. */
374 void ebt_parse_ip6_address(char *address, struct in6_addr *addr,
375                            struct in6_addr *msk)
376 {
377         struct in6_addr *tmp_addr;
378         char buf[256];
379         char *p;
380         int i;
381         int err;
382
383         strncpy(buf, address, sizeof(buf) - 1);
384         /* first the mask */
385         buf[sizeof(buf) - 1] = '\0';
386         if ((p = strrchr(buf, '/')) != NULL) {
387                 *p = '\0';
388                 tmp_addr = parse_ip6_mask(p + 1);
389         } else
390                 tmp_addr = parse_ip6_mask(NULL);
391         in6addrcpy(msk, tmp_addr);
392
393         /* if a null mask is given, the name is ignored, like in "any/0" */
394         if (!memcmp(msk, &in6addr_any, sizeof(in6addr_any)))
395                 strcpy(buf, "::");
396
397         if ((err=inet_pton(AF_INET6, buf, addr)) < 1) {
398                 ebt_print_error("Invalid IPv6 Address '%s' specified", buf);
399                 return;
400         }
401
402         for (i = 0; i < 4; i++)
403                 addr->s6_addr32[i] &= msk->s6_addr32[i];
404 }
405
406 /* Transform the ip6 addr into a string ready for output. */
407 char *ebt_ip6_to_numeric(const struct in6_addr *addrp)
408 {
409         /* 0000:0000:0000:0000:0000:000.000.000.000
410          * 0000:0000:0000:0000:0000:0000:0000:0000 */
411         static char buf[50+1];
412         return (char *)inet_ntop(AF_INET6, addrp, buf, sizeof(buf));
413 }
414
415 char *ebt_ip6_mask_to_string(const struct in6_addr *msk)
416 {
417         /* /0000:0000:0000:0000:0000:000.000.000.000
418          * /0000:0000:0000:0000:0000:0000:0000:0000 */
419         static char buf[51+1];
420         if (msk->s6_addr32[0] == 0xFFFFFFFFL && msk->s6_addr32[1] == 0xFFFFFFFFL &&
421             msk->s6_addr32[2] == 0xFFFFFFFFL && msk->s6_addr32[3] == 0xFFFFFFFFL)
422                 *buf = '\0';
423         else
424                 sprintf(buf, "/%s", ebt_ip6_to_numeric(msk));
425         return buf;
426 }