2
0

qemu-sockets.c 19 KB

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