qemu-sockets.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679
  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. return -1;
  518. }
  519. if (sockets_debug)
  520. fprintf(stderr, "connect(unix:%s): OK\n", path);
  521. return sock;
  522. }
  523. /* compatibility wrapper */
  524. int unix_listen(const char *str, char *ostr, int olen)
  525. {
  526. QemuOpts *opts;
  527. char *path, *optstr;
  528. int sock, len;
  529. opts = qemu_opts_create(&dummy_opts, NULL, 0);
  530. optstr = strchr(str, ',');
  531. if (optstr) {
  532. len = optstr - str;
  533. if (len) {
  534. path = qemu_malloc(len+1);
  535. snprintf(path, len+1, "%.*s", len, str);
  536. qemu_opt_set(opts, "path", path);
  537. qemu_free(path);
  538. }
  539. } else {
  540. qemu_opt_set(opts, "path", str);
  541. }
  542. sock = unix_listen_opts(opts);
  543. if (sock != -1 && ostr)
  544. snprintf(ostr, olen, "%s%s", qemu_opt_get(opts, "path"), optstr ? optstr : "");
  545. qemu_opts_del(opts);
  546. return sock;
  547. }
  548. int unix_connect(const char *path)
  549. {
  550. QemuOpts *opts;
  551. int sock;
  552. opts = qemu_opts_create(&dummy_opts, NULL, 0);
  553. qemu_opt_set(opts, "path", path);
  554. sock = unix_connect_opts(opts);
  555. qemu_opts_del(opts);
  556. return sock;
  557. }
  558. #else
  559. int unix_listen_opts(QemuOpts *opts)
  560. {
  561. fprintf(stderr, "unix sockets are not available on windows\n");
  562. errno = ENOTSUP;
  563. return -1;
  564. }
  565. int unix_connect_opts(QemuOpts *opts)
  566. {
  567. fprintf(stderr, "unix sockets are not available on windows\n");
  568. errno = ENOTSUP;
  569. return -1;
  570. }
  571. int unix_listen(const char *path, char *ostr, int olen)
  572. {
  573. fprintf(stderr, "unix sockets are not available on windows\n");
  574. errno = ENOTSUP;
  575. return -1;
  576. }
  577. int unix_connect(const char *path)
  578. {
  579. fprintf(stderr, "unix sockets are not available on windows\n");
  580. errno = ENOTSUP;
  581. return -1;
  582. }
  583. #endif
  584. #ifdef _WIN32
  585. static void socket_cleanup(void)
  586. {
  587. WSACleanup();
  588. }
  589. #endif
  590. int socket_init(void)
  591. {
  592. #ifdef _WIN32
  593. WSADATA Data;
  594. int ret, err;
  595. ret = WSAStartup(MAKEWORD(2,2), &Data);
  596. if (ret != 0) {
  597. err = WSAGetLastError();
  598. fprintf(stderr, "WSAStartup: %d\n", err);
  599. return -1;
  600. }
  601. atexit(socket_cleanup);
  602. #endif
  603. return 0;
  604. }