1d8db9f85SAsias He #include "kvm/uip.h" 2d8db9f85SAsias He 3d8db9f85SAsias He static u16 uip_csum(u16 csum, u8 *addr, u16 count) 4d8db9f85SAsias He { 5d8db9f85SAsias He long sum = csum; 6d8db9f85SAsias He 7d8db9f85SAsias He while (count > 1) { 8d8db9f85SAsias He sum += *(u16 *)addr; 9d8db9f85SAsias He addr += 2; 10d8db9f85SAsias He count -= 2; 11d8db9f85SAsias He } 12d8db9f85SAsias He 13d8db9f85SAsias He if (count > 0) 14d8db9f85SAsias He sum += *(unsigned char *)addr; 15d8db9f85SAsias He 16d8db9f85SAsias He while (sum>>16) 17d8db9f85SAsias He sum = (sum & 0xffff) + (sum >> 16); 18d8db9f85SAsias He 19d8db9f85SAsias He return ~sum; 20d8db9f85SAsias He } 21d8db9f85SAsias He 22d8db9f85SAsias He u16 uip_csum_ip(struct uip_ip *ip) 23d8db9f85SAsias He { 24d8db9f85SAsias He return uip_csum(0, &ip->vhl, uip_ip_hdrlen(ip)); 25d8db9f85SAsias He } 260134a2a7SAsias He 270134a2a7SAsias He u16 uip_csum_icmp(struct uip_icmp *icmp) 280134a2a7SAsias He { 290134a2a7SAsias He struct uip_ip *ip; 300134a2a7SAsias He 310134a2a7SAsias He ip = &icmp->ip; 320134a2a7SAsias He return icmp->csum = uip_csum(0, &icmp->type, htons(ip->len) - uip_ip_hdrlen(ip) - 8); /* icmp header len = 8 */ 330134a2a7SAsias He } 3407197967SAsias He 3507197967SAsias He u16 uip_csum_udp(struct uip_udp *udp) 3607197967SAsias He { 3707197967SAsias He struct uip_pseudo_hdr hdr; 3807197967SAsias He struct uip_ip *ip; 3907197967SAsias He int udp_len; 4007197967SAsias He u8 *pad; 4107197967SAsias He 4207197967SAsias He ip = &udp->ip; 4307197967SAsias He 4407197967SAsias He hdr.sip = ip->sip; 4507197967SAsias He hdr.dip = ip->dip; 4607197967SAsias He hdr.zero = 0; 4707197967SAsias He hdr.proto = ip->proto; 4807197967SAsias He hdr.len = udp->len; 4907197967SAsias He 5007197967SAsias He udp_len = uip_udp_len(udp); 5107197967SAsias He 5207197967SAsias He if (udp_len % 2) { 5307197967SAsias He pad = (u8 *)&udp->sport + udp_len; 5407197967SAsias He *pad = 0; 5507197967SAsias He memcpy((u8 *)&udp->sport + udp_len + 1, &hdr, sizeof(hdr)); 5607197967SAsias He return uip_csum(0, (u8 *)&udp->sport, udp_len + 1 + sizeof(hdr)); 5707197967SAsias He } else { 5807197967SAsias He memcpy((u8 *)&udp->sport + udp_len, &hdr, sizeof(hdr)); 5907197967SAsias He return uip_csum(0, (u8 *)&udp->sport, udp_len + sizeof(hdr)); 6007197967SAsias He } 6107197967SAsias He 6207197967SAsias He } 63*89fb0bf8SAsias He 64*89fb0bf8SAsias He u16 uip_csum_tcp(struct uip_tcp *tcp) 65*89fb0bf8SAsias He { 66*89fb0bf8SAsias He struct uip_pseudo_hdr hdr; 67*89fb0bf8SAsias He struct uip_ip *ip; 68*89fb0bf8SAsias He u16 tcp_len; 69*89fb0bf8SAsias He u8 *pad; 70*89fb0bf8SAsias He 71*89fb0bf8SAsias He ip = &tcp->ip; 72*89fb0bf8SAsias He tcp_len = ntohs(ip->len) - uip_ip_hdrlen(ip); 73*89fb0bf8SAsias He 74*89fb0bf8SAsias He hdr.sip = ip->sip; 75*89fb0bf8SAsias He hdr.dip = ip->dip; 76*89fb0bf8SAsias He hdr.zero = 0; 77*89fb0bf8SAsias He hdr.proto = ip->proto; 78*89fb0bf8SAsias He hdr.len = htons(tcp_len); 79*89fb0bf8SAsias He 80*89fb0bf8SAsias He if (tcp_len > UIP_MAX_TCP_PAYLOAD + 20) 81*89fb0bf8SAsias He pr_warning("tcp_len(%d) is too large", tcp_len); 82*89fb0bf8SAsias He 83*89fb0bf8SAsias He if (tcp_len % 2) { 84*89fb0bf8SAsias He pad = (u8 *)&tcp->sport + tcp_len; 85*89fb0bf8SAsias He *pad = 0; 86*89fb0bf8SAsias He memcpy((u8 *)&tcp->sport + tcp_len + 1, &hdr, sizeof(hdr)); 87*89fb0bf8SAsias He return uip_csum(0, (u8 *)&tcp->sport, tcp_len + 1 + sizeof(hdr)); 88*89fb0bf8SAsias He } else { 89*89fb0bf8SAsias He memcpy((u8 *)&tcp->sport + tcp_len, &hdr, sizeof(hdr)); 90*89fb0bf8SAsias He return uip_csum(0, (u8 *)&tcp->sport, tcp_len + sizeof(hdr)); 91*89fb0bf8SAsias He } 92*89fb0bf8SAsias He } 93