1/* 2 * inet and unix socket functions for qemu 3 * 4 * (c) 2008 Gerd Hoffmann <kraxel@redhat.com> 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; under version 2 of the License. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 */ 15#include <stdio.h> 16#include <stdlib.h> 17#include <string.h> 18#include <ctype.h> 19#include <errno.h> 20#include <unistd.h> 21 22#include "qemu_socket.h" 23#include "qemu-common.h" /* for qemu_isdigit */ 24 25#ifndef AI_ADDRCONFIG 26# define AI_ADDRCONFIG 0 27#endif 28 29#ifndef INET6_ADDRSTRLEN 30# define INET6_ADDRSTRLEN 46 31#endif 32 33static int sockets_debug = 0; 34static const int on=1, off=0; 35 36/* used temporarely until all users are converted to QemuOpts */ 37static QemuOptsList dummy_opts = { 38 .name = "dummy", 39 .head = QTAILQ_HEAD_INITIALIZER(dummy_opts.head), 40 .desc = { 41 { 42 .name = "path", 43 .type = QEMU_OPT_STRING, 44 },{ 45 .name = "host", 46 .type = QEMU_OPT_STRING, 47 },{ 48 .name = "port", 49 .type = QEMU_OPT_STRING, 50 },{ 51 .name = "to", 52 .type = QEMU_OPT_NUMBER, 53 },{ 54 .name = "ipv4", 55 .type = QEMU_OPT_BOOL, 56 },{ 57 .name = "ipv6", 58 .type = QEMU_OPT_BOOL, 59#ifdef CONFIG_ANDROID 60 },{ 61 .name = "socket", 62 .type = QEMU_OPT_NUMBER, 63#endif 64 }, 65 { /* end if list */ } 66 }, 67}; 68 69 70static const char *sock_address_strfamily(SockAddress *s) 71{ 72 switch (sock_address_get_family(s)) { 73 case SOCKET_IN6: return "ipv6"; 74 case SOCKET_INET: return "ipv4"; 75 case SOCKET_UNIX: return "unix"; 76 default: return "????"; 77 } 78} 79 80int inet_listen_opts(QemuOpts *opts, int port_offset) 81{ 82 SockAddress** list; 83 SockAddress* e; 84 unsigned flags = SOCKET_LIST_PASSIVE; 85 const char *addr; 86 char port[33]; 87 char uaddr[256+1]; 88 char uport[33]; 89 int slisten,to,try_next,nn; 90 91#ifdef CONFIG_ANDROID 92 const char* socket_fd = qemu_opt_get(opts, "socket"); 93 if (socket_fd) { 94 return atoi(socket_fd); 95 } 96#endif 97 98 if ((qemu_opt_get(opts, "host") == NULL) || 99 (qemu_opt_get(opts, "port") == NULL)) { 100 fprintf(stderr, "%s: host and/or port not specified\n", __FUNCTION__); 101 return -1; 102 } 103 pstrcpy(port, sizeof(port), qemu_opt_get(opts, "port")); 104 addr = qemu_opt_get(opts, "host"); 105 106 to = qemu_opt_get_number(opts, "to", 0); 107 if (qemu_opt_get_bool(opts, "ipv4", 0)) 108 flags |= SOCKET_LIST_FORCE_INET; 109 if (qemu_opt_get_bool(opts, "ipv6", 0)) 110 flags |= SOCKET_LIST_FORCE_IN6; 111 112 /* lookup */ 113 if (port_offset) 114 snprintf(port, sizeof(port), "%d", atoi(port) + port_offset); 115 116 list = sock_address_list_create( strlen(addr) ? addr : NULL, 117 port, 118 flags ); 119 if (list == NULL) { 120 fprintf(stderr,"%s: getaddrinfo(%s,%s): %s\n", __FUNCTION__, 121 addr, port, errno_str); 122 return -1; 123 } 124 125 /* create socket + bind */ 126 for (nn = 0; list[nn] != NULL; nn++) { 127 SocketFamily family; 128 129 e = list[nn]; 130 family = sock_address_get_family(e); 131 132 sock_address_get_numeric_info(e, uaddr, sizeof uaddr, uport, sizeof uport); 133 slisten = socket_create(family, SOCKET_STREAM); 134 if (slisten < 0) { 135 fprintf(stderr,"%s: socket(%s): %s\n", __FUNCTION__, 136 sock_address_strfamily(e), errno_str); 137 continue; 138 } 139 140 socket_set_xreuseaddr(slisten); 141#ifdef IPV6_V6ONLY 142 /* listen on both ipv4 and ipv6 */ 143 if (family == SOCKET_IN6) { 144 socket_set_ipv6only(slisten); 145 } 146#endif 147 148 for (;;) { 149 if (socket_bind(slisten, e) == 0) { 150 if (sockets_debug) 151 fprintf(stderr,"%s: bind(%s,%s,%d): OK\n", __FUNCTION__, 152 sock_address_strfamily(e), uaddr, sock_address_get_port(e)); 153 goto listen; 154 } 155 socket_close(slisten); 156 try_next = to && (sock_address_get_port(e) <= to + port_offset); 157 if (!try_next || sockets_debug) 158 fprintf(stderr,"%s: bind(%s,%s,%d): %s\n", __FUNCTION__, 159 sock_address_strfamily(e), uaddr, sock_address_get_port(e), 160 strerror(errno)); 161 if (try_next) { 162 sock_address_set_port(e, sock_address_get_port(e) + 1); 163 continue; 164 } 165 break; 166 } 167 } 168 sock_address_list_free(list); 169 fprintf(stderr, "%s: FAILED\n", __FUNCTION__); 170 return -1; 171 172listen: 173 if (socket_listen(slisten,1) != 0) { 174 perror("listen"); 175 socket_close(slisten); 176 return -1; 177 } 178 snprintf(uport, sizeof(uport), "%d", sock_address_get_port(e) - port_offset); 179 qemu_opt_set(opts, "host", uaddr); 180 qemu_opt_set(opts, "port", uport); 181 qemu_opt_set(opts, "ipv6", (e->family == SOCKET_IN6) ? "on" : "off"); 182 qemu_opt_set(opts, "ipv4", (e->family != SOCKET_IN6) ? "on" : "off"); 183 sock_address_list_free(list); 184 return slisten; 185} 186 187int inet_connect_opts(QemuOpts *opts) 188{ 189 SockAddress** list; 190 SockAddress* e; 191 unsigned flags = 0; 192 const char *addr; 193 const char *port; 194 int sock, nn; 195 196#ifdef CONFIG_ANDROID 197 const char* socket_fd = qemu_opt_get(opts, "socket"); 198 if (socket_fd) { 199 return atoi(socket_fd); 200 } 201#endif 202 203 addr = qemu_opt_get(opts, "host"); 204 port = qemu_opt_get(opts, "port"); 205 if (addr == NULL || port == NULL) { 206 fprintf(stderr, "inet_connect: host and/or port not specified\n"); 207 return -1; 208 } 209 210 if (qemu_opt_get_bool(opts, "ipv4", 0)) { 211 flags &= SOCKET_LIST_FORCE_IN6; 212 flags |= SOCKET_LIST_FORCE_INET; 213 } 214 if (qemu_opt_get_bool(opts, "ipv6", 0)) { 215 flags &= SOCKET_LIST_FORCE_INET; 216 flags |= SOCKET_LIST_FORCE_IN6; 217 } 218 219 /* lookup */ 220 list = sock_address_list_create(addr, port, flags); 221 if (list == NULL) { 222 fprintf(stderr,"getaddrinfo(%s,%s): %s\n", 223 addr, port, errno_str); 224 return -1; 225 } 226 227 for (nn = 0; list[nn] != NULL; nn++) { 228 e = list[nn]; 229 sock = socket_create(sock_address_get_family(e), SOCKET_STREAM); 230 if (sock < 0) { 231 fprintf(stderr,"%s: socket(%s): %s\n", __FUNCTION__, 232 sock_address_strfamily(e), errno_str); 233 continue; 234 } 235 socket_set_xreuseaddr(sock); 236 237 /* connect to peer */ 238 if (socket_connect(sock,e) < 0) { 239 if (sockets_debug) 240 fprintf(stderr, "%s: connect(%s,%s,%s,%s): %s\n", __FUNCTION__, 241 sock_address_strfamily(e), 242 sock_address_to_string(e), addr, port, strerror(errno)); 243 socket_close(sock); 244 continue; 245 } 246 if (sockets_debug) 247 fprintf(stderr, "%s: connect(%s,%s,%s,%s): OK\n", __FUNCTION__, 248 sock_address_strfamily(e), 249 sock_address_to_string(e), addr, port); 250 251 goto EXIT; 252 } 253 sock = -1; 254EXIT: 255 sock_address_list_free(list); 256 return sock; 257} 258 259int inet_dgram_opts(QemuOpts *opts) 260{ 261 SockAddress** peer_list = NULL; 262 SockAddress** local_list = NULL; 263 SockAddress* e; 264 unsigned flags = 0; 265 const char *addr; 266 const char *port; 267 char uaddr[INET6_ADDRSTRLEN+1]; 268 char uport[33]; 269 int sock = -1; 270 int nn; 271 272 /* lookup peer addr */ 273 addr = qemu_opt_get(opts, "host"); 274 port = qemu_opt_get(opts, "port"); 275 if (addr == NULL || strlen(addr) == 0) { 276 addr = "localhost"; 277 } 278 if (port == NULL || strlen(port) == 0) { 279 fprintf(stderr, "inet_dgram: port not specified\n"); 280 return -1; 281 } 282 283 flags = SOCKET_LIST_DGRAM; 284 if (qemu_opt_get_bool(opts, "ipv4", 0)) { 285 flags &= SOCKET_LIST_FORCE_IN6; 286 flags |= SOCKET_LIST_FORCE_INET; 287 } 288 if (qemu_opt_get_bool(opts, "ipv6", 0)) { 289 flags &= SOCKET_LIST_FORCE_INET; 290 flags |= SOCKET_LIST_FORCE_IN6; 291 } 292 293 peer_list = sock_address_list_create(addr, port, flags); 294 if (peer_list == NULL) { 295 fprintf(stderr,"getaddrinfo(%s,%s): %s\n", 296 addr, port, errno_str); 297 return -1; 298 } 299 300 /* lookup local addr */ 301 addr = qemu_opt_get(opts, "localaddr"); 302 port = qemu_opt_get(opts, "localport"); 303 if (addr == NULL || strlen(addr) == 0) { 304 addr = NULL; 305 } 306 if (!port || strlen(port) == 0) 307 port = "0"; 308 309 flags = SOCKET_LIST_DGRAM | SOCKET_LIST_PASSIVE; 310 local_list = sock_address_list_create(addr, port, flags); 311 if (local_list == NULL) { 312 fprintf(stderr,"getaddrinfo(%s,%s): %s\n", 313 addr, port, errno_str); 314 goto EXIT; 315 } 316 317 if (sock_address_get_numeric_info(local_list[0], 318 uaddr, INET6_ADDRSTRLEN, 319 uport, 32)) { 320 fprintf(stderr, "%s: getnameinfo: oops\n", __FUNCTION__); 321 goto EXIT; 322 } 323 324 for (nn = 0; peer_list[nn] != NULL; nn++) { 325 SockAddress *local = local_list[0]; 326 e = peer_list[nn]; 327 sock = socket_create(sock_address_get_family(e), SOCKET_DGRAM); 328 if (sock < 0) { 329 fprintf(stderr,"%s: socket(%s): %s\n", __FUNCTION__, 330 sock_address_strfamily(e), errno_str); 331 continue; 332 } 333 socket_set_xreuseaddr(sock); 334 335 /* bind socket */ 336 if (socket_bind(sock, local) < 0) { 337 fprintf(stderr,"%s: bind(%s,%s,%s): OK\n", __FUNCTION__, 338 sock_address_strfamily(local), addr, port); 339 socket_close(sock); 340 continue; 341 } 342 343 /* connect to peer */ 344 if (socket_connect(sock,e) < 0) { 345 if (sockets_debug) 346 fprintf(stderr, "%s: connect(%s,%s,%s,%s): %s\n", __FUNCTION__, 347 sock_address_strfamily(e), 348 sock_address_to_string(e), addr, port, strerror(errno)); 349 socket_close(sock); 350 continue; 351 } 352 if (sockets_debug) 353 fprintf(stderr, "%s: connect(%s,%s,%s,%s): OK\n", __FUNCTION__, 354 sock_address_strfamily(e), 355 sock_address_to_string(e), addr, port); 356 357 goto EXIT; 358 } 359 sock = -1; 360EXIT: 361 if (local_list) 362 sock_address_list_free(local_list); 363 if (peer_list) 364 sock_address_list_free(peer_list); 365 return sock; 366} 367 368/* compatibility wrapper */ 369static int inet_parse(QemuOpts *opts, const char *str) 370{ 371 const char *optstr, *h; 372 char addr[64]; 373 char port[33]; 374 int pos; 375 376 /* parse address */ 377 if (str[0] == ':') { 378 /* no host given */ 379 addr[0] = '\0'; 380 if (1 != sscanf(str,":%32[^,]%n",port,&pos)) { 381 fprintf(stderr, "%s: portonly parse error (%s)\n", 382 __FUNCTION__, str); 383 return -1; 384 } 385 } else if (str[0] == '[') { 386 /* IPv6 addr */ 387 if (2 != sscanf(str,"[%64[^]]]:%32[^,]%n",addr,port,&pos)) { 388 fprintf(stderr, "%s: ipv6 parse error (%s)\n", 389 __FUNCTION__, str); 390 return -1; 391 } 392 qemu_opt_set(opts, "ipv6", "on"); 393 } else if (qemu_isdigit(str[0])) { 394 /* IPv4 addr */ 395 if (2 != sscanf(str,"%64[0-9.]:%32[^,]%n",addr,port,&pos)) { 396 fprintf(stderr, "%s: ipv4 parse error (%s)\n", 397 __FUNCTION__, str); 398 return -1; 399 } 400 qemu_opt_set(opts, "ipv4", "on"); 401 } else { 402 /* hostname */ 403 if (2 != sscanf(str,"%64[^:]:%32[^,]%n",addr,port,&pos)) { 404 fprintf(stderr, "%s: hostname parse error (%s)\n", 405 __FUNCTION__, str); 406 return -1; 407 } 408 } 409 qemu_opt_set(opts, "host", addr); 410 qemu_opt_set(opts, "port", port); 411 412 /* parse options */ 413 optstr = str + pos; 414 h = strstr(optstr, ",to="); 415 if (h) 416 qemu_opt_set(opts, "to", h+4); 417 if (strstr(optstr, ",ipv4")) 418 qemu_opt_set(opts, "ipv4", "on"); 419 if (strstr(optstr, ",ipv6")) 420 qemu_opt_set(opts, "ipv6", "on"); 421#ifdef CONFIG_ANDROID 422 h = strstr(optstr, ",socket="); 423 if (h) { 424 int socket_fd; 425 char str_fd[12]; 426 if (1 != sscanf(h+7,"%d",&socket_fd)) { 427 fprintf(stderr,"%s: socket fd parse error (%s)\n", 428 __FUNCTION__, h+7); 429 return -1; 430 } 431 if (socket_fd < 0 || socket_fd >= INT_MAX) { 432 fprintf(stderr,"%s: socket fd range error (%d)\n", 433 __FUNCTION__, socket_fd); 434 return -1; 435 } 436 snprintf(str_fd, sizeof str_fd, "%d", socket_fd); 437 qemu_opt_set(opts, "socket", str_fd); 438 } 439#endif 440 return 0; 441} 442 443int inet_listen(const char *str, char *ostr, int olen, 444 int socktype, int port_offset) 445{ 446 QemuOpts *opts; 447 char *optstr; 448 int sock = -1; 449 450 opts = qemu_opts_create(&dummy_opts, NULL, 0); 451 if (inet_parse(opts, str) == 0) { 452 sock = inet_listen_opts(opts, port_offset); 453 if (sock != -1 && ostr) { 454 optstr = strchr(str, ','); 455 if (qemu_opt_get_bool(opts, "ipv6", 0)) { 456 snprintf(ostr, olen, "[%s]:%s%s", 457 qemu_opt_get(opts, "host"), 458 qemu_opt_get(opts, "port"), 459 optstr ? optstr : ""); 460 } else { 461 snprintf(ostr, olen, "%s:%s%s", 462 qemu_opt_get(opts, "host"), 463 qemu_opt_get(opts, "port"), 464 optstr ? optstr : ""); 465 } 466 } 467 } 468 qemu_opts_del(opts); 469 return sock; 470} 471 472int inet_connect(const char *str, int socktype) 473{ 474 QemuOpts *opts; 475 int sock = -1; 476 477 opts = qemu_opts_create(&dummy_opts, NULL, 0); 478 if (inet_parse(opts, str) == 0) 479 sock = inet_connect_opts(opts); 480 qemu_opts_del(opts); 481 return sock; 482} 483 484#ifndef _WIN32 485 486int unix_listen_opts(QemuOpts *opts) 487{ 488 const char *path = qemu_opt_get(opts, "path"); 489 char unpath[PATH_MAX]; 490 const char *upath; 491 int sock, fd; 492 493 if (path && strlen(path)) { 494 upath = path; 495 } else { 496 char *tmpdir = getenv("TMPDIR"); 497 snprintf(unpath, sizeof(unpath), "%s/qemu-socket-XXXXXX", 498 tmpdir ? tmpdir : "/tmp"); 499 upath = unpath; 500 /* 501 * This dummy fd usage silences the mktemp() unsecure warning. 502 * Using mkstemp() doesn't make things more secure here 503 * though. bind() complains about existing files, so we have 504 * to unlink first and thus re-open the race window. The 505 * worst case possible is bind() failing, i.e. a DoS attack. 506 */ 507 fd = mkstemp(unpath); close(fd); 508 qemu_opt_set(opts, "path", unpath); 509 } 510 511 sock = socket_unix_server(upath, SOCKET_STREAM); 512 513 if (sock < 0) { 514 fprintf(stderr, "bind(unix:%s): %s\n", upath, errno_str); 515 goto err; 516 } 517 518 if (sockets_debug) 519 fprintf(stderr, "bind(unix:%s): OK\n", upath); 520 521 return sock; 522 523err: 524 socket_close(sock); 525 return -1; 526} 527 528int unix_connect_opts(QemuOpts *opts) 529{ 530 SockAddress un; 531 const char *path = qemu_opt_get(opts, "path"); 532 int ret, sock; 533 534 sock = socket_create_unix(SOCKET_STREAM); 535 if (sock < 0) { 536 perror("socket(unix)"); 537 return -1; 538 } 539 540 sock_address_init_unix(&un, path); 541 ret = socket_connect(sock, &un); 542 sock_address_done(&un); 543 if (ret < 0) { 544 fprintf(stderr, "connect(unix:%s): %s\n", path, errno_str); 545 return -1; 546 } 547 548 549 if (sockets_debug) 550 fprintf(stderr, "connect(unix:%s): OK\n", path); 551 return sock; 552} 553 554/* compatibility wrapper */ 555int unix_listen(const char *str, char *ostr, int olen) 556{ 557 QemuOpts *opts; 558 char *path, *optstr; 559 int sock, len; 560 561 opts = qemu_opts_create(&dummy_opts, NULL, 0); 562 563 optstr = strchr(str, ','); 564 if (optstr) { 565 len = optstr - str; 566 if (len) { 567 path = qemu_malloc(len+1); 568 snprintf(path, len+1, "%.*s", len, str); 569 qemu_opt_set(opts, "path", path); 570 qemu_free(path); 571 } 572 } else { 573 qemu_opt_set(opts, "path", str); 574 } 575 576 sock = unix_listen_opts(opts); 577 578 if (sock != -1 && ostr) 579 snprintf(ostr, olen, "%s%s", qemu_opt_get(opts, "path"), optstr ? optstr : ""); 580 qemu_opts_del(opts); 581 return sock; 582} 583 584int unix_connect(const char *path) 585{ 586 QemuOpts *opts; 587 int sock; 588 589 opts = qemu_opts_create(&dummy_opts, NULL, 0); 590 qemu_opt_set(opts, "path", path); 591 sock = unix_connect_opts(opts); 592 qemu_opts_del(opts); 593 return sock; 594} 595 596#else 597 598int unix_listen_opts(QemuOpts *opts) 599{ 600 fprintf(stderr, "unix sockets are not available on windows\n"); 601 return -1; 602} 603 604int unix_connect_opts(QemuOpts *opts) 605{ 606 fprintf(stderr, "unix sockets are not available on windows\n"); 607 return -1; 608} 609 610int unix_listen(const char *path, char *ostr, int olen) 611{ 612 fprintf(stderr, "unix sockets are not available on windows\n"); 613 return -1; 614} 615 616int unix_connect(const char *path) 617{ 618 fprintf(stderr, "unix sockets are not available on windows\n"); 619 return -1; 620} 621 622#endif 623 624#ifndef CONFIG_ANDROID /* see sockets.c */ 625#ifdef _WIN32 626static void socket_cleanup(void) 627{ 628 WSACleanup(); 629} 630#endif 631 632int socket_init(void) 633{ 634#ifdef _WIN32 635 WSADATA Data; 636 int ret, err; 637 638 ret = WSAStartup(MAKEWORD(2,2), &Data); 639 if (ret != 0) { 640 err = WSAGetLastError(); 641 fprintf(stderr, "WSAStartup: %d\n", err); 642 return -1; 643 } 644 atexit(socket_cleanup); 645#endif 646 return 0; 647} 648#endif /* !CONFIG_ANDROID */ 649