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