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