1 /* 2 * Copyright (c) 2014 - 2018 The DragonFly Project. All rights reserved. 3 * 4 * This code is derived from software contributed to The DragonFly Project 5 * by Bill Yuan <bycn82@dragonflybsd.org> 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 <net/ipfw3/ip_fw3.h> 59 #include "../../../sbin/ipfw3/ipfw3.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 int 101 match_token(struct char_int_map *table, char *string) 102 { 103 while (table->key) { 104 if (strcmp(table->key, string) == 0) { 105 return table->val; 106 } 107 table++; 108 } 109 return 0; 110 } 111 112 static char * 113 match_token2(struct char_int_map *table, int val) 114 { 115 while (table->val) { 116 if (table->val == val) 117 return table->key; 118 119 table++; 120 } 121 return NULL; 122 }; 123 124 static void 125 fill_iface(ipfw_insn_if *cmd, char *arg) 126 { 127 cmd->name[0] = '\0'; 128 cmd->o.len |= F_INSN_SIZE(ipfw_insn_if); 129 130 /* Parse the interface or address */ 131 if (!strcmp(arg, "any")){ 132 cmd->o.len = 0; 133 } else if (!isdigit(*arg)) { 134 strlcpy(cmd->name, arg, sizeof(cmd->name)); 135 cmd->p.glob = strpbrk(arg, "*?[") != NULL ? 1 : 0; 136 } else if (!inet_aton(arg, &cmd->p.ip)) 137 errx(EX_DATAERR, "bad ip address ``%s''", arg); 138 } 139 140 static int 141 lookup_host (char *host, struct in_addr *ipaddr) 142 { 143 struct hostent *he; 144 145 if (!inet_aton(host, ipaddr)) { 146 if ((he = gethostbyname(host)) == NULL) 147 return -1; 148 *ipaddr = *(struct in_addr *)he->h_addr_list[0]; 149 } 150 return 0; 151 } 152 153 /* 154 * Like strtol, but also translates service names into port numbers 155 * for some protocols. 156 * In particular: 157 * proto == -1 disables the protocol check; 158 * proto == IPPROTO_ETHERTYPE looks up an internal table 159 * proto == <some value in /etc/protocols> matches the values there. 160 * Returns *end == s in case the parameter is not found. 161 */ 162 static int 163 strtoport(char *s, char **end, int base, int proto) 164 { 165 char *p, *buf; 166 char *s1; 167 int i; 168 169 *end = s; /* default - not found */ 170 if ( *s == '\0') 171 return 0; /* not found */ 172 173 if (isdigit(*s)) 174 return strtol(s, end, base); 175 176 /* 177 * find separator. '\\' escapes the next char. 178 */ 179 for (s1 = s; *s1 && (isalnum(*s1) || *s1 == '\\') ; s1++) { 180 if (*s1 == '\\' && s1[1] != '\0') 181 s1++; 182 } 183 184 buf = malloc(s1 - s + 1); 185 if (buf == NULL) 186 return 0; 187 188 /* 189 * copy into a buffer skipping backslashes 190 */ 191 for (p = s, i = 0; p != s1 ; p++) 192 if ( *p != '\\') 193 buf[i++] = *p; 194 buf[i++] = '\0'; 195 196 if (proto == IPPROTO_ETHERTYPE) { 197 i = match_token(ether_types, buf); 198 free(buf); 199 if (i != -1) { /* found */ 200 *end = s1; 201 return i; 202 } 203 } else { 204 struct protoent *pe = NULL; 205 struct servent *se; 206 207 if (proto != 0) 208 pe = getprotobynumber(proto); 209 setservent(1); 210 se = getservbyname(buf, pe ? pe->p_name : NULL); 211 free(buf); 212 if (se != NULL) { 213 *end = s1; 214 return ntohs(se->s_port); 215 } 216 } 217 return 0; /* not found */ 218 } 219 220 static int 221 contigmask(u_char *p, int len) 222 { 223 int i, n; 224 for (i=0; i<len ; i++) { 225 if ( (p[i/8] & (1 << (7 - (i%8)))) == 0) /* first bit unset */ 226 break; 227 } 228 for (n=i+1; n < len; n++) { 229 if ( (p[n/8] & (1 << (7 - (n%8)))) != 0) 230 return -1; /* mask not contiguous */ 231 } 232 return i; 233 } 234 235 static ipfw_insn 236 *add_proto(ipfw_insn *cmd, char *av) 237 { 238 struct protoent *pe; 239 u_char proto = 0; 240 if (!strncmp(av, "all", strlen(av))) { 241 ; 242 } else if ((proto = atoi(av)) > 0) { 243 ; 244 } else if ((pe = getprotobyname(av)) != NULL) { 245 proto = pe->p_proto; 246 } else { 247 errx(EX_USAGE, "protocol `%s' not recognizable\n", av); 248 } 249 if (proto != IPPROTO_IP) { 250 cmd->opcode = O_BASIC_PROTO; 251 cmd->module = MODULE_BASIC_ID; 252 cmd->len |= LEN_OF_IPFWINSN; 253 cmd->arg1 = proto; 254 } 255 return cmd; 256 } 257 258 void 259 parse_count(ipfw_insn **cmd, int *ac, char **av[]) 260 { 261 (*cmd)->opcode = O_BASIC_COUNT; 262 (*cmd)->module = MODULE_BASIC_ID; 263 (*cmd)->len |= LEN_OF_IPFWINSN; 264 NEXT_ARG1; 265 } 266 267 void 268 parse_skipto(ipfw_insn **cmd, int *ac, char **av[]) 269 { 270 NEXT_ARG1; 271 (*cmd)->opcode = O_BASIC_SKIPTO; 272 (*cmd)->module = MODULE_BASIC_ID; 273 (*cmd)->len |= LEN_OF_IPFWINSN; 274 (*cmd)->arg1 = strtoul(**av, NULL, 10); 275 NEXT_ARG1; 276 } 277 278 /* 279 * cmd->arg3 is count of the destination 280 * cmd->arg1 is the type, random 0, round-robin 1, sticky 2 281 */ 282 void 283 parse_forward(ipfw_insn **cmd, int *ac, char **av[]) 284 { 285 ipfw_insn_sa *p = (ipfw_insn_sa *)(*cmd); 286 struct sockaddr_in *sa; 287 char *tok, *end = '\0'; 288 char *str; 289 int count, port; 290 291 (*cmd)->opcode = O_BASIC_FORWARD; 292 NEXT_ARG1; 293 /* 294 * multiple forward destinations are seperated by colon 295 * ip address and port are seperated by comma 296 * e.g. 192.168.1.1:80,192.168.1.2:8080 297 * 192.168.1.1,192.168.1.2 or keep the port the same 298 */ 299 tok = strtok(**av, ","); 300 sa = &p->sa; 301 count = 0; 302 while (tok != NULL) { 303 sa->sin_len = sizeof(struct sockaddr_in); 304 sa->sin_family = AF_INET; 305 sa->sin_port = 0; 306 str = strchr(tok,':'); 307 if (str != NULL) { 308 *(str++) = '\0'; 309 port = strtoport(str, &end, 0, 0); 310 sa->sin_port = (u_short)port; 311 } 312 if (lookup_host(tok, &(sa->sin_addr)) != 0) 313 errx(EX_DATAERR, "forward `%s' invalid dst", tok); 314 tok = strtok (NULL, ","); 315 sa++; 316 count++; 317 } 318 (*cmd)->arg3 = count; 319 if (count == 0) { 320 errx(EX_DATAERR, "forward `%s' not recognizable", **av); 321 } 322 NEXT_ARG1; 323 if (count > 1) { 324 if (strcmp(**av, "round-robin") == 0) { 325 NEXT_ARG1; 326 (*cmd)->arg1 = 1; 327 } else if (strcmp(**av, "sticky") == 0) { 328 NEXT_ARG1; 329 (*cmd)->arg1 = 2; 330 } else { 331 /* random */ 332 (*cmd)->arg1 = 0; 333 } 334 } 335 (*cmd)->len = LEN_OF_IPFWINSN + count * sizeof(struct sockaddr_in); 336 } 337 338 void 339 parse_in(ipfw_insn **cmd, int *ac, char **av[]) 340 { 341 (*cmd)->opcode = O_BASIC_IN; 342 (*cmd)->module = MODULE_BASIC_ID; 343 (*cmd)->len |= LEN_OF_IPFWINSN; 344 (*cmd)->arg1 = 0; 345 NEXT_ARG1; 346 } 347 348 void 349 parse_out(ipfw_insn **cmd, int *ac, char **av[]) 350 { 351 (*cmd)->opcode = O_BASIC_OUT; 352 (*cmd)->module = MODULE_BASIC_ID; 353 (*cmd)->len |= LEN_OF_IPFWINSN; 354 (*cmd)->arg1 = 0; 355 NEXT_ARG1; 356 } 357 358 359 void 360 parse_via(ipfw_insn **cmd, int *ac, char **av[]) 361 { 362 (*cmd)->module = MODULE_BASIC_ID; 363 (*cmd)->len |= LEN_OF_IPFWINSN; 364 if (strcmp(*av[0], "via")==0) { 365 (*cmd)->opcode = O_BASIC_VIA; 366 } else if (strcmp(*av[0], "xmit")==0) { 367 (*cmd)->opcode = O_BASIC_XMIT; 368 } else if (strcmp(*av[0], "recv")==0) { 369 (*cmd)->opcode = O_BASIC_RECV; 370 } 371 NEXT_ARG1; 372 fill_iface((ipfw_insn_if *)(*cmd), *av[0]); 373 NEXT_ARG1; 374 } 375 376 void 377 parse_src_port(ipfw_insn **cmd, int *ac, char **av[]) 378 { 379 NEXT_ARG1; 380 (*cmd)->opcode = O_BASIC_IP_SRCPORT; 381 (*cmd)->module = MODULE_BASIC_ID; 382 (*cmd)->len |= LEN_OF_IPFWINSN; 383 double v = strtol(**av, NULL, 0); 384 if (v <= 0 || v >= 65535) 385 errx(EX_NOHOST, "port `%s' invalid", **av); 386 (*cmd)->arg1 = v; 387 NEXT_ARG1; 388 } 389 390 void 391 parse_dst_port(ipfw_insn **cmd, int *ac, char **av[]) 392 { 393 NEXT_ARG1; 394 (*cmd)->opcode = O_BASIC_IP_DSTPORT; 395 (*cmd)->module = MODULE_BASIC_ID; 396 (*cmd)->len |= LEN_OF_IPFWINSN; 397 double v = strtol(**av, NULL, 0); 398 if (v <= 0 || v >= 65535) 399 errx(EX_NOHOST, "port `%s' invalid", **av); 400 (*cmd)->arg1 = v; 401 NEXT_ARG1; 402 } 403 404 /* 405 * Below formats are supported: 406 * from table 1 O_BASIC_IP_SRC_LOOKUP 407 * from any return 0 len instruction 408 * from me O_BASIC_IP_SRC_ME 409 * from 1.2.3.4 O_BASIC_IP_SRC 410 * from 1.2.3.4/24 O_BASIC_IP_SRC_MASK 411 */ 412 void 413 parse_from(ipfw_insn **cmd, int *ac, char **av[]) 414 { 415 ipfw_insn_ip *p = (ipfw_insn_ip *)(*cmd); 416 double port; 417 int i; 418 419 (*cmd)->module = MODULE_BASIC_ID; 420 NEXT_ARG1; 421 if (strcmp(**av, "table") == 0) { 422 NEXT_ARG1; 423 NEED(*ac, 1, "table id missing"); 424 (*cmd)->len |= F_INSN_SIZE(ipfw_insn); 425 (*cmd)->opcode = O_BASIC_IP_SRC_LOOKUP; 426 (*cmd)->arg1 = strtoul(**av, NULL, 10); 427 } else if (strcmp(**av, "any") == 0) { 428 (*cmd)->len &= ~F_LEN_MASK; 429 } else if (strcmp(**av, "me") == 0) { 430 (*cmd)->len |= F_INSN_SIZE(ipfw_insn); 431 (*cmd)->opcode = O_BASIC_IP_SRC_ME; 432 } else { 433 char *c = NULL, md = 0; 434 c = strchr(**av, '/'); 435 if (!c) 436 c = strchr(**av, ':'); 437 if (c) { 438 md = *c; 439 *c++ = '\0'; 440 } 441 if (lookup_host(**av, &p->addr) != 0) 442 errx(EX_NOHOST, "hostname ``%s'' unknown", **av); 443 switch (md) { 444 case ':': 445 port = strtol(c, NULL, 0); 446 if (port <= 0 || port >= 65535) 447 errx(EX_NOHOST, "port `%s' invalid", c); 448 (*cmd)->arg1 = port; 449 (*cmd)->len |= F_INSN_SIZE(ipfw_insn_ip); 450 (*cmd)->opcode = O_BASIC_IP_SRC_N_PORT; 451 break; 452 case '/': 453 i = atoi(c); 454 if (i == 0) 455 p->mask.s_addr = htonl(0); 456 else if (i > 32) 457 errx(EX_DATAERR, "bad width ``%s''", c); 458 else 459 p->mask.s_addr = htonl(~0 << (32 - i)); 460 (*cmd)->len |= F_INSN_SIZE(ipfw_insn_ip); 461 (*cmd)->opcode = O_BASIC_IP_SRC_MASK; 462 p->addr.s_addr &= p->mask.s_addr; 463 break; 464 default: 465 p->mask.s_addr = htonl(~0); 466 (*cmd)->len |= F_INSN_SIZE(ipfw_insn_u32); 467 (*cmd)->opcode = O_BASIC_IP_SRC; 468 break; 469 } 470 } 471 NEXT_ARG1; 472 } 473 474 void 475 parse_to(ipfw_insn **cmd, int *ac, char **av[]) 476 { 477 ipfw_insn_ip *p = (ipfw_insn_ip *)(*cmd); 478 double port; 479 int i; 480 481 (*cmd)->module = MODULE_BASIC_ID; 482 NEXT_ARG1; 483 if (strcmp(**av, "table") == 0) { 484 NEXT_ARG1; 485 NEED(*ac, 1, "table id missing"); 486 (*cmd)->len |= F_INSN_SIZE(ipfw_insn); 487 (*cmd)->opcode = O_BASIC_IP_DST_LOOKUP; 488 (*cmd)->arg1 = strtoul(**av, NULL, 10); 489 } else if (strcmp(**av, "any") == 0) { 490 (*cmd)->len &= ~F_LEN_MASK; 491 } else if (strcmp(**av, "me") == 0) { 492 (*cmd)->len |= F_INSN_SIZE(ipfw_insn); 493 (*cmd)->opcode = O_BASIC_IP_DST_ME; 494 } else { 495 char *c = NULL, md = 0; 496 c = strchr(**av, '/'); 497 if (!c) 498 c = strchr(**av, ':'); 499 if (c) { 500 md = *c; 501 *c++ = '\0'; 502 } 503 if (lookup_host(**av, &p->addr) != 0) 504 errx(EX_NOHOST, "hostname ``%s'' unknown", **av); 505 switch (md) { 506 case ':': 507 port = strtol(c, NULL, 0); 508 if (port <= 0 || port >= 65535) 509 errx(EX_NOHOST, "port `%s' invalid", c); 510 (*cmd)->arg1 = port; 511 (*cmd)->len |= F_INSN_SIZE(ipfw_insn_ip); 512 (*cmd)->opcode = O_BASIC_IP_DST_N_PORT; 513 break; 514 case '/': 515 i = atoi(c); 516 if (i == 0) 517 p->mask.s_addr = htonl(0); 518 else if (i > 32) 519 errx(EX_DATAERR, "bad width ``%s''", c); 520 else 521 p->mask.s_addr = htonl(~0 << (32 - i)); 522 (*cmd)->len |= F_INSN_SIZE(ipfw_insn_ip); 523 (*cmd)->opcode = O_BASIC_IP_DST_MASK; 524 p->addr.s_addr &= p->mask.s_addr; 525 break; 526 default: 527 p->mask.s_addr = htonl(~0); 528 (*cmd)->len |= F_INSN_SIZE(ipfw_insn_u32); 529 (*cmd)->opcode = O_BASIC_IP_DST; 530 break; 531 } 532 } 533 NEXT_ARG1; 534 535 } 536 537 void 538 parse_proto(ipfw_insn **cmd, int *ac, char **av[]) 539 { 540 add_proto(*cmd, **av); 541 NEXT_ARG1; 542 } 543 544 void 545 parse_prob(ipfw_insn **cmd, int *ac, char **av[]) 546 { 547 NEXT_ARG1; 548 (*cmd)->opcode = O_BASIC_PROB; 549 (*cmd)->module = MODULE_BASIC_ID; 550 (*cmd)->len |= LEN_OF_IPFWINSN; 551 (*cmd)->arg1 = strtoul(**av, NULL, 10); 552 NEXT_ARG1; 553 } 554 555 void 556 parse_keep_state(ipfw_insn **cmd, int *ac, char **av[]) 557 { 558 NEXT_ARG1; 559 (*cmd)->opcode = O_BASIC_KEEP_STATE; 560 (*cmd)->module = MODULE_BASIC_ID; 561 (*cmd)->len |= LEN_OF_IPFWINSN; 562 if (strcmp(**av, "limit") == 0) { 563 NEXT_ARG1; 564 (*cmd)->arg3 = match_token(limit_types, **av); 565 if ((*cmd)->arg3 == 0) 566 errx(EX_DATAERR, "limit `%s' not recognizable", **av); 567 568 NEXT_ARG1; 569 (*cmd)->arg1 = strtoul(**av, NULL, 10); 570 if ((*cmd)->arg1 == 0) 571 errx(EX_DATAERR, "bad limit `%s'", **av); 572 573 NEXT_ARG1; 574 } 575 if (strcmp(**av, "live") == 0) { 576 NEXT_ARG1; 577 (*cmd)->arg2 = strtoul(**av, NULL, 10); 578 NEXT_ARG1; 579 } 580 } 581 582 void 583 parse_check_state(ipfw_insn **cmd, int *ac, char **av[]) 584 { 585 NEXT_ARG1; 586 (*cmd)->opcode = O_BASIC_CHECK_STATE; 587 (*cmd)->module = MODULE_BASIC_ID; 588 (*cmd)->len |= LEN_OF_IPFWINSN; 589 } 590 591 void 592 parse_tagged(ipfw_insn **cmd, int *ac, char **av[]) 593 { 594 NEXT_ARG1; 595 (*cmd)->opcode = O_BASIC_TAGGED; 596 (*cmd)->module = MODULE_BASIC_ID; 597 (*cmd)->len |= LEN_OF_IPFWINSN; 598 (*cmd)->arg1 = strtoul(**av, NULL, 10); 599 NEXT_ARG1; 600 } 601 602 void 603 parse_comment(ipfw_insn **cmd, int *ac, char **av[]) 604 { 605 int l = 0; 606 char *p = (char *)((*cmd) + 1); 607 608 NEXT_ARG1; 609 (*cmd)->opcode = O_BASIC_COMMENT; 610 (*cmd)->module = MODULE_BASIC_ID; 611 612 while (*ac > 0) { 613 l += strlen(**av) + 1; 614 if (l > 84) { 615 errx(EX_DATAERR, "comment too long (max 80 chars)"); 616 } 617 strcpy(p, **av); 618 p += strlen(**av); 619 *p++ = ' '; 620 NEXT_ARG1; 621 } 622 l = 1 + (l + 3) / 4; 623 (*cmd)->len |= l; 624 *(--p) = '\0'; 625 } 626 627 void 628 parse_tag(ipfw_insn **cmd, int *ac, char **av[]) 629 { 630 NEXT_ARG1; 631 (*cmd)->opcode = O_BASIC_TAG; 632 (*cmd)->module = MODULE_BASIC_ID; 633 (*cmd)->len |= LEN_OF_IPFWINSN; 634 (*cmd)->arg1 = strtoul(**av, NULL, 10); 635 NEXT_ARG1; 636 } 637 638 void 639 parse_untag(ipfw_insn **cmd, int *ac, char **av[]) 640 { 641 NEXT_ARG1; 642 (*cmd)->opcode = O_BASIC_UNTAG; 643 (*cmd)->module = MODULE_BASIC_ID; 644 (*cmd)->len |= LEN_OF_IPFWINSN; 645 (*cmd)->arg1 = strtoul(**av, NULL, 10); 646 NEXT_ARG1; 647 } 648 649 void 650 show_count(ipfw_insn *cmd, int show_or) 651 { 652 printf(" count"); 653 } 654 655 void 656 show_skipto(ipfw_insn *cmd, int show_or) 657 { 658 printf(" skipto %u", cmd->arg1); 659 } 660 661 void 662 show_forward(ipfw_insn *cmd, int show_or) 663 { 664 struct sockaddr_in *sa; 665 int i; 666 667 ipfw_insn_sa *s = (ipfw_insn_sa *)cmd; 668 sa = &s->sa; 669 printf(" forward"); 670 for (i = 0; i < cmd->arg3; i++){ 671 if (i > 0) 672 printf(","); 673 else 674 printf(" "); 675 676 printf("%s", inet_ntoa(sa->sin_addr)); 677 if (sa->sin_port != 0) 678 printf(":%d", sa->sin_port); 679 680 sa++; 681 } 682 if (cmd->arg1 == 1) 683 printf(" round-robin"); 684 else if (cmd->arg1 == 2) 685 printf(" sticky"); 686 687 } 688 689 void 690 show_in(ipfw_insn *cmd, int show_or) 691 { 692 printf(" in"); 693 } 694 695 void 696 show_out(ipfw_insn *cmd, int show_or) 697 { 698 printf(" out"); 699 } 700 701 void 702 show_via(ipfw_insn *cmd, int show_or) 703 { 704 char *s; 705 ipfw_insn_if *cmdif = (ipfw_insn_if *)cmd; 706 707 if ((int)cmd->opcode == O_BASIC_XMIT) 708 s = "xmit"; 709 else if ((int)cmd->opcode == O_BASIC_RECV) 710 s = "recv"; 711 else if ((int)cmd->opcode == O_BASIC_VIA) 712 s = "via"; 713 else 714 s = "?huh?"; 715 if (show_or) 716 s = "or"; 717 if (cmdif->name[0] == '\0') 718 printf(" %s %s", s, inet_ntoa(cmdif->p.ip)); 719 720 printf(" %s %s", s, cmdif->name); 721 } 722 723 void 724 show_src_port(ipfw_insn *cmd, int show_or) 725 { 726 char *word = "src-port"; 727 if (show_or) 728 word = "or"; 729 printf(" %s %d", word, cmd->arg1); 730 } 731 732 void 733 show_dst_port(ipfw_insn *cmd, int show_or) 734 { 735 char *word = "dst-port"; 736 if (show_or) 737 word = "or"; 738 printf(" %s %d", word, cmd->arg1); 739 } 740 741 void 742 show_from(ipfw_insn *cmd, int show_or) 743 { 744 char *word = "from"; 745 if (show_or) 746 word = "or"; 747 printf(" %s %s", word, inet_ntoa(((ipfw_insn_ip *)cmd)->addr)); 748 } 749 750 void 751 show_from_lookup(ipfw_insn *cmd, int show_or) 752 { 753 char *word = "from"; 754 if (show_or) 755 word = "or"; 756 printf(" %s table %d", word, cmd->arg1); 757 } 758 759 void 760 show_from_me(ipfw_insn *cmd, int show_or) 761 { 762 char *word = "from"; 763 if (show_or) 764 word = "or"; 765 printf(" %s me", word); 766 } 767 768 void 769 show_from_mask(ipfw_insn *cmd, int show_or) 770 { 771 int mask; 772 char *word = "from"; 773 if (show_or) 774 word = "or"; 775 ipfw_insn_ip *p = (ipfw_insn_ip *)cmd; 776 printf(" %s %s", word, inet_ntoa(p->addr)); 777 778 mask = contigmask((u_char *)&(p->mask.s_addr), 32); 779 if (mask < 32) 780 printf("/%d", mask); 781 } 782 783 void 784 show_from_src_n_port(ipfw_insn *cmd, int show_or) 785 { 786 char *word = "from"; 787 if (show_or) 788 word = "or"; 789 ipfw_insn_ip *p = (ipfw_insn_ip *)cmd; 790 printf(" %s %s", word, inet_ntoa(p->addr)); 791 printf(":%d", cmd->arg1); 792 } 793 794 void 795 show_to(ipfw_insn *cmd, int show_or) 796 { 797 char *word = "to"; 798 if (show_or) 799 word = "or"; 800 ipfw_insn_ip *p = (ipfw_insn_ip *)cmd; 801 printf(" %s %s", word, inet_ntoa(p->addr)); 802 } 803 804 void 805 show_to_lookup(ipfw_insn *cmd, int show_or) 806 { 807 char *word = "to"; 808 if (show_or) 809 word = "or"; 810 printf(" %s table %d", word, cmd->arg1); 811 } 812 813 void 814 show_to_me(ipfw_insn *cmd, int show_or) 815 { 816 char *word = "to"; 817 if (show_or) 818 word = "or"; 819 printf(" %s me", word); 820 } 821 822 void 823 show_to_mask(ipfw_insn *cmd, int show_or) 824 { 825 int mask; 826 char *word = "to"; 827 if (show_or) 828 word = "or"; 829 ipfw_insn_ip *p = (ipfw_insn_ip *)cmd; 830 printf(" %s %s", word, inet_ntoa(p->addr)); 831 832 mask = contigmask((u_char *)&(p->mask.s_addr), 32); 833 if (mask < 32) 834 printf("/%d", mask); 835 } 836 837 void 838 show_to_src_n_port(ipfw_insn *cmd, int show_or) 839 { 840 char *word = "to"; 841 if (show_or) 842 word = "or"; 843 printf(" %s %s", word, inet_ntoa(((ipfw_insn_ip *)cmd)->addr)); 844 printf(":%d", cmd->arg1); 845 } 846 847 void 848 show_proto(ipfw_insn *cmd, int show_or) 849 { 850 struct protoent *pe; 851 u_char proto = 0; 852 proto = cmd->arg1; 853 pe = getprotobynumber(cmd->arg1); 854 printf(" %s", pe->p_name); 855 } 856 857 void 858 show_prob(ipfw_insn *cmd, int show_or) 859 { 860 char *word = "prob"; 861 if (show_or) 862 word = "or"; 863 printf(" %s %d%%", word, cmd->arg1); 864 } 865 866 void 867 show_keep_state(ipfw_insn *cmd, int show_or) 868 { 869 printf(" keep-state"); 870 if (cmd->arg1 != 0) { 871 char *type=match_token2(limit_types, cmd->arg3); 872 printf(" limit %s %d", type, cmd->arg1); 873 } 874 if (cmd->arg2 != 0) { 875 printf(" live %d", cmd->arg2); 876 } 877 } 878 879 void 880 show_check_state(ipfw_insn *cmd, int show_or) 881 { 882 printf(" check-state"); 883 } 884 885 void 886 show_tagged(ipfw_insn *cmd, int show_or) 887 { 888 printf(" tagged %d", cmd->arg1); 889 } 890 891 void 892 show_comment(ipfw_insn *cmd, int show_or) 893 { 894 printf(" // %s", (char *)(cmd + 1)); 895 } 896 897 void 898 show_tag(ipfw_insn *cmd, int show_or) 899 { 900 printf(" tag %d", cmd->arg1); 901 } 902 903 void 904 show_untag(ipfw_insn *cmd, int show_or) 905 { 906 printf(" untag %d", cmd->arg1); 907 } 908 909 void 910 load_module(register_func function, register_keyword keyword) 911 { 912 keyword(MODULE_BASIC_ID, O_BASIC_COUNT, "count", ACTION); 913 function(MODULE_BASIC_ID, O_BASIC_COUNT, 914 (parser_func)parse_count, (shower_func)show_count); 915 916 keyword(MODULE_BASIC_ID, O_BASIC_SKIPTO, "skipto", ACTION); 917 function(MODULE_BASIC_ID, O_BASIC_SKIPTO, 918 (parser_func)parse_skipto, (shower_func)show_skipto); 919 920 keyword(MODULE_BASIC_ID, O_BASIC_FORWARD, "forward", ACTION); 921 function(MODULE_BASIC_ID, O_BASIC_FORWARD, 922 (parser_func)parse_forward, (shower_func)show_forward); 923 924 keyword(MODULE_BASIC_ID, O_BASIC_IN, "in", FILTER); 925 function(MODULE_BASIC_ID, O_BASIC_IN, 926 (parser_func)parse_in, (shower_func)show_in); 927 928 keyword(MODULE_BASIC_ID, O_BASIC_OUT, "out", FILTER); 929 function(MODULE_BASIC_ID, O_BASIC_OUT, 930 (parser_func)parse_out, (shower_func)show_out); 931 932 keyword(MODULE_BASIC_ID, O_BASIC_VIA, "via", FILTER); 933 function(MODULE_BASIC_ID, O_BASIC_VIA, 934 (parser_func)parse_via, (shower_func)show_via); 935 936 keyword(MODULE_BASIC_ID, O_BASIC_XMIT, "xmit", FILTER); 937 function(MODULE_BASIC_ID, O_BASIC_XMIT, 938 (parser_func)parse_via, (shower_func)show_via); 939 940 keyword(MODULE_BASIC_ID, O_BASIC_RECV, "recv", FILTER); 941 function(MODULE_BASIC_ID, O_BASIC_RECV, 942 (parser_func)parse_via, (shower_func)show_via); 943 944 keyword(MODULE_BASIC_ID, O_BASIC_IP_SRCPORT, "src-port", FILTER); 945 function(MODULE_BASIC_ID, O_BASIC_IP_SRCPORT, 946 (parser_func)parse_src_port, (shower_func)show_src_port); 947 948 keyword(MODULE_BASIC_ID, O_BASIC_IP_DSTPORT, "dst-port", FILTER); 949 function(MODULE_BASIC_ID, O_BASIC_IP_DSTPORT, 950 (parser_func)parse_dst_port, (shower_func)show_dst_port); 951 952 keyword(MODULE_BASIC_ID, O_BASIC_IP_SRC, "from", FROM); 953 function(MODULE_BASIC_ID, O_BASIC_IP_SRC, 954 (parser_func)parse_from, (shower_func)show_from); 955 956 keyword(MODULE_BASIC_ID, O_BASIC_IP_SRC_LOOKUP, "from-[table]", FROM); 957 function(MODULE_BASIC_ID, O_BASIC_IP_SRC_LOOKUP, 958 (parser_func)parse_from, (shower_func)show_from_lookup); 959 960 keyword(MODULE_BASIC_ID, O_BASIC_IP_SRC_ME, "from-[me]", FROM); 961 function(MODULE_BASIC_ID, O_BASIC_IP_SRC_ME, 962 (parser_func)parse_from, (shower_func)show_from_me); 963 964 keyword(MODULE_BASIC_ID, O_BASIC_IP_SRC_MASK, "from-[mask]", FROM); 965 function(MODULE_BASIC_ID, O_BASIC_IP_SRC_MASK, 966 (parser_func)parse_from, (shower_func)show_from_mask); 967 968 keyword(MODULE_BASIC_ID, O_BASIC_IP_SRC_N_PORT, "from-[ip:port]", FROM); 969 function(MODULE_BASIC_ID, O_BASIC_IP_SRC_N_PORT, 970 (parser_func)parse_from, (shower_func)show_from_src_n_port); 971 972 keyword(MODULE_BASIC_ID, O_BASIC_IP_DST, "to", TO); 973 function(MODULE_BASIC_ID, O_BASIC_IP_DST, 974 (parser_func)parse_to, (shower_func)show_to); 975 976 keyword(MODULE_BASIC_ID, O_BASIC_IP_DST_LOOKUP, "to-[table]", TO); 977 function(MODULE_BASIC_ID, O_BASIC_IP_DST_LOOKUP, 978 (parser_func)parse_to, (shower_func)show_to_lookup); 979 980 keyword(MODULE_BASIC_ID, O_BASIC_IP_DST_ME, "to-[me]", TO); 981 function(MODULE_BASIC_ID, O_BASIC_IP_DST_ME, 982 (parser_func)parse_to, (shower_func)show_to_me); 983 984 keyword(MODULE_BASIC_ID, O_BASIC_IP_DST_MASK, "to-[mask]", TO); 985 function(MODULE_BASIC_ID, O_BASIC_IP_DST_MASK, 986 (parser_func)parse_to, (shower_func)show_to_mask); 987 988 keyword(MODULE_BASIC_ID, O_BASIC_IP_DST_N_PORT, "to-[ip:port]", FROM); 989 function(MODULE_BASIC_ID, O_BASIC_IP_DST_N_PORT, 990 (parser_func)parse_to, (shower_func)show_to_src_n_port); 991 992 keyword(MODULE_BASIC_ID, O_BASIC_PROTO, "proto", PROTO); 993 function(MODULE_BASIC_ID, O_BASIC_PROTO, 994 (parser_func)parse_proto, (shower_func)show_proto); 995 996 keyword(MODULE_BASIC_ID, O_BASIC_PROB, "prob", FILTER); 997 function(MODULE_BASIC_ID, O_BASIC_PROB, 998 (parser_func)parse_prob, (shower_func)show_prob); 999 1000 keyword(MODULE_BASIC_ID, O_BASIC_KEEP_STATE, "keep-state", FILTER); 1001 function(MODULE_BASIC_ID, O_BASIC_KEEP_STATE, 1002 (parser_func)parse_keep_state, 1003 (shower_func)show_keep_state); 1004 1005 keyword(MODULE_BASIC_ID, O_BASIC_CHECK_STATE, "check-state", BEFORE); 1006 function(MODULE_BASIC_ID, O_BASIC_CHECK_STATE, 1007 (parser_func)parse_check_state, 1008 (shower_func)show_check_state); 1009 1010 keyword(MODULE_BASIC_ID, O_BASIC_TAG, "tag", ACTION); 1011 function(MODULE_BASIC_ID, O_BASIC_TAG, 1012 (parser_func)parse_tag, (shower_func)show_tag); 1013 1014 keyword(MODULE_BASIC_ID, O_BASIC_UNTAG, "untag", ACTION); 1015 function(MODULE_BASIC_ID, O_BASIC_UNTAG, 1016 (parser_func)parse_untag, (shower_func)show_untag); 1017 1018 keyword(MODULE_BASIC_ID, O_BASIC_TAGGED, "tagged", FILTER); 1019 function(MODULE_BASIC_ID, O_BASIC_TAGGED, 1020 (parser_func)parse_tagged, (shower_func)show_tagged); 1021 1022 keyword(MODULE_BASIC_ID, O_BASIC_COMMENT, "//", AFTER); 1023 function(MODULE_BASIC_ID, O_BASIC_COMMENT, 1024 (parser_func)parse_comment, (shower_func)show_comment); 1025 } 1026