summaryrefslogtreecommitdiff
path: root/sys/net/pf.c
diff options
context:
space:
mode:
authorHenning Brauer <henning@cvs.openbsd.org>2013-06-26 09:12:41 +0000
committerHenning Brauer <henning@cvs.openbsd.org>2013-06-26 09:12:41 +0000
commit2092a5a508fea02619356ab86e8fac0b9d17f62c (patch)
treef80658ce533adb3cde6fbcae84d133ac88ef775e /sys/net/pf.c
parentfeaa5c3eb6db1089559e6ecef2894b368b933037 (diff)
put the cksum diff back, of course with the bug fixed where we could
under some circumstances repair broken checksums on the way. ok ryan naddy mikeb . redo most of the protocol (tcp/udp/...) checksum handling -assume we have hardware checksum offloading. stop mucking with the checksum in most of the stack -stop checksum mucking in pf, just set a "needs checksumming" flag if needed -in all output pathes, very late, if we figure out the outbound interface doesn't have hw cksum offloading, do the cksum in software. this especially makes the bridge path behave like a regular output path -little special casing for bridge still required until the broadcast path loses its disgusting shortcut hacks, but at least it's in one place now and not all over the stack in6_proto_cksum_out mostly written by krw@ started at k2k11 in iceland more than 1.5 years ago - yes it took that long, this stuff is everything but easy. this happens to fix the infamous pf rdr bug that made us turn off proto cksum offloading on almost all interface drivers.
Diffstat (limited to 'sys/net/pf.c')
-rw-r--r--sys/net/pf.c615
1 files changed, 231 insertions, 384 deletions
diff --git a/sys/net/pf.c b/sys/net/pf.c
index d44e455d52b..6f785502ade 100644
--- a/sys/net/pf.c
+++ b/sys/net/pf.c
@@ -1,8 +1,8 @@
-/* $OpenBSD: pf.c,v 1.836 2013/06/26 07:53:59 blambert Exp $ */
+/* $OpenBSD: pf.c,v 1.837 2013/06/26 09:12:39 henning Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
- * Copyright (c) 2002 - 2010 Henning Brauer
+ * Copyright (c) 2002 - 2012 Henning Brauer <henning@openbsd.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -147,19 +147,18 @@ void pf_init_threshold(struct pf_threshold *, u_int32_t,
void pf_add_threshold(struct pf_threshold *);
int pf_check_threshold(struct pf_threshold *);
-void pf_change_ap(struct pf_addr *, u_int16_t *,
+void pf_change_ap(struct pf_pdesc *, struct pf_addr *,
u_int16_t *, struct pf_addr *, u_int16_t,
- u_int8_t, sa_family_t, sa_family_t);
+ sa_family_t);
int pf_modulate_sack(struct pf_pdesc *,
struct pf_state_peer *);
-void pf_change_a6(struct pf_addr *, u_int16_t *,
- struct pf_addr *, u_int8_t);
+void pf_change_a6(struct pf_pdesc *, struct pf_addr *a,
+ struct pf_addr *an);
int pf_icmp_mapping(struct pf_pdesc *, u_int8_t, int *,
int *, u_int16_t *, u_int16_t *);
-void pf_change_icmp(struct pf_addr *, u_int16_t *,
- struct pf_addr *, struct pf_addr *, u_int16_t,
- u_int16_t *, u_int16_t *, u_int16_t *,
- u_int8_t, sa_family_t);
+void pf_change_icmp(struct pf_pdesc *, struct pf_addr *,
+ u_int16_t *, struct pf_addr *, struct pf_addr *,
+ u_int16_t, sa_family_t);
int pf_change_icmp_af(struct mbuf *, int,
struct pf_pdesc *, struct pf_pdesc *,
struct pf_addr *, struct pf_addr *, sa_family_t,
@@ -213,8 +212,6 @@ u_int16_t pf_calc_mss(struct pf_addr *, sa_family_t, int,
u_int16_t);
void pf_set_rt_ifp(struct pf_state *,
struct pf_addr *);
-int pf_check_proto_cksum(struct mbuf *, int, int,
- u_int8_t, sa_family_t);
struct pf_divert *pf_get_divert(struct mbuf *);
int pf_walk_option6(struct pf_pdesc *, struct ip6_hdr *,
int, int, u_short *);
@@ -1665,140 +1662,37 @@ pf_addr_wrap_neq(struct pf_addr_wrap *aw1, struct pf_addr_wrap *aw2)
}
}
-u_int16_t
-pf_cksum_fixup(u_int16_t cksum, u_int16_t old, u_int16_t new, u_int8_t udp)
-{
- u_int32_t l;
-
- if (udp && !cksum)
- return (0x0000);
- l = cksum + old - new;
- l = (l >> 16) + (l & 65535);
- l = l & 65535;
- if (udp && !l)
- return (0xFFFF);
- return (l);
-}
-
void
-pf_change_ap(struct pf_addr *a, u_int16_t *p, u_int16_t *pc,
- struct pf_addr *an, u_int16_t pn, u_int8_t u, sa_family_t af,
- sa_family_t naf)
+pf_change_ap(struct pf_pdesc *pd, struct pf_addr *a, u_int16_t *p,
+ struct pf_addr *an, u_int16_t pn, sa_family_t naf)
{
- struct pf_addr ao;
- u_int16_t po;
-
- PF_ACPY(&ao, a, af);
- if (af == naf)
+ if (pd->csum_status == PF_CSUM_UNKNOWN)
+ pf_check_proto_cksum(pd, pd->off, pd->tot_len - pd->off,
+ pd->proto, pd->af);
+ if (pd->af == naf)
PF_ACPY(a, an, naf);
-
- if (p == NULL) /* no port -> done. no cksum to worry about. */
- return;
- po = *p;
- *p = pn;
-
- switch (af) {
-#ifdef INET
- case AF_INET:
- switch (naf) {
- case AF_INET:
- *pc = pf_cksum_fixup(pf_cksum_fixup(pf_cksum_fixup(*pc,
- ao.addr16[0], an->addr16[0], u),
- ao.addr16[1], an->addr16[1], u),
- po, pn, u);
- break;
-#ifdef INET6
- case AF_INET6:
- *pc = pf_cksum_fixup(pf_cksum_fixup(pf_cksum_fixup(
- pf_cksum_fixup(pf_cksum_fixup(pf_cksum_fixup(
- pf_cksum_fixup(pf_cksum_fixup(pf_cksum_fixup(*pc,
- ao.addr16[0], an->addr16[0], u),
- ao.addr16[1], an->addr16[1], u),
- 0, an->addr16[2], u),
- 0, an->addr16[3], u),
- 0, an->addr16[4], u),
- 0, an->addr16[5], u),
- 0, an->addr16[6], u),
- 0, an->addr16[7], u),
- po, pn, u);
- break;
-#endif /* INET6 */
- }
- break;
-#endif /* INET */
-#ifdef INET6
- case AF_INET6:
- switch (naf) {
-#ifdef INET
- case AF_INET:
- *pc = pf_cksum_fixup(pf_cksum_fixup(pf_cksum_fixup(
- pf_cksum_fixup(pf_cksum_fixup(pf_cksum_fixup(
- pf_cksum_fixup(pf_cksum_fixup(pf_cksum_fixup(*pc,
- ao.addr16[0], an->addr16[0], u),
- ao.addr16[1], an->addr16[1], u),
- ao.addr16[2], 0, u),
- ao.addr16[3], 0, u),
- ao.addr16[4], 0, u),
- ao.addr16[5], 0, u),
- ao.addr16[6], 0, u),
- ao.addr16[7], 0, u),
- po, pn, u);
- break;
-#endif /* INET */
- case AF_INET6:
- *pc = pf_cksum_fixup(pf_cksum_fixup(pf_cksum_fixup(
- pf_cksum_fixup(pf_cksum_fixup(pf_cksum_fixup(
- pf_cksum_fixup(pf_cksum_fixup(pf_cksum_fixup(*pc,
- ao.addr16[0], an->addr16[0], u),
- ao.addr16[1], an->addr16[1], u),
- ao.addr16[2], an->addr16[2], u),
- ao.addr16[3], an->addr16[3], u),
- ao.addr16[4], an->addr16[4], u),
- ao.addr16[5], an->addr16[5], u),
- ao.addr16[6], an->addr16[6], u),
- ao.addr16[7], an->addr16[7], u),
- po, pn, u);
- break;
- }
- break;
-#endif /* INET6 */
- }
+ if (p != NULL)
+ *p = pn;
}
/* Changes a u_int32_t. Uses a void * so there are no align restrictions */
void
-pf_change_a(void *a, u_int16_t *c, u_int32_t an, u_int8_t u)
+pf_change_a(struct pf_pdesc *pd, void *a, u_int32_t an)
{
- u_int32_t ao;
-
- memcpy(&ao, a, sizeof(ao));
+ if (pd->csum_status == PF_CSUM_UNKNOWN)
+ pf_check_proto_cksum(pd, pd->off, pd->tot_len - pd->off,
+ pd->proto, pd->af);
memcpy(a, &an, sizeof(u_int32_t));
- if (c != NULL)
- *c = pf_cksum_fixup(pf_cksum_fixup(*c, ao / 65536, an / 65536,
- u), ao % 65536, an % 65536, u);
}
#ifdef INET6
void
-pf_change_a6(struct pf_addr *a, u_int16_t *c, struct pf_addr *an, u_int8_t u)
+pf_change_a6(struct pf_pdesc *pd, struct pf_addr *a, struct pf_addr *an)
{
- struct pf_addr ao;
-
- PF_ACPY(&ao, a, AF_INET6);
+ if (pd->csum_status == PF_CSUM_UNKNOWN)
+ pf_check_proto_cksum(pd, pd->off, pd->tot_len - pd->off,
+ pd->proto, pd->af);
PF_ACPY(a, an, AF_INET6);
-
- if (c)
- *c = pf_cksum_fixup(pf_cksum_fixup(pf_cksum_fixup(
- pf_cksum_fixup(pf_cksum_fixup(pf_cksum_fixup(
- pf_cksum_fixup(pf_cksum_fixup(*c,
- ao.addr16[0], an->addr16[0], u),
- ao.addr16[1], an->addr16[1], u),
- ao.addr16[2], an->addr16[2], u),
- ao.addr16[3], an->addr16[3], u),
- ao.addr16[4], an->addr16[4], u),
- ao.addr16[5], an->addr16[5], u),
- ao.addr16[6], an->addr16[6], u),
- ao.addr16[7], an->addr16[7], u);
}
#endif /* INET6 */
@@ -1986,82 +1880,23 @@ pf_icmp_mapping(struct pf_pdesc *pd, u_int8_t type, int *icmp_dir, int *multi,
}
void
-pf_change_icmp(struct pf_addr *ia, u_int16_t *ip, struct pf_addr *oa,
- struct pf_addr *na, u_int16_t np, u_int16_t *pc, u_int16_t *h2c,
- u_int16_t *ic, u_int8_t u, sa_family_t af)
+pf_change_icmp(struct pf_pdesc *pd, struct pf_addr *ia, u_int16_t *ip,
+ struct pf_addr *oa, struct pf_addr *na, u_int16_t np, sa_family_t af)
{
- struct pf_addr oia, ooa;
-
- PF_ACPY(&oia, ia, af);
- if (oa)
- PF_ACPY(&ooa, oa, af);
-
- /* Change inner protocol port, fix inner protocol checksum. */
- if (ip != NULL) {
- u_int16_t oip = *ip;
- u_int32_t opc;
+ if (pd->csum_status == PF_CSUM_UNKNOWN)
+ pf_check_proto_cksum(pd, pd->off, pd->tot_len - pd->off,
+ pd->proto, pd->af);
- if (pc != NULL)
- opc = *pc;
+ /* Change inner protocol port */
+ if (ip != NULL)
*ip = np;
- if (pc != NULL)
- *pc = pf_cksum_fixup(*pc, oip, *ip, u);
- *ic = pf_cksum_fixup(*ic, oip, *ip, 0);
- if (pc != NULL)
- *ic = pf_cksum_fixup(*ic, opc, *pc, 0);
- }
- /* Change inner ip address, fix inner ip and icmp checksums. */
+
+ /* Change inner ip address */
PF_ACPY(ia, na, af);
- switch (af) {
-#ifdef INET
- case AF_INET: {
- u_int32_t oh2c = *h2c;
-
- /* XXX just in_cksum() */
- *h2c = pf_cksum_fixup(pf_cksum_fixup(*h2c,
- oia.addr16[0], ia->addr16[0], 0),
- oia.addr16[1], ia->addr16[1], 0);
- *ic = pf_cksum_fixup(pf_cksum_fixup(*ic,
- oia.addr16[0], ia->addr16[0], 0),
- oia.addr16[1], ia->addr16[1], 0);
- *ic = pf_cksum_fixup(*ic, oh2c, *h2c, 0);
- break;
- }
-#endif /* INET */
-#ifdef INET6
- case AF_INET6:
- *ic = pf_cksum_fixup(pf_cksum_fixup(pf_cksum_fixup(
- pf_cksum_fixup(pf_cksum_fixup(pf_cksum_fixup(
- pf_cksum_fixup(pf_cksum_fixup(*ic,
- oia.addr16[0], ia->addr16[0], u),
- oia.addr16[1], ia->addr16[1], u),
- oia.addr16[2], ia->addr16[2], u),
- oia.addr16[3], ia->addr16[3], u),
- oia.addr16[4], ia->addr16[4], u),
- oia.addr16[5], ia->addr16[5], u),
- oia.addr16[6], ia->addr16[6], u),
- oia.addr16[7], ia->addr16[7], u);
- break;
-#endif /* INET6 */
- }
+
/* Outer ip address, fix outer icmpv6 checksum, if necessary. */
- if (oa) {
+ if (oa)
PF_ACPY(oa, na, af);
-#ifdef INET6
- if (af == AF_INET6)
- *ic = pf_cksum_fixup(pf_cksum_fixup(pf_cksum_fixup(
- pf_cksum_fixup(pf_cksum_fixup(pf_cksum_fixup(
- pf_cksum_fixup(pf_cksum_fixup(*ic,
- ooa.addr16[0], oa->addr16[0], u),
- ooa.addr16[1], oa->addr16[1], u),
- ooa.addr16[2], oa->addr16[2], u),
- ooa.addr16[3], oa->addr16[3], u),
- ooa.addr16[4], oa->addr16[4], u),
- ooa.addr16[5], oa->addr16[5], u),
- ooa.addr16[6], oa->addr16[6], u),
- ooa.addr16[7], oa->addr16[7], u);
-#endif /* INET6 */
- }
}
#if INET && INET6
@@ -2074,6 +1909,10 @@ pf_translate_af(struct pf_pdesc *pd)
struct icmp6_hdr *icmp;
int hlen;
+ if (pd->csum_status == PF_CSUM_UNKNOWN)
+ pf_check_proto_cksum(pd, pd->off, pd->tot_len - pd->off,
+ pd->proto, pd->af);
+
hlen = pd->naf == AF_INET ? sizeof(*ip4) : sizeof(*ip6);
/* trim the old header */
@@ -2143,6 +1982,10 @@ pf_change_icmp_af(struct mbuf *m, int off, struct pf_pdesc *pd,
struct ip6_hdr *ip6;
int hlen, olen, mlen;
+ if (pd->csum_status == PF_CSUM_UNKNOWN)
+ pf_check_proto_cksum(pd, pd->off, pd->tot_len - pd->off,
+ pd->proto, pd->af);
+
if (af == naf || (af != AF_INET && af != AF_INET6) ||
(naf != AF_INET && naf != AF_INET6))
return (-1);
@@ -2305,28 +2148,12 @@ pf_translate_icmp_af(int af, void *arg)
default:
return (-1);
}
- if (icmp6->icmp6_type != type) {
- icmp6->icmp6_cksum = pf_cksum_fixup(icmp6->icmp6_cksum,
- icmp6->icmp6_type, type, 0);
- icmp6->icmp6_type = type;
- }
- if (icmp6->icmp6_code != code) {
- icmp6->icmp6_cksum = pf_cksum_fixup(icmp6->icmp6_cksum,
- icmp6->icmp6_code, code, 0);
- icmp6->icmp6_code = code;
- }
- if (icmp6->icmp6_mtu != htonl(mtu)) {
- icmp6->icmp6_cksum = pf_cksum_fixup(icmp6->icmp6_cksum,
- htons(ntohl(icmp6->icmp6_mtu)), htons(mtu), 0);
- /* aligns well with a icmpv4 nextmtu */
- icmp6->icmp6_mtu = htonl(mtu);
- }
- if (ptr >= 0 && icmp6->icmp6_pptr != htonl(ptr)) {
- icmp6->icmp6_cksum = pf_cksum_fixup(icmp6->icmp6_cksum,
- htons(ntohl(icmp6->icmp6_pptr)), htons(ptr), 0);
- /* icmpv4 pptr is a one most significant byte */
- icmp6->icmp6_pptr = htonl(ptr << 24);
- }
+ icmp6->icmp6_type = type;
+ icmp6->icmp6_code = code;
+ /* aligns well with a icmpv4 nextmtu */
+ icmp6->icmp6_mtu = htonl(mtu);
+ /* icmpv4 pptr is a one most significant byte */
+ icmp6->icmp6_pptr = htonl(ptr << 24);
break;
case AF_INET6:
icmp4 = arg;
@@ -2415,26 +2242,10 @@ pf_translate_icmp_af(int af, void *arg)
default:
return (-1);
}
- if (icmp4->icmp_type != type) {
- icmp4->icmp_cksum = pf_cksum_fixup(icmp4->icmp_cksum,
- icmp4->icmp_type, type, 0);
- icmp4->icmp_type = type;
- }
- if (icmp4->icmp_code != code) {
- icmp4->icmp_cksum = pf_cksum_fixup(icmp4->icmp_cksum,
- icmp4->icmp_code, code, 0);
- icmp4->icmp_code = code;
- }
- if (icmp4->icmp_nextmtu != htons(mtu)) {
- icmp4->icmp_cksum = pf_cksum_fixup(icmp4->icmp_cksum,
- icmp4->icmp_nextmtu, htons(mtu), 0);
- icmp4->icmp_nextmtu = htons(mtu);
- }
- if (ptr >= 0 && icmp4->icmp_void != ptr) {
- icmp4->icmp_cksum = pf_cksum_fixup(icmp4->icmp_cksum,
- htons(icmp4->icmp_pptr), htons(ptr), 0);
- icmp4->icmp_void = htonl(ptr);
- }
+ icmp4->icmp_type = type;
+ icmp4->icmp_code = code;
+ icmp4->icmp_nextmtu = htons(mtu);
+ icmp4->icmp_void = htonl(ptr);
break;
}
@@ -2476,12 +2287,12 @@ pf_modulate_sack(struct pf_pdesc *pd, struct pf_state_peer *dst)
for (i = 2; i + TCPOLEN_SACK <= olen;
i += TCPOLEN_SACK) {
memcpy(&sack, &opt[i], sizeof(sack));
- pf_change_a(&sack.start, &th->th_sum,
+ pf_change_a(pd, &sack.start,
htonl(ntohl(sack.start) -
- dst->seqdiff), 0);
- pf_change_a(&sack.end, &th->th_sum,
+ dst->seqdiff));
+ pf_change_a(pd, &sack.end,
htonl(ntohl(sack.end) -
- dst->seqdiff), 0);
+ dst->seqdiff));
memcpy(&opt[i], &sack, sizeof(sack));
}
copyback = 1;
@@ -3551,7 +3362,7 @@ pf_test_rule(struct pf_pdesc *pd, struct pf_rule **rm, struct pf_state **sm,
!(th->th_flags & TH_RST)) {
u_int32_t ack = ntohl(th->th_seq) + pd->p_len;
- if (pf_check_proto_cksum(pd->m, pd->off,
+ if (pf_check_proto_cksum(pd, pd->off,
pd->tot_len - pd->off, IPPROTO_TCP, pd->af))
REASON_SET(&reason, PFRES_PROTCKSUM);
else {
@@ -3622,7 +3433,7 @@ pf_test_rule(struct pf_pdesc *pd, struct pf_rule **rm, struct pf_state **sm,
sk->port[pd->af == pd->naf ? pd->sidx : pd->didx],
&sk->addr[pd->af == pd->naf ? pd->didx : pd->sidx],
sk->port[pd->af == pd->naf ? pd->didx : pd->sidx],
- virtual_type, icmp_dir);
+ virtual_type, icmp_dir, pd->m);
}
} else {
while ((ri = SLIST_FIRST(&rules))) {
@@ -3631,9 +3442,11 @@ pf_test_rule(struct pf_pdesc *pd, struct pf_rule **rm, struct pf_state **sm,
}
}
- /* copy back packet headers if we performed NAT operations */
- if (rewrite && pd->hdrlen)
+ /* copy back packet headers if needed */
+ if (rewrite && pd->hdrlen) {
+ pf_cksum(pd, pd->m);
m_copyback(pd->m, pd->off, pd->hdrlen, pd->hdr.any, M_NOWAIT);
+ }
#if NPFSYNC > 0
if (*sm != NULL && !ISSET((*sm)->state_flags, PFSTATE_NOSYNC) &&
@@ -3729,8 +3542,8 @@ pf_create_state(struct pf_pdesc *pd, struct pf_rule *r, struct pf_rule *a,
if ((s->src.seqdiff = pf_tcp_iss(pd) - s->src.seqlo) ==
0)
s->src.seqdiff = 1;
- pf_change_a(&th->th_seq, &th->th_sum,
- htonl(s->src.seqlo + s->src.seqdiff), 0);
+ pf_change_a(pd, &th->th_seq,
+ htonl(s->src.seqlo + s->src.seqdiff));
*rewrite = 1;
} else
s->src.seqdiff = 0;
@@ -3867,7 +3680,7 @@ csfailed:
int
pf_translate(struct pf_pdesc *pd, struct pf_addr *saddr, u_int16_t sport,
struct pf_addr *daddr, u_int16_t dport, u_int16_t virtual_type,
- int icmp_dir)
+ int icmp_dir, struct mbuf *m)
{
/*
* when called from bpf_mtap_pflog, there are extra constraints:
@@ -3884,14 +3697,14 @@ pf_translate(struct pf_pdesc *pd, struct pf_addr *saddr, u_int16_t sport,
case IPPROTO_TCP:
if (afto || PF_ANEQ(saddr, pd->src, pd->af) ||
*pd->sport != sport) {
- pf_change_ap(pd->src, pd->sport, &pd->hdr.tcp->th_sum,
- saddr, sport, 0, pd->af, pd->naf);
+ pf_change_ap(pd, pd->src, pd->sport, saddr, sport,
+ pd->naf);
rewrite = 1;
}
if (afto || PF_ANEQ(daddr, pd->dst, pd->af) ||
*pd->dport != dport) {
- pf_change_ap(pd->dst, pd->dport, &pd->hdr.tcp->th_sum,
- daddr, dport, 0, pd->af, pd->naf);
+ pf_change_ap(pd, pd->dst, pd->dport, daddr, dport,
+ pd->naf);
rewrite = 1;
}
break;
@@ -3899,14 +3712,14 @@ pf_translate(struct pf_pdesc *pd, struct pf_addr *saddr, u_int16_t sport,
case IPPROTO_UDP:
if (afto || PF_ANEQ(saddr, pd->src, pd->af) ||
*pd->sport != sport) {
- pf_change_ap(pd->src, pd->sport, &pd->hdr.udp->uh_sum,
- saddr, sport, 1, pd->af, pd->naf);
+ pf_change_ap(pd, pd->src, pd->sport, saddr, sport,
+ pd->naf);
rewrite = 1;
}
if (afto || PF_ANEQ(daddr, pd->dst, pd->af) ||
*pd->dport != dport) {
- pf_change_ap(pd->dst, pd->dport, &pd->hdr.udp->uh_sum,
- daddr, dport, 1, pd->af, pd->naf);
+ pf_change_ap(pd, pd->dst, pd->dport, daddr, dport,
+ pd->naf);
rewrite = 1;
}
break;
@@ -3926,13 +3739,13 @@ pf_translate(struct pf_pdesc *pd, struct pf_addr *saddr, u_int16_t sport,
#endif /* INET6 */
} else {
if (PF_ANEQ(saddr, pd->src, pd->af)) {
- pf_change_a(&pd->src->v4.s_addr, NULL,
- saddr->v4.s_addr, 0);
+ pf_change_a(pd, &pd->src->v4.s_addr,
+ saddr->v4.s_addr);
rewrite = 1;
}
if (PF_ANEQ(daddr, pd->dst, pd->af)) {
- pf_change_a(&pd->dst->v4.s_addr, NULL,
- daddr->v4.s_addr, 0);
+ pf_change_a(pd, &pd->dst->v4.s_addr,
+ daddr->v4.s_addr);
rewrite = 1;
}
}
@@ -3940,9 +3753,6 @@ pf_translate(struct pf_pdesc *pd, struct pf_addr *saddr, u_int16_t sport,
u_int16_t icmpid = (icmp_dir == PF_IN) ? sport : dport;
if (icmpid != pd->hdr.icmp->icmp_id) {
- pd->hdr.icmp->icmp_cksum = pf_cksum_fixup(
- pd->hdr.icmp->icmp_cksum,
- pd->hdr.icmp->icmp_id, icmpid, 0);
pd->hdr.icmp->icmp_id = icmpid;
rewrite = 1;
}
@@ -3966,13 +3776,11 @@ pf_translate(struct pf_pdesc *pd, struct pf_addr *saddr, u_int16_t sport,
#endif /* INET */
} else {
if (PF_ANEQ(saddr, pd->src, pd->af)) {
- pf_change_a6(pd->src,
- &pd->hdr.icmp6->icmp6_cksum, saddr, 0);
+ pf_change_a6(pd, pd->src, saddr);
rewrite = 1;
}
if (PF_ANEQ(daddr, pd->dst, pd->af)) {
- pf_change_a6(pd->dst,
- &pd->hdr.icmp6->icmp6_cksum, daddr, 0);
+ pf_change_a6(pd, pd->dst, daddr);
rewrite = 1;
}
}
@@ -3984,13 +3792,13 @@ pf_translate(struct pf_pdesc *pd, struct pf_addr *saddr, u_int16_t sport,
#ifdef INET
case AF_INET:
if (!afto && PF_ANEQ(saddr, pd->src, pd->af)) {
- pf_change_a(&pd->src->v4.s_addr, NULL,
- saddr->v4.s_addr, 0);
+ pf_change_a(pd, &pd->src->v4.s_addr,
+ saddr->v4.s_addr);
rewrite = 1;
}
if (!afto && PF_ANEQ(daddr, pd->dst, pd->af)) {
- pf_change_a(&pd->dst->v4.s_addr, NULL,
- daddr->v4.s_addr, 0);
+ pf_change_a(pd, &pd->dst->v4.s_addr,
+ daddr->v4.s_addr);
rewrite = 1;
}
break;
@@ -3998,11 +3806,11 @@ pf_translate(struct pf_pdesc *pd, struct pf_addr *saddr, u_int16_t sport,
#ifdef INET6
case AF_INET6:
if (!afto && PF_ANEQ(saddr, pd->src, pd->af)) {
- pf_change_a6(pd->src, NULL, saddr, 0);
+ pf_change_a6(pd, pd->src, saddr);
rewrite = 1;
}
if (!afto && PF_ANEQ(daddr, pd->dst, pd->af)) {
- pf_change_a6(pd->dst, NULL, daddr, 0);
+ pf_change_a6(pd, pd->dst, daddr);
rewrite = 1;
}
break;
@@ -4053,9 +3861,8 @@ pf_tcp_track_full(struct pf_pdesc *pd, struct pf_state_peer *src,
while ((src->seqdiff = arc4random() - seq) == 0)
;
ack = ntohl(th->th_ack) - dst->seqdiff;
- pf_change_a(&th->th_seq, &th->th_sum, htonl(seq +
- src->seqdiff), 0);
- pf_change_a(&th->th_ack, &th->th_sum, htonl(ack), 0);
+ pf_change_a(pd, &th->th_seq, htonl(seq + src->seqdiff));
+ pf_change_a(pd, &th->th_ack, htonl(ack));
*copyback = 1;
} else {
ack = ntohl(th->th_ack);
@@ -4105,9 +3912,8 @@ pf_tcp_track_full(struct pf_pdesc *pd, struct pf_state_peer *src,
ack = ntohl(th->th_ack) - dst->seqdiff;
if (src->seqdiff) {
/* Modulate sequence numbers */
- pf_change_a(&th->th_seq, &th->th_sum, htonl(seq +
- src->seqdiff), 0);
- pf_change_a(&th->th_ack, &th->th_sum, htonl(ack), 0);
+ pf_change_a(pd, &th->th_seq, htonl(seq + src->seqdiff));
+ pf_change_a(pd, &th->th_ack, htonl(ack));
*copyback = 1;
}
end = seq + pd->p_len;
@@ -4613,19 +4419,17 @@ pf_test_state(struct pf_pdesc *pd, struct pf_state **state, u_short *reason)
if (afto || PF_ANEQ(pd->src, &nk->addr[sidx], pd->af) ||
nk->port[sidx] != pd->osport)
- pf_change_ap(pd->src, pd->sport, pd->pcksum,
- &nk->addr[sidx], nk->port[sidx],
- pd->virtual_proto == IPPROTO_UDP, pd->af, nk->af);
+ pf_change_ap(pd, pd->src, pd->sport,
+ &nk->addr[sidx], nk->port[sidx], nk->af);
if (afto || PF_ANEQ(pd->dst, &nk->addr[didx], pd->af) ||
pd->rdomain != nk->rdomain)
pd->destchg = 1;
+
if (afto || PF_ANEQ(pd->dst, &nk->addr[didx], pd->af) ||
nk->port[didx] != pd->odport)
- pf_change_ap(pd->dst, pd->dport, pd->pcksum,
- &nk->addr[didx], nk->port[didx],
- pd->virtual_proto == IPPROTO_UDP, pd->af, nk->af);
- pd->m->m_pkthdr.rdomain = nk->rdomain;
+ pf_change_ap(pd, pd->dst, pd->dport,
+ &nk->addr[didx], nk->port[didx], nk->af);
#if INET && INET6
if (afto) {
@@ -4636,11 +4440,14 @@ pf_test_state(struct pf_pdesc *pd, struct pf_state **state, u_short *reason)
}
#endif /* INET && INET6 */
+ pd->m->m_pkthdr.rdomain = nk->rdomain;
copyback = 1;
}
- if (copyback && pd->hdrlen > 0)
+ if (copyback && pd->hdrlen > 0) {
+ pf_cksum(pd, pd->m);
m_copyback(pd->m, pd->off, pd->hdrlen, pd->hdr.any, M_NOWAIT);
+ }
return (action);
}
@@ -4702,7 +4509,8 @@ pf_test_state_icmp(struct pf_pdesc *pd, struct pf_state **state,
struct pf_addr *saddr = pd->src, *daddr = pd->dst;
u_int16_t *icmpsum, virtual_id, virtual_type;
u_int8_t icmptype;
- int icmp_dir, iidx, ret, multi;
+ int icmp_dir, iidx, ret, multi, copyback = 0;
+
struct pf_state_key_cmp key;
switch (pd->proto) {
@@ -4776,28 +4584,22 @@ pf_test_state_icmp(struct pf_pdesc *pd, struct pf_state **state,
#endif /* INET6 */
if (!afto && PF_ANEQ(pd->src,
&nk->addr[sidx], AF_INET))
- pf_change_a(&saddr->v4.s_addr, NULL,
- nk->addr[sidx].v4.s_addr, 0);
+ pf_change_a(pd, &saddr->v4.s_addr,
+ nk->addr[sidx].v4.s_addr);
if (!afto && PF_ANEQ(pd->dst,
&nk->addr[didx], AF_INET)) {
- pf_change_a(&daddr->v4.s_addr, NULL,
- nk->addr[didx].v4.s_addr, 0);
+ pf_change_a(pd, &daddr->v4.s_addr,
+ nk->addr[didx].v4.s_addr);
pd->destchg = 1;
}
- if (nk->port[iidx] !=
- pd->hdr.icmp->icmp_id) {
- pd->hdr.icmp->icmp_cksum =
- pf_cksum_fixup(
- pd->hdr.icmp->icmp_cksum,
- pd->hdr.icmp->icmp_id,
- nk->port[iidx], 0);
+ if (nk->port[iidx] != pd->hdr.icmp->icmp_id)
pd->hdr.icmp->icmp_id = nk->port[iidx];
- }
m_copyback(pd->m, pd->off, ICMP_MINLEN,
pd->hdr.icmp, M_NOWAIT);
+ copyback = 1;
break;
#endif /* INET */
#ifdef INET6
@@ -4812,15 +4614,13 @@ pf_test_state_icmp(struct pf_pdesc *pd, struct pf_state **state,
#endif /* INET */
if (!afto && PF_ANEQ(pd->src,
&nk->addr[sidx], AF_INET6))
- pf_change_a6(saddr,
- &pd->hdr.icmp6->icmp6_cksum,
- &nk->addr[sidx], 0);
+ pf_change_a6(pd, saddr,
+ &nk->addr[sidx]);
if (!afto && PF_ANEQ(pd->dst,
&nk->addr[didx], AF_INET6)) {
- pf_change_a6(daddr,
- &pd->hdr.icmp6->icmp6_cksum,
- &nk->addr[didx], 0);
+ pf_change_a6(pd, daddr,
+ &nk->addr[didx]);
pd->destchg = 1;
}
@@ -4831,6 +4631,7 @@ pf_test_state_icmp(struct pf_pdesc *pd, struct pf_state **state,
m_copyback(pd->m, pd->off,
sizeof(struct icmp6_hdr), pd->hdr.icmp6,
M_NOWAIT);
+ copyback = 1;
break;
#endif /* INET6 */
}
@@ -4843,8 +4644,6 @@ pf_test_state_icmp(struct pf_pdesc *pd, struct pf_state **state,
}
#endif /* INET && INET6 */
}
- return (PF_PASS);
-
} else {
/*
* ICMP error message in response to a TCP/UDP packet.
@@ -4931,7 +4730,6 @@ pf_test_state_icmp(struct pf_pdesc *pd, struct pf_state **state,
u_int32_t seq;
struct pf_state_peer *src, *dst;
u_int8_t dws;
- int copyback = 0;
/*
* Only the first 8 bytes of the TCP header can be
@@ -4981,8 +4779,7 @@ pf_test_state_icmp(struct pf_pdesc *pd, struct pf_state **state,
/* Demodulate sequence number */
seq = ntohl(th.th_seq) - src->seqdiff;
if (src->seqdiff) {
- pf_change_a(&th.th_seq, icmpsum,
- htonl(seq), 0);
+ pf_change_a(pd, &th.th_seq, htonl(seq));
copyback = 1;
}
@@ -5064,10 +4861,10 @@ pf_test_state_icmp(struct pf_pdesc *pd, struct pf_state **state,
if (PF_ANEQ(pd2.src,
&nk->addr[pd2.sidx], pd2.af) ||
nk->port[pd2.sidx] != th.th_sport)
- pf_change_icmp(pd2.src, &th.th_sport,
- daddr, &nk->addr[pd2.sidx],
- nk->port[pd2.sidx], NULL,
- ipsum2, icmpsum, 0, pd2.af);
+ pf_change_icmp(pd, pd2.src,
+ &th.th_sport, daddr,
+ &nk->addr[pd2.sidx],
+ nk->port[pd2.sidx], pd2.af);
if (PF_ANEQ(pd2.dst, &nk->addr[pd2.didx],
pd2.af) || pd2.rdomain != nk->rdomain)
@@ -5077,10 +4874,10 @@ pf_test_state_icmp(struct pf_pdesc *pd, struct pf_state **state,
if (PF_ANEQ(pd2.dst,
&nk->addr[pd2.didx], pd2.af) ||
nk->port[pd2.didx] != th.th_dport)
- pf_change_icmp(pd2.dst, &th.th_dport,
- saddr, &nk->addr[pd2.didx],
- nk->port[pd2.didx], NULL,
- ipsum2, icmpsum, 0, pd2.af);
+ pf_change_icmp(pd, pd2.dst,
+ &th.th_dport, saddr,
+ &nk->addr[pd2.didx],
+ nk->port[pd2.didx], pd2.af);
copyback = 1;
}
@@ -5106,8 +4903,6 @@ pf_test_state_icmp(struct pf_pdesc *pd, struct pf_state **state,
}
m_copyback(pd2.m, pd2.off, 8, &th, M_NOWAIT);
}
-
- return (PF_PASS);
break;
}
case IPPROTO_UDP: {
@@ -5161,12 +4956,12 @@ pf_test_state_icmp(struct pf_pdesc *pd, struct pf_state **state,
pd->proto = IPPROTO_ICMP;
else
pd->proto = IPPROTO_ICMPV6;
- pf_change_ap(pd2.src, &uh.uh_sport,
+ pf_change_ap(pd, pd2.src,
&uh.uh_sum, &nk->addr[pd2.sidx],
- nk->port[sidx], 1, pd->af, nk->af);
- pf_change_ap(pd2.dst, &uh.uh_dport,
+ nk->port[sidx], nk->af);
+ pf_change_ap(pd, pd2.dst,
&uh.uh_sum, &nk->addr[pd2.didx],
- nk->port[didx], 1, pd->af, nk->af);
+ nk->port[didx], nk->af);
m_copyback(pd2.m, pd2.off, sizeof(uh),
&uh, M_NOWAIT);
pd->m->m_pkthdr.rdomain = nk->rdomain;
@@ -5183,10 +4978,10 @@ pf_test_state_icmp(struct pf_pdesc *pd, struct pf_state **state,
if (PF_ANEQ(pd2.src,
&nk->addr[pd2.sidx], pd2.af) ||
nk->port[pd2.sidx] != uh.uh_sport)
- pf_change_icmp(pd2.src, &uh.uh_sport,
- daddr, &nk->addr[pd2.sidx],
- nk->port[pd2.sidx], &uh.uh_sum,
- ipsum2, icmpsum, 1, pd2.af);
+ pf_change_icmp(pd, pd2.src,
+ &uh.uh_sport, daddr,
+ &nk->addr[pd2.sidx],
+ nk->port[pd2.sidx], pd2.af);
if (PF_ANEQ(pd2.dst, &nk->addr[pd2.didx],
pd2.af) || pd2.rdomain != nk->rdomain)
@@ -5196,10 +4991,10 @@ pf_test_state_icmp(struct pf_pdesc *pd, struct pf_state **state,
if (PF_ANEQ(pd2.dst,
&nk->addr[pd2.didx], pd2.af) ||
nk->port[pd2.didx] != uh.uh_dport)
- pf_change_icmp(pd2.dst, &uh.uh_dport,
- saddr, &nk->addr[pd2.didx],
- nk->port[pd2.didx], &uh.uh_sum,
- ipsum2, icmpsum, 1, pd2.af);
+ pf_change_icmp(pd, pd2.dst,
+ &uh.uh_dport, saddr,
+ &nk->addr[pd2.didx],
+ nk->port[pd2.didx], pd2.af);
switch (pd2.af) {
#ifdef INET
@@ -5220,10 +5015,11 @@ pf_test_state_icmp(struct pf_pdesc *pd, struct pf_state **state,
break;
#endif /* INET6 */
}
+ uh.uh_sum = 0;
m_copyback(pd2.m, pd2.off, sizeof(uh), &uh,
M_NOWAIT);
+ copyback = 1;
}
- return (PF_PASS);
break;
}
#ifdef INET
@@ -5305,13 +5101,12 @@ pf_test_state_icmp(struct pf_pdesc *pd, struct pf_state **state,
&nk->addr[pd2.sidx], pd2.af) ||
(virtual_type == htons(ICMP_ECHO) &&
nk->port[iidx] != iih.icmp_id))
- pf_change_icmp(pd2.src,
+ pf_change_icmp(pd, pd2.src,
(virtual_type == htons(ICMP_ECHO)) ?
&iih.icmp_id : NULL,
daddr, &nk->addr[pd2.sidx],
(virtual_type == htons(ICMP_ECHO)) ?
- nk->port[iidx] : 0, NULL,
- ipsum2, icmpsum, 0, AF_INET);
+ nk->port[iidx] : 0, AF_INET);
if (PF_ANEQ(pd2.dst, &nk->addr[pd2.didx],
pd2.af) || pd2.rdomain != nk->rdomain)
@@ -5320,9 +5115,9 @@ pf_test_state_icmp(struct pf_pdesc *pd, struct pf_state **state,
if (PF_ANEQ(pd2.dst,
&nk->addr[pd2.didx], pd2.af))
- pf_change_icmp(pd2.dst, NULL, saddr,
- &nk->addr[pd2.didx], 0, NULL,
- ipsum2, icmpsum, 0, AF_INET);
+ pf_change_icmp(pd, pd2.dst, NULL,
+ saddr, &nk->addr[pd2.didx], 0,
+ AF_INET);
m_copyback(pd->m, pd->off, ICMP_MINLEN,
pd->hdr.icmp, M_NOWAIT);
@@ -5330,8 +5125,8 @@ pf_test_state_icmp(struct pf_pdesc *pd, struct pf_state **state,
M_NOWAIT);
m_copyback(pd2.m, pd2.off, ICMP_MINLEN, &iih,
M_NOWAIT);
+ copyback = 1;
}
- return (PF_PASS);
break;
}
#endif /* INET */
@@ -5425,15 +5220,14 @@ pf_test_state_icmp(struct pf_pdesc *pd, struct pf_state **state,
((virtual_type ==
htons(ICMP6_ECHO_REQUEST)) &&
nk->port[pd2.sidx] != iih.icmp6_id))
- pf_change_icmp(pd2.src,
+ pf_change_icmp(pd, pd2.src,
(virtual_type ==
htons(ICMP6_ECHO_REQUEST))
? &iih.icmp6_id : NULL,
daddr, &nk->addr[pd2.sidx],
(virtual_type ==
htons(ICMP6_ECHO_REQUEST))
- ? nk->port[iidx] : 0, NULL,
- ipsum2, icmpsum, 0, AF_INET6);
+ ? nk->port[iidx] : 0, AF_INET6);
if (PF_ANEQ(pd2.dst, &nk->addr[pd2.didx],
pd2.af) || pd2.rdomain != nk->rdomain)
@@ -5442,19 +5236,17 @@ pf_test_state_icmp(struct pf_pdesc *pd, struct pf_state **state,
if (PF_ANEQ(pd2.dst,
&nk->addr[pd2.didx], pd2.af))
- pf_change_icmp(pd2.dst, NULL, saddr,
- &nk->addr[pd2.didx], 0, NULL,
- ipsum2, icmpsum, 0, AF_INET6);
+ pf_change_icmp(pd, pd2.dst, NULL,
+ saddr, &nk->addr[pd2.didx], 0,
+ AF_INET6);
m_copyback(pd->m, pd->off,
sizeof(struct icmp6_hdr), pd->hdr.icmp6,
M_NOWAIT);
- m_copyback(pd2.m, ipoff2, sizeof(h2_6), &h2_6,
- M_NOWAIT);
- m_copyback(pd2.m, pd2.off,
+ m_copyback(pd->m, pd2.off,
sizeof(struct icmp6_hdr), &iih, M_NOWAIT);
+ copyback = 1;
}
- return (PF_PASS);
break;
}
#endif /* INET6 */
@@ -5476,9 +5268,9 @@ pf_test_state_icmp(struct pf_pdesc *pd, struct pf_state **state,
if (PF_ANEQ(pd2.src,
&nk->addr[pd2.sidx], pd2.af))
- pf_change_icmp(pd2.src, NULL, daddr,
- &nk->addr[pd2.sidx], 0, NULL,
- ipsum2, icmpsum, 0, pd2.af);
+ pf_change_icmp(pd, pd2.src, NULL,
+ daddr, &nk->addr[pd2.sidx], 0,
+ pd2.af);
if (PF_ANEQ(pd2.dst, &nk->addr[pd2.didx],
pd2.af) || pd2.rdomain != nk->rdomain)
@@ -5487,9 +5279,9 @@ pf_test_state_icmp(struct pf_pdesc *pd, struct pf_state **state,
if (PF_ANEQ(pd2.dst,
&nk->addr[pd2.didx], pd2.af))
- pf_change_icmp(pd2.dst, NULL, saddr,
- &nk->addr[pd2.didx], 0, NULL,
- ipsum2, icmpsum, 0, pd2.af);
+ pf_change_icmp(pd, pd2.dst, NULL,
+ saddr, &nk->addr[pd2.didx], 0,
+ pd2.af);
switch (pd2.af) {
#ifdef INET
@@ -5510,12 +5302,16 @@ pf_test_state_icmp(struct pf_pdesc *pd, struct pf_state **state,
break;
#endif /* INET6 */
}
+ copyback = 1;
}
- return (PF_PASS);
break;
}
}
}
+ if (copyback)
+ pf_cksum(pd, pd->m);
+
+ return (PF_PASS);
}
/*
@@ -6006,12 +5802,17 @@ bad:
* if the _OUT flag is set the checksum isn't done yet, consider these ok
*/
int
-pf_check_proto_cksum(struct mbuf *m, int off, int len, u_int8_t p,
+pf_check_proto_cksum(struct pf_pdesc *pd, int off, int len, u_int8_t p,
sa_family_t af)
{
u_int16_t flag_ok, flag_bad, flag_out;
u_int16_t sum;
+ if (pd->csum_status == PF_CSUM_OK)
+ return (0);
+ if (pd->csum_status == PF_CSUM_BAD)
+ return (1);
+
switch (p) {
case IPPROTO_TCP:
flag_ok = M_TCP_CSUM_IN_OK;
@@ -6027,47 +5828,55 @@ pf_check_proto_cksum(struct mbuf *m, int off, int len, u_int8_t p,
#ifdef INET6
case IPPROTO_ICMPV6:
#endif /* INET6 */
- flag_ok = flag_out = flag_bad = 0;
+ flag_ok = M_ICMP_CSUM_IN_OK;
+ flag_out = M_ICMP_CSUM_OUT;
+ flag_bad = M_ICMP_CSUM_IN_BAD;
break;
default:
return (1);
}
- if (m->m_pkthdr.csum_flags & (flag_ok | flag_out))
+ if (pd->m->m_pkthdr.csum_flags & (flag_ok | flag_out)) {
+ pd->csum_status = PF_CSUM_OK;
return (0);
- if (m->m_pkthdr.csum_flags & flag_bad)
- return (1);
- if (off < sizeof(struct ip) || len < sizeof(struct udphdr))
- return (1);
- if (m->m_pkthdr.len < off + len)
+ }
+ if (pd->m->m_pkthdr.csum_flags & flag_bad || off < sizeof(struct ip) ||
+ pd->m->m_pkthdr.len < off + len) {
+ pd->csum_status = PF_CSUM_BAD;
return (1);
+ }
switch (af) {
#ifdef INET
case AF_INET:
if (p == IPPROTO_ICMP) {
- if (m->m_len < off)
+ if (pd->m->m_len < off) {
+ pd->csum_status = PF_CSUM_BAD;
return (1);
- m->m_data += off;
- m->m_len -= off;
- sum = in_cksum(m, len);
- m->m_data -= off;
- m->m_len += off;
+ }
+ pd->m->m_data += off;
+ pd->m->m_len -= off;
+ sum = in_cksum(pd->m, len);
+ pd->m->m_data -= off;
+ pd->m->m_len += off;
} else {
- if (m->m_len < sizeof(struct ip))
+ if (pd->m->m_len < sizeof(struct ip)) {
+ pd->csum_status = PF_CSUM_BAD;
return (1);
- sum = in4_cksum(m, p, off, len);
+ }
+ sum = in4_cksum(pd->m, p, off, len);
}
break;
#endif /* INET */
#ifdef INET6
case AF_INET6:
- if (m->m_len < sizeof(struct ip6_hdr))
+ if (pd->m->m_len < sizeof(struct ip6_hdr)) {
+ pd->csum_status = PF_CSUM_BAD;
return (1);
- sum = in6_cksum(m, p, off, len);
+ }
+ sum = in6_cksum(pd->m, p, off, len);
break;
#endif /* INET6 */
}
if (sum) {
- m->m_pkthdr.csum_flags |= flag_bad;
switch (p) {
case IPPROTO_TCP:
tcpstat.tcps_rcvbadsum++;
@@ -6084,9 +5893,12 @@ pf_check_proto_cksum(struct mbuf *m, int off, int len, u_int8_t p,
break;
#endif /* INET6 */
}
+ pd->m->m_pkthdr.csum_flags |= flag_bad;
+ pd->csum_status = PF_CSUM_BAD;
return (1);
}
- m->m_pkthdr.csum_flags |= flag_ok;
+ pd->m->m_pkthdr.csum_flags |= flag_ok;
+ pd->csum_status = PF_CSUM_OK;
return (0);
}
@@ -6922,6 +6734,41 @@ pf_check_congestion(struct ifqueue *ifq)
return (0);
}
+void
+pf_cksum(struct pf_pdesc *pd, struct mbuf *m)
+{
+ if (pd->csum_status != PF_CSUM_OK)
+ return; /* don't fix broken cksums */
+
+ switch (pd->proto) {
+ case IPPROTO_TCP:
+ pd->hdr.tcp->th_sum = 0;
+ if (pd->af == AF_INET) {
+ pd->hdr.tcp->th_sum = in_cksum_phdr(pd->src->v4.s_addr,
+ pd->dst->v4.s_addr, htons(pd->tot_len -
+ pd->off + IPPROTO_TCP));
+ }
+ m->m_pkthdr.csum_flags |= M_TCP_CSUM_OUT;
+ break;
+ case IPPROTO_UDP:
+ pd->hdr.udp->uh_sum = 0;
+ if (pd->af == AF_INET) {
+ pd->hdr.udp->uh_sum = in_cksum_phdr(pd->src->v4.s_addr,
+ pd->dst->v4.s_addr, htons(pd->tot_len -
+ pd->off + IPPROTO_UDP));
+ }
+ m->m_pkthdr.csum_flags |= M_UDP_CSUM_OUT;
+ break;
+ case IPPROTO_ICMP:
+ case IPPROTO_ICMPV6:
+ m->m_pkthdr.csum_flags |= M_ICMP_CSUM_OUT;
+ break;
+ default:
+ /* nothing */
+ break;
+ }
+}
+
/*
* must be called whenever any addressing information such as
* address, port, protocol has changed