1 /* $OpenBSD: pfe_filter.c,v 1.60 2016/09/02 14:45:51 reyk Exp $ */ 2 3 /* 4 * Copyright (c) 2006 Pierre-Yves Ritschard <pyr@openbsd.org> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #include <sys/types.h> 20 #include <sys/queue.h> 21 #include <sys/socket.h> 22 #include <sys/time.h> 23 #include <sys/ioctl.h> 24 25 #include <net/if.h> 26 #include <netinet/in.h> 27 #include <netinet/tcp.h> 28 #include <arpa/inet.h> 29 #include <net/pfvar.h> 30 31 #include <limits.h> 32 #include <string.h> 33 #include <stdio.h> 34 #include <stdlib.h> 35 #include <unistd.h> 36 #include <errno.h> 37 38 #define MINIMUM(a, b) (((a) < (b)) ? (a) : (b)) 39 40 #include "relayd.h" 41 42 struct pfdata { 43 int dev; 44 struct pf_anchor *anchor; 45 struct pfioc_trans pft; 46 struct pfioc_trans_e pfte; 47 u_int8_t pfused; 48 }; 49 50 int transaction_init(struct relayd *, const char *); 51 int transaction_commit(struct relayd *); 52 void kill_tables(struct relayd *); 53 int kill_srcnodes(struct relayd *, struct table *); 54 55 void 56 init_filter(struct relayd *env, int s) 57 { 58 struct pf_status status; 59 60 if (!(env->sc_conf.flags & F_NEEDPF)) 61 return; 62 63 if (s == -1) 64 fatalx("init_filter: invalid socket"); 65 if (env->sc_pf == NULL) { 66 if ((env->sc_pf = calloc(1, sizeof(*(env->sc_pf)))) == NULL) 67 fatal("calloc"); 68 } else 69 close(env->sc_pf->dev); 70 env->sc_pf->dev = s; 71 if (ioctl(env->sc_pf->dev, DIOCGETSTATUS, &status) == -1) 72 fatal("init_filter: DIOCGETSTATUS"); 73 if (!status.running) 74 fatalx("init_filter: pf is disabled"); 75 log_debug("%s: filter init done", __func__); 76 } 77 78 void 79 init_tables(struct relayd *env) 80 { 81 int i; 82 struct rdr *rdr; 83 struct pfr_table *tables; 84 struct pfioc_table io; 85 86 if (!(env->sc_conf.flags & F_NEEDPF)) 87 return; 88 89 if ((tables = calloc(env->sc_rdrcount, sizeof(*tables))) == NULL) 90 fatal("calloc"); 91 i = 0; 92 93 TAILQ_FOREACH(rdr, env->sc_rdrs, entry) { 94 if (strlcpy(tables[i].pfrt_anchor, RELAYD_ANCHOR "/", 95 sizeof(tables[i].pfrt_anchor)) >= PF_ANCHOR_NAME_SIZE) 96 goto toolong; 97 if (strlcat(tables[i].pfrt_anchor, rdr->conf.name, 98 sizeof(tables[i].pfrt_anchor)) >= PF_ANCHOR_NAME_SIZE) 99 goto toolong; 100 if (strlcpy(tables[i].pfrt_name, rdr->conf.name, 101 sizeof(tables[i].pfrt_name)) >= 102 sizeof(tables[i].pfrt_name)) 103 goto toolong; 104 tables[i].pfrt_flags |= PFR_TFLAG_PERSIST; 105 i++; 106 } 107 if (i != env->sc_rdrcount) 108 fatalx("init_tables: table count modified"); 109 110 memset(&io, 0, sizeof(io)); 111 io.pfrio_size = env->sc_rdrcount; 112 io.pfrio_esize = sizeof(*tables); 113 io.pfrio_buffer = tables; 114 115 if (ioctl(env->sc_pf->dev, DIOCRADDTABLES, &io) == -1) 116 fatal("init_tables: cannot create tables"); 117 log_debug("%s: created %d tables", __func__, io.pfrio_nadd); 118 119 free(tables); 120 121 if (io.pfrio_nadd == env->sc_rdrcount) 122 return; 123 124 /* 125 * clear all tables, since some already existed 126 */ 127 TAILQ_FOREACH(rdr, env->sc_rdrs, entry) 128 flush_table(env, rdr); 129 130 return; 131 132 toolong: 133 fatal("init_tables: name too long"); 134 } 135 136 void 137 kill_tables(struct relayd *env) 138 { 139 struct pfioc_table io; 140 struct rdr *rdr; 141 int cnt = 0; 142 143 if (!(env->sc_conf.flags & F_NEEDPF)) 144 return; 145 146 TAILQ_FOREACH(rdr, env->sc_rdrs, entry) { 147 memset(&io, 0, sizeof(io)); 148 if (strlcpy(io.pfrio_table.pfrt_anchor, RELAYD_ANCHOR "/", 149 sizeof(io.pfrio_table.pfrt_anchor)) >= PF_ANCHOR_NAME_SIZE) 150 goto toolong; 151 if (strlcat(io.pfrio_table.pfrt_anchor, rdr->conf.name, 152 sizeof(io.pfrio_table.pfrt_anchor)) >= PF_ANCHOR_NAME_SIZE) 153 goto toolong; 154 if (ioctl(env->sc_pf->dev, DIOCRCLRTABLES, &io) == -1) 155 fatal("kill_tables: ioctl failed"); 156 cnt += io.pfrio_ndel; 157 } 158 log_debug("%s: deleted %d tables", __func__, cnt); 159 return; 160 161 toolong: 162 fatal("kill_tables: name too long"); 163 } 164 165 void 166 sync_table(struct relayd *env, struct rdr *rdr, struct table *table) 167 { 168 int i, cnt = 0; 169 struct pfioc_table io; 170 struct pfr_addr *addlist; 171 struct sockaddr_in *sain; 172 struct sockaddr_in6 *sain6; 173 struct host *host; 174 175 if (!(env->sc_conf.flags & F_NEEDPF)) 176 return; 177 178 if (table == NULL) 179 return; 180 181 if (table->up == 0) { 182 flush_table(env, rdr); 183 return; 184 } 185 186 if ((addlist = calloc(table->up, sizeof(*addlist))) == NULL) 187 fatal("calloc"); 188 189 memset(&io, 0, sizeof(io)); 190 io.pfrio_esize = sizeof(struct pfr_addr); 191 io.pfrio_size = table->up; 192 io.pfrio_size2 = 0; 193 io.pfrio_buffer = addlist; 194 if (strlcpy(io.pfrio_table.pfrt_anchor, RELAYD_ANCHOR "/", 195 sizeof(io.pfrio_table.pfrt_anchor)) >= PF_ANCHOR_NAME_SIZE) 196 goto toolong; 197 if (strlcat(io.pfrio_table.pfrt_anchor, rdr->conf.name, 198 sizeof(io.pfrio_table.pfrt_anchor)) >= PF_ANCHOR_NAME_SIZE) 199 goto toolong; 200 if (strlcpy(io.pfrio_table.pfrt_name, rdr->conf.name, 201 sizeof(io.pfrio_table.pfrt_name)) >= 202 sizeof(io.pfrio_table.pfrt_name)) 203 goto toolong; 204 205 i = 0; 206 TAILQ_FOREACH(host, &table->hosts, entry) { 207 if (host->up != HOST_UP) 208 continue; 209 memset(&(addlist[i]), 0, sizeof(addlist[i])); 210 switch (host->conf.ss.ss_family) { 211 case AF_INET: 212 sain = (struct sockaddr_in *)&host->conf.ss; 213 addlist[i].pfra_af = AF_INET; 214 memcpy(&(addlist[i].pfra_ip4addr), &sain->sin_addr, 215 sizeof(sain->sin_addr)); 216 addlist[i].pfra_net = 32; 217 break; 218 case AF_INET6: 219 sain6 = (struct sockaddr_in6 *)&host->conf.ss; 220 addlist[i].pfra_af = AF_INET6; 221 memcpy(&(addlist[i].pfra_ip6addr), &sain6->sin6_addr, 222 sizeof(sain6->sin6_addr)); 223 addlist[i].pfra_net = 128; 224 break; 225 default: 226 fatalx("sync_table: unknown address family"); 227 break; 228 } 229 i++; 230 } 231 if (i != table->up) 232 fatalx("sync_table: desynchronized"); 233 234 if (ioctl(env->sc_pf->dev, DIOCRSETADDRS, &io) == -1) 235 fatal("sync_table: cannot set address list"); 236 if (rdr->conf.flags & F_STICKY) 237 cnt = kill_srcnodes(env, table); 238 free(addlist); 239 240 if (env->sc_conf.opts & RELAYD_OPT_LOGUPDATE) 241 log_info("table %s: %d added, %d deleted, " 242 "%d changed, %d killed", io.pfrio_table.pfrt_name, 243 io.pfrio_nadd, io.pfrio_ndel, io.pfrio_nchange, cnt); 244 return; 245 246 toolong: 247 fatal("sync_table: name too long"); 248 } 249 250 int 251 kill_srcnodes(struct relayd *env, struct table *table) 252 { 253 struct host *host; 254 struct pfioc_src_node_kill psnk; 255 int cnt = 0; 256 struct sockaddr_in *sain; 257 struct sockaddr_in6 *sain6; 258 259 bzero(&psnk, sizeof(psnk)); 260 261 /* Only match the destination address, source mask will be zero */ 262 memset(&psnk.psnk_dst.addr.v.a.mask, 0xff, 263 sizeof(psnk.psnk_dst.addr.v.a.mask)); 264 265 TAILQ_FOREACH(host, &table->hosts, entry) { 266 if (host->up != HOST_DOWN) 267 continue; 268 269 switch (host->conf.ss.ss_family) { 270 case AF_INET: 271 sain = (struct sockaddr_in *)&host->conf.ss; 272 bcopy(&sain->sin_addr, 273 &psnk.psnk_dst.addr.v.a.addr.v4, 274 sizeof(psnk.psnk_dst.addr.v.a.addr.v4)); 275 break; 276 case AF_INET6: 277 sain6 = (struct sockaddr_in6 *)&host->conf.ss; 278 bcopy(&sain6->sin6_addr, 279 &psnk.psnk_dst.addr.v.a.addr.v6, 280 sizeof(psnk.psnk_dst.addr.v.a.addr.v6)); 281 break; 282 default: 283 fatalx("kill_srcnodes: unknown address family"); 284 break; 285 } 286 287 psnk.psnk_af = host->conf.ss.ss_family; 288 psnk.psnk_killed = 0; 289 290 if (ioctl(env->sc_pf->dev, 291 DIOCKILLSRCNODES, &psnk) == -1) 292 fatal("kill_srcnodes: cannot kill src nodes"); 293 cnt += psnk.psnk_killed; 294 } 295 296 return (cnt); 297 } 298 299 void 300 flush_table(struct relayd *env, struct rdr *rdr) 301 { 302 struct pfioc_table io; 303 304 if (!(env->sc_conf.flags & F_NEEDPF)) 305 return; 306 307 memset(&io, 0, sizeof(io)); 308 if (strlcpy(io.pfrio_table.pfrt_anchor, RELAYD_ANCHOR "/", 309 sizeof(io.pfrio_table.pfrt_anchor)) >= PF_ANCHOR_NAME_SIZE) 310 goto toolong; 311 if (strlcat(io.pfrio_table.pfrt_anchor, rdr->conf.name, 312 sizeof(io.pfrio_table.pfrt_anchor)) >= PF_ANCHOR_NAME_SIZE) 313 goto toolong; 314 if (strlcpy(io.pfrio_table.pfrt_name, rdr->conf.name, 315 sizeof(io.pfrio_table.pfrt_name)) >= 316 sizeof(io.pfrio_table.pfrt_name)) 317 goto toolong; 318 if (ioctl(env->sc_pf->dev, DIOCRCLRADDRS, &io) == -1) 319 fatal("flush_table: cannot flush table addresses"); 320 321 io.pfrio_esize = sizeof(io.pfrio_table); 322 io.pfrio_size = 1; 323 io.pfrio_buffer = &io.pfrio_table; 324 if (ioctl(env->sc_pf->dev, DIOCRCLRTSTATS, &io) == -1) 325 fatal("flush_table: cannot flush table stats"); 326 327 log_debug("%s: flushed table %s", __func__, rdr->conf.name); 328 return; 329 330 toolong: 331 fatal("flush_table: name too long"); 332 } 333 334 int 335 transaction_init(struct relayd *env, const char *anchor) 336 { 337 env->sc_pf->pft.size = 1; 338 env->sc_pf->pft.esize = sizeof(env->sc_pf->pfte); 339 env->sc_pf->pft.array = &env->sc_pf->pfte; 340 341 bzero(&env->sc_pf->pfte, sizeof(env->sc_pf->pfte)); 342 (void)strlcpy(env->sc_pf->pfte.anchor, 343 anchor, PF_ANCHOR_NAME_SIZE); 344 env->sc_pf->pfte.type = PF_TRANS_RULESET; 345 346 if (ioctl(env->sc_pf->dev, DIOCXBEGIN, 347 &env->sc_pf->pft) == -1) 348 return (-1); 349 350 return (0); 351 } 352 353 int 354 transaction_commit(struct relayd *env) 355 { 356 if (ioctl(env->sc_pf->dev, DIOCXCOMMIT, 357 &env->sc_pf->pft) == -1) 358 return (-1); 359 360 return (0); 361 } 362 363 void 364 sync_ruleset(struct relayd *env, struct rdr *rdr, int enable) 365 { 366 struct pfioc_rule rio; 367 struct sockaddr_in *sain; 368 struct sockaddr_in6 *sain6; 369 struct address *address; 370 char anchor[PF_ANCHOR_NAME_SIZE]; 371 struct table *t = rdr->table; 372 373 if ((env->sc_conf.flags & F_NEEDPF) == 0) 374 return; 375 376 bzero(anchor, sizeof(anchor)); 377 if (strlcpy(anchor, RELAYD_ANCHOR "/", sizeof(anchor)) >= 378 PF_ANCHOR_NAME_SIZE) 379 goto toolong; 380 if (strlcat(anchor, rdr->conf.name, sizeof(anchor)) >= 381 PF_ANCHOR_NAME_SIZE) 382 goto toolong; 383 if (transaction_init(env, anchor) == -1) { 384 log_warn("%s: transaction init failed", __func__); 385 return; 386 } 387 388 if (!enable) { 389 if (transaction_commit(env) == -1) 390 log_warn("%s: remove rules transaction failed", 391 __func__); 392 else 393 log_debug("%s: rules removed", __func__); 394 return; 395 } 396 397 TAILQ_FOREACH(address, &rdr->virts, entry) { 398 memset(&rio, 0, sizeof(rio)); 399 (void)strlcpy(rio.anchor, anchor, sizeof(rio.anchor)); 400 401 if (rdr->conf.flags & F_MATCH) { 402 rio.rule.action = PF_MATCH; 403 rio.rule.quick = 0; 404 } else { 405 rio.rule.action = PF_PASS; 406 rio.rule.quick = 1; /* force first match */ 407 } 408 rio.rule.direction = PF_IN; 409 rio.rule.keep_state = PF_STATE_NORMAL; 410 411 switch (t->conf.fwdmode) { 412 case FWD_NORMAL: 413 /* traditional redirection */ 414 if (address->ipproto == IPPROTO_TCP) { 415 rio.rule.flags = TH_SYN; 416 rio.rule.flagset = (TH_SYN|TH_ACK); 417 } 418 break; 419 case FWD_ROUTE: 420 /* re-route with pf for DSR (direct server return) */ 421 rio.rule.rt = PF_ROUTETO; 422 423 /* Use sloppy state handling for half connections */ 424 rio.rule.rule_flag = PFRULE_STATESLOPPY; 425 break; 426 default: 427 fatalx("sync_ruleset: invalid forward mode"); 428 /* NOTREACHED */ 429 } 430 431 rio.ticket = env->sc_pf->pfte.ticket; 432 433 rio.rule.af = address->ss.ss_family; 434 rio.rule.proto = address->ipproto; 435 rio.rule.src.addr.type = PF_ADDR_ADDRMASK; 436 rio.rule.dst.addr.type = PF_ADDR_ADDRMASK; 437 rio.rule.dst.port_op = address->port.op; 438 rio.rule.dst.port[0] = address->port.val[0]; 439 rio.rule.dst.port[1] = address->port.val[1]; 440 rio.rule.rtableid = -1; /* stay in the main routing table */ 441 rio.rule.onrdomain = env->sc_rtable; 442 DPRINTF("%s rtable %d",__func__,env->sc_rtable); 443 444 if (rio.rule.proto == IPPROTO_TCP) 445 rio.rule.timeout[PFTM_TCP_ESTABLISHED] = 446 (u_int32_t)MINIMUM(rdr->conf.timeout.tv_sec, 447 INT_MAX); 448 449 if (strlen(rdr->conf.tag)) 450 (void)strlcpy(rio.rule.tagname, rdr->conf.tag, 451 sizeof(rio.rule.tagname)); 452 if (strlen(address->ifname)) 453 (void)strlcpy(rio.rule.ifname, address->ifname, 454 sizeof(rio.rule.ifname)); 455 456 if (address->ss.ss_family == AF_INET) { 457 sain = (struct sockaddr_in *)&address->ss; 458 459 rio.rule.dst.addr.v.a.addr.addr32[0] = 460 sain->sin_addr.s_addr; 461 rio.rule.dst.addr.v.a.mask.addr32[0] = 0xffffffff; 462 } else { 463 sain6 = (struct sockaddr_in6 *)&address->ss; 464 465 memcpy(&rio.rule.dst.addr.v.a.addr.v6, 466 &sain6->sin6_addr.s6_addr, 467 sizeof(sain6->sin6_addr.s6_addr)); 468 memset(&rio.rule.dst.addr.v.a.mask.addr8, 0xff, 16); 469 } 470 471 rio.rule.nat.addr.type = PF_ADDR_NONE; 472 rio.rule.rdr.addr.type = PF_ADDR_TABLE; 473 if (strlen(t->conf.ifname)) 474 (void)strlcpy(rio.rule.rdr.ifname, t->conf.ifname, 475 sizeof(rio.rule.rdr.ifname)); 476 if (strlcpy(rio.rule.rdr.addr.v.tblname, rdr->conf.name, 477 sizeof(rio.rule.rdr.addr.v.tblname)) >= 478 sizeof(rio.rule.rdr.addr.v.tblname)) 479 fatal("sync_ruleset: table name too long"); 480 481 if (address->port.op == PF_OP_EQ || 482 rdr->table->conf.flags & F_PORT) { 483 rio.rule.rdr.proxy_port[0] = 484 ntohs(rdr->table->conf.port); 485 rio.rule.rdr.port_op = PF_OP_EQ; 486 } 487 488 switch (rdr->conf.mode) { 489 case RELAY_DSTMODE_RANDOM: 490 rio.rule.rdr.opts = PF_POOL_RANDOM; 491 break; 492 case RELAY_DSTMODE_ROUNDROBIN: 493 rio.rule.rdr.opts = PF_POOL_ROUNDROBIN; 494 break; 495 case RELAY_DSTMODE_SRCHASH: 496 rio.rule.rdr.opts = PF_POOL_SRCHASH; 497 break; 498 case RELAY_DSTMODE_LEASTSTATES: 499 rio.rule.rdr.opts = PF_POOL_LEASTSTATES; 500 break; 501 default: 502 fatalx("sync_ruleset: unsupported mode"); 503 /* NOTREACHED */ 504 } 505 if (rdr->conf.flags & F_STICKY) 506 rio.rule.rdr.opts |= PF_POOL_STICKYADDR; 507 if (rdr->conf.flags & F_HASHKEY) 508 memcpy(rio.rule.rdr.key.key32, rdr->conf.key.data, 509 sizeof(rio.rule.rdr.key.key32)); 510 511 if (rio.rule.rt == PF_ROUTETO) { 512 memcpy(&rio.rule.route, &rio.rule.rdr, 513 sizeof(rio.rule.route)); 514 rio.rule.rdr.addr.type = PF_ADDR_NONE; 515 } 516 517 if (ioctl(env->sc_pf->dev, DIOCADDRULE, &rio) == -1) 518 fatal("cannot add rule"); 519 log_debug("%s: rule added to anchor \"%s\"", __func__, anchor); 520 } 521 if (transaction_commit(env) == -1) 522 log_warn("%s: add rules transaction failed", __func__); 523 return; 524 525 toolong: 526 fatal("sync_ruleset: name too long"); 527 } 528 529 void 530 flush_rulesets(struct relayd *env) 531 { 532 struct rdr *rdr; 533 char anchor[PF_ANCHOR_NAME_SIZE]; 534 535 if (!(env->sc_conf.flags & F_NEEDPF)) 536 return; 537 538 kill_tables(env); 539 TAILQ_FOREACH(rdr, env->sc_rdrs, entry) { 540 if (strlcpy(anchor, RELAYD_ANCHOR "/", sizeof(anchor)) >= 541 PF_ANCHOR_NAME_SIZE) 542 goto toolong; 543 if (strlcat(anchor, rdr->conf.name, sizeof(anchor)) >= 544 PF_ANCHOR_NAME_SIZE) 545 goto toolong; 546 if (transaction_init(env, anchor) == -1 || 547 transaction_commit(env) == -1) 548 log_warn("%s: transaction for %s/ failed", __func__, 549 RELAYD_ANCHOR); 550 } 551 if (strlcpy(anchor, RELAYD_ANCHOR, sizeof(anchor)) >= 552 PF_ANCHOR_NAME_SIZE) 553 goto toolong; 554 if (transaction_init(env, anchor) == -1 || 555 transaction_commit(env) == -1) 556 log_warn("%s: transaction for %s failed", __func__, 557 RELAYD_ANCHOR); 558 log_debug("%s: flushed rules", __func__); 559 return; 560 561 toolong: 562 fatal("flush_rulesets: name too long"); 563 } 564 565 int 566 natlook(struct relayd *env, struct ctl_natlook *cnl) 567 { 568 struct pfioc_natlook pnl; 569 struct sockaddr_in *in, *out; 570 struct sockaddr_in6 *in6, *out6; 571 char ibuf[BUFSIZ], obuf[BUFSIZ]; 572 573 if (!(env->sc_conf.flags & F_NEEDPF)) 574 return (0); 575 576 bzero(&pnl, sizeof(pnl)); 577 578 if ((pnl.af = cnl->src.ss_family) != cnl->dst.ss_family) 579 fatalx("natlook: illegal address families"); 580 switch (pnl.af) { 581 case AF_INET: 582 in = (struct sockaddr_in *)&cnl->src; 583 out = (struct sockaddr_in *)&cnl->dst; 584 bcopy(&in->sin_addr, &pnl.saddr.v4, sizeof(pnl.saddr.v4)); 585 pnl.sport = in->sin_port; 586 bcopy(&out->sin_addr, &pnl.daddr.v4, sizeof(pnl.daddr.v4)); 587 pnl.dport = out->sin_port; 588 break; 589 case AF_INET6: 590 in6 = (struct sockaddr_in6 *)&cnl->src; 591 out6 = (struct sockaddr_in6 *)&cnl->dst; 592 bcopy(&in6->sin6_addr, &pnl.saddr.v6, sizeof(pnl.saddr.v6)); 593 pnl.sport = in6->sin6_port; 594 bcopy(&out6->sin6_addr, &pnl.daddr.v6, sizeof(pnl.daddr.v6)); 595 pnl.dport = out6->sin6_port; 596 } 597 pnl.proto = cnl->proto; 598 pnl.direction = PF_IN; 599 cnl->in = 1; 600 601 if (ioctl(env->sc_pf->dev, DIOCNATLOOK, &pnl) == -1) { 602 pnl.direction = PF_OUT; 603 cnl->in = 0; 604 if (ioctl(env->sc_pf->dev, DIOCNATLOOK, &pnl) == -1) { 605 log_debug("%s: ioctl: %s", __func__, strerror(errno)); 606 return (-1); 607 } 608 } 609 610 inet_ntop(pnl.af, &pnl.rsaddr, ibuf, sizeof(ibuf)); 611 inet_ntop(pnl.af, &pnl.rdaddr, obuf, sizeof(obuf)); 612 log_debug("%s: %s %s:%d -> %s:%d", __func__, 613 pnl.direction == PF_IN ? "in" : "out", 614 ibuf, ntohs(pnl.rsport), obuf, ntohs(pnl.rdport)); 615 616 switch (pnl.af) { 617 case AF_INET: 618 in = (struct sockaddr_in *)&cnl->rsrc; 619 out = (struct sockaddr_in *)&cnl->rdst; 620 bcopy(&pnl.rsaddr.v4, &in->sin_addr, sizeof(in->sin_addr)); 621 in->sin_port = pnl.rsport; 622 bcopy(&pnl.rdaddr.v4, &out->sin_addr, sizeof(out->sin_addr)); 623 out->sin_port = pnl.rdport; 624 break; 625 case AF_INET6: 626 in6 = (struct sockaddr_in6 *)&cnl->rsrc; 627 out6 = (struct sockaddr_in6 *)&cnl->rdst; 628 bcopy(&pnl.rsaddr.v6, &in6->sin6_addr, sizeof(in6->sin6_addr)); 629 bcopy(&pnl.rdaddr.v6, &out6->sin6_addr, 630 sizeof(out6->sin6_addr)); 631 break; 632 } 633 cnl->rsrc.ss_family = pnl.af; 634 cnl->rdst.ss_family = pnl.af; 635 cnl->rsport = pnl.rsport; 636 cnl->rdport = pnl.rdport; 637 638 return (0); 639 } 640 641 u_int64_t 642 check_table(struct relayd *env, struct rdr *rdr, struct table *table) 643 { 644 struct pfioc_table io; 645 struct pfr_tstats tstats; 646 647 if (table == NULL) 648 return (0); 649 650 bzero(&io, sizeof(io)); 651 io.pfrio_esize = sizeof(struct pfr_tstats); 652 io.pfrio_size = 1; 653 io.pfrio_buffer = &tstats; 654 if (strlcpy(io.pfrio_table.pfrt_anchor, RELAYD_ANCHOR "/", 655 sizeof(io.pfrio_table.pfrt_anchor)) >= PF_ANCHOR_NAME_SIZE) 656 goto toolong; 657 if (strlcat(io.pfrio_table.pfrt_anchor, rdr->conf.name, 658 sizeof(io.pfrio_table.pfrt_anchor)) >= PF_ANCHOR_NAME_SIZE) 659 goto toolong; 660 if (strlcpy(io.pfrio_table.pfrt_name, rdr->conf.name, 661 sizeof(io.pfrio_table.pfrt_name)) >= 662 sizeof(io.pfrio_table.pfrt_name)) 663 goto toolong; 664 665 if (ioctl(env->sc_pf->dev, DIOCRGETTSTATS, &io) == -1) 666 fatal("check_table: cannot get table stats"); 667 668 return (tstats.pfrts_match); 669 670 toolong: 671 fatal("check_table: name too long"); 672 return (0); 673 } 674