1 /* $OpenBSD: pfctl_parser.c,v 1.56 2001/12/10 18:08:12 dhartmei 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 (p) { 300 if (af == AF_INET) 301 printf(":%u", p); 302 else 303 printf("[%u]", p); 304 } 305 } 306 307 308 void 309 print_seq(struct pf_state_peer *p) 310 { 311 if (p->seqdiff) 312 printf("[%u + %u](+%u)", p->seqlo, p->seqhi - p->seqlo, 313 p->seqdiff); 314 else 315 printf("[%u + %u]", p->seqlo, p->seqhi - p->seqlo); 316 } 317 318 void 319 print_port(u_int8_t op, u_int16_t p1, u_int16_t p2, char *proto) 320 { 321 struct servent *s = getservbyport(p1, proto); 322 323 p1 = ntohs(p1); 324 p2 = ntohs(p2); 325 printf("port "); 326 if (op == PF_OP_IRG) 327 printf("%u >< %u ", p1, p2); 328 else if (op == PF_OP_XRG) 329 printf("%u <> %u ", p1, p2); 330 else if (op == PF_OP_EQ) { 331 if (s != NULL) 332 printf("= %s ", s->s_name); 333 else 334 printf("= %u ", p1); 335 } else if (op == PF_OP_NE) { 336 if (s != NULL) 337 printf("!= %s ", s->s_name); 338 else 339 printf("!= %u ", p1); 340 } else if (op == PF_OP_LT) 341 printf("< %u ", p1); 342 else if (op == PF_OP_LE) 343 printf("<= %u ", p1); 344 else if (op == PF_OP_GT) 345 printf("> %u ", p1); 346 else if (op == PF_OP_GE) 347 printf(">= %u ", p1); 348 } 349 350 void 351 print_flags(u_int8_t f) 352 { 353 int i; 354 355 for (i = 0; i < 6; ++i) 356 if (f & (1 << i)) 357 printf("%c", tcpflags[i]); 358 } 359 360 void 361 print_nat(struct pf_nat *n) 362 { 363 printf("@nat "); 364 if (n->ifname[0]) { 365 printf("on "); 366 if (n->ifnot) 367 printf("! "); 368 printf("%s ", n->ifname); 369 } 370 if (n->proto) { 371 struct protoent *p = getprotobynumber(n->proto); 372 if (n != NULL) 373 printf("proto %s ", p->p_name); 374 else 375 printf("proto %u ", n->proto); 376 } 377 printf("from "); 378 if (!PF_AZERO(&n->saddr, n->af) || !PF_AZERO(&n->smask, n->af)) { 379 if (n->snot) 380 printf("! "); 381 print_addr(&n->saddr, &n->smask, n->af); 382 printf(" "); 383 } else 384 printf("any "); 385 printf("to "); 386 if (!PF_AZERO(&n->daddr, n->af) || !PF_AZERO(&n->dmask, n->af)) { 387 if (n->dnot) 388 printf("! "); 389 print_addr(&n->daddr, &n->dmask, n->af); 390 printf(" "); 391 } else 392 printf("any "); 393 printf("-> "); 394 print_addr(&n->raddr, NULL, n->af); 395 printf("\n"); 396 } 397 398 void 399 print_binat(struct pf_binat *b) 400 { 401 printf("@binat "); 402 if (b->ifname[0]) { 403 printf("on "); 404 printf("%s ", b->ifname); 405 } 406 if (b->proto) { 407 struct protoent *p = getprotobynumber(b->proto); 408 if (p != NULL) 409 printf("proto %s ", p->p_name); 410 else 411 printf("proto %u ", b->proto); 412 } 413 printf("from "); 414 print_addr(&b->saddr, NULL, b->af); 415 printf(" "); 416 printf("to "); 417 if (!PF_AZERO(&b->daddr, b->af) || !PF_AZERO(&b->dmask, b->af)) { 418 if (b->dnot) 419 printf("! "); 420 print_addr(&b->daddr, &b->dmask, b->af); 421 printf(" "); 422 } else 423 printf("any "); 424 printf("-> "); 425 print_addr(&b->raddr, NULL, b->af); 426 printf("\n"); 427 } 428 429 void 430 print_rdr(struct pf_rdr *r) 431 { 432 printf("@rdr "); 433 if (r->ifname[0]) { 434 printf("on "); 435 if (r->ifnot) 436 printf("! "); 437 printf("%s ", r->ifname); 438 } 439 if (r->proto) { 440 struct protoent *p = getprotobynumber(r->proto); 441 if (p != NULL) 442 printf("proto %s ", p->p_name); 443 else 444 printf("proto %u ", r->proto); 445 } 446 printf("from "); 447 if (!PF_AZERO(&r->saddr, r->af) || !PF_AZERO(&r->smask, r->af)) { 448 if (r->snot) 449 printf("! "); 450 print_addr(&r->saddr, &r->smask, r->af); 451 printf(" "); 452 } else 453 printf("any "); 454 printf("to "); 455 if (!PF_AZERO(&r->daddr, r->af) || !PF_AZERO(&r->dmask, r->af)) { 456 if (r->dnot) 457 printf("! "); 458 print_addr(&r->daddr, &r->dmask, r->af); 459 printf(" "); 460 } else 461 printf("any "); 462 if (r->dport) { 463 printf("port %u", ntohs(r->dport)); 464 if (r->opts & PF_DPORT_RANGE) 465 printf(":%u", ntohs(r->dport2)); 466 } 467 printf(" -> "); 468 print_addr(&r->raddr, NULL, r->af); 469 printf(" "); 470 if (r->rport) { 471 printf("port %u", ntohs(r->rport)); 472 if (r->opts & PF_RPORT_RANGE) 473 printf(":*"); 474 } 475 printf("\n"); 476 } 477 478 char *pf_reasons[PFRES_MAX+1] = PFRES_NAMES; 479 char *pf_fcounters[FCNT_MAX+1] = FCNT_NAMES; 480 481 void 482 print_status(struct pf_status *s) 483 { 484 485 time_t t = time(NULL); 486 int i; 487 488 printf("Status: %s Time: %u Since: %u Debug: ", 489 s->running ? "Enabled" : "Disabled", 490 t, s->since); 491 switch (s->debug) { 492 case 0: 493 printf("None"); 494 break; 495 case 1: 496 printf("Urgent"); 497 break; 498 case 2: 499 printf("Misc"); 500 break; 501 } 502 printf("\nBytes In IPv4: %-10llu Bytes Out: %-10llu\n", 503 s->bcounters[0][PF_IN], s->bcounters[0][PF_OUT]); 504 printf(" IPv6: %-10llu Bytes Out: %-10llu\n", 505 s->bcounters[1][PF_IN], s->bcounters[1][PF_OUT]); 506 printf("Inbound Packets IPv4: Passed: %-10llu Dropped: %-10llu\n", 507 s->pcounters[0][PF_IN][PF_PASS], 508 s->pcounters[0][PF_IN][PF_DROP]); 509 printf(" IPv6: Passed: %-10llu Dropped: %-10llu\n", 510 s->pcounters[1][PF_IN][PF_PASS], 511 s->pcounters[1][PF_IN][PF_DROP]); 512 printf("Outbound Packets IPv4: Passed: %-10llu Dropped: %-10llu\n", 513 s->pcounters[0][PF_OUT][PF_PASS], 514 s->pcounters[0][PF_OUT][PF_DROP]); 515 printf(" IPv6: Passed: %-10llu Dropped: %-10llu\n", 516 s->pcounters[1][PF_OUT][PF_PASS], 517 s->pcounters[1][PF_OUT][PF_DROP]); 518 printf("States: %u\n", s->states); 519 printf("pf Counters\n"); 520 for (i = 0; i < FCNT_MAX; i++) 521 printf("%-25s %-8lld\n", pf_fcounters[i], 522 s->fcounters[i]); 523 printf("Counters\n"); 524 for (i = 0; i < PFRES_MAX; i++) 525 printf("%-25s %-8lld\n", pf_reasons[i], 526 s->counters[i]); 527 } 528 529 void 530 print_state(struct pf_state *s, int opts) 531 { 532 struct pf_state_peer *src, *dst; 533 struct protoent *p; 534 u_int8_t hrs, min, sec; 535 536 if (s->direction == PF_OUT) { 537 src = &s->src; 538 dst = &s->dst; 539 } else { 540 src = &s->dst; 541 dst = &s->src; 542 } 543 if ((p = getprotobynumber(s->proto)) != NULL) 544 printf("%s ", p->p_name); 545 else 546 printf("%u ", s->proto); 547 if (PF_ANEQ(&s->lan.addr, &s->gwy.addr, s->af) || 548 (s->lan.port != s->gwy.port)) { 549 print_host(&s->lan, s->af); 550 if (s->direction == PF_OUT) 551 printf(" -> "); 552 else 553 printf(" <- "); 554 } 555 print_host(&s->gwy, s->af); 556 if (s->direction == PF_OUT) 557 printf(" -> "); 558 else 559 printf(" <- "); 560 print_host(&s->ext, s->af); 561 562 printf(" "); 563 if (s->proto == IPPROTO_TCP) { 564 if (src->state <= TCPS_TIME_WAIT && 565 dst->state <= TCPS_TIME_WAIT) { 566 printf(" %s:%s\n", tcpstates[src->state], 567 tcpstates[dst->state]); 568 } else { 569 printf(" <BAD STATE LEVELS>\n"); 570 } 571 if (opts & PF_OPT_VERBOSE) { 572 printf(" "); 573 print_seq(src); 574 printf(" "); 575 print_seq(dst); 576 printf("\n"); 577 } 578 } else { 579 printf(" %u:%u\n", src->state, dst->state); 580 } 581 582 if (opts & PF_OPT_VERBOSE) { 583 sec = s->creation % 60; 584 s->creation /= 60; 585 min = s->creation % 60; 586 s->creation /= 60; 587 hrs = s->creation; 588 printf(" age %.2u:%.2u:%.2u", hrs, min, sec); 589 sec = s->expire % 60; 590 s->expire /= 60; 591 min = s->expire % 60; 592 s->expire /= 60; 593 hrs = s->expire; 594 printf(", expires in %.2u:%.2u:%.2u", hrs, min, sec); 595 printf(", %u pkts, %u bytes\n", s->packets, s->bytes); 596 } 597 } 598 599 void 600 print_rule(struct pf_rule *r) 601 { 602 printf("@%d ", r->nr); 603 if (r->action == PF_PASS) 604 printf("pass "); 605 else if (r->action == PF_DROP) { 606 printf("block "); 607 if (r->rule_flag & PFRULE_RETURNRST) 608 printf("return-rst "); 609 else if (r->return_icmp) { 610 struct icmpcodeent *ic; 611 612 if (r->af != AF_INET6) 613 printf("return-icmp"); 614 else 615 printf("return-icmp6"); 616 ic = geticmpcodebynumber(r->return_icmp >> 8, 617 r->return_icmp & 255, r->af); 618 619 if (ic == NULL) 620 printf("(%u) ", r->return_icmp & 255); 621 else if ((r->af != AF_INET6 && ic->code != ICMP_UNREACH_PORT) || 622 (r->af == AF_INET6 && ic->code != ICMP6_DST_UNREACH_NOPORT)) 623 printf("(%s) ", ic->name); 624 else 625 printf(" "); 626 } 627 } else 628 printf("scrub "); 629 if (r->direction == 0) 630 printf("in "); 631 else 632 printf("out "); 633 if (r->log == 1) 634 printf("log "); 635 else if (r->log == 2) 636 printf("log-all "); 637 if (r->quick) 638 printf("quick "); 639 if (r->ifname[0]) 640 printf("on %s ", r->ifname); 641 if (r->rt) { 642 if (r->rt == PF_ROUTETO) 643 printf("route-to "); 644 else if (r->rt == PF_DUPTO) 645 printf("dup-to "); 646 else if (r->rt == PF_FASTROUTE) 647 printf("fastroute"); 648 if (r->rt_ifname[0]) 649 printf("%s", r->rt_ifname); 650 if (r->af && !PF_AZERO(&r->rt_addr, r->af)) { 651 printf(":"); 652 print_addr(&r->rt_addr, NULL, r->af); 653 } 654 printf(" "); 655 } 656 if (r->af) { 657 if (r->af == AF_INET) 658 printf("inet "); 659 else 660 printf("inet6 "); 661 } 662 if (r->proto) { 663 struct protoent *p = getprotobynumber(r->proto); 664 if (p != NULL) 665 printf("proto %s ", p->p_name); 666 else 667 printf("proto %u ", r->proto); 668 } 669 if (PF_AZERO(&r->src.addr, AF_INET6) && 670 PF_AZERO(&r->src.mask, AF_INET6) && 671 !r->src.port_op && PF_AZERO(&r->dst.addr, AF_INET6) && 672 PF_AZERO(&r->dst.mask, AF_INET6) && !r->dst.port_op) 673 printf("all "); 674 else { 675 printf("from "); 676 if (PF_AZERO(&r->src.addr, AF_INET6) && 677 PF_AZERO(&r->src.mask, AF_INET6)) 678 printf("any "); 679 else { 680 if (r->src.not) 681 printf("! "); 682 print_addr(&r->src.addr, &r->src.mask, r->af); 683 printf(" "); 684 } 685 if (r->src.port_op) 686 print_port(r->src.port_op, r->src.port[0], 687 r->src.port[1], 688 r->proto == IPPROTO_TCP ? "tcp" : "udp"); 689 690 printf("to "); 691 if (PF_AZERO(&r->dst.addr, AF_INET6) && 692 PF_AZERO(&r->dst.mask, AF_INET6)) 693 printf("any "); 694 else { 695 if (r->dst.not) 696 printf("! "); 697 print_addr(&r->dst.addr, &r->dst.mask, r->af); 698 printf(" "); 699 } 700 if (r->dst.port_op) 701 print_port(r->dst.port_op, r->dst.port[0], 702 r->dst.port[1], 703 r->proto == IPPROTO_TCP ? "tcp" : "udp"); 704 } 705 if (r->flags || r->flagset) { 706 printf("flags "); 707 print_flags(r->flags); 708 printf("/"); 709 print_flags(r->flagset); 710 printf(" "); 711 } 712 if (r->type) { 713 struct icmptypeent *p; 714 715 p = geticmptypebynumber(r->type-1, r->af); 716 if (r->af != AF_INET6) 717 printf("icmp-type"); 718 else 719 printf("ipv6-icmp-type"); 720 if (p != NULL) 721 printf(" %s ", p->name); 722 else 723 printf(" %u ", r->type-1); 724 if (r->code) { 725 struct icmpcodeent *p; 726 727 p = geticmpcodebynumber(r->type-1, r->code-1, r->af); 728 if (p != NULL) 729 printf("code %s ", p->name); 730 else 731 printf("code %u ", r->code-1); 732 } 733 } 734 if (r->keep_state == PF_STATE_NORMAL) 735 printf("keep state "); 736 else if (r->keep_state == PF_STATE_MODULATE) 737 printf("modulate state "); 738 if (r->rule_flag & PFRULE_NODF) 739 printf("no-df "); 740 if (r->min_ttl) 741 printf("min-ttl %d ", r->min_ttl); 742 if (r->allow_opts) 743 printf("allow-opts "); 744 745 printf("\n"); 746 } 747 748 int 749 parse_flags(char *s) 750 { 751 char *p, *q; 752 u_int8_t f = 0; 753 754 for (p = s; *p; p++) { 755 if ((q = strchr(tcpflags, *p)) == NULL) 756 return -1; 757 else 758 f |= 1 << (q - tcpflags); 759 } 760 return (f ? f : 63); 761 } 762