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 pthread_cond_init(&sk->cond, NULL); 74 75 if (ntohl(dip) == arg->info->host_ip) 76 sk->addr.sin_addr.s_addr = inet_addr("127.0.0.1"); 77 78 ret = connect(sk->fd, (struct sockaddr *)&sk->addr, sizeof(sk->addr)); 79 if (ret) { 80 free(sk); 81 return NULL; 82 } 83 84 sk->sip = ip->sip; 85 sk->dip = ip->dip; 86 sk->sport = tcp->sport; 87 sk->dport = tcp->dport; 88 89 mutex_lock(sk_lock); 90 list_add_tail(&sk->list, sk_head); 91 mutex_unlock(sk_lock); 92 93 return sk; 94 } 95 96 static int uip_tcp_payload_send(struct uip_tcp_socket *sk, u8 flag, u16 payload_len) 97 { 98 struct uip_info *info; 99 struct uip_eth *eth2; 100 struct uip_tcp *tcp2; 101 struct uip_buf *buf; 102 struct uip_ip *ip2; 103 104 info = sk->info; 105 106 /* 107 * Get free buffer to send data to guest 108 */ 109 buf = uip_buf_get_free(info); 110 111 /* 112 * Cook a ethernet frame 113 */ 114 tcp2 = (struct uip_tcp *)buf->eth; 115 eth2 = (struct uip_eth *)buf->eth; 116 ip2 = (struct uip_ip *)buf->eth; 117 118 eth2->src = info->host_mac; 119 eth2->dst = info->guest_mac; 120 eth2->type = htons(UIP_ETH_P_IP); 121 122 ip2->vhl = UIP_IP_VER_4 | UIP_IP_HDR_LEN; 123 ip2->tos = 0; 124 ip2->id = 0; 125 ip2->flgfrag = 0; 126 ip2->ttl = UIP_IP_TTL; 127 ip2->proto = UIP_IP_P_TCP; 128 ip2->csum = 0; 129 ip2->sip = sk->dip; 130 ip2->dip = sk->sip; 131 132 tcp2->sport = sk->dport; 133 tcp2->dport = sk->sport; 134 tcp2->seq = htonl(sk->seq_server); 135 tcp2->ack = htonl(sk->ack_server); 136 /* 137 * Diable TCP options, tcp hdr len equals 20 bytes 138 */ 139 tcp2->off = UIP_TCP_HDR_LEN; 140 tcp2->flg = flag; 141 tcp2->win = htons(UIP_TCP_WIN_SIZE); 142 tcp2->csum = 0; 143 tcp2->urgent = 0; 144 145 if (payload_len > 0) 146 memcpy(uip_tcp_payload(tcp2), sk->payload, payload_len); 147 148 ip2->len = htons(uip_tcp_hdrlen(tcp2) + payload_len + uip_ip_hdrlen(ip2)); 149 ip2->csum = uip_csum_ip(ip2); 150 tcp2->csum = uip_csum_tcp(tcp2); 151 152 /* 153 * virtio_net_hdr 154 */ 155 buf->vnet_len = sizeof(struct virtio_net_hdr); 156 memset(buf->vnet, 0, buf->vnet_len); 157 158 buf->eth_len = ntohs(ip2->len) + uip_eth_hdrlen(&ip2->eth); 159 160 /* 161 * Increase server seq 162 */ 163 sk->seq_server += payload_len; 164 165 /* 166 * Send data received from socket to guest 167 */ 168 uip_buf_set_used(info, buf); 169 170 return 0; 171 } 172 173 static void *uip_tcp_socket_thread(void *p) 174 { 175 struct uip_tcp_socket *sk; 176 int len, left, ret; 177 u8 *payload, *pos; 178 179 sk = p; 180 181 payload = malloc(UIP_MAX_TCP_PAYLOAD); 182 if (!payload) 183 goto out; 184 185 while (1) { 186 pos = payload; 187 188 ret = read(sk->fd, payload, UIP_MAX_TCP_PAYLOAD); 189 190 if (ret <= 0 || ret > UIP_MAX_TCP_PAYLOAD) 191 goto out; 192 193 left = ret; 194 195 while (left > 0) { 196 mutex_lock(sk->lock); 197 while ((len = sk->guest_acked + sk->window_size - sk->seq_server) <= 0) 198 pthread_cond_wait(&sk->cond, sk->lock); 199 mutex_unlock(sk->lock); 200 201 sk->payload = pos; 202 if (len > left) 203 len = left; 204 if (len > UIP_MAX_TCP_PAYLOAD) 205 len = UIP_MAX_TCP_PAYLOAD; 206 left -= len; 207 pos += len; 208 209 uip_tcp_payload_send(sk, UIP_TCP_FLAG_ACK, len); 210 } 211 } 212 213 out: 214 /* 215 * Close server to guest TCP connection 216 */ 217 uip_tcp_socket_close(sk, SHUT_RD); 218 219 uip_tcp_payload_send(sk, UIP_TCP_FLAG_FIN | UIP_TCP_FLAG_ACK, 0); 220 sk->seq_server += 1; 221 222 sk->read_done = 1; 223 224 free(payload); 225 pthread_exit(NULL); 226 227 return NULL; 228 } 229 230 static int uip_tcp_socket_receive(struct uip_tcp_socket *sk) 231 { 232 if (sk->thread == 0) 233 return pthread_create(&sk->thread, NULL, uip_tcp_socket_thread, (void *)sk); 234 235 return 0; 236 } 237 238 static int uip_tcp_socket_send(struct uip_tcp_socket *sk, struct uip_tcp *tcp) 239 { 240 int len; 241 int ret; 242 u8 *payload; 243 244 if (sk->write_done) 245 return 0; 246 247 payload = uip_tcp_payload(tcp); 248 len = uip_tcp_payloadlen(tcp); 249 250 ret = write(sk->fd, payload, len); 251 if (ret != len) 252 pr_warning("tcp send error"); 253 254 return ret; 255 } 256 257 int uip_tx_do_ipv4_tcp(struct uip_tx_arg *arg) 258 { 259 struct uip_tcp_socket *sk; 260 struct uip_tcp *tcp; 261 struct uip_ip *ip; 262 int ret; 263 264 tcp = (struct uip_tcp *)arg->eth; 265 ip = (struct uip_ip *)arg->eth; 266 267 /* 268 * Guest is trying to start a TCP session, let's fake SYN-ACK to guest 269 */ 270 if (uip_tcp_is_syn(tcp)) { 271 sk = uip_tcp_socket_alloc(arg, ip->sip, ip->dip, tcp->sport, tcp->dport); 272 if (!sk) 273 return -1; 274 275 sk->window_size = ntohs(tcp->win); 276 277 /* 278 * Setup ISN number 279 */ 280 sk->isn_guest = uip_tcp_isn(tcp); 281 sk->isn_server = uip_tcp_isn_alloc(); 282 283 sk->seq_server = sk->isn_server; 284 sk->ack_server = sk->isn_guest + 1; 285 uip_tcp_payload_send(sk, UIP_TCP_FLAG_SYN | UIP_TCP_FLAG_ACK, 0); 286 sk->seq_server += 1; 287 288 /* 289 * Start receive thread for data from remote to guest 290 */ 291 uip_tcp_socket_receive(sk); 292 293 goto out; 294 } 295 296 /* 297 * Find socket we have allocated 298 */ 299 sk = uip_tcp_socket_find(arg, ip->sip, ip->dip, tcp->sport, tcp->dport); 300 if (!sk) 301 return -1; 302 303 mutex_lock(sk->lock); 304 sk->window_size = ntohs(tcp->win); 305 sk->guest_acked = ntohl(tcp->ack); 306 pthread_cond_signal(&sk->cond); 307 mutex_unlock(sk->lock); 308 309 if (uip_tcp_is_fin(tcp)) { 310 if (sk->write_done) 311 goto out; 312 313 sk->write_done = 1; 314 sk->ack_server += 1; 315 uip_tcp_payload_send(sk, UIP_TCP_FLAG_ACK, 0); 316 317 /* 318 * Close guest to server TCP connection 319 */ 320 uip_tcp_socket_close(sk, SHUT_WR); 321 322 goto out; 323 } 324 325 /* 326 * Ignore guest to server frames with zero tcp payload 327 */ 328 if (uip_tcp_payloadlen(tcp) == 0) 329 goto out; 330 331 /* 332 * Sent out TCP data to remote host 333 */ 334 ret = uip_tcp_socket_send(sk, tcp); 335 if (ret < 0) 336 return -1; 337 /* 338 * Send ACK to guest imediately 339 */ 340 sk->ack_server += ret; 341 uip_tcp_payload_send(sk, UIP_TCP_FLAG_ACK, 0); 342 343 out: 344 return 0; 345 } 346