1 #include "kvm/uip.h" 2 3 #include <linux/virtio_net.h> 4 #include <linux/kernel.h> 5 #include <linux/list.h> 6 #include <arpa/inet.h> 7 8 static int uip_tcp_socket_close(struct uip_tcp_socket *sk, int how) 9 { 10 shutdown(sk->fd, how); 11 12 if (sk->write_done && sk->read_done) { 13 shutdown(sk->fd, SHUT_RDWR); 14 close(sk->fd); 15 16 mutex_lock(sk->lock); 17 list_del(&sk->list); 18 mutex_unlock(sk->lock); 19 20 free(sk); 21 } 22 23 return 0; 24 } 25 26 static struct uip_tcp_socket *uip_tcp_socket_find(struct uip_tx_arg *arg, u32 sip, u32 dip, u16 sport, u16 dport) 27 { 28 struct list_head *sk_head; 29 pthread_mutex_t *sk_lock; 30 struct uip_tcp_socket *sk; 31 32 sk_head = &arg->info->tcp_socket_head; 33 sk_lock = &arg->info->tcp_socket_lock; 34 35 mutex_lock(sk_lock); 36 list_for_each_entry(sk, sk_head, list) { 37 if (sk->sip == sip && sk->dip == dip && sk->sport == sport && sk->dport == dport) { 38 mutex_unlock(sk_lock); 39 return sk; 40 } 41 } 42 mutex_unlock(sk_lock); 43 44 return NULL; 45 } 46 47 static struct uip_tcp_socket *uip_tcp_socket_alloc(struct uip_tx_arg *arg, u32 sip, u32 dip, u16 sport, u16 dport) 48 { 49 struct list_head *sk_head; 50 struct uip_tcp_socket *sk; 51 pthread_mutex_t *sk_lock; 52 struct uip_tcp *tcp; 53 struct uip_ip *ip; 54 int ret; 55 56 tcp = (struct uip_tcp *)arg->eth; 57 ip = (struct uip_ip *)arg->eth; 58 59 sk_head = &arg->info->tcp_socket_head; 60 sk_lock = &arg->info->tcp_socket_lock; 61 62 sk = malloc(sizeof(*sk)); 63 memset(sk, 0, sizeof(*sk)); 64 65 sk->lock = sk_lock; 66 sk->info = arg->info; 67 68 sk->fd = socket(AF_INET, SOCK_STREAM, 0); 69 sk->addr.sin_family = AF_INET; 70 sk->addr.sin_port = dport; 71 sk->addr.sin_addr.s_addr = dip; 72 73 if (ntohl(dip) == arg->info->host_ip) 74 sk->addr.sin_addr.s_addr = inet_addr("127.0.0.1"); 75 76 ret = connect(sk->fd, (struct sockaddr *)&sk->addr, sizeof(sk->addr)); 77 if (ret) { 78 free(sk); 79 return NULL; 80 } 81 82 sk->sip = ip->sip; 83 sk->dip = ip->dip; 84 sk->sport = tcp->sport; 85 sk->dport = tcp->dport; 86 87 mutex_lock(sk_lock); 88 list_add_tail(&sk->list, sk_head); 89 mutex_unlock(sk_lock); 90 91 return sk; 92 } 93 94 static int uip_tcp_payload_send(struct uip_tcp_socket *sk, u8 flag, u16 payload_len) 95 { 96 struct uip_info *info; 97 struct uip_eth *eth2; 98 struct uip_tcp *tcp2; 99 struct uip_buf *buf; 100 struct uip_ip *ip2; 101 102 info = sk->info; 103 104 /* 105 * Get free buffer to send data to guest 106 */ 107 buf = uip_buf_get_free(info); 108 109 /* 110 * Cook a ethernet frame 111 */ 112 tcp2 = (struct uip_tcp *)buf->eth; 113 eth2 = (struct uip_eth *)buf->eth; 114 ip2 = (struct uip_ip *)buf->eth; 115 116 eth2->src = info->host_mac; 117 eth2->dst = info->guest_mac; 118 eth2->type = htons(UIP_ETH_P_IP); 119 120 ip2->vhl = UIP_IP_VER_4 | UIP_IP_HDR_LEN; 121 ip2->tos = 0; 122 ip2->id = 0; 123 ip2->flgfrag = 0; 124 ip2->ttl = UIP_IP_TTL; 125 ip2->proto = UIP_IP_P_TCP; 126 ip2->csum = 0; 127 ip2->sip = sk->dip; 128 ip2->dip = sk->sip; 129 130 tcp2->sport = sk->dport; 131 tcp2->dport = sk->sport; 132 tcp2->seq = htonl(sk->seq_server); 133 tcp2->ack = htonl(sk->ack_server); 134 /* 135 * Diable TCP options, tcp hdr len equals 20 bytes 136 */ 137 tcp2->off = UIP_TCP_HDR_LEN; 138 tcp2->flg = flag; 139 tcp2->win = htons(UIP_TCP_WIN_SIZE); 140 tcp2->csum = 0; 141 tcp2->urgent = 0; 142 143 if (payload_len > 0) 144 memcpy(uip_tcp_payload(tcp2), sk->payload, payload_len); 145 146 ip2->len = htons(uip_tcp_hdrlen(tcp2) + payload_len + uip_ip_hdrlen(ip2)); 147 ip2->csum = uip_csum_ip(ip2); 148 tcp2->csum = uip_csum_tcp(tcp2); 149 150 /* 151 * virtio_net_hdr 152 */ 153 buf->vnet_len = sizeof(struct virtio_net_hdr); 154 memset(buf->vnet, 0, buf->vnet_len); 155 156 buf->eth_len = ntohs(ip2->len) + uip_eth_hdrlen(&ip2->eth); 157 158 /* 159 * Increase server seq 160 */ 161 sk->seq_server += payload_len; 162 163 /* 164 * Send data received from socket to guest 165 */ 166 uip_buf_set_used(info, buf); 167 168 return 0; 169 } 170 171 static void *uip_tcp_socket_thread(void *p) 172 { 173 struct uip_tcp_socket *sk; 174 u8 *payload; 175 int ret; 176 177 sk = p; 178 179 payload = malloc(UIP_MAX_TCP_PAYLOAD); 180 sk->payload = payload; 181 if (!sk->payload) 182 goto out; 183 184 while (1) { 185 186 ret = read(sk->fd, payload, UIP_MAX_TCP_PAYLOAD); 187 188 if (ret <= 0 || ret > UIP_MAX_TCP_PAYLOAD) 189 goto out; 190 191 uip_tcp_payload_send(sk, UIP_TCP_FLAG_ACK, ret); 192 193 } 194 195 out: 196 /* 197 * Close server to guest TCP connection 198 */ 199 uip_tcp_socket_close(sk, SHUT_RD); 200 201 uip_tcp_payload_send(sk, UIP_TCP_FLAG_FIN | UIP_TCP_FLAG_ACK, 0); 202 sk->seq_server += 1; 203 204 sk->read_done = 1; 205 206 free(sk->payload); 207 pthread_exit(NULL); 208 209 return NULL; 210 } 211 212 static int uip_tcp_socket_receive(struct uip_tcp_socket *sk) 213 { 214 if (sk->thread == 0) 215 return pthread_create(&sk->thread, NULL, uip_tcp_socket_thread, (void *)sk); 216 217 return 0; 218 } 219 220 static int uip_tcp_socket_send(struct uip_tcp_socket *sk, struct uip_tcp *tcp) 221 { 222 int len; 223 int ret; 224 u8 *payload; 225 226 if (sk->write_done) 227 return 0; 228 229 payload = uip_tcp_payload(tcp); 230 len = uip_tcp_payloadlen(tcp); 231 232 ret = write(sk->fd, payload, len); 233 if (ret != len) 234 pr_warning("tcp send error"); 235 236 return ret; 237 } 238 239 int uip_tx_do_ipv4_tcp(struct uip_tx_arg *arg) 240 { 241 struct uip_tcp_socket *sk; 242 struct uip_tcp *tcp; 243 struct uip_ip *ip; 244 int ret; 245 246 tcp = (struct uip_tcp *)arg->eth; 247 ip = (struct uip_ip *)arg->eth; 248 249 /* 250 * Guest is trying to start a TCP session, let's fake SYN-ACK to guest 251 */ 252 if (uip_tcp_is_syn(tcp)) { 253 sk = uip_tcp_socket_alloc(arg, ip->sip, ip->dip, tcp->sport, tcp->dport); 254 if (!sk) 255 return -1; 256 257 /* 258 * Setup ISN number 259 */ 260 sk->isn_guest = uip_tcp_isn(tcp); 261 sk->isn_server = uip_tcp_isn_alloc(); 262 263 sk->seq_server = sk->isn_server; 264 sk->ack_server = sk->isn_guest + 1; 265 uip_tcp_payload_send(sk, UIP_TCP_FLAG_SYN | UIP_TCP_FLAG_ACK, 0); 266 sk->seq_server += 1; 267 268 /* 269 * Start receive thread for data from remote to guest 270 */ 271 uip_tcp_socket_receive(sk); 272 273 goto out; 274 } 275 276 /* 277 * Find socket we have allocated 278 */ 279 sk = uip_tcp_socket_find(arg, ip->sip, ip->dip, tcp->sport, tcp->dport); 280 if (!sk) 281 return -1; 282 283 sk->guest_acked = ntohl(tcp->ack); 284 285 if (uip_tcp_is_fin(tcp)) { 286 if (sk->write_done) 287 goto out; 288 289 sk->write_done = 1; 290 sk->ack_server += 1; 291 uip_tcp_payload_send(sk, UIP_TCP_FLAG_ACK, 0); 292 293 /* 294 * Close guest to server TCP connection 295 */ 296 uip_tcp_socket_close(sk, SHUT_WR); 297 298 goto out; 299 } 300 301 /* 302 * Ignore guest to server frames with zero tcp payload 303 */ 304 if (uip_tcp_payloadlen(tcp) == 0) 305 goto out; 306 307 /* 308 * Sent out TCP data to remote host 309 */ 310 ret = uip_tcp_socket_send(sk, tcp); 311 if (ret < 0) 312 return -1; 313 /* 314 * Send ACK to guest imediately 315 */ 316 sk->ack_server += ret; 317 uip_tcp_payload_send(sk, UIP_TCP_FLAG_ACK, 0); 318 319 out: 320 return 0; 321 } 322