389 lines
12 KiB
Diff
389 lines
12 KiB
Diff
--- sys/contrib/pf/net/pf.c.orig
|
|
+++ sys/contrib/pf/net/pf.c
|
|
@@ -239,7 +239,7 @@
|
|
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 mbuf *, struct pf_addr *, u_int16_t *,
|
|
u_int16_t *, u_int16_t *, struct pf_addr *,
|
|
u_int16_t, u_int8_t, sa_family_t);
|
|
int pf_modulate_sack(struct mbuf *, int, struct pf_pdesc *,
|
|
@@ -2007,6 +2007,22 @@
|
|
}
|
|
}
|
|
|
|
+/**
|
|
+ * Checksum updates are a little complicated because the checksum in the TCP/UDP
|
|
+ * header isn't always a full checksum. In some cases (i.e. output) it's a
|
|
+ * pseudo-header checksum, which is a partial checksum over src/dst IP
|
|
+ * addresses, protocol number and length.
|
|
+ *
|
|
+ * That means we have the following cases:
|
|
+ * * Input or forwarding: we don't have TSO, the checksum fields are full
|
|
+ * checksums, we need to update the checksum whenever we change anything.
|
|
+ * * Output (i.e. the checksum is a pseudo-header checksum):
|
|
+ * x The field being updated is src/dst address or affects the length of
|
|
+ * the packet. We need to update the pseudo-header checksum (note that this
|
|
+ * checksum is not ones' complement).
|
|
+ * x Some other field is being modified (e.g. src/dst port numbers): We
|
|
+ * don't have to update anything.
|
|
+ **/
|
|
u_int16_t
|
|
pf_cksum_fixup(u_int16_t cksum, u_int16_t old, u_int16_t new, u_int8_t udp)
|
|
{
|
|
@@ -2022,9 +2038,20 @@
|
|
return (l);
|
|
}
|
|
|
|
+u_int16_t
|
|
+pf_proto_cksum_fixup(struct mbuf *m, u_int16_t cksum, u_int16_t old,
|
|
+ u_int16_t new, u_int8_t udp)
|
|
+{
|
|
+ if (m->m_pkthdr.csum_flags & (CSUM_DELAY_DATA | CSUM_DELAY_DATA_IPV6))
|
|
+ return (cksum);
|
|
+
|
|
+ return (pf_cksum_fixup(cksum, old, new, udp));
|
|
+}
|
|
+
|
|
void
|
|
-pf_change_ap(struct pf_addr *a, u_int16_t *p, u_int16_t *ic, u_int16_t *pc,
|
|
- struct pf_addr *an, u_int16_t pn, u_int8_t u, sa_family_t af)
|
|
+pf_change_ap(struct mbuf *m, struct pf_addr *a, u_int16_t *p, u_int16_t *ic,
|
|
+ u_int16_t *pc, struct pf_addr *an, u_int16_t pn, u_int8_t u,
|
|
+ sa_family_t af)
|
|
{
|
|
struct pf_addr ao;
|
|
u_int16_t po = *p;
|
|
@@ -2032,6 +2059,9 @@
|
|
PF_ACPY(&ao, a, af);
|
|
PF_ACPY(a, an, af);
|
|
|
|
+ if (m->m_pkthdr.csum_flags & (CSUM_DELAY_DATA | CSUM_DELAY_DATA_IPV6))
|
|
+ *pc = ~*pc;
|
|
+
|
|
*p = pn;
|
|
|
|
switch (af) {
|
|
@@ -2041,17 +2071,19 @@
|
|
ao.addr16[0], an->addr16[0], 0),
|
|
ao.addr16[1], an->addr16[1], 0);
|
|
*p = pn;
|
|
- *pc = pf_cksum_fixup(pf_cksum_fixup(pf_cksum_fixup(*pc,
|
|
+
|
|
+ *pc = pf_cksum_fixup(pf_cksum_fixup(*pc,
|
|
ao.addr16[0], an->addr16[0], u),
|
|
- ao.addr16[1], an->addr16[1], u),
|
|
- po, pn, u);
|
|
+ ao.addr16[1], an->addr16[1], u);
|
|
+
|
|
+ *pc = pf_proto_cksum_fixup(m, *pc, po, pn, u);
|
|
break;
|
|
#endif /* INET */
|
|
#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,
|
|
+ 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),
|
|
@@ -2059,13 +2091,20 @@
|
|
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);
|
|
+ ao.addr16[7], an->addr16[7], u);
|
|
+
|
|
+ *pc = pf_proto_cksum_fixup(m, *pc, po, pn, u);
|
|
break;
|
|
#endif /* INET6 */
|
|
}
|
|
-}
|
|
|
|
+ if (m->m_pkthdr.csum_flags & (CSUM_DELAY_DATA |
|
|
+ CSUM_DELAY_DATA_IPV6)) {
|
|
+ *pc = ~*pc;
|
|
+ if (! *pc)
|
|
+ *pc = 0xffff;
|
|
+ }
|
|
+}
|
|
|
|
/* Changes a u_int32_t. Uses a void * so there are no align restrictions */
|
|
void
|
|
@@ -2079,6 +2118,19 @@
|
|
ao % 65536, an % 65536, u);
|
|
}
|
|
|
|
+void
|
|
+pf_change_proto_a(struct mbuf *m, void *a, u_int16_t *c, u_int32_t an, u_int8_t udp)
|
|
+{
|
|
+ u_int32_t ao;
|
|
+
|
|
+ memcpy(&ao, a, sizeof(ao));
|
|
+ memcpy(a, &an, sizeof(u_int32_t));
|
|
+
|
|
+ *c = pf_proto_cksum_fixup(m,
|
|
+ pf_proto_cksum_fixup(m, *c, ao / 65536, an / 65536, udp),
|
|
+ ao % 65536, an % 65536, udp);
|
|
+}
|
|
+
|
|
#ifdef INET6
|
|
void
|
|
pf_change_a6(struct pf_addr *a, u_int16_t *c, struct pf_addr *an, u_int8_t u)
|
|
@@ -2228,12 +2280,10 @@
|
|
for (i = 2; i + TCPOLEN_SACK <= olen;
|
|
i += TCPOLEN_SACK) {
|
|
memcpy(&sack, &opt[i], sizeof(sack));
|
|
- pf_change_a(&sack.start, &th->th_sum,
|
|
- htonl(ntohl(sack.start) -
|
|
- dst->seqdiff), 0);
|
|
- pf_change_a(&sack.end, &th->th_sum,
|
|
- htonl(ntohl(sack.end) -
|
|
- dst->seqdiff), 0);
|
|
+ pf_change_proto_a(m, &sack.start, &th->th_sum,
|
|
+ htonl(ntohl(sack.start) - dst->seqdiff), 0);
|
|
+ pf_change_proto_a(m, &sack.end, &th->th_sum,
|
|
+ htonl(ntohl(sack.end) - dst->seqdiff), 0);
|
|
memcpy(&opt[i], &sack, sizeof(sack));
|
|
}
|
|
copyback = 1;
|
|
@@ -3400,7 +3450,7 @@
|
|
|
|
if (PF_ANEQ(saddr, &nk->addr[pd->sidx], af) ||
|
|
nk->port[pd->sidx] != sport) {
|
|
- pf_change_ap(saddr, &th->th_sport, pd->ip_sum,
|
|
+ pf_change_ap(m, saddr, &th->th_sport, pd->ip_sum,
|
|
&th->th_sum, &nk->addr[pd->sidx],
|
|
nk->port[pd->sidx], 0, af);
|
|
pd->sport = &th->th_sport;
|
|
@@ -3409,7 +3459,7 @@
|
|
|
|
if (PF_ANEQ(daddr, &nk->addr[pd->didx], af) ||
|
|
nk->port[pd->didx] != dport) {
|
|
- pf_change_ap(daddr, &th->th_dport, pd->ip_sum,
|
|
+ pf_change_ap(m, daddr, &th->th_dport, pd->ip_sum,
|
|
&th->th_sum, &nk->addr[pd->didx],
|
|
nk->port[pd->didx], 0, af);
|
|
dport = th->th_dport;
|
|
@@ -3423,7 +3473,7 @@
|
|
|
|
if (PF_ANEQ(saddr, &nk->addr[pd->sidx], af) ||
|
|
nk->port[pd->sidx] != sport) {
|
|
- pf_change_ap(saddr, &pd->hdr.udp->uh_sport,
|
|
+ pf_change_ap(m, saddr, &pd->hdr.udp->uh_sport,
|
|
pd->ip_sum, &pd->hdr.udp->uh_sum,
|
|
&nk->addr[pd->sidx],
|
|
nk->port[pd->sidx], 1, af);
|
|
@@ -3433,7 +3483,7 @@
|
|
|
|
if (PF_ANEQ(daddr, &nk->addr[pd->didx], af) ||
|
|
nk->port[pd->didx] != dport) {
|
|
- pf_change_ap(daddr, &pd->hdr.udp->uh_dport,
|
|
+ pf_change_ap(m, daddr, &pd->hdr.udp->uh_dport,
|
|
pd->ip_sum, &pd->hdr.udp->uh_sum,
|
|
&nk->addr[pd->didx],
|
|
nk->port[pd->didx], 1, af);
|
|
@@ -3845,7 +3895,7 @@
|
|
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,
|
|
+ pf_change_proto_a(m, &th->th_seq, &th->th_sum,
|
|
htonl(s->src.seqlo + s->src.seqdiff), 0);
|
|
*rewrite = 1;
|
|
} else
|
|
@@ -4175,9 +4225,9 @@
|
|
while ((src->seqdiff = arc4random() - seq) == 0)
|
|
;
|
|
ack = ntohl(th->th_ack) - dst->seqdiff;
|
|
- pf_change_a(&th->th_seq, &th->th_sum, htonl(seq +
|
|
+ pf_change_proto_a(m, &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_proto_a(m, &th->th_ack, &th->th_sum, htonl(ack), 0);
|
|
*copyback = 1;
|
|
} else {
|
|
ack = ntohl(th->th_ack);
|
|
@@ -4227,9 +4277,9 @@
|
|
ack = ntohl(th->th_ack) - dst->seqdiff;
|
|
if (src->seqdiff) {
|
|
/* Modulate sequence numbers */
|
|
- pf_change_a(&th->th_seq, &th->th_sum, htonl(seq +
|
|
+ pf_change_proto_a(m, &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_proto_a(m, &th->th_ack, &th->th_sum, htonl(ack), 0);
|
|
*copyback = 1;
|
|
}
|
|
end = seq + pd->p_len;
|
|
@@ -4729,14 +4779,14 @@
|
|
|
|
if (PF_ANEQ(pd->src, &nk->addr[pd->sidx], pd->af) ||
|
|
nk->port[pd->sidx] != th->th_sport)
|
|
- pf_change_ap(pd->src, &th->th_sport, pd->ip_sum,
|
|
- &th->th_sum, &nk->addr[pd->sidx],
|
|
+ pf_change_ap(m, pd->src, &th->th_sport,
|
|
+ pd->ip_sum, &th->th_sum, &nk->addr[pd->sidx],
|
|
nk->port[pd->sidx], 0, pd->af);
|
|
|
|
if (PF_ANEQ(pd->dst, &nk->addr[pd->didx], pd->af) ||
|
|
nk->port[pd->didx] != th->th_dport)
|
|
- pf_change_ap(pd->dst, &th->th_dport, pd->ip_sum,
|
|
- &th->th_sum, &nk->addr[pd->didx],
|
|
+ pf_change_ap(m, pd->dst, &th->th_dport,
|
|
+ pd->ip_sum, &th->th_sum, &nk->addr[pd->didx],
|
|
nk->port[pd->didx], 0, pd->af);
|
|
copyback = 1;
|
|
}
|
|
@@ -4807,13 +4857,13 @@
|
|
|
|
if (PF_ANEQ(pd->src, &nk->addr[pd->sidx], pd->af) ||
|
|
nk->port[pd->sidx] != uh->uh_sport)
|
|
- pf_change_ap(pd->src, &uh->uh_sport, pd->ip_sum,
|
|
+ pf_change_ap(m, pd->src, &uh->uh_sport, pd->ip_sum,
|
|
&uh->uh_sum, &nk->addr[pd->sidx],
|
|
nk->port[pd->sidx], 1, pd->af);
|
|
|
|
if (PF_ANEQ(pd->dst, &nk->addr[pd->didx], pd->af) ||
|
|
nk->port[pd->didx] != uh->uh_dport)
|
|
- pf_change_ap(pd->dst, &uh->uh_dport, pd->ip_sum,
|
|
+ pf_change_ap(m, pd->dst, &uh->uh_dport, pd->ip_sum,
|
|
&uh->uh_sum, &nk->addr[pd->didx],
|
|
nk->port[pd->didx], 1, pd->af);
|
|
#ifdef __FreeBSD__
|
|
@@ -6290,6 +6340,13 @@
|
|
ip6 = mtod(m0, struct ip6_hdr *);
|
|
}
|
|
|
|
+ if (m0->m_pkthdr.csum_flags & CSUM_DELAY_DATA_IPV6 &
|
|
+ ~ifp->if_hwassist) {
|
|
+ uint32_t plen = m0->m_pkthdr.len - sizeof(*ip6);
|
|
+ in6_delayed_cksum(m0, plen, sizeof(struct ip6_hdr));
|
|
+ m0->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA_IPV6;
|
|
+ }
|
|
+
|
|
/*
|
|
* If the packet is too large for the outgoing interface,
|
|
* send back an icmp6 error.
|
|
--- sys/contrib/pf/net/pf_ioctl.c.orig
|
|
+++ sys/contrib/pf/net/pf_ioctl.c
|
|
@@ -4158,11 +4158,6 @@
|
|
struct ip *h = NULL;
|
|
int chk;
|
|
|
|
- /* We need a proper CSUM befor we start (s. OpenBSD ip_output) */
|
|
- if ((*m)->m_pkthdr.csum_flags & CSUM_DELAY_DATA) {
|
|
- in_delayed_cksum(*m);
|
|
- (*m)->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA;
|
|
- }
|
|
if ((*m)->m_pkthdr.len >= (int)sizeof(*h)) {
|
|
/* if m_pkthdr.len is less than ip header, pf will handle. */
|
|
h = mtod(*m, struct ip *);
|
|
@@ -4222,14 +4217,6 @@
|
|
*/
|
|
int chk;
|
|
|
|
- /* We need a proper CSUM before we start (s. OpenBSD ip_output) */
|
|
- if ((*m)->m_pkthdr.csum_flags & CSUM_DELAY_DATA) {
|
|
-#ifdef INET
|
|
- /* XXX-BZ copy&paste error from r126261? */
|
|
- in_delayed_cksum(*m);
|
|
-#endif
|
|
- (*m)->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA;
|
|
- }
|
|
CURVNET_SET(ifp->if_vnet);
|
|
chk = pf_test6(PF_OUT, ifp, m, NULL, inp);
|
|
CURVNET_RESTORE();
|
|
--- sys/contrib/pf/net/pf_norm.c.orig
|
|
+++ sys/contrib/pf/net/pf_norm.c
|
|
@@ -1657,13 +1657,14 @@
|
|
th->th_x2 = 0;
|
|
nv = *(u_int16_t *)(&th->th_ack + 1);
|
|
|
|
- th->th_sum = pf_cksum_fixup(th->th_sum, ov, nv, 0);
|
|
+ th->th_sum = pf_proto_cksum_fixup(m, 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_sum = pf_proto_cksum_fixup(m, th->th_sum, th->th_urp,
|
|
+ 0, 0);
|
|
th->th_urp = 0;
|
|
rewrite = 1;
|
|
}
|
|
@@ -1889,7 +1890,7 @@
|
|
(src->scrub->pfss_flags &
|
|
PFSS_TIMESTAMP)) {
|
|
tsval = ntohl(tsval);
|
|
- pf_change_a(&opt[2],
|
|
+ pf_change_proto_a(m, &opt[2],
|
|
&th->th_sum,
|
|
htonl(tsval +
|
|
src->scrub->pfss_ts_mod),
|
|
@@ -1905,7 +1906,7 @@
|
|
PFSS_TIMESTAMP)) {
|
|
tsecr = ntohl(tsecr)
|
|
- dst->scrub->pfss_ts_mod;
|
|
- pf_change_a(&opt[6],
|
|
+ pf_change_proto_a(m, &opt[6],
|
|
&th->th_sum, htonl(tsecr),
|
|
0);
|
|
copyback = 1;
|
|
@@ -2286,8 +2287,8 @@
|
|
case TCPOPT_MAXSEG:
|
|
mss = (u_int16_t *)(optp + 2);
|
|
if ((ntohs(*mss)) > r->max_mss) {
|
|
- th->th_sum = pf_cksum_fixup(th->th_sum,
|
|
- *mss, htons(r->max_mss), 0);
|
|
+ th->th_sum = pf_proto_cksum_fixup(m,
|
|
+ th->th_sum, *mss, htons(r->max_mss), 0);
|
|
*mss = htons(r->max_mss);
|
|
rewrite = 1;
|
|
}
|
|
--- sys/contrib/pf/net/pfvar.h.orig
|
|
+++ sys/contrib/pf/net/pfvar.h
|
|
@@ -1909,6 +1909,8 @@
|
|
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 u_int16_t pf_proto_cksum_fixup(struct mbuf *, u_int16_t,
|
|
+ u_int16_t, u_int16_t, u_int8_t);
|
|
|
|
#ifdef __FreeBSD__
|
|
VNET_DECLARE(struct ifnet *, sync_ifp);
|
|
@@ -1954,6 +1956,9 @@
|
|
void *pf_pull_hdr(struct mbuf *, int, void *, int, u_short *, u_short *,
|
|
sa_family_t);
|
|
void pf_change_a(void *, u_int16_t *, u_int32_t, u_int8_t);
|
|
+void pf_change_proto_a(struct mbuf *, void *, u_int16_t *, u_int32_t,
|
|
+ u_int8_t);
|
|
+void pf_change_tcp_a(struct mbuf *, void *, u_int16_t *, u_int32_t);
|
|
int pflog_packet(struct pfi_kif *, struct mbuf *, sa_family_t, u_int8_t,
|
|
u_int8_t, struct pf_rule *, struct pf_rule *, struct pf_ruleset *,
|
|
struct pf_pdesc *);
|
|
--- sys/netinet6/ip6_output.c.orig
|
|
+++ sys/netinet6/ip6_output.c
|
|
@@ -184,7 +184,7 @@
|
|
}\
|
|
} while (/*CONSTCOND*/ 0)
|
|
|
|
-static void
|
|
+void
|
|
in6_delayed_cksum(struct mbuf *m, uint32_t plen, u_short offset)
|
|
{
|
|
u_short csum;
|
|
--- sys/netinet6/ip6_var.h.orig
|
|
+++ sys/netinet6/ip6_var.h
|
|
@@ -456,6 +456,7 @@
|
|
struct rtentry **, u_int);
|
|
u_int32_t ip6_randomid(void);
|
|
u_int32_t ip6_randomflowlabel(void);
|
|
+void in6_delayed_cksum(struct mbuf *m, uint32_t plen, u_short offset);
|
|
#endif /* _KERNEL */
|
|
|
|
#endif /* !_NETINET6_IP6_VAR_H_ */
|