2 * Copyright (c) 2014 The DragonFly Project. All rights reserved.
4 * This code is derived from software contributed to The DragonFly Project
5 * by Bill Yuan <bycn82@dragonflybsd.org>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
17 * 3. Neither the name of The DragonFly Project nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific, prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
43 #include <net/route.h>
45 #include <netinet/in.h>
47 #include "../../../sys/net/ipfw3/ip_fw3.h"
48 #include "../../../sbin/ipfw3/ipfw3.h"
49 #include "ipfw3_layer2.h"
52 * Returns the number of bits set (from left) in a contiguous bitmask,
53 * or -1 if the mask is not contiguous.
54 * XXX this needs a proper fix.
55 * This effectively works on masks in big-endian (network) format.
56 * when compiled on little endian architectures.
58 * First bit is bit 7 of the first byte -- note, for MAC addresses,
59 * the first bit on the wire is bit 0 of the first byte.
60 * len is the max length in bits.
63 contigmask(u_char *p, int len)
66 for (i = 0; i < len ; i++) {
67 if ( (p[i/8] & (1 << (7 - (i%8)))) == 0) /* first bit unset */
70 for (n = i + 1; n < len; n++) {
71 if ( (p[n/8] & (1 << (7 - (n%8)))) != 0)
72 return -1; /* mask not contiguous */
78 * prints a MAC address/mask pair
81 print_mac(u_char *addr, u_char *mask)
83 int l = contigmask(mask, 48);
88 printf(" %02x:%02x:%02x:%02x:%02x:%02x",
89 addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
91 printf("&%02x:%02x:%02x:%02x:%02x:%02x",
92 mask[0], mask[1], mask[2],
93 mask[3], mask[4], mask[5]);
101 get_mac_addr_mask(char *p, u_char *addr, u_char *mask)
105 for (i = 0; i < 6; i++)
106 addr[i] = mask[i] = 0;
107 if (!strcmp(p, "any"))
110 for (i = 0; *p && i < 6; i++, p++) {
111 addr[i] = strtol(p, &p, 16);
112 if (*p != ':') /* we start with the mask */
115 if (*p == '/') { /* mask len */
116 l = strtol(p + 1, &p, 0);
117 for (i = 0; l > 0; l -= 8, i++)
118 mask[i] = (l >=8) ? 0xff : (~0) << (8-l);
119 } else if (*p == '&') { /* mask */
120 for (i = 0, p++; *p && i < 6; i++, p++) {
121 mask[i] = strtol(p, &p, 16);
125 } else if (*p == '\0') {
126 for (i = 0; i < 6; i++)
129 for (i = 0; i < 6; i++)
134 parse_layer2(ipfw_insn **cmd, int *ac, char **av[])
136 (*cmd)->opcode = O_LAYER2_LAYER2;
137 (*cmd)->module = MODULE_LAYER2_ID;
138 (*cmd)->len = ((*cmd)->len&(F_NOT|F_OR))|LEN_OF_IPFWINSN;
143 parse_mac_from(ipfw_insn **cmd, int *ac, char **av[])
145 NEED(*ac, 2, "mac-from src");
147 if (strcmp(**av, "table") == 0) {
148 NEED(*ac, 2, "mac-from table N");
150 (*cmd)->opcode = O_LAYER2_MAC_SRC_LOOKUP;
151 (*cmd)->module = MODULE_LAYER2_ID;
152 (*cmd)->len = (*cmd)->len | F_INSN_SIZE(ipfw_insn);
153 (*cmd)->arg1 = strtoul(**av, NULL, 10);
156 (*cmd)->opcode = O_LAYER2_MAC_SRC;
157 (*cmd)->module = MODULE_LAYER2_ID;
158 (*cmd)->len = (*cmd)->len | F_INSN_SIZE(ipfw_insn_mac);
159 ipfw_insn_mac *mac = (ipfw_insn_mac *)(*cmd);
161 get_mac_addr_mask(**av, &(mac->addr[6]), &(mac->mask[6]));
167 parse_mac_to(ipfw_insn **cmd, int *ac, char **av[])
169 NEED(*ac, 2, "mac-to dst");
171 if (strcmp(**av, "table") == 0) {
172 NEED(*ac, 2, "mac-to table N");
174 (*cmd)->opcode = O_LAYER2_MAC_DST_LOOKUP;
175 (*cmd)->module = MODULE_LAYER2_ID;
176 (*cmd)->len = (*cmd)->len | F_INSN_SIZE(ipfw_insn);
177 (*cmd)->arg1 = strtoul(**av, NULL, 10);
180 (*cmd)->opcode = O_LAYER2_MAC_DST;
181 (*cmd)->module = MODULE_LAYER2_ID;
182 (*cmd)->len = (*cmd)->len | F_INSN_SIZE(ipfw_insn_mac);
183 ipfw_insn_mac *mac = (ipfw_insn_mac *)(*cmd);
185 get_mac_addr_mask(**av, mac->addr, mac->mask);
192 parse_mac(ipfw_insn **cmd, int *ac, char **av[])
194 NEED(*ac, 3, "mac dst src");
196 (*cmd)->opcode = O_LAYER2_MAC;
197 (*cmd)->module = MODULE_LAYER2_ID;
198 (*cmd)->len = ((*cmd)->len&(F_NOT|F_OR))|F_INSN_SIZE(ipfw_insn_mac);
199 ipfw_insn_mac *mac = (ipfw_insn_mac *)(*cmd);
200 get_mac_addr_mask(**av, mac->addr, mac->mask); /* dst */
202 get_mac_addr_mask(**av, &(mac->addr[6]), &(mac->mask[6])); /* src */
207 show_layer2(ipfw_insn *cmd, int show_or)
213 show_mac(ipfw_insn *cmd, int show_or)
215 ipfw_insn_mac *m = (ipfw_insn_mac *)cmd;
217 print_mac( m->addr, m->mask);
218 print_mac( m->addr + 6, m->mask + 6);
222 show_mac_from(ipfw_insn *cmd, int show_or)
224 ipfw_insn_mac *m = (ipfw_insn_mac *)cmd;
226 print_mac( m->addr + 6, m->mask + 6);
230 show_mac_from_lookup(ipfw_insn *cmd, int show_or)
232 printf(" mac-from table %d", cmd->arg1);
236 show_mac_to(ipfw_insn *cmd, int show_or)
238 ipfw_insn_mac *m = (ipfw_insn_mac *)cmd;
240 print_mac( m->addr, m->mask);
244 show_mac_to_lookup(ipfw_insn *cmd, int show_or)
246 printf(" mac-to table %d", cmd->arg1);
250 load_module(register_func function, register_keyword keyword)
252 keyword(MODULE_LAYER2_ID, O_LAYER2_LAYER2, "layer2", FILTER);
253 function(MODULE_LAYER2_ID, O_LAYER2_LAYER2,
254 (parser_func)parse_layer2, (shower_func)show_layer2);
256 keyword(MODULE_LAYER2_ID, O_LAYER2_MAC, "mac", FILTER);
257 function(MODULE_LAYER2_ID, O_LAYER2_MAC,
258 (parser_func)parse_mac,(shower_func)show_mac);
259 keyword(MODULE_LAYER2_ID, O_LAYER2_MAC_SRC, "mac-from", FROM);
260 function(MODULE_LAYER2_ID, O_LAYER2_MAC_SRC,
261 (parser_func)parse_mac_from,(shower_func)show_mac_from);
262 keyword(MODULE_LAYER2_ID, O_LAYER2_MAC_SRC_LOOKUP,
263 "mac-from-[table]", FROM);
264 function(MODULE_LAYER2_ID, O_LAYER2_MAC_SRC_LOOKUP,
265 (parser_func)parse_mac_from,
266 (shower_func)show_mac_from_lookup);
268 keyword(MODULE_LAYER2_ID, O_LAYER2_MAC_DST, "mac-to", TO);
269 function(MODULE_LAYER2_ID, O_LAYER2_MAC_DST,
270 (parser_func)parse_mac_to,(shower_func)show_mac_to);
271 keyword(MODULE_LAYER2_ID, O_LAYER2_MAC_DST_LOOKUP,
272 "mac-to-[table]", TO);
273 function(MODULE_LAYER2_ID, O_LAYER2_MAC_DST_LOOKUP,
274 (parser_func)parse_mac_to,
275 (shower_func)show_mac_to_lookup);