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