1 /* $FreeBSD: src/sys/contrib/pf/net/if_pfsync.c,v 1.11 2004/08/14 15:32:40 dwmalone Exp $ */ 2 /* $OpenBSD: if_pfsync.c,v 1.26 2004/03/28 18:14:20 mcbride Exp $ */ 3 /* $DragonFly: src/sys/net/pf/if_pfsync.c,v 1.8 2008/04/12 17:39:41 dillon Exp $ */ 4 5 /* 6 * Copyright (c) 2004 The DragonFly Project. All rights reserved. 7 * 8 * Copyright (c) 2002 Michael Shalayeff 9 * All rights reserved. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 23 * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT, 24 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 25 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 28 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 29 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 30 * THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 #include "opt_inet.h" 34 #include "opt_inet6.h" 35 36 #include <sys/param.h> 37 #include <sys/proc.h> 38 #include <sys/priv.h> 39 #include <sys/systm.h> 40 #include <sys/time.h> 41 #include <sys/mbuf.h> 42 #include <sys/socket.h> 43 #include <sys/kernel.h> 44 #include <sys/malloc.h> 45 #include <sys/module.h> 46 #include <sys/sockio.h> 47 #include <sys/thread2.h> 48 #include <vm/vm_zone.h> 49 50 #include <machine/inttypes.h> 51 52 #include <net/if.h> 53 #include <net/if_types.h> 54 #include <net/route.h> 55 #include <net/bpf.h> 56 57 #ifdef INET 58 #include <netinet/in.h> 59 #include <netinet/in_systm.h> 60 #include <netinet/in_var.h> 61 #include <netinet/ip.h> 62 #include <netinet/ip_var.h> 63 #endif 64 65 #ifdef INET6 66 #ifndef INET 67 #include <netinet/in.h> 68 #endif 69 #include <netinet6/nd6.h> 70 #endif /* INET6 */ 71 72 #include <net/pf/pfvar.h> 73 #include <net/pf/if_pfsync.h> 74 75 #define PFSYNCNAME "pfsync" 76 77 #define PFSYNC_MINMTU \ 78 (sizeof(struct pfsync_header) + sizeof(struct pf_state)) 79 80 #ifdef PFSYNCDEBUG 81 #define DPRINTF(x) do { if (pfsyncdebug) kprintf x ; } while (0) 82 int pfsyncdebug; 83 #else 84 #define DPRINTF(x) 85 #endif 86 87 int pfsync_sync_ok; 88 struct pfsyncstats pfsyncstats; 89 90 static void pfsync_clone_destroy(struct ifnet *); 91 static int pfsync_clone_create(struct if_clone *, int); 92 void pfsync_setmtu(struct pfsync_softc *, int); 93 int pfsync_insert_net_state(struct pfsync_state *); 94 int pfsyncoutput(struct ifnet *, struct mbuf *, struct sockaddr *, 95 struct rtentry *); 96 int pfsyncioctl(struct ifnet *, u_long, caddr_t, struct ucred *); 97 void pfsyncstart(struct ifnet *); 98 99 struct mbuf *pfsync_get_mbuf(struct pfsync_softc *, u_int8_t, void **); 100 int pfsync_request_update(struct pfsync_state_upd *, struct in_addr *); 101 int pfsync_sendout(struct pfsync_softc *); 102 void pfsync_timeout(void *); 103 void pfsync_send_bus(struct pfsync_softc *, u_int8_t); 104 void pfsync_bulk_update(void *); 105 void pfsync_bulkfail(void *); 106 107 static MALLOC_DEFINE(M_PFSYNC, PFSYNCNAME, "Packet Filter State Sync. Interface"); 108 static LIST_HEAD(pfsync_list, pfsync_softc) pfsync_list; 109 struct if_clone pfsync_cloner = IF_CLONE_INITIALIZER("pfsync", pfsync_clone_create, 110 pfsync_clone_destroy, 1, 1); 111 112 static void 113 pfsync_clone_destroy(struct ifnet *ifp) 114 { 115 struct pfsync_softc *sc; 116 117 sc = ifp->if_softc; 118 callout_stop(&sc->sc_tmo); 119 callout_stop(&sc->sc_bulk_tmo); 120 callout_stop(&sc->sc_bulkfail_tmo); 121 122 bpfdetach(ifp); 123 if_detach(ifp); 124 LIST_REMOVE(sc, sc_next); 125 kfree(sc, M_PFSYNC); 126 } 127 128 static int 129 pfsync_clone_create(struct if_clone *ifc, int unit) 130 { 131 struct pfsync_softc *sc; 132 struct ifnet *ifp; 133 134 MALLOC(sc, struct pfsync_softc *, sizeof(*sc), M_PFSYNC, 135 M_WAITOK|M_ZERO); 136 137 pfsync_sync_ok = 1; 138 sc->sc_mbuf = NULL; 139 sc->sc_mbuf_net = NULL; 140 sc->sc_statep.s = NULL; 141 sc->sc_statep_net.s = NULL; 142 sc->sc_maxupdates = 128; 143 sc->sc_sendaddr.s_addr = htonl(INADDR_PFSYNC_GROUP); 144 sc->sc_ureq_received = 0; 145 sc->sc_ureq_sent = 0; 146 147 ifp = &sc->sc_if; 148 if_initname(ifp, ifc->ifc_name, unit); 149 ifp->if_ioctl = pfsyncioctl; 150 ifp->if_output = pfsyncoutput; 151 ifp->if_start = pfsyncstart; 152 ifp->if_type = IFT_PFSYNC; 153 ifp->if_snd.ifq_maxlen = ifqmaxlen; 154 ifp->if_hdrlen = PFSYNC_HDRLEN; 155 ifp->if_baudrate = IF_Mbps(100); 156 ifp->if_softc = sc; 157 pfsync_setmtu(sc, MCLBYTES); 158 callout_init(&sc->sc_tmo); 159 callout_init(&sc->sc_bulk_tmo); 160 callout_init(&sc->sc_bulkfail_tmo); 161 if_attach(&sc->sc_if, NULL); 162 163 LIST_INSERT_HEAD(&pfsync_list, sc, sc_next); 164 bpfattach(&sc->sc_if, DLT_PFSYNC, PFSYNC_HDRLEN); 165 166 return (0); 167 } 168 169 /* 170 * Start output on the pfsync interface. 171 */ 172 void 173 pfsyncstart(struct ifnet *ifp) 174 { 175 crit_enter(); 176 IF_DROP(&ifp->if_snd); 177 IF_DRAIN(&ifp->if_snd); 178 crit_exit(); 179 } 180 181 int 182 pfsync_insert_net_state(struct pfsync_state *sp) 183 { 184 struct pf_state *st = NULL; 185 struct pf_rule *r = NULL; 186 struct pfi_kif *kif; 187 188 if (sp->creatorid == 0 && pf_status.debug >= PF_DEBUG_MISC) { 189 kprintf("pfsync_insert_net_state: invalid creator id:" 190 " %08" PRIx32 "\n", ntohl(sp->creatorid)); 191 return (EINVAL); 192 } 193 194 kif = pfi_lookup_create(sp->ifname); 195 if (kif == NULL) { 196 if (pf_status.debug >= PF_DEBUG_MISC) 197 kprintf("pfsync_insert_net_state: " 198 "unknown interface: %s\n", sp->ifname); 199 /* skip this state */ 200 return (0); 201 } 202 203 /* 204 * Just use the default rule until we have infrastructure to find the 205 * best matching rule. 206 */ 207 r = &pf_default_rule; 208 209 if (!r->max_states || r->states < r->max_states) 210 st = pool_get(&pf_state_pl, PR_NOWAIT); 211 if (st == NULL) { 212 pfi_maybe_destroy(kif); 213 return (ENOMEM); 214 } 215 bzero(st, sizeof(*st)); 216 217 st->rule.ptr = r; 218 /* XXX get pointers to nat_rule and anchor */ 219 220 /* fill in the rest of the state entry */ 221 pf_state_host_ntoh(&sp->lan, &st->lan); 222 pf_state_host_ntoh(&sp->gwy, &st->gwy); 223 pf_state_host_ntoh(&sp->ext, &st->ext); 224 225 pf_state_peer_ntoh(&sp->src, &st->src); 226 pf_state_peer_ntoh(&sp->dst, &st->dst); 227 228 bcopy(&sp->rt_addr, &st->rt_addr, sizeof(st->rt_addr)); 229 st->hash = pf_state_hash(st); 230 st->creation = ntohl(sp->creation) + time_second; 231 st->expire = ntohl(sp->expire) + time_second; 232 233 st->af = sp->af; 234 st->proto = sp->proto; 235 st->direction = sp->direction; 236 st->log = sp->log; 237 st->timeout = sp->timeout; 238 st->allow_opts = sp->allow_opts; 239 240 bcopy(sp->id, &st->id, sizeof(st->id)); 241 st->creatorid = sp->creatorid; 242 st->sync_flags = sp->sync_flags | PFSTATE_FROMSYNC; 243 244 245 if (pf_insert_state(kif, st)) { 246 pfi_maybe_destroy(kif); 247 pool_put(&pf_state_pl, st); 248 return (EINVAL); 249 } 250 251 return (0); 252 } 253 254 void 255 pfsync_input(struct mbuf *m, ...) 256 { 257 struct ip *ip = mtod(m, struct ip *); 258 struct pfsync_header *ph; 259 struct pfsync_softc *sc = LIST_FIRST(&pfsync_list); 260 struct pf_state *st, key; 261 struct pfsync_state *sp; 262 struct pfsync_state_upd *up; 263 struct pfsync_state_del *dp; 264 struct pfsync_state_clr *cp; 265 struct pfsync_state_upd_req *rup; 266 struct pfsync_state_bus *bus; 267 struct in_addr src; 268 struct mbuf *mp; 269 int iplen, action, error, i, count, offp; 270 271 pfsyncstats.pfsyncs_ipackets++; 272 273 /* verify that we have a sync interface configured */ 274 if (!sc->sc_sync_ifp || !pf_status.running) 275 goto done; 276 277 /* verify that the packet came in on the right interface */ 278 if (sc->sc_sync_ifp != m->m_pkthdr.rcvif) { 279 pfsyncstats.pfsyncs_badif++; 280 goto done; 281 } 282 283 /* verify that the IP TTL is 255. */ 284 if (ip->ip_ttl != PFSYNC_DFLTTL) { 285 pfsyncstats.pfsyncs_badttl++; 286 goto done; 287 } 288 289 iplen = ip->ip_hl << 2; 290 291 if (m->m_pkthdr.len < iplen + sizeof(*ph)) { 292 pfsyncstats.pfsyncs_hdrops++; 293 goto done; 294 } 295 296 if (iplen + sizeof(*ph) > m->m_len) { 297 if ((m = m_pullup(m, iplen + sizeof(*ph))) == NULL) { 298 pfsyncstats.pfsyncs_hdrops++; 299 goto done; 300 } 301 ip = mtod(m, struct ip *); 302 } 303 ph = (struct pfsync_header *)((char *)ip + iplen); 304 305 /* verify the version */ 306 if (ph->version != PFSYNC_VERSION) { 307 pfsyncstats.pfsyncs_badver++; 308 goto done; 309 } 310 311 action = ph->action; 312 count = ph->count; 313 314 /* make sure it's a valid action code */ 315 if (action >= PFSYNC_ACT_MAX) { 316 pfsyncstats.pfsyncs_badact++; 317 goto done; 318 } 319 320 /* Cheaper to grab this now than having to mess with mbufs later */ 321 src = ip->ip_src; 322 323 switch (action) { 324 case PFSYNC_ACT_CLR: { 325 struct pfi_kif *kif; 326 u_int32_t creatorid; 327 if ((mp = m_pulldown(m, iplen + sizeof(*ph), 328 sizeof(*cp), &offp)) == NULL) { 329 pfsyncstats.pfsyncs_badlen++; 330 return; 331 } 332 cp = (struct pfsync_state_clr *)(mp->m_data + offp); 333 creatorid = cp->creatorid; 334 335 crit_enter(); 336 if (cp->ifname[0] == '\0') { 337 RB_FOREACH(st, pf_state_tree_id, &tree_id) { 338 if (st->creatorid == creatorid) 339 st->timeout = PFTM_PURGE; 340 } 341 } else { 342 kif = pfi_lookup_if(cp->ifname); 343 if (kif == NULL) { 344 if (pf_status.debug >= PF_DEBUG_MISC) 345 kprintf("pfsync_input: PFSYNC_ACT_CLR " 346 "bad interface: %s\n", cp->ifname); 347 crit_exit(); 348 goto done; 349 } 350 RB_FOREACH(st, pf_state_tree_lan_ext, 351 &kif->pfik_lan_ext) { 352 if (st->creatorid == creatorid) 353 st->timeout = PFTM_PURGE; 354 } 355 } 356 pf_purge_expired_states(); 357 crit_exit(); 358 359 break; 360 } 361 case PFSYNC_ACT_INS: 362 if ((mp = m_pulldown(m, iplen + sizeof(*ph), 363 count * sizeof(*sp), &offp)) == NULL) { 364 pfsyncstats.pfsyncs_badlen++; 365 return; 366 } 367 368 crit_enter(); 369 for (i = 0, sp = (struct pfsync_state *)(mp->m_data + offp); 370 i < count; i++, sp++) { 371 /* check for invalid values */ 372 if (sp->timeout >= PFTM_MAX || 373 sp->src.state > PF_TCPS_PROXY_DST || 374 sp->dst.state > PF_TCPS_PROXY_DST || 375 sp->direction > PF_OUT || 376 (sp->af != AF_INET && sp->af != AF_INET6)) { 377 if (pf_status.debug >= PF_DEBUG_MISC) 378 kprintf("pfsync_insert: PFSYNC_ACT_INS: " 379 "invalid value\n"); 380 pfsyncstats.pfsyncs_badstate++; 381 continue; 382 } 383 384 if ((error = pfsync_insert_net_state(sp))) { 385 if (error == ENOMEM) { 386 crit_exit(); 387 goto done; 388 } 389 continue; 390 } 391 } 392 crit_exit(); 393 break; 394 case PFSYNC_ACT_UPD: 395 if ((mp = m_pulldown(m, iplen + sizeof(*ph), 396 count * sizeof(*sp), &offp)) == NULL) { 397 pfsyncstats.pfsyncs_badlen++; 398 return; 399 } 400 401 crit_enter(); 402 for (i = 0, sp = (struct pfsync_state *)(mp->m_data + offp); 403 i < count; i++, sp++) { 404 /* check for invalid values */ 405 if (sp->timeout >= PFTM_MAX || 406 sp->src.state > PF_TCPS_PROXY_DST || 407 sp->dst.state > PF_TCPS_PROXY_DST) { 408 if (pf_status.debug >= PF_DEBUG_MISC) 409 kprintf("pfsync_insert: PFSYNC_ACT_UPD: " 410 "invalid value\n"); 411 pfsyncstats.pfsyncs_badstate++; 412 continue; 413 } 414 415 bcopy(sp->id, &key.id, sizeof(key.id)); 416 key.creatorid = sp->creatorid; 417 418 st = pf_find_state_byid(&key); 419 if (st == NULL) { 420 /* insert the update */ 421 if (pfsync_insert_net_state(sp)) 422 pfsyncstats.pfsyncs_badstate++; 423 continue; 424 } 425 pf_state_peer_ntoh(&sp->src, &st->src); 426 pf_state_peer_ntoh(&sp->dst, &st->dst); 427 st->expire = ntohl(sp->expire) + time_second; 428 st->timeout = sp->timeout; 429 430 } 431 crit_exit(); 432 break; 433 /* 434 * It's not strictly necessary for us to support the "uncompressed" 435 * delete action, but it's relatively simple and maintains consistency. 436 */ 437 case PFSYNC_ACT_DEL: 438 if ((mp = m_pulldown(m, iplen + sizeof(*ph), 439 count * sizeof(*sp), &offp)) == NULL) { 440 pfsyncstats.pfsyncs_badlen++; 441 return; 442 } 443 444 crit_enter(); 445 for (i = 0, sp = (struct pfsync_state *)(mp->m_data + offp); 446 i < count; i++, sp++) { 447 bcopy(sp->id, &key.id, sizeof(key.id)); 448 key.creatorid = sp->creatorid; 449 450 st = pf_find_state_byid(&key); 451 if (st == NULL) { 452 pfsyncstats.pfsyncs_badstate++; 453 continue; 454 } 455 /* 456 * XXX 457 * pf_purge_expired_states() is expensive, 458 * we really want to purge the state directly. 459 */ 460 st->timeout = PFTM_PURGE; 461 st->sync_flags |= PFSTATE_FROMSYNC; 462 } 463 pf_purge_expired_states(); 464 crit_exit(); 465 break; 466 case PFSYNC_ACT_UPD_C: { 467 int update_requested = 0; 468 469 if ((mp = m_pulldown(m, iplen + sizeof(*ph), 470 count * sizeof(*up), &offp)) == NULL) { 471 pfsyncstats.pfsyncs_badlen++; 472 return; 473 } 474 475 crit_enter(); 476 for (i = 0, up = (struct pfsync_state_upd *)(mp->m_data + offp); 477 i < count; i++, up++) { 478 /* check for invalid values */ 479 if (up->timeout >= PFTM_MAX || 480 up->src.state > PF_TCPS_PROXY_DST || 481 up->dst.state > PF_TCPS_PROXY_DST) { 482 if (pf_status.debug >= PF_DEBUG_MISC) 483 kprintf("pfsync_insert: " 484 "PFSYNC_ACT_UPD_C: " 485 "invalid value\n"); 486 pfsyncstats.pfsyncs_badstate++; 487 continue; 488 } 489 490 bcopy(up->id, &key.id, sizeof(key.id)); 491 key.creatorid = up->creatorid; 492 493 st = pf_find_state_byid(&key); 494 if (st == NULL) { 495 /* We don't have this state. Ask for it. */ 496 pfsync_request_update(up, &src); 497 update_requested = 1; 498 pfsyncstats.pfsyncs_badstate++; 499 continue; 500 } 501 pf_state_peer_ntoh(&up->src, &st->src); 502 pf_state_peer_ntoh(&up->dst, &st->dst); 503 st->expire = ntohl(up->expire) + time_second; 504 st->timeout = up->timeout; 505 } 506 if (update_requested) 507 pfsync_sendout(sc); 508 crit_exit(); 509 break; 510 } 511 case PFSYNC_ACT_DEL_C: 512 if ((mp = m_pulldown(m, iplen + sizeof(*ph), 513 count * sizeof(*dp), &offp)) == NULL) { 514 pfsyncstats.pfsyncs_badlen++; 515 return; 516 } 517 518 crit_enter(); 519 for (i = 0, dp = (struct pfsync_state_del *)(mp->m_data + offp); 520 i < count; i++, dp++) { 521 bcopy(dp->id, &key.id, sizeof(key.id)); 522 key.creatorid = dp->creatorid; 523 524 st = pf_find_state_byid(&key); 525 if (st == NULL) { 526 pfsyncstats.pfsyncs_badstate++; 527 continue; 528 } 529 /* 530 * XXX 531 * pf_purge_expired_states() is expensive, 532 * we really want to purge the state directly. 533 */ 534 st->timeout = PFTM_PURGE; 535 st->sync_flags |= PFSTATE_FROMSYNC; 536 } 537 pf_purge_expired_states(); 538 crit_exit(); 539 break; 540 case PFSYNC_ACT_INS_F: 541 case PFSYNC_ACT_DEL_F: 542 /* not implemented */ 543 break; 544 case PFSYNC_ACT_UREQ: 545 if ((mp = m_pulldown(m, iplen + sizeof(*ph), 546 count * sizeof(*rup), &offp)) == NULL) { 547 pfsyncstats.pfsyncs_badlen++; 548 return; 549 } 550 551 crit_enter(); 552 /* XXX send existing. pfsync_pack_state should handle this. */ 553 if (sc->sc_mbuf != NULL) 554 pfsync_sendout(sc); 555 for (i = 0, 556 rup = (struct pfsync_state_upd_req *)(mp->m_data + offp); 557 i < count; i++, rup++) { 558 bcopy(rup->id, &key.id, sizeof(key.id)); 559 key.creatorid = rup->creatorid; 560 561 if (key.id == 0 && key.creatorid == 0) { 562 sc->sc_ureq_received = mycpu->gd_time_seconds; 563 if (pf_status.debug >= PF_DEBUG_MISC) 564 kprintf("pfsync: received " 565 "bulk update request\n"); 566 pfsync_send_bus(sc, PFSYNC_BUS_START); 567 callout_reset(&sc->sc_bulk_tmo, 1 * hz, 568 pfsync_bulk_update, 569 LIST_FIRST(&pfsync_list)); 570 } else { 571 st = pf_find_state_byid(&key); 572 if (st == NULL) { 573 pfsyncstats.pfsyncs_badstate++; 574 continue; 575 } 576 pfsync_pack_state(PFSYNC_ACT_UPD, st, 0); 577 } 578 } 579 if (sc->sc_mbuf != NULL) 580 pfsync_sendout(sc); 581 crit_exit(); 582 break; 583 case PFSYNC_ACT_BUS: 584 /* If we're not waiting for a bulk update, who cares. */ 585 if (sc->sc_ureq_sent == 0) 586 break; 587 588 if ((mp = m_pulldown(m, iplen + sizeof(*ph), 589 sizeof(*bus), &offp)) == NULL) { 590 pfsyncstats.pfsyncs_badlen++; 591 return; 592 } 593 bus = (struct pfsync_state_bus *)(mp->m_data + offp); 594 switch (bus->status) { 595 case PFSYNC_BUS_START: 596 callout_reset(&sc->sc_bulkfail_tmo, 597 pf_pool_limits[PF_LIMIT_STATES].limit / 598 (PFSYNC_BULKPACKETS * sc->sc_maxcount), 599 pfsync_bulkfail, LIST_FIRST(&pfsync_list)); 600 if (pf_status.debug >= PF_DEBUG_MISC) 601 kprintf("pfsync: received bulk " 602 "update start\n"); 603 break; 604 case PFSYNC_BUS_END: 605 if (mycpu->gd_time_seconds - ntohl(bus->endtime) >= 606 sc->sc_ureq_sent) { 607 /* that's it, we're happy */ 608 sc->sc_ureq_sent = 0; 609 sc->sc_bulk_tries = 0; 610 callout_stop(&sc->sc_bulkfail_tmo); 611 pfsync_sync_ok = 1; 612 if (pf_status.debug >= PF_DEBUG_MISC) 613 kprintf("pfsync: received valid " 614 "bulk update end\n"); 615 } else { 616 if (pf_status.debug >= PF_DEBUG_MISC) 617 kprintf("pfsync: received invalid " 618 "bulk update end: bad timestamp\n"); 619 } 620 break; 621 } 622 break; 623 } 624 625 done: 626 if (m) 627 m_freem(m); 628 } 629 630 int 631 pfsyncoutput(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, 632 struct rtentry *rt) 633 { 634 m_freem(m); 635 return (0); 636 } 637 638 /* ARGSUSED */ 639 int 640 pfsyncioctl(struct ifnet *ifp, u_long cmd, caddr_t data, struct ucred *cr) 641 { 642 struct pfsync_softc *sc = ifp->if_softc; 643 struct ifreq *ifr = (struct ifreq *)data; 644 struct ip_moptions *imo = &sc->sc_imo; 645 struct pfsyncreq pfsyncr; 646 struct ifnet *sifp; 647 int error; 648 649 switch (cmd) { 650 case SIOCSIFADDR: 651 case SIOCAIFADDR: 652 case SIOCSIFDSTADDR: 653 case SIOCSIFFLAGS: 654 if (ifp->if_flags & IFF_UP) 655 ifp->if_flags |= IFF_RUNNING; 656 else 657 ifp->if_flags &= ~IFF_RUNNING; 658 break; 659 case SIOCSIFMTU: 660 if (ifr->ifr_mtu < PFSYNC_MINMTU) 661 return (EINVAL); 662 if (ifr->ifr_mtu > MCLBYTES) 663 ifr->ifr_mtu = MCLBYTES; 664 crit_enter(); 665 if (ifr->ifr_mtu < ifp->if_mtu) 666 pfsync_sendout(sc); 667 pfsync_setmtu(sc, ifr->ifr_mtu); 668 crit_exit(); 669 break; 670 case SIOCGETPFSYNC: 671 bzero(&pfsyncr, sizeof(pfsyncr)); 672 if (sc->sc_sync_ifp) 673 strlcpy(pfsyncr.pfsyncr_syncif, 674 sc->sc_sync_ifp->if_xname, IFNAMSIZ); 675 pfsyncr.pfsyncr_maxupdates = sc->sc_maxupdates; 676 if ((error = copyout(&pfsyncr, ifr->ifr_data, sizeof(pfsyncr)))) 677 return (error); 678 break; 679 case SIOCSETPFSYNC: 680 if ((error = priv_check_cred(cr, PRIV_ROOT, NULL_CRED_OKAY)) != 0) 681 return (error); 682 if ((error = copyin(ifr->ifr_data, &pfsyncr, sizeof(pfsyncr)))) 683 return (error); 684 685 if (pfsyncr.pfsyncr_maxupdates > 255) 686 return (EINVAL); 687 sc->sc_maxupdates = pfsyncr.pfsyncr_maxupdates; 688 689 if (pfsyncr.pfsyncr_syncif[0] == 0) { 690 sc->sc_sync_ifp = NULL; 691 if (sc->sc_mbuf_net != NULL) { 692 /* Don't keep stale pfsync packets around. */ 693 crit_enter(); 694 m_freem(sc->sc_mbuf_net); 695 sc->sc_mbuf_net = NULL; 696 sc->sc_statep_net.s = NULL; 697 crit_exit(); 698 } 699 break; 700 } 701 if ((sifp = ifunit(pfsyncr.pfsyncr_syncif)) == NULL) 702 return (EINVAL); 703 else if (sifp == sc->sc_sync_ifp) 704 break; 705 706 crit_enter(); 707 if (sifp->if_mtu < sc->sc_if.if_mtu || 708 (sc->sc_sync_ifp != NULL && 709 sifp->if_mtu < sc->sc_sync_ifp->if_mtu) || 710 sifp->if_mtu < MCLBYTES - sizeof(struct ip)) 711 pfsync_sendout(sc); 712 sc->sc_sync_ifp = sifp; 713 714 pfsync_setmtu(sc, sc->sc_if.if_mtu); 715 716 if (imo->imo_num_memberships > 0) { 717 in_delmulti(imo->imo_membership[--imo->imo_num_memberships]); 718 imo->imo_multicast_ifp = NULL; 719 } 720 721 if (sc->sc_sync_ifp) { 722 struct in_addr addr; 723 724 addr.s_addr = htonl(INADDR_PFSYNC_GROUP); 725 /* XXX do we only use one group? Also see above */ 726 if ((imo->imo_membership[0] = 727 in_addmulti(&addr, sc->sc_sync_ifp)) == NULL) { 728 crit_exit(); 729 return (ENOBUFS); 730 } 731 imo->imo_num_memberships++; 732 imo->imo_multicast_ifp = sc->sc_sync_ifp; 733 imo->imo_multicast_ttl = PFSYNC_DFLTTL; 734 imo->imo_multicast_loop = 0; 735 736 /* Request a full state table update. */ 737 sc->sc_ureq_sent = mycpu->gd_time_seconds; 738 pfsync_sync_ok = 0; 739 if (pf_status.debug >= PF_DEBUG_MISC) 740 kprintf("pfsync: requesting bulk update\n"); 741 callout_reset(&sc->sc_bulkfail_tmo, 5 * hz, 742 pfsync_bulkfail, LIST_FIRST(&pfsync_list)); 743 pfsync_request_update(NULL, NULL); 744 pfsync_sendout(sc); 745 } 746 crit_exit(); 747 748 break; 749 750 default: 751 return (ENOTTY); 752 } 753 754 return (0); 755 } 756 757 void 758 pfsync_setmtu(struct pfsync_softc *sc, int mtu_req) 759 { 760 int mtu; 761 762 if (sc->sc_sync_ifp && sc->sc_sync_ifp->if_mtu < mtu_req) 763 mtu = sc->sc_sync_ifp->if_mtu; 764 else 765 mtu = mtu_req; 766 767 sc->sc_maxcount = (mtu - sizeof(struct pfsync_header)) / 768 sizeof(struct pfsync_state); 769 if (sc->sc_maxcount > 254) 770 sc->sc_maxcount = 254; 771 sc->sc_if.if_mtu = sizeof(struct pfsync_header) + 772 sc->sc_maxcount * sizeof(struct pfsync_state); 773 } 774 775 struct mbuf * 776 pfsync_get_mbuf(struct pfsync_softc *sc, u_int8_t action, void **sp) 777 { 778 struct pfsync_header *h; 779 struct mbuf *m; 780 int len; 781 782 MGETHDR(m, MB_DONTWAIT, MT_DATA); 783 if (m == NULL) { 784 sc->sc_if.if_oerrors++; 785 return (NULL); 786 } 787 788 switch (action) { 789 case PFSYNC_ACT_CLR: 790 len = sizeof(struct pfsync_header) + 791 sizeof(struct pfsync_state_clr); 792 break; 793 case PFSYNC_ACT_UPD_C: 794 len = (sc->sc_maxcount * sizeof(struct pfsync_state_upd)) + 795 sizeof(struct pfsync_header); 796 break; 797 case PFSYNC_ACT_DEL_C: 798 len = (sc->sc_maxcount * sizeof(struct pfsync_state_del)) + 799 sizeof(struct pfsync_header); 800 break; 801 case PFSYNC_ACT_UREQ: 802 len = (sc->sc_maxcount * sizeof(struct pfsync_state_upd_req)) + 803 sizeof(struct pfsync_header); 804 break; 805 case PFSYNC_ACT_BUS: 806 len = sizeof(struct pfsync_header) + 807 sizeof(struct pfsync_state_bus); 808 break; 809 default: 810 len = (sc->sc_maxcount * sizeof(struct pfsync_state)) + 811 sizeof(struct pfsync_header); 812 break; 813 } 814 815 if (len > MHLEN) { 816 MCLGET(m, MB_DONTWAIT); 817 if ((m->m_flags & M_EXT) == 0) { 818 m_free(m); 819 sc->sc_if.if_oerrors++; 820 return (NULL); 821 } 822 m->m_data += (MCLBYTES - len) &~ (sizeof(long) - 1); 823 } else 824 MH_ALIGN(m, len); 825 826 m->m_pkthdr.rcvif = NULL; 827 m->m_pkthdr.len = m->m_len = sizeof(struct pfsync_header); 828 h = mtod(m, struct pfsync_header *); 829 h->version = PFSYNC_VERSION; 830 h->af = 0; 831 h->count = 0; 832 h->action = action; 833 834 *sp = (void *)((char *)h + PFSYNC_HDRLEN); 835 callout_reset(&sc->sc_tmo, hz, pfsync_timeout, 836 LIST_FIRST(&pfsync_list)); 837 return (m); 838 } 839 840 int 841 pfsync_pack_state(u_int8_t action, struct pf_state *st, int compress) 842 { 843 struct ifnet *ifp = &(LIST_FIRST(&pfsync_list))->sc_if; 844 struct pfsync_softc *sc = ifp->if_softc; 845 struct pfsync_header *h, *h_net; 846 struct pfsync_state *sp = NULL; 847 struct pfsync_state_upd *up = NULL; 848 struct pfsync_state_del *dp = NULL; 849 struct pf_rule *r; 850 u_long secs; 851 int ret = 0; 852 u_int8_t i = 255, newaction = 0; 853 854 /* 855 * If a packet falls in the forest and there's nobody around to 856 * hear, does it make a sound? 857 */ 858 if (ifp->if_bpf == NULL && sc->sc_sync_ifp == NULL) { 859 /* Don't leave any stale pfsync packets hanging around. */ 860 if (sc->sc_mbuf != NULL) { 861 m_freem(sc->sc_mbuf); 862 sc->sc_mbuf = NULL; 863 sc->sc_statep.s = NULL; 864 } 865 return (0); 866 } 867 868 if (action >= PFSYNC_ACT_MAX) 869 return (EINVAL); 870 871 crit_enter(); 872 if (sc->sc_mbuf == NULL) { 873 if ((sc->sc_mbuf = pfsync_get_mbuf(sc, action, 874 (void *)&sc->sc_statep.s)) == NULL) { 875 crit_exit(); 876 return (ENOMEM); 877 } 878 h = mtod(sc->sc_mbuf, struct pfsync_header *); 879 } else { 880 h = mtod(sc->sc_mbuf, struct pfsync_header *); 881 if (h->action != action) { 882 pfsync_sendout(sc); 883 if ((sc->sc_mbuf = pfsync_get_mbuf(sc, action, 884 (void *)&sc->sc_statep.s)) == NULL) { 885 crit_exit(); 886 return (ENOMEM); 887 } 888 h = mtod(sc->sc_mbuf, struct pfsync_header *); 889 } else { 890 /* 891 * If it's an update, look in the packet to see if 892 * we already have an update for the state. 893 */ 894 if (action == PFSYNC_ACT_UPD && sc->sc_maxupdates) { 895 struct pfsync_state *usp = 896 (void *)((char *)h + PFSYNC_HDRLEN); 897 898 for (i = 0; i < h->count; i++) { 899 if (!memcmp(usp->id, &st->id, 900 PFSYNC_ID_LEN) && 901 usp->creatorid == st->creatorid) { 902 sp = usp; 903 sp->updates++; 904 break; 905 } 906 usp++; 907 } 908 } 909 } 910 } 911 912 secs = time_second; 913 914 st->pfsync_time = mycpu->gd_time_seconds; 915 TAILQ_REMOVE(&state_updates, st, u.s.entry_updates); 916 TAILQ_INSERT_TAIL(&state_updates, st, u.s.entry_updates); 917 918 if (sp == NULL) { 919 /* not a "duplicate" update */ 920 i = 255; 921 sp = sc->sc_statep.s++; 922 sc->sc_mbuf->m_pkthdr.len = 923 sc->sc_mbuf->m_len += sizeof(struct pfsync_state); 924 h->count++; 925 bzero(sp, sizeof(*sp)); 926 927 bcopy(&st->id, sp->id, sizeof(sp->id)); 928 sp->creatorid = st->creatorid; 929 930 strlcpy(sp->ifname, st->u.s.kif->pfik_name, sizeof(sp->ifname)); 931 pf_state_host_hton(&st->lan, &sp->lan); 932 pf_state_host_hton(&st->gwy, &sp->gwy); 933 pf_state_host_hton(&st->ext, &sp->ext); 934 935 bcopy(&st->rt_addr, &sp->rt_addr, sizeof(sp->rt_addr)); 936 937 sp->creation = htonl(secs - st->creation); 938 sp->packets[0] = htonl(st->packets[0]); 939 sp->packets[1] = htonl(st->packets[1]); 940 sp->bytes[0] = htonl(st->bytes[0]); 941 sp->bytes[1] = htonl(st->bytes[1]); 942 if ((r = st->rule.ptr) == NULL) 943 sp->rule = htonl(-1); 944 else 945 sp->rule = htonl(r->nr); 946 if ((r = st->anchor.ptr) == NULL) 947 sp->anchor = htonl(-1); 948 else 949 sp->anchor = htonl(r->nr); 950 sp->af = st->af; 951 sp->proto = st->proto; 952 sp->direction = st->direction; 953 sp->log = st->log; 954 sp->allow_opts = st->allow_opts; 955 sp->timeout = st->timeout; 956 957 sp->sync_flags = st->sync_flags & PFSTATE_NOSYNC; 958 } 959 960 pf_state_peer_hton(&st->src, &sp->src); 961 pf_state_peer_hton(&st->dst, &sp->dst); 962 963 if (st->expire <= secs) 964 sp->expire = htonl(0); 965 else 966 sp->expire = htonl(st->expire - secs); 967 968 /* do we need to build "compressed" actions for network transfer? */ 969 if (sc->sc_sync_ifp && compress) { 970 switch (action) { 971 case PFSYNC_ACT_UPD: 972 newaction = PFSYNC_ACT_UPD_C; 973 break; 974 case PFSYNC_ACT_DEL: 975 newaction = PFSYNC_ACT_DEL_C; 976 break; 977 default: 978 /* by default we just send the uncompressed states */ 979 break; 980 } 981 } 982 983 if (newaction) { 984 if (sc->sc_mbuf_net == NULL) { 985 if ((sc->sc_mbuf_net = pfsync_get_mbuf(sc, newaction, 986 (void *)&sc->sc_statep_net.s)) == NULL) { 987 crit_exit(); 988 return (ENOMEM); 989 } 990 } 991 h_net = mtod(sc->sc_mbuf_net, struct pfsync_header *); 992 993 switch (newaction) { 994 case PFSYNC_ACT_UPD_C: 995 if (i != 255) { 996 up = (void *)((char *)h_net + 997 PFSYNC_HDRLEN + (i * sizeof(*up))); 998 up->updates++; 999 } else { 1000 h_net->count++; 1001 sc->sc_mbuf_net->m_pkthdr.len = 1002 sc->sc_mbuf_net->m_len += sizeof(*up); 1003 up = sc->sc_statep_net.u++; 1004 1005 bzero(up, sizeof(*up)); 1006 bcopy(&st->id, up->id, sizeof(up->id)); 1007 up->creatorid = st->creatorid; 1008 } 1009 up->timeout = st->timeout; 1010 up->expire = sp->expire; 1011 up->src = sp->src; 1012 up->dst = sp->dst; 1013 break; 1014 case PFSYNC_ACT_DEL_C: 1015 sc->sc_mbuf_net->m_pkthdr.len = 1016 sc->sc_mbuf_net->m_len += sizeof(*dp); 1017 dp = sc->sc_statep_net.d++; 1018 h_net->count++; 1019 1020 bzero(dp, sizeof(*dp)); 1021 bcopy(&st->id, dp->id, sizeof(dp->id)); 1022 dp->creatorid = st->creatorid; 1023 break; 1024 } 1025 } 1026 1027 if (h->count == sc->sc_maxcount || 1028 (sc->sc_maxupdates && (sp->updates >= sc->sc_maxupdates))) 1029 ret = pfsync_sendout(sc); 1030 1031 crit_exit(); 1032 return (ret); 1033 } 1034 1035 /* This must be called in splnet() */ 1036 int 1037 pfsync_request_update(struct pfsync_state_upd *up, struct in_addr *src) 1038 { 1039 struct ifnet *ifp = &(LIST_FIRST(&pfsync_list))->sc_if; 1040 struct pfsync_header *h; 1041 struct pfsync_softc *sc = ifp->if_softc; 1042 struct pfsync_state_upd_req *rup; 1043 int ret = 0; 1044 1045 if (sc->sc_mbuf == NULL) { 1046 if ((sc->sc_mbuf = pfsync_get_mbuf(sc, PFSYNC_ACT_UREQ, 1047 (void *)&sc->sc_statep.s)) == NULL) { 1048 return (ENOMEM); 1049 } 1050 h = mtod(sc->sc_mbuf, struct pfsync_header *); 1051 } else { 1052 h = mtod(sc->sc_mbuf, struct pfsync_header *); 1053 if (h->action != PFSYNC_ACT_UREQ) { 1054 pfsync_sendout(sc); 1055 if ((sc->sc_mbuf = pfsync_get_mbuf(sc, PFSYNC_ACT_UREQ, 1056 (void *)&sc->sc_statep.s)) == NULL) { 1057 return (ENOMEM); 1058 } 1059 h = mtod(sc->sc_mbuf, struct pfsync_header *); 1060 } 1061 } 1062 1063 if (src != NULL) 1064 sc->sc_sendaddr = *src; 1065 sc->sc_mbuf->m_pkthdr.len = sc->sc_mbuf->m_len += sizeof(*rup); 1066 h->count++; 1067 rup = sc->sc_statep.r++; 1068 bzero(rup, sizeof(*rup)); 1069 if (up != NULL) { 1070 bcopy(up->id, rup->id, sizeof(rup->id)); 1071 rup->creatorid = up->creatorid; 1072 } 1073 1074 if (h->count == sc->sc_maxcount) 1075 ret = pfsync_sendout(sc); 1076 1077 return (ret); 1078 } 1079 1080 int 1081 pfsync_clear_states(u_int32_t creatorid, char *ifname) 1082 { 1083 struct ifnet *ifp = &(LIST_FIRST(&pfsync_list))->sc_if; 1084 struct pfsync_softc *sc = ifp->if_softc; 1085 struct pfsync_state_clr *cp; 1086 int ret; 1087 1088 crit_enter(); 1089 if (sc->sc_mbuf != NULL) 1090 pfsync_sendout(sc); 1091 if ((sc->sc_mbuf = pfsync_get_mbuf(sc, PFSYNC_ACT_CLR, 1092 (void *)&sc->sc_statep.c)) == NULL) { 1093 crit_exit(); 1094 return (ENOMEM); 1095 } 1096 sc->sc_mbuf->m_pkthdr.len = sc->sc_mbuf->m_len += sizeof(*cp); 1097 cp = sc->sc_statep.c; 1098 cp->creatorid = creatorid; 1099 if (ifname != NULL) 1100 strlcpy(cp->ifname, ifname, IFNAMSIZ); 1101 1102 ret = (pfsync_sendout(sc)); 1103 crit_exit(); 1104 return (ret); 1105 } 1106 1107 void 1108 pfsync_timeout(void *v) 1109 { 1110 struct pfsync_softc *sc = v; 1111 1112 crit_enter(); 1113 pfsync_sendout(sc); 1114 crit_exit(); 1115 } 1116 1117 void 1118 pfsync_send_bus(struct pfsync_softc *sc, u_int8_t status) 1119 { 1120 struct pfsync_state_bus *bus; 1121 1122 if (sc->sc_mbuf != NULL) 1123 pfsync_sendout(sc); 1124 1125 if (pfsync_sync_ok && 1126 (sc->sc_mbuf = pfsync_get_mbuf(sc, PFSYNC_ACT_BUS, 1127 (void *)&sc->sc_statep.b)) != NULL) { 1128 sc->sc_mbuf->m_pkthdr.len = sc->sc_mbuf->m_len += sizeof(*bus); 1129 bus = sc->sc_statep.b; 1130 bus->creatorid = pf_status.hostid; 1131 bus->status = status; 1132 bus->endtime = htonl(mycpu->gd_time_seconds - sc->sc_ureq_received); 1133 pfsync_sendout(sc); 1134 } 1135 } 1136 1137 void 1138 pfsync_bulk_update(void *v) 1139 { 1140 struct pfsync_softc *sc = v; 1141 int i = 0; 1142 struct pf_state *state; 1143 1144 crit_enter(); 1145 if (sc->sc_mbuf != NULL) 1146 pfsync_sendout(sc); 1147 1148 /* 1149 * Grab at most PFSYNC_BULKPACKETS worth of states which have not 1150 * been sent since the latest request was made. 1151 */ 1152 while ((state = TAILQ_FIRST(&state_updates)) != NULL && 1153 ++i < (sc->sc_maxcount * PFSYNC_BULKPACKETS)) { 1154 if (state->pfsync_time > sc->sc_ureq_received) { 1155 /* we're done */ 1156 pfsync_send_bus(sc, PFSYNC_BUS_END); 1157 sc->sc_ureq_received = 0; 1158 callout_stop(&sc->sc_bulk_tmo); 1159 if (pf_status.debug >= PF_DEBUG_MISC) 1160 kprintf("pfsync: bulk update complete\n"); 1161 break; 1162 } else { 1163 /* send an update and move to end of list */ 1164 if (!state->sync_flags) 1165 pfsync_pack_state(PFSYNC_ACT_UPD, state, 0); 1166 state->pfsync_time = mycpu->gd_time_seconds; 1167 TAILQ_REMOVE(&state_updates, state, u.s.entry_updates); 1168 TAILQ_INSERT_TAIL(&state_updates, state, 1169 u.s.entry_updates); 1170 1171 /* look again for more in a bit */ 1172 callout_reset(&sc->sc_bulk_tmo, 1, pfsync_timeout, 1173 LIST_FIRST(&pfsync_list)); 1174 } 1175 } 1176 if (sc->sc_mbuf != NULL) 1177 pfsync_sendout(sc); 1178 crit_exit(); 1179 } 1180 1181 void 1182 pfsync_bulkfail(void *v) 1183 { 1184 struct pfsync_softc *sc = v; 1185 1186 if (sc->sc_bulk_tries++ < PFSYNC_MAX_BULKTRIES) { 1187 /* Try again in a bit */ 1188 callout_reset(&sc->sc_bulkfail_tmo, 5 * hz, pfsync_bulkfail, 1189 LIST_FIRST(&pfsync_list)); 1190 pfsync_request_update(NULL, NULL); 1191 pfsync_sendout(sc); 1192 } else { 1193 /* Pretend like the transfer was ok */ 1194 sc->sc_ureq_sent = 0; 1195 sc->sc_bulk_tries = 0; 1196 pfsync_sync_ok = 1; 1197 if (pf_status.debug >= PF_DEBUG_MISC) 1198 kprintf("pfsync: failed to receive " 1199 "bulk update status\n"); 1200 callout_stop(&sc->sc_bulkfail_tmo); 1201 } 1202 } 1203 1204 int 1205 pfsync_sendout(struct pfsync_softc *sc) 1206 { 1207 struct ifnet *ifp = &sc->sc_if; 1208 struct mbuf *m; 1209 1210 callout_stop(&sc->sc_tmo); 1211 1212 if (sc->sc_mbuf == NULL) 1213 return (0); 1214 m = sc->sc_mbuf; 1215 sc->sc_mbuf = NULL; 1216 sc->sc_statep.s = NULL; 1217 1218 KASSERT(m != NULL, ("pfsync_sendout: null mbuf")); 1219 BPF_MTAP(ifp, m); 1220 1221 if (sc->sc_mbuf_net) { 1222 m_freem(m); 1223 m = sc->sc_mbuf_net; 1224 sc->sc_mbuf_net = NULL; 1225 sc->sc_statep_net.s = NULL; 1226 } 1227 1228 if (sc->sc_sync_ifp) { 1229 struct ip *ip; 1230 struct ifaddr *ifa; 1231 struct sockaddr sa; 1232 1233 M_PREPEND(m, sizeof(struct ip), MB_DONTWAIT); 1234 if (m == NULL) { 1235 pfsyncstats.pfsyncs_onomem++; 1236 return (0); 1237 } 1238 ip = mtod(m, struct ip *); 1239 ip->ip_v = IPVERSION; 1240 ip->ip_hl = sizeof(*ip) >> 2; 1241 ip->ip_tos = IPTOS_LOWDELAY; 1242 ip->ip_len = m->m_pkthdr.len; 1243 #ifdef RANDOM_IP_ID 1244 ip->ip_id = ip_randomid(); 1245 #else 1246 ip->ip_id = ntohs(ip_id++); 1247 #endif 1248 ip->ip_off = IP_DF; 1249 ip->ip_ttl = PFSYNC_DFLTTL; 1250 ip->ip_p = IPPROTO_PFSYNC; 1251 ip->ip_sum = 0; 1252 1253 bzero(&sa, sizeof(sa)); 1254 sa.sa_family = AF_INET; 1255 ifa = ifaof_ifpforaddr(&sa, sc->sc_sync_ifp); 1256 if (ifa == NULL) 1257 return (0); 1258 ip->ip_src.s_addr = ifatoia(ifa)->ia_addr.sin_addr.s_addr; 1259 1260 if (sc->sc_sendaddr.s_addr == htonl(INADDR_PFSYNC_GROUP)) 1261 m->m_flags |= M_MCAST; 1262 ip->ip_dst = sc->sc_sendaddr; 1263 sc->sc_sendaddr.s_addr = htonl(INADDR_PFSYNC_GROUP); 1264 1265 pfsyncstats.pfsyncs_opackets++; 1266 1267 if (ip_output(m, NULL, NULL, IP_RAWOUTPUT, &sc->sc_imo, NULL)) 1268 pfsyncstats.pfsyncs_oerrors++; 1269 } else 1270 m_freem(m); 1271 1272 return (0); 1273 } 1274 1275 static int 1276 pfsync_modevent(module_t mod, int type, void *data) 1277 { 1278 int error = 0; 1279 1280 switch (type) { 1281 case MOD_LOAD: 1282 LIST_INIT(&pfsync_list); 1283 if_clone_attach(&pfsync_cloner); 1284 break; 1285 1286 case MOD_UNLOAD: 1287 if_clone_detach(&pfsync_cloner); 1288 while (!LIST_EMPTY(&pfsync_list)) 1289 pfsync_clone_destroy( 1290 &LIST_FIRST(&pfsync_list)->sc_if); 1291 break; 1292 1293 default: 1294 error = EINVAL; 1295 break; 1296 } 1297 1298 return error; 1299 } 1300 1301 static moduledata_t pfsync_mod = { 1302 "pfsync", 1303 pfsync_modevent, 1304 0 1305 }; 1306 1307 #define PFSYNC_MODVER 1 1308 1309 DECLARE_MODULE(pfsync, pfsync_mod, SI_SUB_PSEUDO, SI_ORDER_ANY); 1310 MODULE_VERSION(pfsync, PFSYNC_MODVER); 1311