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