blob: e0b1e4c4a8746f3993aaeeb8db8dc9c02fc208eb [file] [log] [blame]
Bart De Schuymer80c82bb2004-01-14 20:06:44 +00001/*
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
33const unsigned char mac_type_unicast[ETH_ALEN] = {0,0,0,0,0,0};
34const unsigned char msk_type_unicast[ETH_ALEN] = {1,0,0,0,0,0};
35const unsigned char mac_type_multicast[ETH_ALEN] = {1,0,0,0,0,0};
36const unsigned char msk_type_multicast[ETH_ALEN] = {1,0,0,0,0,0};
37const unsigned char mac_type_broadcast[ETH_ALEN] = {255,255,255,255,255,255};
38const unsigned char msk_type_broadcast[ETH_ALEN] = {255,255,255,255,255,255};
39const unsigned char mac_type_bridge_group[ETH_ALEN] = {0x01,0x80,0xc2,0,0,0};
40const unsigned char msk_type_bridge_group[ETH_ALEN] = {255,255,255,255,255,255};
41
Bart De Schuymer80c82bb2004-01-14 20:06:44 +000042/*
Bart De Schuymer55d44132004-02-23 20:55:24 +000043 * 0: default, print only 2 digits if necessary
44 * 2: always print 2 digits, a printed mac address
45 * then always has the same length
Bart De Schuymer80c82bb2004-01-14 20:06:44 +000046 */
Bart De Schuymer55d44132004-02-23 20:55:24 +000047int ebt_printstyle_mac;
48
Bart De Schuymer80c82bb2004-01-14 20:06:44 +000049void ebt_print_mac(const char *mac)
50{
51 if (ebt_printstyle_mac == 2) {
52 int j;
53 for (j = 0; j < ETH_ALEN; j++)
54 printf("%02x%s", (unsigned char)mac[j],
55 (j==ETH_ALEN-1) ? "" : ":");
56 } else
57 printf("%s", ether_ntoa((struct ether_addr *) mac));
58}
59
60void ebt_print_mac_and_mask(const char *mac, const char *mask)
61{
62 char hlpmsk[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
63
64 if (!memcmp(mac, mac_type_unicast, 6) &&
65 !memcmp(mask, msk_type_unicast, 6))
66 printf("Unicast");
67 else if (!memcmp(mac, mac_type_multicast, 6) &&
68 !memcmp(mask, msk_type_multicast, 6))
69 printf("Multicast");
70 else if (!memcmp(mac, mac_type_broadcast, 6) &&
71 !memcmp(mask, msk_type_broadcast, 6))
72 printf("Broadcast");
73 else if (!memcmp(mac, mac_type_bridge_group, 6) &&
74 !memcmp(mask, msk_type_bridge_group, 6))
75 printf("BGA");
76 else {
77 ebt_print_mac(mac);
78 if (memcmp(mask, hlpmsk, 6)) {
79 printf("/");
80 ebt_print_mac(mask);
81 }
82 }
83}
84
85/*
86 * Checks the type for validity and calls getethertypebynumber()
87 */
88struct ethertypeent *parseethertypebynumber(int type)
89{
90 if (type < 1536)
Bart De Schuymer64182a32004-01-21 20:39:54 +000091 ebt_print_error("Ethernet protocols have values >= 0x0600");
Bart De Schuymer80c82bb2004-01-14 20:06:44 +000092 if (type > 0xffff)
Bart De Schuymer64182a32004-01-21 20:39:54 +000093 ebt_print_error("Ethernet protocols have values <= 0xffff");
Bart De Schuymer80c82bb2004-01-14 20:06:44 +000094 return getethertypebynumber(type);
95}
96
97/*
98 * put the mac address into 6 (ETH_ALEN) bytes
99 * returns 0 on success
100 */
101int ebt_get_mac_and_mask(char *from, char *to, char *mask)
102{
103 char *p;
104 int i;
105 struct ether_addr *addr;
106
107 if (strcasecmp(from, "Unicast") == 0) {
108 memcpy(to, mac_type_unicast, ETH_ALEN);
109 memcpy(mask, msk_type_unicast, ETH_ALEN);
110 return 0;
111 }
112 if (strcasecmp(from, "Multicast") == 0) {
113 memcpy(to, mac_type_multicast, ETH_ALEN);
114 memcpy(mask, msk_type_multicast, ETH_ALEN);
115 return 0;
116 }
117 if (strcasecmp(from, "Broadcast") == 0) {
118 memcpy(to, mac_type_broadcast, ETH_ALEN);
119 memcpy(mask, msk_type_broadcast, ETH_ALEN);
120 return 0;
121 }
122 if (strcasecmp(from, "BGA") == 0) {
123 memcpy(to, mac_type_bridge_group, ETH_ALEN);
124 memcpy(mask, msk_type_bridge_group, ETH_ALEN);
125 return 0;
126 }
127 if ( (p = strrchr(from, '/')) != NULL) {
128 *p = '\0';
129 if (!(addr = ether_aton(p + 1)))
130 return -1;
131 memcpy(mask, addr, ETH_ALEN);
132 } else
133 memset(mask, 0xff, ETH_ALEN);
134 if (!(addr = ether_aton(from)))
135 return -1;
136 memcpy(to, addr, ETH_ALEN);
137 for (i = 0; i < ETH_ALEN; i++)
138 to[i] &= mask[i];
139 return 0;
140}
141
Bart De Schuymer55d44132004-02-23 20:55:24 +0000142/*
143 * 0: default
144 * 1: the inverse '!' of the option has already been specified
145 */
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000146int ebt_invert = 0;
Bart De Schuymer55d44132004-02-23 20:55:24 +0000147
148/*
149 * Check if the inverse of the option is specified. This is used
150 * in the parse functions of the extensions and ebtables.c.
151 */
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000152int ebt_check_inverse(const char option[])
153{
154 if (strcmp(option, "!") == 0) {
155 if (ebt_invert == 1)
Bart De Schuymer64182a32004-01-21 20:39:54 +0000156 ebt_print_error("double use of '!' not allowed");
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000157 optind++;
158 ebt_invert = 1;
159 return 1;
160 }
161 return ebt_invert;
162}
163
Bart De Schuymer55d44132004-02-23 20:55:24 +0000164/*
165 * Make sure the same option wasn't specified twice. This is used
166 * in the parse functions of the extensions and ebtables.c.
167 */
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000168void ebt_check_option(unsigned int *flags, unsigned int mask)
169{
170 if (*flags & mask)
Bart De Schuymer64182a32004-01-21 20:39:54 +0000171 ebt_print_error("Multiple use of same option not allowed");
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000172 *flags |= mask;
173}
174
Bart De Schuymer55d44132004-02-23 20:55:24 +0000175/*
176 * put the ip string into 4 bytes
177 */
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000178static int undot_ip(char *ip, unsigned char *ip2)
179{
180 char *p, *q, *end;
181 long int onebyte;
182 int i;
183 char buf[20];
184
185 strncpy(buf, ip, sizeof(buf) - 1);
186
187 p = buf;
188 for (i = 0; i < 3; i++) {
189 if ((q = strchr(p, '.')) == NULL)
190 return -1;
191 *q = '\0';
192 onebyte = strtol(p, &end, 10);
193 if (*end != '\0' || onebyte > 255 || onebyte < 0)
194 return -1;
195 ip2[i] = (unsigned char)onebyte;
196 p = q + 1;
197 }
198
199 onebyte = strtol(p, &end, 10);
200 if (*end != '\0' || onebyte > 255 || onebyte < 0)
201 return -1;
202 ip2[3] = (unsigned char)onebyte;
203
204 return 0;
205}
206
Bart De Schuymer55d44132004-02-23 20:55:24 +0000207/*
208 * put the mask into 4 bytes
209 */
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000210static int ip_mask(char *mask, unsigned char *mask2)
211{
212 char *end;
213 long int bits;
214 uint32_t mask22;
215
216 if (undot_ip(mask, mask2)) {
217 /* not the /a.b.c.e format, maybe the /x format */
218 bits = strtol(mask, &end, 10);
219 if (*end != '\0' || bits > 32 || bits < 0)
220 return -1;
221 if (bits != 0) {
222 mask22 = htonl(0xFFFFFFFF << (32 - bits));
223 memcpy(mask2, &mask22, 4);
224 } else {
225 mask22 = 0xFFFFFFFF;
226 memcpy(mask2, &mask22, 4);
227 }
228 }
229 return 0;
230}
231
Bart De Schuymer55d44132004-02-23 20:55:24 +0000232/*
233 * set the ip mask and ip address
234 */
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000235void ebt_parse_ip_address(char *address, uint32_t *addr, uint32_t *msk)
236{
237 char *p;
238
239 /* first the mask */
240 if ((p = strrchr(address, '/')) != NULL) {
241 *p = '\0';
242 if (ip_mask(p + 1, (unsigned char *)msk))
Bart De Schuymer64182a32004-01-21 20:39:54 +0000243 ebt_print_error("Problem with the IP mask");
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000244 } else
245 *msk = 0xFFFFFFFF;
246
247 if (undot_ip(address, (unsigned char *)addr))
Bart De Schuymer64182a32004-01-21 20:39:54 +0000248 ebt_print_error("Problem with the IP address");
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000249 *addr = *addr & *msk;
250}
251
Bart De Schuymer55d44132004-02-23 20:55:24 +0000252/*
253 * transform the ip mask into a string ready for output
254 */
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000255char *ebt_mask_to_dotted(uint32_t mask)
256{
257 int i;
258 static char buf[20];
259 uint32_t maskaddr, bits;
260
261 maskaddr = ntohl(mask);
262
263 /* don't print /32 */
264 if (mask == 0xFFFFFFFFL) {
265 *buf = '\0';
266 return buf;
267 }
268
269 i = 32;
270 bits = 0xFFFFFFFEL; /* case 0xFFFFFFFF has just been dealt with */
271 while (--i >= 0 && maskaddr != bits)
272 bits <<= 1;
273
274 if (i > 0)
275 sprintf(buf, "/%d", i);
276 else if (!i)
277 *buf = '\0';
278 else
279 /* mask was not a decent combination of 1's and 0's */
280 sprintf(buf, "/%d.%d.%d.%d", ((unsigned char *)&mask)[0],
281 ((unsigned char *)&mask)[1], ((unsigned char *)&mask)[2],
282 ((unsigned char *)&mask)[3]);
283
284 return buf;
285}