Deleted Added
full compact
0a1
> /* $FreeBSD: head/sys/contrib/pf/net/pf.c 126261 2004-02-26 02:34:12Z mlaier $ */
36a38,49
> #if defined(__FreeBSD__)
> #include "opt_inet.h"
> #include "opt_inet6.h"
> #endif
>
> #if defined(__FreeBSD__) && __FreeBSD__ >= 5
> #include "opt_bpf.h"
> #define NBPFILTER DEV_BPF
> #include "opt_pf.h"
> #define NPFLOG DEV_PFLOG
> #define NPFSYNC DEV_PFSYNC
> #else
39a53
> #endif
48a63,65
> #if defined(__FreeBSD__)
> #include <sys/sysctl.h>
> #else
49a67
> #endif
70a89
> #if !defined(__FreeBSD__)
71a91
> #endif
80a101,104
> #if defined(__FreeBSD__)
> #include <netinet6/ip6_var.h>
> #include <netinet6/in6_pcb.h>
> #endif
86a111,119
> #if defined(__FreeBSD__)
> #include <machine/in_cksum.h>
> #if (__FreeBSD_version >= 500112)
> #include <sys/limits.h>
> #else
> #include <machine/limits.h>
> #endif
> #include <sys/ucred.h>
> #endif
87a121,128
> #if defined(__FreeBSD__)
> extern int ip_optcopy(struct ip *, struct ip *);
> #if (__FreeBSD_version < 501105)
> int ip_fragment(struct ip *ip, struct mbuf **m_frag, int mtu,
> u_long if_hwassist_flags, int sw_csum);
> #endif
> #endif
>
107a149,151
> #if defined(__FreeBSD__)
> struct callout pf_expire_to; /* expire timeout */
> #else
108a153
> #endif
109a155,159
>
> #if defined(__FreeBSD__)
> uma_zone_t pf_tree_pl, pf_rule_pl, pf_addr_pl;
> uma_zone_t pf_state_pl, pf_altq_pl, pf_pooladdr_pl;
> #else
111a162
> #endif
113a165,167
> #if defined(__FreeBSD__) && defined(HOOK_HACK)
> void pf_dynaddr_update_event(void *arg, struct ifnet *ifp);
> #endif
207a262,264
> #if defined(__FreeBSD__)
> int in4_cksum(struct mbuf *m, u_int8_t nxt, int off, int len);
> #endif
208a266,268
> #if defined(__FreeBSD__)
> struct pf_pool_limit pf_pool_limits[PF_LIMIT_MAX];
> #else
210a271
> #endif
425a487,489
> #if defined(__FreeBSD__)
> struct callout *to = arg;
> #else
426a491
> #endif
428a494,496
> #if defined(__FreeBSD__)
> PF_LOCK();
> #endif
432a501,503
> #if defined(__FreeBSD__)
> PF_UNLOCK();
> #endif
433a505,508
> #if defined(__FreeBSD__)
> callout_reset(to, pf_default_rule.timeout[PFTM_INTERVAL] * hz,
> pf_purge_timeout, to);
> #else
434a510
> #endif
446a523,525
> #if defined(__FreeBSD__)
> return (time_second);
> #else
447a527
> #endif
449a530,533
> #if defined(__FreeBSD__)
> KASSERT((state->timeout < PFTM_MAX),
> ("pf_state_expires: timeout > PFTM_MAX"));
> #else
450a535
> #endif
467a553,555
> #if defined(__FreeBSD__)
> return (time_second);
> #else
468a557
> #endif
481a571,573
> #if defined(__FreeBSD__)
> if (pf_state_expires(cur->state) <= (u_int32_t)time_second) {
> #else
482a575
> #endif
507a601,605
> #if defined(__FreeBSD__)
> KASSERT((peer), ("peer null :%s", __FUNCTION__));
> KASSERT((peer->state == cur->state),
> ("peer->state != cur->state: %s", __FUNCTION__));
> #else
509a608
> #endif
585a685
> #if !defined(__FreeBSD__)
593a694,718
> #elif defined(__FreeBSD__) && defined(HOOK_HACK)
> PF_UNLOCK();
> aw->p.dyn->hook_cookie = EVENTHANDLER_REGISTER(ifaddr_event,
> pf_dynaddr_update_event, aw->p.dyn, EVENTHANDLER_PRI_ANY);
> PF_LOCK();
> if (aw->p.dyn->hook_cookie == NULL) {
> pool_put(&pf_addr_pl, aw->p.dyn);
> aw->p.dyn = NULL;
> return (1);
> }
> #else
> /*
> * XXX
> * We have no hook_establish(9)/dohooks(9) kernel interfaces.
> * This means that we do not aware of interface address changes(add,
> * remove, etc). User should update pf rule manually after interface
> * address changed. This may not be possible solution if you use xDSL.
> * ipfw/ipfw2's approach with this situation(with me keyword) is not
> * very efficient due to analyzing interface address during runtime.
> * Another solution is to use a user-land daemon watching address
> * changes with socket interface. Neither one is good.
> * Supporting hook_establish(9) requries modification of in_control()
> * located in netinet/in.c.
> */
> #endif
597a723
> #if defined(__FreeBSD__) && defined(HOOK_HACK)
598a725,733
> pf_dynaddr_update_event(void *arg, struct ifnet *ifp)
> {
> PF_LOCK();
> pf_dynaddr_update(arg);
> PF_UNLOCK();
> }
> #endif
>
> void
647a783
> #if !defined(__FreeBSD__)
649a786,796
> #elif defined(__FreeBSD__) && defined(HOOK_HACK)
> PF_UNLOCK();
> EVENTHANDLER_DEREGISTER(ifaddr_event, aw->p.dyn->hook_cookie);
> PF_LOCK();
> #else
> /*
> * XXX
> * We have no hook_establish(9)/dohooks(9) kernel interfaces.
> * See comments above function, pf_dynaddr_setup().
> */
> #endif
1103a1251,1256
> #if defined(__FreeBSD__)
> struct ip *ip;
> #if (__FreeBSD_version < 501114)
> struct route ro;
> #endif
> #endif
1209c1362,1364
< h->ip_len = htons(len);
---
> #if defined(__FreeBSD__)
> h->ip_off = htons(path_mtu_discovery ? IP_DF : 0);
> #else
1210a1366,1367
> #endif
> h->ip_len = htons(len);
1212a1370,1391
> #if defined(__FreeBSD__)
> ip = mtod(m, struct ip *);
> /*
> * XXX
> * OpenBSD changed ip_len/ip_off byte ordering!
> * Because FreeBSD assumes host byte ordering we need to
> * change here.
> */
> NTOHS(ip->ip_len);
> NTOHS(ip->ip_off);
> #if (__FreeBSD_version < 501114)
> bzero(&ro, sizeof(ro));
> ip_rtaddr(ip->ip_dst, &ro);
> PF_UNLOCK();
> ip_output(m, (void *)NULL, &ro, 0, (void *)NULL,
> (void *)NULL);
> PF_LOCK();
> if(ro.ro_rt) {
> RTFREE(ro.ro_rt);
> }
> #else /* __FreeBSD_version >= 501114 */
> PF_UNLOCK();
1213a1393,1397
> (void *)NULL);
> PF_LOCK();
> #endif
> #else /* ! __FreeBSD__ */
> ip_output(m, (void *)NULL, (void *)NULL, 0, (void *)NULL,
1214a1399
> #endif
1225a1411,1415
> #if defined(__FreeBSD__)
> PF_UNLOCK();
> ip6_output(m, NULL, NULL, 0, NULL, NULL, NULL);
> PF_LOCK();
> #else
1226a1417
> #endif
1237a1429,1431
> #if defined(__FreeBSD__)
> struct ip *ip;
> #endif
1241a1436,1438
> #if defined(__FreeBSD__)
> m0 = m_copypacket(m, M_DONTWAIT);
> #else
1242a1440
> #endif
1268c1466,1476
< icmp_error(m0, type, code, 0, 0);
---
> #if defined(__FreeBSD__)
> /* icmp_error() expects host byte ordering */
> ip = mtod(m0, struct ip *);
> NTOHS(ip->ip_len);
> NTOHS(ip->ip_off);
> PF_UNLOCK();
> #endif
> icmp_error(m0, type, code, 0, NULL);
> #if defined(__FreeBSD__)
> PF_LOCK();
> #endif
1272a1481,1483
> #if defined(__FreeBSD__)
> PF_UNLOCK();
> #endif
1273a1485,1487
> #if defined(__FreeBSD__)
> PF_LOCK();
> #endif
1900c2114
< &r->src.addr.v.a.mask, saddr,
---
> &r->src.addr.v.a.mask, daddr,
1940a2155,2157
> #if defined(__FreeBSD__)
> struct inpcbinfo *pi;
> #else
1941a2159
> #endif
1949a2168,2170
> #if defined(__FreeBSD__)
> pi = &tcbinfo;
> #else
1950a2172
> #endif
1954a2177,2179
> #if defined(__FreeBSD__)
> pi = &udbinfo;
> #else
1955a2181
> #endif
1973a2200,2216
> #if defined(__FreeBSD__)
> #if (__FreeBSD_version >= 500043)
> INP_INFO_RLOCK(pi); /* XXX LOR */
> #endif
> inp = in_pcblookup_hash(pi, saddr->v4, sport, daddr->v4,
> dport, 0, NULL);
> if (inp == NULL) {
> inp = in_pcblookup_hash(pi, saddr->v4, sport,
> daddr->v4, dport, INPLOOKUP_WILDCARD, NULL);
> if(inp == NULL) {
> #if (__FreeBSD_version >= 500043)
> INP_INFO_RUNLOCK(pi);
> #endif
> return (0);
> }
> }
> #else
1980a2224
> #endif
1983a2228,2244
> #if defined(__FreeBSD__)
> #if (__FreeBSD_version >= 500043)
> INP_INFO_RLOCK(pi);
> #endif
> inp = in6_pcblookup_hash(pi, &saddr->v6, sport,
> &daddr->v6, dport, 0, NULL);
> if (inp == NULL) {
> inp = in6_pcblookup_hash(pi, &saddr->v6, sport,
> &daddr->v6, dport, INPLOOKUP_WILDCARD, NULL);
> if (inp == NULL) {
> #if (__FreeBSD_version >= 500043)
> INP_INFO_RUNLOCK(pi);
> #endif
> return (0);
> }
> }
> #else
1991a2253
> #endif
1997a2260,2270
> #if defined(__FreeBSD__)
> #if (__FreeBSD_version >= 500043)
> INP_LOCK(inp);
> #endif
> *uid = inp->inp_socket->so_cred->cr_uid;
> *gid = inp->inp_socket->so_cred->cr_groups[0];
> #if (__FreeBSD_version >= 500043)
> INP_UNLOCK(inp);
> INP_INFO_RUNLOCK(pi);
> #endif
> #else
1999a2273
> #endif
2101a2376,2382
> #if defined(__FreeBSD__)
> #ifdef RTF_PRCLONING
> rtalloc_ign(&ro, (RTF_CLONING | RTF_PRCLONING));
> #else /* !RTF_PRCLONING */
> rtalloc_ign(&ro, RTF_CLONING);
> #endif
> #else /* ! __FreeBSD__ */
2102a2384
> #endif
2113a2396,2403
> #if defined(__FreeBSD__)
> #ifdef RTF_PRCLONING
> rtalloc_ign((struct route *)&ro6,
> (RTF_CLONING | RTF_PRCLONING));
> #else /* !RTF_PRCLONING */
> rtalloc_ign((struct route *)&ro6, RTF_CLONING);
> #endif
> #else /* ! __FreeBSD__ */
2114a2405
> #endif
2287c2578
< m_copyback(m, off, sizeof(*th), th);
---
> m_copyback(m, off, sizeof(*th), (caddr_t)th);
2419a2711,2714
> #if defined(__FreeBSD__)
> s->creation = time_second;
> s->expire = time_second;
> #else
2421a2717
> #endif
2473c2769
< m_copyback(m, off, sizeof(*th), th);
---
> m_copyback(m, off, sizeof(*th), (caddr_t)th);
2605c2901
< m_copyback(m, off, sizeof(*uh), uh);
---
> m_copyback(m, off, sizeof(*uh), (caddr_t)uh);
2691a2988,2991
> #if defined(__FreeBSD__)
> s->creation = time_second;
> s->expire = time_second;
> #else
2693a2994
> #endif
2708c3009
< m_copyback(m, off, sizeof(*uh), uh);
---
> m_copyback(m, off, sizeof(*uh), (caddr_t)uh);
2878c3179
< pd->hdr.icmp6);
---
> (caddr_t)pd->hdr.icmp6);
2939a3241,3245
>
> #if defined(__FreeBSD__)
> s->creation = time_second;
> s->expire = time_second;
> #else
2941a3248
> #endif
2958c3265
< pd->hdr.icmp6);
---
> (caddr_t)pd->hdr.icmp6);
3166a3474,3477
> #if defined(__FreeBSD__)
> s->creation = time_second;
> s->expire = time_second;
> #else
3168a3480
> #endif
3525a3838,3840
> #if defined(__FreeBSD__)
> (*state)->expire = time_second;
> #else
3526a3842
> #endif
3667c3983
< m_copyback(m, off, sizeof(*th), th);
---
> m_copyback(m, off, sizeof(*th), (caddr_t)th);
3670c3986
< m_copyback(m, off, sizeof(*th), th);
---
> m_copyback(m, off, sizeof(*th), (caddr_t)th);
3723a4040,4042
> #if defined(__FreeBSD__)
> (*state)->expire = time_second;
> #else
3724a4044
> #endif
3740c4060
< m_copyback(m, off, sizeof(*uh), uh);
---
> m_copyback(m, off, sizeof(*uh), (caddr_t)uh);
3814a4135,4137
> #if defined(__FreeBSD__)
> (*state)->expire = time_second;
> #else
3815a4139
> #endif
3836c4160
< pd->hdr.icmp6);
---
> (caddr_t)pd->hdr.icmp6);
3856c4180
< pd->hdr.icmp6);
---
> (caddr_t)pd->hdr.icmp6);
4047c4371
< pd->hdr.icmp);
---
> (caddr_t)pd->hdr.icmp);
4049c4373
< &h2);
---
> (caddr_t)&h2);
4056c4380
< pd->hdr.icmp6);
---
> (caddr_t)pd->hdr.icmp6);
4058c4382
< &h2_6);
---
> (caddr_t)&h2_6);
4062c4386
< m_copyback(m, off2, 8, &th);
---
> m_copyback(m, off2, 8, (caddr_t)&th);
4064c4388
< m_copyback(m, off2, 8, &th);
---
> m_copyback(m, off2, 8, (caddr_t)&th);
4109,4110c4433,4435
< pd->hdr.icmp);
< m_copyback(m, ipoff2, sizeof(h2), &h2);
---
> (caddr_t)pd->hdr.icmp);
> m_copyback(m, ipoff2, sizeof(h2),
> (caddr_t)&h2);
4117c4442
< pd->hdr.icmp6);
---
> (caddr_t)pd->hdr.icmp6);
4119c4444
< &h2_6);
---
> (caddr_t)&h2_6);
4123c4448,4449
< m_copyback(m, off2, sizeof(uh), &uh);
---
> m_copyback(m, off2, sizeof(uh),
> (caddr_t)&uh);
4165,4167c4491,4496
< m_copyback(m, off, ICMP_MINLEN, pd->hdr.icmp);
< m_copyback(m, ipoff2, sizeof(h2), &h2);
< m_copyback(m, off2, ICMP_MINLEN, &iih);
---
> m_copyback(m, off, ICMP_MINLEN,
> (caddr_t)pd->hdr.icmp);
> m_copyback(m, ipoff2, sizeof(h2),
> (caddr_t)&h2);
> m_copyback(m, off2, ICMP_MINLEN,
> (caddr_t)&iih);
4211,4212c4540,4542
< pd->hdr.icmp6);
< m_copyback(m, ipoff2, sizeof(h2_6), &h2_6);
---
> (caddr_t)pd->hdr.icmp6);
> m_copyback(m, ipoff2, sizeof(h2_6),
> (caddr_t)&h2_6);
4214c4544
< &iih);
---
> (caddr_t)&iih);
4251,4252c4581,4583
< pd->hdr.icmp);
< m_copyback(m, ipoff2, sizeof(h2), &h2);
---
> (caddr_t)pd->hdr.icmp);
> m_copyback(m, ipoff2, sizeof(h2),
> (caddr_t)&h2);
4259c4590
< pd->hdr.icmp6);
---
> (caddr_t)pd->hdr.icmp6);
4261c4592
< &h2_6);
---
> (caddr_t)&h2_6);
4310a4642,4644
> #if defined(__FreeBSD__)
> (*state)->expire = time_second;
> #else
4311a4646
> #endif
4425a4761,4767
> #if defined(__FreeBSD__)
> #ifdef RTF_PRCLONING
> rtalloc_ign(&ro, (RTF_CLONING|RTF_PRCLONING));
> #else /* !RTF_PRCLONING */
> rtalloc_ign(&ro, RTF_CLONING);
> #endif
> #else /* ! __FreeBSD__ */
4426a4769
> #endif
4436a4780,4941
>
> #if defined(__FreeBSD__) && (__FreeBSD_version < 501105)
> int
> ip_fragment(struct ip *ip, struct mbuf **m_frag, int mtu,
> u_long if_hwassist_flags, int sw_csum)
> {
> int error = 0;
> int hlen = ip->ip_hl << 2;
> int len = (mtu - hlen) & ~7; /* size of payload in each fragment */
> int off;
> struct mbuf *m0 = *m_frag; /* the original packet */
> int firstlen;
> struct mbuf **mnext;
> int nfrags;
>
> if (ip->ip_off & IP_DF) { /* Fragmentation not allowed */
> ipstat.ips_cantfrag++;
> return EMSGSIZE;
> }
>
> /*
> * Must be able to put at least 8 bytes per fragment.
> */
> if (len < 8)
> return EMSGSIZE;
>
> /*
> * If the interface will not calculate checksums on
> * fragmented packets, then do it here.
> */
> if (m0->m_pkthdr.csum_flags & CSUM_DELAY_DATA &&
> (if_hwassist_flags & CSUM_IP_FRAGS) == 0) {
> in_delayed_cksum(m0);
> m0->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA;
> }
>
> if (len > PAGE_SIZE) {
> /*
> * Fragment large datagrams such that each segment
> * contains a multiple of PAGE_SIZE amount of data,
> * plus headers. This enables a receiver to perform
> * page-flipping zero-copy optimizations.
> *
> * XXX When does this help given that sender and receiver
> * could have different page sizes, and also mtu could
> * be less than the receiver's page size ?
> */
> int newlen;
> struct mbuf *m;
>
> for (m = m0, off = 0; m && (off+m->m_len) <= mtu; m = m->m_next)
> off += m->m_len;
>
> /*
> * firstlen (off - hlen) must be aligned on an
> * 8-byte boundary
> */
> if (off < hlen)
> goto smart_frag_failure;
> off = ((off - hlen) & ~7) + hlen;
> newlen = (~PAGE_MASK) & mtu;
> if ((newlen + sizeof (struct ip)) > mtu) {
> /* we failed, go back the default */
> smart_frag_failure:
> newlen = len;
> off = hlen + len;
> }
> len = newlen;
>
> } else {
> off = hlen + len;
> }
>
> firstlen = off - hlen;
> mnext = &m0->m_nextpkt; /* pointer to next packet */
>
> /*
> * Loop through length of segment after first fragment,
> * make new header and copy data of each part and link onto chain.
> * Here, m0 is the original packet, m is the fragment being created.
> * The fragments are linked off the m_nextpkt of the original
> * packet, which after processing serves as the first fragment.
> */
> for (nfrags = 1; off < ip->ip_len; off += len, nfrags++) {
> struct ip *mhip; /* ip header on the fragment */
> struct mbuf *m;
> int mhlen = sizeof (struct ip);
>
> MGETHDR(m, M_DONTWAIT, MT_HEADER);
> if (m == 0) {
> error = ENOBUFS;
> ipstat.ips_odropped++;
> goto done;
> }
> m->m_flags |= (m0->m_flags & M_MCAST) | M_FRAG;
> /*
> * In the first mbuf, leave room for the link header, then
> * copy the original IP header including options. The payload
> * goes into an additional mbuf chain returned by m_copy().
> */
> m->m_data += max_linkhdr;
> mhip = mtod(m, struct ip *);
> *mhip = *ip;
> if (hlen > sizeof (struct ip)) {
> mhlen = ip_optcopy(ip, mhip) + sizeof (struct ip);
> mhip->ip_v = IPVERSION;
> mhip->ip_hl = mhlen >> 2;
> }
> m->m_len = mhlen;
> /* XXX do we need to add ip->ip_off below ? */
> mhip->ip_off = ((off - hlen) >> 3) + ip->ip_off;
> if (off + len >= ip->ip_len) { /* last fragment */
> len = ip->ip_len - off;
> m->m_flags |= M_LASTFRAG;
> } else
> mhip->ip_off |= IP_MF;
> mhip->ip_len = htons((u_short)(len + mhlen));
> m->m_next = m_copy(m0, off, len);
> if (m->m_next == 0) { /* copy failed */
> m_free(m);
> error = ENOBUFS; /* ??? */
> ipstat.ips_odropped++;
> goto done;
> }
> m->m_pkthdr.len = mhlen + len;
> m->m_pkthdr.rcvif = (struct ifnet *)0;
> #ifdef MAC
> mac_create_fragment(m0, m);
> #endif
> m->m_pkthdr.csum_flags = m0->m_pkthdr.csum_flags;
> mhip->ip_off = htons(mhip->ip_off);
> mhip->ip_sum = 0;
> if (sw_csum & CSUM_DELAY_IP)
> mhip->ip_sum = in_cksum(m, mhlen);
> *mnext = m;
> mnext = &m->m_nextpkt;
> }
> ipstat.ips_ofragments += nfrags;
>
> /* set first marker for fragment chain */
> m0->m_flags |= M_FIRSTFRAG | M_FRAG;
> m0->m_pkthdr.csum_data = nfrags;
>
> /*
> * Update first fragment by trimming what's been copied out
> * and updating header.
> */
> m_adj(m0, hlen + firstlen - ip->ip_len);
> m0->m_pkthdr.len = hlen + firstlen;
> ip->ip_len = htons((u_short)m0->m_pkthdr.len);
> ip->ip_off |= IP_MF;
> ip->ip_off = htons(ip->ip_off);
> ip->ip_sum = 0;
> if (sw_csum & CSUM_DELAY_IP)
> ip->ip_sum = in_cksum(m0, hlen);
>
> done:
> *m_frag = m0;
> return error;
> }
> #endif /* __FreeBSD__ && __FreeBSD_version > 501105 */
>
4449a4955,4957
> #if defined(__FreeBSD__)
> int sw_csum;
> #endif
4463a4972,4974
> #if defined(__FreeBSD__)
> m0 = m_dup(*m, M_DONTWAIT);
> #else
4464a4976
> #endif
4527a5040,5050
> #if defined(__FreeBSD__)
> PF_UNLOCK();
> if (pf_test(PF_OUT, ifp, &m0) != PF_PASS) {
> PF_LOCK();
> goto bad;
> } else if (m0 == NULL) {
> PF_LOCK();
> goto done;
> }
> PF_LOCK();
> #else
4531a5055
> #endif
4536a5061,5101
> #if defined(__FreeBSD__)
> /* Copied from FreeBSD 5.1-CURRENT ip_output. */
> m0->m_pkthdr.csum_flags |= CSUM_IP;
> sw_csum = m0->m_pkthdr.csum_flags & ~ifp->if_hwassist;
> if (sw_csum & CSUM_DELAY_DATA) {
> /*
> * XXX: in_delayed_cksum assumes HBO for ip->ip_len (at least)
> */
> NTOHS(ip->ip_len);
> NTOHS(ip->ip_off); /* XXX: needed? */
> in_delayed_cksum(m0);
> HTONS(ip->ip_len);
> HTONS(ip->ip_off);
> sw_csum &= ~CSUM_DELAY_DATA;
> }
> m0->m_pkthdr.csum_flags &= ifp->if_hwassist;
>
> if (ntohs(ip->ip_len) <= ifp->if_mtu ||
> (ifp->if_hwassist & CSUM_FRAGMENT &&
> ((ip->ip_off & htons(IP_DF)) == 0))) {
> /*
> * ip->ip_len = htons(ip->ip_len);
> * ip->ip_off = htons(ip->ip_off);
> */
> ip->ip_sum = 0;
> if (sw_csum & CSUM_DELAY_IP) {
> /* From KAME */
> if (ip->ip_v == IPVERSION &&
> (ip->ip_hl << 2) == sizeof(*ip)) {
> ip->ip_sum = in_cksum_hdr(ip);
> } else {
> ip->ip_sum = in_cksum(m0, ip->ip_hl << 2);
> }
> }
> PF_UNLOCK();
> error = (*ifp->if_output)(ifp, m0, sintosa(dst), ro->ro_rt);
> PF_LOCK();
> goto done;
> }
>
> #else
4555c5120
<
---
> #endif
4562a5128,5133
> #if defined(__FreeBSD__)
> /* icmp_error() expects host byte ordering */
> NTOHS(ip->ip_len);
> NTOHS(ip->ip_off);
> PF_UNLOCK();
> #endif
4564a5136,5138
> #if defined(__FreeBSD__)
> PF_LOCK();
> #endif
4570a5145,5152
> #if defined(__FreeBSD__)
> /*
> * XXX: is cheaper + less error prone than own function
> */
> NTOHS(ip->ip_len);
> NTOHS(ip->ip_off);
> error = ip_fragment(ip, &m0, ifp->if_mtu, ifp->if_hwassist, sw_csum);
> #else
4571a5154,5157
> #endif
> #if defined(__FreeBSD__)
> if (error)
> #else
4572a5159
> #endif
4577a5165,5172
> #if defined(__FreeBSD__)
> if (error == 0) {
> PF_UNLOCK();
> error = (*ifp->if_output)(ifp, m0, sintosa(dst),
> NULL);
> PF_LOCK();
> } else
> #else
4581a5177
> #endif
4628a5225,5227
> #if defined(__FreeBSD__)
> m0 = m_dup(*m, M_DONTWAIT);
> #else
4629a5229
> #endif
4654a5255,5259
> #if defined(__FreeBSD__)
> PF_UNLOCK();
> ip6_output(m0, NULL, NULL, 0, NULL, NULL, NULL);
> PF_LOCK();
> #else
4655a5261
> #endif
4684a5291,5301
> #if defined(__FreeBSD__)
> PF_UNLOCK();
> if (pf_test6(PF_OUT, ifp, &m0) != PF_PASS) {
> PF_LOCK();
> goto bad;
> } else if (m0 == NULL) {
> PF_LOCK();
> goto done;
> }
> PF_LOCK();
> #else
4688a5306
> #endif
4698a5317,5319
> #if defined(__FreeBSD__)
> PF_UNLOCK();
> #endif
4699a5321,5323
> #if defined(__FreeBSD__)
> PF_LOCK();
> #endif
4701a5326,5332
> #if defined(__FreeBSD__)
> if (r->rt != PF_DUPTO) {
> PF_UNLOCK();
> icmp6_error(m0, ICMP6_PACKET_TOO_BIG, 0, ifp->if_mtu);
> PF_LOCK();
> } else
> #else
4704a5336
> #endif
4719a5352
> #if defined(__FreeBSD__)
4720a5354,5481
> * XXX
> * FreeBSD supports cksum offload for the following drivers.
> * em(4), gx(4), lge(4), nge(4), ti(4), xl(4)
> * If we can make full use of it we would outperform ipfw/ipfilter in
> * very heavy traffic.
> * I have not tested 'cause I don't have NICs that supports cksum offload.
> * (There might be problems. Typical phenomena would be
> * 1. No route message for UDP packet.
> * 2. No connection acceptance from external hosts regardless of rule set.)
> */
> int
> pf_check_proto_cksum(struct mbuf *m, int off, int len, u_int8_t p, sa_family_t af)
> {
> u_int16_t sum = 0;
> int hw_assist = 0;
> struct ip *ip;
>
> if (off < sizeof(struct ip) || len < sizeof(struct udphdr))
> return (1);
> if (m->m_pkthdr.len < off + len)
> return (1);
>
> switch (p) {
> case IPPROTO_TCP:
> if (m->m_pkthdr.csum_flags & CSUM_DATA_VALID) {
> if (m->m_pkthdr.csum_flags & CSUM_PSEUDO_HDR) {
> sum = m->m_pkthdr.csum_data;
> } else {
> ip = mtod(m, struct ip *);
> sum = in_pseudo(ip->ip_src.s_addr,
> ip->ip_dst.s_addr,
> htonl(m->m_pkthdr.csum_data +
> IPPROTO_TCP) + ip->ip_len);
> }
> sum ^= 0xffff;
> ++hw_assist;
> }
> break;
> case IPPROTO_UDP:
> if (m->m_pkthdr.csum_flags & CSUM_DATA_VALID) {
> if (m->m_pkthdr.csum_flags & CSUM_PSEUDO_HDR) {
> sum = m->m_pkthdr.csum_data;
> } else {
> ip = mtod(m, struct ip *);
> sum = in_pseudo(ip->ip_src.s_addr,
> ip->ip_dst.s_addr, htonl((u_short)len +
> m->m_pkthdr.csum_data + IPPROTO_UDP));
> }
> sum ^= 0xffff;
> ++hw_assist;
> }
> break;
> case IPPROTO_ICMP:
> #ifdef INET6
> case IPPROTO_ICMPV6:
> #endif /* INET6 */
> break;
> default:
> return (1);
> }
>
> if (!hw_assist) {
> switch (af) {
> case AF_INET:
> if (p == IPPROTO_ICMP) {
> if (m->m_len < off)
> return (1);
> m->m_data += off;
> m->m_len -= off;
> sum = in_cksum(m, len);
> m->m_data -= off;
> m->m_len += off;
> } else {
> if (m->m_len < sizeof(struct ip))
> return (1);
> sum = in4_cksum(m, p, off, len);
> if (sum == 0) {
> m->m_pkthdr.csum_flags |=
> (CSUM_DATA_VALID |
> CSUM_PSEUDO_HDR);
> m->m_pkthdr.csum_data = 0xffff;
> }
> }
> break;
> #ifdef INET6
> case AF_INET6:
> if (m->m_len < sizeof(struct ip6_hdr))
> return (1);
> sum = in6_cksum(m, p, off, len);
> /*
> * XXX
> * IPv6 H/W cksum off-load not supported yet!
> *
> * if (sum == 0) {
> * m->m_pkthdr.csum_flags |=
> * (CSUM_DATA_VALID|CSUM_PSEUDO_HDR);
> * m->m_pkthdr.csum_data = 0xffff;
> *}
> */
> break;
> #endif /* INET6 */
> default:
> return (1);
> }
> }
> if (sum) {
> switch (p) {
> case IPPROTO_TCP:
> tcpstat.tcps_rcvbadsum++;
> break;
> case IPPROTO_UDP:
> udpstat.udps_badsum++;
> break;
> case IPPROTO_ICMP:
> icmpstat.icps_checksum++;
> break;
> #ifdef INET6
> case IPPROTO_ICMPV6:
> icmp6stat.icp6s_checksum++;
> break;
> #endif /* INET6 */
> }
> return (1);
> }
> return (0);
> }
> #else
> /*
4806a5568
> #endif
4821a5584,5586
> #if defined(__FreeBSD__)
> PF_LOCK();
> #endif
4823,4824c5588,5593
< (m_tag_find(m, PACKET_TAG_PF_GENERATED, NULL) != NULL))
< return (PF_PASS);
---
> (m_tag_find(m, PACKET_TAG_PF_GENERATED, NULL) != NULL)) {
> #if defined(__FreeBSD__)
> PF_UNLOCK();
> #endif
> return (PF_PASS);
> }
4825a5595,5597
> #if defined(__FreeBSD__) && (__FreeBSD_version >= 501000)
> M_ASSERTPKTHDR(m);
> #else
4829a5602
> #endif
5030a5804,5807
> #if defined(__FreeBSD__)
> PF_UNLOCK();
> #endif
>
5047a5825,5828
> #if defined(__FreeBSD__)
> PF_LOCK();
> #endif
>
5049c5830,5833
< (m_tag_find(m, PACKET_TAG_PF_GENERATED, NULL) != NULL))
---
> (m_tag_find(m, PACKET_TAG_PF_GENERATED, NULL) != NULL)) {
> #if defined(__FreeBSD__)
> PF_UNLOCK();
> #endif
5050a5835
> }
5051a5837,5839
> #if defined(__FreeBSD__) && (__FreeBSD_version >= 501000)
> M_ASSERTPKTHDR(m);
> #else
5055a5844
> #endif
5260a6050,6052
> #if defined(__FreeBSD__)
> PF_UNLOCK();
> #endif