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#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 |
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)); |
354 st->creation = time_second - ntohl(sp->creation); |
355 st->expire = ntohl(sp->expire) + time_second; |
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; |
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; |
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') { |
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 } |
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 } |
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 } |
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__ |
636 (unsigned long long)be64toh(st->id), |
637#else |
638 betoh64(st->id), |
639#endif |
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 } |
691 st->timeout = PFTM_PURGE; 692 st->sync_flags |= PFSTATE_FROMSYNC; |
693 pf_purge_expired_state(st); |
694 } |
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. */ |
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 } |
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__ |
777 (unsigned long long)be64toh(st->id), |
778#else |
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 } |
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 } |
830 st->timeout = PFTM_PURGE; 831 st->sync_flags |= PFSTATE_FROMSYNC; |
832 pf_purge_expired_state(st); |
833 } |
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(); |
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) { |
863 sc->sc_ureq_received = time_uptime; |
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 } |
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: |
921 if (time_uptime - ntohl(bus->endtime) >= |
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) |
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 |
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 } |
1059 1060 if ((sifp = ifunit(pfsyncr.pfsyncr_syncdev)) == NULL) { |
1061#ifdef __FreeBSD__ 1062 PF_UNLOCK(); 1063#endif 1064 return (EINVAL); 1065 } |
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 |
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; |
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 |
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 |
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 */ |
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 |
1348 secs = time_second; 1349 1350 st->pfsync_time = time_uptime; |
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 |
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? */ |
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; |
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, |
1491 (void *)&sc->sc_statep.s)) == NULL) |
1492 return (ENOMEM); |
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, |
1499 (void *)&sc->sc_statep.s)) == NULL) |
1500 return (ENOMEM); |
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; |
1592 bus->endtime = htonl(time_uptime - sc->sc_ureq_received); |
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); |
1633 state->pfsync_time = time_uptime; |
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 |
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 |
1746 if (sc->sc_sync_ifp || sc->sc_sync_peer.s_addr != INADDR_PFSYNC_GROUP) { |
1747 struct ip *ip; |
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)); |
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__ |
1785 /* XXX_IMPORT */ 1786 sc->sc_sendaddr.s_addr = htonl(sc->sc_sync_peer.s_addr); |
1787#else |
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 --- |