ichwd - Fix typo in TCO2_CNT register #define.
[dragonfly.git] / sbin / ipfw3 / ipfw3table.c
blob067782cfaf0d353a513ad5a67425df3e6534dcbb
1 /*
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
9 * are met:
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
16 * distribution.
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
32 * SUCH DAMAGE.
35 #include <sys/param.h>
36 #include <sys/mbuf.h>
37 #include <sys/socket.h>
38 #include <sys/sockio.h>
39 #include <sys/sysctl.h>
40 #include <sys/time.h>
41 #include <sys/wait.h>
43 #include <arpa/inet.h>
44 #include <ctype.h>
45 #include <dlfcn.h>
46 #include <err.h>
47 #include <errno.h>
48 #include <grp.h>
49 #include <limits.h>
50 #include <netdb.h>
51 #include <pwd.h>
52 #include <sysexits.h>
53 #include <signal.h>
54 #include <stdio.h>
55 #include <stdlib.h>
56 #include <stdarg.h>
57 #include <string.h>
58 #include <timeconv.h>
59 #include <unistd.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>
66 #include <net/if.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>
78 #include "ipfw3.h"
79 #include "ipfw3table.h"
81 int
82 lookup_host (char *host, struct in_addr *ipaddr)
84 struct hostent *he;
86 if (!inet_aton(host, ipaddr)) {
87 if ((he = gethostbyname(host)) == NULL)
88 return(-1);
89 *ipaddr = *(struct in_addr *)he->h_addr_list[0];
91 return(0);
95 void
96 table_append(int ac, char *av[])
98 struct ipfw_ioc_table tbl;
99 char *p;
100 int size;
102 NEXT_ARG;
103 if (isdigit(**av))
104 tbl.id = atoi(*av);
105 else
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);
111 NEXT_ARG;
112 if (strcmp(*av, "ip") == 0)
113 tbl.type = 1;
114 else if (strcmp(*av, "mac") == 0)
115 tbl.type = 2;
116 else
117 errx(EX_USAGE, "table type `%s' not supported", *av);
119 NEXT_ARG;
120 if (tbl.type == 1) { /* table type ipv4 */
121 struct ipfw_ioc_table_ip_entry ip_ent;
122 if (!ac)
123 errx(EX_USAGE, "IP address required");
125 p = strchr(*av, '/');
126 if (p) {
127 *p++ = '\0';
128 ip_ent.masklen = atoi(p);
129 if (ip_ent.masklen > 32)
130 errx(EX_DATAERR, "bad width ``%s''", p);
131 } else {
132 ip_ent.masklen = 32;
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;
142 if (!ac)
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);
154 void
155 table_remove(int ac, char *av[])
157 struct ipfw_ioc_table tbl;
158 struct ipfw_ioc_table_ip_entry ip_ent;
159 char *p;
160 int size;
162 NEXT_ARG;
163 if (isdigit(**av))
164 tbl.id = atoi(*av);
165 else
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);
171 NEXT_ARG;
172 if (strcmp(*av, "ip") == 0)
173 tbl.type = 1;
174 else if (strcmp(*av, "mac") == 0)
175 tbl.type = 2;
176 else
177 errx(EX_USAGE, "table type `%s' not supported", *av);
179 NEXT_ARG;
180 if (!ac)
181 errx(EX_USAGE, "IP address required");
182 p = strchr(*av, '/');
183 if (p) {
184 *p++ = '\0';
185 ip_ent.masklen = atoi(p);
186 if (ip_ent.masklen > 32)
187 errx(EX_DATAERR, "bad width ``%s''", p);
188 } else {
189 ip_ent.masklen = 32;
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);
203 void
204 table_flush(int ac, char *av[])
206 struct ipfw_ioc_table ioc_table;
207 struct ipfw_ioc_table *t = &ioc_table;
209 NEXT_ARG;
210 if (isdigit(**av)) {
211 t->id = atoi(*av);
212 if (t->id < 0 || t->id > IPFW_TABLES_MAX - 1)
213 errx(EX_USAGE, "table id `%d' invalid", t->id);
214 } else {
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);
222 void
223 table_list(int ac, char *av[])
225 struct ipfw_ioc_table *ioc_table;
226 int i, count, nbytes, nalloc = 1024;
227 void *data = NULL;
228 NEXT_ARG;
229 if (strcmp(*av, "list") == 0) {
230 nbytes = nalloc;
231 while (nbytes >= nalloc) {
232 nalloc = nalloc * 2 ;
233 nbytes = nalloc;
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)
245 printf(" type ip");
246 else if (ioc_table->type == 2)
247 printf(" type mac");
248 printf(" count %d",ioc_table->count);
249 if (strlen(ioc_table->name) > 0)
250 printf(" name %s",ioc_table->name);
251 printf("\n");
255 } else {
256 errx(EX_USAGE, "ipfw3 table `%s' delete invalid", *av);
260 void
261 table_print(struct ipfw_ioc_table * tbl)
263 int i;
264 if (tbl->type == 0)
265 errx(EX_USAGE, "table %d is not in use", tbl->id);
267 printf("table %d", tbl->id);
268 if (tbl->type == 1)
269 printf(" type ip");
270 else if (tbl->type == 2)
271 printf(" type mac");
273 printf(" count %d", tbl->count);
274 if (strlen(tbl->name) > 0)
275 printf(" name %s", tbl->name);
277 printf("\n");
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);
285 printf("\n");
286 ip_ent++;
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));
293 printf("\n");
294 mac_ent++;
299 void
300 table_show(int ac, char *av[])
302 int nbytes, nalloc = 1024;
303 void *data = NULL;
304 NEXT_ARG;
305 if (isdigit(**av)) {
306 nbytes = nalloc;
307 while (nbytes >= nalloc) {
308 nalloc = nalloc * 2 + 256;
309 nbytes = nalloc;
310 if (data == NULL) {
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;
319 *head = atoi(*av);
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;
326 table_print(tbl);
328 } else {
329 errx(EX_USAGE, "ipfw3 table `%s' show invalid", *av);
333 void
334 table_create(int ac, char *av[])
336 struct ipfw_ioc_table ioc_table;
337 struct ipfw_ioc_table *t = &ioc_table;
339 NEXT_ARG;
340 if (ac < 2)
341 errx(EX_USAGE, "table parameters invalid");
342 if (isdigit(**av)) {
343 t->id = atoi(*av);
344 if (t->id < 0 || t->id > IPFW_TABLES_MAX - 1)
345 errx(EX_USAGE, "table id `%d' invalid", t->id);
346 } else {
347 errx(EX_USAGE, "table id `%s' invalid", *av);
349 NEXT_ARG;
350 if (strcmp(*av, "ip") == 0)
351 t->type = 1;
352 else if (strcmp(*av, "mac") == 0)
353 t->type = 2;
354 else
355 errx(EX_USAGE, "table type `%s' not supported", *av);
357 NEXT_ARG;
358 memset(t->name, 0, IPFW_TABLE_NAME_LEN);
359 if (ac == 2 && strcmp(*av, "name") == 0) {
360 NEXT_ARG;
361 if (strlen(*av) < IPFW_TABLE_NAME_LEN) {
362 strncpy(t->name, *av, strlen(*av));
363 } else {
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);
375 void
376 table_delete(int ac, char *av[])
378 struct ipfw_ioc_table ioc_table;
379 struct ipfw_ioc_table *t = &ioc_table;
381 NEXT_ARG;
382 if (isdigit(**av)) {
383 t->id = atoi(*av);
384 if (t->id < 0 || t->id > IPFW_TABLES_MAX - 1)
385 errx(EX_USAGE, "table id `%d' invalid", t->id);
386 } else {
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);
397 void
398 table_test(int ac, char *av[])
400 struct ipfw_ioc_table tbl;
401 int size;
403 NEXT_ARG;
404 if (isdigit(**av))
405 tbl.id = atoi(*av);
406 else
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);
412 NEXT_ARG;
413 if (strcmp(*av, "ip") == 0)
414 tbl.type = 1;
415 else if (strcmp(*av, "mac") == 0)
416 tbl.type = 2;
417 else
418 errx(EX_USAGE, "table type `%s' not supported", *av);
420 NEXT_ARG;
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;
430 if (!ac)
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);
439 } else {
440 printf("YES, %s exists in table %d\n", *av, tbl.id);
444 static void
445 table_rename(int ac, char *av[])
447 struct ipfw_ioc_table tbl;
448 int size;
450 bzero(&tbl, sizeof(tbl));
451 NEXT_ARG;
452 if (isdigit(**av))
453 tbl.id = atoi(*av);
454 else
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);
460 NEXT_ARG;
461 strlcpy(tbl.name, *av, IPFW_TABLE_NAME_LEN);
462 size = sizeof(tbl);
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);
468 void
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))) {
476 table_flush(ac, av);
477 } else if (!strncmp(*av, "list", strlen(*av))) {
478 table_list(ac, av);
479 } else if (!strncmp(*av, "show", strlen(*av))) {
480 table_show(ac, 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))) {
486 table_test(ac,av);
487 } else if (!strncmp(*av, "name", strlen(*av))) {
488 table_rename(ac, av);
489 } else {
490 errx(EX_USAGE, "bad ipfw table command `%s'", *av);