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@gmail.com>
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/ipfw.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(ipfw_insn
**cmd
, int *ac
, char **av
[])
145 NEED(*ac
, 3, "mac dst src");
147 (*cmd
)->opcode
= O_LAYER2_MAC
;
148 (*cmd
)->module
= MODULE_LAYER2_ID
;
149 (*cmd
)->len
= ((*cmd
)->len
&(F_NOT
|F_OR
))|F_INSN_SIZE(ipfw_insn_mac
);
150 ipfw_insn_mac
*mac
= (ipfw_insn_mac
*)(*cmd
);
151 get_mac_addr_mask(**av
, mac
->addr
, mac
->mask
); /* dst */
153 get_mac_addr_mask(**av
, &(mac
->addr
[6]), &(mac
->mask
[6])); /* src */
158 show_layer2(ipfw_insn
*cmd
, int show_or
)
164 show_mac(ipfw_insn
*cmd
, int show_or
)
166 ipfw_insn_mac
*m
= (ipfw_insn_mac
*)cmd
;
168 print_mac( m
->addr
, m
->mask
);
169 print_mac( m
->addr
+ 6, m
->mask
+ 6);
173 load_module(register_func function
, register_keyword keyword
)
175 keyword(MODULE_LAYER2_ID
, O_LAYER2_LAYER2
, "layer2", FILTER
);
176 function(MODULE_LAYER2_ID
, O_LAYER2_LAYER2
,
177 (parser_func
)parse_layer2
, (shower_func
)show_layer2
);
179 keyword(MODULE_LAYER2_ID
, O_LAYER2_MAC
, "mac", FILTER
);
180 function(MODULE_LAYER2_ID
, O_LAYER2_MAC
,
181 (parser_func
)parse_mac
,(shower_func
)show_mac
);