blob: a36062ed2d3fa3606ed85ea827927d41296b6d67 [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{
Bart De Schuymer620443a2004-11-14 13:22:29 +0000154 if (!option)
155 return ebt_invert;
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000156 if (strcmp(option, "!") == 0) {
157 if (ebt_invert == 1)
Bart De Schuymer64182a32004-01-21 20:39:54 +0000158 ebt_print_error("double use of '!' not allowed");
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000159 optind++;
160 ebt_invert = 1;
161 return 1;
162 }
163 return ebt_invert;
164}
165
Bart De Schuymer55d44132004-02-23 20:55:24 +0000166/*
167 * Make sure the same option wasn't specified twice. This is used
168 * in the parse functions of the extensions and ebtables.c.
169 */
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000170void ebt_check_option(unsigned int *flags, unsigned int mask)
171{
172 if (*flags & mask)
Bart De Schuymer64182a32004-01-21 20:39:54 +0000173 ebt_print_error("Multiple use of same option not allowed");
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000174 *flags |= mask;
175}
176
Bart De Schuymer55d44132004-02-23 20:55:24 +0000177/*
178 * put the ip string into 4 bytes
179 */
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000180static int undot_ip(char *ip, unsigned char *ip2)
181{
182 char *p, *q, *end;
183 long int onebyte;
184 int i;
185 char buf[20];
186
187 strncpy(buf, ip, sizeof(buf) - 1);
188
189 p = buf;
190 for (i = 0; i < 3; i++) {
191 if ((q = strchr(p, '.')) == NULL)
192 return -1;
193 *q = '\0';
194 onebyte = strtol(p, &end, 10);
195 if (*end != '\0' || onebyte > 255 || onebyte < 0)
196 return -1;
197 ip2[i] = (unsigned char)onebyte;
198 p = q + 1;
199 }
200
201 onebyte = strtol(p, &end, 10);
202 if (*end != '\0' || onebyte > 255 || onebyte < 0)
203 return -1;
204 ip2[3] = (unsigned char)onebyte;
205
206 return 0;
207}
208
Bart De Schuymer55d44132004-02-23 20:55:24 +0000209/*
210 * put the mask into 4 bytes
211 */
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000212static int ip_mask(char *mask, unsigned char *mask2)
213{
214 char *end;
215 long int bits;
216 uint32_t mask22;
217
218 if (undot_ip(mask, mask2)) {
219 /* not the /a.b.c.e format, maybe the /x format */
220 bits = strtol(mask, &end, 10);
221 if (*end != '\0' || bits > 32 || bits < 0)
222 return -1;
223 if (bits != 0) {
224 mask22 = htonl(0xFFFFFFFF << (32 - bits));
225 memcpy(mask2, &mask22, 4);
226 } else {
227 mask22 = 0xFFFFFFFF;
228 memcpy(mask2, &mask22, 4);
229 }
230 }
231 return 0;
232}
233
Bart De Schuymer55d44132004-02-23 20:55:24 +0000234/*
235 * set the ip mask and ip address
236 */
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000237void ebt_parse_ip_address(char *address, uint32_t *addr, uint32_t *msk)
238{
239 char *p;
240
241 /* first the mask */
242 if ((p = strrchr(address, '/')) != NULL) {
243 *p = '\0';
244 if (ip_mask(p + 1, (unsigned char *)msk))
Bart De Schuymer64182a32004-01-21 20:39:54 +0000245 ebt_print_error("Problem with the IP mask");
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000246 } else
247 *msk = 0xFFFFFFFF;
248
249 if (undot_ip(address, (unsigned char *)addr))
Bart De Schuymer64182a32004-01-21 20:39:54 +0000250 ebt_print_error("Problem with the IP address");
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000251 *addr = *addr & *msk;
252}
253
Bart De Schuymer55d44132004-02-23 20:55:24 +0000254/*
255 * transform the ip mask into a string ready for output
256 */
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000257char *ebt_mask_to_dotted(uint32_t mask)
258{
259 int i;
260 static char buf[20];
261 uint32_t maskaddr, bits;
262
263 maskaddr = ntohl(mask);
264
265 /* don't print /32 */
266 if (mask == 0xFFFFFFFFL) {
267 *buf = '\0';
268 return buf;
269 }
270
271 i = 32;
272 bits = 0xFFFFFFFEL; /* case 0xFFFFFFFF has just been dealt with */
273 while (--i >= 0 && maskaddr != bits)
274 bits <<= 1;
275
276 if (i > 0)
277 sprintf(buf, "/%d", i);
278 else if (!i)
279 *buf = '\0';
280 else
281 /* mask was not a decent combination of 1's and 0's */
282 sprintf(buf, "/%d.%d.%d.%d", ((unsigned char *)&mask)[0],
283 ((unsigned char *)&mask)[1], ((unsigned char *)&mask)[2],
284 ((unsigned char *)&mask)[3]);
285
286 return buf;
287}