__sum16 nf_ip_checksum(struct sk_buff *skb, unsigned int hook, unsigned int dataoff, u_int8_t protocol) { const struct iphdr *iph = ip_hdr(skb); __sum16 csum = 0; switch (skb->ip_summed) { case CHECKSUM_COMPLETE: if (hook != NF_INET_PRE_ROUTING && hook != NF_INET_LOCAL_IN) break; if ((protocol == 0 && !csum_fold(skb->csum)) || !csum_tcpudp_magic(iph->saddr, iph->daddr, skb->len - dataoff, protocol, skb->csum)) { skb->ip_summed = CHECKSUM_UNNECESSARY; break; } /* fall through */ case CHECKSUM_NONE: if (protocol == 0) skb->csum = 0; else skb->csum = csum_tcpudp_nofold(iph->saddr, iph->daddr, skb->len - dataoff, protocol, 0); csum = __skb_checksum_complete(skb); } return csum; }
struct rtsocket *rt_udp_dest_socket(struct rtskb *skb) { struct udphdr *uh = skb->h.uh; unsigned short ulen = ntohs(uh->len); u32 saddr = skb->nh.iph->saddr; u32 daddr = skb->nh.iph->daddr; struct rtnet_device* rtdev = skb->rtdev; if (uh->check == 0) skb->ip_summed = CHECKSUM_UNNECESSARY; /* ip_summed (yet) never equals CHECKSUM_HW else if (skb->ip_summed == CHECKSUM_HW) { skb->ip_summed = CHECKSUM_UNNECESSARY; if ( !rt_udp_check(uh, ulen, saddr, daddr, skb->csum) ) return NULL; skb->ip_summed = CHECKSUM_NONE; }*/ if (skb->ip_summed != CHECKSUM_UNNECESSARY) skb->csum = csum_tcpudp_nofold(saddr, daddr, ulen, IPPROTO_UDP, 0); /* patch broadcast daddr */ if (daddr == rtdev->broadcast_ip) daddr = rtdev->local_ip; /* find the destination socket */ skb->sk = rt_udp_v4_lookup(daddr, uh->dest); return skb->sk; }
/* * computes the checksum of the TCP/UDP pseudo-header * returns a 16-bit checksum, already complemented */ static inline unsigned short int csum_tcpudp_magic(unsigned long saddr, unsigned long daddr, unsigned short len, unsigned short proto, unsigned int sum) { return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum)); }
static __wsum lro_tcp_data_csum(struct iphdr *iph, struct tcphdr *tcph, int len) { __wsum tcp_csum; __wsum tcp_hdr_csum; __wsum tcp_ps_hdr_csum; tcp_csum = ~csum_unfold(tcph->check); tcp_hdr_csum = csum_partial((u8 *)tcph, TCP_HDR_LEN(tcph), tcp_csum); tcp_ps_hdr_csum = csum_tcpudp_nofold(iph->saddr, iph->daddr, len + TCP_HDR_LEN(tcph), IPPROTO_TCP, 0); return csum_sub(csum_sub(tcp_csum, tcp_hdr_csum), tcp_ps_hdr_csum); }
static __sum16 checksum_udp(struct sk_buff *skb, struct udphdr *uh, unsigned short ulen, __be32 saddr, __be32 daddr) { __wsum psum; if (uh->check == 0 || skb_csum_unnecessary(skb)) return 0; psum = csum_tcpudp_nofold(saddr, daddr, ulen, IPPROTO_UDP, 0); if (skb->ip_summed == CHECKSUM_COMPLETE && !csum_fold(csum_add(psum, skb->csum))) return 0; skb->csum = psum; return __skb_checksum_complete(skb); }
static int checksum_udp(struct sk_buff *skb, struct udphdr *uh, unsigned short ulen, u32 saddr, u32 daddr) { unsigned int psum; if (uh->check == 0 || skb->ip_summed == CHECKSUM_UNNECESSARY) return 0; psum = csum_tcpudp_nofold(saddr, daddr, ulen, IPPROTO_UDP, 0); if (skb->ip_summed == CHECKSUM_HW && !(u16)csum_fold(csum_add(psum, skb->csum))) return 0; skb->csum = psum; return __skb_checksum_complete(skb); }
static __sum16 nf_ip_checksum_partial(struct sk_buff *skb, unsigned int hook, unsigned int dataoff, unsigned int len, u_int8_t protocol) { const struct iphdr *iph = ip_hdr(skb); __sum16 csum = 0; switch (skb->ip_summed) { case CHECKSUM_COMPLETE: if (len == skb->len - dataoff) return nf_ip_checksum(skb, hook, dataoff, protocol); /* fall through */ case CHECKSUM_NONE: skb->csum = csum_tcpudp_nofold(iph->saddr, iph->daddr, protocol, skb->len - dataoff, 0); skb->ip_summed = CHECKSUM_NONE; return __skb_checksum_complete_head(skb, dataoff + len); } return csum; }
struct rtsocket *rt_udp_dest_socket(struct rtskb *skb) { struct udphdr *uh; unsigned short ulen; struct rtsocket *rtsk; u32 saddr = skb->nh.iph->saddr; u32 daddr = skb->nh.iph->daddr; uh = skb->h.uh; ulen = ntohs(uh->len); if (uh->check == 0) skb->ip_summed = CHECKSUM_UNNECESSARY; /* ip_summed (yet) never equals CHECKSUM_HW else if (skb->ip_summed == CHECKSUM_HW) { skb->ip_summed = CHECKSUM_UNNECESSARY; if ( !rt_udp_check(uh, ulen, saddr, daddr, skb->csum) ) return NULL; skb->ip_summed = CHECKSUM_NONE; }*/ if (skb->ip_summed != CHECKSUM_UNNECESSARY) skb->csum = csum_tcpudp_nofold(saddr, daddr, ulen, IPPROTO_UDP, 0); /* find a socket */ if ((rtsk = rt_udp_v4_lookup(saddr, uh->source, daddr, uh->dest)) == NULL) return NULL; skb->sk = rtsk; return rtsk; }