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