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
35 #include <sys/param.h>
37 #include <sys/socket.h>
38 #include <sys/sockio.h>
39 #include <sys/sysctl.h>
43 #include <arpa/inet.h>
61 #include <netinet/in.h>
62 #include <netinet/in_systm.h>
63 #include <netinet/ip.h>
64 #include <netinet/ip_icmp.h>
65 #include <netinet/tcp.h>
67 #include <net/if_dl.h>
68 #include <net/route.h>
69 #include <net/ethernet.h>
71 #include <net/ipfw3/ip_fw3.h>
72 #include <net/ipfw3_basic/ip_fw3_table.h>
73 #include <net/ipfw3_basic/ip_fw3_sync.h>
74 #include <net/ipfw3_basic/ip_fw3_basic.h>
75 #include <net/ipfw3_nat/ip_fw3_nat.h>
76 #include <net/dummynet3/ip_dummynet3.h>
79 #include "ipfw3table.h"
82 lookup_host (char *host
, struct in_addr
*ipaddr
)
86 if (!inet_aton(host
, ipaddr
)) {
87 if ((he
= gethostbyname(host
)) == NULL
)
89 *ipaddr
= *(struct in_addr
*)he
->h_addr_list
[0];
96 table_append(int ac
, char *av
[])
98 struct ipfw_ioc_table tbl
;
106 errx(EX_USAGE
, "table id `%s' invalid", *av
);
108 if (tbl
.id
< 0 || tbl
.id
> IPFW_TABLES_MAX
- 1)
109 errx(EX_USAGE
, "table id `%d' invalid", tbl
.id
);
112 if (strcmp(*av
, "ip") == 0)
114 else if (strcmp(*av
, "mac") == 0)
117 errx(EX_USAGE
, "table type `%s' not supported", *av
);
120 if (tbl
.type
== 1) { /* table type ipv4 */
121 struct ipfw_ioc_table_ip_entry ip_ent
;
123 errx(EX_USAGE
, "IP address required");
125 p
= strchr(*av
, '/');
128 ip_ent
.masklen
= atoi(p
);
129 if (ip_ent
.masklen
> 32)
130 errx(EX_DATAERR
, "bad width ``%s''", p
);
135 if (lookup_host(*av
, (struct in_addr
*)&ip_ent
.addr
) != 0)
136 errx(EX_NOHOST
, "hostname ``%s'' unknown", *av
);
138 tbl
.ip_ent
[0] = ip_ent
;
139 size
= sizeof(tbl
) + sizeof(ip_ent
);
140 } else if (tbl
.type
== 2) { /* table type mac */
141 struct ipfw_ioc_table_mac_entry mac_ent
;
143 errx(EX_USAGE
, "MAC address required");
145 mac_ent
.addr
= *ether_aton(*av
);
146 tbl
.mac_ent
[0] = mac_ent
;
147 size
= sizeof(tbl
) + sizeof(mac_ent
);
149 if (do_set_x(IP_FW_TABLE_APPEND
, &tbl
, size
) < 0 )
150 errx(EX_USAGE
, "do_set_x(IP_FW_TABLE_APPEND) "
151 "table `%d' append `%s' failed", tbl
.id
, *av
);
155 table_remove(int ac
, char *av
[])
157 struct ipfw_ioc_table tbl
;
158 struct ipfw_ioc_table_ip_entry ip_ent
;
166 errx(EX_USAGE
, "table id `%s' invalid", *av
);
168 if (tbl
.id
< 0 || tbl
.id
> IPFW_TABLES_MAX
- 1)
169 errx(EX_USAGE
, "table id `%d' invalid", tbl
.id
);
172 if (strcmp(*av
, "ip") == 0)
174 else if (strcmp(*av
, "mac") == 0)
177 errx(EX_USAGE
, "table type `%s' not supported", *av
);
181 errx(EX_USAGE
, "IP address required");
182 p
= strchr(*av
, '/');
185 ip_ent
.masklen
= atoi(p
);
186 if (ip_ent
.masklen
> 32)
187 errx(EX_DATAERR
, "bad width ``%s''", p
);
192 if (lookup_host(*av
, (struct in_addr
*)&ip_ent
.addr
) != 0)
193 errx(EX_NOHOST
, "hostname ``%s'' unknown", *av
);
195 tbl
.ip_ent
[0] = ip_ent
;
196 size
= sizeof(tbl
) + sizeof(ip_ent
);
197 if (do_set_x(IP_FW_TABLE_REMOVE
, &tbl
, size
) < 0 ) {
198 errx(EX_USAGE
, "do_set_x(IP_FW_TABLE_REMOVE) "
199 "table `%d' append `%s' failed", tbl
.id
, *av
);
204 table_flush(int ac
, char *av
[])
206 struct ipfw_ioc_table ioc_table
;
207 struct ipfw_ioc_table
*t
= &ioc_table
;
212 if (t
->id
< 0 || t
->id
> IPFW_TABLES_MAX
- 1)
213 errx(EX_USAGE
, "table id `%d' invalid", t
->id
);
215 errx(EX_USAGE
, "table id `%s' invalid", *av
);
217 if (do_set_x(IP_FW_TABLE_FLUSH
, t
, sizeof(struct ipfw_ioc_table
)) < 0 )
218 errx(EX_USAGE
, "do_set_x(IP_FW_TABLE_FLUSH) "
219 "table `%s' flush failed", *av
);
223 table_list(int ac
, char *av
[])
225 struct ipfw_ioc_table
*ioc_table
;
226 int i
, count
, nbytes
, nalloc
= 1024;
229 if (strcmp(*av
, "list") == 0) {
231 while (nbytes
>= nalloc
) {
232 nalloc
= nalloc
* 2 ;
234 if ((data
= realloc(data
, nbytes
)) == NULL
)
235 err(EX_OSERR
, "realloc");
236 if (do_get_x(IP_FW_TABLE_LIST
, data
, &nbytes
) < 0)
237 err(EX_OSERR
, "do_get_x(IP_FW_TABLE_LIST)");
239 ioc_table
= (struct ipfw_ioc_table
*)data
;
240 count
= nbytes
/ sizeof(struct ipfw_ioc_table
);
241 for (i
= 0; i
< count
; i
++, ioc_table
++) {
242 if (ioc_table
->type
> 0) {
243 printf("table %d",ioc_table
->id
);
244 if (ioc_table
->type
== 1)
246 else if (ioc_table
->type
== 2)
248 printf(" count %d",ioc_table
->count
);
249 if (strlen(ioc_table
->name
) > 0)
250 printf(" name %s",ioc_table
->name
);
256 errx(EX_USAGE
, "ipfw3 table `%s' delete invalid", *av
);
261 table_print(struct ipfw_ioc_table
* tbl
)
265 errx(EX_USAGE
, "table %d is not in use", tbl
->id
);
267 printf("table %d", tbl
->id
);
270 else if (tbl
->type
== 2)
273 printf(" count %d", tbl
->count
);
274 if (strlen(tbl
->name
) > 0)
275 printf(" name %s", tbl
->name
);
279 if (tbl
->type
== 1) {
280 struct ipfw_ioc_table_ip_entry
*ip_ent
;
281 ip_ent
= tbl
->ip_ent
;
282 for (i
= 0; i
< tbl
->count
; i
++) {
283 printf("%s", inet_ntoa(*(struct in_addr
*)&ip_ent
->addr
));
284 printf("/%d ", ip_ent
->masklen
);
288 } else if (tbl
->type
== 2) {
289 struct ipfw_ioc_table_mac_entry
*mac_ent
;
290 mac_ent
= tbl
->mac_ent
;
291 for (i
= 0; i
< tbl
->count
; i
++) {
292 printf("%s", ether_ntoa(&mac_ent
->addr
));
300 table_show(int ac
, char *av
[])
302 int nbytes
, nalloc
= 1024;
307 while (nbytes
>= nalloc
) {
308 nalloc
= nalloc
* 2 + 256;
311 if ((data
= malloc(nbytes
)) == NULL
) {
312 err(EX_OSERR
, "malloc");
314 } else if ((data
= realloc(data
, nbytes
)) == NULL
) {
315 err(EX_OSERR
, "realloc");
317 /* store table id in the header of data */
318 int *head
= (int *)data
;
320 if (*head
< 0 || *head
> IPFW_TABLES_MAX
- 1)
321 errx(EX_USAGE
, "table id `%d' invalid", *head
);
322 if (do_get_x(IP_FW_TABLE_SHOW
, data
, &nbytes
) < 0)
323 err(EX_OSERR
, "do_get_x(IP_FW_TABLE_LIST)");
324 struct ipfw_ioc_table
*tbl
;
325 tbl
= (struct ipfw_ioc_table
*)data
;
329 errx(EX_USAGE
, "ipfw3 table `%s' show invalid", *av
);
334 table_create(int ac
, char *av
[])
336 struct ipfw_ioc_table ioc_table
;
337 struct ipfw_ioc_table
*t
= &ioc_table
;
341 errx(EX_USAGE
, "table parameters invalid");
344 if (t
->id
< 0 || t
->id
> IPFW_TABLES_MAX
- 1)
345 errx(EX_USAGE
, "table id `%d' invalid", t
->id
);
347 errx(EX_USAGE
, "table id `%s' invalid", *av
);
350 if (strcmp(*av
, "ip") == 0)
352 else if (strcmp(*av
, "mac") == 0)
355 errx(EX_USAGE
, "table type `%s' not supported", *av
);
358 memset(t
->name
, 0, IPFW_TABLE_NAME_LEN
);
359 if (ac
== 2 && strcmp(*av
, "name") == 0) {
361 if (strlen(*av
) < IPFW_TABLE_NAME_LEN
) {
362 strncpy(t
->name
, *av
, strlen(*av
));
364 errx(EX_USAGE
, "table name `%s' too long", *av
);
366 } else if (ac
== 1) {
367 errx(EX_USAGE
, "table `%s' invalid", *av
);
370 if (do_set_x(IP_FW_TABLE_CREATE
, t
, sizeof(struct ipfw_ioc_table
)) < 0)
371 errx(EX_USAGE
, "do_set_x(IP_FW_TABLE_CREATE) "
372 "table `%d' in use", t
->id
);
376 table_delete(int ac
, char *av
[])
378 struct ipfw_ioc_table ioc_table
;
379 struct ipfw_ioc_table
*t
= &ioc_table
;
384 if (t
->id
< 0 || t
->id
> IPFW_TABLES_MAX
- 1)
385 errx(EX_USAGE
, "table id `%d' invalid", t
->id
);
387 errx(EX_USAGE
, "table id `%s' invalid", *av
);
389 if (t
->id
< 0 || t
->id
> IPFW_TABLES_MAX
- 1)
390 errx(EX_USAGE
, "table id `%d' invalid", t
->id
);
392 if (do_set_x(IP_FW_TABLE_DELETE
, t
, sizeof(struct ipfw_ioc_table
)) < 0)
393 errx(EX_USAGE
, "do_set_x(IP_FW_TABLE_DELETE) "
394 "table `%s' delete failed", *av
);
398 table_test(int ac
, char *av
[])
400 struct ipfw_ioc_table tbl
;
407 errx(EX_USAGE
, "table id `%s' invalid", *av
);
409 if (tbl
.id
< 0 || tbl
.id
> IPFW_TABLES_MAX
- 1)
410 errx(EX_USAGE
, "table id `%d' invalid", tbl
.id
);
413 if (strcmp(*av
, "ip") == 0)
415 else if (strcmp(*av
, "mac") == 0)
418 errx(EX_USAGE
, "table type `%s' not supported", *av
);
421 if (tbl
.type
== 1) { /* table type ipv4 */
422 struct ipfw_ioc_table_ip_entry ip_ent
;
423 if (lookup_host(*av
, (struct in_addr
*)&ip_ent
.addr
) != 0)
424 errx(EX_NOHOST
, "hostname ``%s'' unknown", *av
);
426 tbl
.ip_ent
[0] = ip_ent
;
427 size
= sizeof(tbl
) + sizeof(ip_ent
);
428 } else if (tbl
.type
== 2) { /* table type mac */
429 struct ipfw_ioc_table_mac_entry mac_ent
;
431 errx(EX_USAGE
, "MAC address required");
433 mac_ent
.addr
= *ether_aton(*av
);
434 tbl
.mac_ent
[0] = mac_ent
;
435 size
= sizeof(tbl
) + sizeof(mac_ent
);
437 if (do_set_x(IP_FW_TABLE_TEST
, &tbl
, size
) < 0 ) {
438 printf("NO, %s not exists in table %d\n", *av
, tbl
.id
);
440 printf("YES, %s exists in table %d\n", *av
, tbl
.id
);
445 table_rename(int ac
, char *av
[])
447 struct ipfw_ioc_table tbl
;
450 bzero(&tbl
, sizeof(tbl
));
455 errx(EX_USAGE
, "table id `%s' invalid", *av
);
457 if (tbl
.id
< 0 || tbl
.id
> IPFW_TABLES_MAX
- 1)
458 errx(EX_USAGE
, "table id `%d' invalid", tbl
.id
);
461 strlcpy(tbl
.name
, *av
, IPFW_TABLE_NAME_LEN
);
463 if (do_set_x(IP_FW_TABLE_RENAME
, &tbl
, size
) < 0 )
464 errx(EX_USAGE
, "do_set_x(IP_FW_TABLE_RENAME) "
465 "table `%d' not in use", tbl
.id
);
469 table_main(int ac
, char **av
)
471 if (!strncmp(*av
, "append", strlen(*av
))) {
472 table_append(ac
, av
);
473 } else if (!strncmp(*av
, "remove", strlen(*av
))) {
474 table_remove(ac
, av
);
475 } else if (!strncmp(*av
, "flush", strlen(*av
))) {
477 } else if (!strncmp(*av
, "list", strlen(*av
))) {
479 } else if (!strncmp(*av
, "show", strlen(*av
))) {
481 } else if (!strncmp(*av
, "type", strlen(*av
))) {
482 table_create(ac
, av
);
483 } else if (!strncmp(*av
, "delete", strlen(*av
))) {
484 table_delete(ac
, av
);
485 } else if (!strncmp(*av
, "test", strlen(*av
))) {
487 } else if (!strncmp(*av
, "name", strlen(*av
))) {
488 table_rename(ac
, av
);
490 errx(EX_USAGE
, "bad ipfw table command `%s'", *av
);