1 /* 2 * Copyright (c) 2002 Luigi Rizzo 3 * Copyright (c) 1996 Alex Nash, Paul Traina, Poul-Henning Kamp 4 * Copyright (c) 1994 Ugen J.S.Antsilevich 5 * 6 * Idea and grammar partially left from: 7 * Copyright (c) 1993 Daniel Boulet 8 * 9 * Redistribution and use in source forms, with and without modification, 10 * are permitted provided that this entire comment appears intact. 11 * 12 * Redistribution in binary form may occur without any restrictions. 13 * Obviously, it would be nice if you gave credit where credit is due 14 * but requiring it would be too onerous. 15 * 16 * This software is provided ``AS IS'' without any warranties of any kind. 17 * 18 * NEW command line interface for IP firewall facility 19 * 20 * $FreeBSD: src/sbin/ipfw/ipfw2.c,v 1.4.2.13 2003/05/27 22:21:11 gshapiro Exp $ 21 */ 22 23 #include <sys/param.h> 24 #include <sys/mbuf.h> 25 #include <sys/socket.h> 26 #include <sys/sockio.h> 27 #include <sys/sysctl.h> 28 #include <sys/time.h> 29 #include <sys/wait.h> 30 31 #include <arpa/inet.h> 32 #include <ctype.h> 33 #include <dlfcn.h> 34 #include <err.h> 35 #include <errno.h> 36 #include <grp.h> 37 #include <limits.h> 38 #include <netdb.h> 39 #include <pwd.h> 40 #include <sysexits.h> 41 #include <signal.h> 42 #include <stdio.h> 43 #include <stdlib.h> 44 #include <stdarg.h> 45 #include <string.h> 46 #include <timeconv.h> 47 #include <unistd.h> 48 49 #include <netinet/in.h> 50 #include <netinet/in_systm.h> 51 #include <netinet/ip.h> 52 #include <netinet/ip_icmp.h> 53 #include <netinet/tcp.h> 54 #include <net/if.h> 55 #include <net/if_dl.h> 56 #include <net/route.h> 57 #include <net/ethernet.h> 58 59 60 #include "../../sys/net/ipfw3/ip_fw3.h" 61 #include "../../sys/net/dummynet3/ip_dummynet3.h" 62 #include "../../sys/net/libalias/alias.h" 63 #include "../../sys/net/ipfw3_basic/ip_fw3_basic.h" 64 #include "../../sys/net/ipfw3_nat/ip_fw3_nat.h" 65 #include "ipfw.h" 66 67 68 #define KEYWORD_SIZE 256 69 #define MAPPING_SIZE 256 70 71 #define MAX_KEYWORD_LEN 20 72 #define MAX_ARGS 32 73 #define WHITESP " \t\f\v\n\r" 74 #define IPFW_LIB_PATH "/usr/lib/libipfw3%s.so" 75 #define IP_MASK_ALL 0xffffffff 76 #define NAT_BUF_LEN 1024 77 /* 78 * we use IPPROTO_ETHERTYPE as a fake protocol id to call the print routines 79 * This is only used in this code. 80 */ 81 #define IPPROTO_ETHERTYPE 0x1000 82 83 /* 84 * This macro returns the size of a struct sockaddr when passed 85 * through a routing socket. Basically we round up sa_len to 86 * a multiple of sizeof(long), with a minimum of sizeof(long). 87 * The check for a NULL pointer is just a convenience, probably never used. 88 * The case sa_len == 0 should only apply to empty structures. 89 */ 90 #define SA_SIZE(sa) \ 91 ( (!(sa) || ((struct sockaddr *)(sa))->sa_len == 0) ? \ 92 sizeof(long) : \ 93 1 + ( (((struct sockaddr *)(sa))->sa_len - 1) | (sizeof(long) - 1) ) ) 94 95 /* 96 * show_rules() prints the body of an ipfw rule. 97 * Because the standard rule has at least proto src_ip dst_ip, we use 98 * a helper function to produce these entries if not provided explicitly. 99 * The first argument is the list of fields we have, the second is 100 * the list of fields we want to be printed. 101 * 102 * Special cases if we have provided a MAC header: 103 * + if the rule does not contain IP addresses/ports, do not print them; 104 * + if the rule does not contain an IP proto, print "all" instead of "ip"; 105 * 106 */ 107 #define HAVE_PROTO 0x0001 108 #define HAVE_SRCIP 0x0002 109 #define HAVE_DSTIP 0x0004 110 #define HAVE_MAC 0x0008 111 #define HAVE_MACTYPE 0x0010 112 #define HAVE_OPTIONS 0x8000 113 114 #define HAVE_IP (HAVE_PROTO | HAVE_SRCIP | HAVE_DSTIP) 115 116 /* 117 * Definition of a port range, and macros to deal with values. 118 * FORMAT: HI 16-bits == first port in range, 0 == all ports. 119 * LO 16-bits == number of ports in range 120 * NOTES: - Port values are not stored in network byte order. 121 */ 122 123 #define port_range u_long 124 125 #define GETLOPORT(x) ((x) >> 0x10) 126 #define GETNUMPORTS(x) ((x) & 0x0000ffff) 127 #define GETHIPORT(x) (GETLOPORT((x)) + GETNUMPORTS((x))) 128 129 /* Set y to be the low-port value in port_range variable x. */ 130 #define SETLOPORT(x, y) ((x) = ((x) & 0x0000ffff) | ((y) << 0x10)) 131 132 /* Set y to be the number of ports in port_range variable x. */ 133 #define SETNUMPORTS(x, y) ((x) = ((x) & 0xffff0000) | (y)) 134 135 #define INC_ARGCV() do { \ 136 (*_av)++; \ 137 (*_ac)--; \ 138 av = *_av; \ 139 ac = *_ac; \ 140 } while (0) 141 142 143 int ipfw_socket = -1; /* main RAW socket */ 144 int do_resolv, /* Would try to resolve all */ 145 do_acct, /* Show packet/byte count */ 146 do_time, /* Show time stamps */ 147 do_quiet = 1, /* Be quiet , default is quiet*/ 148 do_force, /* Don't ask for confirmation */ 149 do_pipe, /* this cmd refers to a pipe */ 150 do_nat, /* Nat configuration. */ 151 do_sort, /* field to sort results (0 = no) */ 152 do_dynamic, /* display dynamic rules */ 153 do_expired, /* display expired dynamic rules */ 154 do_compact, /* show rules in compact mode */ 155 show_sets, /* display rule sets */ 156 verbose; 157 158 enum tokens { 159 TOK_NULL=0, 160 161 TOK_IP, 162 TOK_IF, 163 TOK_ALOG, 164 TOK_DENY_INC, 165 TOK_SAME_PORTS, 166 TOK_UNREG_ONLY, 167 TOK_RESET_ADDR, 168 TOK_ALIAS_REV, 169 TOK_PROXY_ONLY, 170 TOK_REDIR_ADDR, 171 TOK_REDIR_PORT, 172 TOK_REDIR_PROTO, 173 174 TOK_PIPE, 175 TOK_QUEUE, 176 TOK_PLR, 177 TOK_NOERROR, 178 TOK_BUCKETS, 179 TOK_DSTIP, 180 TOK_SRCIP, 181 TOK_DSTPORT, 182 TOK_SRCPORT, 183 TOK_ALL, 184 TOK_MASK, 185 TOK_BW, 186 TOK_DELAY, 187 TOK_RED, 188 TOK_GRED, 189 TOK_DROPTAIL, 190 TOK_PROTO, 191 TOK_WEIGHT, 192 }; 193 194 struct char_int_map dummynet_params[] = { 195 { "plr", TOK_PLR }, 196 { "noerror", TOK_NOERROR }, 197 { "buckets", TOK_BUCKETS }, 198 { "dst-ip", TOK_DSTIP }, 199 { "src-ip", TOK_SRCIP }, 200 { "dst-port", TOK_DSTPORT }, 201 { "src-port", TOK_SRCPORT }, 202 { "proto", TOK_PROTO }, 203 { "weight", TOK_WEIGHT }, 204 { "all", TOK_ALL }, 205 { "mask", TOK_MASK }, 206 { "droptail", TOK_DROPTAIL }, 207 { "red", TOK_RED }, 208 { "gred", TOK_GRED }, 209 { "bw", TOK_BW }, 210 { "bandwidth", TOK_BW }, 211 { "delay", TOK_DELAY }, 212 { "pipe", TOK_PIPE }, 213 { "queue", TOK_QUEUE }, 214 { "dummynet-params", TOK_NULL }, 215 { NULL, 0 } 216 }; 217 218 struct char_int_map nat_params[] = { 219 { "ip", TOK_IP }, 220 { "if", TOK_IF }, 221 { "log", TOK_ALOG }, 222 { "deny_in", TOK_DENY_INC }, 223 { "same_ports", TOK_SAME_PORTS }, 224 { "unreg_only", TOK_UNREG_ONLY }, 225 { "reset", TOK_RESET_ADDR }, 226 { "reverse", TOK_ALIAS_REV }, 227 { "proxy_only", TOK_PROXY_ONLY }, 228 { "redirect_addr", TOK_REDIR_ADDR }, 229 { "redirect_port", TOK_REDIR_PORT }, 230 { "redirect_proto", TOK_REDIR_PROTO }, 231 { NULL, 0 }, 232 }; 233 234 struct ipfw_keyword { 235 int type; 236 char word[MAX_KEYWORD_LEN]; 237 int module; 238 int opcode; 239 }; 240 241 struct ipfw_mapping { 242 int type; 243 int module; 244 int opcode; 245 parser_func parser; 246 shower_func shower; 247 }; 248 249 struct ipfw_keyword keywords[KEYWORD_SIZE]; 250 struct ipfw_mapping mappings[MAPPING_SIZE]; 251 252 static int 253 match_token(struct char_int_map *table, char *string) 254 { 255 while (table->key) { 256 if (strcmp(table->key, string) == 0) { 257 return table->val; 258 } 259 table++; 260 } 261 return 0; 262 } 263 264 static void 265 get_modules(char *modules_str, int len) 266 { 267 if (do_get_x(IP_FW_MODULE, modules_str, &len) < 0) 268 errx(EX_USAGE, "ipfw3 not loaded."); 269 } 270 271 static void 272 list_modules(int ac, char *av[]) 273 { 274 void *module_str = NULL; 275 int len = 1024; 276 if ((module_str = realloc(module_str, len)) == NULL) 277 err(EX_OSERR, "realloc"); 278 279 get_modules(module_str, len); 280 printf("%s", (char *)module_str); 281 } 282 void 283 parse_accept(ipfw_insn **cmd, int *ac, char **av[]) 284 { 285 (*cmd)->opcode = O_BASIC_ACCEPT; 286 (*cmd)->module = MODULE_BASIC_ID; 287 (*cmd)->len = (*cmd)->len|LEN_OF_IPFWINSN; 288 NEXT_ARG1; 289 } 290 291 void 292 parse_deny(ipfw_insn **cmd, int *ac, char **av[]) 293 { 294 (*cmd)->opcode = O_BASIC_DENY; 295 (*cmd)->module = MODULE_BASIC_ID; 296 (*cmd)->len = (*cmd)->len|LEN_OF_IPFWINSN; 297 NEXT_ARG1; 298 } 299 300 void 301 show_accept(ipfw_insn *cmd) 302 { 303 printf(" allow"); 304 } 305 306 void 307 show_deny(ipfw_insn *cmd) 308 { 309 printf(" deny"); 310 } 311 312 static void 313 load_modules(void) 314 { 315 const char *error; 316 init_module mod_init_func; 317 void *module_lib; 318 char module_lib_file[50]; 319 void *module_str = NULL; 320 int len = 1024; 321 322 if ((module_str = realloc(module_str, len)) == NULL) 323 err(EX_OSERR, "realloc"); 324 325 get_modules(module_str, len); 326 327 const char s[2] = ","; 328 char *token; 329 token = strtok(module_str, s); 330 while (token != NULL) { 331 sprintf(module_lib_file, IPFW_LIB_PATH, token); 332 token = strtok(NULL, s); 333 module_lib = dlopen(module_lib_file, RTLD_LAZY); 334 if (!module_lib) { 335 fprintf(stderr, "Couldn't open %s: %s\n", 336 module_lib_file, dlerror()); 337 exit(EX_SOFTWARE); 338 } 339 mod_init_func = dlsym(module_lib, "load_module"); 340 if ((error = dlerror())) 341 { 342 fprintf(stderr, "Couldn't find init function: %s\n", error); 343 exit(EX_SOFTWARE); 344 } 345 (*mod_init_func)((register_func)register_ipfw_func, 346 (register_keyword)register_ipfw_keyword); 347 } 348 } 349 350 void 351 prepare_default_funcs(void) 352 { 353 /* register allow*/ 354 register_ipfw_keyword(MODULE_BASIC_ID, O_BASIC_ACCEPT, 355 "allow", IPFW_KEYWORD_TYPE_ACTION); 356 register_ipfw_keyword(MODULE_BASIC_ID, O_BASIC_ACCEPT, 357 "accept", IPFW_KEYWORD_TYPE_ACTION); 358 register_ipfw_func(MODULE_BASIC_ID, O_BASIC_ACCEPT, 359 (parser_func)parse_accept, (shower_func)show_accept); 360 /* register deny*/ 361 register_ipfw_keyword(MODULE_BASIC_ID, O_BASIC_DENY, "deny", 362 IPFW_KEYWORD_TYPE_ACTION); 363 register_ipfw_keyword(MODULE_BASIC_ID, O_BASIC_DENY, "reject", 364 IPFW_KEYWORD_TYPE_ACTION); 365 register_ipfw_func(MODULE_BASIC_ID, O_BASIC_DENY, 366 (parser_func)parse_deny, (shower_func)show_deny); 367 } 368 369 void 370 register_ipfw_keyword(int module, int opcode, char *word, int type) 371 { 372 struct ipfw_keyword *tmp; 373 374 tmp=keywords; 375 for(;;) { 376 if (tmp->type == IPFW_KEYWORD_TYPE_NONE) { 377 strcpy(tmp->word, word); 378 tmp->module = module; 379 tmp->opcode = opcode; 380 tmp->type = type; 381 break; 382 } else { 383 if (strcmp(tmp->word, word) == 0) 384 errx(EX_USAGE, "keyword `%s' exists", word); 385 else 386 tmp++; 387 } 388 } 389 } 390 391 void 392 register_ipfw_func(int module, int opcode, parser_func parser, shower_func shower) 393 { 394 struct ipfw_mapping *tmp; 395 396 tmp = mappings; 397 while (1) { 398 if (tmp->type == IPFW_MAPPING_TYPE_NONE) { 399 tmp->module = module; 400 tmp->opcode = opcode; 401 tmp->parser = parser; 402 tmp->shower = shower; 403 tmp->type = IPFW_MAPPING_TYPE_IN_USE; 404 break; 405 } else { 406 if (tmp->opcode == opcode && tmp->module == module) { 407 errx(EX_USAGE, "func `%d' of module `%d' exists", 408 opcode, module); 409 break; 410 } else { 411 tmp++; 412 } 413 } 414 } 415 } 416 417 static void 418 show_rules(struct ipfw_ioc_rule *rule, int pcwidth, int bcwidth) 419 { 420 static int twidth = 0; 421 ipfw_insn *cmd; 422 int l, or_block = 0; /* we are in an or block */ 423 424 u_int32_t set_disable = rule->set_disable; 425 426 if (set_disable & (1 << rule->set)) { /* disabled */ 427 if (!show_sets) 428 return; 429 else 430 printf("# DISABLED "); 431 } 432 printf("%05u ", rule->rulenum); 433 434 if (do_acct) 435 printf("%*ju %*ju ", pcwidth, (uintmax_t)rule->pcnt, bcwidth, 436 (uintmax_t)rule->bcnt); 437 438 if (do_time == 1) { 439 char timestr[30]; 440 441 if (twidth == 0) { 442 strcpy(timestr, ctime((time_t *)&twidth)); 443 *strchr(timestr, '\n') = '\0'; 444 twidth = strlen(timestr); 445 } 446 if (rule->timestamp) { 447 time_t t = _long_to_time(rule->timestamp); 448 449 strcpy(timestr, ctime(&t)); 450 *strchr(timestr, '\n') = '\0'; 451 printf("%s ", timestr); 452 } else { 453 printf("%*s ", twidth, " "); 454 } 455 } else if (do_time == 2) { 456 printf( "%10u ", rule->timestamp); 457 } 458 459 if (show_sets) 460 printf("set %d ", rule->set); 461 462 463 struct ipfw_keyword *k; 464 struct ipfw_mapping *m; 465 shower_func fn, comment_fn = NULL; 466 ipfw_insn *comment_cmd; 467 int i, j, changed; 468 469 /* 470 * show others and actions 471 */ 472 for (l = rule->cmd_len - rule->act_ofs, cmd = ACTION_PTR(rule); 473 l > 0; l -= F_LEN(cmd), 474 cmd = (ipfw_insn *)((uint32_t *)cmd + F_LEN(cmd))) { 475 k = keywords; 476 m = mappings; 477 for (i = 1; i< KEYWORD_SIZE; i++, k++) { 478 if ( k->module == cmd->module && k->opcode == cmd->opcode ) { 479 for (j = 1; j< MAPPING_SIZE; j++, m++) { 480 if (m->type == IPFW_MAPPING_TYPE_IN_USE && 481 m->module == cmd->module && 482 m->opcode == cmd->opcode) { 483 if (cmd->module == MODULE_BASIC_ID && 484 cmd->opcode == O_BASIC_COMMENT) { 485 comment_fn = m->shower; 486 comment_cmd = cmd; 487 } else { 488 fn = m->shower; 489 (*fn)(cmd); 490 } 491 if (cmd->module == MODULE_BASIC_ID && 492 cmd->opcode == 493 O_BASIC_CHECK_STATE) { 494 goto done; 495 } 496 break; 497 } 498 } 499 break; 500 } 501 } 502 } 503 504 /* 505 * show proto 506 */ 507 changed=0; 508 for (l = rule->act_ofs, cmd = rule->cmd; 509 l > 0;l -= F_LEN(cmd) , 510 cmd = (ipfw_insn *)((uint32_t *)cmd + F_LEN(cmd))) { 511 k = keywords; 512 m = mappings; 513 for (i = 1; i< KEYWORD_SIZE; i++, k++) { 514 if (k->type == IPFW_KEYWORD_TYPE_FILTER && 515 strcmp(k->word, "proto") == 0) { 516 if (k->module == cmd->module && 517 k->opcode == cmd->opcode) { 518 for (j = 1; j< MAPPING_SIZE; j++, m++) { 519 if (m->type == IPFW_MAPPING_TYPE_IN_USE && 520 k->module == m->module && 521 k->opcode == m->opcode) { 522 if (cmd->len & F_NOT) { 523 printf(" not"); 524 } 525 fn = m->shower; 526 (*fn)(cmd); 527 changed = 1; 528 goto show_from; 529 } 530 } 531 } 532 } 533 } 534 } 535 if (!changed && !do_quiet) 536 printf(" ip"); 537 538 /* 539 * show from 540 */ 541 show_from: 542 changed = 0; 543 for (l = rule->act_ofs, cmd = rule->cmd; 544 l > 0; l -= F_LEN(cmd), 545 cmd = (ipfw_insn *)((uint32_t *)cmd + F_LEN(cmd))) { 546 k = keywords; 547 m = mappings; 548 for (i = 1; i< KEYWORD_SIZE; i++, k++) { 549 if (k->type == IPFW_KEYWORD_TYPE_FILTER && 550 strcmp(k->word, "from") == 0) { 551 if (k->module == cmd->module && 552 k->opcode == cmd->opcode) { 553 for (j = 1; j< MAPPING_SIZE; j++, m++) { 554 if (m->type == IPFW_MAPPING_TYPE_IN_USE && 555 k->module == m->module && 556 k->opcode == m->opcode) { 557 if (cmd->len & F_NOT) 558 printf(" not"); 559 560 fn = m->shower; 561 (*fn)(cmd); 562 changed = 1; 563 goto show_to; 564 } 565 } 566 } 567 } 568 } 569 } 570 if (!changed && !do_quiet) 571 printf(" from any"); 572 573 /* 574 * show to 575 */ 576 show_to: 577 changed = 0; 578 for (l = rule->act_ofs, cmd = rule->cmd; 579 l > 0; l -= F_LEN(cmd), 580 cmd = (ipfw_insn *)((uint32_t *)cmd + F_LEN(cmd))) { 581 k = keywords; 582 m = mappings; 583 for (i = 1; i< KEYWORD_SIZE; i++, k++) { 584 if (k->type == IPFW_KEYWORD_TYPE_FILTER && 585 strcmp(k->word, "to") == 0) { 586 if (k->module == cmd->module && 587 k->opcode == cmd->opcode) { 588 for (j = 1; j < MAPPING_SIZE; j++, m++) { 589 if (m->type == IPFW_MAPPING_TYPE_IN_USE && 590 k->module == m->module && 591 k->opcode == m->opcode ) { 592 if (cmd->len & F_NOT) 593 printf(" not"); 594 595 fn = m->shower; 596 (*fn)(cmd); 597 changed = 1; 598 goto show_filter; 599 } 600 } 601 } 602 } 603 } 604 } 605 if (!changed && !do_quiet) 606 printf(" to any"); 607 608 /* 609 * show other filters 610 */ 611 show_filter: 612 for (l = rule->act_ofs, cmd = rule->cmd, m = mappings; 613 l > 0; l -= F_LEN(cmd), 614 cmd=(ipfw_insn *)((uint32_t *)cmd + F_LEN(cmd))) { 615 k = keywords; 616 m = mappings; 617 for (i = 1; i< KEYWORD_SIZE; i++, k++) { 618 if (k->module == cmd->module && k->opcode == cmd->opcode) { 619 if (strcmp(k->word, "proto") != 0 && 620 strcmp(k->word, "from") !=0 && 621 strcmp(k->word, "to") !=0) { 622 for (j = 1; j < MAPPING_SIZE; j++, m++) { 623 if (m->module == cmd->module && 624 m->opcode == cmd->opcode) { 625 if (cmd->len & F_NOT) 626 printf(" not"); 627 628 fn = m->shower; 629 (*fn)(cmd); 630 break; 631 } 632 } 633 } 634 } 635 } 636 } 637 638 if (cmd->len & F_OR) { 639 printf(" or"); 640 or_block = 1; 641 } else if (or_block) { 642 printf(" }"); 643 or_block = 0; 644 } 645 646 /* show the comment in the end */ 647 if (comment_fn != NULL) { 648 (*comment_fn)(comment_cmd); 649 } 650 done: 651 printf("\n"); 652 } 653 654 static void 655 show_states(struct ipfw_ioc_state *d, int pcwidth, int bcwidth) 656 { 657 struct protoent *pe; 658 struct in_addr a; 659 660 printf("%05u ", d->rulenum); 661 if (do_acct) { 662 printf("%*ju %*ju ", pcwidth, (uintmax_t)d->pcnt, 663 bcwidth, (uintmax_t)d->bcnt); 664 } 665 666 if (do_time == 1) { 667 /* state->timestamp */ 668 char timestr[30]; 669 time_t t = _long_to_time(d->timestamp); 670 strcpy(timestr, ctime(&t)); 671 *strchr(timestr, '\n') = '\0'; 672 printf(" (%s", timestr); 673 674 /* state->lifetime */ 675 printf(" %ds", d->lifetime); 676 677 /* state->expiry */ 678 if (d->expiry !=0) { 679 t = _long_to_time(d->expiry); 680 strcpy(timestr, ctime(&t)); 681 *strchr(timestr, '\n') = '\0'; 682 printf(" %s)", timestr); 683 } else { 684 printf(" 0)"); 685 } 686 687 } else if (do_time == 2) { 688 printf("(%u %ds %u) ", d->timestamp, d->lifetime, d->expiry); 689 } 690 691 if ((pe = getprotobynumber(d->flow_id.proto)) != NULL) 692 printf(" %s", pe->p_name); 693 else 694 printf(" proto %u", d->flow_id.proto); 695 696 a.s_addr = htonl(d->flow_id.src_ip); 697 printf(" %s %d", inet_ntoa(a), d->flow_id.src_port); 698 699 a.s_addr = htonl(d->flow_id.dst_ip); 700 printf(" <-> %s %d", inet_ntoa(a), d->flow_id.dst_port); 701 printf(" CPU %d", d->cpuid); 702 printf("\n"); 703 } 704 705 int 706 sort_q(const void *pa, const void *pb) 707 { 708 int rev = (do_sort < 0); 709 int field = rev ? -do_sort : do_sort; 710 long long res = 0; 711 const struct dn_ioc_flowqueue *a = pa; 712 const struct dn_ioc_flowqueue *b = pb; 713 714 switch(field) { 715 case 1: /* pkts */ 716 res = a->len - b->len; 717 break; 718 case 2: /* bytes */ 719 res = a->len_bytes - b->len_bytes; 720 break; 721 722 case 3: /* tot pkts */ 723 res = a->tot_pkts - b->tot_pkts; 724 break; 725 726 case 4: /* tot bytes */ 727 res = a->tot_bytes - b->tot_bytes; 728 break; 729 } 730 if (res < 0) 731 res = -1; 732 if (res > 0) 733 res = 1; 734 return (int)(rev ? res : -res); 735 } 736 737 static void 738 show_queues(struct dn_ioc_flowset *fs, struct dn_ioc_flowqueue *q) 739 { 740 int l; 741 742 printf("mask: 0x%02x 0x%08x/0x%04x -> 0x%08x/0x%04x\n", 743 fs->flow_mask.u.ip.proto, 744 fs->flow_mask.u.ip.src_ip, fs->flow_mask.u.ip.src_port, 745 fs->flow_mask.u.ip.dst_ip, fs->flow_mask.u.ip.dst_port); 746 if (fs->rq_elements == 0) 747 return; 748 749 printf("BKT Prot ___Source IP/port____ " 750 "____Dest. IP/port____ Tot_pkt/bytes Pkt/Byte Drp\n"); 751 if (do_sort != 0) 752 heapsort(q, fs->rq_elements, sizeof(*q), sort_q); 753 for (l = 0; l < fs->rq_elements; l++) { 754 struct in_addr ina; 755 struct protoent *pe; 756 757 ina.s_addr = htonl(q[l].id.u.ip.src_ip); 758 printf("%3d ", q[l].hash_slot); 759 pe = getprotobynumber(q[l].id.u.ip.proto); 760 if (pe) 761 printf("%-4s ", pe->p_name); 762 else 763 printf("%4u ", q[l].id.u.ip.proto); 764 printf("%15s/%-5d ", 765 inet_ntoa(ina), q[l].id.u.ip.src_port); 766 ina.s_addr = htonl(q[l].id.u.ip.dst_ip); 767 printf("%15s/%-5d ", 768 inet_ntoa(ina), q[l].id.u.ip.dst_port); 769 printf("%4ju %8ju %2u %4u %3u\n", 770 (uintmax_t)q[l].tot_pkts, (uintmax_t)q[l].tot_bytes, 771 q[l].len, q[l].len_bytes, q[l].drops); 772 if (verbose) 773 printf(" S %20ju F %20ju\n", 774 (uintmax_t)q[l].S, (uintmax_t)q[l].F); 775 } 776 } 777 778 static void 779 show_flowset_parms(struct dn_ioc_flowset *fs, char *prefix) 780 { 781 char qs[30]; 782 char plr[30]; 783 char red[90]; /* Display RED parameters */ 784 int l; 785 786 l = fs->qsize; 787 if (fs->flags_fs & DN_QSIZE_IS_BYTES) { 788 if (l >= 8192) 789 sprintf(qs, "%d KB", l / 1024); 790 else 791 sprintf(qs, "%d B", l); 792 } else 793 sprintf(qs, "%3d sl.", l); 794 if (fs->plr) 795 sprintf(plr, "plr %f", 1.0 * fs->plr / (double)(0x7fffffff)); 796 else 797 plr[0] = '\0'; 798 if (fs->flags_fs & DN_IS_RED) /* RED parameters */ 799 sprintf(red, 800 "\n\t %cRED w_q %f min_th %d max_th %d max_p %f", 801 (fs->flags_fs & DN_IS_GENTLE_RED) ? 'G' : ' ', 802 1.0 * fs->w_q / (double)(1 << SCALE_RED), 803 SCALE_VAL(fs->min_th), 804 SCALE_VAL(fs->max_th), 805 1.0 * fs->max_p / (double)(1 << SCALE_RED)); 806 else 807 sprintf(red, "droptail"); 808 809 printf("%s %s%s %d queues (%d buckets) %s\n", 810 prefix, qs, plr, fs->rq_elements, fs->rq_size, red); 811 } 812 813 static void 814 show_pipes(void *data, int nbytes, int ac, char *av[]) 815 { 816 u_long rulenum; 817 void *next = data; 818 struct dn_ioc_pipe *p = (struct dn_ioc_pipe *)data; 819 struct dn_ioc_flowset *fs; 820 struct dn_ioc_flowqueue *q; 821 int l; 822 823 if (ac > 0) 824 rulenum = strtoul(*av++, NULL, 10); 825 else 826 rulenum = 0; 827 for (; nbytes >= sizeof(*p); p = (struct dn_ioc_pipe *)next) { 828 double b = p->bandwidth; 829 char buf[30]; 830 char prefix[80]; 831 832 if (p->fs.fs_type != DN_IS_PIPE) 833 break; /* done with pipes, now queues */ 834 835 /* 836 * compute length, as pipe have variable size 837 */ 838 l = sizeof(*p) + p->fs.rq_elements * sizeof(*q); 839 next = (void *)p + l; 840 nbytes -= l; 841 842 if (rulenum != 0 && rulenum != p->pipe_nr) 843 continue; 844 845 /* 846 * Print rate 847 */ 848 if (b == 0) 849 sprintf(buf, "unlimited"); 850 else if (b >= 1000000) 851 sprintf(buf, "%7.3f Mbit/s", b/1000000); 852 else if (b >= 1000) 853 sprintf(buf, "%7.3f Kbit/s", b/1000); 854 else 855 sprintf(buf, "%7.3f bit/s ", b); 856 857 sprintf(prefix, "%05d: %s %4d ms ", 858 p->pipe_nr, buf, p->delay); 859 show_flowset_parms(&p->fs, prefix); 860 if (verbose) 861 printf(" V %20ju\n", (uintmax_t)p->V >> MY_M); 862 863 q = (struct dn_ioc_flowqueue *)(p+1); 864 show_queues(&p->fs, q); 865 } 866 867 for (fs = next; nbytes >= sizeof(*fs); fs = next) { 868 char prefix[80]; 869 870 if (fs->fs_type != DN_IS_QUEUE) 871 break; 872 l = sizeof(*fs) + fs->rq_elements * sizeof(*q); 873 next = (void *)fs + l; 874 nbytes -= l; 875 q = (struct dn_ioc_flowqueue *)(fs+1); 876 sprintf(prefix, "q%05d: weight %d pipe %d ", 877 fs->fs_nr, fs->weight, fs->parent_nr); 878 show_flowset_parms(fs, prefix); 879 show_queues(fs, q); 880 } 881 } 882 883 /* 884 * This one handles all set-related commands 885 * ipfw set { show | enable | disable } 886 * ipfw set swap X Y 887 * ipfw set move X to Y 888 * ipfw set move rule X to Y 889 */ 890 static void 891 sets_handler(int ac, char *av[]) 892 { 893 u_int32_t set_disable, masks[2]; 894 u_int16_t rulenum; 895 u_int8_t cmd, new_set; 896 int i, nbytes; 897 898 NEXT_ARG; 899 if (!ac) 900 errx(EX_USAGE, "set needs command"); 901 if (!strncmp(*av, "show", strlen(*av)) ) { 902 void *data = NULL; 903 char *msg; 904 int nalloc=1000; 905 nbytes = nalloc; 906 907 while (nbytes >= nalloc) { 908 nalloc = nalloc * 2+321; 909 nbytes = nalloc; 910 if (data == NULL) { 911 if ((data = malloc(nbytes)) == NULL) { 912 err(EX_OSERR, "malloc"); 913 } 914 } else if ((data = realloc(data, nbytes)) == NULL) { 915 err(EX_OSERR, "realloc"); 916 } 917 if (do_get_x(IP_FW_GET, data, &nbytes) < 0) { 918 err(EX_OSERR, "getsockopt(IP_FW_GET)"); 919 } 920 } 921 set_disable = ((struct ipfw_ioc_rule *)data)->set_disable; 922 for (i = 0, msg = "disable" ; i < 31; i++) 923 if ( (set_disable & (1<<i))) { 924 printf("%s %d", msg, i); 925 msg = ""; 926 } 927 msg = (set_disable) ? " enable" : "enable"; 928 for (i = 0; i < 31; i++) 929 if ( !(set_disable & (1<<i))) { 930 printf("%s %d", msg, i); 931 msg = ""; 932 } 933 printf("\n"); 934 } else if (!strncmp(*av, "swap", strlen(*av))) { 935 NEXT_ARG; 936 if (ac != 2) 937 errx(EX_USAGE, "set swap needs 2 set numbers\n"); 938 rulenum = atoi(av[0]); 939 new_set = atoi(av[1]); 940 if (!isdigit(*(av[0])) || rulenum > 30) 941 errx(EX_DATAERR, "invalid set number %s\n", av[0]); 942 if (!isdigit(*(av[1])) || new_set > 30) 943 errx(EX_DATAERR, "invalid set number %s\n", av[1]); 944 masks[0] = (4 << 24) | (new_set << 16) | (rulenum); 945 i = do_set_x(IP_FW_DEL, masks, sizeof(u_int32_t)); 946 } else if (!strncmp(*av, "move", strlen(*av))) { 947 NEXT_ARG; 948 if (ac && !strncmp(*av, "rule", strlen(*av))) { 949 cmd = 2; 950 NEXT_ARG; 951 } else 952 cmd = 3; 953 if (ac != 3 || strncmp(av[1], "to", strlen(*av))) 954 errx(EX_USAGE, "syntax: set move [rule] X to Y\n"); 955 rulenum = atoi(av[0]); 956 new_set = atoi(av[2]); 957 if (!isdigit(*(av[0])) || (cmd == 3 && rulenum > 30) || 958 (cmd == 2 && rulenum == 65535) ) 959 errx(EX_DATAERR, "invalid source number %s\n", av[0]); 960 if (!isdigit(*(av[2])) || new_set > 30) 961 errx(EX_DATAERR, "invalid dest. set %s\n", av[1]); 962 masks[0] = (cmd << 24) | (new_set << 16) | (rulenum); 963 i = do_set_x(IP_FW_DEL, masks, sizeof(u_int32_t)); 964 } else if (!strncmp(*av, "disable", strlen(*av)) || 965 !strncmp(*av, "enable", strlen(*av)) ) { 966 int which = !strncmp(*av, "enable", strlen(*av)) ? 1 : 0; 967 968 NEXT_ARG; 969 masks[0] = masks[1] = 0; 970 971 while (ac) { 972 if (isdigit(**av)) { 973 i = atoi(*av); 974 if (i < 0 || i > 30) 975 errx(EX_DATAERR, "invalid set number %d\n", i); 976 masks[which] |= (1<<i); 977 } else if (!strncmp(*av, "disable", strlen(*av))) 978 which = 0; 979 else if (!strncmp(*av, "enable", strlen(*av))) 980 which = 1; 981 else 982 errx(EX_DATAERR, "invalid set command %s\n", *av); 983 NEXT_ARG; 984 } 985 if ( (masks[0] & masks[1]) != 0 ) 986 errx(EX_DATAERR, "cannot enable and disable the same set\n"); 987 i = do_set_x(IP_FW_DEL, masks, sizeof(masks)); 988 if (i) 989 warn("set enable/disable: setsockopt(IP_FW_DEL)"); 990 } else 991 errx(EX_USAGE, "invalid set command %s\n", *av); 992 } 993 994 static void 995 add_state(int ac, char *av[]) 996 { 997 struct ipfw_ioc_state ioc_state; 998 ioc_state.expiry = 0; 999 ioc_state.lifetime = 0; 1000 NEXT_ARG; 1001 if (strcmp(*av, "rulenum") == 0) { 1002 NEXT_ARG; 1003 ioc_state.rulenum = atoi(*av); 1004 } else { 1005 errx(EX_USAGE, "ipfw state add rule"); 1006 } 1007 NEXT_ARG; 1008 struct protoent *pe; 1009 pe = getprotobyname(*av); 1010 ioc_state.flow_id.proto = pe->p_proto; 1011 1012 NEXT_ARG; 1013 ioc_state.flow_id.src_ip = inet_addr(*av); 1014 1015 NEXT_ARG; 1016 ioc_state.flow_id.src_port = atoi(*av); 1017 1018 NEXT_ARG; 1019 ioc_state.flow_id.dst_ip = inet_addr(*av); 1020 1021 NEXT_ARG; 1022 ioc_state.flow_id.dst_port = atoi(*av); 1023 1024 NEXT_ARG; 1025 if (strcmp(*av, "live") == 0) { 1026 NEXT_ARG; 1027 ioc_state.lifetime = atoi(*av); 1028 NEXT_ARG; 1029 } 1030 1031 if (strcmp(*av, "expiry") == 0) { 1032 NEXT_ARG; 1033 ioc_state.expiry = strtoul(*av, NULL, 10); 1034 printf("ioc_state.expiry=%d\n", ioc_state.expiry); 1035 } 1036 1037 if (do_set_x(IP_FW_STATE_ADD, &ioc_state, sizeof(struct ipfw_ioc_state)) < 0 ) { 1038 err(EX_UNAVAILABLE, "do_set_x(IP_FW_STATE_ADD)"); 1039 } 1040 if (!do_quiet) { 1041 printf("Flushed all states.\n"); 1042 } 1043 } 1044 1045 static void 1046 delete_state(int ac, char *av[]) 1047 { 1048 int rulenum; 1049 NEXT_ARG; 1050 if (ac == 1 && isdigit(**av)) 1051 rulenum = atoi(*av); 1052 if (do_set_x(IP_FW_STATE_DEL, &rulenum, sizeof(int)) < 0 ) 1053 err(EX_UNAVAILABLE, "do_set_x(IP_FW_STATE_DEL)"); 1054 if (!do_quiet) 1055 printf("Flushed all states.\n"); 1056 } 1057 1058 static void 1059 flush_state(int ac, char *av[]) 1060 { 1061 if (!do_force) { 1062 int c; 1063 1064 printf("Are you sure? [yn] "); 1065 fflush(stdout); 1066 do { 1067 c = toupper(getc(stdin)); 1068 while (c != '\n' && getc(stdin) != '\n') 1069 if (feof(stdin)) 1070 return; /* and do not flush */ 1071 } while (c != 'Y' && c != 'N'); 1072 if (c == 'N') /* user said no */ 1073 return; 1074 } 1075 if (do_set_x(IP_FW_STATE_FLUSH, NULL, 0) < 0 ) 1076 err(EX_UNAVAILABLE, "do_set_x(IP_FW_STATE_FLUSH)"); 1077 if (!do_quiet) 1078 printf("Flushed all states.\n"); 1079 } 1080 1081 static void 1082 list(int ac, char *av[]) 1083 { 1084 struct ipfw_ioc_state *dynrules, *d; 1085 struct ipfw_ioc_rule *r; 1086 1087 u_long rnum; 1088 void *data = NULL; 1089 int bcwidth, n, nbytes, nstat, ndyn, pcwidth, width; 1090 int exitval = EX_OK, lac; 1091 char **lav, *endptr; 1092 int seen = 0; 1093 int nalloc = 1024; 1094 1095 NEXT_ARG; 1096 1097 /* get rules or pipes from kernel, resizing array as necessary */ 1098 nbytes = nalloc; 1099 1100 while (nbytes >= nalloc) { 1101 nalloc = nalloc * 2 ; 1102 nbytes = nalloc; 1103 if ((data = realloc(data, nbytes)) == NULL) 1104 err(EX_OSERR, "realloc"); 1105 if (do_get_x(IP_FW_GET, data, &nbytes) < 0) 1106 err(EX_OSERR, "do_get_x(IP_FW_GET)"); 1107 } 1108 1109 /* 1110 * Count static rules. 1111 */ 1112 r = data; 1113 nstat = r->static_count; 1114 1115 /* 1116 * Count dynamic rules. This is easier as they have 1117 * fixed size. 1118 */ 1119 dynrules = (struct ipfw_ioc_state *)((void *)r + r->static_len); 1120 ndyn = (nbytes - r->static_len) / sizeof(*dynrules); 1121 1122 /* if showing stats, figure out column widths ahead of time */ 1123 bcwidth = pcwidth = 0; 1124 if (do_acct) { 1125 for (n = 0, r = data; n < nstat; 1126 n++, r = (void *)r + IOC_RULESIZE(r)) { 1127 /* packet counter */ 1128 width = snprintf(NULL, 0, "%ju", (uintmax_t)r->pcnt); 1129 if (width > pcwidth) 1130 pcwidth = width; 1131 1132 /* byte counter */ 1133 width = snprintf(NULL, 0, "%ju", (uintmax_t)r->bcnt); 1134 if (width > bcwidth) 1135 bcwidth = width; 1136 } 1137 } 1138 if (do_dynamic && ndyn) { 1139 for (n = 0, d = dynrules; n < ndyn; n++, d++) { 1140 width = snprintf(NULL, 0, "%ju", (uintmax_t)d->pcnt); 1141 if (width > pcwidth) 1142 pcwidth = width; 1143 1144 width = snprintf(NULL, 0, "%ju", (uintmax_t)d->bcnt); 1145 if (width > bcwidth) 1146 bcwidth = width; 1147 } 1148 } 1149 1150 /* if no rule numbers were specified, list all rules */ 1151 if (ac == 0) { 1152 if (do_dynamic != 2) { 1153 for (n = 0, r = data; n < nstat; n++, 1154 r = (void *)r + IOC_RULESIZE(r)) { 1155 show_rules(r, pcwidth, bcwidth); 1156 } 1157 } 1158 if (do_dynamic && ndyn) { 1159 if (do_dynamic != 2) { 1160 printf("## States (%d):\n", ndyn); 1161 } 1162 for (n = 0, d = dynrules; n < ndyn; n++, d++) 1163 show_states(d, pcwidth, bcwidth); 1164 } 1165 goto done; 1166 } 1167 1168 /* display specific rules requested on command line */ 1169 1170 if (do_dynamic != 2) { 1171 for (lac = ac, lav = av; lac != 0; lac--) { 1172 /* convert command line rule # */ 1173 rnum = strtoul(*lav++, &endptr, 10); 1174 if (*endptr) { 1175 exitval = EX_USAGE; 1176 warnx("invalid rule number: %s", *(lav - 1)); 1177 continue; 1178 } 1179 for (n = seen = 0, r = data; n < nstat; 1180 n++, r = (void *)r + IOC_RULESIZE(r) ) { 1181 if (r->rulenum > rnum) 1182 break; 1183 if (r->rulenum == rnum) { 1184 show_rules(r, pcwidth, bcwidth); 1185 seen = 1; 1186 } 1187 } 1188 if (!seen) { 1189 /* give precedence to other error(s) */ 1190 if (exitval == EX_OK) 1191 exitval = EX_UNAVAILABLE; 1192 warnx("rule %lu does not exist", rnum); 1193 } 1194 } 1195 } 1196 1197 if (do_dynamic && ndyn) { 1198 if (do_dynamic != 2) { 1199 printf("## States (%d):\n", ndyn); 1200 } 1201 for (lac = ac, lav = av; lac != 0; lac--) { 1202 rnum = strtoul(*lav++, &endptr, 10); 1203 if (*endptr) 1204 /* already warned */ 1205 continue; 1206 for (n = 0, d = dynrules; n < ndyn; n++, d++) { 1207 if (d->rulenum > rnum) 1208 break; 1209 if (d->rulenum == rnum) 1210 show_states(d, pcwidth, bcwidth); 1211 } 1212 } 1213 } 1214 1215 ac = 0; 1216 1217 done: 1218 free(data); 1219 1220 if (exitval != EX_OK) 1221 exit(exitval); 1222 } 1223 1224 static void 1225 show_dummynet(int ac, char *av[]) 1226 { 1227 void *data = NULL; 1228 int nbytes; 1229 int nalloc = 1024; /* start somewhere... */ 1230 1231 NEXT_ARG; 1232 1233 nbytes = nalloc; 1234 while (nbytes >= nalloc) { 1235 nalloc = nalloc * 2 + 200; 1236 nbytes = nalloc; 1237 if ((data = realloc(data, nbytes)) == NULL) 1238 err(EX_OSERR, "realloc"); 1239 if (do_get_x(IP_DUMMYNET_GET, data, &nbytes) < 0) { 1240 err(EX_OSERR, "do_get_x(IP_%s_GET)", 1241 do_pipe ? "DUMMYNET" : "FW"); 1242 } 1243 } 1244 1245 show_pipes(data, nbytes, ac, av); 1246 free(data); 1247 } 1248 1249 static void 1250 help(void) 1251 { 1252 fprintf(stderr, "usage: ipfw [options]\n" 1253 " ipfw add [rulenum] [set id] action filters\n" 1254 " ipfw delete [rulenum]\n" 1255 " ipfw flush\n" 1256 " ipfw list [rulenum]\n" 1257 " ipfw show [rulenum]\n" 1258 " ipfw zero [rulenum]\n" 1259 " ipfw set [show|enable|disable]\n" 1260 " ipfw module\n" 1261 " ipfw [enable|disable]\n" 1262 " ipfw log [reset|off|on]\n" 1263 " ipfw nat [config|show|delete]\n" 1264 " ipfw pipe [config|show|delete]\n" 1265 " ipfw state [add|delete|list|show]" 1266 "\nsee ipfw manpage for details\n"); 1267 exit(EX_USAGE); 1268 } 1269 1270 static void 1271 delete_nat_config(int ac, char *av[]) 1272 { 1273 NEXT_ARG; 1274 int i = 0; 1275 if (ac > 0) { 1276 i = atoi(*av); 1277 } 1278 if (do_set_x(IP_FW_NAT_DEL, &i, sizeof(i)) == -1) 1279 err(EX_UNAVAILABLE, "getsockopt(%s)", "IP_FW_NAT_DEL"); 1280 } 1281 1282 static void 1283 delete_rules(int ac, char *av[]) 1284 { 1285 struct dn_ioc_pipe pipe; 1286 u_int32_t rulenum; 1287 int exitval = EX_OK; 1288 int do_set = 0; 1289 int i; 1290 1291 memset(&pipe, 0, sizeof pipe); 1292 1293 NEXT_ARG; 1294 if (ac > 0 && !strncmp(*av, "set", strlen(*av))) { 1295 do_set = 1; /* delete set */ 1296 NEXT_ARG; 1297 } 1298 1299 /* Rule number */ 1300 while (ac && isdigit(**av)) { 1301 i = atoi(*av); 1302 NEXT_ARG; 1303 if (do_pipe) { 1304 if (do_pipe == 1) 1305 pipe.pipe_nr = i; 1306 else 1307 pipe.fs.fs_nr = i; 1308 1309 i = do_set_x(IP_DUMMYNET_DEL, &pipe, sizeof pipe); 1310 if (i) { 1311 exitval = 1; 1312 warn("rule %u: setsockopt(IP_DUMMYNET_DEL)", 1313 do_pipe == 1 ? pipe.pipe_nr : pipe.fs.fs_nr); 1314 } 1315 } else { 1316 rulenum = (i & 0xffff) | (do_set << 24); 1317 i = do_set_x(IP_FW_DEL, &rulenum, sizeof rulenum); 1318 if (i) { 1319 exitval = EX_UNAVAILABLE; 1320 warn("rule %u: setsockopt(IP_FW_DEL)", 1321 rulenum); 1322 } 1323 } 1324 } 1325 if (exitval != EX_OK) 1326 exit(exitval); 1327 } 1328 1329 1330 static unsigned long 1331 getbw(const char *str, u_short *flags, int kb) 1332 { 1333 unsigned long val; 1334 int inbytes = 0; 1335 char *end; 1336 1337 val = strtoul(str, &end, 0); 1338 if (*end == 'k' || *end == 'K') { 1339 ++end; 1340 val *= kb; 1341 } else if (*end == 'm' || *end == 'M') { 1342 ++end; 1343 val *= kb * kb; 1344 } 1345 1346 /* 1347 * Deal with bits or bytes or b(bits) or B(bytes). If there is no 1348 * trailer assume bits. 1349 */ 1350 if (strncasecmp(end, "bit", 3) == 0) { 1351 ; 1352 } else if (strncasecmp(end, "byte", 4) == 0) { 1353 inbytes = 1; 1354 } else if (*end == 'b') { 1355 ; 1356 } else if (*end == 'B') { 1357 inbytes = 1; 1358 } 1359 1360 /* 1361 * Return in bits if flags is NULL, else flag bits 1362 * or bytes in flags and return the unconverted value. 1363 */ 1364 if (inbytes && flags) 1365 *flags |= DN_QSIZE_IS_BYTES; 1366 else if (inbytes && flags == NULL) 1367 val *= 8; 1368 1369 return(val); 1370 } 1371 1372 /* 1373 * config dummynet pipe/queue 1374 */ 1375 static void 1376 config_dummynet(int ac, char **av) 1377 { 1378 struct dn_ioc_pipe pipe; 1379 u_int32_t a; 1380 void *par = NULL; 1381 int i; 1382 char *end; 1383 1384 NEXT_ARG; 1385 memset(&pipe, 0, sizeof pipe); 1386 /* Pipe number */ 1387 if (ac && isdigit(**av)) { 1388 i = atoi(*av); 1389 NEXT_ARG; 1390 if (do_pipe == 1) 1391 pipe.pipe_nr = i; 1392 else 1393 pipe.fs.fs_nr = i; 1394 } 1395 1396 while (ac > 0) { 1397 double d; 1398 1399 int tok = match_token(dummynet_params, *av); 1400 NEXT_ARG; 1401 1402 switch(tok) { 1403 case TOK_NOERROR: 1404 pipe.fs.flags_fs |= DN_NOERROR; 1405 break; 1406 1407 case TOK_PLR: 1408 NEED1("plr needs argument 0..1\n"); 1409 d = strtod(av[0], NULL); 1410 if (d > 1) 1411 d = 1; 1412 else if (d < 0) 1413 d = 0; 1414 pipe.fs.plr = (int)(d*0x7fffffff); 1415 NEXT_ARG; 1416 break; 1417 1418 case TOK_QUEUE: 1419 NEED1("queue needs queue size\n"); 1420 end = NULL; 1421 pipe.fs.qsize = getbw(av[0], &pipe.fs.flags_fs, 1024); 1422 NEXT_ARG; 1423 break; 1424 1425 case TOK_BUCKETS: 1426 NEED1("buckets needs argument\n"); 1427 pipe.fs.rq_size = strtoul(av[0], NULL, 0); 1428 NEXT_ARG; 1429 break; 1430 1431 case TOK_MASK: 1432 NEED1("mask needs mask specifier\n"); 1433 /* 1434 * per-flow queue, mask is dst_ip, dst_port, 1435 * src_ip, src_port, proto measured in bits 1436 */ 1437 par = NULL; 1438 1439 pipe.fs.flow_mask.type = ETHERTYPE_IP; 1440 pipe.fs.flow_mask.u.ip.dst_ip = 0; 1441 pipe.fs.flow_mask.u.ip.src_ip = 0; 1442 pipe.fs.flow_mask.u.ip.dst_port = 0; 1443 pipe.fs.flow_mask.u.ip.src_port = 0; 1444 pipe.fs.flow_mask.u.ip.proto = 0; 1445 end = NULL; 1446 1447 while (ac >= 1) { 1448 u_int32_t *p32 = NULL; 1449 u_int16_t *p16 = NULL; 1450 1451 tok = match_token(dummynet_params, *av); 1452 NEXT_ARG; 1453 switch(tok) { 1454 case TOK_ALL: 1455 /* 1456 * special case, all bits significant 1457 */ 1458 pipe.fs.flow_mask.u.ip.dst_ip = ~0; 1459 pipe.fs.flow_mask.u.ip.src_ip = ~0; 1460 pipe.fs.flow_mask.u.ip.dst_port = ~0; 1461 pipe.fs.flow_mask.u.ip.src_port = ~0; 1462 pipe.fs.flow_mask.u.ip.proto = ~0; 1463 pipe.fs.flags_fs |= DN_HAVE_FLOW_MASK; 1464 goto end_mask; 1465 1466 case TOK_DSTIP: 1467 p32 = &pipe.fs.flow_mask.u.ip.dst_ip; 1468 break; 1469 1470 case TOK_SRCIP: 1471 p32 = &pipe.fs.flow_mask.u.ip.src_ip; 1472 break; 1473 1474 case TOK_DSTPORT: 1475 p16 = &pipe.fs.flow_mask.u.ip.dst_port; 1476 break; 1477 1478 case TOK_SRCPORT: 1479 p16 = &pipe.fs.flow_mask.u.ip.src_port; 1480 break; 1481 1482 case TOK_PROTO: 1483 break; 1484 1485 default: 1486 NEXT_ARG; 1487 goto end_mask; 1488 } 1489 if (ac < 1) 1490 errx(EX_USAGE, "mask: value missing"); 1491 if (*av[0] == '/') { 1492 a = strtoul(av[0]+1, &end, 0); 1493 a = (a == 32) ? ~0 : (1 << a) - 1; 1494 } else 1495 a = strtoul(av[0], &end, 0); 1496 if (p32 != NULL) 1497 *p32 = a; 1498 else if (p16 != NULL) { 1499 if (a > 65535) 1500 errx(EX_DATAERR, 1501 "mask: must be 16 bit"); 1502 *p16 = (u_int16_t)a; 1503 } else { 1504 if (a > 255) 1505 errx(EX_DATAERR, 1506 "mask: must be 8 bit"); 1507 pipe.fs.flow_mask.u.ip.proto = (uint8_t)a; 1508 } 1509 if (a != 0) 1510 pipe.fs.flags_fs |= DN_HAVE_FLOW_MASK; 1511 NEXT_ARG; 1512 } /* end while, config masks */ 1513 1514 end_mask: 1515 break; 1516 1517 case TOK_RED: 1518 case TOK_GRED: 1519 NEED1("red/gred needs w_q/min_th/max_th/max_p\n"); 1520 pipe.fs.flags_fs |= DN_IS_RED; 1521 if (tok == TOK_GRED) 1522 pipe.fs.flags_fs |= DN_IS_GENTLE_RED; 1523 /* 1524 * the format for parameters is w_q/min_th/max_th/max_p 1525 */ 1526 if ((end = strsep(&av[0], "/"))) { 1527 double w_q = strtod(end, NULL); 1528 if (w_q > 1 || w_q <= 0) 1529 errx(EX_DATAERR, "0 < w_q <= 1"); 1530 pipe.fs.w_q = (int) (w_q * (1 << SCALE_RED)); 1531 } 1532 if ((end = strsep(&av[0], "/"))) { 1533 pipe.fs.min_th = strtoul(end, &end, 0); 1534 if (*end == 'K' || *end == 'k') 1535 pipe.fs.min_th *= 1024; 1536 } 1537 if ((end = strsep(&av[0], "/"))) { 1538 pipe.fs.max_th = strtoul(end, &end, 0); 1539 if (*end == 'K' || *end == 'k') 1540 pipe.fs.max_th *= 1024; 1541 } 1542 if ((end = strsep(&av[0], "/"))) { 1543 double max_p = strtod(end, NULL); 1544 if (max_p > 1 || max_p <= 0) 1545 errx(EX_DATAERR, "0 < max_p <= 1"); 1546 pipe.fs.max_p = (int)(max_p * (1 << SCALE_RED)); 1547 } 1548 NEXT_ARG; 1549 break; 1550 1551 case TOK_DROPTAIL: 1552 pipe.fs.flags_fs &= ~(DN_IS_RED|DN_IS_GENTLE_RED); 1553 break; 1554 1555 case TOK_BW: 1556 NEED1("bw needs bandwidth\n"); 1557 if (do_pipe != 1) 1558 errx(EX_DATAERR, "bandwidth only valid for pipes"); 1559 /* 1560 * set bandwidth value 1561 */ 1562 pipe.bandwidth = getbw(av[0], NULL, 1000); 1563 if (pipe.bandwidth < 0) 1564 errx(EX_DATAERR, "bandwidth too large"); 1565 NEXT_ARG; 1566 break; 1567 1568 case TOK_DELAY: 1569 if (do_pipe != 1) 1570 errx(EX_DATAERR, "delay only valid for pipes"); 1571 NEED1("delay needs argument 0..10000ms\n"); 1572 pipe.delay = strtoul(av[0], NULL, 0); 1573 NEXT_ARG; 1574 break; 1575 1576 case TOK_WEIGHT: 1577 if (do_pipe == 1) 1578 errx(EX_DATAERR, "weight only valid for queues"); 1579 NEED1("weight needs argument 0..100\n"); 1580 pipe.fs.weight = strtoul(av[0], &end, 0); 1581 NEXT_ARG; 1582 break; 1583 1584 case TOK_PIPE: 1585 if (do_pipe == 1) 1586 errx(EX_DATAERR, "pipe only valid for queues"); 1587 NEED1("pipe needs pipe_number\n"); 1588 pipe.fs.parent_nr = strtoul(av[0], &end, 0); 1589 NEXT_ARG; 1590 break; 1591 1592 default: 1593 errx(EX_DATAERR, "unrecognised option ``%s''", *av); 1594 } 1595 } 1596 if (do_pipe == 1) { 1597 if (pipe.pipe_nr == 0) 1598 errx(EX_DATAERR, "pipe_nr must be > 0"); 1599 if (pipe.delay > 10000) 1600 errx(EX_DATAERR, "delay must be < 10000"); 1601 } else { /* do_pipe == 2, queue */ 1602 if (pipe.fs.parent_nr == 0) 1603 errx(EX_DATAERR, "pipe must be > 0"); 1604 if (pipe.fs.weight >100) 1605 errx(EX_DATAERR, "weight must be <= 100"); 1606 } 1607 if (pipe.fs.flags_fs & DN_QSIZE_IS_BYTES) { 1608 if (pipe.fs.qsize > 1024*1024) 1609 errx(EX_DATAERR, "queue size must be < 1MB"); 1610 } else { 1611 if (pipe.fs.qsize > 100) 1612 errx(EX_DATAERR, "2 <= queue size <= 100"); 1613 } 1614 if (pipe.fs.flags_fs & DN_IS_RED) { 1615 size_t len; 1616 int lookup_depth, avg_pkt_size; 1617 double s, idle, weight, w_q; 1618 int clock_hz; 1619 int t; 1620 1621 if (pipe.fs.min_th >= pipe.fs.max_th) 1622 errx(EX_DATAERR, "min_th %d must be < than max_th %d", 1623 pipe.fs.min_th, pipe.fs.max_th); 1624 if (pipe.fs.max_th == 0) 1625 errx(EX_DATAERR, "max_th must be > 0"); 1626 1627 len = sizeof(int); 1628 if (sysctlbyname("net.inet.ip.dummynet.red_lookup_depth", 1629 &lookup_depth, &len, NULL, 0) == -1) 1630 1631 errx(1, "sysctlbyname(\"%s\")", 1632 "net.inet.ip.dummynet.red_lookup_depth"); 1633 if (lookup_depth == 0) 1634 errx(EX_DATAERR, "net.inet.ip.dummynet.red_lookup_depth" 1635 " must be greater than zero"); 1636 1637 len = sizeof(int); 1638 if (sysctlbyname("net.inet.ip.dummynet.red_avg_pkt_size", 1639 &avg_pkt_size, &len, NULL, 0) == -1) 1640 1641 errx(1, "sysctlbyname(\"%s\")", 1642 "net.inet.ip.dummynet.red_avg_pkt_size"); 1643 if (avg_pkt_size == 0) 1644 errx(EX_DATAERR, 1645 "net.inet.ip.dummynet.red_avg_pkt_size must" 1646 " be greater than zero"); 1647 1648 len = sizeof(clock_hz); 1649 if (sysctlbyname("net.inet.ip.dummynet.hz", &clock_hz, &len, 1650 NULL, 0) == -1) { 1651 errx(1, "sysctlbyname(\"%s\")", 1652 "net.inet.ip.dummynet.hz"); 1653 } 1654 1655 /* 1656 * Ticks needed for sending a medium-sized packet. 1657 * Unfortunately, when we are configuring a WF2Q+ queue, we 1658 * do not have bandwidth information, because that is stored 1659 * in the parent pipe, and also we have multiple queues 1660 * competing for it. So we set s=0, which is not very 1661 * correct. But on the other hand, why do we want RED with 1662 * WF2Q+ ? 1663 */ 1664 if (pipe.bandwidth == 0) /* this is a WF2Q+ queue */ 1665 s = 0; 1666 else 1667 s = clock_hz * avg_pkt_size * 8 / pipe.bandwidth; 1668 1669 /* 1670 * max idle time (in ticks) before avg queue size becomes 0. 1671 * NOTA: (3/w_q) is approx the value x so that 1672 * (1-w_q)^x < 10^-3. 1673 */ 1674 w_q = ((double)pipe.fs.w_q) / (1 << SCALE_RED); 1675 idle = s * 3. / w_q; 1676 pipe.fs.lookup_step = (int)idle / lookup_depth; 1677 if (!pipe.fs.lookup_step) 1678 pipe.fs.lookup_step = 1; 1679 weight = 1 - w_q; 1680 for (t = pipe.fs.lookup_step; t > 0; --t) 1681 weight *= weight; 1682 pipe.fs.lookup_weight = (int)(weight * (1 << SCALE_RED)); 1683 } 1684 i = do_set_x(IP_DUMMYNET_CONFIGURE, &pipe, sizeof pipe); 1685 if (i) 1686 err(1, "do_set_x(%s)", "IP_DUMMYNET_CONFIGURE"); 1687 } 1688 1689 /* 1690 * helper function, updates the pointer to cmd with the length 1691 * of the current command, and also cleans up the first word of 1692 * the new command in case it has been clobbered before. 1693 */ 1694 static ipfw_insn* 1695 next_cmd(ipfw_insn *cmd) 1696 { 1697 cmd += F_LEN(cmd); 1698 bzero(cmd, sizeof(*cmd)); 1699 return cmd; 1700 } 1701 1702 /* 1703 * Parse arguments and assemble the microinstructions which make up a rule. 1704 * Rules are added into the 'rulebuf' and then copied in the correct order 1705 * into the actual rule. 1706 * 1707 * 1708 */ 1709 static void 1710 add(int ac, char *av[]) 1711 { 1712 /* 1713 * rules are added into the 'rulebuf' and then copied in 1714 * the correct order into the actual rule. 1715 * Some things that need to go out of order (prob, action etc.) 1716 * go into actbuf[]. 1717 */ 1718 static uint32_t rulebuf[IPFW_RULE_SIZE_MAX]; 1719 static uint32_t actbuf[IPFW_RULE_SIZE_MAX]; 1720 static uint32_t othbuf[IPFW_RULE_SIZE_MAX]; 1721 static uint32_t cmdbuf[IPFW_RULE_SIZE_MAX]; 1722 1723 ipfw_insn *src, *dst, *cmd, *action, *other; 1724 ipfw_insn *the_comment = NULL; 1725 struct ipfw_ioc_rule *rule; 1726 struct ipfw_keyword *key; 1727 struct ipfw_mapping *map; 1728 parser_func fn; 1729 int i, j; 1730 1731 bzero(actbuf, sizeof(actbuf)); /* actions go here */ 1732 bzero(othbuf, sizeof(actbuf)); /* others */ 1733 bzero(cmdbuf, sizeof(cmdbuf)); /* filters */ 1734 bzero(rulebuf, sizeof(rulebuf)); 1735 1736 rule = (struct ipfw_ioc_rule *)rulebuf; 1737 cmd = (ipfw_insn *)cmdbuf; 1738 action = (ipfw_insn *)actbuf; 1739 other = (ipfw_insn *)othbuf; 1740 1741 NEED2("need more parameters"); 1742 NEXT_ARG; 1743 1744 /* [rule N] -- Rule number optional */ 1745 if (ac && isdigit(**av)) { 1746 rule->rulenum = atoi(*av); 1747 NEXT_ARG; 1748 } 1749 1750 /* [set N] -- set number (0..30), optional */ 1751 if (ac > 1 && !strncmp(*av, "set", strlen(*av))) { 1752 int set = strtoul(av[1], NULL, 10); 1753 if (set < 0 || set > 30) 1754 errx(EX_DATAERR, "illegal set %s", av[1]); 1755 rule->set = set; 1756 av += 2; ac -= 2; 1757 } 1758 1759 /* 1760 * parse others 1761 */ 1762 for (;;) { 1763 for (i = 0, key = keywords; i < KEYWORD_SIZE; i++, key++) { 1764 if (key->type == IPFW_KEYWORD_TYPE_OTHERS && 1765 strcmp(key->word, *av) == 0) { 1766 for (j = 0, map = mappings; 1767 j < MAPPING_SIZE; j++, map++) { 1768 if (map->type == IPFW_MAPPING_TYPE_IN_USE && 1769 map->module == key->module && 1770 map->opcode == key->opcode ) { 1771 fn = map->parser; 1772 (*fn)(&other, &ac, &av); 1773 break; 1774 } 1775 } 1776 break; 1777 } 1778 } 1779 if (i >= KEYWORD_SIZE) { 1780 break; 1781 } else if (F_LEN(other) > 0) { 1782 if (other->module == MODULE_BASIC_ID && 1783 other->opcode == O_BASIC_CHECK_STATE) { 1784 other = next_cmd(other); 1785 goto done; 1786 } 1787 other = next_cmd(other); 1788 } 1789 } 1790 1791 /* 1792 * parse actions 1793 * 1794 * only accept 1 action 1795 */ 1796 NEED1("missing action"); 1797 for (i = 0, key = keywords; i < KEYWORD_SIZE; i++, key++) { 1798 if (ac > 0 && key->type == IPFW_KEYWORD_TYPE_ACTION && 1799 strcmp(key->word, *av) == 0) { 1800 for (j = 0, map = mappings; j<MAPPING_SIZE; j++, map++) { 1801 if (map->type == IPFW_MAPPING_TYPE_IN_USE && 1802 map->module == key->module && 1803 map->opcode == key->opcode) { 1804 fn = map->parser; 1805 (*fn)(&action, &ac, &av); 1806 break; 1807 } 1808 } 1809 break; 1810 } 1811 } 1812 if (F_LEN(action) > 0) 1813 action = next_cmd(action); 1814 1815 /* 1816 * parse protocol 1817 */ 1818 if (strcmp(*av, "proto") == 0){ 1819 NEXT_ARG; 1820 } 1821 1822 NEED1("missing protocol"); 1823 for (i = 0, key = keywords; i < KEYWORD_SIZE; i++, key++) { 1824 if (key->type == IPFW_KEYWORD_TYPE_FILTER && 1825 strcmp(key->word, "proto") == 0) { 1826 for (j = 0, map = mappings; j<MAPPING_SIZE; j++, map++) { 1827 if (map->type == IPFW_MAPPING_TYPE_IN_USE && 1828 map->module == key->module && 1829 map->opcode == key->opcode ) { 1830 fn = map->parser; 1831 (*fn)(&cmd, &ac, &av); 1832 break; 1833 } 1834 } 1835 break; 1836 } 1837 } 1838 if (F_LEN(cmd) > 0) 1839 cmd = next_cmd(cmd); 1840 1841 /* 1842 * other filters 1843 */ 1844 while (ac > 0) { 1845 char *s; 1846 ipfw_insn_u32 *cmd32; /* alias for cmd */ 1847 1848 s = *av; 1849 cmd32 = (ipfw_insn_u32 *)cmd; 1850 if (strcmp(*av, "not") == 0) { 1851 if (cmd->len & F_NOT) 1852 errx(EX_USAGE, "double \"not\" not allowed\n"); 1853 cmd->len = F_NOT; 1854 NEXT_ARG; 1855 continue; 1856 } 1857 if (*s == '!') { /* alternate syntax for NOT */ 1858 if (cmd->len & F_NOT) 1859 errx(EX_USAGE, "double \"not\" not allowed"); 1860 cmd->len = F_NOT; 1861 s++; 1862 } 1863 for (i = 0, key = keywords; i < KEYWORD_SIZE; i++, key++) { 1864 if (key->type == IPFW_KEYWORD_TYPE_FILTER && 1865 strcmp(key->word, s) == 0) { 1866 for (j = 0, map = mappings; 1867 j< MAPPING_SIZE; j++, map++) { 1868 if (map->type == IPFW_MAPPING_TYPE_IN_USE && 1869 map->module == key->module && 1870 map->opcode == key->opcode ) { 1871 fn = map->parser; 1872 (*fn)(&cmd, &ac, &av); 1873 break; 1874 } 1875 } 1876 break; 1877 } else if (i == KEYWORD_SIZE-1) { 1878 errx(EX_USAGE, "bad command `%s'", s); 1879 } 1880 } 1881 if (i >= KEYWORD_SIZE) { 1882 break; 1883 } else if (F_LEN(cmd) > 0) { 1884 cmd = next_cmd(cmd); 1885 } 1886 } 1887 1888 done: 1889 if (ac>0) 1890 errx(EX_USAGE, "bad command `%s'", *av); 1891 1892 /* 1893 * Now copy stuff into the rule. 1894 * [filters][others][action][comment] 1895 */ 1896 dst = (ipfw_insn *)rule->cmd; 1897 /* 1898 * copy all filters, except comment 1899 */ 1900 src = (ipfw_insn *)cmdbuf; 1901 for (src = (ipfw_insn *)cmdbuf; src != cmd; src += i) { 1902 /* pick comment out */ 1903 i = F_LEN(src); 1904 if (src->module == MODULE_BASIC_ID && src->opcode == O_BASIC_COMMENT) { 1905 the_comment=src; 1906 } else { 1907 bcopy(src, dst, i * sizeof(u_int32_t)); 1908 dst = (ipfw_insn *)((uint32_t *)dst + i); 1909 } 1910 } 1911 1912 /* 1913 * start action section, it begin with others 1914 */ 1915 rule->act_ofs = (uint32_t *)dst - (uint32_t *)(rule->cmd); 1916 1917 /* 1918 * copy all other others 1919 */ 1920 for (src = (ipfw_insn *)othbuf; src != other; src += i) { 1921 i = F_LEN(src); 1922 bcopy(src, dst, i * sizeof(u_int32_t)); 1923 dst = (ipfw_insn *)((uint32_t *)dst + i); 1924 } 1925 1926 /* copy the action to the end of rule */ 1927 src = (ipfw_insn *)actbuf; 1928 i = F_LEN(src); 1929 bcopy(src, dst, i * sizeof(u_int32_t)); 1930 dst = (ipfw_insn *)((uint32_t *)dst + i); 1931 1932 /* 1933 * comment place behind the action 1934 */ 1935 if (the_comment != NULL) { 1936 i = F_LEN(the_comment); 1937 bcopy(the_comment, dst, i * sizeof(u_int32_t)); 1938 dst = (ipfw_insn *)((uint32_t *)dst + i); 1939 } 1940 1941 rule->cmd_len = (u_int32_t *)dst - (u_int32_t *)(rule->cmd); 1942 i = (void *)dst - (void *)rule; 1943 if (do_set_x(IP_FW_ADD, (void *)rule, i) == -1) { 1944 err(EX_UNAVAILABLE, "getsockopt(%s)", "IP_FW_ADD"); 1945 } 1946 if (!do_quiet) 1947 show_rules(rule, 10, 10); 1948 } 1949 1950 static void 1951 zero(int ac, char *av[]) 1952 { 1953 int rulenum; 1954 int failed = EX_OK; 1955 1956 NEXT_ARG; 1957 1958 if (!ac) { 1959 /* clear all entries */ 1960 if (do_set_x(IP_FW_ZERO, NULL, 0) < 0) 1961 err(EX_UNAVAILABLE, "do_set_x(IP_FW_ZERO)"); 1962 if (!do_quiet) 1963 printf("Accounting cleared.\n"); 1964 return; 1965 } 1966 1967 while (ac) { 1968 /* Rule number */ 1969 if (isdigit(**av)) { 1970 rulenum = atoi(*av); 1971 NEXT_ARG; 1972 if (do_set_x(IP_FW_ZERO, &rulenum, sizeof rulenum)) { 1973 warn("rule %u: do_set_x(IP_FW_ZERO)", rulenum); 1974 failed = EX_UNAVAILABLE; 1975 } else if (!do_quiet) 1976 printf("Entry %d cleared\n", rulenum); 1977 } else { 1978 errx(EX_USAGE, "invalid rule number ``%s''", *av); 1979 } 1980 } 1981 if (failed != EX_OK) 1982 exit(failed); 1983 } 1984 1985 static void 1986 resetlog(int ac, char *av[]) 1987 { 1988 int rulenum; 1989 int failed = EX_OK; 1990 1991 NEXT_ARG; 1992 1993 if (!ac) { 1994 /* clear all entries */ 1995 if (setsockopt(ipfw_socket, IPPROTO_IP, IP_FW_RESETLOG, NULL, 0) < 0) 1996 err(EX_UNAVAILABLE, "setsockopt(IP_FW_RESETLOG)"); 1997 if (!do_quiet) 1998 printf("Logging counts reset.\n"); 1999 2000 return; 2001 } 2002 2003 while (ac) { 2004 /* Rule number */ 2005 if (isdigit(**av)) { 2006 rulenum = atoi(*av); 2007 NEXT_ARG; 2008 if (setsockopt(ipfw_socket, IPPROTO_IP, 2009 IP_FW_RESETLOG, &rulenum, sizeof rulenum)) { 2010 warn("rule %u: setsockopt(IP_FW_RESETLOG)", rulenum); 2011 failed = EX_UNAVAILABLE; 2012 } else if (!do_quiet) 2013 printf("Entry %d logging count reset\n", rulenum); 2014 } else { 2015 errx(EX_DATAERR, "invalid rule number ``%s''", *av); 2016 } 2017 } 2018 if (failed != EX_OK) 2019 exit(failed); 2020 } 2021 2022 static void 2023 flush(void) 2024 { 2025 int cmd = IP_FW_FLUSH; 2026 if (do_pipe) { 2027 cmd = IP_DUMMYNET_FLUSH; 2028 } else if (do_nat) { 2029 cmd = IP_FW_NAT_FLUSH; 2030 } 2031 if (!do_force) { 2032 int c; 2033 2034 printf("Are you sure? [yn] "); 2035 fflush(stdout); 2036 do { 2037 c = toupper(getc(stdin)); 2038 while (c != '\n' && getc(stdin) != '\n') 2039 if (feof(stdin)) 2040 return; /* and do not flush */ 2041 } while (c != 'Y' && c != 'N'); 2042 if (c == 'N') /* user said no */ 2043 return; 2044 } 2045 if (do_set_x(cmd, NULL, 0) < 0 ) { 2046 err(EX_UNAVAILABLE, "do_set_x(%s)", 2047 do_pipe? "IP_DUMMYNET_FLUSH": 2048 (do_nat? "IP_FW_NAT_FLUSH": "IP_FW_FLUSH")); 2049 } 2050 if (!do_quiet) { 2051 printf("Flushed all %s.\n", do_pipe ? "pipes": 2052 (do_nat?"nat configurations":"rules")); 2053 } 2054 } 2055 2056 static void 2057 str2addr(const char* str, struct in_addr* addr) 2058 { 2059 struct hostent* hp; 2060 2061 if (inet_aton (str, addr)) 2062 return; 2063 2064 hp = gethostbyname (str); 2065 if (!hp) 2066 errx (1, "unknown host %s", str); 2067 2068 memcpy (addr, hp->h_addr, sizeof (struct in_addr)); 2069 } 2070 2071 static int 2072 str2portrange(const char* str, const char* proto, port_range *portRange) 2073 { 2074 struct servent* sp; 2075 char* sep; 2076 char* end; 2077 u_short loPort, hiPort; 2078 2079 /* First see if this is a service, return corresponding port if so. */ 2080 sp = getservbyname (str, proto); 2081 if (sp) { 2082 SETLOPORT(*portRange, ntohs(sp->s_port)); 2083 SETNUMPORTS(*portRange, 1); 2084 return 0; 2085 } 2086 2087 /* Not a service, see if it's a single port or port range. */ 2088 sep = strchr (str, '-'); 2089 if (sep == NULL) { 2090 SETLOPORT(*portRange, strtol(str, &end, 10)); 2091 if (end != str) { 2092 /* Single port. */ 2093 SETNUMPORTS(*portRange, 1); 2094 return 0; 2095 } 2096 2097 /* Error in port range field. */ 2098 errx (EX_DATAERR, "%s/%s: unknown service", str, proto); 2099 } 2100 2101 /* Port range, get the values and sanity check. */ 2102 sscanf (str, "%hu-%hu", &loPort, &hiPort); 2103 SETLOPORT(*portRange, loPort); 2104 SETNUMPORTS(*portRange, 0); /* Error by default */ 2105 if (loPort <= hiPort) 2106 SETNUMPORTS(*portRange, hiPort - loPort + 1); 2107 2108 if (GETNUMPORTS(*portRange) == 0) 2109 errx (EX_DATAERR, "invalid port range %s", str); 2110 2111 return 0; 2112 } 2113 2114 static int 2115 str2proto(const char* str) 2116 { 2117 if (!strcmp (str, "tcp")) 2118 return IPPROTO_TCP; 2119 if (!strcmp (str, "udp")) 2120 return IPPROTO_UDP; 2121 errx (EX_DATAERR, "unknown protocol %s. Expected tcp or udp", str); 2122 } 2123 2124 static int 2125 str2addr_portrange (const char* str, struct in_addr* addr, 2126 char* proto, port_range *portRange) 2127 { 2128 char* ptr; 2129 2130 ptr = strchr (str, ':'); 2131 if (!ptr) 2132 errx (EX_DATAERR, "%s is missing port number", str); 2133 2134 *ptr = '\0'; 2135 ++ptr; 2136 2137 str2addr (str, addr); 2138 return str2portrange (ptr, proto, portRange); 2139 } 2140 2141 /* 2142 * Search for interface with name "ifn", and fill n accordingly: 2143 * 2144 * n->ip ip address of interface "ifn" 2145 * n->if_name copy of interface name "ifn" 2146 */ 2147 static void 2148 set_addr_dynamic(const char *ifn, struct cfg_nat *n) 2149 { 2150 struct if_msghdr *ifm; 2151 struct ifa_msghdr *ifam; 2152 struct sockaddr_dl *sdl; 2153 struct sockaddr_in *sin; 2154 char *buf, *lim, *next; 2155 size_t needed; 2156 int mib[6]; 2157 int ifIndex, ifMTU; 2158 2159 mib[0] = CTL_NET; 2160 mib[1] = PF_ROUTE; 2161 mib[2] = 0; 2162 mib[3] = AF_INET; 2163 mib[4] = NET_RT_IFLIST; 2164 mib[5] = 0; 2165 2166 /* 2167 * Get interface data. 2168 */ 2169 if (sysctl(mib, 6, NULL, &needed, NULL, 0) == -1) 2170 err(1, "iflist-sysctl-estimate"); 2171 if ((buf = malloc(needed)) == NULL) 2172 errx(1, "malloc failed"); 2173 if (sysctl(mib, 6, buf, &needed, NULL, 0) == -1) 2174 err(1, "iflist-sysctl-get"); 2175 lim = buf + needed; 2176 /* 2177 * Loop through interfaces until one with 2178 * given name is found. This is done to 2179 * find correct interface index for routing 2180 * message processing. 2181 */ 2182 ifIndex = 0; 2183 next = buf; 2184 while (next < lim) { 2185 ifm = (struct if_msghdr *)next; 2186 next += ifm->ifm_msglen; 2187 if (ifm->ifm_version != RTM_VERSION) { 2188 if (verbose) 2189 warnx("routing message version %d " 2190 "not understood", ifm->ifm_version); 2191 continue; 2192 } 2193 if (ifm->ifm_type == RTM_IFINFO) { 2194 sdl = (struct sockaddr_dl *)(ifm + 1); 2195 if (strlen(ifn) == sdl->sdl_nlen && 2196 strncmp(ifn, sdl->sdl_data, sdl->sdl_nlen) == 0) { 2197 ifIndex = ifm->ifm_index; 2198 ifMTU = ifm->ifm_data.ifi_mtu; 2199 break; 2200 } 2201 } 2202 } 2203 if (!ifIndex) 2204 errx(1, "unknown interface name %s", ifn); 2205 /* 2206 * Get interface address. 2207 */ 2208 sin = NULL; 2209 while (next < lim) { 2210 ifam = (struct ifa_msghdr *)next; 2211 next += ifam->ifam_msglen; 2212 if (ifam->ifam_version != RTM_VERSION) { 2213 if (verbose) 2214 warnx("routing message version %d " 2215 "not understood", ifam->ifam_version); 2216 continue; 2217 } 2218 if (ifam->ifam_type != RTM_NEWADDR) 2219 break; 2220 if (ifam->ifam_addrs & RTA_IFA) { 2221 int i; 2222 char *cp = (char *)(ifam + 1); 2223 2224 for (i = 1; i < RTA_IFA; i <<= 1) { 2225 if (ifam->ifam_addrs & i) 2226 cp += SA_SIZE((struct sockaddr *)cp); 2227 } 2228 if (((struct sockaddr *)cp)->sa_family == AF_INET) { 2229 sin = (struct sockaddr_in *)cp; 2230 break; 2231 } 2232 } 2233 } 2234 if (sin == NULL) 2235 errx(1, "%s: cannot get interface address", ifn); 2236 2237 n->ip = sin->sin_addr; 2238 strncpy(n->if_name, ifn, IF_NAMESIZE); 2239 2240 free(buf); 2241 } 2242 2243 static int 2244 setup_redir_addr(char *spool_buf, int len, int *_ac, char ***_av) 2245 { 2246 struct cfg_redir *r; 2247 struct cfg_spool *tmp; 2248 char **av, *sep; 2249 char tmp_spool_buf[NAT_BUF_LEN]; 2250 int ac, i, space, lsnat; 2251 2252 i=0; 2253 av = *_av; 2254 ac = *_ac; 2255 space = 0; 2256 lsnat = 0; 2257 if (len >= SOF_REDIR) { 2258 r = (struct cfg_redir *)spool_buf; 2259 /* Skip cfg_redir at beginning of buf. */ 2260 spool_buf = &spool_buf[SOF_REDIR]; 2261 space = SOF_REDIR; 2262 len -= SOF_REDIR; 2263 } else { 2264 goto nospace; 2265 } 2266 2267 r->mode = REDIR_ADDR; 2268 /* Extract local address. */ 2269 if (ac == 0) 2270 errx(EX_DATAERR, "redirect_addr: missing local address"); 2271 2272 sep = strchr(*av, ','); 2273 if (sep) { /* LSNAT redirection syntax. */ 2274 r->laddr.s_addr = INADDR_NONE; 2275 /* Preserve av, copy spool servers to tmp_spool_buf. */ 2276 strncpy(tmp_spool_buf, *av, strlen(*av)+1); 2277 lsnat = 1; 2278 } else { 2279 str2addr(*av, &r->laddr); 2280 } 2281 INC_ARGCV(); 2282 2283 /* Extract public address. */ 2284 if (ac == 0) 2285 errx(EX_DATAERR, "redirect_addr: missing public address"); 2286 2287 str2addr(*av, &r->paddr); 2288 INC_ARGCV(); 2289 2290 /* Setup LSNAT server pool. */ 2291 if (sep) { 2292 sep = strtok(tmp_spool_buf, ", "); 2293 while (sep != NULL) { 2294 tmp = (struct cfg_spool *)spool_buf; 2295 if (len < SOF_SPOOL) 2296 goto nospace; 2297 2298 len -= SOF_SPOOL; 2299 space += SOF_SPOOL; 2300 str2addr(sep, &tmp->addr); 2301 tmp->port = ~0; 2302 r->spool_cnt++; 2303 /* Point to the next possible cfg_spool. */ 2304 spool_buf = &spool_buf[SOF_SPOOL]; 2305 sep = strtok(NULL, ", "); 2306 } 2307 } 2308 return(space); 2309 2310 nospace: 2311 errx(EX_DATAERR, "redirect_addr: buf is too small\n"); 2312 } 2313 2314 static int 2315 setup_redir_port(char *spool_buf, int len, int *_ac, char ***_av) 2316 { 2317 char **av, *sep, *protoName; 2318 char tmp_spool_buf[NAT_BUF_LEN]; 2319 int ac, space, lsnat; 2320 struct cfg_redir *r; 2321 struct cfg_spool *tmp; 2322 u_short numLocalPorts; 2323 port_range portRange; 2324 2325 av = *_av; 2326 ac = *_ac; 2327 space = 0; 2328 lsnat = 0; 2329 numLocalPorts = 0; 2330 2331 if (len >= SOF_REDIR) { 2332 r = (struct cfg_redir *)spool_buf; 2333 /* Skip cfg_redir at beginning of buf. */ 2334 spool_buf = &spool_buf[SOF_REDIR]; 2335 space = SOF_REDIR; 2336 len -= SOF_REDIR; 2337 } else { 2338 goto nospace; 2339 } 2340 2341 r->mode = REDIR_PORT; 2342 /* 2343 * Extract protocol. 2344 */ 2345 if (ac == 0) 2346 errx (EX_DATAERR, "redirect_port: missing protocol"); 2347 2348 r->proto = str2proto(*av); 2349 protoName = *av; 2350 INC_ARGCV(); 2351 2352 /* 2353 * Extract local address. 2354 */ 2355 if (ac == 0) 2356 errx (EX_DATAERR, "redirect_port: missing local address"); 2357 2358 sep = strchr(*av, ','); 2359 /* LSNAT redirection syntax. */ 2360 if (sep) { 2361 r->laddr.s_addr = INADDR_NONE; 2362 r->lport = ~0; 2363 numLocalPorts = 1; 2364 /* Preserve av, copy spool servers to tmp_spool_buf. */ 2365 strncpy(tmp_spool_buf, *av, strlen(*av)+1); 2366 lsnat = 1; 2367 } else { 2368 if (str2addr_portrange (*av, &r->laddr, protoName, &portRange) != 0) 2369 errx(EX_DATAERR, "redirect_port:" 2370 "invalid local port range"); 2371 2372 r->lport = GETLOPORT(portRange); 2373 numLocalPorts = GETNUMPORTS(portRange); 2374 } 2375 INC_ARGCV(); 2376 2377 /* 2378 * Extract public port and optionally address. 2379 */ 2380 if (ac == 0) 2381 errx (EX_DATAERR, "redirect_port: missing public port"); 2382 2383 sep = strchr (*av, ':'); 2384 if (sep) { 2385 if (str2addr_portrange (*av, &r->paddr, protoName, &portRange) != 0) 2386 errx(EX_DATAERR, "redirect_port:" 2387 "invalid public port range"); 2388 } else { 2389 r->paddr.s_addr = INADDR_ANY; 2390 if (str2portrange(*av, protoName, &portRange) != 0) 2391 errx(EX_DATAERR, "redirect_port:" 2392 "invalid public port range"); 2393 } 2394 2395 r->pport = GETLOPORT(portRange); 2396 r->pport_cnt = GETNUMPORTS(portRange); 2397 INC_ARGCV(); 2398 2399 /* 2400 * Extract remote address and optionally port. 2401 */ 2402 /* 2403 * NB: isalpha(**av) => we've to check that next parameter is really an 2404 * option for this redirect entry, else stop here processing arg[cv]. 2405 */ 2406 if (ac != 0 && !isalpha(**av)) { 2407 sep = strchr (*av, ':'); 2408 if (sep) { 2409 if (str2addr_portrange (*av, &r->raddr, 2410 protoName, &portRange) != 0) 2411 errx(EX_DATAERR, "redirect_port:" 2412 "invalid remote port range"); 2413 } else { 2414 SETLOPORT(portRange, 0); 2415 SETNUMPORTS(portRange, 1); 2416 str2addr (*av, &r->raddr); 2417 } 2418 INC_ARGCV(); 2419 } else { 2420 SETLOPORT(portRange, 0); 2421 SETNUMPORTS(portRange, 1); 2422 r->raddr.s_addr = INADDR_ANY; 2423 } 2424 r->rport = GETLOPORT(portRange); 2425 r->rport_cnt = GETNUMPORTS(portRange); 2426 2427 /* 2428 * Make sure port ranges match up, then add the redirect ports. 2429 */ 2430 if (numLocalPorts != r->pport_cnt) 2431 errx(EX_DATAERR, "redirect_port:" 2432 "port ranges must be equal in size"); 2433 2434 /* Remote port range is allowed to be '0' which means all ports. */ 2435 if (r->rport_cnt != numLocalPorts && 2436 (r->rport_cnt != 1 || r->rport != 0)) 2437 errx(EX_DATAERR, "redirect_port: remote port must" 2438 "be 0 or equal to local port range in size"); 2439 2440 /* 2441 * Setup LSNAT server pool. 2442 */ 2443 if (lsnat) { 2444 sep = strtok(tmp_spool_buf, ", "); 2445 while (sep != NULL) { 2446 tmp = (struct cfg_spool *)spool_buf; 2447 if (len < SOF_SPOOL) 2448 goto nospace; 2449 2450 len -= SOF_SPOOL; 2451 space += SOF_SPOOL; 2452 if (str2addr_portrange(sep, 2453 &tmp->addr, protoName, &portRange) != 0) 2454 errx(EX_DATAERR, "redirect_port:" 2455 "invalid local port range"); 2456 if (GETNUMPORTS(portRange) != 1) 2457 errx(EX_DATAERR, "redirect_port: local port" 2458 "must be single in this context"); 2459 tmp->port = GETLOPORT(portRange); 2460 r->spool_cnt++; 2461 /* Point to the next possible cfg_spool. */ 2462 spool_buf = &spool_buf[SOF_SPOOL]; 2463 sep = strtok(NULL, ", "); 2464 } 2465 } 2466 return (space); 2467 2468 nospace: 2469 errx(EX_DATAERR, "redirect_port: buf is too small\n"); 2470 } 2471 2472 static int 2473 setup_redir_proto(char *spool_buf, int len, int *_ac, char ***_av) 2474 { 2475 struct protoent *protoent; 2476 struct cfg_redir *r; 2477 int ac, i, space; 2478 char **av; 2479 2480 i=0; 2481 av = *_av; 2482 ac = *_ac; 2483 if (len >= SOF_REDIR) { 2484 r = (struct cfg_redir *)spool_buf; 2485 /* Skip cfg_redir at beginning of buf. */ 2486 spool_buf = &spool_buf[SOF_REDIR]; 2487 space = SOF_REDIR; 2488 len -= SOF_REDIR; 2489 } else { 2490 goto nospace; 2491 } 2492 r->mode = REDIR_PROTO; 2493 /* 2494 * Extract protocol. 2495 */ 2496 if (ac == 0) 2497 errx(EX_DATAERR, "redirect_proto: missing protocol"); 2498 2499 protoent = getprotobyname(*av); 2500 if (protoent == NULL) 2501 errx(EX_DATAERR, "redirect_proto: unknown protocol %s", *av); 2502 else 2503 r->proto = protoent->p_proto; 2504 2505 INC_ARGCV(); 2506 2507 /* 2508 * Extract local address. 2509 */ 2510 if (ac == 0) 2511 errx(EX_DATAERR, "redirect_proto: missing local address"); 2512 else 2513 str2addr(*av, &r->laddr); 2514 INC_ARGCV(); 2515 2516 /* 2517 * Extract optional public address. 2518 */ 2519 if (ac == 0) { 2520 r->paddr.s_addr = INADDR_ANY; 2521 r->raddr.s_addr = INADDR_ANY; 2522 } else { 2523 /* see above in setup_redir_port() */ 2524 if (!isalpha(**av)) { 2525 str2addr(*av, &r->paddr); 2526 INC_ARGCV(); 2527 2528 /* 2529 * Extract optional remote address. 2530 */ 2531 /* see above in setup_redir_port() */ 2532 if (ac != 0 && !isalpha(**av)) { 2533 str2addr(*av, &r->raddr); 2534 INC_ARGCV(); 2535 } 2536 } 2537 } 2538 return (space); 2539 2540 nospace: 2541 errx(EX_DATAERR, "redirect_proto: buf is too small\n"); 2542 } 2543 2544 static void 2545 show_nat_config(char *buf) { 2546 struct cfg_nat *n; 2547 struct cfg_redir *t; 2548 struct cfg_spool *s; 2549 struct protoent *p; 2550 int i, cnt, flag, off; 2551 2552 n = (struct cfg_nat *)buf; 2553 flag = 1; 2554 off = sizeof(*n); 2555 printf("ipfw nat %u config", n->id); 2556 if (strlen(n->if_name) != 0) 2557 printf(" if %s", n->if_name); 2558 else if (n->ip.s_addr != 0) 2559 printf(" ip %s", inet_ntoa(n->ip)); 2560 while (n->mode != 0) { 2561 if (n->mode & PKT_ALIAS_LOG) { 2562 printf(" log"); 2563 n->mode &= ~PKT_ALIAS_LOG; 2564 } else if (n->mode & PKT_ALIAS_DENY_INCOMING) { 2565 printf(" deny_in"); 2566 n->mode &= ~PKT_ALIAS_DENY_INCOMING; 2567 } else if (n->mode & PKT_ALIAS_SAME_PORTS) { 2568 printf(" same_ports"); 2569 n->mode &= ~PKT_ALIAS_SAME_PORTS; 2570 } else if (n->mode & PKT_ALIAS_UNREGISTERED_ONLY) { 2571 printf(" unreg_only"); 2572 n->mode &= ~PKT_ALIAS_UNREGISTERED_ONLY; 2573 } else if (n->mode & PKT_ALIAS_RESET_ON_ADDR_CHANGE) { 2574 printf(" reset"); 2575 n->mode &= ~PKT_ALIAS_RESET_ON_ADDR_CHANGE; 2576 } else if (n->mode & PKT_ALIAS_REVERSE) { 2577 printf(" reverse"); 2578 n->mode &= ~PKT_ALIAS_REVERSE; 2579 } else if (n->mode & PKT_ALIAS_PROXY_ONLY) { 2580 printf(" proxy_only"); 2581 n->mode &= ~PKT_ALIAS_PROXY_ONLY; 2582 } 2583 } 2584 /* Print all the redirect's data configuration. */ 2585 for (cnt = 0; cnt < n->redir_cnt; cnt++) { 2586 t = (struct cfg_redir *)&buf[off]; 2587 off += SOF_REDIR; 2588 switch (t->mode) { 2589 case REDIR_ADDR: 2590 printf(" redirect_addr"); 2591 if (t->spool_cnt == 0) 2592 printf(" %s", inet_ntoa(t->laddr)); 2593 else 2594 for (i = 0; i < t->spool_cnt; i++) { 2595 s = (struct cfg_spool *)&buf[off]; 2596 if (i) 2597 printf(", "); 2598 else 2599 printf(" "); 2600 printf("%s", inet_ntoa(s->addr)); 2601 off += SOF_SPOOL; 2602 } 2603 printf(" %s", inet_ntoa(t->paddr)); 2604 break; 2605 case REDIR_PORT: 2606 p = getprotobynumber(t->proto); 2607 printf(" redirect_port %s ", p->p_name); 2608 if (!t->spool_cnt) { 2609 printf("%s:%u", inet_ntoa(t->laddr), t->lport); 2610 if (t->pport_cnt > 1) 2611 printf("-%u", t->lport + t->pport_cnt - 1); 2612 } else 2613 for (i=0; i < t->spool_cnt; i++) { 2614 s = (struct cfg_spool *)&buf[off]; 2615 if (i) 2616 printf(", "); 2617 printf("%s:%u", inet_ntoa(s->addr), s->port); 2618 off += SOF_SPOOL; 2619 } 2620 2621 printf(" "); 2622 if (t->paddr.s_addr) 2623 printf("%s:", inet_ntoa(t->paddr)); 2624 printf("%u", t->pport); 2625 if (!t->spool_cnt && t->pport_cnt > 1) 2626 printf("-%u", t->pport + t->pport_cnt - 1); 2627 2628 if (t->raddr.s_addr) { 2629 printf(" %s", inet_ntoa(t->raddr)); 2630 if (t->rport) { 2631 printf(":%u", t->rport); 2632 if (!t->spool_cnt && t->rport_cnt > 1) 2633 printf("-%u", t->rport + 2634 t->rport_cnt - 1); 2635 } 2636 } 2637 break; 2638 case REDIR_PROTO: 2639 p = getprotobynumber(t->proto); 2640 printf(" redirect_proto %s %s", p->p_name, 2641 inet_ntoa(t->laddr)); 2642 if (t->paddr.s_addr != 0) { 2643 printf(" %s", inet_ntoa(t->paddr)); 2644 if (t->raddr.s_addr) 2645 printf(" %s", inet_ntoa(t->raddr)); 2646 } 2647 break; 2648 default: 2649 errx(EX_DATAERR, "unknown redir mode"); 2650 break; 2651 } 2652 } 2653 printf("\n"); 2654 } 2655 2656 2657 static void 2658 show_nat(int ac, char **av) { 2659 struct cfg_nat *n; 2660 struct cfg_redir *e; 2661 int i, nbytes, nalloc, size; 2662 int nat_cnt, redir_cnt, nat_id; 2663 uint8_t *data; 2664 2665 nalloc = 1024; 2666 size = 0; 2667 data = NULL; 2668 2669 NEXT_ARG; 2670 2671 if (ac == 0) 2672 nat_id = 0; 2673 else 2674 nat_id = strtoul(*av, NULL, 10); 2675 2676 nbytes = nalloc; 2677 while (nbytes >= nalloc) { 2678 nalloc = nalloc * 2; 2679 nbytes = nalloc; 2680 if ((data = realloc(data, nbytes)) == NULL) { 2681 err(EX_OSERR, "realloc"); 2682 } 2683 if (do_get_x(IP_FW_NAT_GET, data, &nbytes) < 0) { 2684 err(EX_OSERR, "do_get_x(IP_FW_NAT_GET)"); 2685 } 2686 } 2687 2688 if (nbytes == 0) { 2689 exit(EX_OK); 2690 } 2691 2692 nat_cnt = *((int *)data); 2693 for (i = sizeof(nat_cnt); nat_cnt; nat_cnt--) { 2694 n = (struct cfg_nat *)&data[i]; 2695 if (n->id >= 0 && n->id <= IPFW_DEFAULT_RULE) { 2696 if (nat_id == 0 || n->id == nat_id) 2697 show_nat_config(&data[i]); 2698 } 2699 i += sizeof(struct cfg_nat); 2700 for (redir_cnt = 0; redir_cnt < n->redir_cnt; redir_cnt++) { 2701 e = (struct cfg_redir *)&data[i]; 2702 i += sizeof(struct cfg_redir) + 2703 e->spool_cnt * sizeof(struct cfg_spool); 2704 } 2705 } 2706 } 2707 2708 /* 2709 * do_set_x - extended version og do_set 2710 * insert a x_header in the beginning of the rule buf 2711 * and call setsockopt() with IP_FW_X. 2712 */ 2713 int 2714 do_set_x(int optname, void *rule, int optlen) 2715 { 2716 int len, *newbuf; 2717 2718 ip_fw_x_header *x_header; 2719 if (ipfw_socket < 0) 2720 err(EX_UNAVAILABLE, "socket not avaialble"); 2721 len = optlen + sizeof(ip_fw_x_header); 2722 newbuf = malloc(len); 2723 if (newbuf == NULL) 2724 err(EX_OSERR, "malloc newbuf in do_set_x"); 2725 bzero(newbuf, len); 2726 x_header = (ip_fw_x_header *)newbuf; 2727 x_header->opcode = optname; 2728 /* copy the rule into the newbuf, just after the x_header*/ 2729 bcopy(rule, ++x_header, optlen); 2730 return setsockopt(ipfw_socket, IPPROTO_IP, IP_FW_X, newbuf, len); 2731 } 2732 2733 /* 2734 * same as do_set_x 2735 */ 2736 int 2737 do_get_x(int optname, void *rule, int *optlen) 2738 { 2739 int len, *newbuf, retval; 2740 2741 ip_fw_x_header *x_header; 2742 if (ipfw_socket < 0) 2743 err(EX_UNAVAILABLE, "socket not avaialble"); 2744 len = *optlen + sizeof(ip_fw_x_header); 2745 newbuf = malloc(len); 2746 if (newbuf == NULL) 2747 err(EX_OSERR, "malloc newbuf in do_get_x"); 2748 bzero(newbuf, len); 2749 x_header = (ip_fw_x_header *)newbuf; 2750 x_header->opcode = optname; 2751 /* copy the rule into the newbuf, just after the x_header*/ 2752 bcopy(rule, ++x_header, *optlen); 2753 retval = getsockopt(ipfw_socket, IPPROTO_IP, IP_FW_X, newbuf, &len); 2754 bcopy(newbuf, rule, len); 2755 *optlen=len; 2756 return retval; 2757 } 2758 2759 static void 2760 config_nat(int ac, char **av) 2761 { 2762 struct cfg_nat *n; /* Nat instance configuration. */ 2763 int i, len, off, tok; 2764 char *id, buf[NAT_BUF_LEN]; /* Buffer for serialized data. */ 2765 2766 len = NAT_BUF_LEN; 2767 /* Offset in buf: save space for n at the beginning. */ 2768 off = sizeof(struct cfg_nat); 2769 memset(buf, 0, sizeof(buf)); 2770 n = (struct cfg_nat *)buf; 2771 2772 NEXT_ARG; 2773 /* Nat id. */ 2774 if (ac && isdigit(**av)) { 2775 id = *av; 2776 i = atoi(*av); 2777 NEXT_ARG; 2778 n->id = i; 2779 } else 2780 errx(EX_DATAERR, "missing nat id"); 2781 if (ac == 0) 2782 errx(EX_DATAERR, "missing option"); 2783 2784 while (ac > 0) { 2785 tok = match_token(nat_params, *av); 2786 NEXT_ARG; 2787 switch (tok) { 2788 case TOK_IP: 2789 if (ac == 0) 2790 errx(EX_DATAERR, "missing option"); 2791 if (!inet_aton(av[0], &(n->ip))) 2792 errx(EX_DATAERR, "bad ip address ``%s''", 2793 av[0]); 2794 NEXT_ARG; 2795 break; 2796 case TOK_IF: 2797 if (ac == 0) 2798 errx(EX_DATAERR, "missing option"); 2799 set_addr_dynamic(av[0], n); 2800 NEXT_ARG; 2801 break; 2802 case TOK_ALOG: 2803 n->mode |= PKT_ALIAS_LOG; 2804 break; 2805 case TOK_DENY_INC: 2806 n->mode |= PKT_ALIAS_DENY_INCOMING; 2807 break; 2808 case TOK_SAME_PORTS: 2809 n->mode |= PKT_ALIAS_SAME_PORTS; 2810 break; 2811 case TOK_UNREG_ONLY: 2812 n->mode |= PKT_ALIAS_UNREGISTERED_ONLY; 2813 break; 2814 case TOK_RESET_ADDR: 2815 n->mode |= PKT_ALIAS_RESET_ON_ADDR_CHANGE; 2816 break; 2817 case TOK_ALIAS_REV: 2818 n->mode |= PKT_ALIAS_REVERSE; 2819 break; 2820 case TOK_PROXY_ONLY: 2821 n->mode |= PKT_ALIAS_PROXY_ONLY; 2822 break; 2823 /* 2824 * All the setup_redir_* functions work directly in the final 2825 * buffer, see above for details. 2826 */ 2827 case TOK_REDIR_ADDR: 2828 case TOK_REDIR_PORT: 2829 case TOK_REDIR_PROTO: 2830 switch (tok) { 2831 case TOK_REDIR_ADDR: 2832 i = setup_redir_addr(&buf[off], len, &ac, &av); 2833 break; 2834 case TOK_REDIR_PORT: 2835 i = setup_redir_port(&buf[off], len, &ac, &av); 2836 break; 2837 case TOK_REDIR_PROTO: 2838 i = setup_redir_proto(&buf[off], len, &ac, &av); 2839 break; 2840 } 2841 n->redir_cnt++; 2842 off += i; 2843 len -= i; 2844 break; 2845 default: 2846 errx(EX_DATAERR, "unrecognised option ``%s''", av[-1]); 2847 } 2848 } 2849 i = do_set_x(IP_FW_NAT_CFG, buf, off); 2850 if (i) 2851 err(1, "do_set_x(%s)", "IP_FW_NAT_CFG"); 2852 2853 /* After every modification, we show the resultant rule. */ 2854 int _ac = 2; 2855 char *_av[] = {"config", id}; 2856 show_nat(_ac, _av); 2857 } 2858 2859 2860 static int 2861 ipfw_main(int ac, char **av) 2862 { 2863 int ch; 2864 2865 if (ac == 1) 2866 help(); 2867 2868 /* Set the force flag for non-interactive processes */ 2869 do_force = !isatty(STDIN_FILENO); 2870 2871 optind = optreset = 1; 2872 while ((ch = getopt(ac, av, "hs:acdDefNStTv")) != -1) 2873 switch (ch) { 2874 case 'h': /* help */ 2875 help(); 2876 break; /* NOTREACHED */ 2877 2878 case 's': /* sort */ 2879 do_sort = atoi(optarg); 2880 break; 2881 case 'a': 2882 do_acct = 1; 2883 break; 2884 case 'c': 2885 do_compact = 1; 2886 break; 2887 case 'd': 2888 do_dynamic = 1; 2889 break; 2890 case 'D': 2891 do_dynamic = 2; 2892 break; 2893 case 'e': 2894 do_expired = 1; 2895 break; 2896 case 'f': 2897 do_force = 1; 2898 break; 2899 case 'N': 2900 do_resolv = 1; 2901 break; 2902 case 'S': 2903 show_sets = 1; 2904 break; 2905 case 't': 2906 do_time = 1; 2907 break; 2908 case 'T': 2909 do_time = 2; 2910 break; 2911 case 'v': 2912 do_quiet = 0; 2913 verbose++; 2914 break; 2915 default: 2916 help(); 2917 } 2918 2919 ac -= optind; 2920 av += optind; 2921 NEED1("bad arguments, for usage summary ``ipfw''"); 2922 2923 /* 2924 * optional: pipe or queue or nat 2925 */ 2926 do_nat = 0; 2927 do_pipe = 0; 2928 if (!strncmp(*av, "nat", strlen(*av))) 2929 do_nat = 1; 2930 else if (!strncmp(*av, "pipe", strlen(*av))) { 2931 do_pipe = 1; 2932 } else if (!strncmp(*av, "queue", strlen(*av))) { 2933 do_pipe = 2; 2934 } 2935 NEED1("missing command"); 2936 2937 /* 2938 * for pipes and queues and nat we normally say 'pipe NN config' 2939 * but the code is easier to parse as 'pipe config NN' 2940 * so we swap the two arguments. 2941 */ 2942 if ((do_pipe || do_nat) && ac > 2 && isdigit(*(av[1]))) { 2943 char *p = av[1]; 2944 av[1] = av[2]; 2945 av[2] = p; 2946 } 2947 2948 if (!strncmp(*av, "add", strlen(*av))) { 2949 load_modules(); 2950 add(ac, av); 2951 } else if (!strncmp(*av, "delete", strlen(*av))) { 2952 delete_rules(ac, av); 2953 } else if (!strncmp(*av, "flush", strlen(*av))) { 2954 flush(); 2955 } else if (!strncmp(*av, "list", strlen(*av))) { 2956 load_modules(); 2957 list(ac, av); 2958 } else if (!strncmp(*av, "show", strlen(*av))) { 2959 do_acct++; 2960 load_modules(); 2961 list(ac, av); 2962 } else if (!strncmp(*av, "zero", strlen(*av))) { 2963 zero(ac, av); 2964 } else if (!strncmp(*av, "set", strlen(*av))) { 2965 sets_handler(ac, av); 2966 } else if (!strncmp(*av, "module", strlen(*av))) { 2967 NEXT_ARG; 2968 if (!strncmp(*av, "show", strlen(*av)) || 2969 !strncmp(*av, "show", strlen(*av))) { 2970 list_modules(ac, av); 2971 } else { 2972 errx(EX_USAGE, "bad ipfw module command `%s'", *av); 2973 } 2974 } else if (!strncmp(*av, "resetlog", strlen(*av))) { 2975 resetlog(ac, av); 2976 } else if (!strncmp(*av, "log", strlen(*av))) { 2977 NEXT_ARG; 2978 if (!strncmp(*av, "reset", strlen(*av))) { 2979 resetlog(ac, av); 2980 } else if (!strncmp(*av, "off", strlen(*av))) { 2981 2982 } else if (!strncmp(*av, "on", strlen(*av))) { 2983 2984 } else { 2985 errx(EX_USAGE, "bad command `%s'", *av); 2986 } 2987 } else if (!strncmp(*av, "nat", strlen(*av))) { 2988 NEXT_ARG; 2989 if (!strncmp(*av, "config", strlen(*av))) { 2990 config_nat(ac, av); 2991 } else if (!strncmp(*av, "flush", strlen(*av))) { 2992 flush(); 2993 } else if (!strncmp(*av, "show", strlen(*av)) || 2994 !strncmp(*av, "list", strlen(*av))) { 2995 show_nat(ac, av); 2996 } else if (!strncmp(*av, "delete", strlen(*av))) { 2997 delete_nat_config(ac, av); 2998 } else { 2999 errx(EX_USAGE, "bad ipfw nat command `%s'", *av); 3000 } 3001 } else if (!strncmp(*av, "pipe", strlen(*av)) || 3002 !strncmp(*av, "queue", strlen(*av))) { 3003 NEXT_ARG; 3004 if (!strncmp(*av, "config", strlen(*av))) { 3005 config_dummynet(ac, av); 3006 } else if (!strncmp(*av, "flush", strlen(*av))) { 3007 flush(); 3008 } else if (!strncmp(*av, "show", strlen(*av))) { 3009 show_dummynet(ac, av); 3010 } else { 3011 errx(EX_USAGE, "bad ipfw pipe command `%s'", *av); 3012 } 3013 } else if (!strncmp(*av, "state", strlen(*av))) { 3014 NEXT_ARG; 3015 if (!strncmp(*av, "add", strlen(*av))) { 3016 add_state(ac, av); 3017 } else if (!strncmp(*av, "delete", strlen(*av))) { 3018 delete_state(ac, av); 3019 } else if (!strncmp(*av, "flush", strlen(*av))) { 3020 flush_state(ac, av); 3021 } else if (!strncmp(*av, "list", strlen(*av))) { 3022 do_dynamic = 2; 3023 list(ac, av); 3024 } else if (!strncmp(*av, "show", strlen(*av))) { 3025 do_acct = 1; 3026 do_dynamic =2; 3027 list(ac, av); 3028 } else { 3029 errx(EX_USAGE, "bad ipfw state command `%s'", *av); 3030 } 3031 } else { 3032 errx(EX_USAGE, "bad ipfw command `%s'", *av); 3033 } 3034 return 0; 3035 } 3036 3037 static void 3038 ipfw_readfile(int ac, char *av[]) 3039 { 3040 char buf[BUFSIZ]; 3041 char *a, *p, *args[MAX_ARGS], *cmd = NULL; 3042 char linename[10]; 3043 int i=0, lineno=0, qflag=0, pflag=0, status; 3044 FILE *f = NULL; 3045 pid_t preproc = 0; 3046 int c; 3047 3048 while ((c = getopt(ac, av, "D:U:p:q")) != -1) { 3049 switch (c) { 3050 case 'D': 3051 if (!pflag) 3052 errx(EX_USAGE, "-D requires -p"); 3053 if (i > MAX_ARGS - 2) 3054 errx(EX_USAGE, "too many -D or -U options"); 3055 args[i++] = "-D"; 3056 args[i++] = optarg; 3057 break; 3058 3059 case 'U': 3060 if (!pflag) 3061 errx(EX_USAGE, "-U requires -p"); 3062 if (i > MAX_ARGS - 2) 3063 errx(EX_USAGE, "too many -D or -U options"); 3064 args[i++] = "-U"; 3065 args[i++] = optarg; 3066 break; 3067 3068 case 'p': 3069 pflag = 1; 3070 cmd = optarg; 3071 args[0] = cmd; 3072 i = 1; 3073 break; 3074 3075 case 'q': 3076 qflag = 1; 3077 break; 3078 3079 default: 3080 errx(EX_USAGE, "bad arguments, for usage" 3081 " summary ``ipfw''"); 3082 } 3083 } 3084 3085 av += optind; 3086 ac -= optind; 3087 if (ac != 1) 3088 errx(EX_USAGE, "extraneous filename arguments"); 3089 3090 if ((f = fopen(av[0], "r")) == NULL) 3091 err(EX_UNAVAILABLE, "fopen: %s", av[0]); 3092 3093 if (pflag) { 3094 /* pipe through preprocessor (cpp or m4) */ 3095 int pipedes[2]; 3096 3097 args[i] = NULL; 3098 3099 if (pipe(pipedes) == -1) 3100 err(EX_OSERR, "cannot create pipe"); 3101 3102 switch ((preproc = fork())) { 3103 case -1: 3104 err(EX_OSERR, "cannot fork"); 3105 3106 case 0: 3107 /* child */ 3108 if (dup2(fileno(f), 0) == -1 || 3109 dup2(pipedes[1], 1) == -1) { 3110 err(EX_OSERR, "dup2()"); 3111 } 3112 fclose(f); 3113 close(pipedes[1]); 3114 close(pipedes[0]); 3115 execvp(cmd, args); 3116 err(EX_OSERR, "execvp(%s) failed", cmd); 3117 3118 default: 3119 /* parent */ 3120 fclose(f); 3121 close(pipedes[1]); 3122 if ((f = fdopen(pipedes[0], "r")) == NULL) { 3123 int savederrno = errno; 3124 3125 kill(preproc, SIGTERM); 3126 errno = savederrno; 3127 err(EX_OSERR, "fdopen()"); 3128 } 3129 } 3130 } 3131 3132 while (fgets(buf, BUFSIZ, f)) { 3133 lineno++; 3134 sprintf(linename, "Line %d", lineno); 3135 args[0] = linename; 3136 3137 if (*buf == '#') 3138 continue; 3139 if ((p = strchr(buf, '#')) != NULL) 3140 *p = '\0'; 3141 i = 1; 3142 if (qflag) 3143 args[i++] = "-q"; 3144 for (a = strtok(buf, WHITESP); a && i < MAX_ARGS; 3145 a = strtok(NULL, WHITESP), i++) { 3146 args[i] = a; 3147 } 3148 3149 if (i == (qflag? 2: 1)) 3150 continue; 3151 if (i == MAX_ARGS) 3152 errx(EX_USAGE, "%s: too many arguments", linename); 3153 3154 args[i] = NULL; 3155 ipfw_main(i, args); 3156 } 3157 fclose(f); 3158 if (pflag) { 3159 if (waitpid(preproc, &status, 0) == -1) 3160 errx(EX_OSERR, "waitpid()"); 3161 if (WIFEXITED(status) && WEXITSTATUS(status) != EX_OK) 3162 errx(EX_UNAVAILABLE, "preprocessor exited with status %d", 3163 WEXITSTATUS(status)); 3164 else if (WIFSIGNALED(status)) 3165 errx(EX_UNAVAILABLE, "preprocessor exited with signal %d", 3166 WTERMSIG(status)); 3167 } 3168 } 3169 3170 int 3171 main(int ac, char *av[]) 3172 { 3173 ipfw_socket = socket(AF_INET, SOCK_RAW, IPPROTO_RAW); 3174 if (ipfw_socket < 0) 3175 err(EX_UNAVAILABLE, "socket"); 3176 3177 memset(keywords, 0, sizeof(struct ipfw_keyword) * KEYWORD_SIZE); 3178 memset(mappings, 0, sizeof(struct ipfw_mapping) * MAPPING_SIZE); 3179 3180 prepare_default_funcs(); 3181 3182 if (ac > 1 && av[ac - 1][0] == '/' && access(av[ac - 1], R_OK) == 0) 3183 ipfw_readfile(ac, av); 3184 else 3185 ipfw_main(ac, av); 3186 return EX_OK; 3187 } 3188