Deleted Added
full compact
1/* $FreeBSD: head/sys/contrib/pf/net/if_pfsync.c 141584 2005-02-09 19:29:13Z mlaier $ */
2/* $OpenBSD: if_pfsync.c,v 1.26 2004/03/28 18:14:20 mcbride Exp $ */
1/* $FreeBSD: head/sys/contrib/pf/net/if_pfsync.c 145836 2005-05-03 16:43:32Z mlaier $ */
2/* $OpenBSD: if_pfsync.c,v 1.46 2005/02/20 15:58:38 mcbride Exp $ */
3
4/*
5 * Copyright (c) 2002 Michael Shalayeff
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:

--- 32 unchanged lines hidden (view full) ---

43#endif
44
45#include <sys/param.h>
46#include <sys/proc.h>
47#include <sys/systm.h>
48#include <sys/time.h>
49#include <sys/mbuf.h>
50#include <sys/socket.h>
51#ifdef __FreeBSD__
51#include <sys/kernel.h>
52#ifdef __FreeBSD__
53#include <sys/endian.h>
54#include <sys/malloc.h>
55#include <sys/module.h>
56#include <sys/sockio.h>
57#include <sys/lock.h>
58#include <sys/mutex.h>
59#else
60#include <sys/ioctl.h>
61#include <sys/timeout.h>
62#endif
63
64#include <net/if.h>
65#if defined(__FreeBSD__)
66#include <net/if_clone.h>
67#endif
68#include <net/if_types.h>
69#include <net/route.h>
70#include <net/bpf.h>
71#include <netinet/tcp.h>
72#include <netinet/tcp_seq.h>
73
74#ifdef INET
75#include <netinet/in.h>
76#include <netinet/in_systm.h>
77#include <netinet/in_var.h>
78#include <netinet/ip.h>
79#include <netinet/ip_var.h>
80#endif
81
82#ifdef INET6
83#ifndef INET
84#include <netinet/in.h>
85#endif
86#include <netinet6/nd6.h>
87#endif /* INET6 */
88
89#ifdef __FreeBSD__
90#include "opt_carp.h"
91#ifdef DEV_CARP
92#define NCARP 1
93#endif
94#else
95#include "carp.h"
96#endif
97#if NCARP > 0
98extern int carp_suppress_preempt;
99#endif
100
101#include <net/pfvar.h>
102#include <net/if_pfsync.h>
103
104#ifdef __FreeBSD__
105#define PFSYNCNAME "pfsync"
106#endif
107
108#define PFSYNC_MINMTU \

--- 4 unchanged lines hidden (view full) ---

113int pfsyncdebug;
114#else
115#define DPRINTF(x)
116#endif
117
118#ifndef __FreeBSD__
119struct pfsync_softc pfsyncif;
120#endif
106int pfsync_sync_ok;
121struct pfsyncstats pfsyncstats;
122
123#ifdef __FreeBSD__
124
125/*
126 * Locking notes:
127 * Whenever we really touch/look at the state table we have to hold the
128 * PF_LOCK. Functions that do just the interface handling, grab the per

--- 16 unchanged lines hidden (view full) ---

145struct mbuf *pfsync_get_mbuf(struct pfsync_softc *, u_int8_t, void **);
146int pfsync_request_update(struct pfsync_state_upd *, struct in_addr *);
147int pfsync_sendout(struct pfsync_softc *);
148void pfsync_timeout(void *);
149void pfsync_send_bus(struct pfsync_softc *, u_int8_t);
150void pfsync_bulk_update(void *);
151void pfsync_bulkfail(void *);
152
153int pfsync_sync_ok;
154#ifndef __FreeBSD__
155extern int ifqmaxlen;
156extern struct timeval time;
157extern struct timeval mono_time;
158extern int hz;
159#endif
160
161#ifdef __FreeBSD__

--- 75 unchanged lines hidden (view full) ---

237
238 pfsync_sync_ok = 1;
239 bzero(&pfsyncif, sizeof(pfsyncif));
240 pfsyncif.sc_mbuf = NULL;
241 pfsyncif.sc_mbuf_net = NULL;
242 pfsyncif.sc_statep.s = NULL;
243 pfsyncif.sc_statep_net.s = NULL;
244 pfsyncif.sc_maxupdates = 128;
245 pfsyncif.sc_sync_peer.s_addr = INADDR_PFSYNC_GROUP;
246 pfsyncif.sc_sendaddr.s_addr = INADDR_PFSYNC_GROUP;
247 pfsyncif.sc_ureq_received = 0;
248 pfsyncif.sc_ureq_sent = 0;
249 ifp = &pfsyncif.sc_if;
250 strlcpy(ifp->if_xname, "pfsync0", sizeof ifp->if_xname);
251 ifp->if_softc = &pfsyncif;
252 ifp->if_ioctl = pfsyncioctl;
253 ifp->if_output = pfsyncoutput;

--- 80 unchanged lines hidden (view full) ---

334 pfi_maybe_destroy(kif);
335 return (ENOMEM);
336 }
337 bzero(st, sizeof(*st));
338
339 st->rule.ptr = r;
340 /* XXX get pointers to nat_rule and anchor */
341
342 /* XXX when we have nat_rule/anchors, use STATE_INC_COUNTERS */
343 r->states++;
344
345 /* fill in the rest of the state entry */
346 pf_state_host_ntoh(&sp->lan, &st->lan);
347 pf_state_host_ntoh(&sp->gwy, &st->gwy);
348 pf_state_host_ntoh(&sp->ext, &st->ext);
349
350 pf_state_peer_ntoh(&sp->src, &st->src);
351 pf_state_peer_ntoh(&sp->dst, &st->dst);
352
353 bcopy(&sp->rt_addr, &st->rt_addr, sizeof(st->rt_addr));
335#ifdef __FreeBSD__
336 st->creation = ntohl(sp->creation) + time_second;
354 st->creation = time_second - ntohl(sp->creation);
355 st->expire = ntohl(sp->expire) + time_second;
338#else
339 st->creation = ntohl(sp->creation) + time.tv_sec;
340 st->expire = ntohl(sp->expire) + time.tv_sec;
341#endif
356
357 st->af = sp->af;
358 st->proto = sp->proto;
359 st->direction = sp->direction;
360 st->log = sp->log;
361 st->timeout = sp->timeout;
362 st->allow_opts = sp->allow_opts;
363
364 bcopy(sp->id, &st->id, sizeof(st->id));
365 st->creatorid = sp->creatorid;
352 st->sync_flags = sp->sync_flags | PFSTATE_FROMSYNC;
366 st->sync_flags = PFSTATE_FROMSYNC;
367
368
369 if (pf_insert_state(kif, st)) {
370 pfi_maybe_destroy(kif);
371 /* XXX when we have nat_rule/anchors, use STATE_DEC_COUNTERS */
372 r->states--;
373 pool_put(&pf_state_pl, st);
374 return (EINVAL);
375 }
376
377 return (0);
378}
379
380void

--- 14 unchanged lines hidden (view full) ---

395 struct pfsync_state *sp;
396 struct pfsync_state_upd *up;
397 struct pfsync_state_del *dp;
398 struct pfsync_state_clr *cp;
399 struct pfsync_state_upd_req *rup;
400 struct pfsync_state_bus *bus;
401 struct in_addr src;
402 struct mbuf *mp;
387 int iplen, action, error, i, s, count, offp;
403 int iplen, action, error, i, s, count, offp, sfail, stale = 0;
404
405 pfsyncstats.pfsyncs_ipackets++;
406
407 /* verify that we have a sync interface configured */
408 if (!sc->sc_sync_ifp || !pf_status.running) /* XXX PF_LOCK? */
409 goto done;
410
411 /* verify that the packet came in on the right interface */

--- 39 unchanged lines hidden (view full) ---

451 goto done;
452 }
453
454 /* Cheaper to grab this now than having to mess with mbufs later */
455 src = ip->ip_src;
456
457 switch (action) {
458 case PFSYNC_ACT_CLR: {
459 struct pf_state *nexts;
460 struct pfi_kif *kif;
461 u_int32_t creatorid;
462 if ((mp = m_pulldown(m, iplen + sizeof(*ph),
463 sizeof(*cp), &offp)) == NULL) {
464 pfsyncstats.pfsyncs_badlen++;
465 return;
466 }
467 cp = (struct pfsync_state_clr *)(mp->m_data + offp);
468 creatorid = cp->creatorid;
469
470 s = splsoftnet();
471#ifdef __FreeBSD__
472 PF_LOCK();
473#endif
474 if (cp->ifname[0] == '\0') {
458 RB_FOREACH(st, pf_state_tree_id, &tree_id) {
459 if (st->creatorid == creatorid)
475 for (st = RB_MIN(pf_state_tree_id, &tree_id);
476 st; st = nexts) {
477 nexts = RB_NEXT(pf_state_tree_id, &tree_id, st);
478 if (st->creatorid == creatorid) {
479 st->timeout = PFTM_PURGE;
480 pf_purge_expired_state(st);
481 }
482 }
483 } else {
484 kif = pfi_lookup_if(cp->ifname);
485 if (kif == NULL) {
486 if (pf_status.debug >= PF_DEBUG_MISC)
487 printf("pfsync_input: PFSYNC_ACT_CLR "
488 "bad interface: %s\n", cp->ifname);
489 splx(s);
490#ifdef __FreeBSD__
491 PF_UNLOCK();
492#endif
493 goto done;
494 }
474 RB_FOREACH(st, pf_state_tree_lan_ext,
475 &kif->pfik_lan_ext) {
476 if (st->creatorid == creatorid)
495 for (st = RB_MIN(pf_state_tree_lan_ext,
496 &kif->pfik_lan_ext); st; st = nexts) {
497 nexts = RB_NEXT(pf_state_tree_lan_ext,
498 &kif->pfik_lan_ext, st);
499 if (st->creatorid == creatorid) {
500 st->timeout = PFTM_PURGE;
501 pf_purge_expired_state(st);
502 }
503 }
504 }
480 pf_purge_expired_states();
505#ifdef __FreeBSD__
506 PF_UNLOCK();
507#endif
508 splx(s);
509
510 break;
511 }
512 case PFSYNC_ACT_INS:

--- 46 unchanged lines hidden (view full) ---

559 }
560
561 s = splsoftnet();
562#ifdef __FreeBSD__
563 PF_LOCK();
564#endif
565 for (i = 0, sp = (struct pfsync_state *)(mp->m_data + offp);
566 i < count; i++, sp++) {
567 int flags = PFSYNC_FLAG_STALE;
568
569 /* check for invalid values */
570 if (sp->timeout >= PFTM_MAX ||
571 sp->src.state > PF_TCPS_PROXY_DST ||
572 sp->dst.state > PF_TCPS_PROXY_DST) {
573 if (pf_status.debug >= PF_DEBUG_MISC)
574 printf("pfsync_insert: PFSYNC_ACT_UPD: "
575 "invalid value\n");
576 pfsyncstats.pfsyncs_badstate++;

--- 5 unchanged lines hidden (view full) ---

582
583 st = pf_find_state_byid(&key);
584 if (st == NULL) {
585 /* insert the update */
586 if (pfsync_insert_net_state(sp))
587 pfsyncstats.pfsyncs_badstate++;
588 continue;
589 }
564 pf_state_peer_ntoh(&sp->src, &st->src);
565 pf_state_peer_ntoh(&sp->dst, &st->dst);
590 sfail = 0;
591 if (st->proto == IPPROTO_TCP) {
592 /*
593 * The state should never go backwards except
594 * for syn-proxy states. Neither should the
595 * sequence window slide backwards.
596 */
597 if (st->src.state > sp->src.state &&
598 (st->src.state < PF_TCPS_PROXY_SRC ||
599 sp->src.state >= PF_TCPS_PROXY_SRC))
600 sfail = 1;
601 else if (SEQ_GT(st->src.seqlo,
602 ntohl(sp->src.seqlo)))
603 sfail = 3;
604 else if (st->dst.state > sp->dst.state) {
605 /* There might still be useful
606 * information about the src state here,
607 * so import that part of the update,
608 * then "fail" so we send the updated
609 * state back to the peer who is missing
610 * our what we know. */
611 pf_state_peer_ntoh(&sp->src, &st->src);
612 /* XXX do anything with timeouts? */
613 sfail = 7;
614 flags = 0;
615 } else if (st->dst.state >= TCPS_SYN_SENT &&
616 SEQ_GT(st->dst.seqlo, ntohl(sp->dst.seqlo)))
617 sfail = 4;
618 } else {
619 /*
620 * Non-TCP protocol state machine always go
621 * forwards
622 */
623 if (st->src.state > sp->src.state)
624 sfail = 5;
625 else if ( st->dst.state > sp->dst.state)
626 sfail = 6;
627 }
628 if (sfail) {
629 if (pf_status.debug >= PF_DEBUG_MISC)
630 printf("pfsync: %s stale update "
631 "(%d) id: %016llx "
632 "creatorid: %08x\n",
633 (sfail < 7 ? "ignoring"
634 : "partial"), sfail,
635#ifdef __FreeBSD__
567 st->expire = ntohl(sp->expire) + time_second;
636 (unsigned long long)be64toh(st->id),
637#else
569 st->expire = ntohl(sp->expire) + time.tv_sec;
638 betoh64(st->id),
639#endif
571 st->timeout = sp->timeout;
640 ntohl(st->creatorid));
641 pfsyncstats.pfsyncs_badstate++;
642
643 if (!(sp->sync_flags & PFSTATE_STALE)) {
644 /* we have a better state, send it */
645 if (sc->sc_mbuf != NULL && !stale)
646 pfsync_sendout(sc);
647 stale++;
648 if (!st->sync_flags)
649 pfsync_pack_state(
650 PFSYNC_ACT_UPD, st, flags);
651 }
652 continue;
653 }
654 pf_state_peer_ntoh(&sp->src, &st->src);
655 pf_state_peer_ntoh(&sp->dst, &st->dst);
656 st->expire = ntohl(sp->expire) + time_second;
657 st->timeout = sp->timeout;
658 }
659 if (stale && sc->sc_mbuf != NULL)
660 pfsync_sendout(sc);
661#ifdef __FreeBSD__
662 PF_UNLOCK();
663#endif
664 splx(s);
665 break;
666 /*
667 * It's not strictly necessary for us to support the "uncompressed"
668 * delete action, but it's relatively simple and maintains consistency.

--- 14 unchanged lines hidden (view full) ---

683 bcopy(sp->id, &key.id, sizeof(key.id));
684 key.creatorid = sp->creatorid;
685
686 st = pf_find_state_byid(&key);
687 if (st == NULL) {
688 pfsyncstats.pfsyncs_badstate++;
689 continue;
690 }
604 /*
605 * XXX
606 * pf_purge_expired_states() is expensive,
607 * we really want to purge the state directly.
608 */
691 st->timeout = PFTM_PURGE;
692 st->sync_flags |= PFSTATE_FROMSYNC;
693 pf_purge_expired_state(st);
694 }
612 pf_purge_expired_states();
695#ifdef __FreeBSD__
696 PF_UNLOCK();
697#endif
698 splx(s);
699 break;
700 case PFSYNC_ACT_UPD_C: {
701 int update_requested = 0;
702

--- 22 unchanged lines hidden (view full) ---

725 }
726
727 bcopy(up->id, &key.id, sizeof(key.id));
728 key.creatorid = up->creatorid;
729
730 st = pf_find_state_byid(&key);
731 if (st == NULL) {
732 /* We don't have this state. Ask for it. */
651 pfsync_request_update(up, &src);
733 error = pfsync_request_update(up, &src);
734 if (error == ENOMEM) {
735 splx(s);
736 goto done;
737 }
738 update_requested = 1;
739 pfsyncstats.pfsyncs_badstate++;
740 continue;
741 }
656 pf_state_peer_ntoh(&up->src, &st->src);
657 pf_state_peer_ntoh(&up->dst, &st->dst);
742 sfail = 0;
743 if (st->proto == IPPROTO_TCP) {
744 /*
745 * The state should never go backwards except
746 * for syn-proxy states. Neither should the
747 * sequence window slide backwards.
748 */
749 if (st->src.state > up->src.state &&
750 (st->src.state < PF_TCPS_PROXY_SRC ||
751 up->src.state >= PF_TCPS_PROXY_SRC))
752 sfail = 1;
753 else if (st->dst.state > up->dst.state)
754 sfail = 2;
755 else if (SEQ_GT(st->src.seqlo,
756 ntohl(up->src.seqlo)))
757 sfail = 3;
758 else if (st->dst.state >= TCPS_SYN_SENT &&
759 SEQ_GT(st->dst.seqlo, ntohl(up->dst.seqlo)))
760 sfail = 4;
761 } else {
762 /*
763 * Non-TCP protocol state machine always go
764 * forwards
765 */
766 if (st->src.state > up->src.state)
767 sfail = 5;
768 else if (st->dst.state > up->dst.state)
769 sfail = 6;
770 }
771 if (sfail) {
772 if (pf_status.debug >= PF_DEBUG_MISC)
773 printf("pfsync: ignoring stale update "
774 "(%d) id: %016llx "
775 "creatorid: %08x\n", sfail,
776#ifdef __FreeBSD__
659 st->expire = ntohl(up->expire) + time_second;
777 (unsigned long long)be64toh(st->id),
778#else
661 st->expire = ntohl(up->expire) + time.tv_sec;
779 betoh64(st->id),
780#endif
781 ntohl(st->creatorid));
782 pfsyncstats.pfsyncs_badstate++;
783
784 /* we have a better state, send it out */
785 if ((!stale || update_requested) &&
786 sc->sc_mbuf != NULL) {
787 pfsync_sendout(sc);
788 update_requested = 0;
789 }
790 stale++;
791 if (!st->sync_flags)
792 pfsync_pack_state(PFSYNC_ACT_UPD, st,
793 PFSYNC_FLAG_STALE);
794 continue;
795 }
796 pf_state_peer_ntoh(&up->src, &st->src);
797 pf_state_peer_ntoh(&up->dst, &st->dst);
798 st->expire = ntohl(up->expire) + time_second;
799 st->timeout = up->timeout;
800 }
665 if (update_requested)
801 if ((update_requested || stale) && sc->sc_mbuf)
802 pfsync_sendout(sc);
803#ifdef __FreeBSD__
804 PF_UNLOCK();
805#endif
806 splx(s);
807 break;
808 }
809 case PFSYNC_ACT_DEL_C:

--- 12 unchanged lines hidden (view full) ---

822 bcopy(dp->id, &key.id, sizeof(key.id));
823 key.creatorid = dp->creatorid;
824
825 st = pf_find_state_byid(&key);
826 if (st == NULL) {
827 pfsyncstats.pfsyncs_badstate++;
828 continue;
829 }
694 /*
695 * XXX
696 * pf_purge_expired_states() is expensive,
697 * we really want to purge the state directly.
698 */
830 st->timeout = PFTM_PURGE;
831 st->sync_flags |= PFSTATE_FROMSYNC;
832 pf_purge_expired_state(st);
833 }
702 pf_purge_expired_states();
834#ifdef __FreeBSD__
835 PF_UNLOCK();
836#endif
837 splx(s);
838 break;
839 case PFSYNC_ACT_INS_F:
840 case PFSYNC_ACT_DEL_F:
841 /* not implemented */
842 break;
843 case PFSYNC_ACT_UREQ:
844 if ((mp = m_pulldown(m, iplen + sizeof(*ph),
845 count * sizeof(*rup), &offp)) == NULL) {
846 pfsyncstats.pfsyncs_badlen++;
847 return;
848 }
849
850 s = splsoftnet();
720 /* XXX send existing. pfsync_pack_state should handle this. */
851#ifdef __FreeBSD__
852 PF_LOCK();
853#endif
854 if (sc->sc_mbuf != NULL)
855 pfsync_sendout(sc);
856 for (i = 0,
857 rup = (struct pfsync_state_upd_req *)(mp->m_data + offp);
858 i < count; i++, rup++) {
859 bcopy(rup->id, &key.id, sizeof(key.id));
860 key.creatorid = rup->creatorid;
861
862 if (key.id == 0 && key.creatorid == 0) {
733#ifdef __FreeBSD__
863 sc->sc_ureq_received = time_uptime;
735#else
736 sc->sc_ureq_received = mono_time.tv_sec;
737#endif
864 if (pf_status.debug >= PF_DEBUG_MISC)
865 printf("pfsync: received "
866 "bulk update request\n");
867 pfsync_send_bus(sc, PFSYNC_BUS_START);
868#ifdef __FreeBSD__
869 callout_reset(&sc->sc_bulk_tmo, 1 * hz,
870 pfsync_bulk_update,
871 LIST_FIRST(&pfsync_list));
872#else
873 timeout_add(&sc->sc_bulk_tmo, 1 * hz);
874#endif
875 } else {
876 st = pf_find_state_byid(&key);
877 if (st == NULL) {
878 pfsyncstats.pfsyncs_badstate++;
879 continue;
880 }
755 pfsync_pack_state(PFSYNC_ACT_UPD, st, 0);
881 if (!st->sync_flags)
882 pfsync_pack_state(PFSYNC_ACT_UPD,
883 st, 0);
884 }
885 }
886 if (sc->sc_mbuf != NULL)
887 pfsync_sendout(sc);
888#ifdef __FreeBSD__
889 PF_UNLOCK();
890#endif
891 splx(s);

--- 21 unchanged lines hidden (view full) ---

913 pf_pool_limits[PF_LIMIT_STATES].limit /
914 (PFSYNC_BULKPACKETS * sc->sc_maxcount));
915#endif
916 if (pf_status.debug >= PF_DEBUG_MISC)
917 printf("pfsync: received bulk "
918 "update start\n");
919 break;
920 case PFSYNC_BUS_END:
793#ifdef __FreeBSD__
921 if (time_uptime - ntohl(bus->endtime) >=
795#else
796 if (mono_time.tv_sec - ntohl(bus->endtime) >=
797#endif
922 sc->sc_ureq_sent) {
923 /* that's it, we're happy */
924 sc->sc_ureq_sent = 0;
925 sc->sc_bulk_tries = 0;
926#ifdef __FreeBSD__
927 callout_stop(&sc->sc_bulkfail_tmo);
928#else
929 timeout_del(&sc->sc_bulkfail_tmo);
930#endif
931#if NCARP > 0 /* XXX_IMPORT */
932 if (!pfsync_sync_ok)
933 carp_suppress_preempt--;
934#endif
935 pfsync_sync_ok = 1;
936 if (pf_status.debug >= PF_DEBUG_MISC)
937 printf("pfsync: received valid "
938 "bulk update end\n");
939 } else {
940 if (pf_status.debug >= PF_DEBUG_MISC)
941 printf("pfsync: received invalid "
942 "bulk update end: bad timestamp\n");

--- 59 unchanged lines hidden (view full) ---

1002 splx(s);
1003 break;
1004 case SIOCGETPFSYNC:
1005#ifdef __FreeBSD__
1006 /* XXX: read unlocked */
1007#endif
1008 bzero(&pfsyncr, sizeof(pfsyncr));
1009 if (sc->sc_sync_ifp)
882 strlcpy(pfsyncr.pfsyncr_syncif,
1010 strlcpy(pfsyncr.pfsyncr_syncdev,
1011 sc->sc_sync_ifp->if_xname, IFNAMSIZ);
1012 pfsyncr.pfsyncr_syncpeer = sc->sc_sync_peer;
1013 pfsyncr.pfsyncr_maxupdates = sc->sc_maxupdates;
1014 if ((error = copyout(&pfsyncr, ifr->ifr_data, sizeof(pfsyncr))))
1015 return (error);
1016 break;
1017 case SIOCSETPFSYNC:
1018#ifdef __FreeBSD__
1019 if ((error = suser(curthread)) != 0)
1020#else
1021 if ((error = suser(p, p->p_acflag)) != 0)
1022#endif
1023 return (error);
1024 if ((error = copyin(ifr->ifr_data, &pfsyncr, sizeof(pfsyncr))))
1025 return (error);
1026
1027 if (pfsyncr.pfsyncr_syncpeer.s_addr == 0)
1028 sc->sc_sync_peer.s_addr = INADDR_PFSYNC_GROUP;
1029 else
1030 sc->sc_sync_peer.s_addr =
1031 pfsyncr.pfsyncr_syncpeer.s_addr;
1032
1033 if (pfsyncr.pfsyncr_maxupdates > 255)
1034 return (EINVAL);
1035#ifdef __FreeBSD__
1036 PF_LOCK();
1037#endif
1038 sc->sc_maxupdates = pfsyncr.pfsyncr_maxupdates;
1039
905 if (pfsyncr.pfsyncr_syncif[0] == 0) {
1040 if (pfsyncr.pfsyncr_syncdev[0] == 0) {
1041 sc->sc_sync_ifp = NULL;
1042 if (sc->sc_mbuf_net != NULL) {
1043 /* Don't keep stale pfsync packets around. */
1044 s = splnet();
1045 m_freem(sc->sc_mbuf_net);
1046 sc->sc_mbuf_net = NULL;
1047 sc->sc_statep_net.s = NULL;
1048 splx(s);
1049 }
1050 if (imo->imo_num_memberships > 0) {
1051 in_delmulti(imo->imo_membership[--imo->imo_num_memberships]);
1052 imo->imo_multicast_ifp = NULL;
1053 }
1054#ifdef __FreeBSD__
1055 PF_UNLOCK();
1056#endif
1057 break;
1058 }
920 if ((sifp = ifunit(pfsyncr.pfsyncr_syncif)) == NULL) {
1059
1060 if ((sifp = ifunit(pfsyncr.pfsyncr_syncdev)) == NULL) {
1061#ifdef __FreeBSD__
1062 PF_UNLOCK();
1063#endif
1064 return (EINVAL);
1065 }
926 else if (sifp == sc->sc_sync_ifp) {
927#ifdef __FreeBSD__
928 PF_UNLOCK();
929#endif
930 break;
931 }
1066
1067 s = splnet();
1068#ifdef __FreeBSD__
1069 if (sifp->if_mtu < SCP2IFP(sc)->if_mtu ||
1070#else
1071 if (sifp->if_mtu < sc->sc_if.if_mtu ||
1072#endif
1073 (sc->sc_sync_ifp != NULL &&

--- 8 unchanged lines hidden (view full) ---

1082 pfsync_setmtu(sc, sc->sc_if.if_mtu);
1083#endif
1084
1085 if (imo->imo_num_memberships > 0) {
1086 in_delmulti(imo->imo_membership[--imo->imo_num_memberships]);
1087 imo->imo_multicast_ifp = NULL;
1088 }
1089
956 if (sc->sc_sync_ifp) {
1090 if (sc->sc_sync_ifp &&
1091 sc->sc_sync_peer.s_addr == INADDR_PFSYNC_GROUP) {
1092 struct in_addr addr;
1093
1094 if (!(sc->sc_sync_ifp->if_flags & IFF_MULTICAST)) {
1095 sc->sc_sync_ifp = NULL;
1096#ifdef __FreeBSD__
1097 PF_UNLOCK();
1098#endif
1099 splx(s);
1100 return (EADDRNOTAVAIL);
1101 }
1102#ifdef __FreeBSD__
1103 PF_UNLOCK(); /* addmulti mallocs w/ WAITOK */
1104 addr.s_addr = htonl(INADDR_PFSYNC_GROUP);
1105#else
1106 addr.s_addr = INADDR_PFSYNC_GROUP;
1107#endif
1108
1109 if ((imo->imo_membership[0] =
1110 in_addmulti(&addr, sc->sc_sync_ifp)) == NULL) {
1111 sc->sc_sync_ifp = NULL;
1112 splx(s);
1113 return (ENOBUFS);
1114 }
1115 imo->imo_num_memberships++;
1116 imo->imo_multicast_ifp = sc->sc_sync_ifp;
1117 imo->imo_multicast_ttl = PFSYNC_DFLTTL;
1118 imo->imo_multicast_loop = 0;
1119 }
1120
1121 if (sc->sc_sync_ifp ||
1122 sc->sc_sendaddr.s_addr != INADDR_PFSYNC_GROUP) {
1123 /* Request a full state table update. */
1124#ifdef __FreeBSD__
1125 PF_LOCK();
1126#endif
1127 sc->sc_ureq_sent = time_uptime;
979#else
980 sc->sc_ureq_sent = mono_time.tv_sec;
1128#if NCARP > 0
1129 if (pfsync_sync_ok)
1130 carp_suppress_preempt++;
1131#endif
1132 pfsync_sync_ok = 0;
1133 if (pf_status.debug >= PF_DEBUG_MISC)
1134 printf("pfsync: requesting bulk update\n");
1135#ifdef __FreeBSD__
1136 callout_reset(&sc->sc_bulkfail_tmo, 5 * hz,
1137 pfsync_bulkfail, LIST_FIRST(&pfsync_list));
1138#else
1139 timeout_add(&sc->sc_bulkfail_tmo, 5 * hz);
1140#endif
991 pfsync_request_update(NULL, NULL);
1141 error = pfsync_request_update(NULL, NULL);
1142 if (error == ENOMEM) {
1143#ifdef __FreeBSD__
1144 PF_UNLOCK();
1145#endif
1146 splx(s);
1147 return (ENOMEM);
1148 }
1149 pfsync_sendout(sc);
1150 }
1151#ifdef __FreeBSD__
1152 PF_UNLOCK();
1153#endif
1154 splx(s);
1155
1156 break;

--- 104 unchanged lines hidden (view full) ---

1261 LIST_FIRST(&pfsync_list));
1262#else
1263 timeout_add(&sc->sc_tmo, hz);
1264#endif
1265 return (m);
1266}
1267
1268int
1112pfsync_pack_state(u_int8_t action, struct pf_state *st, int compress)
1269pfsync_pack_state(u_int8_t action, struct pf_state *st, int flags)
1270{
1271#ifdef __FreeBSD__
1272 struct ifnet *ifp = SCP2IFP(LIST_FIRST(&pfsync_list));
1273#else
1274 struct ifnet *ifp = &pfsyncif.sc_if;
1275#endif
1276 struct pfsync_softc *sc = ifp->if_softc;
1277 struct pfsync_header *h, *h_net;

--- 7 unchanged lines hidden (view full) ---

1285
1286#ifdef __FreeBSD__
1287 PF_ASSERT(MA_OWNED);
1288#endif
1289 /*
1290 * If a packet falls in the forest and there's nobody around to
1291 * hear, does it make a sound?
1292 */
1136 if (ifp->if_bpf == NULL && sc->sc_sync_ifp == NULL) {
1293 if (ifp->if_bpf == NULL && sc->sc_sync_ifp == NULL &&
1294 sc->sc_sync_peer.s_addr == INADDR_PFSYNC_GROUP) {
1295 /* Don't leave any stale pfsync packets hanging around. */
1296 if (sc->sc_mbuf != NULL) {
1297 m_freem(sc->sc_mbuf);
1298 sc->sc_mbuf = NULL;
1299 sc->sc_statep.s = NULL;
1300 }
1301 return (0);
1302 }

--- 37 unchanged lines hidden (view full) ---

1340 break;
1341 }
1342 usp++;
1343 }
1344 }
1345 }
1346 }
1347
1190#ifdef __FreeBSD__
1348 secs = time_second;
1349
1350 st->pfsync_time = time_uptime;
1194#else
1195 secs = time.tv_sec;
1196
1197 st->pfsync_time = mono_time.tv_sec;
1198#endif
1351 TAILQ_REMOVE(&state_updates, st, u.s.entry_updates);
1352 TAILQ_INSERT_TAIL(&state_updates, st, u.s.entry_updates);
1353
1354 if (sp == NULL) {
1355 /* not a "duplicate" update */
1356 i = 255;
1357 sp = sc->sc_statep.s++;
1358 sc->sc_mbuf->m_pkthdr.len =

--- 26 unchanged lines hidden (view full) ---

1385 sp->anchor = htonl(r->nr);
1386 sp->af = st->af;
1387 sp->proto = st->proto;
1388 sp->direction = st->direction;
1389 sp->log = st->log;
1390 sp->allow_opts = st->allow_opts;
1391 sp->timeout = st->timeout;
1392
1241 sp->sync_flags = st->sync_flags & PFSTATE_NOSYNC;
1393 if (flags & PFSYNC_FLAG_STALE)
1394 sp->sync_flags |= PFSTATE_STALE;
1395 }
1396
1397 pf_state_peer_hton(&st->src, &sp->src);
1398 pf_state_peer_hton(&st->dst, &sp->dst);
1399
1400 if (st->expire <= secs)
1401 sp->expire = htonl(0);
1402 else
1403 sp->expire = htonl(st->expire - secs);
1404
1405 /* do we need to build "compressed" actions for network transfer? */
1253 if (sc->sc_sync_ifp && compress) {
1406 if (sc->sc_sync_ifp && flags & PFSYNC_FLAG_COMPRESS) {
1407 switch (action) {
1408 case PFSYNC_ACT_UPD:
1409 newaction = PFSYNC_ACT_UPD_C;
1410 break;
1411 case PFSYNC_ACT_DEL:
1412 newaction = PFSYNC_ACT_DEL_C;
1413 break;
1414 default:

--- 61 unchanged lines hidden (view full) ---

1476#ifdef __FreeBSD__
1477 struct ifnet *ifp = SCP2IFP(LIST_FIRST(&pfsync_list));
1478#else
1479 struct ifnet *ifp = &pfsyncif.sc_if;
1480#endif
1481 struct pfsync_header *h;
1482 struct pfsync_softc *sc = ifp->if_softc;
1483 struct pfsync_state_upd_req *rup;
1331 int s = 0, ret = 0; /* make the compiler happy */
1484 int ret = 0;
1485
1486#ifdef __FreeBSD__
1487 PF_ASSERT(MA_OWNED);
1488#endif
1489 if (sc->sc_mbuf == NULL) {
1490 if ((sc->sc_mbuf = pfsync_get_mbuf(sc, PFSYNC_ACT_UREQ,
1338 (void *)&sc->sc_statep.s)) == NULL) {
1339 splx(s);
1491 (void *)&sc->sc_statep.s)) == NULL)
1492 return (ENOMEM);
1341 }
1493 h = mtod(sc->sc_mbuf, struct pfsync_header *);
1494 } else {
1495 h = mtod(sc->sc_mbuf, struct pfsync_header *);
1496 if (h->action != PFSYNC_ACT_UREQ) {
1497 pfsync_sendout(sc);
1498 if ((sc->sc_mbuf = pfsync_get_mbuf(sc, PFSYNC_ACT_UREQ,
1348 (void *)&sc->sc_statep.s)) == NULL) {
1349 splx(s);
1499 (void *)&sc->sc_statep.s)) == NULL)
1500 return (ENOMEM);
1351 }
1501 h = mtod(sc->sc_mbuf, struct pfsync_header *);
1502 }
1503 }
1504
1505 if (src != NULL)
1506 sc->sc_sendaddr = *src;
1507 sc->sc_mbuf->m_pkthdr.len = sc->sc_mbuf->m_len += sizeof(*rup);
1508 h->count++;

--- 56 unchanged lines hidden (view full) ---

1565#endif
1566 pfsync_sendout(sc);
1567#ifdef __FreeBSD__
1568 PF_UNLOCK();
1569#endif
1570 splx(s);
1571}
1572
1573/* This must be called in splnet() */
1574void
1575pfsync_send_bus(struct pfsync_softc *sc, u_int8_t status)
1576{
1577 struct pfsync_state_bus *bus;
1578
1579#ifdef __FreeBSD__
1580 PF_ASSERT(MA_OWNED);
1581#endif
1582 if (sc->sc_mbuf != NULL)
1583 pfsync_sendout(sc);
1584
1585 if (pfsync_sync_ok &&
1586 (sc->sc_mbuf = pfsync_get_mbuf(sc, PFSYNC_ACT_BUS,
1587 (void *)&sc->sc_statep.b)) != NULL) {
1588 sc->sc_mbuf->m_pkthdr.len = sc->sc_mbuf->m_len += sizeof(*bus);
1589 bus = sc->sc_statep.b;
1590 bus->creatorid = pf_status.hostid;
1591 bus->status = status;
1442#ifdef __FreeBSD__
1592 bus->endtime = htonl(time_uptime - sc->sc_ureq_received);
1444#else
1445 bus->endtime = htonl(mono_time.tv_sec - sc->sc_ureq_received);
1446#endif
1593 pfsync_sendout(sc);
1594 }
1595}
1596
1597void
1598pfsync_bulk_update(void *v)
1599{
1600 struct pfsync_softc *sc = v;

--- 24 unchanged lines hidden (view full) ---

1625#endif
1626 if (pf_status.debug >= PF_DEBUG_MISC)
1627 printf("pfsync: bulk update complete\n");
1628 break;
1629 } else {
1630 /* send an update and move to end of list */
1631 if (!state->sync_flags)
1632 pfsync_pack_state(PFSYNC_ACT_UPD, state, 0);
1487#ifdef __FreeBSD__
1633 state->pfsync_time = time_uptime;
1489#else
1490 state->pfsync_time = mono_time.tv_sec;
1491#endif
1634 TAILQ_REMOVE(&state_updates, state, u.s.entry_updates);
1635 TAILQ_INSERT_TAIL(&state_updates, state,
1636 u.s.entry_updates);
1637
1638 /* look again for more in a bit */
1639#ifdef __FreeBSD__
1640 callout_reset(&sc->sc_bulk_tmo, 1, pfsync_timeout,
1641 LIST_FIRST(&pfsync_list));

--- 9 unchanged lines hidden (view full) ---

1651 PF_UNLOCK();
1652#endif
1653}
1654
1655void
1656pfsync_bulkfail(void *v)
1657{
1658 struct pfsync_softc *sc = v;
1659 int s, error;
1660
1661#ifdef __FreeBSD__
1662 PF_LOCK();
1663#endif
1664 if (sc->sc_bulk_tries++ < PFSYNC_MAX_BULKTRIES) {
1665 /* Try again in a bit */
1666#ifdef __FreeBSD__
1667 callout_reset(&sc->sc_bulkfail_tmo, 5 * hz, pfsync_bulkfail,
1668 LIST_FIRST(&pfsync_list));
1669#else
1670 timeout_add(&sc->sc_bulkfail_tmo, 5 * hz);
1671#endif
1529 pfsync_request_update(NULL, NULL);
1530 pfsync_sendout(sc);
1672 s = splnet();
1673 error = pfsync_request_update(NULL, NULL);
1674 if (error == ENOMEM) {
1675 if (pf_status.debug >= PF_DEBUG_MISC)
1676 printf("pfsync: cannot allocate mbufs for "
1677 "bulk update\n");
1678 } else
1679 pfsync_sendout(sc);
1680 splx(s);
1681 } else {
1682 /* Pretend like the transfer was ok */
1683 sc->sc_ureq_sent = 0;
1684 sc->sc_bulk_tries = 0;
1685#if NCARP > 0
1686 if (!pfsync_sync_ok)
1687 carp_suppress_preempt--;
1688#endif
1689 pfsync_sync_ok = 1;
1690 if (pf_status.debug >= PF_DEBUG_MISC)
1691 printf("pfsync: failed to receive "
1692 "bulk update status\n");
1693#ifdef __FreeBSD__
1694 callout_stop(&sc->sc_bulkfail_tmo);
1695#else
1696 timeout_del(&sc->sc_bulkfail_tmo);
1697#endif
1698 }
1699#ifdef __FreeBSD__
1700 PF_UNLOCK();
1701#endif
1702}
1703
1704/* This must be called in splnet() */
1705int
1706pfsync_sendout(sc)
1707 struct pfsync_softc *sc;
1708{
1709#if NBPFILTER > 0
1710# ifdef __FreeBSD__
1711 struct ifnet *ifp = SCP2IFP(sc);
1712# else

--- 25 unchanged lines hidden (view full) ---

1738
1739 if (sc->sc_mbuf_net) {
1740 m_freem(m);
1741 m = sc->sc_mbuf_net;
1742 sc->sc_mbuf_net = NULL;
1743 sc->sc_statep_net.s = NULL;
1744 }
1745
1591 if (sc->sc_sync_ifp) {
1746 if (sc->sc_sync_ifp || sc->sc_sync_peer.s_addr != INADDR_PFSYNC_GROUP) {
1747 struct ip *ip;
1593 struct ifaddr *ifa;
1748 struct sockaddr sa;
1749
1750 M_PREPEND(m, sizeof(struct ip), M_DONTWAIT);
1751 if (m == NULL) {
1752 pfsyncstats.pfsyncs_onomem++;
1753 return (0);
1754 }
1755 ip = mtod(m, struct ip *);

--- 11 unchanged lines hidden (view full) ---

1767#else
1768 ip->ip_off = htons(IP_DF);
1769#endif
1770 ip->ip_ttl = PFSYNC_DFLTTL;
1771 ip->ip_p = IPPROTO_PFSYNC;
1772 ip->ip_sum = 0;
1773
1774 bzero(&sa, sizeof(sa));
1621 sa.sa_family = AF_INET;
1622 ifa = ifaof_ifpforaddr(&sa, sc->sc_sync_ifp);
1623 if (ifa == NULL)
1624 return (0);
1625 ip->ip_src.s_addr = ifatoia(ifa)->ia_addr.sin_addr.s_addr;
1775 ip->ip_src.s_addr = INADDR_ANY;
1776
1777#ifdef __FreeBSD__
1778 if (sc->sc_sendaddr.s_addr == htonl(INADDR_PFSYNC_GROUP))
1779#else
1780 if (sc->sc_sendaddr.s_addr == INADDR_PFSYNC_GROUP)
1781#endif
1782 m->m_flags |= M_MCAST;
1783 ip->ip_dst = sc->sc_sendaddr;
1784#ifdef __FreeBSD__
1635 sc->sc_sendaddr.s_addr = htonl(INADDR_PFSYNC_GROUP);
1785 /* XXX_IMPORT */
1786 sc->sc_sendaddr.s_addr = htonl(sc->sc_sync_peer.s_addr);
1787#else
1637 sc->sc_sendaddr.s_addr = INADDR_PFSYNC_GROUP;
1788 sc->sc_sendaddr.s_addr = sc->sc_sync_peer.s_addr;
1789#endif
1790
1791 pfsyncstats.pfsyncs_opackets++;
1792
1793#ifdef __FreeBSD__
1794 PF_UNLOCK();
1795#endif
1796 if (ip_output(m, NULL, NULL, IP_RAWOUTPUT, &sc->sc_imo, NULL))

--- 50 unchanged lines hidden ---