1 /* 2 * Copyright (c) 2014 The DragonFly Project. All rights reserved. 3 * 4 * This code is derived from software contributed to The DragonFly Project 5 * by Bill Yuan <bycn82@gmail.com> 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 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. 20 * 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. 33 */ 34 35 #include <ctype.h> 36 #include <err.h> 37 #include <errno.h> 38 #include <grp.h> 39 #include <limits.h> 40 #include <netdb.h> 41 #include <pwd.h> 42 #include <signal.h> 43 #include <stdio.h> 44 #include <stdlib.h> 45 #include <stdarg.h> 46 #include <string.h> 47 #include <sysexits.h> 48 #include <timeconv.h> 49 #include <unistd.h> 50 51 #include <netinet/in.h> 52 53 #include <arpa/inet.h> 54 #include <net/if.h> 55 #include <net/route.h> 56 #include <net/pfil.h> 57 58 #include "../../../sys/net/ipfw3/ip_fw3.h" 59 #include "../../../sbin/ipfw3/ipfw.h" 60 #include "ipfw3_basic.h" 61 62 63 #define IP_MASK_ALL 0xffffffff 64 /* 65 * we use IPPROTO_ETHERTYPE as a fake protocol id to call the print routines 66 * This is only used in this code. 67 */ 68 #define IPPROTO_ETHERTYPE 0x1000 69 70 71 struct char_int_map limit_types[] = { 72 { "src-addr", 1 }, 73 { "src-port", 2 }, 74 { "dst-addr", 3 }, 75 { "dst-port", 4 }, 76 { NULL, 0 } 77 }; 78 79 static struct char_int_map ether_types[] = { 80 { "ip", 0x0800 }, 81 { "ipv4", 0x0800 }, 82 { "ipv6", 0x86dd }, 83 { "arp", 0x0806 }, 84 { "rarp", 0x8035 }, 85 { "vlan", 0x8100 }, 86 { "loop", 0x9000 }, 87 { "trail", 0x1000 }, 88 { "pppoe_disc", 0x8863 }, 89 { "pppoe_sess", 0x8864 }, 90 { "ipx_8022", 0x00E0 }, 91 { "ipx_8023", 0x0000 }, 92 { "ipx_ii", 0x8137 }, 93 { "ipx_snap", 0x8137 }, 94 { "ipx", 0x8137 }, 95 { "ns", 0x0600 }, 96 { NULL, 0 } 97 }; 98 99 /** 100 * match_token takes a table and a string, returns the value associated 101 * with the string (0 meaning an error in most cases) 102 */ 103 static int 104 match_token(struct char_int_map *table, char *string) 105 { 106 while (table->key) { 107 if (strcmp(table->key, string) == 0) 108 return table->val; 109 110 table++; 111 } 112 return 0; 113 }; 114 115 static char * 116 match_token2(struct char_int_map *table, int val) 117 { 118 while (table->val) { 119 if (table->val == val) 120 return table->key; 121 122 table++; 123 } 124 return NULL; 125 }; 126 127 static void 128 fill_iface(ipfw_insn_if *cmd, char *arg) 129 { 130 cmd->name[0] = '\0'; 131 cmd->o.len |= F_INSN_SIZE(ipfw_insn_if); 132 133 /* Parse the interface or address */ 134 if (!strcmp(arg, "any")){ 135 cmd->o.len = 0; 136 } else if (!isdigit(*arg)) { 137 strlcpy(cmd->name, arg, sizeof(cmd->name)); 138 cmd->p.glob = strpbrk(arg, "*?[") != NULL ? 1 : 0; 139 } else if (!inet_aton(arg, &cmd->p.ip)) 140 errx(EX_DATAERR, "bad ip address ``%s''", arg); 141 } 142 143 static int 144 lookup_host (char *host, struct in_addr *ipaddr) 145 { 146 struct hostent *he; 147 148 if (!inet_aton(host, ipaddr)) { 149 if ((he = gethostbyname(host)) == NULL) 150 return(-1); 151 *ipaddr = *(struct in_addr *)he->h_addr_list[0]; 152 } 153 return(0); 154 } 155 156 /* 157 * Like strtol, but also translates service names into port numbers 158 * for some protocols. 159 * In particular: 160 * proto == -1 disables the protocol check; 161 * proto == IPPROTO_ETHERTYPE looks up an internal table 162 * proto == <some value in /etc/protocols> matches the values there. 163 * Returns *end == s in case the parameter is not found. 164 */ 165 static int 166 strtoport(char *s, char **end, int base, int proto) 167 { 168 char *p, *buf; 169 char *s1; 170 int i; 171 172 *end = s; /* default - not found */ 173 if ( *s == '\0') 174 return 0; /* not found */ 175 176 if (isdigit(*s)) 177 return strtol(s, end, base); 178 179 /* 180 * find separator. '\\' escapes the next char. 181 */ 182 for (s1 = s; *s1 && (isalnum(*s1) || *s1 == '\\') ; s1++) { 183 if (*s1 == '\\' && s1[1] != '\0') 184 s1++; 185 } 186 187 buf = malloc(s1 - s + 1); 188 if (buf == NULL) 189 return 0; 190 191 /* 192 * copy into a buffer skipping backslashes 193 */ 194 for (p = s, i = 0; p != s1 ; p++) 195 if ( *p != '\\') 196 buf[i++] = *p; 197 buf[i++] = '\0'; 198 199 if (proto == IPPROTO_ETHERTYPE) { 200 i = match_token(ether_types, buf); 201 free(buf); 202 if (i != -1) { /* found */ 203 *end = s1; 204 return i; 205 } 206 } else { 207 struct protoent *pe = NULL; 208 struct servent *se; 209 210 if (proto != 0) 211 pe = getprotobynumber(proto); 212 setservent(1); 213 se = getservbyname(buf, pe ? pe->p_name : NULL); 214 free(buf); 215 if (se != NULL) { 216 *end = s1; 217 return ntohs(se->s_port); 218 } 219 } 220 return 0; /* not found */ 221 } 222 223 static int 224 contigmask(u_char *p, int len) 225 { 226 int i, n; 227 for (i=0; i<len ; i++) { 228 if ( (p[i/8] & (1 << (7 - (i%8)))) == 0) /* first bit unset */ 229 break; 230 } 231 for (n=i+1; n < len; n++) { 232 if ( (p[n/8] & (1 << (7 - (n%8)))) != 0) 233 return -1; /* mask not contiguous */ 234 } 235 return i; 236 } 237 238 static void 239 fill_ip(ipfw_insn_ip *cmd, char *av) 240 { 241 char *p = NULL, md = 0; 242 u_int32_t i; 243 244 cmd->o.len &= ~F_LEN_MASK; /* zero len */ 245 246 if (!strncmp(av, "any", strlen(av))) 247 return; 248 249 if (!strncmp(av, "me", strlen(av))) { 250 cmd->o.len |= F_INSN_SIZE(ipfw_insn); 251 return; 252 } 253 254 p = strchr(av, '/'); 255 if (!p) 256 p = strchr(av, ':'); 257 258 if (p) { 259 md = *p; 260 *p++ = '\0'; 261 } 262 263 if (lookup_host(av, &cmd->addr) != 0) 264 errx(EX_NOHOST, "hostname ``%s'' unknown", av); 265 switch (md) { 266 case ':': 267 if (!inet_aton(p, &cmd->mask)) 268 errx(EX_DATAERR, "bad netmask ``%s''", p); 269 break; 270 case '/': 271 i = atoi(p); 272 if (i == 0) 273 cmd->mask.s_addr = htonl(0); 274 else if (i > 32) 275 errx(EX_DATAERR, "bad width ``%s''", p); 276 else 277 cmd->mask.s_addr = htonl(~0 << (32 - i)); 278 break; 279 default: 280 cmd->mask.s_addr = htonl(~0); 281 break; 282 } 283 cmd->addr.s_addr &= cmd->mask.s_addr; 284 285 if (p) 286 p = strchr(p, '{'); 287 if (p) { 288 u_int32_t *d; 289 int low, high; 290 int i = contigmask((u_char *)&(cmd->mask), 32); 291 292 if (i < 24 || i > 31) { 293 fprintf(stderr, "invalid set with mask %d\n", i); 294 exit(0); 295 } 296 cmd->o.arg1 = 1<<(32-i); 297 cmd->addr.s_addr = ntohl(cmd->addr.s_addr); 298 d = (u_int32_t *)&cmd->mask; 299 cmd->o.opcode = O_BASIC_IP_DST_SET; /* default */ 300 cmd->o.len |= F_INSN_SIZE(ipfw_insn_u32) + (cmd->o.arg1+31)/32; 301 for (i = 0; i < (cmd->o.arg1+31)/32 ; i++) 302 d[i] = 0; /* clear masks */ 303 304 av = p+1; 305 low = cmd->addr.s_addr & 0xff; 306 high = low + cmd->o.arg1 - 1; 307 while (isdigit(*av)) { 308 char *s; 309 u_int16_t a = strtol(av, &s, 0); 310 311 if (s == av) /* no parameter */ 312 break; 313 if (a < low || a > high) { 314 fprintf(stderr, 315 "addr %d out of range [%d-%d]\n", 316 a, low, high); 317 exit(0); 318 } 319 a -= low; 320 d[ a/32] |= 1<<(a & 31); 321 if (*s != ',') 322 break; 323 av = s+1; 324 } 325 return; 326 } 327 328 if (cmd->mask.s_addr == 0) { 329 if (cmd->o.len & F_NOT) 330 errx(EX_DATAERR, "not any never matches"); 331 else /* useless, nuke it */ 332 return; 333 } else if (cmd->mask.s_addr == IP_MASK_ALL) { 334 cmd->o.len |= F_INSN_SIZE(ipfw_insn_u32); 335 } else { /* addr/mask */ 336 cmd->o.len |= F_INSN_SIZE(ipfw_insn_ip); 337 printf("cmd->o.len=%d\n", cmd->o.len); 338 } 339 } 340 341 342 static ipfw_insn *add_srcip(ipfw_insn *cmd, char *av) 343 { 344 fill_ip((ipfw_insn_ip *)cmd, av); 345 if ((int)cmd->opcode == O_BASIC_IP_DST_SET) /* set */ 346 cmd->opcode = O_BASIC_IP_SRC_SET; 347 else if (F_LEN(cmd) == F_INSN_SIZE(ipfw_insn)) /* me */ 348 cmd->opcode = O_BASIC_IP_SRC_ME; 349 else if (F_LEN(cmd) == F_INSN_SIZE(ipfw_insn_u32)) /* one IP */ 350 cmd->opcode = O_BASIC_IP_SRC; 351 else if (F_LEN(cmd) == F_INSN_SIZE(ipfw_insn_ip)) /* addr/mask */ 352 cmd->opcode = O_BASIC_IP_SRC_MASK; 353 return cmd; 354 } 355 356 357 static ipfw_insn *add_dstip(ipfw_insn *cmd, char *av) 358 { 359 fill_ip((ipfw_insn_ip *)cmd, av); 360 if ((int)cmd->opcode == O_BASIC_IP_DST_SET) 361 cmd->opcode = O_BASIC_IP_DST_SET; 362 else if (F_LEN(cmd) == F_INSN_SIZE(ipfw_insn)) 363 cmd->opcode = O_BASIC_IP_DST_ME; 364 else if (F_LEN(cmd) == F_INSN_SIZE(ipfw_insn_u32)) 365 cmd->opcode = O_BASIC_IP_DST; 366 else if (F_LEN(cmd) == F_INSN_SIZE(ipfw_insn_ip)) 367 cmd->opcode = O_BASIC_IP_DST_MASK; 368 return cmd; 369 } 370 371 372 static ipfw_insn *add_proto(ipfw_insn *cmd, char *av) 373 { 374 struct protoent *pe; 375 u_char proto = 0; 376 if (!strncmp(av, "all", strlen(av))) { 377 ; 378 } else if ((proto = atoi(av)) > 0) { 379 ; 380 } else if ((pe = getprotobyname(av)) != NULL) { 381 proto = pe->p_proto; 382 } else { 383 errx(EX_USAGE, "protocol `%s' not recognizable\n", av); 384 } 385 if (proto != IPPROTO_IP) { 386 cmd->opcode = O_BASIC_PROTO; 387 cmd->module = MODULE_BASIC_ID; 388 cmd->len = cmd->len|LEN_OF_IPFWINSN; 389 cmd->arg1 = proto; 390 } 391 return cmd; 392 } 393 394 void 395 parse_count(ipfw_insn **cmd, int *ac, char **av[]) 396 { 397 (*cmd)->opcode = O_BASIC_COUNT; 398 (*cmd)->module = MODULE_BASIC_ID; 399 (*cmd)->len = LEN_OF_IPFWINSN; 400 NEXT_ARG1; 401 } 402 403 void 404 parse_skipto(ipfw_insn **cmd, int *ac, char **av[]) 405 { 406 NEXT_ARG1; 407 (*cmd)->opcode = O_BASIC_SKIPTO; 408 (*cmd)->module = MODULE_BASIC_ID; 409 (*cmd)->len = LEN_OF_IPFWINSN; 410 (*cmd)->arg1 = strtoul(**av, NULL, 10); 411 NEXT_ARG1; 412 } 413 414 /* 415 * cmd->arg3 is count of the destination 416 * cmd->arg1 is the type, random 0, round-robin 1, sticky 2 417 */ 418 void 419 parse_forward(ipfw_insn **cmd, int *ac, char **av[]) 420 { 421 ipfw_insn_sa *p = (ipfw_insn_sa *)(*cmd); 422 struct sockaddr_in *sa; 423 char *tok, *end = '\0'; 424 char *str; 425 int count, port; 426 427 (*cmd)->opcode = O_BASIC_FORWARD; 428 NEXT_ARG1; 429 /* 430 * multiple forward destinations are seperated by colon 431 * ip address and port are seperated by comma 432 * e.g. 192.168.1.1:80,192.168.1.2:8080 433 * 192.168.1.1,192.168.1.2 or keep the port the same 434 */ 435 tok = strtok(**av, ","); 436 sa = &p->sa; 437 count = 0; 438 while (tok != NULL) { 439 sa->sin_len = sizeof(struct sockaddr_in); 440 sa->sin_family = AF_INET; 441 sa->sin_port = 0; 442 str = strchr(tok,':'); 443 if (str != NULL) { 444 *(str++) = '\0'; 445 port = strtoport(str, &end, 0, 0); 446 sa->sin_port = (u_short)port; 447 } 448 lookup_host(tok, &(sa->sin_addr)); 449 tok = strtok (NULL, ","); 450 sa++; 451 count++; 452 } 453 (*cmd)->arg3 = count; 454 if (count == 0) { 455 errx(EX_DATAERR, "forward `%s' not recognizable", **av); 456 } 457 NEXT_ARG1; 458 if (count > 1) { 459 if (strcmp(**av, "round-robin") == 0) { 460 NEXT_ARG1; 461 (*cmd)->arg1 = 1; 462 } else if (strcmp(**av, "sticky") == 0) { 463 NEXT_ARG1; 464 (*cmd)->arg1 = 2; 465 } else { 466 /* random */ 467 (*cmd)->arg1 = 0; 468 } 469 } 470 (*cmd)->len = LEN_OF_IPFWINSN + count * sizeof(struct sockaddr_in); 471 } 472 473 void 474 parse_in(ipfw_insn **cmd, int *ac, char **av[]) 475 { 476 (*cmd)->opcode = O_BASIC_IN; 477 (*cmd)->module = MODULE_BASIC_ID; 478 (*cmd)->len = LEN_OF_IPFWINSN; 479 (*cmd)->arg1 = 0; 480 NEXT_ARG1; 481 } 482 483 void 484 parse_out(ipfw_insn **cmd, int *ac, char **av[]) 485 { 486 (*cmd)->opcode = O_BASIC_OUT; 487 (*cmd)->module = MODULE_BASIC_ID; 488 (*cmd)->len = LEN_OF_IPFWINSN; 489 (*cmd)->arg1 = 0; 490 NEXT_ARG1; 491 } 492 493 494 void 495 parse_via(ipfw_insn **cmd, int *ac, char **av[]) 496 { 497 (*cmd)->module = MODULE_BASIC_ID; 498 (*cmd)->len = LEN_OF_IPFWINSN; 499 if (strcmp(*av[0], "via")==0) { 500 (*cmd)->opcode = O_BASIC_VIA; 501 } else if (strcmp(*av[0], "xmit")==0) { 502 (*cmd)->opcode = O_BASIC_XMIT; 503 } else if (strcmp(*av[0], "recv")==0) { 504 (*cmd)->opcode = O_BASIC_RECV; 505 } 506 NEXT_ARG1; 507 fill_iface((ipfw_insn_if *)(*cmd), *av[0]); 508 NEXT_ARG1; 509 } 510 511 void 512 parse_from(ipfw_insn **cmd, int *ac, char **av[]) 513 { 514 (*cmd)->module = MODULE_BASIC_ID; 515 NEXT_ARG1; 516 add_srcip(*cmd, **av); 517 NEXT_ARG1; 518 } 519 520 void 521 parse_to(ipfw_insn **cmd, int *ac, char **av[]) 522 { 523 (*cmd)->module = MODULE_BASIC_ID; 524 NEXT_ARG1; 525 add_dstip(*cmd, **av); 526 NEXT_ARG1; 527 } 528 529 void 530 parse_proto(ipfw_insn **cmd, int *ac, char **av[]) 531 { 532 add_proto(*cmd, **av); 533 NEXT_ARG1; 534 } 535 536 void 537 parse_prob(ipfw_insn **cmd, int *ac, char **av[]) 538 { 539 NEXT_ARG1; 540 (*cmd)->opcode = O_BASIC_PROB; 541 (*cmd)->module = MODULE_BASIC_ID; 542 (*cmd)->len = LEN_OF_IPFWINSN; 543 (*cmd)->arg1 = strtoul(**av, NULL, 10); 544 NEXT_ARG1; 545 } 546 547 void 548 parse_keep_state(ipfw_insn **cmd, int *ac, char **av[]) 549 { 550 NEXT_ARG1; 551 (*cmd)->opcode = O_BASIC_KEEP_STATE; 552 (*cmd)->module = MODULE_BASIC_ID; 553 (*cmd)->len = LEN_OF_IPFWINSN; 554 if (strcmp(**av, "limit") == 0) { 555 NEXT_ARG1; 556 (*cmd)->arg3 = match_token(limit_types, **av); 557 if ((*cmd)->arg3 == 0) 558 errx(EX_DATAERR, "limit `%s' not recognizable", **av); 559 560 NEXT_ARG1; 561 (*cmd)->arg1 = strtoul(**av, NULL, 10); 562 if ((*cmd)->arg1 == 0) 563 errx(EX_DATAERR, "bad limit `%s'", **av); 564 565 NEXT_ARG1; 566 } 567 if (strcmp(**av, "live") == 0) { 568 NEXT_ARG1; 569 (*cmd)->arg2 = strtoul(**av, NULL, 10); 570 NEXT_ARG1; 571 } 572 } 573 574 void 575 parse_check_state(ipfw_insn **cmd, int *ac, char **av[]) 576 { 577 NEXT_ARG1; 578 (*cmd)->opcode = O_BASIC_CHECK_STATE; 579 (*cmd)->module = MODULE_BASIC_ID; 580 (*cmd)->len = LEN_OF_IPFWINSN; 581 } 582 583 void 584 parse_tagged(ipfw_insn **cmd, int *ac, char **av[]) 585 { 586 NEXT_ARG1; 587 (*cmd)->opcode = O_BASIC_TAGGED; 588 (*cmd)->module = MODULE_BASIC_ID; 589 (*cmd)->len = LEN_OF_IPFWINSN; 590 (*cmd)->arg1 = strtoul(**av, NULL, 10); 591 NEXT_ARG1; 592 } 593 594 void 595 parse_comment(ipfw_insn **cmd, int *ac, char **av[]) 596 { 597 int l = 0; 598 char *p = (char *)((*cmd) + 1); 599 600 NEXT_ARG1; 601 (*cmd)->opcode = O_BASIC_COMMENT; 602 (*cmd)->module = MODULE_BASIC_ID; 603 604 while (*ac > 0) { 605 l += strlen(**av) + 1; 606 if (l > 84) { 607 errx(EX_DATAERR, "comment too long (max 80 chars)"); 608 } 609 strcpy(p, **av); 610 p += strlen(**av); 611 *p++ = ' '; 612 NEXT_ARG1; 613 } 614 l = 1 + (l + 3) / 4; 615 (*cmd)->len = l; 616 *(--p) = '\0'; 617 } 618 619 void 620 parse_tag(ipfw_insn **cmd, int *ac, char **av[]) 621 { 622 NEXT_ARG1; 623 (*cmd)->opcode = O_BASIC_TAG; 624 (*cmd)->module = MODULE_BASIC_ID; 625 (*cmd)->len = LEN_OF_IPFWINSN; 626 (*cmd)->arg1 = strtoul(**av, NULL, 10); 627 NEXT_ARG1; 628 } 629 630 void 631 parse_untag(ipfw_insn **cmd, int *ac, char **av[]) 632 { 633 NEXT_ARG1; 634 (*cmd)->opcode = O_BASIC_UNTAG; 635 (*cmd)->module = MODULE_BASIC_ID; 636 (*cmd)->len = LEN_OF_IPFWINSN; 637 (*cmd)->arg1 = strtoul(**av, NULL, 10); 638 NEXT_ARG1; 639 } 640 641 void 642 show_count(ipfw_insn *cmd) 643 { 644 printf(" count"); 645 } 646 647 void 648 show_skipto(ipfw_insn *cmd) 649 { 650 printf(" skipto %u", cmd->arg1); 651 } 652 653 void 654 show_forward(ipfw_insn *cmd) 655 { 656 struct sockaddr_in *sa; 657 int i; 658 659 ipfw_insn_sa *s = (ipfw_insn_sa *)cmd; 660 sa = &s->sa; 661 printf(" forward"); 662 for (i = 0; i < cmd->arg3; i++){ 663 if (i > 0) 664 printf(","); 665 else 666 printf(" "); 667 668 printf("%s", inet_ntoa(sa->sin_addr)); 669 if (sa->sin_port != 0) 670 printf(":%d", sa->sin_port); 671 672 sa++; 673 } 674 if (cmd->arg1 == 1) 675 printf(" round-robin"); 676 else if (cmd->arg1 == 2) 677 printf(" sticky"); 678 679 } 680 681 void 682 show_in(ipfw_insn *cmd) 683 { 684 printf(" in"); 685 } 686 687 void 688 show_out(ipfw_insn *cmd) 689 { 690 printf(" out"); 691 } 692 693 void 694 show_via(ipfw_insn *cmd) 695 { 696 char *s; 697 ipfw_insn_if *cmdif = (ipfw_insn_if *)cmd; 698 699 if ((int)cmd->opcode == O_BASIC_XMIT) 700 s = "xmit"; 701 else if ((int)cmd->opcode == O_BASIC_RECV) 702 s = "recv"; 703 else if ((int)cmd->opcode == O_BASIC_VIA) 704 s = "via"; 705 else 706 s = "?huh?"; 707 708 if (cmdif->name[0] == '\0') 709 printf(" %s %s", s, inet_ntoa(cmdif->p.ip)); 710 711 printf(" %s %s", s, cmdif->name); 712 } 713 714 void 715 show_from(ipfw_insn *cmd) 716 { 717 printf(" from %s", inet_ntoa(((ipfw_insn_ip *)cmd)->addr)); 718 } 719 720 void 721 show_to(ipfw_insn *cmd) 722 { 723 printf(" to %s", inet_ntoa(((ipfw_insn_ip *)cmd)->addr)); 724 } 725 726 void 727 show_proto(ipfw_insn *cmd) 728 { 729 struct protoent *pe; 730 u_char proto = 0; 731 proto = cmd->arg1; 732 pe = getprotobynumber(cmd->arg1); 733 printf(" %s", pe->p_name); 734 } 735 736 void 737 show_prob(ipfw_insn *cmd) 738 { 739 printf(" prob %d%%", cmd->arg1); 740 } 741 742 void 743 show_keep_state(ipfw_insn *cmd) 744 { 745 printf(" keep-state"); 746 if (cmd->arg1 != 0) { 747 char *type=match_token2(limit_types, cmd->arg3); 748 printf(" limit %s %d", type, cmd->arg1); 749 } 750 if (cmd->arg2 != 0) { 751 printf(" live %d", cmd->arg2); 752 } 753 } 754 755 void 756 show_check_state(ipfw_insn *cmd) 757 { 758 printf(" check-state"); 759 } 760 761 void 762 show_tagged(ipfw_insn *cmd) 763 { 764 printf(" tagged %d", cmd->arg1); 765 } 766 767 void 768 show_comment(ipfw_insn *cmd) 769 { 770 printf(" // %s", (char *)(cmd + 1)); 771 } 772 773 void 774 show_tag(ipfw_insn *cmd) 775 { 776 printf(" tag %d", cmd->arg1); 777 } 778 779 void 780 show_untag(ipfw_insn *cmd) 781 { 782 printf(" untag %d", cmd->arg1); 783 } 784 785 void 786 load_module(register_func function, register_keyword keyword) 787 { 788 keyword(MODULE_BASIC_ID, O_BASIC_COUNT, "count", 789 IPFW_KEYWORD_TYPE_ACTION); 790 function(MODULE_BASIC_ID, O_BASIC_COUNT, 791 (parser_func)parse_count, (shower_func)show_count); 792 793 keyword(MODULE_BASIC_ID, O_BASIC_SKIPTO, "skipto", 794 IPFW_KEYWORD_TYPE_ACTION); 795 function(MODULE_BASIC_ID, O_BASIC_SKIPTO, 796 (parser_func)parse_skipto, (shower_func)show_skipto); 797 798 keyword(MODULE_BASIC_ID, O_BASIC_FORWARD, "forward", 799 IPFW_KEYWORD_TYPE_ACTION); 800 function(MODULE_BASIC_ID, O_BASIC_FORWARD, 801 (parser_func)parse_forward, (shower_func)show_forward); 802 803 keyword(MODULE_BASIC_ID, O_BASIC_IN, "in", IPFW_KEYWORD_TYPE_FILTER); 804 function(MODULE_BASIC_ID, O_BASIC_IN, 805 (parser_func)parse_in, (shower_func)show_in); 806 807 keyword(MODULE_BASIC_ID, O_BASIC_OUT, "out", IPFW_KEYWORD_TYPE_FILTER); 808 function(MODULE_BASIC_ID, O_BASIC_OUT, 809 (parser_func)parse_out, (shower_func)show_out); 810 811 keyword(MODULE_BASIC_ID, O_BASIC_VIA, "via", IPFW_KEYWORD_TYPE_FILTER); 812 function(MODULE_BASIC_ID, O_BASIC_VIA, 813 (parser_func)parse_via, (shower_func)show_via); 814 815 keyword(MODULE_BASIC_ID, O_BASIC_XMIT, "xmit", 816 IPFW_KEYWORD_TYPE_FILTER); 817 function(MODULE_BASIC_ID, O_BASIC_XMIT, 818 (parser_func)parse_via, (shower_func)show_via); 819 820 keyword(MODULE_BASIC_ID, O_BASIC_RECV, "recv", 821 IPFW_KEYWORD_TYPE_FILTER); 822 function(MODULE_BASIC_ID, O_BASIC_RECV, 823 (parser_func)parse_via, (shower_func)show_via); 824 825 keyword(MODULE_BASIC_ID, O_BASIC_IP_SRC, "from", 826 IPFW_KEYWORD_TYPE_FILTER); 827 function(MODULE_BASIC_ID, O_BASIC_IP_SRC, 828 (parser_func)parse_from, (shower_func)show_from); 829 830 keyword(MODULE_BASIC_ID, O_BASIC_IP_DST, "to", 831 IPFW_KEYWORD_TYPE_FILTER); 832 function(MODULE_BASIC_ID, O_BASIC_IP_DST, 833 (parser_func)parse_to, (shower_func)show_to); 834 835 keyword(MODULE_BASIC_ID, O_BASIC_PROTO, "proto", 836 IPFW_KEYWORD_TYPE_FILTER); 837 function(MODULE_BASIC_ID, O_BASIC_PROTO, 838 (parser_func)parse_proto, (shower_func)show_proto); 839 840 keyword(MODULE_BASIC_ID, O_BASIC_PROB, "prob", 841 IPFW_KEYWORD_TYPE_FILTER); 842 function(MODULE_BASIC_ID, O_BASIC_PROB, 843 (parser_func)parse_prob, (shower_func)show_prob); 844 845 keyword(MODULE_BASIC_ID, O_BASIC_KEEP_STATE, "keep-state", 846 IPFW_KEYWORD_TYPE_FILTER); 847 function(MODULE_BASIC_ID, O_BASIC_KEEP_STATE, 848 (parser_func)parse_keep_state, 849 (shower_func)show_keep_state); 850 851 keyword(MODULE_BASIC_ID, O_BASIC_CHECK_STATE, "check-state", 852 IPFW_KEYWORD_TYPE_OTHERS); 853 function(MODULE_BASIC_ID, O_BASIC_CHECK_STATE, 854 (parser_func)parse_check_state, 855 (shower_func)show_check_state); 856 857 keyword(MODULE_BASIC_ID, O_BASIC_TAG, "tag", IPFW_KEYWORD_TYPE_OTHERS); 858 function(MODULE_BASIC_ID, O_BASIC_TAG, 859 (parser_func)parse_tag, (shower_func)show_tag); 860 861 keyword(MODULE_BASIC_ID, O_BASIC_UNTAG, "untag", 862 IPFW_KEYWORD_TYPE_OTHERS); 863 function(MODULE_BASIC_ID, O_BASIC_UNTAG, 864 (parser_func)parse_untag, (shower_func)show_untag); 865 866 keyword(MODULE_BASIC_ID, O_BASIC_TAGGED, "tagged", 867 IPFW_KEYWORD_TYPE_FILTER); 868 function(MODULE_BASIC_ID, O_BASIC_TAGGED, 869 (parser_func)parse_tagged, (shower_func)show_tagged); 870 871 keyword(MODULE_BASIC_ID, O_BASIC_COMMENT, "//", 872 IPFW_KEYWORD_TYPE_FILTER); 873 function(MODULE_BASIC_ID, O_BASIC_COMMENT, 874 (parser_func)parse_comment, (shower_func)show_comment); 875 } 876