Deleted Added
full compact
pf.c (126259) pf.c (126261)
1/* $FreeBSD: head/sys/contrib/pf/net/pf.c 126261 2004-02-26 02:34:12Z mlaier $ */
1/* $OpenBSD: pf.c,v 1.390 2003/09/24 17:18:03 mcbride Exp $ */
2
3/*
4 * Copyright (c) 2001 Daniel Hartmeier
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions

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

29 * POSSIBILITY OF SUCH DAMAGE.
30 *
31 * Effort sponsored in part by the Defense Advanced Research Projects
32 * Agency (DARPA) and Air Force Research Laboratory, Air Force
33 * Materiel Command, USAF, under agreement number F30602-01-2-0537.
34 *
35 */
36
2/* $OpenBSD: pf.c,v 1.390 2003/09/24 17:18:03 mcbride Exp $ */
3
4/*
5 * Copyright (c) 2001 Daniel Hartmeier
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

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

30 * POSSIBILITY OF SUCH DAMAGE.
31 *
32 * Effort sponsored in part by the Defense Advanced Research Projects
33 * Agency (DARPA) and Air Force Research Laboratory, Air Force
34 * Materiel Command, USAF, under agreement number F30602-01-2-0537.
35 *
36 */
37
38#if defined(__FreeBSD__)
39#include "opt_inet.h"
40#include "opt_inet6.h"
41#endif
42
43#if defined(__FreeBSD__) && __FreeBSD__ >= 5
44#include "opt_bpf.h"
45#define NBPFILTER DEV_BPF
46#include "opt_pf.h"
47#define NPFLOG DEV_PFLOG
48#define NPFSYNC DEV_PFSYNC
49#else
37#include "bpfilter.h"
38#include "pflog.h"
39#include "pfsync.h"
50#include "bpfilter.h"
51#include "pflog.h"
52#include "pfsync.h"
53#endif
40
41#include <sys/param.h>
42#include <sys/systm.h>
43#include <sys/mbuf.h>
44#include <sys/filio.h>
45#include <sys/socket.h>
46#include <sys/socketvar.h>
47#include <sys/kernel.h>
48#include <sys/time.h>
54
55#include <sys/param.h>
56#include <sys/systm.h>
57#include <sys/mbuf.h>
58#include <sys/filio.h>
59#include <sys/socket.h>
60#include <sys/socketvar.h>
61#include <sys/kernel.h>
62#include <sys/time.h>
63#if defined(__FreeBSD__)
64#include <sys/sysctl.h>
65#else
49#include <sys/pool.h>
66#include <sys/pool.h>
67#endif
50
51#include <net/if.h>
52#include <net/if_types.h>
53#include <net/bpf.h>
54#include <net/route.h>
55
56#include <netinet/in.h>
57#include <netinet/in_var.h>

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

63#include <netinet/udp.h>
64#include <netinet/ip_icmp.h>
65#include <netinet/in_pcb.h>
66#include <netinet/tcp_timer.h>
67#include <netinet/tcp_var.h>
68#include <netinet/udp_var.h>
69#include <netinet/icmp_var.h>
70
68
69#include <net/if.h>
70#include <net/if_types.h>
71#include <net/bpf.h>
72#include <net/route.h>
73
74#include <netinet/in.h>
75#include <netinet/in_var.h>

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

81#include <netinet/udp.h>
82#include <netinet/ip_icmp.h>
83#include <netinet/in_pcb.h>
84#include <netinet/tcp_timer.h>
85#include <netinet/tcp_var.h>
86#include <netinet/udp_var.h>
87#include <netinet/icmp_var.h>
88
89#if !defined(__FreeBSD__)
71#include <dev/rndvar.h>
90#include <dev/rndvar.h>
91#endif
72#include <net/pfvar.h>
73#include <net/if_pflog.h>
74#include <net/if_pfsync.h>
75
76#ifdef INET6
77#include <netinet/ip6.h>
78#include <netinet/in_pcb.h>
79#include <netinet/icmp6.h>
80#include <netinet6/nd6.h>
92#include <net/pfvar.h>
93#include <net/if_pflog.h>
94#include <net/if_pfsync.h>
95
96#ifdef INET6
97#include <netinet/ip6.h>
98#include <netinet/in_pcb.h>
99#include <netinet/icmp6.h>
100#include <netinet6/nd6.h>
101#if defined(__FreeBSD__)
102#include <netinet6/ip6_var.h>
103#include <netinet6/in6_pcb.h>
104#endif
81#endif /* INET6 */
82
83#ifdef ALTQ
84#include <altq/if_altq.h>
85#endif
86
105#endif /* INET6 */
106
107#ifdef ALTQ
108#include <altq/if_altq.h>
109#endif
110
111#if defined(__FreeBSD__)
112#include <machine/in_cksum.h>
113#if (__FreeBSD_version >= 500112)
114#include <sys/limits.h>
115#else
116#include <machine/limits.h>
117#endif
118#include <sys/ucred.h>
119#endif
87
120
121#if defined(__FreeBSD__)
122extern int ip_optcopy(struct ip *, struct ip *);
123#if (__FreeBSD_version < 501105)
124int ip_fragment(struct ip *ip, struct mbuf **m_frag, int mtu,
125 u_long if_hwassist_flags, int sw_csum);
126#endif
127#endif
128
88#define DPFPRINTF(n, x) if (pf_status.debug >= (n)) printf x
89struct pf_state_tree;
90
91/*
92 * Global variables
93 */
94
95struct pf_anchorqueue pf_anchors;

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

100struct pf_altqqueue *pf_altqs_inactive;
101struct pf_status pf_status;
102struct ifnet *status_ifp;
103
104u_int32_t ticket_altqs_active;
105u_int32_t ticket_altqs_inactive;
106u_int32_t ticket_pabuf;
107
129#define DPFPRINTF(n, x) if (pf_status.debug >= (n)) printf x
130struct pf_state_tree;
131
132/*
133 * Global variables
134 */
135
136struct pf_anchorqueue pf_anchors;

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

141struct pf_altqqueue *pf_altqs_inactive;
142struct pf_status pf_status;
143struct ifnet *status_ifp;
144
145u_int32_t ticket_altqs_active;
146u_int32_t ticket_altqs_inactive;
147u_int32_t ticket_pabuf;
148
149#if defined(__FreeBSD__)
150struct callout pf_expire_to; /* expire timeout */
151#else
108struct timeout pf_expire_to; /* expire timeout */
152struct timeout pf_expire_to; /* expire timeout */
153#endif
109
154
155
156#if defined(__FreeBSD__)
157uma_zone_t pf_tree_pl, pf_rule_pl, pf_addr_pl;
158uma_zone_t pf_state_pl, pf_altq_pl, pf_pooladdr_pl;
159#else
110struct pool pf_tree_pl, pf_rule_pl, pf_addr_pl;
111struct pool pf_state_pl, pf_altq_pl, pf_pooladdr_pl;
160struct pool pf_tree_pl, pf_rule_pl, pf_addr_pl;
161struct pool pf_state_pl, pf_altq_pl, pf_pooladdr_pl;
162#endif
112
113void pf_dynaddr_update(void *);
163
164void pf_dynaddr_update(void *);
165#if defined(__FreeBSD__) && defined(HOOK_HACK)
166void pf_dynaddr_update_event(void *arg, struct ifnet *ifp);
167#endif
114void pf_print_host(struct pf_addr *, u_int16_t, u_int8_t);
115void pf_print_state(struct pf_state *);
116void pf_print_flags(u_int8_t);
117
118u_int16_t pf_cksum_fixup(u_int16_t, u_int16_t, u_int16_t,
119 u_int8_t);
120void pf_change_ap(struct pf_addr *, u_int16_t *,
121 u_int16_t *, u_int16_t *, struct pf_addr *,

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

200 u_int16_t);
201void pf_set_rt_ifp(struct pf_state *,
202 struct pf_addr *);
203int pf_check_proto_cksum(struct mbuf *, int, int,
204 u_int8_t, sa_family_t);
205int pf_addr_wrap_neq(struct pf_addr_wrap *,
206 struct pf_addr_wrap *);
207
168void pf_print_host(struct pf_addr *, u_int16_t, u_int8_t);
169void pf_print_state(struct pf_state *);
170void pf_print_flags(u_int8_t);
171
172u_int16_t pf_cksum_fixup(u_int16_t, u_int16_t, u_int16_t,
173 u_int8_t);
174void pf_change_ap(struct pf_addr *, u_int16_t *,
175 u_int16_t *, u_int16_t *, struct pf_addr *,

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

254 u_int16_t);
255void pf_set_rt_ifp(struct pf_state *,
256 struct pf_addr *);
257int pf_check_proto_cksum(struct mbuf *, int, int,
258 u_int8_t, sa_family_t);
259int pf_addr_wrap_neq(struct pf_addr_wrap *,
260 struct pf_addr_wrap *);
261
262#if defined(__FreeBSD__)
263int in4_cksum(struct mbuf *m, u_int8_t nxt, int off, int len);
264#endif
208
265
266#if defined(__FreeBSD__)
267struct pf_pool_limit pf_pool_limits[PF_LIMIT_MAX];
268#else
209struct pf_pool_limit pf_pool_limits[PF_LIMIT_MAX] =
210 { { &pf_state_pl, PFSTATE_HIWAT }, { &pf_frent_pl, PFFRAG_FRENT_HIWAT } };
269struct pf_pool_limit pf_pool_limits[PF_LIMIT_MAX] =
270 { { &pf_state_pl, PFSTATE_HIWAT }, { &pf_frent_pl, PFFRAG_FRENT_HIWAT } };
271#endif
211
212#define STATE_LOOKUP() \
213 do { \
214 if (direction == PF_IN) \
215 *state = pf_find_state(&tree_ext_gwy, &key); \
216 else \
217 *state = pf_find_state(&tree_lan_ext, &key); \
218 if (*state == NULL) \

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

418 pfsync_insert_state(state);
419#endif
420 return (0);
421}
422
423void
424pf_purge_timeout(void *arg)
425{
272
273#define STATE_LOOKUP() \
274 do { \
275 if (direction == PF_IN) \
276 *state = pf_find_state(&tree_ext_gwy, &key); \
277 else \
278 *state = pf_find_state(&tree_lan_ext, &key); \
279 if (*state == NULL) \

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

479 pfsync_insert_state(state);
480#endif
481 return (0);
482}
483
484void
485pf_purge_timeout(void *arg)
486{
487#if defined(__FreeBSD__)
488 struct callout *to = arg;
489#else
426 struct timeout *to = arg;
490 struct timeout *to = arg;
491#endif
427 int s;
428
492 int s;
493
494#if defined(__FreeBSD__)
495 PF_LOCK();
496#endif
429 s = splsoftnet();
430 pf_purge_expired_states();
431 pf_purge_expired_fragments();
432 splx(s);
497 s = splsoftnet();
498 pf_purge_expired_states();
499 pf_purge_expired_fragments();
500 splx(s);
501#if defined(__FreeBSD__)
502 PF_UNLOCK();
503#endif
433
504
505#if defined(__FreeBSD__)
506 callout_reset(to, pf_default_rule.timeout[PFTM_INTERVAL] * hz,
507 pf_purge_timeout, to);
508#else
434 timeout_add(to, pf_default_rule.timeout[PFTM_INTERVAL] * hz);
509 timeout_add(to, pf_default_rule.timeout[PFTM_INTERVAL] * hz);
510#endif
435}
436
437u_int32_t
438pf_state_expires(const struct pf_state *state)
439{
440 u_int32_t timeout;
441 u_int32_t start;
442 u_int32_t end;
443 u_int32_t states;
444
445 /* handle all PFTM_* > PFTM_MAX here */
446 if (state->timeout == PFTM_PURGE)
511}
512
513u_int32_t
514pf_state_expires(const struct pf_state *state)
515{
516 u_int32_t timeout;
517 u_int32_t start;
518 u_int32_t end;
519 u_int32_t states;
520
521 /* handle all PFTM_* > PFTM_MAX here */
522 if (state->timeout == PFTM_PURGE)
523#if defined(__FreeBSD__)
524 return (time_second);
525#else
447 return (time.tv_sec);
526 return (time.tv_sec);
527#endif
448 if (state->timeout == PFTM_UNTIL_PACKET)
449 return (0);
528 if (state->timeout == PFTM_UNTIL_PACKET)
529 return (0);
530#if defined(__FreeBSD__)
531 KASSERT((state->timeout < PFTM_MAX),
532 ("pf_state_expires: timeout > PFTM_MAX"));
533#else
450 KASSERT(state->timeout < PFTM_MAX);
534 KASSERT(state->timeout < PFTM_MAX);
535#endif
451 timeout = state->rule.ptr->timeout[state->timeout];
452 if (!timeout)
453 timeout = pf_default_rule.timeout[state->timeout];
454 start = state->rule.ptr->timeout[PFTM_ADAPTIVE_START];
455 if (start) {
456 end = state->rule.ptr->timeout[PFTM_ADAPTIVE_END];
457 states = state->rule.ptr->states;
458 } else {
459 start = pf_default_rule.timeout[PFTM_ADAPTIVE_START];
460 end = pf_default_rule.timeout[PFTM_ADAPTIVE_END];
461 states = pf_status.states;
462 }
463 if (end && states > start && start < end) {
464 if (states < end)
465 return (state->expire + timeout * (end - states) /
466 (end - start));
467 else
536 timeout = state->rule.ptr->timeout[state->timeout];
537 if (!timeout)
538 timeout = pf_default_rule.timeout[state->timeout];
539 start = state->rule.ptr->timeout[PFTM_ADAPTIVE_START];
540 if (start) {
541 end = state->rule.ptr->timeout[PFTM_ADAPTIVE_END];
542 states = state->rule.ptr->states;
543 } else {
544 start = pf_default_rule.timeout[PFTM_ADAPTIVE_START];
545 end = pf_default_rule.timeout[PFTM_ADAPTIVE_END];
546 states = pf_status.states;
547 }
548 if (end && states > start && start < end) {
549 if (states < end)
550 return (state->expire + timeout * (end - states) /
551 (end - start));
552 else
553#if defined(__FreeBSD__)
554 return (time_second);
555#else
468 return (time.tv_sec);
556 return (time.tv_sec);
557#endif
469 }
470 return (state->expire + timeout);
471}
472
473void
474pf_purge_expired_states(void)
475{
476 struct pf_tree_node *cur, *peer, *next;
477 struct pf_tree_node key;
478
479 for (cur = RB_MIN(pf_state_tree, &tree_ext_gwy); cur; cur = next) {
480 next = RB_NEXT(pf_state_tree, &tree_ext_gwy, cur);
481
558 }
559 return (state->expire + timeout);
560}
561
562void
563pf_purge_expired_states(void)
564{
565 struct pf_tree_node *cur, *peer, *next;
566 struct pf_tree_node key;
567
568 for (cur = RB_MIN(pf_state_tree, &tree_ext_gwy); cur; cur = next) {
569 next = RB_NEXT(pf_state_tree, &tree_ext_gwy, cur);
570
571#if defined(__FreeBSD__)
572 if (pf_state_expires(cur->state) <= (u_int32_t)time_second) {
573#else
482 if (pf_state_expires(cur->state) <= time.tv_sec) {
574 if (pf_state_expires(cur->state) <= time.tv_sec) {
575#endif
483 if (cur->state->src.state == PF_TCPS_PROXY_DST)
484 pf_send_tcp(cur->state->rule.ptr,
485 cur->state->af,
486 &cur->state->ext.addr,
487 &cur->state->lan.addr,
488 cur->state->ext.port,
489 cur->state->lan.port,
490 cur->state->src.seqhi,

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

500 PF_ACPY(&key.addr[0], &cur->state->lan.addr,
501 cur->state->af);
502 key.port[0] = cur->state->lan.port;
503 PF_ACPY(&key.addr[1], &cur->state->ext.addr,
504 cur->state->af);
505 key.port[1] = cur->state->ext.port;
506
507 peer = RB_FIND(pf_state_tree, &tree_lan_ext, &key);
576 if (cur->state->src.state == PF_TCPS_PROXY_DST)
577 pf_send_tcp(cur->state->rule.ptr,
578 cur->state->af,
579 &cur->state->ext.addr,
580 &cur->state->lan.addr,
581 cur->state->ext.port,
582 cur->state->lan.port,
583 cur->state->src.seqhi,

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

593 PF_ACPY(&key.addr[0], &cur->state->lan.addr,
594 cur->state->af);
595 key.port[0] = cur->state->lan.port;
596 PF_ACPY(&key.addr[1], &cur->state->ext.addr,
597 cur->state->af);
598 key.port[1] = cur->state->ext.port;
599
600 peer = RB_FIND(pf_state_tree, &tree_lan_ext, &key);
601#if defined(__FreeBSD__)
602 KASSERT((peer), ("peer null :%s", __FUNCTION__));
603 KASSERT((peer->state == cur->state),
604 ("peer->state != cur->state: %s", __FUNCTION__));
605#else
508 KASSERT(peer);
509 KASSERT(peer->state == cur->state);
606 KASSERT(peer);
607 KASSERT(peer->state == cur->state);
608#endif
510 RB_REMOVE(pf_state_tree, &tree_lan_ext, peer);
511
512#if NPFSYNC
513 pfsync_delete_state(cur->state);
514#endif
515 if (--cur->state->rule.ptr->states <= 0)
516 pf_rm_rule(NULL, cur->state->rule.ptr);
517 if (cur->state->nat_rule.ptr != NULL)

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

578 if (aw->p.dyn->ifp == NULL) {
579 pool_put(&pf_addr_pl, aw->p.dyn);
580 aw->p.dyn = NULL;
581 return (1);
582 }
583 aw->p.dyn->addr = &aw->v.a.addr;
584 aw->p.dyn->af = af;
585 aw->p.dyn->undefined = 1;
609 RB_REMOVE(pf_state_tree, &tree_lan_ext, peer);
610
611#if NPFSYNC
612 pfsync_delete_state(cur->state);
613#endif
614 if (--cur->state->rule.ptr->states <= 0)
615 pf_rm_rule(NULL, cur->state->rule.ptr);
616 if (cur->state->nat_rule.ptr != NULL)

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

677 if (aw->p.dyn->ifp == NULL) {
678 pool_put(&pf_addr_pl, aw->p.dyn);
679 aw->p.dyn = NULL;
680 return (1);
681 }
682 aw->p.dyn->addr = &aw->v.a.addr;
683 aw->p.dyn->af = af;
684 aw->p.dyn->undefined = 1;
685#if !defined(__FreeBSD__)
586 aw->p.dyn->hook_cookie = hook_establish(
587 aw->p.dyn->ifp->if_addrhooks, 1,
588 pf_dynaddr_update, aw->p.dyn);
589 if (aw->p.dyn->hook_cookie == NULL) {
590 pool_put(&pf_addr_pl, aw->p.dyn);
591 aw->p.dyn = NULL;
592 return (1);
593 }
686 aw->p.dyn->hook_cookie = hook_establish(
687 aw->p.dyn->ifp->if_addrhooks, 1,
688 pf_dynaddr_update, aw->p.dyn);
689 if (aw->p.dyn->hook_cookie == NULL) {
690 pool_put(&pf_addr_pl, aw->p.dyn);
691 aw->p.dyn = NULL;
692 return (1);
693 }
694#elif defined(__FreeBSD__) && defined(HOOK_HACK)
695 PF_UNLOCK();
696 aw->p.dyn->hook_cookie = EVENTHANDLER_REGISTER(ifaddr_event,
697 pf_dynaddr_update_event, aw->p.dyn, EVENTHANDLER_PRI_ANY);
698 PF_LOCK();
699 if (aw->p.dyn->hook_cookie == NULL) {
700 pool_put(&pf_addr_pl, aw->p.dyn);
701 aw->p.dyn = NULL;
702 return (1);
703 }
704#else
705 /*
706 * XXX
707 * We have no hook_establish(9)/dohooks(9) kernel interfaces.
708 * This means that we do not aware of interface address changes(add,
709 * remove, etc). User should update pf rule manually after interface
710 * address changed. This may not be possible solution if you use xDSL.
711 * ipfw/ipfw2's approach with this situation(with me keyword) is not
712 * very efficient due to analyzing interface address during runtime.
713 * Another solution is to use a user-land daemon watching address
714 * changes with socket interface. Neither one is good.
715 * Supporting hook_establish(9) requries modification of in_control()
716 * located in netinet/in.c.
717 */
718#endif
594 pf_dynaddr_update(aw->p.dyn);
595 return (0);
596}
597
719 pf_dynaddr_update(aw->p.dyn);
720 return (0);
721}
722
723#if defined(__FreeBSD__) && defined(HOOK_HACK)
598void
724void
725pf_dynaddr_update_event(void *arg, struct ifnet *ifp)
726{
727 PF_LOCK();
728 pf_dynaddr_update(arg);
729 PF_UNLOCK();
730}
731#endif
732
733void
599pf_dynaddr_update(void *p)
600{
601 struct pf_addr_dyn *ad = (struct pf_addr_dyn *)p;
602 struct ifaddr *ia;
603 int s, changed = 0;
604
605 if (ad == NULL || ad->ifp == NULL)
606 panic("pf_dynaddr_update");

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

640 splx(s);
641}
642
643void
644pf_dynaddr_remove(struct pf_addr_wrap *aw)
645{
646 if (aw->type != PF_ADDR_DYNIFTL || aw->p.dyn == NULL)
647 return;
734pf_dynaddr_update(void *p)
735{
736 struct pf_addr_dyn *ad = (struct pf_addr_dyn *)p;
737 struct ifaddr *ia;
738 int s, changed = 0;
739
740 if (ad == NULL || ad->ifp == NULL)
741 panic("pf_dynaddr_update");

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

775 splx(s);
776}
777
778void
779pf_dynaddr_remove(struct pf_addr_wrap *aw)
780{
781 if (aw->type != PF_ADDR_DYNIFTL || aw->p.dyn == NULL)
782 return;
783#if !defined(__FreeBSD__)
648 hook_disestablish(aw->p.dyn->ifp->if_addrhooks,
649 aw->p.dyn->hook_cookie);
784 hook_disestablish(aw->p.dyn->ifp->if_addrhooks,
785 aw->p.dyn->hook_cookie);
786#elif defined(__FreeBSD__) && defined(HOOK_HACK)
787 PF_UNLOCK();
788 EVENTHANDLER_DEREGISTER(ifaddr_event, aw->p.dyn->hook_cookie);
789 PF_LOCK();
790#else
791 /*
792 * XXX
793 * We have no hook_establish(9)/dohooks(9) kernel interfaces.
794 * See comments above function, pf_dynaddr_setup().
795 */
796#endif
650 pool_put(&pf_addr_pl, aw->p.dyn);
651 aw->p.dyn = NULL;
652}
653
654void
655pf_dynaddr_copyout(struct pf_addr_wrap *aw)
656{
657 if (aw->type != PF_ADDR_DYNIFTL || aw->p.dyn == NULL)

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

1096 int len, tlen;
1097#ifdef INET
1098 struct ip *h;
1099#endif /* INET */
1100#ifdef INET6
1101 struct ip6_hdr *h6;
1102#endif /* INET6 */
1103 struct tcphdr *th;
797 pool_put(&pf_addr_pl, aw->p.dyn);
798 aw->p.dyn = NULL;
799}
800
801void
802pf_dynaddr_copyout(struct pf_addr_wrap *aw)
803{
804 if (aw->type != PF_ADDR_DYNIFTL || aw->p.dyn == NULL)

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

1243 int len, tlen;
1244#ifdef INET
1245 struct ip *h;
1246#endif /* INET */
1247#ifdef INET6
1248 struct ip6_hdr *h6;
1249#endif /* INET6 */
1250 struct tcphdr *th;
1251#if defined(__FreeBSD__)
1252 struct ip *ip;
1253#if (__FreeBSD_version < 501114)
1254 struct route ro;
1255#endif
1256#endif
1104 char *opt;
1105
1106 /* maximum segment size tcp option */
1107 tlen = sizeof(struct tcphdr);
1108 if (mss)
1109 tlen += 4;
1110
1111 switch (af) {

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

1201 case AF_INET:
1202 /* TCP checksum */
1203 th->th_sum = in_cksum(m, len);
1204
1205 /* Finish the IP header */
1206 h->ip_v = 4;
1207 h->ip_hl = sizeof(*h) >> 2;
1208 h->ip_tos = IPTOS_LOWDELAY;
1257 char *opt;
1258
1259 /* maximum segment size tcp option */
1260 tlen = sizeof(struct tcphdr);
1261 if (mss)
1262 tlen += 4;
1263
1264 switch (af) {

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

1354 case AF_INET:
1355 /* TCP checksum */
1356 th->th_sum = in_cksum(m, len);
1357
1358 /* Finish the IP header */
1359 h->ip_v = 4;
1360 h->ip_hl = sizeof(*h) >> 2;
1361 h->ip_tos = IPTOS_LOWDELAY;
1209 h->ip_len = htons(len);
1362#if defined(__FreeBSD__)
1363 h->ip_off = htons(path_mtu_discovery ? IP_DF : 0);
1364#else
1210 h->ip_off = htons(ip_mtudisc ? IP_DF : 0);
1365 h->ip_off = htons(ip_mtudisc ? IP_DF : 0);
1366#endif
1367 h->ip_len = htons(len);
1211 h->ip_ttl = ttl ? ttl : ip_defttl;
1212 h->ip_sum = 0;
1368 h->ip_ttl = ttl ? ttl : ip_defttl;
1369 h->ip_sum = 0;
1370#if defined(__FreeBSD__)
1371 ip = mtod(m, struct ip *);
1372 /*
1373 * XXX
1374 * OpenBSD changed ip_len/ip_off byte ordering!
1375 * Because FreeBSD assumes host byte ordering we need to
1376 * change here.
1377 */
1378 NTOHS(ip->ip_len);
1379 NTOHS(ip->ip_off);
1380#if (__FreeBSD_version < 501114)
1381 bzero(&ro, sizeof(ro));
1382 ip_rtaddr(ip->ip_dst, &ro);
1383 PF_UNLOCK();
1384 ip_output(m, (void *)NULL, &ro, 0, (void *)NULL,
1385 (void *)NULL);
1386 PF_LOCK();
1387 if(ro.ro_rt) {
1388 RTFREE(ro.ro_rt);
1389 }
1390#else /* __FreeBSD_version >= 501114 */
1391 PF_UNLOCK();
1213 ip_output(m, (void *)NULL, (void *)NULL, 0, (void *)NULL,
1392 ip_output(m, (void *)NULL, (void *)NULL, 0, (void *)NULL,
1393 (void *)NULL);
1394 PF_LOCK();
1395#endif
1396#else /* ! __FreeBSD__ */
1397 ip_output(m, (void *)NULL, (void *)NULL, 0, (void *)NULL,
1214 (void *)NULL);
1398 (void *)NULL);
1399#endif
1215 break;
1216#endif /* INET */
1217#ifdef INET6
1218 case AF_INET6:
1219 /* TCP checksum */
1220 th->th_sum = in6_cksum(m, IPPROTO_TCP,
1221 sizeof(struct ip6_hdr), tlen);
1222
1223 h6->ip6_vfc |= IPV6_VERSION;
1224 h6->ip6_hlim = IPV6_DEFHLIM;
1225
1400 break;
1401#endif /* INET */
1402#ifdef INET6
1403 case AF_INET6:
1404 /* TCP checksum */
1405 th->th_sum = in6_cksum(m, IPPROTO_TCP,
1406 sizeof(struct ip6_hdr), tlen);
1407
1408 h6->ip6_vfc |= IPV6_VERSION;
1409 h6->ip6_hlim = IPV6_DEFHLIM;
1410
1411#if defined(__FreeBSD__)
1412 PF_UNLOCK();
1413 ip6_output(m, NULL, NULL, 0, NULL, NULL, NULL);
1414 PF_LOCK();
1415#else
1226 ip6_output(m, NULL, NULL, 0, NULL, NULL);
1416 ip6_output(m, NULL, NULL, 0, NULL, NULL);
1417#endif
1227 break;
1228#endif /* INET6 */
1229 }
1230}
1231
1232void
1233pf_send_icmp(struct mbuf *m, u_int8_t type, u_int8_t code, sa_family_t af,
1234 struct pf_rule *r)
1235{
1236 struct m_tag *mtag;
1237 struct mbuf *m0;
1418 break;
1419#endif /* INET6 */
1420 }
1421}
1422
1423void
1424pf_send_icmp(struct mbuf *m, u_int8_t type, u_int8_t code, sa_family_t af,
1425 struct pf_rule *r)
1426{
1427 struct m_tag *mtag;
1428 struct mbuf *m0;
1429#if defined(__FreeBSD__)
1430 struct ip *ip;
1431#endif
1238
1239 mtag = m_tag_get(PACKET_TAG_PF_GENERATED, 0, M_NOWAIT);
1240 if (mtag == NULL)
1241 return;
1432
1433 mtag = m_tag_get(PACKET_TAG_PF_GENERATED, 0, M_NOWAIT);
1434 if (mtag == NULL)
1435 return;
1436#if defined(__FreeBSD__)
1437 m0 = m_copypacket(m, M_DONTWAIT);
1438#else
1242 m0 = m_copy(m, 0, M_COPYALL);
1439 m0 = m_copy(m, 0, M_COPYALL);
1440#endif
1243 if (m0 == NULL) {
1244 m_tag_free(mtag);
1245 return;
1246 }
1247 m_tag_prepend(m0, mtag);
1248
1249#ifdef ALTQ
1250 if (r->qid) {

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

1260 m_tag_prepend(m0, mtag);
1261 }
1262 }
1263#endif
1264
1265 switch (af) {
1266#ifdef INET
1267 case AF_INET:
1441 if (m0 == NULL) {
1442 m_tag_free(mtag);
1443 return;
1444 }
1445 m_tag_prepend(m0, mtag);
1446
1447#ifdef ALTQ
1448 if (r->qid) {

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

1458 m_tag_prepend(m0, mtag);
1459 }
1460 }
1461#endif
1462
1463 switch (af) {
1464#ifdef INET
1465 case AF_INET:
1268 icmp_error(m0, type, code, 0, 0);
1466#if defined(__FreeBSD__)
1467 /* icmp_error() expects host byte ordering */
1468 ip = mtod(m0, struct ip *);
1469 NTOHS(ip->ip_len);
1470 NTOHS(ip->ip_off);
1471 PF_UNLOCK();
1472#endif
1473 icmp_error(m0, type, code, 0, NULL);
1474#if defined(__FreeBSD__)
1475 PF_LOCK();
1476#endif
1269 break;
1270#endif /* INET */
1271#ifdef INET6
1272 case AF_INET6:
1477 break;
1478#endif /* INET */
1479#ifdef INET6
1480 case AF_INET6:
1481#if defined(__FreeBSD__)
1482 PF_UNLOCK();
1483#endif
1273 icmp6_error(m0, type, code, 0);
1484 icmp6_error(m0, type, code, 0);
1485#if defined(__FreeBSD__)
1486 PF_LOCK();
1487#endif
1274 break;
1275#endif /* INET6 */
1276 }
1277}
1278
1279/*
1280 * Return 1 if the addresses a and b match (with mask m), otherwise return 0.
1281 * If n is 0, they match if they are equal. If n is != 0, they match if they

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

1892 break;
1893 case PF_IN:
1894 if (r->src.addr.type == PF_ADDR_DYNIFTL &&
1895 r->src.addr.p.dyn->undefined)
1896 return (NULL);
1897 else
1898 PF_POOLMASK(naddr,
1899 &r->src.addr.v.a.addr,
1488 break;
1489#endif /* INET6 */
1490 }
1491}
1492
1493/*
1494 * Return 1 if the addresses a and b match (with mask m), otherwise return 0.
1495 * If n is 0, they match if they are equal. If n is != 0, they match if they

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

2106 break;
2107 case PF_IN:
2108 if (r->src.addr.type == PF_ADDR_DYNIFTL &&
2109 r->src.addr.p.dyn->undefined)
2110 return (NULL);
2111 else
2112 PF_POOLMASK(naddr,
2113 &r->src.addr.v.a.addr,
1900 &r->src.addr.v.a.mask, saddr,
2114 &r->src.addr.v.a.mask, daddr,
1901 pd->af);
1902 break;
1903 }
1904 break;
1905 case PF_RDR: {
1906 if (pf_map_addr(r->af, &r->rpool, saddr, naddr, NULL))
1907 return (NULL);
1908

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

1933}
1934
1935int
1936pf_socket_lookup(uid_t *uid, gid_t *gid, int direction, sa_family_t af,
1937 int proto, struct pf_pdesc *pd)
1938{
1939 struct pf_addr *saddr, *daddr;
1940 u_int16_t sport, dport;
2115 pd->af);
2116 break;
2117 }
2118 break;
2119 case PF_RDR: {
2120 if (pf_map_addr(r->af, &r->rpool, saddr, naddr, NULL))
2121 return (NULL);
2122

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

2147}
2148
2149int
2150pf_socket_lookup(uid_t *uid, gid_t *gid, int direction, sa_family_t af,
2151 int proto, struct pf_pdesc *pd)
2152{
2153 struct pf_addr *saddr, *daddr;
2154 u_int16_t sport, dport;
2155#if defined(__FreeBSD__)
2156 struct inpcbinfo *pi;
2157#else
1941 struct inpcbtable *tb;
2158 struct inpcbtable *tb;
2159#endif
1942 struct inpcb *inp;
1943
1944 *uid = UID_MAX;
1945 *gid = GID_MAX;
1946 switch (proto) {
1947 case IPPROTO_TCP:
1948 sport = pd->hdr.tcp->th_sport;
1949 dport = pd->hdr.tcp->th_dport;
2160 struct inpcb *inp;
2161
2162 *uid = UID_MAX;
2163 *gid = GID_MAX;
2164 switch (proto) {
2165 case IPPROTO_TCP:
2166 sport = pd->hdr.tcp->th_sport;
2167 dport = pd->hdr.tcp->th_dport;
2168#if defined(__FreeBSD__)
2169 pi = &tcbinfo;
2170#else
1950 tb = &tcbtable;
2171 tb = &tcbtable;
2172#endif
1951 break;
1952 case IPPROTO_UDP:
1953 sport = pd->hdr.udp->uh_sport;
1954 dport = pd->hdr.udp->uh_dport;
2173 break;
2174 case IPPROTO_UDP:
2175 sport = pd->hdr.udp->uh_sport;
2176 dport = pd->hdr.udp->uh_dport;
2177#if defined(__FreeBSD__)
2178 pi = &udbinfo;
2179#else
1955 tb = &udbtable;
2180 tb = &udbtable;
2181#endif
1956 break;
1957 default:
1958 return (0);
1959 }
1960 if (direction == PF_IN) {
1961 saddr = pd->src;
1962 daddr = pd->dst;
1963 } else {
1964 u_int16_t p;
1965
1966 p = sport;
1967 sport = dport;
1968 dport = p;
1969 saddr = pd->dst;
1970 daddr = pd->src;
1971 }
1972 switch(af) {
1973 case AF_INET:
2182 break;
2183 default:
2184 return (0);
2185 }
2186 if (direction == PF_IN) {
2187 saddr = pd->src;
2188 daddr = pd->dst;
2189 } else {
2190 u_int16_t p;
2191
2192 p = sport;
2193 sport = dport;
2194 dport = p;
2195 saddr = pd->dst;
2196 daddr = pd->src;
2197 }
2198 switch(af) {
2199 case AF_INET:
2200#if defined(__FreeBSD__)
2201#if (__FreeBSD_version >= 500043)
2202 INP_INFO_RLOCK(pi); /* XXX LOR */
2203#endif
2204 inp = in_pcblookup_hash(pi, saddr->v4, sport, daddr->v4,
2205 dport, 0, NULL);
2206 if (inp == NULL) {
2207 inp = in_pcblookup_hash(pi, saddr->v4, sport,
2208 daddr->v4, dport, INPLOOKUP_WILDCARD, NULL);
2209 if(inp == NULL) {
2210#if (__FreeBSD_version >= 500043)
2211 INP_INFO_RUNLOCK(pi);
2212#endif
2213 return (0);
2214 }
2215 }
2216#else
1974 inp = in_pcbhashlookup(tb, saddr->v4, sport, daddr->v4, dport);
1975 if (inp == NULL) {
1976 inp = in_pcblookup(tb, &saddr->v4, sport, &daddr->v4,
1977 dport, INPLOOKUP_WILDCARD);
1978 if (inp == NULL)
1979 return (0);
1980 }
2217 inp = in_pcbhashlookup(tb, saddr->v4, sport, daddr->v4, dport);
2218 if (inp == NULL) {
2219 inp = in_pcblookup(tb, &saddr->v4, sport, &daddr->v4,
2220 dport, INPLOOKUP_WILDCARD);
2221 if (inp == NULL)
2222 return (0);
2223 }
2224#endif
1981 break;
1982#ifdef INET6
1983 case AF_INET6:
2225 break;
2226#ifdef INET6
2227 case AF_INET6:
2228#if defined(__FreeBSD__)
2229#if (__FreeBSD_version >= 500043)
2230 INP_INFO_RLOCK(pi);
2231#endif
2232 inp = in6_pcblookup_hash(pi, &saddr->v6, sport,
2233 &daddr->v6, dport, 0, NULL);
2234 if (inp == NULL) {
2235 inp = in6_pcblookup_hash(pi, &saddr->v6, sport,
2236 &daddr->v6, dport, INPLOOKUP_WILDCARD, NULL);
2237 if (inp == NULL) {
2238#if (__FreeBSD_version >= 500043)
2239 INP_INFO_RUNLOCK(pi);
2240#endif
2241 return (0);
2242 }
2243 }
2244#else
1984 inp = in6_pcbhashlookup(tb, &saddr->v6, sport, &daddr->v6,
1985 dport);
1986 if (inp == NULL) {
1987 inp = in_pcblookup(tb, &saddr->v6, sport, &daddr->v6,
1988 dport, INPLOOKUP_WILDCARD | INPLOOKUP_IPV6);
1989 if (inp == NULL)
1990 return (0);
1991 }
2245 inp = in6_pcbhashlookup(tb, &saddr->v6, sport, &daddr->v6,
2246 dport);
2247 if (inp == NULL) {
2248 inp = in_pcblookup(tb, &saddr->v6, sport, &daddr->v6,
2249 dport, INPLOOKUP_WILDCARD | INPLOOKUP_IPV6);
2250 if (inp == NULL)
2251 return (0);
2252 }
2253#endif
1992 break;
1993#endif /* INET6 */
1994
1995 default:
1996 return (0);
1997 }
2254 break;
2255#endif /* INET6 */
2256
2257 default:
2258 return (0);
2259 }
2260#if defined(__FreeBSD__)
2261#if (__FreeBSD_version >= 500043)
2262 INP_LOCK(inp);
2263#endif
2264 *uid = inp->inp_socket->so_cred->cr_uid;
2265 *gid = inp->inp_socket->so_cred->cr_groups[0];
2266#if (__FreeBSD_version >= 500043)
2267 INP_UNLOCK(inp);
2268 INP_INFO_RUNLOCK(pi);
2269#endif
2270#else
1998 *uid = inp->inp_socket->so_euid;
1999 *gid = inp->inp_socket->so_egid;
2271 *uid = inp->inp_socket->so_euid;
2272 *gid = inp->inp_socket->so_egid;
2273#endif
2000 return (1);
2001}
2002
2003u_int8_t
2004pf_get_wscale(struct mbuf *m, int off, u_int16_t th_off, sa_family_t af)
2005{
2006 int hlen;
2007 u_int8_t hdr[60];

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

2094#ifdef INET
2095 case AF_INET:
2096 hlen = sizeof(struct ip);
2097 bzero(&ro, sizeof(ro));
2098 dst = (struct sockaddr_in *)&ro.ro_dst;
2099 dst->sin_family = AF_INET;
2100 dst->sin_len = sizeof(*dst);
2101 dst->sin_addr = addr->v4;
2274 return (1);
2275}
2276
2277u_int8_t
2278pf_get_wscale(struct mbuf *m, int off, u_int16_t th_off, sa_family_t af)
2279{
2280 int hlen;
2281 u_int8_t hdr[60];

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

2368#ifdef INET
2369 case AF_INET:
2370 hlen = sizeof(struct ip);
2371 bzero(&ro, sizeof(ro));
2372 dst = (struct sockaddr_in *)&ro.ro_dst;
2373 dst->sin_family = AF_INET;
2374 dst->sin_len = sizeof(*dst);
2375 dst->sin_addr = addr->v4;
2376#if defined(__FreeBSD__)
2377#ifdef RTF_PRCLONING
2378 rtalloc_ign(&ro, (RTF_CLONING | RTF_PRCLONING));
2379#else /* !RTF_PRCLONING */
2380 rtalloc_ign(&ro, RTF_CLONING);
2381#endif
2382#else /* ! __FreeBSD__ */
2102 rtalloc_noclone(&ro, NO_CLONING);
2383 rtalloc_noclone(&ro, NO_CLONING);
2384#endif
2103 rt = ro.ro_rt;
2104 break;
2105#endif /* INET */
2106#ifdef INET6
2107 case AF_INET6:
2108 hlen = sizeof(struct ip6_hdr);
2109 bzero(&ro6, sizeof(ro6));
2110 dst6 = (struct sockaddr_in6 *)&ro6.ro_dst;
2111 dst6->sin6_family = AF_INET6;
2112 dst6->sin6_len = sizeof(*dst6);
2113 dst6->sin6_addr = addr->v6;
2385 rt = ro.ro_rt;
2386 break;
2387#endif /* INET */
2388#ifdef INET6
2389 case AF_INET6:
2390 hlen = sizeof(struct ip6_hdr);
2391 bzero(&ro6, sizeof(ro6));
2392 dst6 = (struct sockaddr_in6 *)&ro6.ro_dst;
2393 dst6->sin6_family = AF_INET6;
2394 dst6->sin6_len = sizeof(*dst6);
2395 dst6->sin6_addr = addr->v6;
2396#if defined(__FreeBSD__)
2397#ifdef RTF_PRCLONING
2398 rtalloc_ign((struct route *)&ro6,
2399 (RTF_CLONING | RTF_PRCLONING));
2400#else /* !RTF_PRCLONING */
2401 rtalloc_ign((struct route *)&ro6, RTF_CLONING);
2402#endif
2403#else /* ! __FreeBSD__ */
2114 rtalloc_noclone((struct route *)&ro6, NO_CLONING);
2404 rtalloc_noclone((struct route *)&ro6, NO_CLONING);
2405#endif
2115 rt = ro6.ro_rt;
2116 break;
2117#endif /* INET6 */
2118 }
2119
2120 if (rt && rt->rt_ifp) {
2121 mss = rt->rt_ifp->if_mtu - hlen - sizeof(struct tcphdr);
2122 mss = max(tcp_mssdflt, mss);

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

2279 if (a != NULL) {
2280 a->packets++;
2281 a->bytes += pd->tot_len;
2282 }
2283 REASON_SET(&reason, PFRES_MATCH);
2284
2285 if (r->log) {
2286 if (rewrite)
2406 rt = ro6.ro_rt;
2407 break;
2408#endif /* INET6 */
2409 }
2410
2411 if (rt && rt->rt_ifp) {
2412 mss = rt->rt_ifp->if_mtu - hlen - sizeof(struct tcphdr);
2413 mss = max(tcp_mssdflt, mss);

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

2570 if (a != NULL) {
2571 a->packets++;
2572 a->bytes += pd->tot_len;
2573 }
2574 REASON_SET(&reason, PFRES_MATCH);
2575
2576 if (r->log) {
2577 if (rewrite)
2287 m_copyback(m, off, sizeof(*th), th);
2578 m_copyback(m, off, sizeof(*th), (caddr_t)th);
2288 PFLOG_PACKET(ifp, h, m, af, direction, reason, r, a, ruleset);
2289 }
2290
2291 if ((r->action == PF_DROP) &&
2292 ((r->rule_flag & PFRULE_RETURNRST) ||
2293 (r->rule_flag & PFRULE_RETURNICMP) ||
2294 (r->rule_flag & PFRULE_RETURN))) {
2295 /* undo NAT changes, if they have taken place */

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

2412 (s->src.wscale & PF_WSCALE_MASK);
2413 }
2414 if (th->th_flags & TH_FIN)
2415 s->src.seqhi++;
2416 s->dst.seqhi = 1;
2417 s->dst.max_win = 1;
2418 s->src.state = TCPS_SYN_SENT;
2419 s->dst.state = TCPS_CLOSED;
2579 PFLOG_PACKET(ifp, h, m, af, direction, reason, r, a, ruleset);
2580 }
2581
2582 if ((r->action == PF_DROP) &&
2583 ((r->rule_flag & PFRULE_RETURNRST) ||
2584 (r->rule_flag & PFRULE_RETURNICMP) ||
2585 (r->rule_flag & PFRULE_RETURN))) {
2586 /* undo NAT changes, if they have taken place */

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

2703 (s->src.wscale & PF_WSCALE_MASK);
2704 }
2705 if (th->th_flags & TH_FIN)
2706 s->src.seqhi++;
2707 s->dst.seqhi = 1;
2708 s->dst.max_win = 1;
2709 s->src.state = TCPS_SYN_SENT;
2710 s->dst.state = TCPS_CLOSED;
2711#if defined(__FreeBSD__)
2712 s->creation = time_second;
2713 s->expire = time_second;
2714#else
2420 s->creation = time.tv_sec;
2421 s->expire = time.tv_sec;
2715 s->creation = time.tv_sec;
2716 s->expire = time.tv_sec;
2717#endif
2422 s->timeout = PFTM_TCP_FIRST_PACKET;
2423 s->packets[0] = 1;
2424 s->bytes[0] = pd->tot_len;
2425 pf_set_rt_ifp(s, saddr);
2426
2427 if ((pd->flags & PFDESC_TCP_NORM) && pf_normalize_tcp_init(m,
2428 off, pd, th, &s->src, &s->dst)) {
2429 REASON_SET(&reason, PFRES_MEMORY);

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

2465 th->th_sport, s->src.seqhi,
2466 ntohl(th->th_seq) + 1, TH_SYN|TH_ACK, 0, s->src.mss, 0);
2467 return (PF_SYNPROXY_DROP);
2468 }
2469 }
2470
2471 /* copy back packet headers if we performed NAT operations */
2472 if (rewrite)
2718 s->timeout = PFTM_TCP_FIRST_PACKET;
2719 s->packets[0] = 1;
2720 s->bytes[0] = pd->tot_len;
2721 pf_set_rt_ifp(s, saddr);
2722
2723 if ((pd->flags & PFDESC_TCP_NORM) && pf_normalize_tcp_init(m,
2724 off, pd, th, &s->src, &s->dst)) {
2725 REASON_SET(&reason, PFRES_MEMORY);

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

2761 th->th_sport, s->src.seqhi,
2762 ntohl(th->th_seq) + 1, TH_SYN|TH_ACK, 0, s->src.mss, 0);
2763 return (PF_SYNPROXY_DROP);
2764 }
2765 }
2766
2767 /* copy back packet headers if we performed NAT operations */
2768 if (rewrite)
2473 m_copyback(m, off, sizeof(*th), th);
2769 m_copyback(m, off, sizeof(*th), (caddr_t)th);
2474
2475 return (PF_PASS);
2476}
2477
2478int
2479pf_test_udp(struct pf_rule **rm, struct pf_state **sm, int direction,
2480 struct ifnet *ifp, struct mbuf *m, int ipoff, int off, void *h,
2481 struct pf_pdesc *pd, struct pf_rule **am, struct pf_ruleset **rsm)

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

2597 if (a != NULL) {
2598 a->packets++;
2599 a->bytes += pd->tot_len;
2600 }
2601 REASON_SET(&reason, PFRES_MATCH);
2602
2603 if (r->log) {
2604 if (rewrite)
2770
2771 return (PF_PASS);
2772}
2773
2774int
2775pf_test_udp(struct pf_rule **rm, struct pf_state **sm, int direction,
2776 struct ifnet *ifp, struct mbuf *m, int ipoff, int off, void *h,
2777 struct pf_pdesc *pd, struct pf_rule **am, struct pf_ruleset **rsm)

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

2893 if (a != NULL) {
2894 a->packets++;
2895 a->bytes += pd->tot_len;
2896 }
2897 REASON_SET(&reason, PFRES_MATCH);
2898
2899 if (r->log) {
2900 if (rewrite)
2605 m_copyback(m, off, sizeof(*uh), uh);
2901 m_copyback(m, off, sizeof(*uh), (caddr_t)uh);
2606 PFLOG_PACKET(ifp, h, m, af, direction, reason, r, a, ruleset);
2607 }
2608
2609 if ((r->action == PF_DROP) &&
2610 ((r->rule_flag & PFRULE_RETURNICMP) ||
2611 (r->rule_flag & PFRULE_RETURN))) {
2612 /* undo NAT changes, if they have taken place */
2613 if (nat != NULL) {

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

2684 s->gwy.port = bport;
2685 } else {
2686 PF_ACPY(&s->gwy.addr, &s->lan.addr, af);
2687 s->gwy.port = s->lan.port;
2688 }
2689 }
2690 s->src.state = PFUDPS_SINGLE;
2691 s->dst.state = PFUDPS_NO_TRAFFIC;
2902 PFLOG_PACKET(ifp, h, m, af, direction, reason, r, a, ruleset);
2903 }
2904
2905 if ((r->action == PF_DROP) &&
2906 ((r->rule_flag & PFRULE_RETURNICMP) ||
2907 (r->rule_flag & PFRULE_RETURN))) {
2908 /* undo NAT changes, if they have taken place */
2909 if (nat != NULL) {

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

2980 s->gwy.port = bport;
2981 } else {
2982 PF_ACPY(&s->gwy.addr, &s->lan.addr, af);
2983 s->gwy.port = s->lan.port;
2984 }
2985 }
2986 s->src.state = PFUDPS_SINGLE;
2987 s->dst.state = PFUDPS_NO_TRAFFIC;
2988#if defined(__FreeBSD__)
2989 s->creation = time_second;
2990 s->expire = time_second;
2991#else
2692 s->creation = time.tv_sec;
2693 s->expire = time.tv_sec;
2992 s->creation = time.tv_sec;
2993 s->expire = time.tv_sec;
2994#endif
2694 s->timeout = PFTM_UDP_FIRST_PACKET;
2695 s->packets[0] = 1;
2696 s->bytes[0] = pd->tot_len;
2697 pf_set_rt_ifp(s, saddr);
2698 if (pf_insert_state(s)) {
2699 REASON_SET(&reason, PFRES_MEMORY);
2700 pool_put(&pf_state_pl, s);
2701 return (PF_DROP);
2702 } else
2703 *sm = s;
2704 }
2705
2706 /* copy back packet headers if we performed NAT operations */
2707 if (rewrite)
2995 s->timeout = PFTM_UDP_FIRST_PACKET;
2996 s->packets[0] = 1;
2997 s->bytes[0] = pd->tot_len;
2998 pf_set_rt_ifp(s, saddr);
2999 if (pf_insert_state(s)) {
3000 REASON_SET(&reason, PFRES_MEMORY);
3001 pool_put(&pf_state_pl, s);
3002 return (PF_DROP);
3003 } else
3004 *sm = s;
3005 }
3006
3007 /* copy back packet headers if we performed NAT operations */
3008 if (rewrite)
2708 m_copyback(m, off, sizeof(*uh), uh);
3009 m_copyback(m, off, sizeof(*uh), (caddr_t)uh);
2709
2710 return (PF_PASS);
2711}
2712
2713int
2714pf_test_icmp(struct pf_rule **rm, struct pf_state **sm, int direction,
2715 struct ifnet *ifp, struct mbuf *m, int ipoff, int off, void *h,
2716 struct pf_pdesc *pd, struct pf_rule **am, struct pf_ruleset **rsm)

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

2870 a->bytes += pd->tot_len;
2871 }
2872 REASON_SET(&reason, PFRES_MATCH);
2873
2874 if (r->log) {
2875#ifdef INET6
2876 if (rewrite)
2877 m_copyback(m, off, sizeof(struct icmp6_hdr),
3010
3011 return (PF_PASS);
3012}
3013
3014int
3015pf_test_icmp(struct pf_rule **rm, struct pf_state **sm, int direction,
3016 struct ifnet *ifp, struct mbuf *m, int ipoff, int off, void *h,
3017 struct pf_pdesc *pd, struct pf_rule **am, struct pf_ruleset **rsm)

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

3171 a->bytes += pd->tot_len;
3172 }
3173 REASON_SET(&reason, PFRES_MATCH);
3174
3175 if (r->log) {
3176#ifdef INET6
3177 if (rewrite)
3178 m_copyback(m, off, sizeof(struct icmp6_hdr),
2878 pd->hdr.icmp6);
3179 (caddr_t)pd->hdr.icmp6);
2879#endif /* INET6 */
2880 PFLOG_PACKET(ifp, h, m, af, direction, reason, r, a, ruleset);
2881 }
2882
2883 if (r->action != PF_PASS)
2884 return (PF_DROP);
2885
2886 if (pf_tag_packet(m, pftag, tag)) {

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

2932 PF_ACPY(&s->ext.addr, saddr, af);
2933 s->ext.port = icmpid;
2934 if (rdr != NULL)
2935 PF_ACPY(&s->gwy.addr, &baddr, af);
2936 else
2937 PF_ACPY(&s->gwy.addr, &s->lan.addr, af);
2938 s->gwy.port = icmpid;
2939 }
3180#endif /* INET6 */
3181 PFLOG_PACKET(ifp, h, m, af, direction, reason, r, a, ruleset);
3182 }
3183
3184 if (r->action != PF_PASS)
3185 return (PF_DROP);
3186
3187 if (pf_tag_packet(m, pftag, tag)) {

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

3233 PF_ACPY(&s->ext.addr, saddr, af);
3234 s->ext.port = icmpid;
3235 if (rdr != NULL)
3236 PF_ACPY(&s->gwy.addr, &baddr, af);
3237 else
3238 PF_ACPY(&s->gwy.addr, &s->lan.addr, af);
3239 s->gwy.port = icmpid;
3240 }
3241
3242#if defined(__FreeBSD__)
3243 s->creation = time_second;
3244 s->expire = time_second;
3245#else
2940 s->creation = time.tv_sec;
2941 s->expire = time.tv_sec;
3246 s->creation = time.tv_sec;
3247 s->expire = time.tv_sec;
3248#endif
2942 s->timeout = PFTM_ICMP_FIRST_PACKET;
2943 s->packets[0] = 1;
2944 s->bytes[0] = pd->tot_len;
2945 pf_set_rt_ifp(s, saddr);
2946 if (pf_insert_state(s)) {
2947 REASON_SET(&reason, PFRES_MEMORY);
2948 pool_put(&pf_state_pl, s);
2949 return (PF_DROP);
2950 } else
2951 *sm = s;
2952 }
2953
2954#ifdef INET6
2955 /* copy back packet headers if we performed IPv6 NAT operations */
2956 if (rewrite)
2957 m_copyback(m, off, sizeof(struct icmp6_hdr),
3249 s->timeout = PFTM_ICMP_FIRST_PACKET;
3250 s->packets[0] = 1;
3251 s->bytes[0] = pd->tot_len;
3252 pf_set_rt_ifp(s, saddr);
3253 if (pf_insert_state(s)) {
3254 REASON_SET(&reason, PFRES_MEMORY);
3255 pool_put(&pf_state_pl, s);
3256 return (PF_DROP);
3257 } else
3258 *sm = s;
3259 }
3260
3261#ifdef INET6
3262 /* copy back packet headers if we performed IPv6 NAT operations */
3263 if (rewrite)
3264 m_copyback(m, off, sizeof(struct icmp6_hdr),
2958 pd->hdr.icmp6);
3265 (caddr_t)pd->hdr.icmp6);
2959#endif /* INET6 */
2960
2961 return (PF_PASS);
2962}
2963
2964int
2965pf_test_other(struct pf_rule **rm, struct pf_state **sm, int direction,
2966 struct ifnet *ifp, struct mbuf *m, int off, void *h, struct pf_pdesc *pd,

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

3159 PF_ACPY(&s->ext.addr, saddr, af);
3160 if (rdr != NULL)
3161 PF_ACPY(&s->gwy.addr, &baddr, af);
3162 else
3163 PF_ACPY(&s->gwy.addr, &s->lan.addr, af);
3164 }
3165 s->src.state = PFOTHERS_SINGLE;
3166 s->dst.state = PFOTHERS_NO_TRAFFIC;
3266#endif /* INET6 */
3267
3268 return (PF_PASS);
3269}
3270
3271int
3272pf_test_other(struct pf_rule **rm, struct pf_state **sm, int direction,
3273 struct ifnet *ifp, struct mbuf *m, int off, void *h, struct pf_pdesc *pd,

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

3466 PF_ACPY(&s->ext.addr, saddr, af);
3467 if (rdr != NULL)
3468 PF_ACPY(&s->gwy.addr, &baddr, af);
3469 else
3470 PF_ACPY(&s->gwy.addr, &s->lan.addr, af);
3471 }
3472 s->src.state = PFOTHERS_SINGLE;
3473 s->dst.state = PFOTHERS_NO_TRAFFIC;
3474#if defined(__FreeBSD__)
3475 s->creation = time_second;
3476 s->expire = time_second;
3477#else
3167 s->creation = time.tv_sec;
3168 s->expire = time.tv_sec;
3478 s->creation = time.tv_sec;
3479 s->expire = time.tv_sec;
3480#endif
3169 s->timeout = PFTM_OTHER_FIRST_PACKET;
3170 s->packets[0] = 1;
3171 s->bytes[0] = pd->tot_len;
3172 pf_set_rt_ifp(s, saddr);
3173 if (pf_insert_state(s)) {
3174 REASON_SET(&reason, PFRES_MEMORY);
3175 if (r->log)
3176 PFLOG_PACKET(ifp, h, m, af, direction, reason,

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

3518 dst->state = TCPS_ESTABLISHED;
3519 else if (dst->state == TCPS_CLOSING)
3520 dst->state = TCPS_FIN_WAIT_2;
3521 }
3522 if (th->th_flags & TH_RST)
3523 src->state = dst->state = TCPS_TIME_WAIT;
3524
3525 /* update expire time */
3481 s->timeout = PFTM_OTHER_FIRST_PACKET;
3482 s->packets[0] = 1;
3483 s->bytes[0] = pd->tot_len;
3484 pf_set_rt_ifp(s, saddr);
3485 if (pf_insert_state(s)) {
3486 REASON_SET(&reason, PFRES_MEMORY);
3487 if (r->log)
3488 PFLOG_PACKET(ifp, h, m, af, direction, reason,

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

3830 dst->state = TCPS_ESTABLISHED;
3831 else if (dst->state == TCPS_CLOSING)
3832 dst->state = TCPS_FIN_WAIT_2;
3833 }
3834 if (th->th_flags & TH_RST)
3835 src->state = dst->state = TCPS_TIME_WAIT;
3836
3837 /* update expire time */
3838#if defined(__FreeBSD__)
3839 (*state)->expire = time_second;
3840#else
3526 (*state)->expire = time.tv_sec;
3841 (*state)->expire = time.tv_sec;
3842#endif
3527 if (src->state >= TCPS_FIN_WAIT_2 &&
3528 dst->state >= TCPS_FIN_WAIT_2)
3529 (*state)->timeout = PFTM_TCP_CLOSED;
3530 else if (src->state >= TCPS_FIN_WAIT_2 ||
3531 dst->state >= TCPS_FIN_WAIT_2)
3532 (*state)->timeout = PFTM_TCP_FIN_WAIT;
3533 else if (src->state < TCPS_ESTABLISHED ||
3534 dst->state < TCPS_ESTABLISHED)

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

3659 if (direction == PF_OUT)
3660 pf_change_ap(pd->src, &th->th_sport, pd->ip_sum,
3661 &th->th_sum, &(*state)->gwy.addr,
3662 (*state)->gwy.port, 0, pd->af);
3663 else
3664 pf_change_ap(pd->dst, &th->th_dport, pd->ip_sum,
3665 &th->th_sum, &(*state)->lan.addr,
3666 (*state)->lan.port, 0, pd->af);
3843 if (src->state >= TCPS_FIN_WAIT_2 &&
3844 dst->state >= TCPS_FIN_WAIT_2)
3845 (*state)->timeout = PFTM_TCP_CLOSED;
3846 else if (src->state >= TCPS_FIN_WAIT_2 ||
3847 dst->state >= TCPS_FIN_WAIT_2)
3848 (*state)->timeout = PFTM_TCP_FIN_WAIT;
3849 else if (src->state < TCPS_ESTABLISHED ||
3850 dst->state < TCPS_ESTABLISHED)

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

3975 if (direction == PF_OUT)
3976 pf_change_ap(pd->src, &th->th_sport, pd->ip_sum,
3977 &th->th_sum, &(*state)->gwy.addr,
3978 (*state)->gwy.port, 0, pd->af);
3979 else
3980 pf_change_ap(pd->dst, &th->th_dport, pd->ip_sum,
3981 &th->th_sum, &(*state)->lan.addr,
3982 (*state)->lan.port, 0, pd->af);
3667 m_copyback(m, off, sizeof(*th), th);
3983 m_copyback(m, off, sizeof(*th), (caddr_t)th);
3668 } else if (copyback) {
3669 /* Copyback sequence modulation or stateful scrub changes */
3984 } else if (copyback) {
3985 /* Copyback sequence modulation or stateful scrub changes */
3670 m_copyback(m, off, sizeof(*th), th);
3986 m_copyback(m, off, sizeof(*th), (caddr_t)th);
3671 }
3672
3673 (*state)->rule.ptr->packets++;
3674 (*state)->rule.ptr->bytes += pd->tot_len;
3675 if ((*state)->nat_rule.ptr != NULL) {
3676 (*state)->nat_rule.ptr->packets++;
3677 (*state)->nat_rule.ptr->bytes += pd->tot_len;
3678 }

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

3716
3717 /* update states */
3718 if (src->state < PFUDPS_SINGLE)
3719 src->state = PFUDPS_SINGLE;
3720 if (dst->state == PFUDPS_SINGLE)
3721 dst->state = PFUDPS_MULTIPLE;
3722
3723 /* update expire time */
3987 }
3988
3989 (*state)->rule.ptr->packets++;
3990 (*state)->rule.ptr->bytes += pd->tot_len;
3991 if ((*state)->nat_rule.ptr != NULL) {
3992 (*state)->nat_rule.ptr->packets++;
3993 (*state)->nat_rule.ptr->bytes += pd->tot_len;
3994 }

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

4032
4033 /* update states */
4034 if (src->state < PFUDPS_SINGLE)
4035 src->state = PFUDPS_SINGLE;
4036 if (dst->state == PFUDPS_SINGLE)
4037 dst->state = PFUDPS_MULTIPLE;
4038
4039 /* update expire time */
4040#if defined(__FreeBSD__)
4041 (*state)->expire = time_second;
4042#else
3724 (*state)->expire = time.tv_sec;
4043 (*state)->expire = time.tv_sec;
4044#endif
3725 if (src->state == PFUDPS_MULTIPLE && dst->state == PFUDPS_MULTIPLE)
3726 (*state)->timeout = PFTM_UDP_MULTIPLE;
3727 else
3728 (*state)->timeout = PFTM_UDP_SINGLE;
3729
3730 /* translate source/destination address, if necessary */
3731 if (STATE_TRANSLATE(*state)) {
3732 if (direction == PF_OUT)
3733 pf_change_ap(pd->src, &uh->uh_sport, pd->ip_sum,
3734 &uh->uh_sum, &(*state)->gwy.addr,
3735 (*state)->gwy.port, 1, pd->af);
3736 else
3737 pf_change_ap(pd->dst, &uh->uh_dport, pd->ip_sum,
3738 &uh->uh_sum, &(*state)->lan.addr,
3739 (*state)->lan.port, 1, pd->af);
4045 if (src->state == PFUDPS_MULTIPLE && dst->state == PFUDPS_MULTIPLE)
4046 (*state)->timeout = PFTM_UDP_MULTIPLE;
4047 else
4048 (*state)->timeout = PFTM_UDP_SINGLE;
4049
4050 /* translate source/destination address, if necessary */
4051 if (STATE_TRANSLATE(*state)) {
4052 if (direction == PF_OUT)
4053 pf_change_ap(pd->src, &uh->uh_sport, pd->ip_sum,
4054 &uh->uh_sum, &(*state)->gwy.addr,
4055 (*state)->gwy.port, 1, pd->af);
4056 else
4057 pf_change_ap(pd->dst, &uh->uh_dport, pd->ip_sum,
4058 &uh->uh_sum, &(*state)->lan.addr,
4059 (*state)->lan.port, 1, pd->af);
3740 m_copyback(m, off, sizeof(*uh), uh);
4060 m_copyback(m, off, sizeof(*uh), (caddr_t)uh);
3741 }
3742
3743 (*state)->rule.ptr->packets++;
3744 (*state)->rule.ptr->bytes += pd->tot_len;
3745 if ((*state)->nat_rule.ptr != NULL) {
3746 (*state)->nat_rule.ptr->packets++;
3747 (*state)->nat_rule.ptr->bytes += pd->tot_len;
3748 }

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

3807 key.port[0] = icmpid;
3808 key.port[1] = icmpid;
3809
3810 STATE_LOOKUP();
3811
3812 dirndx = (direction == (*state)->direction) ? 0 : 1;
3813 (*state)->packets[dirndx]++;
3814 (*state)->bytes[dirndx] += pd->tot_len;
4061 }
4062
4063 (*state)->rule.ptr->packets++;
4064 (*state)->rule.ptr->bytes += pd->tot_len;
4065 if ((*state)->nat_rule.ptr != NULL) {
4066 (*state)->nat_rule.ptr->packets++;
4067 (*state)->nat_rule.ptr->bytes += pd->tot_len;
4068 }

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

4127 key.port[0] = icmpid;
4128 key.port[1] = icmpid;
4129
4130 STATE_LOOKUP();
4131
4132 dirndx = (direction == (*state)->direction) ? 0 : 1;
4133 (*state)->packets[dirndx]++;
4134 (*state)->bytes[dirndx] += pd->tot_len;
4135#if defined(__FreeBSD__)
4136 (*state)->expire = time_second;
4137#else
3815 (*state)->expire = time.tv_sec;
4138 (*state)->expire = time.tv_sec;
4139#endif
3816 (*state)->timeout = PFTM_ICMP_ERROR_REPLY;
3817
3818 /* translate source/destination address, if necessary */
3819 if (PF_ANEQ(&(*state)->lan.addr, &(*state)->gwy.addr, pd->af)) {
3820 if (direction == PF_OUT) {
3821 switch (pd->af) {
3822#ifdef INET
3823 case AF_INET:

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

3828#endif /* INET */
3829#ifdef INET6
3830 case AF_INET6:
3831 pf_change_a6(saddr,
3832 &pd->hdr.icmp6->icmp6_cksum,
3833 &(*state)->gwy.addr, 0);
3834 m_copyback(m, off,
3835 sizeof(struct icmp6_hdr),
4140 (*state)->timeout = PFTM_ICMP_ERROR_REPLY;
4141
4142 /* translate source/destination address, if necessary */
4143 if (PF_ANEQ(&(*state)->lan.addr, &(*state)->gwy.addr, pd->af)) {
4144 if (direction == PF_OUT) {
4145 switch (pd->af) {
4146#ifdef INET
4147 case AF_INET:

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

4152#endif /* INET */
4153#ifdef INET6
4154 case AF_INET6:
4155 pf_change_a6(saddr,
4156 &pd->hdr.icmp6->icmp6_cksum,
4157 &(*state)->gwy.addr, 0);
4158 m_copyback(m, off,
4159 sizeof(struct icmp6_hdr),
3836 pd->hdr.icmp6);
4160 (caddr_t)pd->hdr.icmp6);
3837 break;
3838#endif /* INET6 */
3839 }
3840 } else {
3841 switch (pd->af) {
3842#ifdef INET
3843 case AF_INET:
3844 pf_change_a(&daddr->v4.s_addr,
3845 pd->ip_sum,
3846 (*state)->lan.addr.v4.s_addr, 0);
3847 break;
3848#endif /* INET */
3849#ifdef INET6
3850 case AF_INET6:
3851 pf_change_a6(daddr,
3852 &pd->hdr.icmp6->icmp6_cksum,
3853 &(*state)->lan.addr, 0);
3854 m_copyback(m, off,
3855 sizeof(struct icmp6_hdr),
4161 break;
4162#endif /* INET6 */
4163 }
4164 } else {
4165 switch (pd->af) {
4166#ifdef INET
4167 case AF_INET:
4168 pf_change_a(&daddr->v4.s_addr,
4169 pd->ip_sum,
4170 (*state)->lan.addr.v4.s_addr, 0);
4171 break;
4172#endif /* INET */
4173#ifdef INET6
4174 case AF_INET6:
4175 pf_change_a6(daddr,
4176 &pd->hdr.icmp6->icmp6_cksum,
4177 &(*state)->lan.addr, 0);
4178 m_copyback(m, off,
4179 sizeof(struct icmp6_hdr),
3856 pd->hdr.icmp6);
4180 (caddr_t)pd->hdr.icmp6);
3857 break;
3858#endif /* INET6 */
3859 }
3860 }
3861 }
3862
3863 return (PF_PASS);
3864

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

4039 (*state)->gwy.port, NULL,
4040 pd2.ip_sum, icmpsum,
4041 pd->ip_sum, 0, pd2.af);
4042 }
4043 switch (pd2.af) {
4044#ifdef INET
4045 case AF_INET:
4046 m_copyback(m, off, ICMP_MINLEN,
4181 break;
4182#endif /* INET6 */
4183 }
4184 }
4185 }
4186
4187 return (PF_PASS);
4188

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

4363 (*state)->gwy.port, NULL,
4364 pd2.ip_sum, icmpsum,
4365 pd->ip_sum, 0, pd2.af);
4366 }
4367 switch (pd2.af) {
4368#ifdef INET
4369 case AF_INET:
4370 m_copyback(m, off, ICMP_MINLEN,
4047 pd->hdr.icmp);
4371 (caddr_t)pd->hdr.icmp);
4048 m_copyback(m, ipoff2, sizeof(h2),
4372 m_copyback(m, ipoff2, sizeof(h2),
4049 &h2);
4373 (caddr_t)&h2);
4050 break;
4051#endif /* INET */
4052#ifdef INET6
4053 case AF_INET6:
4054 m_copyback(m, off,
4055 sizeof(struct icmp6_hdr),
4374 break;
4375#endif /* INET */
4376#ifdef INET6
4377 case AF_INET6:
4378 m_copyback(m, off,
4379 sizeof(struct icmp6_hdr),
4056 pd->hdr.icmp6);
4380 (caddr_t)pd->hdr.icmp6);
4057 m_copyback(m, ipoff2, sizeof(h2_6),
4381 m_copyback(m, ipoff2, sizeof(h2_6),
4058 &h2_6);
4382 (caddr_t)&h2_6);
4059 break;
4060#endif /* INET6 */
4061 }
4383 break;
4384#endif /* INET6 */
4385 }
4062 m_copyback(m, off2, 8, &th);
4386 m_copyback(m, off2, 8, (caddr_t)&th);
4063 } else if (src->seqdiff) {
4387 } else if (src->seqdiff) {
4064 m_copyback(m, off2, 8, &th);
4388 m_copyback(m, off2, 8, (caddr_t)&th);
4065 }
4066
4067 return (PF_PASS);
4068 break;
4069 }
4070 case IPPROTO_UDP: {
4071 struct udphdr uh;
4072 struct pf_tree_node key;

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

4101 (*state)->gwy.port, &uh.uh_sum,
4102 pd2.ip_sum, icmpsum,
4103 pd->ip_sum, 1, pd2.af);
4104 }
4105 switch (pd2.af) {
4106#ifdef INET
4107 case AF_INET:
4108 m_copyback(m, off, ICMP_MINLEN,
4389 }
4390
4391 return (PF_PASS);
4392 break;
4393 }
4394 case IPPROTO_UDP: {
4395 struct udphdr uh;
4396 struct pf_tree_node key;

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

4425 (*state)->gwy.port, &uh.uh_sum,
4426 pd2.ip_sum, icmpsum,
4427 pd->ip_sum, 1, pd2.af);
4428 }
4429 switch (pd2.af) {
4430#ifdef INET
4431 case AF_INET:
4432 m_copyback(m, off, ICMP_MINLEN,
4109 pd->hdr.icmp);
4110 m_copyback(m, ipoff2, sizeof(h2), &h2);
4433 (caddr_t)pd->hdr.icmp);
4434 m_copyback(m, ipoff2, sizeof(h2),
4435 (caddr_t)&h2);
4111 break;
4112#endif /* INET */
4113#ifdef INET6
4114 case AF_INET6:
4115 m_copyback(m, off,
4116 sizeof(struct icmp6_hdr),
4436 break;
4437#endif /* INET */
4438#ifdef INET6
4439 case AF_INET6:
4440 m_copyback(m, off,
4441 sizeof(struct icmp6_hdr),
4117 pd->hdr.icmp6);
4442 (caddr_t)pd->hdr.icmp6);
4118 m_copyback(m, ipoff2, sizeof(h2_6),
4443 m_copyback(m, ipoff2, sizeof(h2_6),
4119 &h2_6);
4444 (caddr_t)&h2_6);
4120 break;
4121#endif /* INET6 */
4122 }
4445 break;
4446#endif /* INET6 */
4447 }
4123 m_copyback(m, off2, sizeof(uh), &uh);
4448 m_copyback(m, off2, sizeof(uh),
4449 (caddr_t)&uh);
4124 }
4125
4126 return (PF_PASS);
4127 break;
4128 }
4129#ifdef INET
4130 case IPPROTO_ICMP: {
4131 struct icmp iih;

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

4157 pd->ip_sum, 0, AF_INET);
4158 } else {
4159 pf_change_icmp(pd2.dst, &iih.icmp_id,
4160 saddr, &(*state)->gwy.addr,
4161 (*state)->gwy.port, NULL,
4162 pd2.ip_sum, icmpsum,
4163 pd->ip_sum, 0, AF_INET);
4164 }
4450 }
4451
4452 return (PF_PASS);
4453 break;
4454 }
4455#ifdef INET
4456 case IPPROTO_ICMP: {
4457 struct icmp iih;

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

4483 pd->ip_sum, 0, AF_INET);
4484 } else {
4485 pf_change_icmp(pd2.dst, &iih.icmp_id,
4486 saddr, &(*state)->gwy.addr,
4487 (*state)->gwy.port, NULL,
4488 pd2.ip_sum, icmpsum,
4489 pd->ip_sum, 0, AF_INET);
4490 }
4165 m_copyback(m, off, ICMP_MINLEN, pd->hdr.icmp);
4166 m_copyback(m, ipoff2, sizeof(h2), &h2);
4167 m_copyback(m, off2, ICMP_MINLEN, &iih);
4491 m_copyback(m, off, ICMP_MINLEN,
4492 (caddr_t)pd->hdr.icmp);
4493 m_copyback(m, ipoff2, sizeof(h2),
4494 (caddr_t)&h2);
4495 m_copyback(m, off2, ICMP_MINLEN,
4496 (caddr_t)&iih);
4168 }
4169
4170 return (PF_PASS);
4171 break;
4172 }
4173#endif /* INET */
4174#ifdef INET6
4175 case IPPROTO_ICMPV6: {

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

4203 } else {
4204 pf_change_icmp(pd2.dst, &iih.icmp6_id,
4205 saddr, &(*state)->gwy.addr,
4206 (*state)->gwy.port, NULL,
4207 pd2.ip_sum, icmpsum,
4208 pd->ip_sum, 0, AF_INET6);
4209 }
4210 m_copyback(m, off, sizeof(struct icmp6_hdr),
4497 }
4498
4499 return (PF_PASS);
4500 break;
4501 }
4502#endif /* INET */
4503#ifdef INET6
4504 case IPPROTO_ICMPV6: {

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

4532 } else {
4533 pf_change_icmp(pd2.dst, &iih.icmp6_id,
4534 saddr, &(*state)->gwy.addr,
4535 (*state)->gwy.port, NULL,
4536 pd2.ip_sum, icmpsum,
4537 pd->ip_sum, 0, AF_INET6);
4538 }
4539 m_copyback(m, off, sizeof(struct icmp6_hdr),
4211 pd->hdr.icmp6);
4212 m_copyback(m, ipoff2, sizeof(h2_6), &h2_6);
4540 (caddr_t)pd->hdr.icmp6);
4541 m_copyback(m, ipoff2, sizeof(h2_6),
4542 (caddr_t)&h2_6);
4213 m_copyback(m, off2, sizeof(struct icmp6_hdr),
4543 m_copyback(m, off2, sizeof(struct icmp6_hdr),
4214 &iih);
4544 (caddr_t)&iih);
4215 }
4216
4217 return (PF_PASS);
4218 break;
4219 }
4220#endif /* INET6 */
4221 default: {
4222 struct pf_tree_node key;

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

4243 0, NULL,
4244 pd2.ip_sum, icmpsum,
4245 pd->ip_sum, 0, pd2.af);
4246 }
4247 switch (pd2.af) {
4248#ifdef INET
4249 case AF_INET:
4250 m_copyback(m, off, ICMP_MINLEN,
4545 }
4546
4547 return (PF_PASS);
4548 break;
4549 }
4550#endif /* INET6 */
4551 default: {
4552 struct pf_tree_node key;

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

4573 0, NULL,
4574 pd2.ip_sum, icmpsum,
4575 pd->ip_sum, 0, pd2.af);
4576 }
4577 switch (pd2.af) {
4578#ifdef INET
4579 case AF_INET:
4580 m_copyback(m, off, ICMP_MINLEN,
4251 pd->hdr.icmp);
4252 m_copyback(m, ipoff2, sizeof(h2), &h2);
4581 (caddr_t)pd->hdr.icmp);
4582 m_copyback(m, ipoff2, sizeof(h2),
4583 (caddr_t)&h2);
4253 break;
4254#endif /* INET */
4255#ifdef INET6
4256 case AF_INET6:
4257 m_copyback(m, off,
4258 sizeof(struct icmp6_hdr),
4584 break;
4585#endif /* INET */
4586#ifdef INET6
4587 case AF_INET6:
4588 m_copyback(m, off,
4589 sizeof(struct icmp6_hdr),
4259 pd->hdr.icmp6);
4590 (caddr_t)pd->hdr.icmp6);
4260 m_copyback(m, ipoff2, sizeof(h2_6),
4591 m_copyback(m, ipoff2, sizeof(h2_6),
4261 &h2_6);
4592 (caddr_t)&h2_6);
4262 break;
4263#endif /* INET6 */
4264 }
4265 }
4266
4267 return (PF_PASS);
4268 break;
4269 }

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

4303
4304 /* update states */
4305 if (src->state < PFOTHERS_SINGLE)
4306 src->state = PFOTHERS_SINGLE;
4307 if (dst->state == PFOTHERS_SINGLE)
4308 dst->state = PFOTHERS_MULTIPLE;
4309
4310 /* update expire time */
4593 break;
4594#endif /* INET6 */
4595 }
4596 }
4597
4598 return (PF_PASS);
4599 break;
4600 }

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

4634
4635 /* update states */
4636 if (src->state < PFOTHERS_SINGLE)
4637 src->state = PFOTHERS_SINGLE;
4638 if (dst->state == PFOTHERS_SINGLE)
4639 dst->state = PFOTHERS_MULTIPLE;
4640
4641 /* update expire time */
4642#if defined(__FreeBSD__)
4643 (*state)->expire = time_second;
4644#else
4311 (*state)->expire = time.tv_sec;
4645 (*state)->expire = time.tv_sec;
4646#endif
4312 if (src->state == PFOTHERS_MULTIPLE && dst->state == PFOTHERS_MULTIPLE)
4313 (*state)->timeout = PFTM_OTHER_MULTIPLE;
4314 else
4315 (*state)->timeout = PFTM_OTHER_SINGLE;
4316
4317 /* translate source/destination address, if necessary */
4318 if (STATE_TRANSLATE(*state)) {
4319 if (direction == PF_OUT)

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

4418 struct route ro;
4419 int ret = 0;
4420
4421 bzero(&ro, sizeof(ro));
4422 dst = satosin(&ro.ro_dst);
4423 dst->sin_family = af;
4424 dst->sin_len = sizeof(*dst);
4425 dst->sin_addr = addr->v4;
4647 if (src->state == PFOTHERS_MULTIPLE && dst->state == PFOTHERS_MULTIPLE)
4648 (*state)->timeout = PFTM_OTHER_MULTIPLE;
4649 else
4650 (*state)->timeout = PFTM_OTHER_SINGLE;
4651
4652 /* translate source/destination address, if necessary */
4653 if (STATE_TRANSLATE(*state)) {
4654 if (direction == PF_OUT)

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

4753 struct route ro;
4754 int ret = 0;
4755
4756 bzero(&ro, sizeof(ro));
4757 dst = satosin(&ro.ro_dst);
4758 dst->sin_family = af;
4759 dst->sin_len = sizeof(*dst);
4760 dst->sin_addr = addr->v4;
4761#if defined(__FreeBSD__)
4762#ifdef RTF_PRCLONING
4763 rtalloc_ign(&ro, (RTF_CLONING|RTF_PRCLONING));
4764#else /* !RTF_PRCLONING */
4765 rtalloc_ign(&ro, RTF_CLONING);
4766#endif
4767#else /* ! __FreeBSD__ */
4426 rtalloc_noclone(&ro, NO_CLONING);
4768 rtalloc_noclone(&ro, NO_CLONING);
4769#endif
4427
4428 if (ro.ro_rt != NULL) {
4429 ret = 1;
4430 RTFREE(ro.ro_rt);
4431 }
4432
4433 return (ret);
4434}
4435
4436#ifdef INET
4770
4771 if (ro.ro_rt != NULL) {
4772 ret = 1;
4773 RTFREE(ro.ro_rt);
4774 }
4775
4776 return (ret);
4777}
4778
4779#ifdef INET
4780
4781#if defined(__FreeBSD__) && (__FreeBSD_version < 501105)
4782int
4783ip_fragment(struct ip *ip, struct mbuf **m_frag, int mtu,
4784 u_long if_hwassist_flags, int sw_csum)
4785{
4786 int error = 0;
4787 int hlen = ip->ip_hl << 2;
4788 int len = (mtu - hlen) & ~7; /* size of payload in each fragment */
4789 int off;
4790 struct mbuf *m0 = *m_frag; /* the original packet */
4791 int firstlen;
4792 struct mbuf **mnext;
4793 int nfrags;
4794
4795 if (ip->ip_off & IP_DF) { /* Fragmentation not allowed */
4796 ipstat.ips_cantfrag++;
4797 return EMSGSIZE;
4798 }
4799
4800 /*
4801 * Must be able to put at least 8 bytes per fragment.
4802 */
4803 if (len < 8)
4804 return EMSGSIZE;
4805
4806 /*
4807 * If the interface will not calculate checksums on
4808 * fragmented packets, then do it here.
4809 */
4810 if (m0->m_pkthdr.csum_flags & CSUM_DELAY_DATA &&
4811 (if_hwassist_flags & CSUM_IP_FRAGS) == 0) {
4812 in_delayed_cksum(m0);
4813 m0->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA;
4814 }
4815
4816 if (len > PAGE_SIZE) {
4817 /*
4818 * Fragment large datagrams such that each segment
4819 * contains a multiple of PAGE_SIZE amount of data,
4820 * plus headers. This enables a receiver to perform
4821 * page-flipping zero-copy optimizations.
4822 *
4823 * XXX When does this help given that sender and receiver
4824 * could have different page sizes, and also mtu could
4825 * be less than the receiver's page size ?
4826 */
4827 int newlen;
4828 struct mbuf *m;
4829
4830 for (m = m0, off = 0; m && (off+m->m_len) <= mtu; m = m->m_next)
4831 off += m->m_len;
4832
4833 /*
4834 * firstlen (off - hlen) must be aligned on an
4835 * 8-byte boundary
4836 */
4837 if (off < hlen)
4838 goto smart_frag_failure;
4839 off = ((off - hlen) & ~7) + hlen;
4840 newlen = (~PAGE_MASK) & mtu;
4841 if ((newlen + sizeof (struct ip)) > mtu) {
4842 /* we failed, go back the default */
4843smart_frag_failure:
4844 newlen = len;
4845 off = hlen + len;
4846 }
4847 len = newlen;
4848
4849 } else {
4850 off = hlen + len;
4851 }
4852
4853 firstlen = off - hlen;
4854 mnext = &m0->m_nextpkt; /* pointer to next packet */
4855
4856 /*
4857 * Loop through length of segment after first fragment,
4858 * make new header and copy data of each part and link onto chain.
4859 * Here, m0 is the original packet, m is the fragment being created.
4860 * The fragments are linked off the m_nextpkt of the original
4861 * packet, which after processing serves as the first fragment.
4862 */
4863 for (nfrags = 1; off < ip->ip_len; off += len, nfrags++) {
4864 struct ip *mhip; /* ip header on the fragment */
4865 struct mbuf *m;
4866 int mhlen = sizeof (struct ip);
4867
4868 MGETHDR(m, M_DONTWAIT, MT_HEADER);
4869 if (m == 0) {
4870 error = ENOBUFS;
4871 ipstat.ips_odropped++;
4872 goto done;
4873 }
4874 m->m_flags |= (m0->m_flags & M_MCAST) | M_FRAG;
4875 /*
4876 * In the first mbuf, leave room for the link header, then
4877 * copy the original IP header including options. The payload
4878 * goes into an additional mbuf chain returned by m_copy().
4879 */
4880 m->m_data += max_linkhdr;
4881 mhip = mtod(m, struct ip *);
4882 *mhip = *ip;
4883 if (hlen > sizeof (struct ip)) {
4884 mhlen = ip_optcopy(ip, mhip) + sizeof (struct ip);
4885 mhip->ip_v = IPVERSION;
4886 mhip->ip_hl = mhlen >> 2;
4887 }
4888 m->m_len = mhlen;
4889 /* XXX do we need to add ip->ip_off below ? */
4890 mhip->ip_off = ((off - hlen) >> 3) + ip->ip_off;
4891 if (off + len >= ip->ip_len) { /* last fragment */
4892 len = ip->ip_len - off;
4893 m->m_flags |= M_LASTFRAG;
4894 } else
4895 mhip->ip_off |= IP_MF;
4896 mhip->ip_len = htons((u_short)(len + mhlen));
4897 m->m_next = m_copy(m0, off, len);
4898 if (m->m_next == 0) { /* copy failed */
4899 m_free(m);
4900 error = ENOBUFS; /* ??? */
4901 ipstat.ips_odropped++;
4902 goto done;
4903 }
4904 m->m_pkthdr.len = mhlen + len;
4905 m->m_pkthdr.rcvif = (struct ifnet *)0;
4906#ifdef MAC
4907 mac_create_fragment(m0, m);
4908#endif
4909 m->m_pkthdr.csum_flags = m0->m_pkthdr.csum_flags;
4910 mhip->ip_off = htons(mhip->ip_off);
4911 mhip->ip_sum = 0;
4912 if (sw_csum & CSUM_DELAY_IP)
4913 mhip->ip_sum = in_cksum(m, mhlen);
4914 *mnext = m;
4915 mnext = &m->m_nextpkt;
4916 }
4917 ipstat.ips_ofragments += nfrags;
4918
4919 /* set first marker for fragment chain */
4920 m0->m_flags |= M_FIRSTFRAG | M_FRAG;
4921 m0->m_pkthdr.csum_data = nfrags;
4922
4923 /*
4924 * Update first fragment by trimming what's been copied out
4925 * and updating header.
4926 */
4927 m_adj(m0, hlen + firstlen - ip->ip_len);
4928 m0->m_pkthdr.len = hlen + firstlen;
4929 ip->ip_len = htons((u_short)m0->m_pkthdr.len);
4930 ip->ip_off |= IP_MF;
4931 ip->ip_off = htons(ip->ip_off);
4932 ip->ip_sum = 0;
4933 if (sw_csum & CSUM_DELAY_IP)
4934 ip->ip_sum = in_cksum(m0, hlen);
4935
4936done:
4937 *m_frag = m0;
4938 return error;
4939}
4940#endif /* __FreeBSD__ && __FreeBSD_version > 501105 */
4941
4437void
4438pf_route(struct mbuf **m, struct pf_rule *r, int dir, struct ifnet *oifp,
4439 struct pf_state *s)
4440{
4441 struct mbuf *m0, *m1;
4442 struct route iproute;
4443 struct route *ro;
4444 struct sockaddr_in *dst;
4445 struct ip *ip;
4446 struct ifnet *ifp = NULL;
4447 struct m_tag *mtag;
4448 struct pf_addr naddr;
4449 int error = 0;
4942void
4943pf_route(struct mbuf **m, struct pf_rule *r, int dir, struct ifnet *oifp,
4944 struct pf_state *s)
4945{
4946 struct mbuf *m0, *m1;
4947 struct route iproute;
4948 struct route *ro;
4949 struct sockaddr_in *dst;
4950 struct ip *ip;
4951 struct ifnet *ifp = NULL;
4952 struct m_tag *mtag;
4953 struct pf_addr naddr;
4954 int error = 0;
4955#if defined(__FreeBSD__)
4956 int sw_csum;
4957#endif
4450
4451 if (m == NULL || *m == NULL || r == NULL ||
4452 (dir != PF_IN && dir != PF_OUT) || oifp == NULL)
4453 panic("pf_route: invalid parameters");
4454
4455 if (r->rt == PF_DUPTO) {
4456 m0 = *m;
4457 mtag = m_tag_find(m0, PACKET_TAG_PF_ROUTED, NULL);
4458 if (mtag == NULL) {
4459 mtag = m_tag_get(PACKET_TAG_PF_ROUTED, 0, M_NOWAIT);
4460 if (mtag == NULL)
4461 goto bad;
4462 m_tag_prepend(m0, mtag);
4463 }
4958
4959 if (m == NULL || *m == NULL || r == NULL ||
4960 (dir != PF_IN && dir != PF_OUT) || oifp == NULL)
4961 panic("pf_route: invalid parameters");
4962
4963 if (r->rt == PF_DUPTO) {
4964 m0 = *m;
4965 mtag = m_tag_find(m0, PACKET_TAG_PF_ROUTED, NULL);
4966 if (mtag == NULL) {
4967 mtag = m_tag_get(PACKET_TAG_PF_ROUTED, 0, M_NOWAIT);
4968 if (mtag == NULL)
4969 goto bad;
4970 m_tag_prepend(m0, mtag);
4971 }
4972#if defined(__FreeBSD__)
4973 m0 = m_dup(*m, M_DONTWAIT);
4974#else
4464 m0 = m_copym2(*m, 0, M_COPYALL, M_NOWAIT);
4975 m0 = m_copym2(*m, 0, M_COPYALL, M_NOWAIT);
4976#endif
4465 if (m0 == NULL)
4466 return;
4467 } else {
4468 if ((r->rt == PF_REPLYTO) == (r->direction == dir))
4469 return;
4470 m0 = *m;
4471 }
4472

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

4520
4521 mtag = m_tag_get(PACKET_TAG_PF_ROUTED, 0, M_NOWAIT);
4522 if (mtag == NULL)
4523 goto bad;
4524 m_tag_prepend(m0, mtag);
4525 }
4526
4527 if (oifp != ifp && mtag == NULL) {
4977 if (m0 == NULL)
4978 return;
4979 } else {
4980 if ((r->rt == PF_REPLYTO) == (r->direction == dir))
4981 return;
4982 m0 = *m;
4983 }
4984

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

5032
5033 mtag = m_tag_get(PACKET_TAG_PF_ROUTED, 0, M_NOWAIT);
5034 if (mtag == NULL)
5035 goto bad;
5036 m_tag_prepend(m0, mtag);
5037 }
5038
5039 if (oifp != ifp && mtag == NULL) {
5040#if defined(__FreeBSD__)
5041 PF_UNLOCK();
5042 if (pf_test(PF_OUT, ifp, &m0) != PF_PASS) {
5043 PF_LOCK();
5044 goto bad;
5045 } else if (m0 == NULL) {
5046 PF_LOCK();
5047 goto done;
5048 }
5049 PF_LOCK();
5050#else
4528 if (pf_test(PF_OUT, ifp, &m0) != PF_PASS)
4529 goto bad;
4530 else if (m0 == NULL)
4531 goto done;
5051 if (pf_test(PF_OUT, ifp, &m0) != PF_PASS)
5052 goto bad;
5053 else if (m0 == NULL)
5054 goto done;
5055#endif
4532 if (m0->m_len < sizeof(struct ip))
4533 panic("pf_route: m0->m_len < sizeof(struct ip)");
4534 ip = mtod(m0, struct ip *);
4535 }
4536
5056 if (m0->m_len < sizeof(struct ip))
5057 panic("pf_route: m0->m_len < sizeof(struct ip)");
5058 ip = mtod(m0, struct ip *);
5059 }
5060
5061#if defined(__FreeBSD__)
5062 /* Copied from FreeBSD 5.1-CURRENT ip_output. */
5063 m0->m_pkthdr.csum_flags |= CSUM_IP;
5064 sw_csum = m0->m_pkthdr.csum_flags & ~ifp->if_hwassist;
5065 if (sw_csum & CSUM_DELAY_DATA) {
5066 /*
5067 * XXX: in_delayed_cksum assumes HBO for ip->ip_len (at least)
5068 */
5069 NTOHS(ip->ip_len);
5070 NTOHS(ip->ip_off); /* XXX: needed? */
5071 in_delayed_cksum(m0);
5072 HTONS(ip->ip_len);
5073 HTONS(ip->ip_off);
5074 sw_csum &= ~CSUM_DELAY_DATA;
5075 }
5076 m0->m_pkthdr.csum_flags &= ifp->if_hwassist;
5077
5078 if (ntohs(ip->ip_len) <= ifp->if_mtu ||
5079 (ifp->if_hwassist & CSUM_FRAGMENT &&
5080 ((ip->ip_off & htons(IP_DF)) == 0))) {
5081 /*
5082 * ip->ip_len = htons(ip->ip_len);
5083 * ip->ip_off = htons(ip->ip_off);
5084 */
5085 ip->ip_sum = 0;
5086 if (sw_csum & CSUM_DELAY_IP) {
5087 /* From KAME */
5088 if (ip->ip_v == IPVERSION &&
5089 (ip->ip_hl << 2) == sizeof(*ip)) {
5090 ip->ip_sum = in_cksum_hdr(ip);
5091 } else {
5092 ip->ip_sum = in_cksum(m0, ip->ip_hl << 2);
5093 }
5094 }
5095 PF_UNLOCK();
5096 error = (*ifp->if_output)(ifp, m0, sintosa(dst), ro->ro_rt);
5097 PF_LOCK();
5098 goto done;
5099 }
5100
5101#else
4537 /* Copied from ip_output. */
4538 if (ntohs(ip->ip_len) <= ifp->if_mtu) {
4539 if ((ifp->if_capabilities & IFCAP_CSUM_IPv4) &&
4540 ifp->if_bridge == NULL) {
4541 m0->m_pkthdr.csum |= M_IPV4_CSUM_OUT;
4542 ipstat.ips_outhwcsum++;
4543 } else {
4544 ip->ip_sum = 0;
4545 ip->ip_sum = in_cksum(m0, ip->ip_hl << 2);
4546 }
4547 /* Update relevant hardware checksum stats for TCP/UDP */
4548 if (m0->m_pkthdr.csum & M_TCPV4_CSUM_OUT)
4549 tcpstat.tcps_outhwcsum++;
4550 else if (m0->m_pkthdr.csum & M_UDPV4_CSUM_OUT)
4551 udpstat.udps_outhwcsum++;
4552 error = (*ifp->if_output)(ifp, m0, sintosa(dst), NULL);
4553 goto done;
4554 }
5102 /* Copied from ip_output. */
5103 if (ntohs(ip->ip_len) <= ifp->if_mtu) {
5104 if ((ifp->if_capabilities & IFCAP_CSUM_IPv4) &&
5105 ifp->if_bridge == NULL) {
5106 m0->m_pkthdr.csum |= M_IPV4_CSUM_OUT;
5107 ipstat.ips_outhwcsum++;
5108 } else {
5109 ip->ip_sum = 0;
5110 ip->ip_sum = in_cksum(m0, ip->ip_hl << 2);
5111 }
5112 /* Update relevant hardware checksum stats for TCP/UDP */
5113 if (m0->m_pkthdr.csum & M_TCPV4_CSUM_OUT)
5114 tcpstat.tcps_outhwcsum++;
5115 else if (m0->m_pkthdr.csum & M_UDPV4_CSUM_OUT)
5116 udpstat.udps_outhwcsum++;
5117 error = (*ifp->if_output)(ifp, m0, sintosa(dst), NULL);
5118 goto done;
5119 }
4555
5120#endif
4556 /*
4557 * Too large for interface; fragment if possible.
4558 * Must be able to put at least 8 bytes per fragment.
4559 */
4560 if (ip->ip_off & htons(IP_DF)) {
4561 ipstat.ips_cantfrag++;
4562 if (r->rt != PF_DUPTO) {
5121 /*
5122 * Too large for interface; fragment if possible.
5123 * Must be able to put at least 8 bytes per fragment.
5124 */
5125 if (ip->ip_off & htons(IP_DF)) {
5126 ipstat.ips_cantfrag++;
5127 if (r->rt != PF_DUPTO) {
5128#if defined(__FreeBSD__)
5129 /* icmp_error() expects host byte ordering */
5130 NTOHS(ip->ip_len);
5131 NTOHS(ip->ip_off);
5132 PF_UNLOCK();
5133#endif
4563 icmp_error(m0, ICMP_UNREACH, ICMP_UNREACH_NEEDFRAG, 0,
4564 ifp);
5134 icmp_error(m0, ICMP_UNREACH, ICMP_UNREACH_NEEDFRAG, 0,
5135 ifp);
5136#if defined(__FreeBSD__)
5137 PF_LOCK();
5138#endif
4565 goto done;
4566 } else
4567 goto bad;
4568 }
4569
4570 m1 = m0;
5139 goto done;
5140 } else
5141 goto bad;
5142 }
5143
5144 m1 = m0;
5145#if defined(__FreeBSD__)
5146 /*
5147 * XXX: is cheaper + less error prone than own function
5148 */
5149 NTOHS(ip->ip_len);
5150 NTOHS(ip->ip_off);
5151 error = ip_fragment(ip, &m0, ifp->if_mtu, ifp->if_hwassist, sw_csum);
5152#else
4571 error = ip_fragment(m0, ifp, ifp->if_mtu);
5153 error = ip_fragment(m0, ifp, ifp->if_mtu);
5154#endif
5155#if defined(__FreeBSD__)
5156 if (error)
5157#else
4572 if (error == EMSGSIZE)
5158 if (error == EMSGSIZE)
5159#endif
4573 goto bad;
4574
4575 for (m0 = m1; m0; m0 = m1) {
4576 m1 = m0->m_nextpkt;
4577 m0->m_nextpkt = 0;
5160 goto bad;
5161
5162 for (m0 = m1; m0; m0 = m1) {
5163 m1 = m0->m_nextpkt;
5164 m0->m_nextpkt = 0;
5165#if defined(__FreeBSD__)
5166 if (error == 0) {
5167 PF_UNLOCK();
5168 error = (*ifp->if_output)(ifp, m0, sintosa(dst),
5169 NULL);
5170 PF_LOCK();
5171 } else
5172#else
4578 if (error == 0)
4579 error = (*ifp->if_output)(ifp, m0, sintosa(dst),
4580 NULL);
4581 else
5173 if (error == 0)
5174 error = (*ifp->if_output)(ifp, m0, sintosa(dst),
5175 NULL);
5176 else
5177#endif
4582 m_freem(m0);
4583 }
4584
4585 if (error == 0)
4586 ipstat.ips_fragmented++;
4587
4588done:
4589 if (r->rt != PF_DUPTO)

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

4621 m0 = *m;
4622 mtag = m_tag_find(m0, PACKET_TAG_PF_ROUTED, NULL);
4623 if (mtag == NULL) {
4624 mtag = m_tag_get(PACKET_TAG_PF_ROUTED, 0, M_NOWAIT);
4625 if (mtag == NULL)
4626 goto bad;
4627 m_tag_prepend(m0, mtag);
4628 }
5178 m_freem(m0);
5179 }
5180
5181 if (error == 0)
5182 ipstat.ips_fragmented++;
5183
5184done:
5185 if (r->rt != PF_DUPTO)

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

5217 m0 = *m;
5218 mtag = m_tag_find(m0, PACKET_TAG_PF_ROUTED, NULL);
5219 if (mtag == NULL) {
5220 mtag = m_tag_get(PACKET_TAG_PF_ROUTED, 0, M_NOWAIT);
5221 if (mtag == NULL)
5222 goto bad;
5223 m_tag_prepend(m0, mtag);
5224 }
5225#if defined(__FreeBSD__)
5226 m0 = m_dup(*m, M_DONTWAIT);
5227#else
4629 m0 = m_copym2(*m, 0, M_COPYALL, M_NOWAIT);
5228 m0 = m_copym2(*m, 0, M_COPYALL, M_NOWAIT);
5229#endif
4630 if (m0 == NULL)
4631 return;
4632 } else {
4633 if ((r->rt == PF_REPLYTO) == (r->direction == dir))
4634 return;
4635 m0 = *m;
4636 }
4637

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

4647 dst->sin6_addr = ip6->ip6_dst;
4648
4649 /* Cheat. */
4650 if (r->rt == PF_FASTROUTE) {
4651 mtag = m_tag_get(PACKET_TAG_PF_GENERATED, 0, M_NOWAIT);
4652 if (mtag == NULL)
4653 goto bad;
4654 m_tag_prepend(m0, mtag);
5230 if (m0 == NULL)
5231 return;
5232 } else {
5233 if ((r->rt == PF_REPLYTO) == (r->direction == dir))
5234 return;
5235 m0 = *m;
5236 }
5237

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

5247 dst->sin6_addr = ip6->ip6_dst;
5248
5249 /* Cheat. */
5250 if (r->rt == PF_FASTROUTE) {
5251 mtag = m_tag_get(PACKET_TAG_PF_GENERATED, 0, M_NOWAIT);
5252 if (mtag == NULL)
5253 goto bad;
5254 m_tag_prepend(m0, mtag);
5255#if defined(__FreeBSD__)
5256 PF_UNLOCK();
5257 ip6_output(m0, NULL, NULL, 0, NULL, NULL, NULL);
5258 PF_LOCK();
5259#else
4655 ip6_output(m0, NULL, NULL, 0, NULL, NULL);
5260 ip6_output(m0, NULL, NULL, 0, NULL, NULL);
5261#endif
4656 return;
4657 }
4658
4659 if (TAILQ_EMPTY(&r->rpool.list))
4660 panic("pf_route6: TAILQ_EMPTY(&r->rpool.list)");
4661 if (s == NULL) {
4662 pf_map_addr(AF_INET6, &r->rpool,
4663 (struct pf_addr *)&ip6->ip6_src, &naddr, NULL);

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

4677
4678 if (oifp != ifp) {
4679 mtag = m_tag_find(m0, PACKET_TAG_PF_ROUTED, NULL);
4680 if (mtag == NULL) {
4681 mtag = m_tag_get(PACKET_TAG_PF_ROUTED, 0, M_NOWAIT);
4682 if (mtag == NULL)
4683 goto bad;
4684 m_tag_prepend(m0, mtag);
5262 return;
5263 }
5264
5265 if (TAILQ_EMPTY(&r->rpool.list))
5266 panic("pf_route6: TAILQ_EMPTY(&r->rpool.list)");
5267 if (s == NULL) {
5268 pf_map_addr(AF_INET6, &r->rpool,
5269 (struct pf_addr *)&ip6->ip6_src, &naddr, NULL);

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

5283
5284 if (oifp != ifp) {
5285 mtag = m_tag_find(m0, PACKET_TAG_PF_ROUTED, NULL);
5286 if (mtag == NULL) {
5287 mtag = m_tag_get(PACKET_TAG_PF_ROUTED, 0, M_NOWAIT);
5288 if (mtag == NULL)
5289 goto bad;
5290 m_tag_prepend(m0, mtag);
5291#if defined(__FreeBSD__)
5292 PF_UNLOCK();
5293 if (pf_test6(PF_OUT, ifp, &m0) != PF_PASS) {
5294 PF_LOCK();
5295 goto bad;
5296 } else if (m0 == NULL) {
5297 PF_LOCK();
5298 goto done;
5299 }
5300 PF_LOCK();
5301#else
4685 if (pf_test6(PF_OUT, ifp, &m0) != PF_PASS)
4686 goto bad;
4687 else if (m0 == NULL)
4688 goto done;
5302 if (pf_test6(PF_OUT, ifp, &m0) != PF_PASS)
5303 goto bad;
5304 else if (m0 == NULL)
5305 goto done;
5306#endif
4689 }
4690 }
4691
4692 /*
4693 * If the packet is too large for the outgoing interface,
4694 * send back an icmp6 error.
4695 */
4696 if (IN6_IS_ADDR_LINKLOCAL(&dst->sin6_addr))
4697 dst->sin6_addr.s6_addr16[1] = htons(ifp->if_index);
4698 if ((u_long)m0->m_pkthdr.len <= ifp->if_mtu) {
5307 }
5308 }
5309
5310 /*
5311 * If the packet is too large for the outgoing interface,
5312 * send back an icmp6 error.
5313 */
5314 if (IN6_IS_ADDR_LINKLOCAL(&dst->sin6_addr))
5315 dst->sin6_addr.s6_addr16[1] = htons(ifp->if_index);
5316 if ((u_long)m0->m_pkthdr.len <= ifp->if_mtu) {
5317#if defined(__FreeBSD__)
5318 PF_UNLOCK();
5319#endif
4699 error = nd6_output(ifp, ifp, m0, dst, NULL);
5320 error = nd6_output(ifp, ifp, m0, dst, NULL);
5321#if defined(__FreeBSD__)
5322 PF_LOCK();
5323#endif
4700 } else {
4701 in6_ifstat_inc(ifp, ifs6_in_toobig);
5324 } else {
5325 in6_ifstat_inc(ifp, ifs6_in_toobig);
5326#if defined(__FreeBSD__)
5327 if (r->rt != PF_DUPTO) {
5328 PF_UNLOCK();
5329 icmp6_error(m0, ICMP6_PACKET_TOO_BIG, 0, ifp->if_mtu);
5330 PF_LOCK();
5331 } else
5332#else
4702 if (r->rt != PF_DUPTO)
4703 icmp6_error(m0, ICMP6_PACKET_TOO_BIG, 0, ifp->if_mtu);
4704 else
5333 if (r->rt != PF_DUPTO)
5334 icmp6_error(m0, ICMP6_PACKET_TOO_BIG, 0, ifp->if_mtu);
5335 else
5336#endif
4705 goto bad;
4706 }
4707
4708done:
4709 if (r->rt != PF_DUPTO)
4710 *m = NULL;
4711 return;
4712
4713bad:
4714 m_freem(m0);
4715 goto done;
4716}
4717#endif /* INET6 */
4718
4719
5337 goto bad;
5338 }
5339
5340done:
5341 if (r->rt != PF_DUPTO)
5342 *m = NULL;
5343 return;
5344
5345bad:
5346 m_freem(m0);
5347 goto done;
5348}
5349#endif /* INET6 */
5350
5351
5352#if defined(__FreeBSD__)
4720/*
5353/*
5354 * XXX
5355 * FreeBSD supports cksum offload for the following drivers.
5356 * em(4), gx(4), lge(4), nge(4), ti(4), xl(4)
5357 * If we can make full use of it we would outperform ipfw/ipfilter in
5358 * very heavy traffic.
5359 * I have not tested 'cause I don't have NICs that supports cksum offload.
5360 * (There might be problems. Typical phenomena would be
5361 * 1. No route message for UDP packet.
5362 * 2. No connection acceptance from external hosts regardless of rule set.)
5363 */
5364int
5365pf_check_proto_cksum(struct mbuf *m, int off, int len, u_int8_t p, sa_family_t af)
5366{
5367 u_int16_t sum = 0;
5368 int hw_assist = 0;
5369 struct ip *ip;
5370
5371 if (off < sizeof(struct ip) || len < sizeof(struct udphdr))
5372 return (1);
5373 if (m->m_pkthdr.len < off + len)
5374 return (1);
5375
5376 switch (p) {
5377 case IPPROTO_TCP:
5378 if (m->m_pkthdr.csum_flags & CSUM_DATA_VALID) {
5379 if (m->m_pkthdr.csum_flags & CSUM_PSEUDO_HDR) {
5380 sum = m->m_pkthdr.csum_data;
5381 } else {
5382 ip = mtod(m, struct ip *);
5383 sum = in_pseudo(ip->ip_src.s_addr,
5384 ip->ip_dst.s_addr,
5385 htonl(m->m_pkthdr.csum_data +
5386 IPPROTO_TCP) + ip->ip_len);
5387 }
5388 sum ^= 0xffff;
5389 ++hw_assist;
5390 }
5391 break;
5392 case IPPROTO_UDP:
5393 if (m->m_pkthdr.csum_flags & CSUM_DATA_VALID) {
5394 if (m->m_pkthdr.csum_flags & CSUM_PSEUDO_HDR) {
5395 sum = m->m_pkthdr.csum_data;
5396 } else {
5397 ip = mtod(m, struct ip *);
5398 sum = in_pseudo(ip->ip_src.s_addr,
5399 ip->ip_dst.s_addr, htonl((u_short)len +
5400 m->m_pkthdr.csum_data + IPPROTO_UDP));
5401 }
5402 sum ^= 0xffff;
5403 ++hw_assist;
5404 }
5405 break;
5406 case IPPROTO_ICMP:
5407#ifdef INET6
5408 case IPPROTO_ICMPV6:
5409#endif /* INET6 */
5410 break;
5411 default:
5412 return (1);
5413 }
5414
5415 if (!hw_assist) {
5416 switch (af) {
5417 case AF_INET:
5418 if (p == IPPROTO_ICMP) {
5419 if (m->m_len < off)
5420 return (1);
5421 m->m_data += off;
5422 m->m_len -= off;
5423 sum = in_cksum(m, len);
5424 m->m_data -= off;
5425 m->m_len += off;
5426 } else {
5427 if (m->m_len < sizeof(struct ip))
5428 return (1);
5429 sum = in4_cksum(m, p, off, len);
5430 if (sum == 0) {
5431 m->m_pkthdr.csum_flags |=
5432 (CSUM_DATA_VALID |
5433 CSUM_PSEUDO_HDR);
5434 m->m_pkthdr.csum_data = 0xffff;
5435 }
5436 }
5437 break;
5438#ifdef INET6
5439 case AF_INET6:
5440 if (m->m_len < sizeof(struct ip6_hdr))
5441 return (1);
5442 sum = in6_cksum(m, p, off, len);
5443 /*
5444 * XXX
5445 * IPv6 H/W cksum off-load not supported yet!
5446 *
5447 * if (sum == 0) {
5448 * m->m_pkthdr.csum_flags |=
5449 * (CSUM_DATA_VALID|CSUM_PSEUDO_HDR);
5450 * m->m_pkthdr.csum_data = 0xffff;
5451 *}
5452 */
5453 break;
5454#endif /* INET6 */
5455 default:
5456 return (1);
5457 }
5458 }
5459 if (sum) {
5460 switch (p) {
5461 case IPPROTO_TCP:
5462 tcpstat.tcps_rcvbadsum++;
5463 break;
5464 case IPPROTO_UDP:
5465 udpstat.udps_badsum++;
5466 break;
5467 case IPPROTO_ICMP:
5468 icmpstat.icps_checksum++;
5469 break;
5470#ifdef INET6
5471 case IPPROTO_ICMPV6:
5472 icmp6stat.icp6s_checksum++;
5473 break;
5474#endif /* INET6 */
5475 }
5476 return (1);
5477 }
5478 return (0);
5479}
5480#else
5481/*
4721 * check protocol (tcp/udp/icmp/icmp6) checksum and set mbuf flag
4722 * off is the offset where the protocol header starts
4723 * len is the total length of protocol header plus payload
4724 * returns 0 when the checksum is valid, otherwise returns 1.
4725 */
4726int
4727pf_check_proto_cksum(struct mbuf *m, int off, int len, u_int8_t p, sa_family_t af)
4728{

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

4799 break;
4800#endif /* INET6 */
4801 }
4802 return (1);
4803 }
4804 m->m_pkthdr.csum |= flag_ok;
4805 return (0);
4806}
5482 * check protocol (tcp/udp/icmp/icmp6) checksum and set mbuf flag
5483 * off is the offset where the protocol header starts
5484 * len is the total length of protocol header plus payload
5485 * returns 0 when the checksum is valid, otherwise returns 1.
5486 */
5487int
5488pf_check_proto_cksum(struct mbuf *m, int off, int len, u_int8_t p, sa_family_t af)
5489{

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

5560 break;
5561#endif /* INET6 */
5562 }
5563 return (1);
5564 }
5565 m->m_pkthdr.csum |= flag_ok;
5566 return (0);
5567}
5568#endif
4807
4808#ifdef INET
4809int
4810pf_test(int dir, struct ifnet *ifp, struct mbuf **m0)
4811{
4812 u_short action, reason = 0, log = 0;
4813 struct mbuf *m = *m0;
4814 struct ip *h;
4815 struct pf_rule *a = NULL, *r = &pf_default_rule, *tr;
4816 struct pf_state *s = NULL;
4817 struct pf_ruleset *ruleset = NULL;
4818 struct pf_pdesc pd;
4819 int off;
4820 int pqid = 0;
4821
5569
5570#ifdef INET
5571int
5572pf_test(int dir, struct ifnet *ifp, struct mbuf **m0)
5573{
5574 u_short action, reason = 0, log = 0;
5575 struct mbuf *m = *m0;
5576 struct ip *h;
5577 struct pf_rule *a = NULL, *r = &pf_default_rule, *tr;
5578 struct pf_state *s = NULL;
5579 struct pf_ruleset *ruleset = NULL;
5580 struct pf_pdesc pd;
5581 int off;
5582 int pqid = 0;
5583
5584#if defined(__FreeBSD__)
5585 PF_LOCK();
5586#endif
4822 if (!pf_status.running ||
5587 if (!pf_status.running ||
4823 (m_tag_find(m, PACKET_TAG_PF_GENERATED, NULL) != NULL))
4824 return (PF_PASS);
5588 (m_tag_find(m, PACKET_TAG_PF_GENERATED, NULL) != NULL)) {
5589#if defined(__FreeBSD__)
5590 PF_UNLOCK();
5591#endif
5592 return (PF_PASS);
5593 }
4825
5594
5595#if defined(__FreeBSD__) && (__FreeBSD_version >= 501000)
5596 M_ASSERTPKTHDR(m);
5597#else
4826#ifdef DIAGNOSTIC
4827 if ((m->m_flags & M_PKTHDR) == 0)
4828 panic("non-M_PKTHDR is passed to pf_test");
4829#endif
5598#ifdef DIAGNOSTIC
5599 if ((m->m_flags & M_PKTHDR) == 0)
5600 panic("non-M_PKTHDR is passed to pf_test");
5601#endif
5602#endif
4830
4831 if (m->m_pkthdr.len < (int)sizeof(*h)) {
4832 action = PF_DROP;
4833 REASON_SET(&reason, PFRES_SHORT);
4834 log = 1;
4835 goto done;
4836 }
4837

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

5023 if (action == PF_SYNPROXY_DROP) {
5024 m_freem(*m0);
5025 *m0 = NULL;
5026 action = PF_PASS;
5027 } else if (r->rt)
5028 /* pf_route can free the mbuf causing *m0 to become NULL */
5029 pf_route(m0, r, dir, ifp, s);
5030
5603
5604 if (m->m_pkthdr.len < (int)sizeof(*h)) {
5605 action = PF_DROP;
5606 REASON_SET(&reason, PFRES_SHORT);
5607 log = 1;
5608 goto done;
5609 }
5610

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

5796 if (action == PF_SYNPROXY_DROP) {
5797 m_freem(*m0);
5798 *m0 = NULL;
5799 action = PF_PASS;
5800 } else if (r->rt)
5801 /* pf_route can free the mbuf causing *m0 to become NULL */
5802 pf_route(m0, r, dir, ifp, s);
5803
5804#if defined(__FreeBSD__)
5805 PF_UNLOCK();
5806#endif
5807
5031 return (action);
5032}
5033#endif /* INET */
5034
5035#ifdef INET6
5036int
5037pf_test6(int dir, struct ifnet *ifp, struct mbuf **m0)
5038{
5039 u_short action, reason = 0, log = 0;
5040 struct mbuf *m = *m0;
5041 struct ip6_hdr *h;
5042 struct pf_rule *a = NULL, *r = &pf_default_rule, *tr;
5043 struct pf_state *s = NULL;
5044 struct pf_ruleset *ruleset = NULL;
5045 struct pf_pdesc pd;
5046 int off, terminal = 0;
5047
5808 return (action);
5809}
5810#endif /* INET */
5811
5812#ifdef INET6
5813int
5814pf_test6(int dir, struct ifnet *ifp, struct mbuf **m0)
5815{
5816 u_short action, reason = 0, log = 0;
5817 struct mbuf *m = *m0;
5818 struct ip6_hdr *h;
5819 struct pf_rule *a = NULL, *r = &pf_default_rule, *tr;
5820 struct pf_state *s = NULL;
5821 struct pf_ruleset *ruleset = NULL;
5822 struct pf_pdesc pd;
5823 int off, terminal = 0;
5824
5825#if defined(__FreeBSD__)
5826 PF_LOCK();
5827#endif
5828
5048 if (!pf_status.running ||
5829 if (!pf_status.running ||
5049 (m_tag_find(m, PACKET_TAG_PF_GENERATED, NULL) != NULL))
5830 (m_tag_find(m, PACKET_TAG_PF_GENERATED, NULL) != NULL)) {
5831#if defined(__FreeBSD__)
5832 PF_UNLOCK();
5833#endif
5050 return (PF_PASS);
5834 return (PF_PASS);
5835 }
5051
5836
5837#if defined(__FreeBSD__) && (__FreeBSD_version >= 501000)
5838 M_ASSERTPKTHDR(m);
5839#else
5052#ifdef DIAGNOSTIC
5053 if ((m->m_flags & M_PKTHDR) == 0)
5054 panic("non-M_PKTHDR is passed to pf_test");
5055#endif
5840#ifdef DIAGNOSTIC
5841 if ((m->m_flags & M_PKTHDR) == 0)
5842 panic("non-M_PKTHDR is passed to pf_test");
5843#endif
5844#endif
5056
5057 if (m->m_pkthdr.len < (int)sizeof(*h)) {
5058 action = PF_DROP;
5059 REASON_SET(&reason, PFRES_SHORT);
5060 log = 1;
5061 goto done;
5062 }
5063

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

5253 if (action == PF_SYNPROXY_DROP) {
5254 m_freem(*m0);
5255 *m0 = NULL;
5256 action = PF_PASS;
5257 } else if (r->rt)
5258 /* pf_route6 can free the mbuf causing *m0 to become NULL */
5259 pf_route6(m0, r, dir, ifp, s);
5260
5845
5846 if (m->m_pkthdr.len < (int)sizeof(*h)) {
5847 action = PF_DROP;
5848 REASON_SET(&reason, PFRES_SHORT);
5849 log = 1;
5850 goto done;
5851 }
5852

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

6042 if (action == PF_SYNPROXY_DROP) {
6043 m_freem(*m0);
6044 *m0 = NULL;
6045 action = PF_PASS;
6046 } else if (r->rt)
6047 /* pf_route6 can free the mbuf causing *m0 to become NULL */
6048 pf_route6(m0, r, dir, ifp, s);
6049
6050#if defined(__FreeBSD__)
6051 PF_UNLOCK();
6052#endif
5261 return (action);
5262}
5263#endif /* INET6 */
6053 return (action);
6054}
6055#endif /* INET6 */