static void *uip_udp_socket_thread(void *p) { struct epoll_event events[UIP_UDP_MAX_EVENTS]; struct uip_udp_socket *sk; struct uip_info *info; struct uip_buf *buf; int payload_len; u8 *payload; int nfds; int i; kvm__set_thread_name("uip-udp"); info = p; do { payload = malloc(UIP_MAX_UDP_PAYLOAD); } while (!payload); while (1) { nfds = epoll_wait(info->udp_epollfd, events, UIP_UDP_MAX_EVENTS, -1); if (nfds == -1) continue; for (i = 0; i < nfds; i++) { sk = events[i].data.ptr; payload_len = recvfrom(sk->fd, payload, UIP_MAX_UDP_PAYLOAD, 0, NULL, NULL); if (payload_len < 0) continue; /* * Get free buffer to send data to guest */ buf = uip_buf_get_free(info); uip_udp_make_pkg(info, sk, buf, payload, payload_len); /* * Send data received from socket to guest */ uip_buf_set_used(info, buf); } } free(payload); pthread_exit(NULL); return NULL; }
int uip_tx_do_ipv4_udp_dhcp(struct uip_tx_arg *arg) { struct uip_udp_socket sk; struct uip_dhcp *dhcp; struct uip_info *info; struct uip_buf *buf; u8 reply_msg_type; dhcp = (struct uip_dhcp *)arg->eth; if (uip_dhcp_is_discovery(dhcp)) reply_msg_type = UIP_DHCP_OFFER; else if (uip_dhcp_is_request(dhcp)) reply_msg_type = UIP_DHCP_ACK; else return -1; buf = uip_buf_clone(arg); info = arg->info; /* * Cook DHCP pkg */ uip_dhcp_make_pkg(info, &sk, buf, reply_msg_type); /* * Cook UDP pkg */ uip_udp_make_pkg(info, &sk, buf, NULL, UIP_DHCP_MAX_PAYLOAD_LEN); /* * Send data received from socket to guest */ uip_buf_set_used(info, buf); return 0; }
int uip_tx_do_ipv4_icmp(struct uip_tx_arg *arg) { struct uip_ip *ip, *ip2; struct uip_icmp *icmp2; struct uip_icmp *icmp; struct uip_buf *buf; ip = (struct uip_ip *)(arg->eth); icmp = uip_ip_proto(ip); /* Check the icmp type first.. */ switch(icmp->type) { case UIP_ICMP_ECHO: buf = uip_buf_clone(arg); ip2 = (struct uip_ip *)(buf->eth); icmp2 = uip_ip_proto(ip2); ip2->sip = ip->dip; ip2->dip = ip->sip; ip2->csum = 0; /* * ICMP reply: 0 */ icmp2->type = UIP_ICMP_ECHO_REPLY; icmp2->csum = 0; ip2->csum = uip_csum_ip(ip2); icmp2->csum = uip_csum_icmp(ip2, icmp2); uip_buf_set_used(arg->info, buf); return 0; /* FIXME: need to process unreachable reports */ default: 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; }