summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHenning Brauer <henning@cvs.openbsd.org>2012-11-06 12:32:43 +0000
committerHenning Brauer <henning@cvs.openbsd.org>2012-11-06 12:32:43 +0000
commitcdb55f2492d4777204a5a27b340ac160f237054a (patch)
tree80a626642d88e29ab1ec6b295d4799011726e9a6
parent0a997370e6625d6631c40501416aa015179279b0 (diff)
backout csum diff for the moment, requested by theo
-rw-r--r--sys/net/if_bridge.c20
-rw-r--r--sys/net/if_pflog.c4
-rw-r--r--sys/net/pf.c501
-rw-r--r--sys/net/pf_norm.c22
-rw-r--r--sys/net/pfvar.h10
-rw-r--r--sys/netinet/ip_input.c5
-rw-r--r--sys/netinet/ip_output.c6
-rw-r--r--sys/netinet6/in6.h3
-rw-r--r--sys/netinet6/ip6_divert.c5
-rw-r--r--sys/netinet6/ip6_forward.c5
-rw-r--r--sys/netinet6/ip6_input.c5
-rw-r--r--sys/netinet6/ip6_output.c65
12 files changed, 392 insertions, 259 deletions
diff --git a/sys/net/if_bridge.c b/sys/net/if_bridge.c
index 6d055980fd6..c310abe759b 100644
--- a/sys/net/if_bridge.c
+++ b/sys/net/if_bridge.c
@@ -1,8 +1,7 @@
-/* $OpenBSD: if_bridge.c,v 1.201 2012/11/01 07:55:55 henning Exp $ */
+/* $OpenBSD: if_bridge.c,v 1.202 2012/11/06 12:32:41 henning Exp $ */
/*
* Copyright (c) 1999, 2000 Jason L. Wright (jason@thought.net)
- * Copyright (c) 2003 - 2012 Henning Brauer <henning@openbsd.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -1012,6 +1011,15 @@ bridge_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *sa,
return (0);
}
#endif /* IPSEC */
+
+ /* Catch packets that need TCP/UDP hardware checksumming */
+ if (m->m_pkthdr.csum_flags & M_TCP_CSUM_OUT ||
+ m->m_pkthdr.csum_flags & M_UDP_CSUM_OUT) {
+ m_freem(m);
+ splx(s);
+ return (0);
+ }
+
bridge_span(sc, NULL, m);
LIST_FOREACH(p, &sc->sc_iflist, next) {
@@ -2343,12 +2351,6 @@ bridge_ipsec(struct bridge_softc *sc, struct ifnet *ifp,
}
if (m == NULL)
return (1);
- else if (af == AF_INET)
- in_proto_cksum_out(m, encif);
-#ifdef INET6
- else if (af == AF_INET6)
- in6_proto_cksum_out(m, encif);
-#endif /* INET6 */
#endif /* NPF */
ip = mtod(m, struct ip *);
@@ -2501,7 +2503,6 @@ bridge_ip(struct bridge_softc *sc, int dir, struct ifnet *ifp,
return (NULL);
if (m->m_len < sizeof(struct ip))
goto dropit;
- in_proto_cksum_out(m, ifp);
ip = mtod(m, struct ip *);
ip->ip_sum = 0;
if (0 && (ifp->if_capabilities & IFCAP_CSUM_IPv4)) {
@@ -2547,7 +2548,6 @@ bridge_ip(struct bridge_softc *sc, int dir, struct ifnet *ifp,
if (m == NULL)
return (NULL);
#endif /* NPF > 0 */
- in6_proto_cksum_out(m, ifp);
break;
}
diff --git a/sys/net/if_pflog.c b/sys/net/if_pflog.c
index 7ffe6af74d7..41832bb6463 100644
--- a/sys/net/if_pflog.c
+++ b/sys/net/if_pflog.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_pflog.c,v 1.51 2012/11/01 07:55:55 henning Exp $ */
+/* $OpenBSD: if_pflog.c,v 1.52 2012/11/06 12:32:41 henning Exp $ */
/*
* The authors of this code are John Ioannidis (ji@tla.org),
* Angelos D. Keromytis (kermit@csd.uch.gr) and
@@ -443,7 +443,7 @@ pflog_bpfcopy(const void *src_arg, void *dst_arg, size_t len)
if (pd.virtual_proto != PF_VPROTO_FRAGMENT &&
(pfloghdr->rewritten = pf_translate(&pd, &pfloghdr->saddr,
pfloghdr->sport, &pfloghdr->daddr, pfloghdr->dport, 0,
- pfloghdr->dir, pd.m))) {
+ pfloghdr->dir))) {
m_copyback(pd.m, pd.off, min(pd.m->m_len - pd.off, pd.hdrlen),
pd.hdr.any, M_NOWAIT);
#if INET && INET6
diff --git a/sys/net/pf.c b/sys/net/pf.c
index d3fa2450ede..5177466a4c1 100644
--- a/sys/net/pf.c
+++ b/sys/net/pf.c
@@ -1,8 +1,8 @@
-/* $OpenBSD: pf.c,v 1.815 2012/11/01 07:55:56 henning Exp $ */
+/* $OpenBSD: pf.c,v 1.816 2012/11/06 12:32:41 henning Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
- * Copyright (c) 2002 - 2012 Henning Brauer <henning@openbsd.org>
+ * Copyright (c) 2002 - 2010 Henning Brauer
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -148,16 +148,18 @@ void pf_add_threshold(struct pf_threshold *);
int pf_check_threshold(struct pf_threshold *);
void pf_change_ap(struct pf_addr *, u_int16_t *,
- struct pf_addr *, u_int16_t, sa_family_t,
- sa_family_t);
+ u_int16_t *, struct pf_addr *, u_int16_t,
+ u_int8_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 *a, struct pf_addr *an);
+void pf_change_a6(struct pf_addr *, u_int16_t *,
+ struct pf_addr *, u_int8_t);
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,
- sa_family_t);
+ u_int16_t *, u_int16_t *, u_int16_t *,
+ u_int8_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,
@@ -1650,27 +1652,137 @@ 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, struct pf_addr *an,
- u_int16_t pn, sa_family_t af, sa_family_t naf)
+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)
{
+ struct pf_addr ao;
+ u_int16_t po = *p;
+
+ PF_ACPY(&ao, a, af);
if (af == naf)
PF_ACPY(a, an, naf);
+
*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 */
+ }
}
/* Changes a u_int32_t. Uses a void * so there are no align restrictions */
void
-pf_change_a(void *a, u_int32_t an)
+pf_change_a(void *a, u_int16_t *c, u_int32_t an, u_int8_t u)
{
+ u_int32_t ao;
+
+ memcpy(&ao, a, sizeof(ao));
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, struct pf_addr *an)
+pf_change_a6(struct pf_addr *a, u_int16_t *c, struct pf_addr *an, u_int8_t u)
{
+ struct pf_addr ao;
+
+ PF_ACPY(&ao, a, AF_INET6);
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 */
@@ -1859,18 +1971,81 @@ 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, sa_family_t af)
+ 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)
{
- /* Change inner protocol port */
- if (ip != NULL)
- *ip = np;
+ struct pf_addr oia, ooa;
- /* Change inner ip address */
- PF_ACPY(ia, na, af);
+ 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 (pc != NULL)
+ opc = *pc;
+ *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. */
+ 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
@@ -2114,12 +2289,28 @@ pf_translate_icmp_af(int af, void *arg)
default:
return (-1);
}
- 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);
+ 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);
+ }
break;
case AF_INET6:
icmp4 = arg;
@@ -2208,10 +2399,26 @@ pf_translate_icmp_af(int af, void *arg)
default:
return (-1);
}
- icmp4->icmp_type = type;
- icmp4->icmp_code = code;
- icmp4->icmp_nextmtu = htons(mtu);
- icmp4->icmp_void = htonl(ptr);
+ 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);
+ }
break;
}
@@ -2253,12 +2460,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,
+ pf_change_a(&sack.start, &th->th_sum,
htonl(ntohl(sack.start) -
- dst->seqdiff));
- pf_change_a(&sack.end,
+ dst->seqdiff), 0);
+ pf_change_a(&sack.end, &th->th_sum,
htonl(ntohl(sack.end) -
- dst->seqdiff));
+ dst->seqdiff), 0);
memcpy(&opt[i], &sack, sizeof(sack));
}
copyback = 1;
@@ -3408,7 +3615,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, pd->m);
+ virtual_type, icmp_dir);
}
} else {
while ((ri = SLIST_FIRST(&rules))) {
@@ -3417,11 +3624,9 @@ pf_test_rule(struct pf_pdesc *pd, struct pf_rule **rm, struct pf_state **sm,
}
}
- /* copy back packet headers if needed */
- if (rewrite && pd->hdrlen) {
- pf_cksum(pd, pd->m);
+ /* copy back packet headers if we performed NAT operations */
+ if (rewrite && pd->hdrlen)
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) &&
@@ -3515,8 +3720,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,
- htonl(s->src.seqlo + s->src.seqdiff));
+ pf_change_a(&th->th_seq, &th->th_sum,
+ htonl(s->src.seqlo + s->src.seqdiff), 0);
*rewrite = 1;
} else
s->src.seqdiff = 0;
@@ -3653,7 +3858,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, struct mbuf *m)
+ int icmp_dir)
{
/*
* when called from bpf_mtap_pflog, there are extra constraints:
@@ -3670,14 +3875,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, saddr, sport, pd->af,
- pd->naf);
+ pf_change_ap(pd->src, pd->sport, &pd->hdr.tcp->th_sum,
+ saddr, sport, 0, pd->af, pd->naf);
rewrite = 1;
}
if (afto || PF_ANEQ(daddr, pd->dst, pd->af) ||
*pd->dport != dport) {
- pf_change_ap(pd->dst, pd->dport, daddr, dport, pd->af,
- pd->naf);
+ pf_change_ap(pd->dst, pd->dport, &pd->hdr.tcp->th_sum,
+ daddr, dport, 0, pd->af, pd->naf);
rewrite = 1;
}
break;
@@ -3685,14 +3890,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, saddr, sport, pd->af,
- pd->naf);
+ pf_change_ap(pd->src, pd->sport, &pd->hdr.udp->uh_sum,
+ saddr, sport, 1, pd->af, pd->naf);
rewrite = 1;
}
if (afto || PF_ANEQ(daddr, pd->dst, pd->af) ||
*pd->dport != dport) {
- pf_change_ap(pd->dst, pd->dport, daddr, dport, pd->af,
- pd->naf);
+ pf_change_ap(pd->dst, pd->dport, &pd->hdr.udp->uh_sum,
+ daddr, dport, 1, pd->af, pd->naf);
rewrite = 1;
}
break;
@@ -3712,13 +3917,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,
- saddr->v4.s_addr);
+ pf_change_a(&pd->src->v4.s_addr, NULL,
+ saddr->v4.s_addr, 0);
rewrite = 1;
}
if (PF_ANEQ(daddr, pd->dst, pd->af)) {
- pf_change_a(&pd->dst->v4.s_addr,
- daddr->v4.s_addr);
+ pf_change_a(&pd->dst->v4.s_addr, NULL,
+ daddr->v4.s_addr, 0);
rewrite = 1;
}
}
@@ -3726,6 +3931,9 @@ 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;
}
@@ -3749,11 +3957,13 @@ 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, saddr);
+ pf_change_a6(pd->src,
+ &pd->hdr.icmp6->icmp6_cksum, saddr, 0);
rewrite = 1;
}
if (PF_ANEQ(daddr, pd->dst, pd->af)) {
- pf_change_a6(pd->dst, daddr);
+ pf_change_a6(pd->dst,
+ &pd->hdr.icmp6->icmp6_cksum, daddr, 0);
rewrite = 1;
}
}
@@ -3765,13 +3975,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,
- saddr->v4.s_addr);
+ pf_change_a(&pd->src->v4.s_addr, NULL,
+ saddr->v4.s_addr, 0);
rewrite = 1;
}
if (!afto && PF_ANEQ(daddr, pd->dst, pd->af)) {
- pf_change_a(&pd->dst->v4.s_addr,
- daddr->v4.s_addr);
+ pf_change_a(&pd->dst->v4.s_addr, NULL,
+ daddr->v4.s_addr, 0);
rewrite = 1;
}
break;
@@ -3779,11 +3989,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, saddr);
+ pf_change_a6(pd->src, NULL, saddr, 0);
rewrite = 1;
}
if (!afto && PF_ANEQ(daddr, pd->dst, pd->af)) {
- pf_change_a6(pd->dst, daddr);
+ pf_change_a6(pd->dst, NULL, daddr, 0);
rewrite = 1;
}
break;
@@ -3834,8 +4044,9 @@ 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, htonl(seq + src->seqdiff));
- pf_change_a(&th->th_ack, htonl(ack));
+ 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);
*copyback = 1;
} else {
ack = ntohl(th->th_ack);
@@ -3884,8 +4095,9 @@ 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, htonl(seq + src->seqdiff));
- pf_change_a(&th->th_ack, htonl(ack));
+ 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);
*copyback = 1;
}
end = seq + pd->p_len;
@@ -4345,14 +4557,17 @@ pf_test_state_tcp(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] != th->th_sport)
- pf_change_ap(pd->src, &th->th_sport,
- &nk->addr[sidx], nk->port[sidx], pd->af, nk->af);
+ pf_change_ap(pd->src, &th->th_sport, &th->th_sum,
+ &nk->addr[sidx], nk->port[sidx], 0, pd->af, 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] != th->th_dport)
- pf_change_ap(pd->dst, &th->th_dport,
- &nk->addr[didx], nk->port[didx], pd->af, nk->af);
-
+ pf_change_ap(pd->dst, &th->th_dport, &th->th_sum,
+ &nk->addr[didx], nk->port[didx], 0, pd->af,
+ nk->af);
pd->m->m_pkthdr.rdomain = nk->rdomain;
#if INET && INET6
@@ -4368,10 +4583,9 @@ pf_test_state_tcp(struct pf_pdesc *pd, struct pf_state **state, u_short *reason)
}
/* Copyback sequence modulation or stateful scrub changes if needed */
- if (copyback) {
- pf_cksum(pd, pd->m);
+ if (copyback)
m_copyback(pd->m, pd->off, sizeof(*th), th, M_NOWAIT);
- }
+
return (action);
}
@@ -4430,17 +4644,17 @@ pf_test_state_udp(struct pf_pdesc *pd, struct pf_state **state)
if (afto || PF_ANEQ(pd->src, &nk->addr[sidx], pd->af) ||
nk->port[sidx] != uh->uh_sport)
- pf_change_ap(pd->src, &uh->uh_sport,
- &nk->addr[sidx], nk->port[sidx], pd->af, nk->af);
+ pf_change_ap(pd->src, &uh->uh_sport, &uh->uh_sum,
+ &nk->addr[sidx], nk->port[sidx], 1, pd->af, 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] != uh->uh_dport)
- pf_change_ap(pd->dst, &uh->uh_dport,
- &nk->addr[didx], nk->port[didx], pd->af, nk->af);
+ pf_change_ap(pd->dst, &uh->uh_dport, &uh->uh_sum,
+ &nk->addr[didx], nk->port[didx], 1, pd->af, nk->af);
+ pd->m->m_pkthdr.rdomain = nk->rdomain;
#if INET && INET6
if (afto) {
@@ -4451,8 +4665,6 @@ pf_test_state_udp(struct pf_pdesc *pd, struct pf_state **state)
}
#endif /* INET && INET6 */
- pd->m->m_pkthdr.rdomain = nk->rdomain;
- pf_cksum(pd, pd->m);
m_copyback(pd->m, pd->off, sizeof(*uh), uh, M_NOWAIT);
}
@@ -4516,8 +4728,7 @@ 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, copyback = 0;
-
+ int icmp_dir, iidx, ret, multi;
struct pf_state_key_cmp key;
switch (pd->proto) {
@@ -4591,22 +4802,28 @@ 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,
- nk->addr[sidx].v4.s_addr);
+ pf_change_a(&saddr->v4.s_addr, NULL,
+ nk->addr[sidx].v4.s_addr, 0);
if (!afto && PF_ANEQ(pd->dst,
&nk->addr[didx], AF_INET)) {
- pf_change_a(&daddr->v4.s_addr,
- nk->addr[didx].v4.s_addr);
+ pf_change_a(&daddr->v4.s_addr, NULL,
+ nk->addr[didx].v4.s_addr, 0);
pd->destchg = 1;
}
- if (nk->port[iidx] != pd->hdr.icmp->icmp_id)
+ 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);
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
@@ -4622,12 +4839,14 @@ pf_test_state_icmp(struct pf_pdesc *pd, struct pf_state **state,
if (!afto && PF_ANEQ(pd->src,
&nk->addr[sidx], AF_INET6))
pf_change_a6(saddr,
- &nk->addr[sidx]);
+ &pd->hdr.icmp6->icmp6_cksum,
+ &nk->addr[sidx], 0);
if (!afto && PF_ANEQ(pd->dst,
&nk->addr[didx], AF_INET6)) {
pf_change_a6(daddr,
- &nk->addr[didx]);
+ &pd->hdr.icmp6->icmp6_cksum,
+ &nk->addr[didx], 0);
pd->destchg = 1;
}
@@ -4638,7 +4857,6 @@ 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 */
}
@@ -4651,6 +4869,8 @@ 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.
@@ -4737,6 +4957,7 @@ 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
@@ -4786,7 +5007,8 @@ 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, htonl(seq));
+ pf_change_a(&th.th_seq, icmpsum,
+ htonl(seq), 0);
copyback = 1;
}
@@ -4870,7 +5092,8 @@ pf_test_state_icmp(struct pf_pdesc *pd, struct pf_state **state,
nk->port[pd2.sidx] != th.th_sport)
pf_change_icmp(pd2.src, &th.th_sport,
daddr, &nk->addr[pd2.sidx],
- nk->port[pd2.sidx], pd2.af);
+ nk->port[pd2.sidx], NULL,
+ ipsum2, icmpsum, 0, pd2.af);
if (PF_ANEQ(pd2.dst, &nk->addr[pd2.didx],
pd2.af) || pd2.rdomain != nk->rdomain)
@@ -4882,7 +5105,8 @@ pf_test_state_icmp(struct pf_pdesc *pd, struct pf_state **state,
nk->port[pd2.didx] != th.th_dport)
pf_change_icmp(pd2.dst, &th.th_dport,
saddr, &nk->addr[pd2.didx],
- nk->port[pd2.didx], pd2.af);
+ nk->port[pd2.didx], NULL,
+ ipsum2, icmpsum, 0, pd2.af);
copyback = 1;
}
@@ -4908,6 +5132,8 @@ 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: {
@@ -4961,12 +5187,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,
+ pf_change_ap(pd2.src, &uh.uh_sport,
&uh.uh_sum, &nk->addr[pd2.sidx],
- nk->port[sidx], pd->af, nk->af);
- pf_change_ap(pd2.dst,
+ nk->port[sidx], 1, pd->af, nk->af);
+ pf_change_ap(pd2.dst, &uh.uh_dport,
&uh.uh_sum, &nk->addr[pd2.didx],
- nk->port[didx], pd->af, nk->af);
+ nk->port[didx], 1, pd->af, nk->af);
m_copyback(pd2.m, pd2.off, sizeof(uh),
&uh, M_NOWAIT);
pd->m->m_pkthdr.rdomain = nk->rdomain;
@@ -4985,7 +5211,8 @@ pf_test_state_icmp(struct pf_pdesc *pd, struct pf_state **state,
nk->port[pd2.sidx] != uh.uh_sport)
pf_change_icmp(pd2.src, &uh.uh_sport,
daddr, &nk->addr[pd2.sidx],
- nk->port[pd2.sidx], pd2.af);
+ nk->port[pd2.sidx], &uh.uh_sum,
+ ipsum2, icmpsum, 1, pd2.af);
if (PF_ANEQ(pd2.dst, &nk->addr[pd2.didx],
pd2.af) || pd2.rdomain != nk->rdomain)
@@ -4997,7 +5224,8 @@ pf_test_state_icmp(struct pf_pdesc *pd, struct pf_state **state,
nk->port[pd2.didx] != uh.uh_dport)
pf_change_icmp(pd2.dst, &uh.uh_dport,
saddr, &nk->addr[pd2.didx],
- nk->port[pd2.didx], pd2.af);
+ nk->port[pd2.didx], &uh.uh_sum,
+ ipsum2, icmpsum, 1, pd2.af);
switch (pd2.af) {
#ifdef INET
@@ -5018,11 +5246,10 @@ 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
@@ -5109,7 +5336,8 @@ pf_test_state_icmp(struct pf_pdesc *pd, struct pf_state **state,
&iih.icmp_id : NULL,
daddr, &nk->addr[pd2.sidx],
(virtual_type == htons(ICMP_ECHO)) ?
- nk->port[iidx] : 0, AF_INET);
+ nk->port[iidx] : 0, NULL,
+ ipsum2, icmpsum, 0, AF_INET);
if (PF_ANEQ(pd2.dst, &nk->addr[pd2.didx],
pd2.af) || pd2.rdomain != nk->rdomain)
@@ -5119,7 +5347,8 @@ 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, AF_INET);
+ &nk->addr[pd2.didx], 0, NULL,
+ ipsum2, icmpsum, 0, AF_INET);
m_copyback(pd->m, pd->off, ICMP_MINLEN,
pd->hdr.icmp, M_NOWAIT);
@@ -5127,8 +5356,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 */
@@ -5229,7 +5458,8 @@ pf_test_state_icmp(struct pf_pdesc *pd, struct pf_state **state,
daddr, &nk->addr[pd2.sidx],
(virtual_type ==
htons(ICMP6_ECHO_REQUEST))
- ? nk->port[iidx] : 0, AF_INET6);
+ ? nk->port[iidx] : 0, NULL,
+ ipsum2, icmpsum, 0, AF_INET6);
if (PF_ANEQ(pd2.dst, &nk->addr[pd2.didx],
pd2.af) || pd2.rdomain != nk->rdomain)
@@ -5239,15 +5469,18 @@ 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, AF_INET6);
+ &nk->addr[pd2.didx], 0, NULL,
+ ipsum2, icmpsum, 0, AF_INET6);
m_copyback(pd->m, pd->off,
sizeof(struct icmp6_hdr), pd->hdr.icmp6,
M_NOWAIT);
- m_copyback(pd->m, pd2.off,
+ m_copyback(pd2.m, ipoff2, sizeof(h2_6), &h2_6,
+ M_NOWAIT);
+ m_copyback(pd2.m, pd2.off,
sizeof(struct icmp6_hdr), &iih, M_NOWAIT);
- copyback = 1;
}
+ return (PF_PASS);
break;
}
#endif /* INET6 */
@@ -5270,7 +5503,8 @@ 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, pd2.af);
+ &nk->addr[pd2.sidx], 0, NULL,
+ ipsum2, icmpsum, 0, pd2.af);
if (PF_ANEQ(pd2.dst, &nk->addr[pd2.didx],
pd2.af) || pd2.rdomain != nk->rdomain)
@@ -5280,7 +5514,8 @@ 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, pd2.af);
+ &nk->addr[pd2.didx], 0, NULL,
+ ipsum2, icmpsum, 0, pd2.af);
switch (pd2.af) {
#ifdef INET
@@ -5301,16 +5536,12 @@ 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);
}
int
@@ -5372,12 +5603,14 @@ pf_test_state_other(struct pf_pdesc *pd, struct pf_state **state)
case AF_INET:
if (!afto &&
PF_ANEQ(pd->src, &nk->addr[pd->sidx], AF_INET))
- pf_change_a(&pd->src->v4.s_addr,
- nk->addr[pd->sidx].v4.s_addr);
+ pf_change_a(&pd->src->v4.s_addr, NULL,
+ nk->addr[pd->sidx].v4.s_addr,
+ 0);
if (!afto &&
PF_ANEQ(pd->dst, &nk->addr[pd->didx], AF_INET)) {
- pf_change_a(&pd->dst->v4.s_addr,
- nk->addr[pd->didx].v4.s_addr);
+ pf_change_a(&pd->dst->v4.s_addr, NULL,
+ nk->addr[pd->didx].v4.s_addr,
+ 0);
pd->destchg = 1;
}
break;
@@ -6812,38 +7045,6 @@ pf_check_congestion(struct ifqueue *ifq)
return (0);
}
-void
-pf_cksum(struct pf_pdesc *pd, struct mbuf *m)
-{
- 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
diff --git a/sys/net/pf_norm.c b/sys/net/pf_norm.c
index 46c1635d0ec..1ab9d4ba804 100644
--- a/sys/net/pf_norm.c
+++ b/sys/net/pf_norm.c
@@ -1,8 +1,8 @@
-/* $OpenBSD: pf_norm.c,v 1.156 2012/11/01 07:55:56 henning Exp $ */
+/* $OpenBSD: pf_norm.c,v 1.157 2012/11/06 12:32:41 henning Exp $ */
/*
* Copyright 2001 Niels Provos <provos@citi.umich.edu>
- * Copyright 2009 - 2012 Henning Brauer <henning@openbsd.org>
+ * Copyright 2009 Henning Brauer <henning@openbsd.org>
* Copyright 2011 Alexander Bluhm <bluhm@openbsd.org>
* All rights reserved.
*
@@ -869,20 +869,20 @@ pf_normalize_tcp(struct pf_pdesc *pd)
th->th_x2 = 0;
nv = *(u_int16_t *)(&th->th_ack + 1);
+ th->th_sum = pf_cksum_fixup(th->th_sum, ov, nv, 0);
rewrite = 1;
}
/* Remove urgent pointer, if TH_URG is not set */
if (!(flags & TH_URG) && th->th_urp) {
+ th->th_sum = pf_cksum_fixup(th->th_sum, th->th_urp, 0, 0);
th->th_urp = 0;
rewrite = 1;
}
/* copy back packet headers if we sanitized */
- if (rewrite) {
- pf_cksum(pd, pd->m);
+ if (rewrite)
m_copyback(pd->m, pd->off, sizeof(*th), th, M_NOWAIT);
- }
return (PF_PASS);
@@ -1075,8 +1075,10 @@ pf_normalize_tcp_stateful(struct pf_pdesc *pd, u_short *reason,
PFSS_TIMESTAMP)) {
tsval = ntohl(tsval);
pf_change_a(&opt[2],
+ &th->th_sum,
htonl(tsval +
- src->scrub->pfss_ts_mod));
+ src->scrub->pfss_ts_mod),
+ 0);
copyback = 1;
}
@@ -1089,7 +1091,8 @@ pf_normalize_tcp_stateful(struct pf_pdesc *pd, u_short *reason,
tsecr = ntohl(tsecr)
- dst->scrub->pfss_ts_mod;
pf_change_a(&opt[6],
- htonl(tsecr));
+ &th->th_sum, htonl(tsecr),
+ 0);
copyback = 1;
}
got_ts = 1;
@@ -1419,11 +1422,12 @@ pf_normalize_mss(struct pf_pdesc *pd, u_int16_t maxmss)
case TCPOPT_MAXSEG:
bcopy((caddr_t)(optp + 2), (caddr_t)&mss, 2);
if (ntohs(mss) > maxmss) {
+ th->th_sum = pf_cksum_fixup(th->th_sum,
+ mss, htons(maxmss), 0);
mss = htons(maxmss);
m_copyback(pd->m,
pd->off + sizeof(*th) + optp + 2 - opts,
2, &mss, M_NOWAIT);
- pf_cksum(pd, pd->m);
m_copyback(pd->m, pd->off, sizeof(*th), th,
M_NOWAIT);
}
@@ -1433,6 +1437,8 @@ pf_normalize_mss(struct pf_pdesc *pd, u_int16_t maxmss)
}
}
+
+
return (0);
}
diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h
index b5396408ec6..030f4fb0d58 100644
--- a/sys/net/pfvar.h
+++ b/sys/net/pfvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfvar.h,v 1.373 2012/11/01 07:55:56 henning Exp $ */
+/* $OpenBSD: pfvar.h,v 1.374 2012/11/06 12:32:41 henning Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -1767,6 +1767,8 @@ extern void pf_state_export(struct pfsync_state *,
struct pf_state *);
extern void pf_print_state(struct pf_state *);
extern void pf_print_flags(u_int8_t);
+extern u_int16_t pf_cksum_fixup(u_int16_t, u_int16_t, u_int16_t,
+ u_int8_t);
extern struct ifnet *sync_ifp;
extern struct pf_rule pf_default_rule;
@@ -1790,7 +1792,7 @@ void pf_addr_inc(struct pf_addr *, sa_family_t);
void *pf_pull_hdr(struct mbuf *, int, void *, int, u_short *, u_short *,
sa_family_t);
-void pf_change_a(void *, u_int32_t);
+void pf_change_a(void *, u_int16_t *, u_int32_t, u_int8_t);
int pflog_packet(struct pf_pdesc *, u_int8_t, struct pf_rule *,
struct pf_rule *, struct pf_ruleset *);
void pf_send_deferred_syn(struct pf_state *);
@@ -1827,7 +1829,7 @@ struct pf_state_key *pf_alloc_state_key(int);
void pf_pkt_addr_changed(struct mbuf *);
int pf_state_key_attach(struct pf_state_key *, struct pf_state *, int);
int pf_translate(struct pf_pdesc *, struct pf_addr *, u_int16_t,
- struct pf_addr *, u_int16_t, u_int16_t, int, struct mbuf *);
+ struct pf_addr *, u_int16_t, u_int16_t, int);
int pf_translate_af(struct pf_pdesc *);
void pf_route(struct mbuf **, struct pf_rule *, int,
struct ifnet *, struct pf_state *);
@@ -1982,8 +1984,6 @@ int pf_map_addr(sa_family_t, struct pf_rule *,
int pf_postprocess_addr(struct pf_state *);
-void pf_cksum(struct pf_pdesc *, struct mbuf *);
-
#endif /* _KERNEL */
diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c
index efaa96609bc..3ac5f4b995d 100644
--- a/sys/netinet/ip_input.c
+++ b/sys/netinet/ip_input.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_input.c,v 1.199 2012/11/01 07:55:56 henning Exp $ */
+/* $OpenBSD: ip_input.c,v 1.200 2012/11/06 12:32:42 henning Exp $ */
/* $NetBSD: ip_input.c,v 1.30 1996/03/16 23:53:58 christos Exp $ */
/*
@@ -500,9 +500,6 @@ ipv4_input(struct mbuf *m)
return;
ours:
- /* pf might have modified stuff, might have to chksum */
- in_proto_cksum_out(m, NULL);
-
/*
* If offset or IP_MF are set, must reassemble.
* Otherwise, nothing need be done.
diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c
index a156cb44833..b2477a6714b 100644
--- a/sys/netinet/ip_output.c
+++ b/sys/netinet/ip_output.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_output.c,v 1.234 2012/11/05 21:49:15 claudio Exp $ */
+/* $OpenBSD: ip_output.c,v 1.235 2012/11/06 12:32:42 henning Exp $ */
/* $NetBSD: ip_output.c,v 1.28 1996/02/13 23:43:07 christos Exp $ */
/*
@@ -627,7 +627,6 @@ sendit:
* What's the behaviour?
*/
#endif
- in_proto_cksum_out(m, encif);
/* Check if we are allowed to fragment */
if (ip_mtudisc && (ip->ip_off & htons(IP_DF)) && tdb->tdb_mtu &&
@@ -698,6 +697,8 @@ sendit:
}
#endif /* IPSEC */
+ in_proto_cksum_out(m, ifp);
+
/*
* Packet filter
*/
@@ -723,7 +724,6 @@ sendit:
goto reroute;
}
#endif
- in_proto_cksum_out(m, ifp);
#ifdef IPSEC
if (ipsec_in_use && (flags & IP_FORWARDING) && (ipforwarding == 2) &&
diff --git a/sys/netinet6/in6.h b/sys/netinet6/in6.h
index ad01de151cb..778e8784ce6 100644
--- a/sys/netinet6/in6.h
+++ b/sys/netinet6/in6.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: in6.h,v 1.60 2012/11/01 07:55:56 henning Exp $ */
+/* $OpenBSD: in6.h,v 1.61 2012/11/06 12:32:42 henning Exp $ */
/* $KAME: in6.h,v 1.83 2001/03/29 02:55:07 jinmei Exp $ */
/*
@@ -758,7 +758,6 @@ struct ip6_mtuinfo {
struct cmsghdr;
int in6_cksum(struct mbuf *, u_int8_t, u_int32_t, u_int32_t);
-extern void in6_proto_cksum_out(struct mbuf *, struct ifnet *);
int in6_localaddr(struct in6_addr *);
int in6_addrscope(struct in6_addr *);
struct in6_ifaddr *in6_ifawithscope(struct ifnet *, struct in6_addr *, u_int);
diff --git a/sys/netinet6/ip6_divert.c b/sys/netinet6/ip6_divert.c
index 603c7995625..c985cdfec1d 100644
--- a/sys/netinet6/ip6_divert.c
+++ b/sys/netinet6/ip6_divert.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip6_divert.c,v 1.7 2012/11/01 07:55:56 henning Exp $ */
+/* $OpenBSD: ip6_divert.c,v 1.8 2012/11/06 12:32:42 henning Exp $ */
/*
* Copyright (c) 2009 Michele Marchetto <michele@openbsd.org>
@@ -188,9 +188,6 @@ divert6_packet(struct mbuf *m, int dir)
break;
}
}
- /* force checksum calculation */
- if (dir == PF_OUT)
- in6_proto_cksum_out(m, NULL);
if (inp != CIRCLEQ_END(&divb6table.inpt_queue)) {
sa = inp->inp_socket;
diff --git a/sys/netinet6/ip6_forward.c b/sys/netinet6/ip6_forward.c
index 2cb614c2bb7..caa67d3099d 100644
--- a/sys/netinet6/ip6_forward.c
+++ b/sys/netinet6/ip6_forward.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip6_forward.c,v 1.56 2012/11/05 21:49:15 claudio Exp $ */
+/* $OpenBSD: ip6_forward.c,v 1.57 2012/11/06 12:32:42 henning Exp $ */
/* $KAME: ip6_forward.c,v 1.75 2001/06/29 12:42:13 jinmei Exp $ */
/*
@@ -370,7 +370,6 @@ reroute:
* What's the behaviour?
*/
#endif
- in6_proto_cksum_out(m, encif);
m->m_flags &= ~(M_BCAST | M_MCAST); /* just in case */
@@ -471,6 +470,7 @@ reroute:
}
if (m == NULL)
goto senderr;
+
ip6 = mtod(m, struct ip6_hdr *);
if ((m->m_pkthdr.pf.flags & (PF_TAG_REROUTE | PF_TAG_GENERATED)) ==
(PF_TAG_REROUTE | PF_TAG_GENERATED)) {
@@ -483,7 +483,6 @@ reroute:
goto reroute;
}
#endif
- in6_proto_cksum_out(m, rt->rt_ifp);
/* Check the size after pf_test to give pf a chance to refragment. */
if (m->m_pkthdr.len > IN6_LINKMTU(rt->rt_ifp)) {
diff --git a/sys/netinet6/ip6_input.c b/sys/netinet6/ip6_input.c
index 3cbd344b3da..e45b80885d0 100644
--- a/sys/netinet6/ip6_input.c
+++ b/sys/netinet6/ip6_input.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip6_input.c,v 1.104 2012/11/01 07:55:56 henning Exp $ */
+/* $OpenBSD: ip6_input.c,v 1.105 2012/11/06 12:32:42 henning Exp $ */
/* $KAME: ip6_input.c,v 1.188 2001/03/29 05:34:31 itojun Exp $ */
/*
@@ -670,9 +670,6 @@ ip6_input(struct mbuf *m)
return;
}
- /* pf might have changed things */
- in6_proto_cksum_out(m, NULL);
-
ip6 = mtod(m, struct ip6_hdr *);
/*
diff --git a/sys/netinet6/ip6_output.c b/sys/netinet6/ip6_output.c
index 8ac4566b4b9..cc271fe7cf4 100644
--- a/sys/netinet6/ip6_output.c
+++ b/sys/netinet6/ip6_output.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip6_output.c,v 1.131 2012/11/05 21:49:15 claudio Exp $ */
+/* $OpenBSD: ip6_output.c,v 1.132 2012/11/06 12:32:42 henning Exp $ */
/* $KAME: ip6_output.c,v 1.172 2001/03/25 09:55:56 itojun Exp $ */
/*
@@ -134,8 +134,6 @@ int ip6_splithdr(struct mbuf *, struct ip6_exthdrs *);
int ip6_getpmtu(struct route_in6 *, struct route_in6 *,
struct ifnet *, struct in6_addr *, u_long *, int *);
int copypktopts(struct ip6_pktopts *, struct ip6_pktopts *, int);
-void in6_delayed_cksum(struct mbuf *, u_int8_t);
-void in6_proto_cksum_out(struct mbuf *, struct ifnet *);
/* Context for non-repeating IDs */
struct idgen32_ctx ip6_id_ctx;
@@ -543,7 +541,6 @@ reroute:
* What's the behaviour?
*/
#endif
- in6_proto_cksum_out(m, encif);
m->m_flags &= ~(M_BCAST | M_MCAST); /* just in case */
@@ -819,7 +816,6 @@ reroute:
goto reroute;
}
#endif
- in6_proto_cksum_out(m, ifp);
/*
* Send the packet to the outgoing interface.
@@ -3218,62 +3214,3 @@ ip6_randomid_init(void)
{
idgen32_init(&ip6_id_ctx);
}
-
-/*
- * Process a delayed payload checksum calculation.
- */
-void
-in6_delayed_cksum(struct mbuf *m, u_int8_t nxt)
-{
- int nxtp, offset;
- u_int16_t csum;
-
- offset = ip6_lasthdr(m, 0, IPPROTO_IPV6, &nxtp);
- if (offset <= 0 || nxtp != nxt)
- /* If the desired next protocol isn't found, punt. */
- return;
-
- csum = (u_int16_t)(in6_cksum(m, nxt, offset, m->m_pkthdr.len - offset));
-
- switch (nxt) {
- case IPPROTO_TCP:
- offset += offsetof(struct tcphdr, th_sum);
- break;
-
- case IPPROTO_UDP:
- offset += offsetof(struct udphdr, uh_sum);
- if (csum == 0)
- csum = 0xffff;
- break;
-
- case IPPROTO_ICMPV6:
- offset += offsetof(struct icmp6_hdr, icmp6_cksum);
- break;
- }
-
- if ((offset + sizeof(u_int16_t)) > m->m_len)
- m_copyback(m, offset, sizeof(csum), &csum, M_NOWAIT);
- else
- *(u_int16_t *)(mtod(m, caddr_t) + offset) = csum;
-}
-
-void
-in6_proto_cksum_out(struct mbuf *m, struct ifnet *ifp)
-{
- if (m->m_pkthdr.csum_flags & M_TCP_CSUM_OUT) {
- if (!ifp || !(ifp->if_capabilities & IFCAP_CSUM_TCPv6) ||
- ifp->if_bridgeport != NULL) {
- in6_delayed_cksum(m, IPPROTO_TCP);
- m->m_pkthdr.csum_flags &= ~M_TCP_CSUM_OUT; /* Clear */
- }
- } else if (m->m_pkthdr.csum_flags & M_UDP_CSUM_OUT) {
- if (!ifp || !(ifp->if_capabilities & IFCAP_CSUM_UDPv6) ||
- ifp->if_bridgeport != NULL) {
- in6_delayed_cksum(m, IPPROTO_UDP);
- m->m_pkthdr.csum_flags &= ~M_UDP_CSUM_OUT; /* Clear */
- }
- } else if (m->m_pkthdr.csum_flags & M_ICMP_CSUM_OUT) {
- in6_delayed_cksum(m, IPPROTO_ICMPV6);
- m->m_pkthdr.csum_flags &= ~M_ICMP_CSUM_OUT; /* Clear */
- }
-}