int uip_tx_do_ipv4(struct uip_tx_arg *arg) { struct uip_ip *ip; ip = (struct uip_ip *)(arg->eth); if (uip_ip_hdrlen(ip) != 20) { pr_warning("IP header length is not 20 bytes"); return -1; } switch (ip->proto) { case UIP_IP_P_ICMP: uip_tx_do_ipv4_icmp(arg); break; case UIP_IP_P_TCP: uip_tx_do_ipv4_tcp(arg); break; case UIP_IP_P_UDP: uip_tx_do_ipv4_udp(arg); break; default: break; } return 0; }
int uip_udp_make_pkg(struct uip_info *info, struct uip_udp_socket *sk, struct uip_buf *buf, u8* payload, int payload_len) { struct uip_eth *eth2; struct uip_udp *udp2; struct uip_ip *ip2; /* * Cook a ethernet frame */ udp2 = (struct uip_udp *)(buf->eth); eth2 = (struct uip_eth *)buf->eth; ip2 = (struct uip_ip *)(buf->eth); eth2->src = info->host_mac; eth2->dst = info->guest_mac; eth2->type = htons(UIP_ETH_P_IP); ip2->vhl = UIP_IP_VER_4 | UIP_IP_HDR_LEN; ip2->tos = 0; ip2->id = 0; ip2->flgfrag = 0; ip2->ttl = UIP_IP_TTL; ip2->proto = UIP_IP_P_UDP; ip2->csum = 0; ip2->sip = sk->dip; ip2->dip = sk->sip; udp2->sport = sk->dport; udp2->dport = sk->sport; udp2->len = htons(payload_len + uip_udp_hdrlen(udp2)); udp2->csum = 0; if (payload) memcpy(udp2->payload, payload, payload_len); ip2->len = udp2->len + htons(uip_ip_hdrlen(ip2)); ip2->csum = uip_csum_ip(ip2); udp2->csum = uip_csum_udp(udp2); /* * virtio_net_hdr */ buf->vnet_len = info->vnet_hdr_len; memset(buf->vnet, 0, buf->vnet_len); buf->eth_len = ntohs(ip2->len) + uip_eth_hdrlen(&ip2->eth); return 0; }
static int uip_tcp_payload_send(struct uip_tcp_socket *sk, u8 flag, u16 payload_len) { struct uip_info *info; struct uip_eth *eth2; struct uip_tcp *tcp2; struct uip_buf *buf; struct uip_ip *ip2; info = sk->info; /* * Get free buffer to send data to guest */ buf = uip_buf_get_free(info); /* * Cook a ethernet frame */ tcp2 = (struct uip_tcp *)buf->eth; eth2 = (struct uip_eth *)buf->eth; ip2 = (struct uip_ip *)buf->eth; eth2->src = info->host_mac; eth2->dst = info->guest_mac; eth2->type = htons(UIP_ETH_P_IP); ip2->vhl = UIP_IP_VER_4 | UIP_IP_HDR_LEN; ip2->tos = 0; ip2->id = 0; ip2->flgfrag = 0; ip2->ttl = UIP_IP_TTL; ip2->proto = UIP_IP_P_TCP; ip2->csum = 0; ip2->sip = sk->dip; ip2->dip = sk->sip; tcp2->sport = sk->dport; tcp2->dport = sk->sport; tcp2->seq = htonl(sk->seq_server); tcp2->ack = htonl(sk->ack_server); /* * Diable TCP options, tcp hdr len equals 20 bytes */ tcp2->off = UIP_TCP_HDR_LEN; tcp2->flg = flag; tcp2->win = htons(UIP_TCP_WIN_SIZE); tcp2->csum = 0; tcp2->urgent = 0; if (payload_len > 0) memcpy(uip_tcp_payload(tcp2), sk->payload, payload_len); ip2->len = htons(uip_tcp_hdrlen(tcp2) + payload_len + uip_ip_hdrlen(ip2)); ip2->csum = uip_csum_ip(ip2); tcp2->csum = uip_csum_tcp(tcp2); /* * virtio_net_hdr */ buf->vnet_len = sizeof(struct virtio_net_hdr); memset(buf->vnet, 0, buf->vnet_len); buf->eth_len = ntohs(ip2->len) + uip_eth_hdrlen(&ip2->eth); /* * Increase server seq */ sk->seq_server += payload_len; /* * Send data received from socket to guest */ uip_buf_set_used(info, buf); return 0; }