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