1 /* $OpenBSD: pfctl_parser.c,v 1.50 2001/09/15 23:23:40 wilfried Exp $ */ 2 3 /* 4 * Copyright (c) 2001 Daniel Hartmeier 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * - Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * - Redistributions in binary form must reproduce the above 14 * copyright notice, this list of conditions and the following 15 * disclaimer in the documentation and/or other materials provided 16 * with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 21 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 22 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 24 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 28 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 * 31 */ 32 33 #include <sys/types.h> 34 #include <sys/socket.h> 35 #include <net/if.h> 36 #include <netinet/in.h> 37 #include <netinet/in_systm.h> 38 #include <netinet/ip.h> 39 #include <netinet/ip_icmp.h> 40 #include <netinet/icmp6.h> 41 #define TCPSTATES 42 #include <netinet/tcp_fsm.h> 43 #include <net/pfvar.h> 44 #include <arpa/inet.h> 45 46 #include <stdio.h> 47 #include <stdlib.h> 48 #include <string.h> 49 #include <ctype.h> 50 #include <netdb.h> 51 #include <stdarg.h> 52 #include <errno.h> 53 #include <err.h> 54 55 #include "pfctl_parser.h" 56 57 int unmask (struct pf_addr *, int); 58 void print_addr (struct pf_addr *, struct pf_addr *, int); 59 void print_host (struct pf_state_host *, int); 60 void print_seq (struct pf_state_peer *); 61 void print_port (u_int8_t, u_int16_t, u_int16_t, char *); 62 void print_flags (u_int8_t); 63 64 char *tcpflags = "FSRPAU"; 65 66 struct icmptypeent icmp_type[] = { 67 { "echoreq", ICMP_ECHO }, 68 { "echorep", ICMP_ECHOREPLY }, 69 { "unreach", ICMP_UNREACH }, 70 { "squench", ICMP_SOURCEQUENCH }, 71 { "redir", ICMP_REDIRECT }, 72 { "althost", ICMP_ALTHOSTADDR }, 73 { "routeradv", ICMP_ROUTERADVERT }, 74 { "routersol", ICMP_ROUTERSOLICIT }, 75 { "timex", ICMP_TIMXCEED }, 76 { "paramprob", ICMP_PARAMPROB }, 77 { "timereq", ICMP_TSTAMP }, 78 { "timerep", ICMP_TSTAMPREPLY }, 79 { "inforeq", ICMP_IREQ }, 80 { "inforep", ICMP_IREQREPLY }, 81 { "maskreq", ICMP_MASKREQ }, 82 { "maskrep", ICMP_MASKREPLY }, 83 { "trace", ICMP_TRACEROUTE }, 84 { "dataconv", ICMP_DATACONVERR }, 85 { "mobredir", ICMP_MOBILE_REDIRECT }, 86 { "ipv6-where", ICMP_IPV6_WHEREAREYOU }, 87 { "ipv6-here", ICMP_IPV6_IAMHERE }, 88 { "mobregreq", ICMP_MOBILE_REGREQUEST }, 89 { "mobregrep", ICMP_MOBILE_REGREPLY }, 90 { "skip", ICMP_SKIP }, 91 { "photuris", ICMP_PHOTURIS } 92 93 }; 94 95 struct icmptypeent icmp6_type[] = { 96 { "unreach", ICMP6_DST_UNREACH }, 97 { "toobig", ICMP6_PACKET_TOO_BIG }, 98 { "timex", ICMP6_TIME_EXCEEDED }, 99 { "paramprob", ICMP6_PARAM_PROB }, 100 { "echoreq", ICMP6_ECHO_REQUEST }, 101 { "echorep", ICMP6_ECHO_REPLY }, 102 { "groupqry", ICMP6_MEMBERSHIP_QUERY }, 103 { "listqry", MLD6_LISTENER_QUERY }, 104 { "grouprep", ICMP6_MEMBERSHIP_REPORT }, 105 { "listenrep", MLD6_LISTENER_REPORT }, 106 { "groupterm", ICMP6_MEMBERSHIP_REDUCTION }, 107 { "listendone", MLD6_LISTENER_DONE }, 108 { "routersol", ND_ROUTER_SOLICIT }, 109 { "routeradv", ND_ROUTER_ADVERT }, 110 { "neighbrsol", ND_NEIGHBOR_SOLICIT }, 111 { "neighbradv", ND_NEIGHBOR_ADVERT }, 112 { "redir", ND_REDIRECT }, 113 { "routrrenum", ICMP6_ROUTER_RENUMBERING }, 114 { "wrureq", ICMP6_WRUREQUEST }, 115 { "wrurep", ICMP6_WRUREPLY }, 116 { "fqdnreq", ICMP6_FQDN_QUERY }, 117 { "fqdnrep", ICMP6_FQDN_REPLY }, 118 { "niqry", ICMP6_NI_QUERY }, 119 { "nirep", ICMP6_NI_REPLY }, 120 { "mtraceresp", MLD6_MTRACE_RESP }, 121 { "mtrace", MLD6_MTRACE } 122 }; 123 124 struct icmpcodeent icmp_code[] = { 125 { "net-unr", ICMP_UNREACH, ICMP_UNREACH_NET }, 126 { "host-unr", ICMP_UNREACH, ICMP_UNREACH_HOST }, 127 { "proto-unr", ICMP_UNREACH, ICMP_UNREACH_PROTOCOL }, 128 { "port-unr", ICMP_UNREACH, ICMP_UNREACH_PORT }, 129 { "needfrag", ICMP_UNREACH, ICMP_UNREACH_NEEDFRAG }, 130 { "srcfail", ICMP_UNREACH, ICMP_UNREACH_SRCFAIL }, 131 { "net-unk", ICMP_UNREACH, ICMP_UNREACH_NET_UNKNOWN }, 132 { "host-unk", ICMP_UNREACH, ICMP_UNREACH_HOST_UNKNOWN }, 133 { "isolate", ICMP_UNREACH, ICMP_UNREACH_ISOLATED }, 134 { "net-prohib", ICMP_UNREACH, ICMP_UNREACH_NET_PROHIB }, 135 { "host-prohib", ICMP_UNREACH, ICMP_UNREACH_HOST_PROHIB }, 136 { "net-tos", ICMP_UNREACH, ICMP_UNREACH_TOSNET }, 137 { "host-tos", ICMP_UNREACH, ICMP_UNREACH_TOSHOST }, 138 { "filter-prohib", ICMP_UNREACH, ICMP_UNREACH_FILTER_PROHIB }, 139 { "host-preced", ICMP_UNREACH, ICMP_UNREACH_HOST_PRECEDENCE }, 140 { "cutoff-preced", ICMP_UNREACH, ICMP_UNREACH_PRECEDENCE_CUTOFF }, 141 { "redir-net", ICMP_REDIRECT, ICMP_REDIRECT_NET }, 142 { "redir-host", ICMP_REDIRECT, ICMP_REDIRECT_HOST }, 143 { "redir-tos-net", ICMP_REDIRECT, ICMP_REDIRECT_TOSNET }, 144 { "redir-tos-host", ICMP_REDIRECT, ICMP_REDIRECT_TOSHOST }, 145 { "normal-adv", ICMP_ROUTERADVERT, ICMP_ROUTERADVERT_NORMAL }, 146 { "common-adv", ICMP_ROUTERADVERT, ICMP_ROUTERADVERT_NOROUTE_COMMON }, 147 { "transit", ICMP_TIMXCEED, ICMP_TIMXCEED_INTRANS }, 148 { "reassemb", ICMP_TIMXCEED, ICMP_TIMXCEED_REASS }, 149 { "badhead", ICMP_PARAMPROB, ICMP_PARAMPROB_ERRATPTR }, 150 { "optmiss", ICMP_PARAMPROB, ICMP_PARAMPROB_OPTABSENT }, 151 { "badlen", ICMP_PARAMPROB, ICMP_PARAMPROB_LENGTH }, 152 { "unknown-ind", ICMP_PHOTURIS, ICMP_PHOTURIS_UNKNOWN_INDEX }, 153 { "auth-fail", ICMP_PHOTURIS, ICMP_PHOTURIS_AUTH_FAILED }, 154 { "decrypt-fail", ICMP_PHOTURIS, ICMP_PHOTURIS_DECRYPT_FAILED } 155 }; 156 157 struct icmpcodeent icmp6_code[] = { 158 { "admin-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_ADMIN }, 159 { "noroute-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOROUTE }, 160 { "notnbr-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOTNEIGHBOR }, 161 { "beyond-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_BEYONDSCOPE }, 162 { "addr-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_ADDR }, 163 { "port-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOPORT }, 164 { "transit", ICMP6_TIME_EXCEEDED, ICMP6_TIME_EXCEED_TRANSIT }, 165 { "reassemb", ICMP6_TIME_EXCEEDED, ICMP6_TIME_EXCEED_REASSEMBLY }, 166 { "badhead", ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER }, 167 { "nxthdr", ICMP6_PARAM_PROB, ICMP6_PARAMPROB_NEXTHEADER }, 168 { "redironlink", ND_REDIRECT, ND_REDIRECT_ONLINK }, 169 { "redirrouter", ND_REDIRECT, ND_REDIRECT_ROUTER } 170 }; 171 172 173 struct icmptypeent * 174 geticmptypebynumber(u_int8_t type, u_int8_t af) 175 { 176 unsigned i; 177 178 if (af != AF_INET6) { 179 for(i=0; i < (sizeof (icmp_type) / sizeof(icmp_type[0])); i++) { 180 if(type == icmp_type[i].type) 181 return (&icmp_type[i]); 182 } 183 } else { 184 for(i=0; i < (sizeof (icmp6_type) / 185 sizeof(icmp6_type[0])); i++) { 186 if(type == icmp6_type[i].type) 187 return (&icmp6_type[i]); 188 } 189 } 190 return (NULL); 191 } 192 193 struct icmptypeent * 194 geticmptypebyname(char *w, u_int8_t af) 195 { 196 unsigned i; 197 198 if (af != AF_INET6) { 199 for(i=0; i < (sizeof (icmp_type) / sizeof(icmp_type[0])); i++) { 200 if(!strcmp(w, icmp_type[i].name)) 201 return (&icmp_type[i]); 202 } 203 } else { 204 for(i=0; i < (sizeof (icmp6_type) / 205 sizeof(icmp6_type[0])); i++) { 206 if(!strcmp(w, icmp6_type[i].name)) 207 return (&icmp6_type[i]); 208 } 209 } 210 return (NULL); 211 } 212 213 struct icmpcodeent * 214 geticmpcodebynumber(u_int8_t type, u_int8_t code, u_int8_t af) 215 { 216 unsigned i; 217 218 if (af != AF_INET6) { 219 for(i=0; i < (sizeof (icmp_code) / sizeof(icmp_code[0])); i++) { 220 if (type == icmp_code[i].type && 221 code == icmp_code[i].code) 222 return (&icmp_code[i]); 223 } 224 } else { 225 for(i=0; i < (sizeof (icmp6_code) / 226 sizeof(icmp6_code[0])); i++) { 227 if (type == icmp6_code[i].type && 228 code == icmp6_code[i].code) 229 return (&icmp6_code[i]); 230 } 231 } 232 return (NULL); 233 } 234 235 struct icmpcodeent * 236 geticmpcodebyname(u_long type, char *w, u_int8_t af) 237 { 238 unsigned i; 239 240 if (af != AF_INET6) { 241 for(i=0; i < (sizeof (icmp_code) / sizeof(icmp_code[0])); i++) { 242 if (type == icmp_code[i].type && 243 !strcmp(w, icmp_code[i].name)) 244 return (&icmp_code[i]); 245 } 246 } else { 247 for(i=0; i < (sizeof (icmp6_code) / 248 sizeof(icmp6_code[0])); i++) { 249 if (type == icmp6_code[i].type && 250 !strcmp(w, icmp6_code[i].name)) 251 return (&icmp6_code[i]); 252 } 253 } 254 return (NULL); 255 } 256 257 int 258 unmask(struct pf_addr *m, int af) 259 { 260 int i = 31, j = 0, b = 0, msize; 261 u_int32_t tmp; 262 263 if (af == AF_INET) 264 msize = 1; 265 else 266 msize = 4; 267 while (j < msize && m->addr32[j] == 0xffffffff) { 268 b += 32; 269 j++; 270 } 271 if (j < msize) { 272 tmp = ntohl(m->addr32[j]); 273 for (i = 31; tmp & (1 << i); --i) 274 b++; 275 } 276 return (b); 277 } 278 279 void 280 print_addr(struct pf_addr *addr, struct pf_addr *mask, int af) 281 { 282 char buf[48]; 283 const char *bf; 284 285 bf = inet_ntop(af, addr, buf, sizeof(buf)); 286 printf("%s", bf); 287 if (mask != NULL) { 288 if (!PF_AZERO(mask, af)) 289 printf("/%u", unmask(mask, af)); 290 } 291 } 292 293 void 294 print_host(struct pf_state_host *h, int af) 295 { 296 u_int16_t p = ntohs(h->port); 297 298 print_addr(&h->addr, NULL, af); 299 if (af == AF_INET) 300 printf(":%u", p); 301 else 302 printf("[%u]", p); 303 } 304 305 306 void 307 print_seq(struct pf_state_peer *p) 308 { 309 if (p->seqdiff) 310 printf("[%u + %u](+%u)", p->seqlo, p->seqhi - p->seqlo, 311 p->seqdiff); 312 else 313 printf("[%u + %u]", p->seqlo, p->seqhi - p->seqlo); 314 } 315 316 void 317 print_port(u_int8_t op, u_int16_t p1, u_int16_t p2, char *proto) 318 { 319 struct servent *s = getservbyport(p1, proto); 320 321 p1 = ntohs(p1); 322 p2 = ntohs(p2); 323 printf("port "); 324 if (op == PF_OP_IRG) 325 printf("%u >< %u ", p1, p2); 326 else if (op == PF_OP_XRG) 327 printf("%u <> %u ", p1, p2); 328 else if (op == PF_OP_EQ) { 329 if (s != NULL) 330 printf("= %s ", s->s_name); 331 else 332 printf("= %u ", p1); 333 } else if (op == PF_OP_NE) { 334 if (s != NULL) 335 printf("!= %s ", s->s_name); 336 else 337 printf("!= %u ", p1); 338 } else if (op == PF_OP_LT) 339 printf("< %u ", p1); 340 else if (op == PF_OP_LE) 341 printf("<= %u ", p1); 342 else if (op == PF_OP_GT) 343 printf("> %u ", p1); 344 else if (op == PF_OP_GE) 345 printf(">= %u ", p1); 346 } 347 348 void 349 print_flags(u_int8_t f) 350 { 351 int i; 352 353 for (i = 0; i < 6; ++i) 354 if (f & (1 << i)) 355 printf("%c", tcpflags[i]); 356 } 357 358 void 359 print_nat(struct pf_nat *n) 360 { 361 printf("@nat "); 362 if (n->ifname[0]) { 363 printf("on "); 364 if (n->ifnot) 365 printf("! "); 366 printf("%s ", n->ifname); 367 } 368 printf("from "); 369 if (!PF_AZERO(&n->saddr, n->af) || !PF_AZERO(&n->smask, n->af)) { 370 if (n->snot) 371 printf("! "); 372 print_addr(&n->saddr, &n->smask, n->af); 373 printf(" "); 374 } else 375 printf("any "); 376 printf("to "); 377 if (!PF_AZERO(&n->daddr, n->af) || !PF_AZERO(&n->dmask, n->af)) { 378 if (n->snot) 379 printf("! "); 380 print_addr(&n->daddr, &n->dmask, n->af); 381 printf(" "); 382 } else 383 printf("any "); 384 printf("-> "); 385 print_addr(&n->raddr, NULL, n->af); 386 printf(" "); 387 switch (n->proto) { 388 case IPPROTO_TCP: 389 printf("proto tcp"); 390 break; 391 case IPPROTO_UDP: 392 printf("proto udp"); 393 break; 394 case IPPROTO_ICMP: 395 printf("proto icmp"); 396 break; 397 } 398 printf("\n"); 399 } 400 401 void 402 print_binat(struct pf_binat *b) 403 { 404 printf("@binat "); 405 if (b->ifname[0]) { 406 printf("on "); 407 printf("%s ", b->ifname); 408 } 409 switch (b->proto) { 410 case IPPROTO_TCP: 411 printf("proto tcp "); 412 break; 413 case IPPROTO_UDP: 414 printf("proto udp "); 415 break; 416 case IPPROTO_ICMP: 417 printf("proto icmp "); 418 break; 419 } 420 printf("from "); 421 print_addr(&b->saddr, NULL, b->af); 422 printf(" "); 423 printf("to "); 424 if (!PF_AZERO(&b->daddr, b->af) || !PF_AZERO(&b->dmask, b->af)) { 425 if (b->dnot) 426 printf("! "); 427 print_addr(&b->daddr, &b->dmask, b->af); 428 printf(" "); 429 } else 430 printf("any "); 431 printf("-> "); 432 print_addr(&b->raddr, NULL, b->af); 433 printf("\n"); 434 } 435 436 void 437 print_rdr(struct pf_rdr *r) 438 { 439 printf("@rdr "); 440 if (r->ifname[0]) { 441 printf("on "); 442 if (r->ifnot) 443 printf("! "); 444 printf("%s ", r->ifname); 445 } 446 switch (r->proto) { 447 case IPPROTO_TCP: 448 printf("proto tcp "); 449 break; 450 case IPPROTO_UDP: 451 printf("proto udp "); 452 break; 453 } 454 printf("from "); 455 if (!PF_AZERO(&r->saddr, r->af) || !PF_AZERO(&r->smask, r->af)) { 456 if (r->snot) 457 printf("! "); 458 print_addr(&r->saddr, &r->smask, r->af); 459 printf(" "); 460 } else 461 printf("any "); 462 printf("to "); 463 if (!PF_AZERO(&r->daddr, r->af) || !PF_AZERO(&r->dmask, r->af)) { 464 if (r->snot) 465 printf("! "); 466 print_addr(&r->daddr, &r->dmask, r->af); 467 printf(" "); 468 } else 469 printf("any "); 470 printf("port %u", ntohs(r->dport)); 471 if (r->opts & PF_DPORT_RANGE) 472 printf(":%u", ntohs(r->dport2)); 473 printf(" -> "); 474 print_addr(&r->raddr, NULL, r->af); 475 printf(" "); 476 printf("port %u", ntohs(r->rport)); 477 if (r->opts & PF_RPORT_RANGE) 478 printf(":*"); 479 printf("\n"); 480 } 481 482 char *pf_reasons[PFRES_MAX+1] = PFRES_NAMES; 483 char *pf_fcounters[FCNT_MAX+1] = FCNT_NAMES; 484 485 void 486 print_status(struct pf_status *s) 487 { 488 489 time_t t = time(NULL); 490 int i; 491 492 printf("Status: %s Time: %u Since: %u Debug: ", 493 s->running ? "Enabled" : "Disabled", 494 t, s->since); 495 switch (s->debug) { 496 case 0: 497 printf("None"); 498 break; 499 case 1: 500 printf("Urgent"); 501 break; 502 case 2: 503 printf("Misc"); 504 break; 505 } 506 printf("\nBytes In IPv4: %-10llu Bytes Out: %-10llu\n", 507 s->bcounters[0][PF_IN], s->bcounters[0][PF_OUT]); 508 printf(" IPv6: %-10llu Bytes Out: %-10llu\n", 509 s->bcounters[1][PF_IN], s->bcounters[1][PF_OUT]); 510 printf("Inbound Packets IPv4: Passed: %-10llu Dropped: %-10llu\n", 511 s->pcounters[0][PF_IN][PF_PASS], 512 s->pcounters[0][PF_IN][PF_DROP]); 513 printf(" IPv6: Passed: %-10llu Dropped: %-10llu\n", 514 s->pcounters[1][PF_IN][PF_PASS], 515 s->pcounters[1][PF_IN][PF_DROP]); 516 printf("Outbound Packets IPv4: Passed: %-10llu Dropped: %-10llu\n", 517 s->pcounters[0][PF_OUT][PF_PASS], 518 s->pcounters[0][PF_OUT][PF_DROP]); 519 printf(" IPv6: Passed: %-10llu Dropped: %-10llu\n", 520 s->pcounters[1][PF_OUT][PF_PASS], 521 s->pcounters[1][PF_OUT][PF_DROP]); 522 printf("States: %u\n", s->states); 523 printf("pf Counters\n"); 524 for (i = 0; i < FCNT_MAX; i++) 525 printf("%-25s %-8lld\n", pf_fcounters[i], 526 s->fcounters[i]); 527 printf("Counters\n"); 528 for (i = 0; i < PFRES_MAX; i++) 529 printf("%-25s %-8lld\n", pf_reasons[i], 530 s->counters[i]); 531 } 532 533 void 534 print_state(struct pf_state *s) 535 { 536 struct pf_state_peer *src, *dst; 537 u_int8_t hrs, min, sec; 538 539 if (s->direction == PF_OUT) { 540 src = &s->src; 541 dst = &s->dst; 542 } else { 543 src = &s->dst; 544 dst = &s->src; 545 } 546 switch (s->proto) { 547 case IPPROTO_TCP: 548 printf("TCP "); 549 break; 550 case IPPROTO_UDP: 551 printf("UDP "); 552 break; 553 case IPPROTO_ICMPV6: 554 case IPPROTO_ICMP: 555 printf("ICMP "); 556 break; 557 default: 558 printf("???? "); 559 break; 560 } 561 if (PF_ANEQ(&s->lan.addr, &s->gwy.addr, s->af) || 562 (s->lan.port != s->gwy.port)) { 563 print_host(&s->lan, s->af); 564 if (s->direction == PF_OUT) 565 printf(" -> "); 566 else 567 printf(" <- "); 568 } 569 print_host(&s->gwy, s->af); 570 if (s->direction == PF_OUT) 571 printf(" -> "); 572 else 573 printf(" <- "); 574 print_host(&s->ext, s->af); 575 576 printf(" "); 577 if (s->proto == IPPROTO_TCP) { 578 if (src->state <= TCPS_TIME_WAIT && 579 dst->state <= TCPS_TIME_WAIT) { 580 printf(" %s:%s\n", tcpstates[src->state], 581 tcpstates[dst->state]); 582 } else { 583 printf(" <BAD STATE LEVELS>\n"); 584 } 585 printf(" "); 586 print_seq(src); 587 printf(" "); 588 print_seq(dst); 589 printf("\n"); 590 } else { 591 printf(" %u:%u\n", src->state, dst->state); 592 } 593 594 sec = s->creation % 60; 595 s->creation /= 60; 596 min = s->creation % 60; 597 s->creation /= 60; 598 hrs = s->creation; 599 printf(" age %.2u:%.2u:%.2u", hrs, min, sec); 600 sec = s->expire % 60; 601 s->expire /= 60; 602 min = s->expire % 60; 603 s->expire /= 60; 604 hrs = s->expire; 605 printf(", expires in %.2u:%.2u:%.2u", hrs, min, sec); 606 printf(", %u pkts, %u bytes\n", s->packets, s->bytes); 607 } 608 609 void 610 print_rule(struct pf_rule *r) 611 { 612 printf("@%d ", r->nr); 613 if (r->action == PF_PASS) 614 printf("pass "); 615 else if (r->action == PF_DROP) { 616 printf("block "); 617 if (r->rule_flag & PFRULE_RETURNRST) 618 printf("return-rst "); 619 else if (r->return_icmp) { 620 struct icmpcodeent *ic; 621 622 if (r->af != AF_INET6) 623 printf("return-icmp"); 624 else 625 printf("return-icmp6"); 626 ic = geticmpcodebynumber(r->return_icmp >> 8, 627 r->return_icmp & 255, r->af); 628 629 if (ic == NULL) 630 printf("(%u) ", r->return_icmp & 255); 631 else if ((r->af != AF_INET6 && ic->code != ICMP_UNREACH_PORT) || 632 (r->af == AF_INET6 && ic->code != ICMP6_DST_UNREACH_NOPORT)) 633 printf("(%s) ", ic->name); 634 else 635 printf(" "); 636 } 637 } else 638 printf("scrub "); 639 if (r->direction == 0) 640 printf("in "); 641 else 642 printf("out "); 643 if (r->log == 1) 644 printf("log "); 645 else if (r->log == 2) 646 printf("log-all "); 647 if (r->quick) 648 printf("quick "); 649 if (r->ifname[0]) 650 printf("on %s ", r->ifname); 651 if (r->af) { 652 if (r->af == AF_INET) 653 printf("inet "); 654 else 655 printf("inet6 "); 656 } 657 if (r->proto) { 658 struct protoent *p = getprotobynumber(r->proto); 659 if (p != NULL) 660 printf("proto %s ", p->p_name); 661 else 662 printf("proto %u ", r->proto); 663 } 664 if (PF_AZERO(&r->src.addr, AF_INET6) && 665 PF_AZERO(&r->src.mask, AF_INET6) && 666 !r->src.port_op && PF_AZERO(&r->dst.addr, AF_INET6) && 667 PF_AZERO(&r->dst.mask, AF_INET6) && !r->dst.port_op) 668 printf("all "); 669 else { 670 printf("from "); 671 if (PF_AZERO(&r->src.addr, AF_INET6) && 672 PF_AZERO(&r->src.mask, AF_INET6)) 673 printf("any "); 674 else { 675 if (r->src.not) 676 printf("! "); 677 print_addr(&r->src.addr, &r->src.mask, r->af); 678 printf(" "); 679 } 680 if (r->src.port_op) 681 print_port(r->src.port_op, r->src.port[0], 682 r->src.port[1], 683 r->proto == IPPROTO_TCP ? "tcp" : "udp"); 684 685 printf("to "); 686 if (PF_AZERO(&r->dst.addr, AF_INET6) && 687 PF_AZERO(&r->dst.mask, AF_INET6)) 688 printf("any "); 689 else { 690 if (r->dst.not) 691 printf("! "); 692 print_addr(&r->dst.addr, &r->dst.mask, r->af); 693 printf(" "); 694 } 695 if (r->dst.port_op) 696 print_port(r->dst.port_op, r->dst.port[0], 697 r->dst.port[1], 698 r->proto == IPPROTO_TCP ? "tcp" : "udp"); 699 } 700 if (r->flags || r->flagset) { 701 printf("flags "); 702 print_flags(r->flags); 703 printf("/"); 704 print_flags(r->flagset); 705 printf(" "); 706 } 707 if (r->type) { 708 struct icmptypeent *p; 709 710 p = geticmptypebynumber(r->type-1, r->af); 711 if (r->af != AF_INET6) 712 printf("icmp-type"); 713 else 714 printf("ipv6-icmp-type"); 715 if (p != NULL) 716 printf(" %s ", p->name); 717 else 718 printf(" %u ", r->type-1); 719 if (r->code) { 720 struct icmpcodeent *p; 721 722 p = geticmpcodebynumber(r->type-1, r->code-1, r->af); 723 if (p != NULL) 724 printf("code %s ", p->name); 725 else 726 printf("code %u ", r->code-1); 727 } 728 } 729 if (r->keep_state == PF_STATE_NORMAL) 730 printf("keep state "); 731 else if (r->keep_state == PF_STATE_MODULATE) 732 printf("modulate state "); 733 if (r->rule_flag & PFRULE_NODF) 734 printf("no-df "); 735 if (r->min_ttl) 736 printf("min-ttl %d ", r->min_ttl); 737 738 printf("\n"); 739 } 740 741 int 742 parse_flags(char *s) 743 { 744 char *p, *q; 745 u_int8_t f = 0; 746 747 for (p = s; *p; p++) { 748 if ((q = strchr(tcpflags, *p)) == NULL) 749 return -1; 750 else 751 f |= 1 << (q - tcpflags); 752 } 753 return (f ? f : 63); 754 } 755