I haven't received any feedback on this from anybody not in edmonton right now. please help us by testing this as much as you can, or you might end up finding out it broke in your usage case after the next release when you upgrade your production boxes... we wanna avoid that, mkay?
* Henning Brauer <[email protected]> [2011-07-03 23:37]: > this just makes the eyes hurt: > *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, > and trust me, it's not just about the eyes. > > anyway. here is a complete revamp of the checksum handling in our > kernel. instead of mucking with them all the time we move to a model > where we assume the hardware will do it at the end. if we run into a > case where we don't have such hardware we apply band-aid in form of > calling the software implementation to re-do the checksums. note that > we're talking ip as well as protocol (tcp, udp, ...) checksums here. > > this has seen light testing but will need much much more. guess the > most interesting cases are forwarding boxes (routing as well as bridging, > the fooookin' bridge is very annoying here), especially with pf making > changes (e. g. all forms of NAT), and of course various tunnel > situations. > > contains traces of v6 code written by krw (thanks again!). 99% from > iceland by yours truly. it is a net minus and would be a way bigger > net minus if ipvshit wasn't so retarded. > > Index: net/if_bridge.c > =================================================================== > RCS file: /cvs/src/sys/net/if_bridge.c,v > retrieving revision 1.192 > diff -u -p -r1.192 if_bridge.c > --- net/if_bridge.c 16 May 2011 20:06:28 -0000 1.192 > +++ net/if_bridge.c 3 Jul 2011 19:16:05 -0000 > @@ -1061,15 +1061,6 @@ bridge_output(struct ifnet *ifp, struct > 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) { > @@ -2459,6 +2450,8 @@ bridge_ipsec(struct bridge_softc *sc, st > m_freem(m); > return (1); > } > + if (m) > + in_proto_cksum_out(m, encif); > break; > #endif /* INET */ > #ifdef INET6 > @@ -2470,6 +2463,8 @@ bridge_ipsec(struct bridge_softc *sc, st > m_freem(m); > return (1); > } > + if (m) > + in6_proto_cksum_out(m, encif); > break; > #endif /* INET6 */ > } > @@ -2627,6 +2622,7 @@ bridge_ip(struct bridge_softc *sc, int d > 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)) { > @@ -2672,6 +2668,7 @@ bridge_ip(struct bridge_softc *sc, int d > if (m == NULL) > return (NULL); > #endif /* NPF > 0 */ > + in6_proto_cksum_out(m, ifp); > > break; > } > Index: net/if_pflog.c > =================================================================== > RCS file: /cvs/src/sys/net/if_pflog.c,v > retrieving revision 1.35 > diff -u -p -r1.35 if_pflog.c > --- net/if_pflog.c 20 Jun 2011 19:03:41 -0000 1.35 > +++ net/if_pflog.c 3 Jul 2011 19:16:05 -0000 > @@ -347,7 +347,7 @@ pflog_bpfcopy(const void *src_arg, void > > if ((pfloghdr->rewritten = pf_translate(&pd, &pfloghdr->saddr, > pfloghdr->sport, &pfloghdr->daddr, pfloghdr->dport, 0, > - pfloghdr->dir))) { > + pfloghdr->dir, mfake))) { > m_copyback(mfake, off, min(mfake->m_len - off, hdrlen), > pd.hdr.any, M_NOWAIT); > PF_ACPY(&pfloghdr->saddr, &osaddr, pd.af); > Index: net/pf.c > =================================================================== > RCS file: /cvs/src/sys/net/pf.c,v > retrieving revision 1.754 > diff -u -p -r1.754 pf.c > --- net/pf.c 3 Jul 2011 18:42:45 -0000 1.754 > +++ net/pf.c 3 Jul 2011 19:16:07 -0000 > @@ -2,7 +2,7 @@ > > /* > * Copyright (c) 2001 Daniel Hartmeier > - * Copyright (c) 2002 - 2010 Henning Brauer > + * Copyright (c) 2002 - 2011 Henning Brauer > * All rights reserved. > * > * Redistribution and use in source and binary forms, with or without > @@ -147,20 +147,17 @@ void pf_add_threshold(struct > pf_thres > int pf_check_threshold(struct pf_threshold *); > > void pf_change_ap(struct pf_addr *, u_int16_t *, > - u_int16_t *, struct pf_addr *, u_int16_t, > - u_int8_t, sa_family_t); > + struct pf_addr *, u_int16_t, sa_family_t); > int pf_modulate_sack(struct mbuf *, int, struct pf_pdesc *, > struct tcphdr *, struct pf_state_peer *); > #ifdef INET6 > -void pf_change_a6(struct pf_addr *, u_int16_t *, > - struct pf_addr *, u_int8_t); > +void pf_change_a6(struct pf_addr *, struct pf_addr *); > #endif /* INET6 */ > 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); > + sa_family_t); > void pf_send_tcp(const struct pf_rule *, sa_family_t, > const struct pf_addr *, const struct pf_addr *, > u_int16_t, u_int16_t, u_int32_t, u_int32_t, > @@ -1512,95 +1509,27 @@ pf_addr_wrap_neq(struct pf_addr_wrap *aw > } > } > > -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) > +pf_change_ap(struct pf_addr *a, u_int16_t *p, struct pf_addr *an, > + u_int16_t pn, sa_family_t af) > { > - struct pf_addr ao; > - u_int16_t po = *p; > - > - PF_ACPY(&ao, a, af); > PF_ACPY(a, an, af); > *p = pn; > - > - switch (af) { > -#ifdef INET > - 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; > -#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, > - 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; > -#endif /* INET6 */ > - } > } > > > /* 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(void *a, u_int32_t an) > { > - 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, u_int16_t *c, struct pf_addr *an, u_int8_t u) > +pf_change_a6(struct pf_addr *a, struct pf_addr *an) > { > - 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 */ > > @@ -1791,8 +1720,7 @@ pf_icmp_mapping(struct pf_pdesc *pd, u_i > > 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) > + struct pf_addr *na, u_int16_t np, sa_family_t af) > { > struct pf_addr oia, ooa; > > @@ -1800,72 +1728,16 @@ pf_change_icmp(struct pf_addr *ia, u_int > 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; > + /* 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 */ > - } > } > > > @@ -1902,12 +1774,12 @@ pf_modulate_sack(struct mbuf *m, int off > 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(&sack.start, > htonl(ntohl(sack.start) - > - dst->seqdiff), 0); > - pf_change_a(&sack.end, &th->th_sum, > + dst->seqdiff)); > + pf_change_a(&sack.end, > htonl(ntohl(sack.end) - > - dst->seqdiff), 0); > + dst->seqdiff)); > memcpy(&opt[i], &sack, sizeof(sack)); > } > copyback = 1; > @@ -3021,7 +2893,7 @@ pf_test_rule(struct pf_rule **rm, struct > rewrite += pf_translate(pd, > &sk->addr[pd->sidx], sk->port[pd->sidx], > &sk->addr[pd->didx], sk->port[pd->didx], > - virtual_type, icmp_dir); > + virtual_type, icmp_dir, m); > } > } else { > while ((ri = SLIST_FIRST(&rules))) { > @@ -3114,9 +2986,10 @@ pf_create_state(struct pf_rule *r, struc > 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(&th->th_seq, > + htonl(s->src.seqlo + s->src.seqdiff)); > *rewrite = 1; > + m->m_pkthdr.csum_flags |= M_TCP_CSUM_OUT; > } else > s->src.seqdiff = 0; > if (th->th_flags & TH_SYN) { > @@ -3253,7 +3126,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: > @@ -3268,28 +3141,28 @@ pf_translate(struct pf_pdesc *pd, struct > switch (pd->proto) { > case IPPROTO_TCP: > if (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); > + pf_change_ap(pd->src, pd->sport, saddr, sport, pd->af); > rewrite = 1; > } > if (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); > + pf_change_ap(pd->dst, pd->dport, daddr, dport, pd->af); > rewrite = 1; > } > + if (rewrite) > + m->m_pkthdr.csum_flags |= M_TCP_CSUM_OUT; > break; > > case IPPROTO_UDP: > if (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); > + pf_change_ap(pd->src, pd->sport, saddr, sport, pd->af); > rewrite = 1; > } > if (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); > + pf_change_ap(pd->dst, pd->dport, daddr, dport, pd->af); > rewrite = 1; > } > + if (rewrite) > + m->m_pkthdr.csum_flags |= M_UDP_CSUM_OUT; > break; > > #ifdef INET > @@ -3299,26 +3172,23 @@ pf_translate(struct pf_pdesc *pd, struct > return (0); > > 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->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->dst->v4.s_addr, daddr->v4.s_addr); > rewrite = 1; > } > if (virtual_type == htons(ICMP_ECHO)) { > 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; > } > } > + if (rewrite) > + m->m_pkthdr.csum_flags |= M_ICMP_CSUM_OUT; > break; > #endif /* INET */ > > @@ -3329,15 +3199,15 @@ pf_translate(struct pf_pdesc *pd, struct > return (0); > > if (PF_ANEQ(saddr, pd->src, pd->af)) { > - pf_change_a6(pd->src, &pd->hdr.icmp6->icmp6_cksum, > - saddr, 0); > + pf_change_a6(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->dst, daddr); > rewrite = 1; > } > + if (rewrite) > + m->m_pkthdr.csum_flags |= M_ICMP_CSUM_OUT; > break; > #endif /* INET6 */ > > @@ -3346,13 +3216,13 @@ pf_translate(struct pf_pdesc *pd, struct > #ifdef INET > case AF_INET: > 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->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->dst->v4.s_addr, > + daddr->v4.s_addr); > rewrite = 1; > } > break; > @@ -3360,11 +3230,11 @@ pf_translate(struct pf_pdesc *pd, struct > #ifdef INET6 > case AF_INET6: > if (PF_ANEQ(saddr, pd->src, pd->af)) { > - pf_change_a6(pd->src, NULL, saddr, 0); > + pf_change_a6(pd->src, saddr); > rewrite = 1; > } > if (PF_ANEQ(daddr, pd->dst, pd->af)) { > - pf_change_a6(pd->dst, NULL, daddr, 0); > + pf_change_a6(pd->dst, daddr); > rewrite = 1; > } > break; > @@ -3501,9 +3371,8 @@ pf_tcp_track_full(struct pf_state_peer * > 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(&th->th_seq, htonl(seq + src->seqdiff)); > + pf_change_a(&th->th_ack, htonl(ack)); > *copyback = 1; > } else { > ack = ntohl(th->th_ack); > @@ -3553,9 +3422,8 @@ pf_tcp_track_full(struct pf_state_peer * > 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(&th->th_seq, htonl(seq + src->seqdiff)); > + pf_change_a(&th->th_ack, htonl(ack)); > *copyback = 1; > } > end = seq + pd->p_len; > @@ -4006,22 +3874,24 @@ pf_test_state_tcp(struct pf_state **stat > > 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, &th->th_sum, > - &nk->addr[pd->sidx], nk->port[pd->sidx], 0, pd->af); > + pf_change_ap(pd->src, &th->th_sport, > + &nk->addr[pd->sidx], nk->port[pd->sidx], pd->af); > if (PF_ANEQ(pd->dst, &nk->addr[pd->didx], pd->af) || > pd->rdomain != nk->rdomain) > pd->destchg = 1; > 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, &th->th_sum, > - &nk->addr[pd->didx], nk->port[pd->didx], 0, pd->af); > + pf_change_ap(pd->dst, &th->th_dport, > + &nk->addr[pd->didx], nk->port[pd->didx], pd->af); > m->m_pkthdr.rdomain = nk->rdomain; > copyback = 1; > } > > /* Copyback sequence modulation or stateful scrub changes if needed */ > - if (copyback) > + if (copyback) { > m_copyback(m, off, sizeof(*th), th, M_NOWAIT); > + m->m_pkthdr.csum_flags |= M_TCP_CSUM_OUT; > + } > > return (PF_PASS); > } > @@ -4078,17 +3948,18 @@ pf_test_state_udp(struct pf_state **stat > > 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, &uh->uh_sum, > - &nk->addr[pd->sidx], nk->port[pd->sidx], 1, pd->af); > + pf_change_ap(pd->src, &uh->uh_sport, > + &nk->addr[pd->sidx], nk->port[pd->sidx], pd->af); > if (PF_ANEQ(pd->dst, &nk->addr[pd->didx], pd->af) || > pd->rdomain != nk->rdomain) > pd->destchg = 1; > 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, &uh->uh_sum, > - &nk->addr[pd->didx], nk->port[pd->didx], 1, pd->af); > + pf_change_ap(pd->dst, &uh->uh_dport, > + &nk->addr[pd->didx], nk->port[pd->didx], pd->af); > m->m_pkthdr.rdomain = nk->rdomain; > m_copyback(m, off, sizeof(*uh), uh, M_NOWAIT); > + m->m_pkthdr.csum_flags |= M_UDP_CSUM_OUT; > } > > return (PF_PASS); > @@ -4158,7 +4029,8 @@ pf_test_state_icmp(struct pf_state **sta > struct pf_addr *saddr = pd->src, *daddr = pd->dst; > u_int16_t icmpid, *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) { > @@ -4215,28 +4087,22 @@ pf_test_state_icmp(struct pf_state **sta > case AF_INET: > if (PF_ANEQ(pd->src, > &nk->addr[pd->sidx], AF_INET)) > - pf_change_a(&saddr->v4.s_addr, NULL, > - nk->addr[pd->sidx].v4.s_addr, 0); > + pf_change_a(&saddr->v4.s_addr, > + nk->addr[pd->sidx].v4.s_addr); > > if (PF_ANEQ(pd->dst, &nk->addr[pd->didx], > AF_INET)) { > - pf_change_a(&daddr->v4.s_addr, NULL, > - nk->addr[pd->didx].v4.s_addr, 0); > + pf_change_a(&daddr->v4.s_addr, > + nk->addr[pd->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(m, off, ICMP_MINLEN, > pd->hdr.icmp, M_NOWAIT); > + copyback = 1; > break; > #endif /* INET */ > #ifdef INET6 > @@ -4244,26 +4110,23 @@ pf_test_state_icmp(struct pf_state **sta > if (PF_ANEQ(pd->src, > &nk->addr[pd->sidx], AF_INET6)) > pf_change_a6(saddr, > - &pd->hdr.icmp6->icmp6_cksum, > - &nk->addr[pd->sidx], 0); > + &nk->addr[pd->sidx]); > > if (PF_ANEQ(pd->dst, > &nk->addr[pd->didx], AF_INET6)) { > pf_change_a6(daddr, > - &pd->hdr.icmp6->icmp6_cksum, > - &nk->addr[pd->didx], 0); > + &nk->addr[pd->didx]); > pd->destchg = 1; > } > > m_copyback(m, off, > sizeof(struct icmp6_hdr), > pd->hdr.icmp6, M_NOWAIT); > + copyback = 1; > break; > #endif /* INET6 */ > } > } > - return (PF_PASS); > - > } else { > /* > * ICMP error message in response to a TCP/UDP packet. > @@ -4377,7 +4240,6 @@ pf_test_state_icmp(struct pf_state **sta > 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 > @@ -4417,8 +4279,7 @@ pf_test_state_icmp(struct pf_state **sta > /* 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(&th.th_seq, htonl(seq)); > copyback = 1; > } > > @@ -4463,8 +4324,7 @@ pf_test_state_icmp(struct pf_state **sta > 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, > - pd2.ip_sum, icmpsum, 0, pd2.af); > + nk->port[pd2.sidx], pd2.af); > > if (PF_ANEQ(pd2.dst, &nk->addr[pd2.didx], > pd2.af) || pd2.rdomain != nk->rdomain) > @@ -4476,8 +4336,7 @@ pf_test_state_icmp(struct pf_state **sta > 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, > - pd2.ip_sum, icmpsum, 0, pd2.af); > + nk->port[pd2.didx], pd2.af); > copyback = 1; > } > > @@ -4503,8 +4362,6 @@ pf_test_state_icmp(struct pf_state **sta > } > m_copyback(m, off2, 8, &th, M_NOWAIT); > } > - > - return (PF_PASS); > break; > } > case IPPROTO_UDP: { > @@ -4538,8 +4395,7 @@ pf_test_state_icmp(struct pf_state **sta > 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, > - pd2.ip_sum, icmpsum, 1, pd2.af); > + nk->port[pd2.sidx], pd2.af); > > if (PF_ANEQ(pd2.dst, &nk->addr[pd2.didx], > pd2.af) || pd2.rdomain != nk->rdomain) > @@ -4551,8 +4407,7 @@ pf_test_state_icmp(struct pf_state **sta > 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, > - pd2.ip_sum, icmpsum, 1, pd2.af); > + nk->port[pd2.didx], pd2.af); > > switch (pd2.af) { > #ifdef INET > @@ -4573,9 +4428,10 @@ pf_test_state_icmp(struct pf_state **sta > break; > #endif /* INET6 */ > } > + uh.uh_sum = 0; > m_copyback(m, off2, sizeof(uh), &uh, M_NOWAIT); > + copyback = 1; > } > - return (PF_PASS); > break; > } > #ifdef INET > @@ -4614,8 +4470,7 @@ pf_test_state_icmp(struct pf_state **sta > &iih.icmp_id : NULL, > daddr, &nk->addr[pd2.sidx], > (virtual_type == htons(ICMP_ECHO)) ? > - nk->port[iidx] : 0, NULL, > - pd2.ip_sum, 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) > @@ -4625,8 +4480,7 @@ pf_test_state_icmp(struct pf_state **sta > if (PF_ANEQ(pd2.dst, > &nk->addr[pd2.didx], pd2.af)) > pf_change_icmp(pd2.dst, NULL, saddr, > - &nk->addr[pd2.didx], 0, NULL, > - pd2.ip_sum, icmpsum, 0, AF_INET); > + &nk->addr[pd2.didx], 0, AF_INET); > > m_copyback(m, off, ICMP_MINLEN, pd->hdr.icmp, > M_NOWAIT); > @@ -4634,8 +4488,8 @@ pf_test_state_icmp(struct pf_state **sta > M_NOWAIT); > m_copyback(m, off2, ICMP_MINLEN, &iih, > M_NOWAIT); > + copyback = 1; > } > - return (PF_PASS); > break; > } > #endif /* INET */ > @@ -4687,8 +4541,7 @@ pf_test_state_icmp(struct pf_state **sta > daddr, &nk->addr[pd2.sidx], > (virtual_type == > htons(ICMP6_ECHO_REQUEST)) > - ? nk->port[iidx] : 0, NULL, > - pd2.ip_sum, 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) > @@ -4698,8 +4551,7 @@ pf_test_state_icmp(struct pf_state **sta > if (PF_ANEQ(pd2.dst, > &nk->addr[pd2.didx], pd2.af)) > pf_change_icmp(pd2.dst, NULL, saddr, > - &nk->addr[pd2.didx], 0, NULL, > - pd2.ip_sum, icmpsum, 0, AF_INET6); > + &nk->addr[pd2.didx], 0, AF_INET6); > > m_copyback(m, off, sizeof(struct icmp6_hdr), > pd->hdr.icmp6, M_NOWAIT); > @@ -4707,8 +4559,8 @@ pf_test_state_icmp(struct pf_state **sta > M_NOWAIT); > m_copyback(m, off2, sizeof(struct icmp6_hdr), > &iih, M_NOWAIT); > + copyback = 1; > } > - return (PF_PASS); > break; > } > #endif /* INET6 */ > @@ -4731,8 +4583,7 @@ pf_test_state_icmp(struct pf_state **sta > if (PF_ANEQ(pd2.src, > &nk->addr[pd2.sidx], pd2.af)) > pf_change_icmp(pd2.src, NULL, daddr, > - &nk->addr[pd2.sidx], 0, NULL, > - pd2.ip_sum, icmpsum, 0, pd2.af); > + &nk->addr[pd2.sidx], 0, pd2.af); > > if (PF_ANEQ(pd2.dst, &nk->addr[pd2.didx], > pd2.af) || pd2.rdomain != nk->rdomain) > @@ -4742,8 +4593,7 @@ pf_test_state_icmp(struct pf_state **sta > if (PF_ANEQ(pd2.dst, > &nk->addr[pd2.didx], pd2.af)) > pf_change_icmp(pd2.dst, NULL, saddr, > - &nk->addr[pd2.didx], 0, NULL, > - pd2.ip_sum, icmpsum, 0, pd2.af); > + &nk->addr[pd2.didx], 0, pd2.af); > > switch (pd2.af) { > #ifdef INET > @@ -4764,12 +4614,15 @@ pf_test_state_icmp(struct pf_state **sta > break; > #endif /* INET6 */ > } > + copyback = 1; > } > - return (PF_PASS); > break; > } > } > } > + if (copyback) > + m->m_pkthdr.csum_flags |= M_ICMP_CSUM_OUT; > + return (PF_PASS); > } > > int > @@ -4828,13 +4681,11 @@ pf_test_state_other(struct pf_state **st > #ifdef INET > case AF_INET: > if (PF_ANEQ(pd->src, &nk->addr[pd->sidx], AF_INET)) > - pf_change_a(&pd->src->v4.s_addr, NULL, > - nk->addr[pd->sidx].v4.s_addr, > - 0); > + pf_change_a(&pd->src->v4.s_addr, > + nk->addr[pd->sidx].v4.s_addr); > if (PF_ANEQ(pd->dst, &nk->addr[pd->didx], AF_INET)) { > - pf_change_a(&pd->dst->v4.s_addr, NULL, > - nk->addr[pd->didx].v4.s_addr, > - 0); > + pf_change_a(&pd->dst->v4.s_addr, > + nk->addr[pd->didx].v4.s_addr); > pd->destchg = 1; > } > break; > Index: net/pf_norm.c > =================================================================== > RCS file: /cvs/src/sys/net/pf_norm.c,v > retrieving revision 1.136 > diff -u -p -r1.136 pf_norm.c > --- net/pf_norm.c 3 Jul 2011 18:08:02 -0000 1.136 > +++ net/pf_norm.c 3 Jul 2011 19:16:07 -0000 > @@ -2,7 +2,7 @@ > > /* > * Copyright 2001 Niels Provos <[email protected]> > - * Copyright 2009 Henning Brauer <[email protected]> > + * Copyright 2009 - 2011 Henning Brauer <[email protected]> > * Copyright 2011 Alexander Bluhm <[email protected]> > * All rights reserved. > * > @@ -967,20 +967,20 @@ pf_normalize_tcp(int dir, struct mbuf *m > 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) > + if (rewrite) { > m_copyback(m, off, sizeof(*th), th, M_NOWAIT); > + m->m_pkthdr.csum_flags |= M_TCP_CSUM_OUT; > + } > > return (PF_PASS); > > @@ -1169,10 +1169,8 @@ pf_normalize_tcp_stateful(struct mbuf *m > PFSS_TIMESTAMP)) { > tsval = ntohl(tsval); > pf_change_a(&opt[2], > - &th->th_sum, > htonl(tsval + > - src->scrub->pfss_ts_mod), > - 0); > + src->scrub->pfss_ts_mod)); > copyback = 1; > } > > @@ -1185,8 +1183,7 @@ pf_normalize_tcp_stateful(struct mbuf *m > tsecr = ntohl(tsecr) > - dst->scrub->pfss_ts_mod; > pf_change_a(&opt[6], > - &th->th_sum, htonl(tsecr), > - 0); > + htonl(tsecr)); > copyback = 1; > } > got_ts = 1; > @@ -1204,6 +1201,7 @@ pf_normalize_tcp_stateful(struct mbuf *m > m_copyback(m, off + sizeof(struct tcphdr), > (th->th_off << 2) - sizeof(struct tcphdr), hdr + > sizeof(struct tcphdr), M_NOWAIT); > + m->m_pkthdr.csum_flags |= M_TCP_CSUM_OUT; > } > } > > @@ -1516,21 +1514,18 @@ pf_normalize_mss(struct mbuf *m, int off > 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(m, > off + sizeof(*th) + optp + 2 - opts, > 2, &mss, M_NOWAIT); > m_copyback(m, off, sizeof(*th), th, M_NOWAIT); > + m->m_pkthdr.csum_flags |= M_TCP_CSUM_OUT; > } > break; > default: > break; > } > } > - > - > > return (0); > } > Index: net/pfvar.h > =================================================================== > RCS file: /cvs/src/sys/net/pfvar.h,v > retrieving revision 1.334 > diff -u -p -r1.334 pfvar.h > --- net/pfvar.h 21 Jun 2011 08:59:47 -0000 1.334 > +++ net/pfvar.h 3 Jul 2011 19:16:07 -0000 > @@ -1730,8 +1730,6 @@ extern struct pf_state *pf_find_state_a > u_int, int *); > 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; > @@ -1759,7 +1757,7 @@ void pf_addr_inc(struct pf_addr *, sa_fa > > 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_a(void *, u_int32_t); > int pflog_packet(struct pfi_kif *, struct mbuf *, u_int8_t, > u_int8_t, struct pf_rule *, struct pf_rule *, struct pf_ruleset *, > struct pf_pdesc *); > @@ -1798,7 +1796,7 @@ struct pf_state_key *pf_alloc_state_key( > 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 pf_addr *, u_int16_t, u_int16_t, int, struct mbuf *); > > void pfr_initialize(void); > int pfr_match_addr(struct pfr_ktable *, struct pf_addr *, sa_family_t); > Index: netinet/ip_input.c > =================================================================== > RCS file: /cvs/src/sys/netinet/ip_input.c,v > retrieving revision 1.192 > diff -u -p -r1.192 ip_input.c > --- netinet/ip_input.c 15 Jun 2011 09:11:01 -0000 1.192 > +++ netinet/ip_input.c 3 Jul 2011 19:16:07 -0000 > @@ -501,6 +501,9 @@ ipv4_input(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. > Index: netinet/ip_output.c > =================================================================== > RCS file: /cvs/src/sys/netinet/ip_output.c,v > retrieving revision 1.222 > diff -u -p -r1.222 ip_output.c > --- netinet/ip_output.c 15 Jun 2011 09:11:01 -0000 1.222 > +++ netinet/ip_output.c 3 Jul 2011 19:16:08 -0000 > @@ -615,6 +615,7 @@ sendit: > splx(s); > goto done; > } > + in_proto_cksum_out(m, encif); > ip = mtod(m, struct ip *); > hlen = ip->ip_hl << 2; > /* > @@ -698,8 +699,6 @@ sendit: > } > #endif /* IPSEC */ > > - in_proto_cksum_out(m, ifp); > - > /* > * Packet filter > */ > @@ -711,6 +710,7 @@ sendit: > } > if (m == NULL) > goto done; > + in_proto_cksum_out(m, ifp); > ip = mtod(m, struct ip *); > hlen = ip->ip_hl << 2; > if ((m->m_pkthdr.pf.flags & (PF_TAG_REROUTE | PF_TAG_GENERATED)) == > Index: netinet6/in6.h > =================================================================== > RCS file: /cvs/src/sys/netinet6/in6.h,v > retrieving revision 1.53 > diff -u -p -r1.53 in6.h > --- netinet6/in6.h 2 May 2011 13:48:38 -0000 1.53 > +++ netinet6/in6.h 3 Jul 2011 19:16:08 -0000 > @@ -834,6 +834,7 @@ extern int inet6_rth_add(void *, const s > extern int inet6_rth_reverse(const void *, void *); > extern int inet6_rth_segments(const void *); > extern struct in6_addr *inet6_rth_getaddr(const void *, int); > +extern void in6_proto_cksum_out(struct mbuf *, struct ifnet *); > __END_DECLS > > #endif /* !_NETINET6_IN6_H_ */ > Index: netinet6/ip6_forward.c > =================================================================== > RCS file: /cvs/src/sys/netinet6/ip6_forward.c,v > retrieving revision 1.52 > diff -u -p -r1.52 ip6_forward.c > --- netinet6/ip6_forward.c 24 Mar 2011 20:09:45 -0000 1.52 > +++ netinet6/ip6_forward.c 3 Jul 2011 19:16:08 -0000 > @@ -361,6 +361,7 @@ reroute: > splx(s); > goto senderr; > } > + in6_proto_cksum_out(m, encif); > ip6 = mtod(m, struct ip6_hdr *); > /* > * PF_TAG_REROUTE handling or not... > @@ -470,7 +471,7 @@ reroute: > } > if (m == NULL) > goto senderr; > - > + in6_proto_cksum_out(m, rt->rt_ifp); > ip6 = mtod(m, struct ip6_hdr *); > if ((m->m_pkthdr.pf.flags & (PF_TAG_REROUTE | PF_TAG_GENERATED)) == > (PF_TAG_REROUTE | PF_TAG_GENERATED)) { > Index: netinet6/ip6_input.c > =================================================================== > RCS file: /cvs/src/sys/netinet6/ip6_input.c,v > retrieving revision 1.99 > diff -u -p -r1.99 ip6_input.c > --- netinet6/ip6_input.c 3 Apr 2011 13:56:05 -0000 1.99 > +++ netinet6/ip6_input.c 3 Jul 2011 19:16:09 -0000 > @@ -669,6 +669,9 @@ ip6_input(struct mbuf *m) > return; > } > > + /* pf might have changed things */ > + in6_proto_cksum_out(m, NULL); > + > ip6 = mtod(m, struct ip6_hdr *); > > /* > Index: netinet6/ip6_output.c > =================================================================== > RCS file: /cvs/src/sys/netinet6/ip6_output.c,v > retrieving revision 1.121 > diff -u -p -r1.121 ip6_output.c > --- netinet6/ip6_output.c 2 May 2011 22:17:28 -0000 1.121 > +++ netinet6/ip6_output.c 3 Jul 2011 19:16:09 -0000 > @@ -134,6 +134,8 @@ int ip6_splithdr(struct mbuf *, struct i > 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; > @@ -532,6 +534,7 @@ reroute: > splx(s); > goto done; > } > + in6_proto_cksum_out(m, encif); > ip6 = mtod(m, struct ip6_hdr *); > /* > * PF_TAG_REROUTE handling or not... > @@ -803,6 +806,7 @@ reroute: > } > if (m == NULL) > goto done; > + in6_proto_cksum_out(m, ifp); > ip6 = mtod(m, struct ip6_hdr *); > if ((m->m_pkthdr.pf.flags & (PF_TAG_REROUTE | PF_TAG_GENERATED)) == > (PF_TAG_REROUTE | PF_TAG_GENERATED)) { > @@ -3204,4 +3208,63 @@ void > 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_TCPv4) || > + ifp->if_bridge != 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_UDPv4) || > + ifp->if_bridge != 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 */ > + } > } > -- Henning Brauer, [email protected], [email protected] BS Web Services, http://bsws.de Full-Service ISP - Secure Hosting, Mail and DNS Services Dedicated Servers, Rootservers, Application Hosting
