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