qemu-sockets.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681
  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. #include "qemu_socket.h"
  22. #include "qemu-common.h" /* for qemu_isdigit */
  23. #ifndef AI_ADDRCONFIG
  24. # define AI_ADDRCONFIG 0
  25. #endif
  26. static const int on=1, off=0;
  27. /* used temporarely until all users are converted to QemuOpts */
  28. static QemuOptsList dummy_opts = {
  29. .name = "dummy",
  30. .head = QTAILQ_HEAD_INITIALIZER(dummy_opts.head),
  31. .desc = {
  32. {
  33. .name = "path",
  34. .type = QEMU_OPT_STRING,
  35. },{
  36. .name = "host",
  37. .type = QEMU_OPT_STRING,
  38. },{
  39. .name = "port",
  40. .type = QEMU_OPT_STRING,
  41. },{
  42. .name = "to",
  43. .type = QEMU_OPT_NUMBER,
  44. },{
  45. .name = "ipv4",
  46. .type = QEMU_OPT_BOOL,
  47. },{
  48. .name = "ipv6",
  49. .type = QEMU_OPT_BOOL,
  50. },{
  51. .name = "block",
  52. .type = QEMU_OPT_BOOL,
  53. },
  54. { /* end if list */ }
  55. },
  56. };
  57. static int inet_getport(struct addrinfo *e)
  58. {
  59. struct sockaddr_in *i4;
  60. struct sockaddr_in6 *i6;
  61. switch (e->ai_family) {
  62. case PF_INET6:
  63. i6 = (void*)e->ai_addr;
  64. return ntohs(i6->sin6_port);
  65. case PF_INET:
  66. i4 = (void*)e->ai_addr;
  67. return ntohs(i4->sin_port);
  68. default:
  69. return 0;
  70. }
  71. }
  72. static void inet_setport(struct addrinfo *e, int port)
  73. {
  74. struct sockaddr_in *i4;
  75. struct sockaddr_in6 *i6;
  76. switch (e->ai_family) {
  77. case PF_INET6:
  78. i6 = (void*)e->ai_addr;
  79. i6->sin6_port = htons(port);
  80. break;
  81. case PF_INET:
  82. i4 = (void*)e->ai_addr;
  83. i4->sin_port = htons(port);
  84. break;
  85. }
  86. }
  87. const char *inet_strfamily(int family)
  88. {
  89. switch (family) {
  90. case PF_INET6: return "ipv6";
  91. case PF_INET: return "ipv4";
  92. case PF_UNIX: return "unix";
  93. }
  94. return "unknown";
  95. }
  96. int inet_listen_opts(QemuOpts *opts, int port_offset, Error **errp)
  97. {
  98. struct addrinfo ai,*res,*e;
  99. const char *addr;
  100. char port[33];
  101. char uaddr[INET6_ADDRSTRLEN+1];
  102. char uport[33];
  103. int slisten, rc, to, port_min, port_max, p;
  104. memset(&ai,0, sizeof(ai));
  105. ai.ai_flags = AI_PASSIVE | AI_ADDRCONFIG;
  106. ai.ai_family = PF_UNSPEC;
  107. ai.ai_socktype = SOCK_STREAM;
  108. if ((qemu_opt_get(opts, "host") == NULL) ||
  109. (qemu_opt_get(opts, "port") == NULL)) {
  110. fprintf(stderr, "%s: host and/or port not specified\n", __FUNCTION__);
  111. error_set(errp, QERR_SOCKET_CREATE_FAILED);
  112. return -1;
  113. }
  114. pstrcpy(port, sizeof(port), qemu_opt_get(opts, "port"));
  115. addr = qemu_opt_get(opts, "host");
  116. to = qemu_opt_get_number(opts, "to", 0);
  117. if (qemu_opt_get_bool(opts, "ipv4", 0))
  118. ai.ai_family = PF_INET;
  119. if (qemu_opt_get_bool(opts, "ipv6", 0))
  120. ai.ai_family = PF_INET6;
  121. /* lookup */
  122. if (port_offset)
  123. snprintf(port, sizeof(port), "%d", atoi(port) + port_offset);
  124. rc = getaddrinfo(strlen(addr) ? addr : NULL, port, &ai, &res);
  125. if (rc != 0) {
  126. fprintf(stderr,"getaddrinfo(%s,%s): %s\n", addr, port,
  127. gai_strerror(rc));
  128. error_set(errp, QERR_SOCKET_CREATE_FAILED);
  129. return -1;
  130. }
  131. /* create socket + bind */
  132. for (e = res; e != NULL; e = e->ai_next) {
  133. getnameinfo((struct sockaddr*)e->ai_addr,e->ai_addrlen,
  134. uaddr,INET6_ADDRSTRLEN,uport,32,
  135. NI_NUMERICHOST | NI_NUMERICSERV);
  136. slisten = qemu_socket(e->ai_family, e->ai_socktype, e->ai_protocol);
  137. if (slisten < 0) {
  138. fprintf(stderr,"%s: socket(%s): %s\n", __FUNCTION__,
  139. inet_strfamily(e->ai_family), strerror(errno));
  140. if (!e->ai_next) {
  141. error_set(errp, QERR_SOCKET_CREATE_FAILED);
  142. }
  143. continue;
  144. }
  145. setsockopt(slisten,SOL_SOCKET,SO_REUSEADDR,(void*)&on,sizeof(on));
  146. #ifdef IPV6_V6ONLY
  147. if (e->ai_family == PF_INET6) {
  148. /* listen on both ipv4 and ipv6 */
  149. setsockopt(slisten,IPPROTO_IPV6,IPV6_V6ONLY,(void*)&off,
  150. sizeof(off));
  151. }
  152. #endif
  153. port_min = inet_getport(e);
  154. port_max = to ? to + port_offset : port_min;
  155. for (p = port_min; p <= port_max; p++) {
  156. inet_setport(e, p);
  157. if (bind(slisten, e->ai_addr, e->ai_addrlen) == 0) {
  158. goto listen;
  159. }
  160. if (p == port_max) {
  161. fprintf(stderr,"%s: bind(%s,%s,%d): %s\n", __FUNCTION__,
  162. inet_strfamily(e->ai_family), uaddr, inet_getport(e),
  163. strerror(errno));
  164. if (!e->ai_next) {
  165. error_set(errp, QERR_SOCKET_BIND_FAILED);
  166. }
  167. }
  168. }
  169. closesocket(slisten);
  170. }
  171. fprintf(stderr, "%s: FAILED\n", __FUNCTION__);
  172. freeaddrinfo(res);
  173. return -1;
  174. listen:
  175. if (listen(slisten,1) != 0) {
  176. error_set(errp, QERR_SOCKET_LISTEN_FAILED);
  177. perror("listen");
  178. closesocket(slisten);
  179. freeaddrinfo(res);
  180. return -1;
  181. }
  182. snprintf(uport, sizeof(uport), "%d", inet_getport(e) - port_offset);
  183. qemu_opt_set(opts, "host", uaddr);
  184. qemu_opt_set(opts, "port", uport);
  185. qemu_opt_set(opts, "ipv6", (e->ai_family == PF_INET6) ? "on" : "off");
  186. qemu_opt_set(opts, "ipv4", (e->ai_family != PF_INET6) ? "on" : "off");
  187. freeaddrinfo(res);
  188. return slisten;
  189. }
  190. int inet_connect_opts(QemuOpts *opts, Error **errp)
  191. {
  192. struct addrinfo ai,*res,*e;
  193. const char *addr;
  194. const char *port;
  195. char uaddr[INET6_ADDRSTRLEN+1];
  196. char uport[33];
  197. int sock,rc;
  198. bool block;
  199. memset(&ai,0, sizeof(ai));
  200. ai.ai_flags = AI_CANONNAME | AI_ADDRCONFIG;
  201. ai.ai_family = PF_UNSPEC;
  202. ai.ai_socktype = SOCK_STREAM;
  203. addr = qemu_opt_get(opts, "host");
  204. port = qemu_opt_get(opts, "port");
  205. block = qemu_opt_get_bool(opts, "block", 0);
  206. if (addr == NULL || port == NULL) {
  207. fprintf(stderr, "inet_connect: host and/or port not specified\n");
  208. error_set(errp, QERR_SOCKET_CREATE_FAILED);
  209. return -1;
  210. }
  211. if (qemu_opt_get_bool(opts, "ipv4", 0))
  212. ai.ai_family = PF_INET;
  213. if (qemu_opt_get_bool(opts, "ipv6", 0))
  214. ai.ai_family = PF_INET6;
  215. /* lookup */
  216. if (0 != (rc = getaddrinfo(addr, port, &ai, &res))) {
  217. fprintf(stderr,"getaddrinfo(%s,%s): %s\n", addr, port,
  218. gai_strerror(rc));
  219. error_set(errp, QERR_SOCKET_CREATE_FAILED);
  220. return -1;
  221. }
  222. for (e = res; e != NULL; e = e->ai_next) {
  223. if (getnameinfo((struct sockaddr*)e->ai_addr,e->ai_addrlen,
  224. uaddr,INET6_ADDRSTRLEN,uport,32,
  225. NI_NUMERICHOST | NI_NUMERICSERV) != 0) {
  226. fprintf(stderr,"%s: getnameinfo: oops\n", __FUNCTION__);
  227. continue;
  228. }
  229. sock = qemu_socket(e->ai_family, e->ai_socktype, e->ai_protocol);
  230. if (sock < 0) {
  231. fprintf(stderr,"%s: socket(%s): %s\n", __FUNCTION__,
  232. inet_strfamily(e->ai_family), strerror(errno));
  233. continue;
  234. }
  235. setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,(void*)&on,sizeof(on));
  236. if (!block) {
  237. socket_set_nonblock(sock);
  238. }
  239. /* connect to peer */
  240. do {
  241. rc = 0;
  242. if (connect(sock, e->ai_addr, e->ai_addrlen) < 0) {
  243. rc = -socket_error();
  244. }
  245. } while (rc == -EINTR);
  246. #ifdef _WIN32
  247. if (!block && (rc == -EINPROGRESS || rc == -EWOULDBLOCK
  248. || rc == -WSAEALREADY)) {
  249. #else
  250. if (!block && (rc == -EINPROGRESS)) {
  251. #endif
  252. error_set(errp, QERR_SOCKET_CONNECT_IN_PROGRESS);
  253. } else if (rc < 0) {
  254. if (NULL == e->ai_next)
  255. fprintf(stderr, "%s: connect(%s,%s,%s,%s): %s\n", __FUNCTION__,
  256. inet_strfamily(e->ai_family),
  257. e->ai_canonname, uaddr, uport, strerror(errno));
  258. closesocket(sock);
  259. sock = -1;
  260. continue;
  261. }
  262. freeaddrinfo(res);
  263. return sock;
  264. }
  265. error_set(errp, QERR_SOCKET_CONNECT_FAILED);
  266. freeaddrinfo(res);
  267. return -1;
  268. }
  269. int inet_dgram_opts(QemuOpts *opts)
  270. {
  271. struct addrinfo ai, *peer = NULL, *local = NULL;
  272. const char *addr;
  273. const char *port;
  274. char uaddr[INET6_ADDRSTRLEN+1];
  275. char uport[33];
  276. int sock = -1, rc;
  277. /* lookup peer addr */
  278. memset(&ai,0, sizeof(ai));
  279. ai.ai_flags = AI_CANONNAME | AI_ADDRCONFIG;
  280. ai.ai_family = PF_UNSPEC;
  281. ai.ai_socktype = SOCK_DGRAM;
  282. addr = qemu_opt_get(opts, "host");
  283. port = qemu_opt_get(opts, "port");
  284. if (addr == NULL || strlen(addr) == 0) {
  285. addr = "localhost";
  286. }
  287. if (port == NULL || strlen(port) == 0) {
  288. fprintf(stderr, "inet_dgram: port not specified\n");
  289. return -1;
  290. }
  291. if (qemu_opt_get_bool(opts, "ipv4", 0))
  292. ai.ai_family = PF_INET;
  293. if (qemu_opt_get_bool(opts, "ipv6", 0))
  294. ai.ai_family = PF_INET6;
  295. if (0 != (rc = getaddrinfo(addr, port, &ai, &peer))) {
  296. fprintf(stderr,"getaddrinfo(%s,%s): %s\n", addr, port,
  297. gai_strerror(rc));
  298. return -1;
  299. }
  300. /* lookup local addr */
  301. memset(&ai,0, sizeof(ai));
  302. ai.ai_flags = AI_PASSIVE;
  303. ai.ai_family = peer->ai_family;
  304. ai.ai_socktype = SOCK_DGRAM;
  305. addr = qemu_opt_get(opts, "localaddr");
  306. port = qemu_opt_get(opts, "localport");
  307. if (addr == NULL || strlen(addr) == 0) {
  308. addr = NULL;
  309. }
  310. if (!port || strlen(port) == 0)
  311. port = "0";
  312. if (0 != (rc = getaddrinfo(addr, port, &ai, &local))) {
  313. fprintf(stderr,"getaddrinfo(%s,%s): %s\n", addr, port,
  314. gai_strerror(rc));
  315. return -1;
  316. }
  317. /* create socket */
  318. sock = qemu_socket(peer->ai_family, peer->ai_socktype, peer->ai_protocol);
  319. if (sock < 0) {
  320. fprintf(stderr,"%s: socket(%s): %s\n", __FUNCTION__,
  321. inet_strfamily(peer->ai_family), strerror(errno));
  322. goto err;
  323. }
  324. setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,(void*)&on,sizeof(on));
  325. /* bind socket */
  326. if (getnameinfo((struct sockaddr*)local->ai_addr,local->ai_addrlen,
  327. uaddr,INET6_ADDRSTRLEN,uport,32,
  328. NI_NUMERICHOST | NI_NUMERICSERV) != 0) {
  329. fprintf(stderr, "%s: getnameinfo: oops\n", __FUNCTION__);
  330. goto err;
  331. }
  332. if (bind(sock, local->ai_addr, local->ai_addrlen) < 0) {
  333. fprintf(stderr,"%s: bind(%s,%s,%d): OK\n", __FUNCTION__,
  334. inet_strfamily(local->ai_family), uaddr, inet_getport(local));
  335. goto err;
  336. }
  337. /* connect to peer */
  338. if (getnameinfo((struct sockaddr*)peer->ai_addr, peer->ai_addrlen,
  339. uaddr, INET6_ADDRSTRLEN, uport, 32,
  340. NI_NUMERICHOST | NI_NUMERICSERV) != 0) {
  341. fprintf(stderr, "%s: getnameinfo: oops\n", __FUNCTION__);
  342. goto err;
  343. }
  344. if (connect(sock,peer->ai_addr,peer->ai_addrlen) < 0) {
  345. fprintf(stderr, "%s: connect(%s,%s,%s,%s): %s\n", __FUNCTION__,
  346. inet_strfamily(peer->ai_family),
  347. peer->ai_canonname, uaddr, uport, strerror(errno));
  348. goto err;
  349. }
  350. freeaddrinfo(local);
  351. freeaddrinfo(peer);
  352. return sock;
  353. err:
  354. if (-1 != sock)
  355. closesocket(sock);
  356. if (local)
  357. freeaddrinfo(local);
  358. if (peer)
  359. freeaddrinfo(peer);
  360. return -1;
  361. }
  362. /* compatibility wrapper */
  363. static int inet_parse(QemuOpts *opts, const char *str)
  364. {
  365. const char *optstr, *h;
  366. char addr[64];
  367. char port[33];
  368. int pos;
  369. /* parse address */
  370. if (str[0] == ':') {
  371. /* no host given */
  372. addr[0] = '\0';
  373. if (1 != sscanf(str,":%32[^,]%n",port,&pos)) {
  374. fprintf(stderr, "%s: portonly parse error (%s)\n",
  375. __FUNCTION__, str);
  376. return -1;
  377. }
  378. } else if (str[0] == '[') {
  379. /* IPv6 addr */
  380. if (2 != sscanf(str,"[%64[^]]]:%32[^,]%n",addr,port,&pos)) {
  381. fprintf(stderr, "%s: ipv6 parse error (%s)\n",
  382. __FUNCTION__, str);
  383. return -1;
  384. }
  385. qemu_opt_set(opts, "ipv6", "on");
  386. } else if (qemu_isdigit(str[0])) {
  387. /* IPv4 addr */
  388. if (2 != sscanf(str,"%64[0-9.]:%32[^,]%n",addr,port,&pos)) {
  389. fprintf(stderr, "%s: ipv4 parse error (%s)\n",
  390. __FUNCTION__, str);
  391. return -1;
  392. }
  393. qemu_opt_set(opts, "ipv4", "on");
  394. } else {
  395. /* hostname */
  396. if (2 != sscanf(str,"%64[^:]:%32[^,]%n",addr,port,&pos)) {
  397. fprintf(stderr, "%s: hostname parse error (%s)\n",
  398. __FUNCTION__, str);
  399. return -1;
  400. }
  401. }
  402. qemu_opt_set(opts, "host", addr);
  403. qemu_opt_set(opts, "port", port);
  404. /* parse options */
  405. optstr = str + pos;
  406. h = strstr(optstr, ",to=");
  407. if (h)
  408. qemu_opt_set(opts, "to", h+4);
  409. if (strstr(optstr, ",ipv4"))
  410. qemu_opt_set(opts, "ipv4", "on");
  411. if (strstr(optstr, ",ipv6"))
  412. qemu_opt_set(opts, "ipv6", "on");
  413. return 0;
  414. }
  415. int inet_listen(const char *str, char *ostr, int olen,
  416. int socktype, int port_offset, Error **errp)
  417. {
  418. QemuOpts *opts;
  419. char *optstr;
  420. int sock = -1;
  421. opts = qemu_opts_create(&dummy_opts, NULL, 0);
  422. if (inet_parse(opts, str) == 0) {
  423. sock = inet_listen_opts(opts, port_offset, errp);
  424. if (sock != -1 && ostr) {
  425. optstr = strchr(str, ',');
  426. if (qemu_opt_get_bool(opts, "ipv6", 0)) {
  427. snprintf(ostr, olen, "[%s]:%s%s",
  428. qemu_opt_get(opts, "host"),
  429. qemu_opt_get(opts, "port"),
  430. optstr ? optstr : "");
  431. } else {
  432. snprintf(ostr, olen, "%s:%s%s",
  433. qemu_opt_get(opts, "host"),
  434. qemu_opt_get(opts, "port"),
  435. optstr ? optstr : "");
  436. }
  437. }
  438. } else {
  439. error_set(errp, QERR_SOCKET_CREATE_FAILED);
  440. }
  441. qemu_opts_del(opts);
  442. return sock;
  443. }
  444. int inet_connect(const char *str, bool block, Error **errp)
  445. {
  446. QemuOpts *opts;
  447. int sock = -1;
  448. opts = qemu_opts_create(&dummy_opts, NULL, 0);
  449. if (inet_parse(opts, str) == 0) {
  450. if (block) {
  451. qemu_opt_set(opts, "block", "on");
  452. }
  453. sock = inet_connect_opts(opts, errp);
  454. } else {
  455. error_set(errp, QERR_SOCKET_CREATE_FAILED);
  456. }
  457. qemu_opts_del(opts);
  458. return sock;
  459. }
  460. #ifndef _WIN32
  461. int unix_listen_opts(QemuOpts *opts)
  462. {
  463. struct sockaddr_un un;
  464. const char *path = qemu_opt_get(opts, "path");
  465. int sock, fd;
  466. sock = qemu_socket(PF_UNIX, SOCK_STREAM, 0);
  467. if (sock < 0) {
  468. perror("socket(unix)");
  469. return -1;
  470. }
  471. memset(&un, 0, sizeof(un));
  472. un.sun_family = AF_UNIX;
  473. if (path && strlen(path)) {
  474. snprintf(un.sun_path, sizeof(un.sun_path), "%s", path);
  475. } else {
  476. char *tmpdir = getenv("TMPDIR");
  477. snprintf(un.sun_path, sizeof(un.sun_path), "%s/qemu-socket-XXXXXX",
  478. tmpdir ? tmpdir : "/tmp");
  479. /*
  480. * This dummy fd usage silences the mktemp() unsecure warning.
  481. * Using mkstemp() doesn't make things more secure here
  482. * though. bind() complains about existing files, so we have
  483. * to unlink first and thus re-open the race window. The
  484. * worst case possible is bind() failing, i.e. a DoS attack.
  485. */
  486. fd = mkstemp(un.sun_path); close(fd);
  487. qemu_opt_set(opts, "path", un.sun_path);
  488. }
  489. unlink(un.sun_path);
  490. if (bind(sock, (struct sockaddr*) &un, sizeof(un)) < 0) {
  491. fprintf(stderr, "bind(unix:%s): %s\n", un.sun_path, strerror(errno));
  492. goto err;
  493. }
  494. if (listen(sock, 1) < 0) {
  495. fprintf(stderr, "listen(unix:%s): %s\n", un.sun_path, strerror(errno));
  496. goto err;
  497. }
  498. return sock;
  499. err:
  500. closesocket(sock);
  501. return -1;
  502. }
  503. int unix_connect_opts(QemuOpts *opts)
  504. {
  505. struct sockaddr_un un;
  506. const char *path = qemu_opt_get(opts, "path");
  507. int sock;
  508. if (NULL == path) {
  509. fprintf(stderr, "unix connect: no path specified\n");
  510. return -1;
  511. }
  512. sock = qemu_socket(PF_UNIX, SOCK_STREAM, 0);
  513. if (sock < 0) {
  514. perror("socket(unix)");
  515. return -1;
  516. }
  517. memset(&un, 0, sizeof(un));
  518. un.sun_family = AF_UNIX;
  519. snprintf(un.sun_path, sizeof(un.sun_path), "%s", path);
  520. if (connect(sock, (struct sockaddr*) &un, sizeof(un)) < 0) {
  521. fprintf(stderr, "connect(unix:%s): %s\n", path, strerror(errno));
  522. close(sock);
  523. return -1;
  524. }
  525. return sock;
  526. }
  527. /* compatibility wrapper */
  528. int unix_listen(const char *str, char *ostr, int olen)
  529. {
  530. QemuOpts *opts;
  531. char *path, *optstr;
  532. int sock, len;
  533. opts = qemu_opts_create(&dummy_opts, NULL, 0);
  534. optstr = strchr(str, ',');
  535. if (optstr) {
  536. len = optstr - str;
  537. if (len) {
  538. path = g_malloc(len+1);
  539. snprintf(path, len+1, "%.*s", len, str);
  540. qemu_opt_set(opts, "path", path);
  541. g_free(path);
  542. }
  543. } else {
  544. qemu_opt_set(opts, "path", str);
  545. }
  546. sock = unix_listen_opts(opts);
  547. if (sock != -1 && ostr)
  548. snprintf(ostr, olen, "%s%s", qemu_opt_get(opts, "path"), optstr ? optstr : "");
  549. qemu_opts_del(opts);
  550. return sock;
  551. }
  552. int unix_connect(const char *path)
  553. {
  554. QemuOpts *opts;
  555. int sock;
  556. opts = qemu_opts_create(&dummy_opts, NULL, 0);
  557. qemu_opt_set(opts, "path", path);
  558. sock = unix_connect_opts(opts);
  559. qemu_opts_del(opts);
  560. return sock;
  561. }
  562. #else
  563. int unix_listen_opts(QemuOpts *opts)
  564. {
  565. fprintf(stderr, "unix sockets are not available on windows\n");
  566. errno = ENOTSUP;
  567. return -1;
  568. }
  569. int unix_connect_opts(QemuOpts *opts)
  570. {
  571. fprintf(stderr, "unix sockets are not available on windows\n");
  572. errno = ENOTSUP;
  573. return -1;
  574. }
  575. int unix_listen(const char *path, char *ostr, int olen)
  576. {
  577. fprintf(stderr, "unix sockets are not available on windows\n");
  578. errno = ENOTSUP;
  579. return -1;
  580. }
  581. int unix_connect(const char *path)
  582. {
  583. fprintf(stderr, "unix sockets are not available on windows\n");
  584. errno = ENOTSUP;
  585. return -1;
  586. }
  587. #endif
  588. #ifdef _WIN32
  589. static void socket_cleanup(void)
  590. {
  591. WSACleanup();
  592. }
  593. #endif
  594. int socket_init(void)
  595. {
  596. #ifdef _WIN32
  597. WSADATA Data;
  598. int ret, err;
  599. ret = WSAStartup(MAKEWORD(2,2), &Data);
  600. if (ret != 0) {
  601. err = WSAGetLastError();
  602. fprintf(stderr, "WSAStartup: %d\n", err);
  603. return -1;
  604. }
  605. atexit(socket_cleanup);
  606. #endif
  607. return 0;
  608. }