blob: cec0cc462fed59e716c886cb8fdc1ebb873af96c [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
42int ebt_printstyle_mac;
43/*
44 * flag = 2: byte always printed with 2 digits
45 */
46void ebt_print_mac(const char *mac)
47{
48 if (ebt_printstyle_mac == 2) {
49 int j;
50 for (j = 0; j < ETH_ALEN; j++)
51 printf("%02x%s", (unsigned char)mac[j],
52 (j==ETH_ALEN-1) ? "" : ":");
53 } else
54 printf("%s", ether_ntoa((struct ether_addr *) mac));
55}
56
57void ebt_print_mac_and_mask(const char *mac, const char *mask)
58{
59 char hlpmsk[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
60
61 if (!memcmp(mac, mac_type_unicast, 6) &&
62 !memcmp(mask, msk_type_unicast, 6))
63 printf("Unicast");
64 else if (!memcmp(mac, mac_type_multicast, 6) &&
65 !memcmp(mask, msk_type_multicast, 6))
66 printf("Multicast");
67 else if (!memcmp(mac, mac_type_broadcast, 6) &&
68 !memcmp(mask, msk_type_broadcast, 6))
69 printf("Broadcast");
70 else if (!memcmp(mac, mac_type_bridge_group, 6) &&
71 !memcmp(mask, msk_type_bridge_group, 6))
72 printf("BGA");
73 else {
74 ebt_print_mac(mac);
75 if (memcmp(mask, hlpmsk, 6)) {
76 printf("/");
77 ebt_print_mac(mask);
78 }
79 }
80}
81
82/*
83 * Checks the type for validity and calls getethertypebynumber()
84 */
85struct ethertypeent *parseethertypebynumber(int type)
86{
87 if (type < 1536)
88 print_error("Ethernet protocols have values >= 0x0600");
89 if (type > 0xffff)
90 print_error("Ethernet protocols have values <= 0xffff");
91 return getethertypebynumber(type);
92}
93
94/*
95 * put the mac address into 6 (ETH_ALEN) bytes
96 * returns 0 on success
97 */
98int ebt_get_mac_and_mask(char *from, char *to, char *mask)
99{
100 char *p;
101 int i;
102 struct ether_addr *addr;
103
104 if (strcasecmp(from, "Unicast") == 0) {
105 memcpy(to, mac_type_unicast, ETH_ALEN);
106 memcpy(mask, msk_type_unicast, ETH_ALEN);
107 return 0;
108 }
109 if (strcasecmp(from, "Multicast") == 0) {
110 memcpy(to, mac_type_multicast, ETH_ALEN);
111 memcpy(mask, msk_type_multicast, ETH_ALEN);
112 return 0;
113 }
114 if (strcasecmp(from, "Broadcast") == 0) {
115 memcpy(to, mac_type_broadcast, ETH_ALEN);
116 memcpy(mask, msk_type_broadcast, ETH_ALEN);
117 return 0;
118 }
119 if (strcasecmp(from, "BGA") == 0) {
120 memcpy(to, mac_type_bridge_group, ETH_ALEN);
121 memcpy(mask, msk_type_bridge_group, ETH_ALEN);
122 return 0;
123 }
124 if ( (p = strrchr(from, '/')) != NULL) {
125 *p = '\0';
126 if (!(addr = ether_aton(p + 1)))
127 return -1;
128 memcpy(mask, addr, ETH_ALEN);
129 } else
130 memset(mask, 0xff, ETH_ALEN);
131 if (!(addr = ether_aton(from)))
132 return -1;
133 memcpy(to, addr, ETH_ALEN);
134 for (i = 0; i < ETH_ALEN; i++)
135 to[i] &= mask[i];
136 return 0;
137}
138
139int ebt_invert = 0;
140int ebt_check_inverse(const char option[])
141{
142 if (strcmp(option, "!") == 0) {
143 if (ebt_invert == 1)
144 print_error("double use of '!' not allowed");
145 optind++;
146 ebt_invert = 1;
147 return 1;
148 }
149 return ebt_invert;
150}
151
152void ebt_check_option(unsigned int *flags, unsigned int mask)
153{
154 if (*flags & mask)
155 print_error("Multiple use of same option not allowed");
156 *flags |= mask;
157}
158
159/* put the ip string into 4 bytes */
160static int undot_ip(char *ip, unsigned char *ip2)
161{
162 char *p, *q, *end;
163 long int onebyte;
164 int i;
165 char buf[20];
166
167 strncpy(buf, ip, sizeof(buf) - 1);
168
169 p = buf;
170 for (i = 0; i < 3; i++) {
171 if ((q = strchr(p, '.')) == NULL)
172 return -1;
173 *q = '\0';
174 onebyte = strtol(p, &end, 10);
175 if (*end != '\0' || onebyte > 255 || onebyte < 0)
176 return -1;
177 ip2[i] = (unsigned char)onebyte;
178 p = q + 1;
179 }
180
181 onebyte = strtol(p, &end, 10);
182 if (*end != '\0' || onebyte > 255 || onebyte < 0)
183 return -1;
184 ip2[3] = (unsigned char)onebyte;
185
186 return 0;
187}
188
189/* put the mask into 4 bytes */
190static int ip_mask(char *mask, unsigned char *mask2)
191{
192 char *end;
193 long int bits;
194 uint32_t mask22;
195
196 if (undot_ip(mask, mask2)) {
197 /* not the /a.b.c.e format, maybe the /x format */
198 bits = strtol(mask, &end, 10);
199 if (*end != '\0' || bits > 32 || bits < 0)
200 return -1;
201 if (bits != 0) {
202 mask22 = htonl(0xFFFFFFFF << (32 - bits));
203 memcpy(mask2, &mask22, 4);
204 } else {
205 mask22 = 0xFFFFFFFF;
206 memcpy(mask2, &mask22, 4);
207 }
208 }
209 return 0;
210}
211
212/* set the ip mask and ip address */
213void ebt_parse_ip_address(char *address, uint32_t *addr, uint32_t *msk)
214{
215 char *p;
216
217 /* first the mask */
218 if ((p = strrchr(address, '/')) != NULL) {
219 *p = '\0';
220 if (ip_mask(p + 1, (unsigned char *)msk))
221 print_error("Problem with the IP mask");
222 } else
223 *msk = 0xFFFFFFFF;
224
225 if (undot_ip(address, (unsigned char *)addr))
226 print_error("Problem with the IP address");
227 *addr = *addr & *msk;
228}
229
230/* transform the ip mask into a string ready for output */
231char *ebt_mask_to_dotted(uint32_t mask)
232{
233 int i;
234 static char buf[20];
235 uint32_t maskaddr, bits;
236
237 maskaddr = ntohl(mask);
238
239 /* don't print /32 */
240 if (mask == 0xFFFFFFFFL) {
241 *buf = '\0';
242 return buf;
243 }
244
245 i = 32;
246 bits = 0xFFFFFFFEL; /* case 0xFFFFFFFF has just been dealt with */
247 while (--i >= 0 && maskaddr != bits)
248 bits <<= 1;
249
250 if (i > 0)
251 sprintf(buf, "/%d", i);
252 else if (!i)
253 *buf = '\0';
254 else
255 /* mask was not a decent combination of 1's and 0's */
256 sprintf(buf, "/%d.%d.%d.%d", ((unsigned char *)&mask)[0],
257 ((unsigned char *)&mask)[1], ((unsigned char *)&mask)[2],
258 ((unsigned char *)&mask)[3]);
259
260 return buf;
261}