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 $ */
6 * Copyright (c) 2004 The DragonFly Project. All rights reserved.
8 * Copyright (c) 2002 Michael Shalayeff
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
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.
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.
34 #include "opt_inet6.h"
36 #include <sys/param.h>
39 #include <sys/systm.h>
42 #include <sys/socket.h>
43 #include <sys/kernel.h>
44 #include <sys/malloc.h>
45 #include <sys/module.h>
46 #include <sys/sockio.h>
47 #include <sys/thread2.h>
48 #include <vm/vm_zone.h>
50 #include <machine/inttypes.h>
53 #include <net/if_types.h>
54 #include <net/route.h>
58 #include <netinet/in.h>
59 #include <netinet/in_systm.h>
60 #include <netinet/in_var.h>
61 #include <netinet/ip.h>
62 #include <netinet/ip_var.h>
67 #include <netinet/in.h>
69 #include <netinet6/nd6.h>
72 #include <net/pf/pfvar.h>
73 #include <net/pf/if_pfsync.h>
75 #define PFSYNCNAME "pfsync"
77 #define PFSYNC_MINMTU \
78 (sizeof(struct pfsync_header) + sizeof(struct pf_state))
81 #define DPRINTF(x) do { if (pfsyncdebug) kprintf x ; } while (0)
88 struct pfsyncstats pfsyncstats
;
90 static void pfsync_clone_destroy(struct ifnet
*);
91 static int pfsync_clone_create(struct if_clone
*, int);
92 void pfsync_setmtu(struct pfsync_softc
*, int);
93 int pfsync_insert_net_state(struct pfsync_state
*);
94 int pfsyncoutput(struct ifnet
*, struct mbuf
*, struct sockaddr
*,
96 int pfsyncioctl(struct ifnet
*, u_long
, caddr_t
, struct ucred
*);
97 void pfsyncstart(struct ifnet
*);
99 struct mbuf
*pfsync_get_mbuf(struct pfsync_softc
*, u_int8_t
, void **);
100 int pfsync_request_update(struct pfsync_state_upd
*, struct in_addr
*);
101 int pfsync_sendout(struct pfsync_softc
*);
102 void pfsync_timeout(void *);
103 void pfsync_send_bus(struct pfsync_softc
*, u_int8_t
);
104 void pfsync_bulk_update(void *);
105 void pfsync_bulkfail(void *);
107 static MALLOC_DEFINE(M_PFSYNC
, PFSYNCNAME
, "Packet Filter State Sync. Interface");
108 static LIST_HEAD(pfsync_list
, pfsync_softc
) pfsync_list
;
109 struct if_clone pfsync_cloner
= IF_CLONE_INITIALIZER("pfsync", pfsync_clone_create
,
110 pfsync_clone_destroy
, 1, 1);
113 pfsync_clone_destroy(struct ifnet
*ifp
)
115 struct pfsync_softc
*sc
;
118 callout_stop(&sc
->sc_tmo
);
119 callout_stop(&sc
->sc_bulk_tmo
);
120 callout_stop(&sc
->sc_bulkfail_tmo
);
124 LIST_REMOVE(sc
, sc_next
);
129 pfsync_clone_create(struct if_clone
*ifc
, int unit
)
131 struct pfsync_softc
*sc
;
134 MALLOC(sc
, struct pfsync_softc
*, sizeof(*sc
), M_PFSYNC
,
139 sc
->sc_mbuf_net
= NULL
;
140 sc
->sc_statep
.s
= NULL
;
141 sc
->sc_statep_net
.s
= NULL
;
142 sc
->sc_maxupdates
= 128;
143 sc
->sc_sendaddr
.s_addr
= htonl(INADDR_PFSYNC_GROUP
);
144 sc
->sc_ureq_received
= 0;
145 sc
->sc_ureq_sent
= 0;
148 if_initname(ifp
, ifc
->ifc_name
, unit
);
149 ifp
->if_ioctl
= pfsyncioctl
;
150 ifp
->if_output
= pfsyncoutput
;
151 ifp
->if_start
= pfsyncstart
;
152 ifp
->if_type
= IFT_PFSYNC
;
153 ifp
->if_snd
.ifq_maxlen
= ifqmaxlen
;
154 ifp
->if_hdrlen
= PFSYNC_HDRLEN
;
155 ifp
->if_baudrate
= IF_Mbps(100);
157 pfsync_setmtu(sc
, MCLBYTES
);
158 callout_init(&sc
->sc_tmo
);
159 callout_init(&sc
->sc_bulk_tmo
);
160 callout_init(&sc
->sc_bulkfail_tmo
);
161 if_attach(&sc
->sc_if
, NULL
);
163 LIST_INSERT_HEAD(&pfsync_list
, sc
, sc_next
);
164 bpfattach(&sc
->sc_if
, DLT_PFSYNC
, PFSYNC_HDRLEN
);
170 * Start output on the pfsync interface.
173 pfsyncstart(struct ifnet
*ifp
)
176 IF_DROP(&ifp
->if_snd
);
177 IF_DRAIN(&ifp
->if_snd
);
182 pfsync_insert_net_state(struct pfsync_state
*sp
)
184 struct pf_state
*st
= NULL
;
185 struct pf_rule
*r
= NULL
;
188 if (sp
->creatorid
== 0 && pf_status
.debug
>= PF_DEBUG_MISC
) {
189 kprintf("pfsync_insert_net_state: invalid creator id:"
190 " %08" PRIx32
"\n", ntohl(sp
->creatorid
));
194 kif
= pfi_lookup_create(sp
->ifname
);
196 if (pf_status
.debug
>= PF_DEBUG_MISC
)
197 kprintf("pfsync_insert_net_state: "
198 "unknown interface: %s\n", sp
->ifname
);
199 /* skip this state */
204 * Just use the default rule until we have infrastructure to find the
205 * best matching rule.
207 r
= &pf_default_rule
;
209 if (!r
->max_states
|| r
->states
< r
->max_states
)
210 st
= pool_get(&pf_state_pl
, PR_NOWAIT
);
212 pfi_maybe_destroy(kif
);
215 bzero(st
, sizeof(*st
));
218 /* XXX get pointers to nat_rule and anchor */
220 /* fill in the rest of the state entry */
221 pf_state_host_ntoh(&sp
->lan
, &st
->lan
);
222 pf_state_host_ntoh(&sp
->gwy
, &st
->gwy
);
223 pf_state_host_ntoh(&sp
->ext
, &st
->ext
);
225 pf_state_peer_ntoh(&sp
->src
, &st
->src
);
226 pf_state_peer_ntoh(&sp
->dst
, &st
->dst
);
228 bcopy(&sp
->rt_addr
, &st
->rt_addr
, sizeof(st
->rt_addr
));
229 st
->hash
= pf_state_hash(st
);
230 st
->creation
= ntohl(sp
->creation
) + time_second
;
231 st
->expire
= ntohl(sp
->expire
) + time_second
;
234 st
->proto
= sp
->proto
;
235 st
->direction
= sp
->direction
;
237 st
->timeout
= sp
->timeout
;
238 st
->allow_opts
= sp
->allow_opts
;
240 bcopy(sp
->id
, &st
->id
, sizeof(st
->id
));
241 st
->creatorid
= sp
->creatorid
;
242 st
->sync_flags
= sp
->sync_flags
| PFSTATE_FROMSYNC
;
245 if (pf_insert_state(kif
, st
)) {
246 pfi_maybe_destroy(kif
);
247 pool_put(&pf_state_pl
, st
);
255 pfsync_input(struct mbuf
*m
, ...)
257 struct ip
*ip
= mtod(m
, struct ip
*);
258 struct pfsync_header
*ph
;
259 struct pfsync_softc
*sc
= LIST_FIRST(&pfsync_list
);
260 struct pf_state
*st
, key
;
261 struct pfsync_state
*sp
;
262 struct pfsync_state_upd
*up
;
263 struct pfsync_state_del
*dp
;
264 struct pfsync_state_clr
*cp
;
265 struct pfsync_state_upd_req
*rup
;
266 struct pfsync_state_bus
*bus
;
269 int iplen
, action
, error
, i
, count
, offp
;
271 pfsyncstats
.pfsyncs_ipackets
++;
273 /* verify that we have a sync interface configured */
274 if (!sc
->sc_sync_ifp
|| !pf_status
.running
)
277 /* verify that the packet came in on the right interface */
278 if (sc
->sc_sync_ifp
!= m
->m_pkthdr
.rcvif
) {
279 pfsyncstats
.pfsyncs_badif
++;
283 /* verify that the IP TTL is 255. */
284 if (ip
->ip_ttl
!= PFSYNC_DFLTTL
) {
285 pfsyncstats
.pfsyncs_badttl
++;
289 iplen
= ip
->ip_hl
<< 2;
291 if (m
->m_pkthdr
.len
< iplen
+ sizeof(*ph
)) {
292 pfsyncstats
.pfsyncs_hdrops
++;
296 if (iplen
+ sizeof(*ph
) > m
->m_len
) {
297 if ((m
= m_pullup(m
, iplen
+ sizeof(*ph
))) == NULL
) {
298 pfsyncstats
.pfsyncs_hdrops
++;
301 ip
= mtod(m
, struct ip
*);
303 ph
= (struct pfsync_header
*)((char *)ip
+ iplen
);
305 /* verify the version */
306 if (ph
->version
!= PFSYNC_VERSION
) {
307 pfsyncstats
.pfsyncs_badver
++;
314 /* make sure it's a valid action code */
315 if (action
>= PFSYNC_ACT_MAX
) {
316 pfsyncstats
.pfsyncs_badact
++;
320 /* Cheaper to grab this now than having to mess with mbufs later */
324 case PFSYNC_ACT_CLR
: {
327 if ((mp
= m_pulldown(m
, iplen
+ sizeof(*ph
),
328 sizeof(*cp
), &offp
)) == NULL
) {
329 pfsyncstats
.pfsyncs_badlen
++;
332 cp
= (struct pfsync_state_clr
*)(mp
->m_data
+ offp
);
333 creatorid
= cp
->creatorid
;
336 if (cp
->ifname
[0] == '\0') {
337 RB_FOREACH(st
, pf_state_tree_id
, &tree_id
) {
338 if (st
->creatorid
== creatorid
)
339 st
->timeout
= PFTM_PURGE
;
342 kif
= pfi_lookup_if(cp
->ifname
);
344 if (pf_status
.debug
>= PF_DEBUG_MISC
)
345 kprintf("pfsync_input: PFSYNC_ACT_CLR "
346 "bad interface: %s\n", cp
->ifname
);
350 RB_FOREACH(st
, pf_state_tree_lan_ext
,
351 &kif
->pfik_lan_ext
) {
352 if (st
->creatorid
== creatorid
)
353 st
->timeout
= PFTM_PURGE
;
356 pf_purge_expired_states();
362 if ((mp
= m_pulldown(m
, iplen
+ sizeof(*ph
),
363 count
* sizeof(*sp
), &offp
)) == NULL
) {
364 pfsyncstats
.pfsyncs_badlen
++;
369 for (i
= 0, sp
= (struct pfsync_state
*)(mp
->m_data
+ offp
);
370 i
< count
; i
++, sp
++) {
371 /* check for invalid values */
372 if (sp
->timeout
>= PFTM_MAX
||
373 sp
->src
.state
> PF_TCPS_PROXY_DST
||
374 sp
->dst
.state
> PF_TCPS_PROXY_DST
||
375 sp
->direction
> PF_OUT
||
376 (sp
->af
!= AF_INET
&& sp
->af
!= AF_INET6
)) {
377 if (pf_status
.debug
>= PF_DEBUG_MISC
)
378 kprintf("pfsync_insert: PFSYNC_ACT_INS: "
380 pfsyncstats
.pfsyncs_badstate
++;
384 if ((error
= pfsync_insert_net_state(sp
))) {
385 if (error
== ENOMEM
) {
395 if ((mp
= m_pulldown(m
, iplen
+ sizeof(*ph
),
396 count
* sizeof(*sp
), &offp
)) == NULL
) {
397 pfsyncstats
.pfsyncs_badlen
++;
402 for (i
= 0, sp
= (struct pfsync_state
*)(mp
->m_data
+ offp
);
403 i
< count
; i
++, sp
++) {
404 /* check for invalid values */
405 if (sp
->timeout
>= PFTM_MAX
||
406 sp
->src
.state
> PF_TCPS_PROXY_DST
||
407 sp
->dst
.state
> PF_TCPS_PROXY_DST
) {
408 if (pf_status
.debug
>= PF_DEBUG_MISC
)
409 kprintf("pfsync_insert: PFSYNC_ACT_UPD: "
411 pfsyncstats
.pfsyncs_badstate
++;
415 bcopy(sp
->id
, &key
.id
, sizeof(key
.id
));
416 key
.creatorid
= sp
->creatorid
;
418 st
= pf_find_state_byid(&key
);
420 /* insert the update */
421 if (pfsync_insert_net_state(sp
))
422 pfsyncstats
.pfsyncs_badstate
++;
425 pf_state_peer_ntoh(&sp
->src
, &st
->src
);
426 pf_state_peer_ntoh(&sp
->dst
, &st
->dst
);
427 st
->expire
= ntohl(sp
->expire
) + time_second
;
428 st
->timeout
= sp
->timeout
;
434 * It's not strictly necessary for us to support the "uncompressed"
435 * delete action, but it's relatively simple and maintains consistency.
438 if ((mp
= m_pulldown(m
, iplen
+ sizeof(*ph
),
439 count
* sizeof(*sp
), &offp
)) == NULL
) {
440 pfsyncstats
.pfsyncs_badlen
++;
445 for (i
= 0, sp
= (struct pfsync_state
*)(mp
->m_data
+ offp
);
446 i
< count
; i
++, sp
++) {
447 bcopy(sp
->id
, &key
.id
, sizeof(key
.id
));
448 key
.creatorid
= sp
->creatorid
;
450 st
= pf_find_state_byid(&key
);
452 pfsyncstats
.pfsyncs_badstate
++;
457 * pf_purge_expired_states() is expensive,
458 * we really want to purge the state directly.
460 st
->timeout
= PFTM_PURGE
;
461 st
->sync_flags
|= PFSTATE_FROMSYNC
;
463 pf_purge_expired_states();
466 case PFSYNC_ACT_UPD_C
: {
467 int update_requested
= 0;
469 if ((mp
= m_pulldown(m
, iplen
+ sizeof(*ph
),
470 count
* sizeof(*up
), &offp
)) == NULL
) {
471 pfsyncstats
.pfsyncs_badlen
++;
476 for (i
= 0, up
= (struct pfsync_state_upd
*)(mp
->m_data
+ offp
);
477 i
< count
; i
++, up
++) {
478 /* check for invalid values */
479 if (up
->timeout
>= PFTM_MAX
||
480 up
->src
.state
> PF_TCPS_PROXY_DST
||
481 up
->dst
.state
> PF_TCPS_PROXY_DST
) {
482 if (pf_status
.debug
>= PF_DEBUG_MISC
)
483 kprintf("pfsync_insert: "
486 pfsyncstats
.pfsyncs_badstate
++;
490 bcopy(up
->id
, &key
.id
, sizeof(key
.id
));
491 key
.creatorid
= up
->creatorid
;
493 st
= pf_find_state_byid(&key
);
495 /* We don't have this state. Ask for it. */
496 pfsync_request_update(up
, &src
);
497 update_requested
= 1;
498 pfsyncstats
.pfsyncs_badstate
++;
501 pf_state_peer_ntoh(&up
->src
, &st
->src
);
502 pf_state_peer_ntoh(&up
->dst
, &st
->dst
);
503 st
->expire
= ntohl(up
->expire
) + time_second
;
504 st
->timeout
= up
->timeout
;
506 if (update_requested
)
511 case PFSYNC_ACT_DEL_C
:
512 if ((mp
= m_pulldown(m
, iplen
+ sizeof(*ph
),
513 count
* sizeof(*dp
), &offp
)) == NULL
) {
514 pfsyncstats
.pfsyncs_badlen
++;
519 for (i
= 0, dp
= (struct pfsync_state_del
*)(mp
->m_data
+ offp
);
520 i
< count
; i
++, dp
++) {
521 bcopy(dp
->id
, &key
.id
, sizeof(key
.id
));
522 key
.creatorid
= dp
->creatorid
;
524 st
= pf_find_state_byid(&key
);
526 pfsyncstats
.pfsyncs_badstate
++;
531 * pf_purge_expired_states() is expensive,
532 * we really want to purge the state directly.
534 st
->timeout
= PFTM_PURGE
;
535 st
->sync_flags
|= PFSTATE_FROMSYNC
;
537 pf_purge_expired_states();
540 case PFSYNC_ACT_INS_F
:
541 case PFSYNC_ACT_DEL_F
:
542 /* not implemented */
544 case PFSYNC_ACT_UREQ
:
545 if ((mp
= m_pulldown(m
, iplen
+ sizeof(*ph
),
546 count
* sizeof(*rup
), &offp
)) == NULL
) {
547 pfsyncstats
.pfsyncs_badlen
++;
552 /* XXX send existing. pfsync_pack_state should handle this. */
553 if (sc
->sc_mbuf
!= NULL
)
556 rup
= (struct pfsync_state_upd_req
*)(mp
->m_data
+ offp
);
557 i
< count
; i
++, rup
++) {
558 bcopy(rup
->id
, &key
.id
, sizeof(key
.id
));
559 key
.creatorid
= rup
->creatorid
;
561 if (key
.id
== 0 && key
.creatorid
== 0) {
562 sc
->sc_ureq_received
= mycpu
->gd_time_seconds
;
563 if (pf_status
.debug
>= PF_DEBUG_MISC
)
564 kprintf("pfsync: received "
565 "bulk update request\n");
566 pfsync_send_bus(sc
, PFSYNC_BUS_START
);
567 callout_reset(&sc
->sc_bulk_tmo
, 1 * hz
,
569 LIST_FIRST(&pfsync_list
));
571 st
= pf_find_state_byid(&key
);
573 pfsyncstats
.pfsyncs_badstate
++;
576 pfsync_pack_state(PFSYNC_ACT_UPD
, st
, 0);
579 if (sc
->sc_mbuf
!= NULL
)
584 /* If we're not waiting for a bulk update, who cares. */
585 if (sc
->sc_ureq_sent
== 0)
588 if ((mp
= m_pulldown(m
, iplen
+ sizeof(*ph
),
589 sizeof(*bus
), &offp
)) == NULL
) {
590 pfsyncstats
.pfsyncs_badlen
++;
593 bus
= (struct pfsync_state_bus
*)(mp
->m_data
+ offp
);
594 switch (bus
->status
) {
595 case PFSYNC_BUS_START
:
596 callout_reset(&sc
->sc_bulkfail_tmo
,
597 pf_pool_limits
[PF_LIMIT_STATES
].limit
/
598 (PFSYNC_BULKPACKETS
* sc
->sc_maxcount
),
599 pfsync_bulkfail
, LIST_FIRST(&pfsync_list
));
600 if (pf_status
.debug
>= PF_DEBUG_MISC
)
601 kprintf("pfsync: received bulk "
605 if (mycpu
->gd_time_seconds
- ntohl(bus
->endtime
) >=
607 /* that's it, we're happy */
608 sc
->sc_ureq_sent
= 0;
609 sc
->sc_bulk_tries
= 0;
610 callout_stop(&sc
->sc_bulkfail_tmo
);
612 if (pf_status
.debug
>= PF_DEBUG_MISC
)
613 kprintf("pfsync: received valid "
614 "bulk update end\n");
616 if (pf_status
.debug
>= PF_DEBUG_MISC
)
617 kprintf("pfsync: received invalid "
618 "bulk update end: bad timestamp\n");
631 pfsyncoutput(struct ifnet
*ifp
, struct mbuf
*m
, struct sockaddr
*dst
,
640 pfsyncioctl(struct ifnet
*ifp
, u_long cmd
, caddr_t data
, struct ucred
*cr
)
642 struct pfsync_softc
*sc
= ifp
->if_softc
;
643 struct ifreq
*ifr
= (struct ifreq
*)data
;
644 struct ip_moptions
*imo
= &sc
->sc_imo
;
645 struct pfsyncreq pfsyncr
;
654 if (ifp
->if_flags
& IFF_UP
)
655 ifp
->if_flags
|= IFF_RUNNING
;
657 ifp
->if_flags
&= ~IFF_RUNNING
;
660 if (ifr
->ifr_mtu
< PFSYNC_MINMTU
)
662 if (ifr
->ifr_mtu
> MCLBYTES
)
663 ifr
->ifr_mtu
= MCLBYTES
;
665 if (ifr
->ifr_mtu
< ifp
->if_mtu
)
667 pfsync_setmtu(sc
, ifr
->ifr_mtu
);
671 bzero(&pfsyncr
, sizeof(pfsyncr
));
673 strlcpy(pfsyncr
.pfsyncr_syncif
,
674 sc
->sc_sync_ifp
->if_xname
, IFNAMSIZ
);
675 pfsyncr
.pfsyncr_maxupdates
= sc
->sc_maxupdates
;
676 if ((error
= copyout(&pfsyncr
, ifr
->ifr_data
, sizeof(pfsyncr
))))
680 if ((error
= priv_check_cred(cr
, PRIV_ROOT
, NULL_CRED_OKAY
)) != 0)
682 if ((error
= copyin(ifr
->ifr_data
, &pfsyncr
, sizeof(pfsyncr
))))
685 if (pfsyncr
.pfsyncr_maxupdates
> 255)
687 sc
->sc_maxupdates
= pfsyncr
.pfsyncr_maxupdates
;
689 if (pfsyncr
.pfsyncr_syncif
[0] == 0) {
690 sc
->sc_sync_ifp
= NULL
;
691 if (sc
->sc_mbuf_net
!= NULL
) {
692 /* Don't keep stale pfsync packets around. */
694 m_freem(sc
->sc_mbuf_net
);
695 sc
->sc_mbuf_net
= NULL
;
696 sc
->sc_statep_net
.s
= NULL
;
701 if ((sifp
= ifunit(pfsyncr
.pfsyncr_syncif
)) == NULL
)
703 else if (sifp
== sc
->sc_sync_ifp
)
707 if (sifp
->if_mtu
< sc
->sc_if
.if_mtu
||
708 (sc
->sc_sync_ifp
!= NULL
&&
709 sifp
->if_mtu
< sc
->sc_sync_ifp
->if_mtu
) ||
710 sifp
->if_mtu
< MCLBYTES
- sizeof(struct ip
))
712 sc
->sc_sync_ifp
= sifp
;
714 pfsync_setmtu(sc
, sc
->sc_if
.if_mtu
);
716 if (imo
->imo_num_memberships
> 0) {
717 in_delmulti(imo
->imo_membership
[--imo
->imo_num_memberships
]);
718 imo
->imo_multicast_ifp
= NULL
;
721 if (sc
->sc_sync_ifp
) {
724 addr
.s_addr
= htonl(INADDR_PFSYNC_GROUP
);
725 /* XXX do we only use one group? Also see above */
726 if ((imo
->imo_membership
[0] =
727 in_addmulti(&addr
, sc
->sc_sync_ifp
)) == NULL
) {
731 imo
->imo_num_memberships
++;
732 imo
->imo_multicast_ifp
= sc
->sc_sync_ifp
;
733 imo
->imo_multicast_ttl
= PFSYNC_DFLTTL
;
734 imo
->imo_multicast_loop
= 0;
736 /* Request a full state table update. */
737 sc
->sc_ureq_sent
= mycpu
->gd_time_seconds
;
739 if (pf_status
.debug
>= PF_DEBUG_MISC
)
740 kprintf("pfsync: requesting bulk update\n");
741 callout_reset(&sc
->sc_bulkfail_tmo
, 5 * hz
,
742 pfsync_bulkfail
, LIST_FIRST(&pfsync_list
));
743 pfsync_request_update(NULL
, NULL
);
758 pfsync_setmtu(struct pfsync_softc
*sc
, int mtu_req
)
762 if (sc
->sc_sync_ifp
&& sc
->sc_sync_ifp
->if_mtu
< mtu_req
)
763 mtu
= sc
->sc_sync_ifp
->if_mtu
;
767 sc
->sc_maxcount
= (mtu
- sizeof(struct pfsync_header
)) /
768 sizeof(struct pfsync_state
);
769 if (sc
->sc_maxcount
> 254)
770 sc
->sc_maxcount
= 254;
771 sc
->sc_if
.if_mtu
= sizeof(struct pfsync_header
) +
772 sc
->sc_maxcount
* sizeof(struct pfsync_state
);
776 pfsync_get_mbuf(struct pfsync_softc
*sc
, u_int8_t action
, void **sp
)
778 struct pfsync_header
*h
;
782 MGETHDR(m
, MB_DONTWAIT
, MT_DATA
);
784 sc
->sc_if
.if_oerrors
++;
790 len
= sizeof(struct pfsync_header
) +
791 sizeof(struct pfsync_state_clr
);
793 case PFSYNC_ACT_UPD_C
:
794 len
= (sc
->sc_maxcount
* sizeof(struct pfsync_state_upd
)) +
795 sizeof(struct pfsync_header
);
797 case PFSYNC_ACT_DEL_C
:
798 len
= (sc
->sc_maxcount
* sizeof(struct pfsync_state_del
)) +
799 sizeof(struct pfsync_header
);
801 case PFSYNC_ACT_UREQ
:
802 len
= (sc
->sc_maxcount
* sizeof(struct pfsync_state_upd_req
)) +
803 sizeof(struct pfsync_header
);
806 len
= sizeof(struct pfsync_header
) +
807 sizeof(struct pfsync_state_bus
);
810 len
= (sc
->sc_maxcount
* sizeof(struct pfsync_state
)) +
811 sizeof(struct pfsync_header
);
816 MCLGET(m
, MB_DONTWAIT
);
817 if ((m
->m_flags
& M_EXT
) == 0) {
819 sc
->sc_if
.if_oerrors
++;
822 m
->m_data
+= (MCLBYTES
- len
) &~ (sizeof(long) - 1);
826 m
->m_pkthdr
.rcvif
= NULL
;
827 m
->m_pkthdr
.len
= m
->m_len
= sizeof(struct pfsync_header
);
828 h
= mtod(m
, struct pfsync_header
*);
829 h
->version
= PFSYNC_VERSION
;
834 *sp
= (void *)((char *)h
+ PFSYNC_HDRLEN
);
835 callout_reset(&sc
->sc_tmo
, hz
, pfsync_timeout
,
836 LIST_FIRST(&pfsync_list
));
841 pfsync_pack_state(u_int8_t action
, struct pf_state
*st
, int compress
)
843 struct ifnet
*ifp
= &(LIST_FIRST(&pfsync_list
))->sc_if
;
844 struct pfsync_softc
*sc
= ifp
->if_softc
;
845 struct pfsync_header
*h
, *h_net
;
846 struct pfsync_state
*sp
= NULL
;
847 struct pfsync_state_upd
*up
= NULL
;
848 struct pfsync_state_del
*dp
= NULL
;
852 u_int8_t i
= 255, newaction
= 0;
855 * If a packet falls in the forest and there's nobody around to
856 * hear, does it make a sound?
858 if (ifp
->if_bpf
== NULL
&& sc
->sc_sync_ifp
== NULL
) {
859 /* Don't leave any stale pfsync packets hanging around. */
860 if (sc
->sc_mbuf
!= NULL
) {
861 m_freem(sc
->sc_mbuf
);
863 sc
->sc_statep
.s
= NULL
;
868 if (action
>= PFSYNC_ACT_MAX
)
872 if (sc
->sc_mbuf
== NULL
) {
873 if ((sc
->sc_mbuf
= pfsync_get_mbuf(sc
, action
,
874 (void *)&sc
->sc_statep
.s
)) == NULL
) {
878 h
= mtod(sc
->sc_mbuf
, struct pfsync_header
*);
880 h
= mtod(sc
->sc_mbuf
, struct pfsync_header
*);
881 if (h
->action
!= action
) {
883 if ((sc
->sc_mbuf
= pfsync_get_mbuf(sc
, action
,
884 (void *)&sc
->sc_statep
.s
)) == NULL
) {
888 h
= mtod(sc
->sc_mbuf
, struct pfsync_header
*);
891 * If it's an update, look in the packet to see if
892 * we already have an update for the state.
894 if (action
== PFSYNC_ACT_UPD
&& sc
->sc_maxupdates
) {
895 struct pfsync_state
*usp
=
896 (void *)((char *)h
+ PFSYNC_HDRLEN
);
898 for (i
= 0; i
< h
->count
; i
++) {
899 if (!memcmp(usp
->id
, &st
->id
,
901 usp
->creatorid
== st
->creatorid
) {
914 st
->pfsync_time
= mycpu
->gd_time_seconds
;
915 TAILQ_REMOVE(&state_updates
, st
, u
.s
.entry_updates
);
916 TAILQ_INSERT_TAIL(&state_updates
, st
, u
.s
.entry_updates
);
919 /* not a "duplicate" update */
921 sp
= sc
->sc_statep
.s
++;
922 sc
->sc_mbuf
->m_pkthdr
.len
=
923 sc
->sc_mbuf
->m_len
+= sizeof(struct pfsync_state
);
925 bzero(sp
, sizeof(*sp
));
927 bcopy(&st
->id
, sp
->id
, sizeof(sp
->id
));
928 sp
->creatorid
= st
->creatorid
;
930 strlcpy(sp
->ifname
, st
->u
.s
.kif
->pfik_name
, sizeof(sp
->ifname
));
931 pf_state_host_hton(&st
->lan
, &sp
->lan
);
932 pf_state_host_hton(&st
->gwy
, &sp
->gwy
);
933 pf_state_host_hton(&st
->ext
, &sp
->ext
);
935 bcopy(&st
->rt_addr
, &sp
->rt_addr
, sizeof(sp
->rt_addr
));
937 sp
->creation
= htonl(secs
- st
->creation
);
938 sp
->packets
[0] = htonl(st
->packets
[0]);
939 sp
->packets
[1] = htonl(st
->packets
[1]);
940 sp
->bytes
[0] = htonl(st
->bytes
[0]);
941 sp
->bytes
[1] = htonl(st
->bytes
[1]);
942 if ((r
= st
->rule
.ptr
) == NULL
)
943 sp
->rule
= htonl(-1);
945 sp
->rule
= htonl(r
->nr
);
946 if ((r
= st
->anchor
.ptr
) == NULL
)
947 sp
->anchor
= htonl(-1);
949 sp
->anchor
= htonl(r
->nr
);
951 sp
->proto
= st
->proto
;
952 sp
->direction
= st
->direction
;
954 sp
->allow_opts
= st
->allow_opts
;
955 sp
->timeout
= st
->timeout
;
957 sp
->sync_flags
= st
->sync_flags
& PFSTATE_NOSYNC
;
960 pf_state_peer_hton(&st
->src
, &sp
->src
);
961 pf_state_peer_hton(&st
->dst
, &sp
->dst
);
963 if (st
->expire
<= secs
)
964 sp
->expire
= htonl(0);
966 sp
->expire
= htonl(st
->expire
- secs
);
968 /* do we need to build "compressed" actions for network transfer? */
969 if (sc
->sc_sync_ifp
&& compress
) {
972 newaction
= PFSYNC_ACT_UPD_C
;
975 newaction
= PFSYNC_ACT_DEL_C
;
978 /* by default we just send the uncompressed states */
984 if (sc
->sc_mbuf_net
== NULL
) {
985 if ((sc
->sc_mbuf_net
= pfsync_get_mbuf(sc
, newaction
,
986 (void *)&sc
->sc_statep_net
.s
)) == NULL
) {
991 h_net
= mtod(sc
->sc_mbuf_net
, struct pfsync_header
*);
994 case PFSYNC_ACT_UPD_C
:
996 up
= (void *)((char *)h_net
+
997 PFSYNC_HDRLEN
+ (i
* sizeof(*up
)));
1001 sc
->sc_mbuf_net
->m_pkthdr
.len
=
1002 sc
->sc_mbuf_net
->m_len
+= sizeof(*up
);
1003 up
= sc
->sc_statep_net
.u
++;
1005 bzero(up
, sizeof(*up
));
1006 bcopy(&st
->id
, up
->id
, sizeof(up
->id
));
1007 up
->creatorid
= st
->creatorid
;
1009 up
->timeout
= st
->timeout
;
1010 up
->expire
= sp
->expire
;
1014 case PFSYNC_ACT_DEL_C
:
1015 sc
->sc_mbuf_net
->m_pkthdr
.len
=
1016 sc
->sc_mbuf_net
->m_len
+= sizeof(*dp
);
1017 dp
= sc
->sc_statep_net
.d
++;
1020 bzero(dp
, sizeof(*dp
));
1021 bcopy(&st
->id
, dp
->id
, sizeof(dp
->id
));
1022 dp
->creatorid
= st
->creatorid
;
1027 if (h
->count
== sc
->sc_maxcount
||
1028 (sc
->sc_maxupdates
&& (sp
->updates
>= sc
->sc_maxupdates
)))
1029 ret
= pfsync_sendout(sc
);
1035 /* This must be called in splnet() */
1037 pfsync_request_update(struct pfsync_state_upd
*up
, struct in_addr
*src
)
1039 struct ifnet
*ifp
= &(LIST_FIRST(&pfsync_list
))->sc_if
;
1040 struct pfsync_header
*h
;
1041 struct pfsync_softc
*sc
= ifp
->if_softc
;
1042 struct pfsync_state_upd_req
*rup
;
1045 if (sc
->sc_mbuf
== NULL
) {
1046 if ((sc
->sc_mbuf
= pfsync_get_mbuf(sc
, PFSYNC_ACT_UREQ
,
1047 (void *)&sc
->sc_statep
.s
)) == NULL
) {
1050 h
= mtod(sc
->sc_mbuf
, struct pfsync_header
*);
1052 h
= mtod(sc
->sc_mbuf
, struct pfsync_header
*);
1053 if (h
->action
!= PFSYNC_ACT_UREQ
) {
1055 if ((sc
->sc_mbuf
= pfsync_get_mbuf(sc
, PFSYNC_ACT_UREQ
,
1056 (void *)&sc
->sc_statep
.s
)) == NULL
) {
1059 h
= mtod(sc
->sc_mbuf
, struct pfsync_header
*);
1064 sc
->sc_sendaddr
= *src
;
1065 sc
->sc_mbuf
->m_pkthdr
.len
= sc
->sc_mbuf
->m_len
+= sizeof(*rup
);
1067 rup
= sc
->sc_statep
.r
++;
1068 bzero(rup
, sizeof(*rup
));
1070 bcopy(up
->id
, rup
->id
, sizeof(rup
->id
));
1071 rup
->creatorid
= up
->creatorid
;
1074 if (h
->count
== sc
->sc_maxcount
)
1075 ret
= pfsync_sendout(sc
);
1081 pfsync_clear_states(u_int32_t creatorid
, char *ifname
)
1083 struct ifnet
*ifp
= &(LIST_FIRST(&pfsync_list
))->sc_if
;
1084 struct pfsync_softc
*sc
= ifp
->if_softc
;
1085 struct pfsync_state_clr
*cp
;
1089 if (sc
->sc_mbuf
!= NULL
)
1091 if ((sc
->sc_mbuf
= pfsync_get_mbuf(sc
, PFSYNC_ACT_CLR
,
1092 (void *)&sc
->sc_statep
.c
)) == NULL
) {
1096 sc
->sc_mbuf
->m_pkthdr
.len
= sc
->sc_mbuf
->m_len
+= sizeof(*cp
);
1097 cp
= sc
->sc_statep
.c
;
1098 cp
->creatorid
= creatorid
;
1100 strlcpy(cp
->ifname
, ifname
, IFNAMSIZ
);
1102 ret
= (pfsync_sendout(sc
));
1108 pfsync_timeout(void *v
)
1110 struct pfsync_softc
*sc
= v
;
1118 pfsync_send_bus(struct pfsync_softc
*sc
, u_int8_t status
)
1120 struct pfsync_state_bus
*bus
;
1122 if (sc
->sc_mbuf
!= NULL
)
1125 if (pfsync_sync_ok
&&
1126 (sc
->sc_mbuf
= pfsync_get_mbuf(sc
, PFSYNC_ACT_BUS
,
1127 (void *)&sc
->sc_statep
.b
)) != NULL
) {
1128 sc
->sc_mbuf
->m_pkthdr
.len
= sc
->sc_mbuf
->m_len
+= sizeof(*bus
);
1129 bus
= sc
->sc_statep
.b
;
1130 bus
->creatorid
= pf_status
.hostid
;
1131 bus
->status
= status
;
1132 bus
->endtime
= htonl(mycpu
->gd_time_seconds
- sc
->sc_ureq_received
);
1138 pfsync_bulk_update(void *v
)
1140 struct pfsync_softc
*sc
= v
;
1142 struct pf_state
*state
;
1145 if (sc
->sc_mbuf
!= NULL
)
1149 * Grab at most PFSYNC_BULKPACKETS worth of states which have not
1150 * been sent since the latest request was made.
1152 while ((state
= TAILQ_FIRST(&state_updates
)) != NULL
&&
1153 ++i
< (sc
->sc_maxcount
* PFSYNC_BULKPACKETS
)) {
1154 if (state
->pfsync_time
> sc
->sc_ureq_received
) {
1156 pfsync_send_bus(sc
, PFSYNC_BUS_END
);
1157 sc
->sc_ureq_received
= 0;
1158 callout_stop(&sc
->sc_bulk_tmo
);
1159 if (pf_status
.debug
>= PF_DEBUG_MISC
)
1160 kprintf("pfsync: bulk update complete\n");
1163 /* send an update and move to end of list */
1164 if (!state
->sync_flags
)
1165 pfsync_pack_state(PFSYNC_ACT_UPD
, state
, 0);
1166 state
->pfsync_time
= mycpu
->gd_time_seconds
;
1167 TAILQ_REMOVE(&state_updates
, state
, u
.s
.entry_updates
);
1168 TAILQ_INSERT_TAIL(&state_updates
, state
,
1171 /* look again for more in a bit */
1172 callout_reset(&sc
->sc_bulk_tmo
, 1, pfsync_timeout
,
1173 LIST_FIRST(&pfsync_list
));
1176 if (sc
->sc_mbuf
!= NULL
)
1182 pfsync_bulkfail(void *v
)
1184 struct pfsync_softc
*sc
= v
;
1186 if (sc
->sc_bulk_tries
++ < PFSYNC_MAX_BULKTRIES
) {
1187 /* Try again in a bit */
1188 callout_reset(&sc
->sc_bulkfail_tmo
, 5 * hz
, pfsync_bulkfail
,
1189 LIST_FIRST(&pfsync_list
));
1190 pfsync_request_update(NULL
, NULL
);
1193 /* Pretend like the transfer was ok */
1194 sc
->sc_ureq_sent
= 0;
1195 sc
->sc_bulk_tries
= 0;
1197 if (pf_status
.debug
>= PF_DEBUG_MISC
)
1198 kprintf("pfsync: failed to receive "
1199 "bulk update status\n");
1200 callout_stop(&sc
->sc_bulkfail_tmo
);
1205 pfsync_sendout(struct pfsync_softc
*sc
)
1207 struct ifnet
*ifp
= &sc
->sc_if
;
1210 callout_stop(&sc
->sc_tmo
);
1212 if (sc
->sc_mbuf
== NULL
)
1216 sc
->sc_statep
.s
= NULL
;
1218 KASSERT(m
!= NULL
, ("pfsync_sendout: null mbuf"));
1221 if (sc
->sc_mbuf_net
) {
1223 m
= sc
->sc_mbuf_net
;
1224 sc
->sc_mbuf_net
= NULL
;
1225 sc
->sc_statep_net
.s
= NULL
;
1228 if (sc
->sc_sync_ifp
) {
1233 M_PREPEND(m
, sizeof(struct ip
), MB_DONTWAIT
);
1235 pfsyncstats
.pfsyncs_onomem
++;
1238 ip
= mtod(m
, struct ip
*);
1239 ip
->ip_v
= IPVERSION
;
1240 ip
->ip_hl
= sizeof(*ip
) >> 2;
1241 ip
->ip_tos
= IPTOS_LOWDELAY
;
1242 ip
->ip_len
= m
->m_pkthdr
.len
;
1244 ip
->ip_id
= ip_randomid();
1246 ip
->ip_id
= ntohs(ip_id
++);
1249 ip
->ip_ttl
= PFSYNC_DFLTTL
;
1250 ip
->ip_p
= IPPROTO_PFSYNC
;
1253 bzero(&sa
, sizeof(sa
));
1254 sa
.sa_family
= AF_INET
;
1255 ifa
= ifaof_ifpforaddr(&sa
, sc
->sc_sync_ifp
);
1258 ip
->ip_src
.s_addr
= ifatoia(ifa
)->ia_addr
.sin_addr
.s_addr
;
1260 if (sc
->sc_sendaddr
.s_addr
== htonl(INADDR_PFSYNC_GROUP
))
1261 m
->m_flags
|= M_MCAST
;
1262 ip
->ip_dst
= sc
->sc_sendaddr
;
1263 sc
->sc_sendaddr
.s_addr
= htonl(INADDR_PFSYNC_GROUP
);
1265 pfsyncstats
.pfsyncs_opackets
++;
1267 if (ip_output(m
, NULL
, NULL
, IP_RAWOUTPUT
, &sc
->sc_imo
, NULL
))
1268 pfsyncstats
.pfsyncs_oerrors
++;
1276 pfsync_modevent(module_t mod
, int type
, void *data
)
1282 LIST_INIT(&pfsync_list
);
1283 if_clone_attach(&pfsync_cloner
);
1287 if_clone_detach(&pfsync_cloner
);
1288 while (!LIST_EMPTY(&pfsync_list
))
1289 pfsync_clone_destroy(
1290 &LIST_FIRST(&pfsync_list
)->sc_if
);
1301 static moduledata_t pfsync_mod
= {
1307 #define PFSYNC_MODVER 1
1309 DECLARE_MODULE(pfsync
, pfsync_mod
, SI_SUB_PSEUDO
, SI_ORDER_ANY
);
1310 MODULE_VERSION(pfsync
, PFSYNC_MODVER
);