2 * Copyright (c) 2014 - 2018 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 <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
|= 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
|= 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
|= 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
|= 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
|= 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
|= 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
;
220 print_mac( m
->addr
, m
->mask
);
221 print_mac( m
->addr
+ 6, m
->mask
+ 6);
225 show_mac_from(ipfw_insn
*cmd
, int show_or
)
227 ipfw_insn_mac
*m
= (ipfw_insn_mac
*)cmd
;
232 print_mac( m
->addr
+ 6, m
->mask
+ 6);
236 show_mac_from_lookup(ipfw_insn
*cmd
, int show_or
)
238 printf(" mac-from table %d", cmd
->arg1
);
242 show_mac_to(ipfw_insn
*cmd
, int show_or
)
244 ipfw_insn_mac
*m
= (ipfw_insn_mac
*)cmd
;
249 print_mac( m
->addr
, m
->mask
);
253 show_mac_to_lookup(ipfw_insn
*cmd
, int show_or
)
255 printf(" mac-to table %d", cmd
->arg1
);
259 load_module(register_func function
, register_keyword keyword
)
261 keyword(MODULE_LAYER2_ID
, O_LAYER2_LAYER2
, "layer2", FILTER
);
262 function(MODULE_LAYER2_ID
, O_LAYER2_LAYER2
,
263 (parser_func
)parse_layer2
, (shower_func
)show_layer2
);
265 keyword(MODULE_LAYER2_ID
, O_LAYER2_MAC
, "mac", FILTER
);
266 function(MODULE_LAYER2_ID
, O_LAYER2_MAC
,
267 (parser_func
)parse_mac
,(shower_func
)show_mac
);
268 keyword(MODULE_LAYER2_ID
, O_LAYER2_MAC_SRC
, "mac-from", FROM
);
269 function(MODULE_LAYER2_ID
, O_LAYER2_MAC_SRC
,
270 (parser_func
)parse_mac_from
,(shower_func
)show_mac_from
);
271 keyword(MODULE_LAYER2_ID
, O_LAYER2_MAC_SRC_LOOKUP
,
272 "mac-from-[table]", FROM
);
273 function(MODULE_LAYER2_ID
, O_LAYER2_MAC_SRC_LOOKUP
,
274 (parser_func
)parse_mac_from
,
275 (shower_func
)show_mac_from_lookup
);
277 keyword(MODULE_LAYER2_ID
, O_LAYER2_MAC_DST
, "mac-to", TO
);
278 function(MODULE_LAYER2_ID
, O_LAYER2_MAC_DST
,
279 (parser_func
)parse_mac_to
,(shower_func
)show_mac_to
);
280 keyword(MODULE_LAYER2_ID
, O_LAYER2_MAC_DST_LOOKUP
,
281 "mac-to-[table]", TO
);
282 function(MODULE_LAYER2_ID
, O_LAYER2_MAC_DST_LOOKUP
,
283 (parser_func
)parse_mac_to
,
284 (shower_func
)show_mac_to_lookup
);