1 /* 2 * QEMU System Emulator 3 * 4 * Copyright (c) 2003-2008 Fabrice Bellard 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a copy 7 * of this software and associated documentation files (the "Software"), to deal 8 * in the Software without restriction, including without limitation the rights 9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 * copies of the Software, and to permit persons to whom the Software is 11 * furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included in 14 * all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 * THE SOFTWARE. 23 */ 24 #include "net/socket.h" 25 26 #include "config-host.h" 27 28 #include "net.h" 29 #include "qemu-char.h" 30 #include "qemu-common.h" 31 #include "qemu-error.h" 32 #include "qemu-option.h" 33 #include "qemu_socket.h" 34 35 typedef struct NetSocketState { 36 VLANClientState nc; 37 int fd; 38 int state; /* 0 = getting length, 1 = getting data */ 39 unsigned int index; 40 unsigned int packet_len; 41 uint8_t buf[4096]; 42 struct sockaddr_in dgram_dst; /* contains inet host and port destination iff connectionless (SOCK_DGRAM) */ 43 } NetSocketState; 44 45 typedef struct NetSocketListenState { 46 VLANState *vlan; 47 char *model; 48 char *name; 49 int fd; 50 } NetSocketListenState; 51 52 /* XXX: we consider we can send the whole packet without blocking */ 53 static ssize_t net_socket_receive(VLANClientState *nc, const uint8_t *buf, size_t size) 54 { 55 NetSocketState *s = DO_UPCAST(NetSocketState, nc, nc); 56 uint32_t len; 57 len = htonl(size); 58 59 send_all(s->fd, (const uint8_t *)&len, sizeof(len)); 60 return send_all(s->fd, buf, size); 61 } 62 63 static ssize_t net_socket_receive_dgram(VLANClientState *nc, const uint8_t *buf, size_t size) 64 { 65 NetSocketState *s = DO_UPCAST(NetSocketState, nc, nc); 66 67 return sendto(s->fd, (const void *)buf, size, 0, 68 (struct sockaddr *)&s->dgram_dst, sizeof(s->dgram_dst)); 69 } 70 71 static void net_socket_send(void *opaque) 72 { 73 NetSocketState *s = opaque; 74 int size, err; 75 unsigned l; 76 uint8_t buf1[4096]; 77 const uint8_t *buf; 78 79 size = recv(s->fd, (void *)buf1, sizeof(buf1), 0); 80 if (size < 0) { 81 err = socket_error(); 82 if (err != EWOULDBLOCK) 83 goto eoc; 84 } else if (size == 0) { 85 /* end of connection */ 86 eoc: 87 qemu_set_fd_handler(s->fd, NULL, NULL, NULL); 88 closesocket(s->fd); 89 return; 90 } 91 buf = buf1; 92 while (size > 0) { 93 /* reassemble a packet from the network */ 94 switch(s->state) { 95 case 0: 96 l = 4 - s->index; 97 if (l > size) 98 l = size; 99 memcpy(s->buf + s->index, buf, l); 100 buf += l; 101 size -= l; 102 s->index += l; 103 if (s->index == 4) { 104 /* got length */ 105 s->packet_len = ntohl(*(uint32_t *)s->buf); 106 s->index = 0; 107 s->state = 1; 108 } 109 break; 110 case 1: 111 l = s->packet_len - s->index; 112 if (l > size) 113 l = size; 114 if (s->index + l <= sizeof(s->buf)) { 115 memcpy(s->buf + s->index, buf, l); 116 } else { 117 fprintf(stderr, "serious error: oversized packet received," 118 "connection terminated.\n"); 119 s->state = 0; 120 goto eoc; 121 } 122 123 s->index += l; 124 buf += l; 125 size -= l; 126 if (s->index >= s->packet_len) { 127 qemu_send_packet(&s->nc, s->buf, s->packet_len); 128 s->index = 0; 129 s->state = 0; 130 } 131 break; 132 } 133 } 134 } 135 136 static void net_socket_send_dgram(void *opaque) 137 { 138 NetSocketState *s = opaque; 139 int size; 140 141 size = recv(s->fd, (void *)s->buf, sizeof(s->buf), 0); 142 if (size < 0) 143 return; 144 if (size == 0) { 145 /* end of connection */ 146 qemu_set_fd_handler(s->fd, NULL, NULL, NULL); 147 return; 148 } 149 qemu_send_packet(&s->nc, s->buf, size); 150 } 151 152 static int net_socket_mcast_create(struct sockaddr_in *mcastaddr) 153 { 154 struct ip_mreq imr; 155 int fd; 156 int val, ret; 157 if (!IN_MULTICAST(ntohl(mcastaddr->sin_addr.s_addr))) { 158 fprintf(stderr, "qemu: error: specified mcastaddr \"%s\" (0x%08x) does not contain a multicast address\n", 159 inet_ntoa(mcastaddr->sin_addr), 160 (int)ntohl(mcastaddr->sin_addr.s_addr)); 161 return -1; 162 163 } 164 fd = qemu_socket(PF_INET, SOCK_DGRAM, 0); 165 if (fd < 0) { 166 perror("socket(PF_INET, SOCK_DGRAM)"); 167 return -1; 168 } 169 170 val = 1; 171 ret=setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, 172 (const char *)&val, sizeof(val)); 173 if (ret < 0) { 174 perror("setsockopt(SOL_SOCKET, SO_REUSEADDR)"); 175 goto fail; 176 } 177 178 ret = bind(fd, (struct sockaddr *)mcastaddr, sizeof(*mcastaddr)); 179 if (ret < 0) { 180 perror("bind"); 181 goto fail; 182 } 183 184 /* Add host to multicast group */ 185 imr.imr_multiaddr = mcastaddr->sin_addr; 186 imr.imr_interface.s_addr = htonl(INADDR_ANY); 187 188 ret = setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, 189 (const char *)&imr, sizeof(struct ip_mreq)); 190 if (ret < 0) { 191 perror("setsockopt(IP_ADD_MEMBERSHIP)"); 192 goto fail; 193 } 194 195 /* Force mcast msgs to loopback (eg. several QEMUs in same host */ 196 val = 1; 197 ret=setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, 198 (const char *)&val, sizeof(val)); 199 if (ret < 0) { 200 perror("setsockopt(SOL_IP, IP_MULTICAST_LOOP)"); 201 goto fail; 202 } 203 204 socket_set_nonblock(fd); 205 return fd; 206 fail: 207 if (fd >= 0) 208 closesocket(fd); 209 return -1; 210 } 211 212 static void net_socket_cleanup(VLANClientState *nc) 213 { 214 NetSocketState *s = DO_UPCAST(NetSocketState, nc, nc); 215 qemu_set_fd_handler(s->fd, NULL, NULL, NULL); 216 close(s->fd); 217 } 218 219 static NetClientInfo net_dgram_socket_info = { 220 .type = NET_CLIENT_TYPE_SOCKET, 221 .size = sizeof(NetSocketState), 222 .receive = net_socket_receive_dgram, 223 .cleanup = net_socket_cleanup, 224 }; 225 226 static NetSocketState *net_socket_fd_init_dgram(VLANState *vlan, 227 const char *model, 228 const char *name, 229 int fd, int is_connected) 230 { 231 struct sockaddr_in saddr; 232 int newfd; 233 socklen_t saddr_len; 234 VLANClientState *nc; 235 NetSocketState *s; 236 237 /* fd passed: multicast: "learn" dgram_dst address from bound address and save it 238 * Because this may be "shared" socket from a "master" process, datagrams would be recv() 239 * by ONLY ONE process: we must "clone" this dgram socket --jjo 240 */ 241 242 if (is_connected) { 243 if (getsockname(fd, (struct sockaddr *) &saddr, &saddr_len) == 0) { 244 /* must be bound */ 245 if (saddr.sin_addr.s_addr==0) { 246 fprintf(stderr, "qemu: error: init_dgram: fd=%d unbound, cannot setup multicast dst addr\n", 247 fd); 248 return NULL; 249 } 250 /* clone dgram socket */ 251 newfd = net_socket_mcast_create(&saddr); 252 if (newfd < 0) { 253 /* error already reported by net_socket_mcast_create() */ 254 close(fd); 255 return NULL; 256 } 257 /* clone newfd to fd, close newfd */ 258 dup2(newfd, fd); 259 close(newfd); 260 261 } else { 262 fprintf(stderr, "qemu: error: init_dgram: fd=%d failed getsockname(): %s\n", 263 fd, strerror(errno)); 264 return NULL; 265 } 266 } 267 268 nc = qemu_new_net_client(&net_dgram_socket_info, vlan, NULL, model, name); 269 270 snprintf(nc->info_str, sizeof(nc->info_str), 271 "socket: fd=%d (%s mcast=%s:%d)", 272 fd, is_connected ? "cloned" : "", 273 inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port)); 274 275 s = DO_UPCAST(NetSocketState, nc, nc); 276 277 s->fd = fd; 278 279 qemu_set_fd_handler(s->fd, net_socket_send_dgram, NULL, s); 280 281 /* mcast: save bound address as dst */ 282 if (is_connected) s->dgram_dst=saddr; 283 284 return s; 285 } 286 287 static void net_socket_connect(void *opaque) 288 { 289 NetSocketState *s = opaque; 290 qemu_set_fd_handler(s->fd, net_socket_send, NULL, s); 291 } 292 293 static NetClientInfo net_socket_info = { 294 .type = NET_CLIENT_TYPE_SOCKET, 295 .size = sizeof(NetSocketState), 296 .receive = net_socket_receive, 297 .cleanup = net_socket_cleanup, 298 }; 299 300 static NetSocketState *net_socket_fd_init_stream(VLANState *vlan, 301 const char *model, 302 const char *name, 303 int fd, int is_connected) 304 { 305 VLANClientState *nc; 306 NetSocketState *s; 307 308 nc = qemu_new_net_client(&net_socket_info, vlan, NULL, model, name); 309 310 snprintf(nc->info_str, sizeof(nc->info_str), "socket: fd=%d", fd); 311 312 s = DO_UPCAST(NetSocketState, nc, nc); 313 314 s->fd = fd; 315 316 if (is_connected) { 317 net_socket_connect(s); 318 } else { 319 qemu_set_fd_handler(s->fd, NULL, net_socket_connect, s); 320 } 321 return s; 322 } 323 324 static NetSocketState *net_socket_fd_init(VLANState *vlan, 325 const char *model, const char *name, 326 int fd, int is_connected) 327 { 328 int so_type = -1, optlen=sizeof(so_type); 329 330 if(getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&so_type, 331 (socklen_t *)&optlen)< 0) { 332 fprintf(stderr, "qemu: error: getsockopt(SO_TYPE) for fd=%d failed\n", fd); 333 return NULL; 334 } 335 switch(so_type) { 336 case SOCK_DGRAM: 337 return net_socket_fd_init_dgram(vlan, model, name, fd, is_connected); 338 case SOCK_STREAM: 339 return net_socket_fd_init_stream(vlan, model, name, fd, is_connected); 340 default: 341 /* who knows ... this could be a eg. a pty, do warn and continue as stream */ 342 fprintf(stderr, "qemu: warning: socket type=%d for fd=%d is not SOCK_DGRAM or SOCK_STREAM\n", so_type, fd); 343 return net_socket_fd_init_stream(vlan, model, name, fd, is_connected); 344 } 345 return NULL; 346 } 347 348 static void net_socket_accept(void *opaque) 349 { 350 NetSocketListenState *s = opaque; 351 NetSocketState *s1; 352 struct sockaddr_in saddr; 353 socklen_t len; 354 int fd; 355 356 for(;;) { 357 len = sizeof(saddr); 358 fd = qemu_accept(s->fd, (struct sockaddr *)&saddr, &len); 359 if (fd < 0 && errno != EINTR) { 360 return; 361 } else if (fd >= 0) { 362 break; 363 } 364 } 365 s1 = net_socket_fd_init(s->vlan, s->model, s->name, fd, 1); 366 if (!s1) { 367 closesocket(fd); 368 } else { 369 snprintf(s1->nc.info_str, sizeof(s1->nc.info_str), 370 "socket: connection from %s:%d", 371 inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port)); 372 } 373 } 374 375 static int net_socket_listen_init(VLANState *vlan, 376 const char *model, 377 const char *name, 378 const char *host_str) 379 { 380 NetSocketListenState *s; 381 int fd, val, ret; 382 struct sockaddr_in saddr; 383 384 if (parse_host_port(&saddr, host_str) < 0) 385 return -1; 386 387 s = qemu_mallocz(sizeof(NetSocketListenState)); 388 389 fd = qemu_socket(PF_INET, SOCK_STREAM, 0); 390 if (fd < 0) { 391 perror("socket"); 392 return -1; 393 } 394 socket_set_nonblock(fd); 395 396 /* allow fast reuse */ 397 val = 1; 398 setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const char *)&val, sizeof(val)); 399 400 ret = bind(fd, (struct sockaddr *)&saddr, sizeof(saddr)); 401 if (ret < 0) { 402 perror("bind"); 403 return -1; 404 } 405 ret = listen(fd, 0); 406 if (ret < 0) { 407 perror("listen"); 408 return -1; 409 } 410 s->vlan = vlan; 411 s->model = qemu_strdup(model); 412 s->name = name ? qemu_strdup(name) : NULL; 413 s->fd = fd; 414 qemu_set_fd_handler(fd, net_socket_accept, NULL, s); 415 return 0; 416 } 417 418 static int net_socket_connect_init(VLANState *vlan, 419 const char *model, 420 const char *name, 421 const char *host_str) 422 { 423 NetSocketState *s; 424 int fd, connected, ret, err; 425 struct sockaddr_in saddr; 426 427 if (parse_host_port(&saddr, host_str) < 0) 428 return -1; 429 430 fd = qemu_socket(PF_INET, SOCK_STREAM, 0); 431 if (fd < 0) { 432 perror("socket"); 433 return -1; 434 } 435 socket_set_nonblock(fd); 436 437 connected = 0; 438 for(;;) { 439 ret = connect(fd, (struct sockaddr *)&saddr, sizeof(saddr)); 440 if (ret < 0) { 441 err = socket_error(); 442 if (err == EINTR || err == EWOULDBLOCK) { 443 } else if (err == EINPROGRESS) { 444 break; 445 #ifdef _WIN32 446 } else if (err == WSAEALREADY) { 447 break; 448 #endif 449 } else { 450 perror("connect"); 451 closesocket(fd); 452 return -1; 453 } 454 } else { 455 connected = 1; 456 break; 457 } 458 } 459 s = net_socket_fd_init(vlan, model, name, fd, connected); 460 if (!s) 461 return -1; 462 snprintf(s->nc.info_str, sizeof(s->nc.info_str), 463 "socket: connect to %s:%d", 464 inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port)); 465 return 0; 466 } 467 468 static int net_socket_mcast_init(VLANState *vlan, 469 const char *model, 470 const char *name, 471 const char *host_str) 472 { 473 NetSocketState *s; 474 int fd; 475 struct sockaddr_in saddr; 476 477 if (parse_host_port(&saddr, host_str) < 0) 478 return -1; 479 480 481 fd = net_socket_mcast_create(&saddr); 482 if (fd < 0) 483 return -1; 484 485 s = net_socket_fd_init(vlan, model, name, fd, 0); 486 if (!s) 487 return -1; 488 489 s->dgram_dst = saddr; 490 491 snprintf(s->nc.info_str, sizeof(s->nc.info_str), 492 "socket: mcast=%s:%d", 493 inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port)); 494 return 0; 495 496 } 497 498 int net_init_socket(QemuOpts *opts, 499 Monitor *mon, 500 const char *name, 501 VLANState *vlan) 502 { 503 if (qemu_opt_get(opts, "fd")) { 504 int fd; 505 506 if (qemu_opt_get(opts, "listen") || 507 qemu_opt_get(opts, "connect") || 508 qemu_opt_get(opts, "mcast")) { 509 error_report("listen=, connect= and mcast= is invalid with fd="); 510 return -1; 511 } 512 513 fd = net_handle_fd_param(mon, qemu_opt_get(opts, "fd")); 514 if (fd == -1) { 515 return -1; 516 } 517 518 if (!net_socket_fd_init(vlan, "socket", name, fd, 1)) { 519 close(fd); 520 return -1; 521 } 522 } else if (qemu_opt_get(opts, "listen")) { 523 const char *listen; 524 525 if (qemu_opt_get(opts, "fd") || 526 qemu_opt_get(opts, "connect") || 527 qemu_opt_get(opts, "mcast")) { 528 error_report("fd=, connect= and mcast= is invalid with listen="); 529 return -1; 530 } 531 532 listen = qemu_opt_get(opts, "listen"); 533 534 if (net_socket_listen_init(vlan, "socket", name, listen) == -1) { 535 return -1; 536 } 537 } else if (qemu_opt_get(opts, "connect")) { 538 const char *connect; 539 540 if (qemu_opt_get(opts, "fd") || 541 qemu_opt_get(opts, "listen") || 542 qemu_opt_get(opts, "mcast")) { 543 error_report("fd=, listen= and mcast= is invalid with connect="); 544 return -1; 545 } 546 547 connect = qemu_opt_get(opts, "connect"); 548 549 if (net_socket_connect_init(vlan, "socket", name, connect) == -1) { 550 return -1; 551 } 552 } else if (qemu_opt_get(opts, "mcast")) { 553 const char *mcast; 554 555 if (qemu_opt_get(opts, "fd") || 556 qemu_opt_get(opts, "connect") || 557 qemu_opt_get(opts, "listen")) { 558 error_report("fd=, connect= and listen= is invalid with mcast="); 559 return -1; 560 } 561 562 mcast = qemu_opt_get(opts, "mcast"); 563 564 if (net_socket_mcast_init(vlan, "socket", name, mcast) == -1) { 565 return -1; 566 } 567 } else { 568 error_report("-socket requires fd=, listen=, connect= or mcast="); 569 return -1; 570 } 571 572 return 0; 573 } 574