mirror of
https://github.com/clearlinux/kvmtool.git
synced 2026-09-06 13:41:44 +00:00
85 lines
1.8 KiB
C
85 lines
1.8 KiB
C
#include "kvm/uip.h"
|
|
|
|
static u16 uip_csum(u16 csum, u8 *addr, u16 count)
|
|
{
|
|
long sum = csum;
|
|
|
|
while (count > 1) {
|
|
sum += *(u16 *)addr;
|
|
addr += 2;
|
|
count -= 2;
|
|
}
|
|
|
|
if (count > 0)
|
|
sum += *(unsigned char *)addr;
|
|
|
|
while (sum>>16)
|
|
sum = (sum & 0xffff) + (sum >> 16);
|
|
|
|
return ~sum;
|
|
}
|
|
|
|
u16 uip_csum_ip(struct uip_ip *ip)
|
|
{
|
|
return uip_csum(0, &ip->vhl, uip_ip_hdrlen(ip));
|
|
}
|
|
|
|
u16 uip_csum_icmp(struct uip_ip *ip, struct uip_icmp *icmp)
|
|
{
|
|
return icmp->csum = uip_csum(0, &icmp->type, htons(ip->len) - uip_ip_hdrlen(ip) - 8); /* icmp header len = 8 */
|
|
}
|
|
|
|
u16 uip_csum_udp(struct uip_ip *ip, struct uip_udp *udp)
|
|
{
|
|
struct uip_pseudo_hdr hdr;
|
|
int udp_len;
|
|
u8 *pad;
|
|
|
|
hdr.sip = ip->sip;
|
|
hdr.dip = ip->dip;
|
|
hdr.zero = 0;
|
|
hdr.proto = ip->proto;
|
|
hdr.len = udp->len;
|
|
|
|
udp_len = uip_udp_len(udp);
|
|
|
|
if (udp_len % 2) {
|
|
pad = (u8 *)&udp->sport + udp_len;
|
|
*pad = 0;
|
|
memcpy((u8 *)&udp->sport + udp_len + 1, &hdr, sizeof(hdr));
|
|
return uip_csum(0, (u8 *)&udp->sport, udp_len + 1 + sizeof(hdr));
|
|
} else {
|
|
memcpy((u8 *)&udp->sport + udp_len, &hdr, sizeof(hdr));
|
|
return uip_csum(0, (u8 *)&udp->sport, udp_len + sizeof(hdr));
|
|
}
|
|
|
|
}
|
|
|
|
u16 uip_csum_tcp(struct uip_ip *ip, struct uip_tcp *tcp)
|
|
{
|
|
struct uip_pseudo_hdr hdr;
|
|
u16 tcp_len;
|
|
u8 *pad;
|
|
|
|
tcp_len = ntohs(ip->len) - uip_ip_hdrlen(ip);
|
|
|
|
hdr.sip = ip->sip;
|
|
hdr.dip = ip->dip;
|
|
hdr.zero = 0;
|
|
hdr.proto = ip->proto;
|
|
hdr.len = htons(tcp_len);
|
|
|
|
if (tcp_len > UIP_MAX_TCP_PAYLOAD + 20)
|
|
pr_warning("tcp_len(%d) is too large", tcp_len);
|
|
|
|
if (tcp_len % 2) {
|
|
pad = (u8 *)&tcp->sport + tcp_len;
|
|
*pad = 0;
|
|
memcpy((u8 *)&tcp->sport + tcp_len + 1, &hdr, sizeof(hdr));
|
|
return uip_csum(0, (u8 *)&tcp->sport, tcp_len + 1 + sizeof(hdr));
|
|
} else {
|
|
memcpy((u8 *)&tcp->sport + tcp_len, &hdr, sizeof(hdr));
|
|
return uip_csum(0, (u8 *)&tcp->sport, tcp_len + sizeof(hdr));
|
|
}
|
|
}
|