qemu-sockets.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830
  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. * Contributions after 2012-01-13 are licensed under the terms of the
  16. * GNU GPL, version 2 or (at your option) any later version.
  17. */
  18. #include <stdio.h>
  19. #include <stdlib.h>
  20. #include <string.h>
  21. #include <ctype.h>
  22. #include <errno.h>
  23. #include <unistd.h>
  24. #include "qemu_socket.h"
  25. #include "qemu-common.h" /* for qemu_isdigit */
  26. #include "main-loop.h"
  27. #ifndef AI_ADDRCONFIG
  28. # define AI_ADDRCONFIG 0
  29. #endif
  30. static const int on=1, off=0;
  31. /* used temporarely until all users are converted to QemuOpts */
  32. static QemuOptsList dummy_opts = {
  33. .name = "dummy",
  34. .head = QTAILQ_HEAD_INITIALIZER(dummy_opts.head),
  35. .desc = {
  36. {
  37. .name = "path",
  38. .type = QEMU_OPT_STRING,
  39. },{
  40. .name = "host",
  41. .type = QEMU_OPT_STRING,
  42. },{
  43. .name = "port",
  44. .type = QEMU_OPT_STRING,
  45. },{
  46. .name = "to",
  47. .type = QEMU_OPT_NUMBER,
  48. },{
  49. .name = "ipv4",
  50. .type = QEMU_OPT_BOOL,
  51. },{
  52. .name = "ipv6",
  53. .type = QEMU_OPT_BOOL,
  54. },
  55. { /* end if list */ }
  56. },
  57. };
  58. static int inet_getport(struct addrinfo *e)
  59. {
  60. struct sockaddr_in *i4;
  61. struct sockaddr_in6 *i6;
  62. switch (e->ai_family) {
  63. case PF_INET6:
  64. i6 = (void*)e->ai_addr;
  65. return ntohs(i6->sin6_port);
  66. case PF_INET:
  67. i4 = (void*)e->ai_addr;
  68. return ntohs(i4->sin_port);
  69. default:
  70. return 0;
  71. }
  72. }
  73. static void inet_setport(struct addrinfo *e, int port)
  74. {
  75. struct sockaddr_in *i4;
  76. struct sockaddr_in6 *i6;
  77. switch (e->ai_family) {
  78. case PF_INET6:
  79. i6 = (void*)e->ai_addr;
  80. i6->sin6_port = htons(port);
  81. break;
  82. case PF_INET:
  83. i4 = (void*)e->ai_addr;
  84. i4->sin_port = htons(port);
  85. break;
  86. }
  87. }
  88. const char *inet_strfamily(int family)
  89. {
  90. switch (family) {
  91. case PF_INET6: return "ipv6";
  92. case PF_INET: return "ipv4";
  93. case PF_UNIX: return "unix";
  94. }
  95. return "unknown";
  96. }
  97. int inet_listen_opts(QemuOpts *opts, int port_offset, Error **errp)
  98. {
  99. struct addrinfo ai,*res,*e;
  100. const char *addr;
  101. char port[33];
  102. char uaddr[INET6_ADDRSTRLEN+1];
  103. char uport[33];
  104. int slisten, rc, to, port_min, port_max, p;
  105. memset(&ai,0, sizeof(ai));
  106. ai.ai_flags = AI_PASSIVE | AI_ADDRCONFIG;
  107. ai.ai_family = PF_UNSPEC;
  108. ai.ai_socktype = SOCK_STREAM;
  109. if ((qemu_opt_get(opts, "host") == NULL) ||
  110. (qemu_opt_get(opts, "port") == NULL)) {
  111. fprintf(stderr, "%s: host and/or port not specified\n", __FUNCTION__);
  112. error_set(errp, QERR_SOCKET_CREATE_FAILED);
  113. return -1;
  114. }
  115. pstrcpy(port, sizeof(port), qemu_opt_get(opts, "port"));
  116. addr = qemu_opt_get(opts, "host");
  117. to = qemu_opt_get_number(opts, "to", 0);
  118. if (qemu_opt_get_bool(opts, "ipv4", 0))
  119. ai.ai_family = PF_INET;
  120. if (qemu_opt_get_bool(opts, "ipv6", 0))
  121. ai.ai_family = PF_INET6;
  122. /* lookup */
  123. if (port_offset)
  124. snprintf(port, sizeof(port), "%d", atoi(port) + port_offset);
  125. rc = getaddrinfo(strlen(addr) ? addr : NULL, port, &ai, &res);
  126. if (rc != 0) {
  127. fprintf(stderr,"getaddrinfo(%s,%s): %s\n", addr, port,
  128. gai_strerror(rc));
  129. error_set(errp, QERR_SOCKET_CREATE_FAILED);
  130. return -1;
  131. }
  132. /* create socket + bind */
  133. for (e = res; e != NULL; e = e->ai_next) {
  134. getnameinfo((struct sockaddr*)e->ai_addr,e->ai_addrlen,
  135. uaddr,INET6_ADDRSTRLEN,uport,32,
  136. NI_NUMERICHOST | NI_NUMERICSERV);
  137. slisten = qemu_socket(e->ai_family, e->ai_socktype, e->ai_protocol);
  138. if (slisten < 0) {
  139. fprintf(stderr,"%s: socket(%s): %s\n", __FUNCTION__,
  140. inet_strfamily(e->ai_family), strerror(errno));
  141. if (!e->ai_next) {
  142. error_set(errp, QERR_SOCKET_CREATE_FAILED);
  143. }
  144. continue;
  145. }
  146. setsockopt(slisten,SOL_SOCKET,SO_REUSEADDR,(void*)&on,sizeof(on));
  147. #ifdef IPV6_V6ONLY
  148. if (e->ai_family == PF_INET6) {
  149. /* listen on both ipv4 and ipv6 */
  150. setsockopt(slisten,IPPROTO_IPV6,IPV6_V6ONLY,(void*)&off,
  151. sizeof(off));
  152. }
  153. #endif
  154. port_min = inet_getport(e);
  155. port_max = to ? to + port_offset : port_min;
  156. for (p = port_min; p <= port_max; p++) {
  157. inet_setport(e, p);
  158. if (bind(slisten, e->ai_addr, e->ai_addrlen) == 0) {
  159. goto listen;
  160. }
  161. if (p == port_max) {
  162. fprintf(stderr,"%s: bind(%s,%s,%d): %s\n", __FUNCTION__,
  163. inet_strfamily(e->ai_family), uaddr, inet_getport(e),
  164. strerror(errno));
  165. if (!e->ai_next) {
  166. error_set(errp, QERR_SOCKET_BIND_FAILED);
  167. }
  168. }
  169. }
  170. closesocket(slisten);
  171. }
  172. fprintf(stderr, "%s: FAILED\n", __FUNCTION__);
  173. freeaddrinfo(res);
  174. return -1;
  175. listen:
  176. if (listen(slisten,1) != 0) {
  177. error_set(errp, QERR_SOCKET_LISTEN_FAILED);
  178. perror("listen");
  179. closesocket(slisten);
  180. freeaddrinfo(res);
  181. return -1;
  182. }
  183. snprintf(uport, sizeof(uport), "%d", inet_getport(e) - port_offset);
  184. qemu_opt_set(opts, "host", uaddr);
  185. qemu_opt_set(opts, "port", uport);
  186. qemu_opt_set(opts, "ipv6", (e->ai_family == PF_INET6) ? "on" : "off");
  187. qemu_opt_set(opts, "ipv4", (e->ai_family != PF_INET6) ? "on" : "off");
  188. freeaddrinfo(res);
  189. return slisten;
  190. }
  191. #ifdef _WIN32
  192. #define QEMU_SOCKET_RC_INPROGRESS(rc) \
  193. ((rc) == -EINPROGRESS || (rc) == -EWOULDBLOCK || (rc) == -WSAEALREADY)
  194. #else
  195. #define QEMU_SOCKET_RC_INPROGRESS(rc) \
  196. ((rc) == -EINPROGRESS)
  197. #endif
  198. /* Struct to store connect state for non blocking connect */
  199. typedef struct ConnectState {
  200. int fd;
  201. struct addrinfo *addr_list;
  202. struct addrinfo *current_addr;
  203. NonBlockingConnectHandler *callback;
  204. void *opaque;
  205. } ConnectState;
  206. static int inet_connect_addr(struct addrinfo *addr, bool *in_progress,
  207. ConnectState *connect_state);
  208. static void wait_for_connect(void *opaque)
  209. {
  210. ConnectState *s = opaque;
  211. int val = 0, rc = 0;
  212. socklen_t valsize = sizeof(val);
  213. bool in_progress;
  214. qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL);
  215. do {
  216. rc = getsockopt(s->fd, SOL_SOCKET, SO_ERROR, (void *) &val, &valsize);
  217. } while (rc == -1 && socket_error() == EINTR);
  218. /* update rc to contain error */
  219. if (!rc && val) {
  220. rc = -1;
  221. }
  222. /* connect error */
  223. if (rc < 0) {
  224. closesocket(s->fd);
  225. s->fd = rc;
  226. }
  227. /* try to connect to the next address on the list */
  228. while (s->current_addr->ai_next != NULL && s->fd < 0) {
  229. s->current_addr = s->current_addr->ai_next;
  230. s->fd = inet_connect_addr(s->current_addr, &in_progress, s);
  231. /* connect in progress */
  232. if (in_progress) {
  233. return;
  234. }
  235. }
  236. freeaddrinfo(s->addr_list);
  237. if (s->callback) {
  238. s->callback(s->fd, s->opaque);
  239. }
  240. g_free(s);
  241. return;
  242. }
  243. static int inet_connect_addr(struct addrinfo *addr, bool *in_progress,
  244. ConnectState *connect_state)
  245. {
  246. int sock, rc;
  247. *in_progress = false;
  248. sock = qemu_socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
  249. if (sock < 0) {
  250. fprintf(stderr, "%s: socket(%s): %s\n", __func__,
  251. inet_strfamily(addr->ai_family), strerror(errno));
  252. return -1;
  253. }
  254. setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
  255. if (connect_state != NULL) {
  256. socket_set_nonblock(sock);
  257. }
  258. /* connect to peer */
  259. do {
  260. rc = 0;
  261. if (connect(sock, addr->ai_addr, addr->ai_addrlen) < 0) {
  262. rc = -socket_error();
  263. }
  264. } while (rc == -EINTR);
  265. if (connect_state != NULL && QEMU_SOCKET_RC_INPROGRESS(rc)) {
  266. connect_state->fd = sock;
  267. qemu_set_fd_handler2(sock, NULL, NULL, wait_for_connect,
  268. connect_state);
  269. *in_progress = true;
  270. } else if (rc < 0) {
  271. closesocket(sock);
  272. return -1;
  273. }
  274. return sock;
  275. }
  276. static struct addrinfo *inet_parse_connect_opts(QemuOpts *opts, Error **errp)
  277. {
  278. struct addrinfo ai, *res;
  279. int rc;
  280. const char *addr;
  281. const char *port;
  282. memset(&ai, 0, sizeof(ai));
  283. ai.ai_flags = AI_CANONNAME | AI_ADDRCONFIG;
  284. ai.ai_family = PF_UNSPEC;
  285. ai.ai_socktype = SOCK_STREAM;
  286. addr = qemu_opt_get(opts, "host");
  287. port = qemu_opt_get(opts, "port");
  288. if (addr == NULL || port == NULL) {
  289. fprintf(stderr,
  290. "inet_parse_connect_opts: host and/or port not specified\n");
  291. error_set(errp, QERR_SOCKET_CREATE_FAILED);
  292. return NULL;
  293. }
  294. if (qemu_opt_get_bool(opts, "ipv4", 0)) {
  295. ai.ai_family = PF_INET;
  296. }
  297. if (qemu_opt_get_bool(opts, "ipv6", 0)) {
  298. ai.ai_family = PF_INET6;
  299. }
  300. /* lookup */
  301. rc = getaddrinfo(addr, port, &ai, &res);
  302. if (rc != 0) {
  303. fprintf(stderr, "getaddrinfo(%s,%s): %s\n", addr, port,
  304. gai_strerror(rc));
  305. error_set(errp, QERR_SOCKET_CREATE_FAILED);
  306. return NULL;
  307. }
  308. return res;
  309. }
  310. /**
  311. * Create a socket and connect it to an address.
  312. *
  313. * @opts: QEMU options, recognized parameters strings "host" and "port",
  314. * bools "ipv4" and "ipv6".
  315. * @errp: set on error
  316. * @callback: callback function for non-blocking connect
  317. * @opaque: opaque for callback function
  318. *
  319. * Returns: -1 on error, file descriptor on success.
  320. *
  321. * If @callback is non-null, the connect is non-blocking. If this
  322. * function succeeds, callback will be called when the connection
  323. * completes, with the file descriptor on success, or -1 on error.
  324. */
  325. int inet_connect_opts(QemuOpts *opts, Error **errp,
  326. NonBlockingConnectHandler *callback, void *opaque)
  327. {
  328. struct addrinfo *res, *e;
  329. int sock = -1;
  330. bool in_progress;
  331. ConnectState *connect_state = NULL;
  332. res = inet_parse_connect_opts(opts, errp);
  333. if (!res) {
  334. return -1;
  335. }
  336. if (callback != NULL) {
  337. connect_state = g_malloc0(sizeof(*connect_state));
  338. connect_state->addr_list = res;
  339. connect_state->callback = callback;
  340. connect_state->opaque = opaque;
  341. }
  342. for (e = res; e != NULL; e = e->ai_next) {
  343. if (connect_state != NULL) {
  344. connect_state->current_addr = e;
  345. }
  346. sock = inet_connect_addr(e, &in_progress, connect_state);
  347. if (in_progress) {
  348. return sock;
  349. } else if (sock >= 0) {
  350. /* non blocking socket immediate success, call callback */
  351. if (callback != NULL) {
  352. callback(sock, opaque);
  353. }
  354. break;
  355. }
  356. }
  357. if (sock < 0) {
  358. error_set(errp, QERR_SOCKET_CONNECT_FAILED);
  359. }
  360. g_free(connect_state);
  361. freeaddrinfo(res);
  362. return sock;
  363. }
  364. int inet_dgram_opts(QemuOpts *opts)
  365. {
  366. struct addrinfo ai, *peer = NULL, *local = NULL;
  367. const char *addr;
  368. const char *port;
  369. char uaddr[INET6_ADDRSTRLEN+1];
  370. char uport[33];
  371. int sock = -1, rc;
  372. /* lookup peer addr */
  373. memset(&ai,0, sizeof(ai));
  374. ai.ai_flags = AI_CANONNAME | AI_ADDRCONFIG;
  375. ai.ai_family = PF_UNSPEC;
  376. ai.ai_socktype = SOCK_DGRAM;
  377. addr = qemu_opt_get(opts, "host");
  378. port = qemu_opt_get(opts, "port");
  379. if (addr == NULL || strlen(addr) == 0) {
  380. addr = "localhost";
  381. }
  382. if (port == NULL || strlen(port) == 0) {
  383. fprintf(stderr, "inet_dgram: port not specified\n");
  384. return -1;
  385. }
  386. if (qemu_opt_get_bool(opts, "ipv4", 0))
  387. ai.ai_family = PF_INET;
  388. if (qemu_opt_get_bool(opts, "ipv6", 0))
  389. ai.ai_family = PF_INET6;
  390. if (0 != (rc = getaddrinfo(addr, port, &ai, &peer))) {
  391. fprintf(stderr,"getaddrinfo(%s,%s): %s\n", addr, port,
  392. gai_strerror(rc));
  393. return -1;
  394. }
  395. /* lookup local addr */
  396. memset(&ai,0, sizeof(ai));
  397. ai.ai_flags = AI_PASSIVE;
  398. ai.ai_family = peer->ai_family;
  399. ai.ai_socktype = SOCK_DGRAM;
  400. addr = qemu_opt_get(opts, "localaddr");
  401. port = qemu_opt_get(opts, "localport");
  402. if (addr == NULL || strlen(addr) == 0) {
  403. addr = NULL;
  404. }
  405. if (!port || strlen(port) == 0)
  406. port = "0";
  407. if (0 != (rc = getaddrinfo(addr, port, &ai, &local))) {
  408. fprintf(stderr,"getaddrinfo(%s,%s): %s\n", addr, port,
  409. gai_strerror(rc));
  410. goto err;
  411. }
  412. /* create socket */
  413. sock = qemu_socket(peer->ai_family, peer->ai_socktype, peer->ai_protocol);
  414. if (sock < 0) {
  415. fprintf(stderr,"%s: socket(%s): %s\n", __FUNCTION__,
  416. inet_strfamily(peer->ai_family), strerror(errno));
  417. goto err;
  418. }
  419. setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,(void*)&on,sizeof(on));
  420. /* bind socket */
  421. if (getnameinfo((struct sockaddr*)local->ai_addr,local->ai_addrlen,
  422. uaddr,INET6_ADDRSTRLEN,uport,32,
  423. NI_NUMERICHOST | NI_NUMERICSERV) != 0) {
  424. fprintf(stderr, "%s: getnameinfo: oops\n", __FUNCTION__);
  425. goto err;
  426. }
  427. if (bind(sock, local->ai_addr, local->ai_addrlen) < 0) {
  428. fprintf(stderr,"%s: bind(%s,%s,%d): OK\n", __FUNCTION__,
  429. inet_strfamily(local->ai_family), uaddr, inet_getport(local));
  430. goto err;
  431. }
  432. /* connect to peer */
  433. if (getnameinfo((struct sockaddr*)peer->ai_addr, peer->ai_addrlen,
  434. uaddr, INET6_ADDRSTRLEN, uport, 32,
  435. NI_NUMERICHOST | NI_NUMERICSERV) != 0) {
  436. fprintf(stderr, "%s: getnameinfo: oops\n", __FUNCTION__);
  437. goto err;
  438. }
  439. if (connect(sock,peer->ai_addr,peer->ai_addrlen) < 0) {
  440. fprintf(stderr, "%s: connect(%s,%s,%s,%s): %s\n", __FUNCTION__,
  441. inet_strfamily(peer->ai_family),
  442. peer->ai_canonname, uaddr, uport, strerror(errno));
  443. goto err;
  444. }
  445. freeaddrinfo(local);
  446. freeaddrinfo(peer);
  447. return sock;
  448. err:
  449. if (-1 != sock)
  450. closesocket(sock);
  451. if (local)
  452. freeaddrinfo(local);
  453. if (peer)
  454. freeaddrinfo(peer);
  455. return -1;
  456. }
  457. /* compatibility wrapper */
  458. static int inet_parse(QemuOpts *opts, const char *str)
  459. {
  460. const char *optstr, *h;
  461. char addr[64];
  462. char port[33];
  463. int pos;
  464. /* parse address */
  465. if (str[0] == ':') {
  466. /* no host given */
  467. addr[0] = '\0';
  468. if (1 != sscanf(str,":%32[^,]%n",port,&pos)) {
  469. fprintf(stderr, "%s: portonly parse error (%s)\n",
  470. __FUNCTION__, str);
  471. return -1;
  472. }
  473. } else if (str[0] == '[') {
  474. /* IPv6 addr */
  475. if (2 != sscanf(str,"[%64[^]]]:%32[^,]%n",addr,port,&pos)) {
  476. fprintf(stderr, "%s: ipv6 parse error (%s)\n",
  477. __FUNCTION__, str);
  478. return -1;
  479. }
  480. qemu_opt_set(opts, "ipv6", "on");
  481. } else if (qemu_isdigit(str[0])) {
  482. /* IPv4 addr */
  483. if (2 != sscanf(str,"%64[0-9.]:%32[^,]%n",addr,port,&pos)) {
  484. fprintf(stderr, "%s: ipv4 parse error (%s)\n",
  485. __FUNCTION__, str);
  486. return -1;
  487. }
  488. qemu_opt_set(opts, "ipv4", "on");
  489. } else {
  490. /* hostname */
  491. if (2 != sscanf(str,"%64[^:]:%32[^,]%n",addr,port,&pos)) {
  492. fprintf(stderr, "%s: hostname parse error (%s)\n",
  493. __FUNCTION__, str);
  494. return -1;
  495. }
  496. }
  497. qemu_opt_set(opts, "host", addr);
  498. qemu_opt_set(opts, "port", port);
  499. /* parse options */
  500. optstr = str + pos;
  501. h = strstr(optstr, ",to=");
  502. if (h)
  503. qemu_opt_set(opts, "to", h+4);
  504. if (strstr(optstr, ",ipv4"))
  505. qemu_opt_set(opts, "ipv4", "on");
  506. if (strstr(optstr, ",ipv6"))
  507. qemu_opt_set(opts, "ipv6", "on");
  508. return 0;
  509. }
  510. int inet_listen(const char *str, char *ostr, int olen,
  511. int socktype, int port_offset, Error **errp)
  512. {
  513. QemuOpts *opts;
  514. char *optstr;
  515. int sock = -1;
  516. opts = qemu_opts_create(&dummy_opts, NULL, 0, NULL);
  517. if (inet_parse(opts, str) == 0) {
  518. sock = inet_listen_opts(opts, port_offset, errp);
  519. if (sock != -1 && ostr) {
  520. optstr = strchr(str, ',');
  521. if (qemu_opt_get_bool(opts, "ipv6", 0)) {
  522. snprintf(ostr, olen, "[%s]:%s%s",
  523. qemu_opt_get(opts, "host"),
  524. qemu_opt_get(opts, "port"),
  525. optstr ? optstr : "");
  526. } else {
  527. snprintf(ostr, olen, "%s:%s%s",
  528. qemu_opt_get(opts, "host"),
  529. qemu_opt_get(opts, "port"),
  530. optstr ? optstr : "");
  531. }
  532. }
  533. } else {
  534. error_set(errp, QERR_SOCKET_CREATE_FAILED);
  535. }
  536. qemu_opts_del(opts);
  537. return sock;
  538. }
  539. /**
  540. * Create a blocking socket and connect it to an address.
  541. *
  542. * @str: address string
  543. * @errp: set in case of an error
  544. *
  545. * Returns -1 in case of error, file descriptor on success
  546. **/
  547. int inet_connect(const char *str, Error **errp)
  548. {
  549. QemuOpts *opts;
  550. int sock = -1;
  551. opts = qemu_opts_create(&dummy_opts, NULL, 0, NULL);
  552. if (inet_parse(opts, str) == 0) {
  553. sock = inet_connect_opts(opts, errp, NULL, NULL);
  554. } else {
  555. error_set(errp, QERR_SOCKET_CREATE_FAILED);
  556. }
  557. qemu_opts_del(opts);
  558. return sock;
  559. }
  560. /**
  561. * Create a non-blocking socket and connect it to an address.
  562. * Calls the callback function with fd in case of success or -1 in case of
  563. * error.
  564. *
  565. * @str: address string
  566. * @callback: callback function that is called when connect completes,
  567. * cannot be NULL.
  568. * @opaque: opaque for callback function
  569. * @errp: set in case of an error
  570. *
  571. * Returns: -1 on immediate error, file descriptor on success.
  572. **/
  573. int inet_nonblocking_connect(const char *str,
  574. NonBlockingConnectHandler *callback,
  575. void *opaque, Error **errp)
  576. {
  577. QemuOpts *opts;
  578. int sock = -1;
  579. g_assert(callback != NULL);
  580. opts = qemu_opts_create(&dummy_opts, NULL, 0, NULL);
  581. if (inet_parse(opts, str) == 0) {
  582. sock = inet_connect_opts(opts, errp, callback, opaque);
  583. } else {
  584. error_set(errp, QERR_SOCKET_CREATE_FAILED);
  585. }
  586. qemu_opts_del(opts);
  587. return sock;
  588. }
  589. #ifndef _WIN32
  590. int unix_listen_opts(QemuOpts *opts)
  591. {
  592. struct sockaddr_un un;
  593. const char *path = qemu_opt_get(opts, "path");
  594. int sock, fd;
  595. sock = qemu_socket(PF_UNIX, SOCK_STREAM, 0);
  596. if (sock < 0) {
  597. perror("socket(unix)");
  598. return -1;
  599. }
  600. memset(&un, 0, sizeof(un));
  601. un.sun_family = AF_UNIX;
  602. if (path && strlen(path)) {
  603. snprintf(un.sun_path, sizeof(un.sun_path), "%s", path);
  604. } else {
  605. char *tmpdir = getenv("TMPDIR");
  606. snprintf(un.sun_path, sizeof(un.sun_path), "%s/qemu-socket-XXXXXX",
  607. tmpdir ? tmpdir : "/tmp");
  608. /*
  609. * This dummy fd usage silences the mktemp() unsecure warning.
  610. * Using mkstemp() doesn't make things more secure here
  611. * though. bind() complains about existing files, so we have
  612. * to unlink first and thus re-open the race window. The
  613. * worst case possible is bind() failing, i.e. a DoS attack.
  614. */
  615. fd = mkstemp(un.sun_path); close(fd);
  616. qemu_opt_set(opts, "path", un.sun_path);
  617. }
  618. unlink(un.sun_path);
  619. if (bind(sock, (struct sockaddr*) &un, sizeof(un)) < 0) {
  620. fprintf(stderr, "bind(unix:%s): %s\n", un.sun_path, strerror(errno));
  621. goto err;
  622. }
  623. if (listen(sock, 1) < 0) {
  624. fprintf(stderr, "listen(unix:%s): %s\n", un.sun_path, strerror(errno));
  625. goto err;
  626. }
  627. return sock;
  628. err:
  629. closesocket(sock);
  630. return -1;
  631. }
  632. int unix_connect_opts(QemuOpts *opts)
  633. {
  634. struct sockaddr_un un;
  635. const char *path = qemu_opt_get(opts, "path");
  636. int sock;
  637. if (NULL == path) {
  638. fprintf(stderr, "unix connect: no path specified\n");
  639. return -1;
  640. }
  641. sock = qemu_socket(PF_UNIX, SOCK_STREAM, 0);
  642. if (sock < 0) {
  643. perror("socket(unix)");
  644. return -1;
  645. }
  646. memset(&un, 0, sizeof(un));
  647. un.sun_family = AF_UNIX;
  648. snprintf(un.sun_path, sizeof(un.sun_path), "%s", path);
  649. if (connect(sock, (struct sockaddr*) &un, sizeof(un)) < 0) {
  650. fprintf(stderr, "connect(unix:%s): %s\n", path, strerror(errno));
  651. close(sock);
  652. return -1;
  653. }
  654. return sock;
  655. }
  656. /* compatibility wrapper */
  657. int unix_listen(const char *str, char *ostr, int olen)
  658. {
  659. QemuOpts *opts;
  660. char *path, *optstr;
  661. int sock, len;
  662. opts = qemu_opts_create(&dummy_opts, NULL, 0, NULL);
  663. optstr = strchr(str, ',');
  664. if (optstr) {
  665. len = optstr - str;
  666. if (len) {
  667. path = g_malloc(len+1);
  668. snprintf(path, len+1, "%.*s", len, str);
  669. qemu_opt_set(opts, "path", path);
  670. g_free(path);
  671. }
  672. } else {
  673. qemu_opt_set(opts, "path", str);
  674. }
  675. sock = unix_listen_opts(opts);
  676. if (sock != -1 && ostr)
  677. snprintf(ostr, olen, "%s%s", qemu_opt_get(opts, "path"), optstr ? optstr : "");
  678. qemu_opts_del(opts);
  679. return sock;
  680. }
  681. int unix_connect(const char *path)
  682. {
  683. QemuOpts *opts;
  684. int sock;
  685. opts = qemu_opts_create(&dummy_opts, NULL, 0, NULL);
  686. qemu_opt_set(opts, "path", path);
  687. sock = unix_connect_opts(opts);
  688. qemu_opts_del(opts);
  689. return sock;
  690. }
  691. #else
  692. int unix_listen_opts(QemuOpts *opts)
  693. {
  694. fprintf(stderr, "unix sockets are not available on windows\n");
  695. errno = ENOTSUP;
  696. return -1;
  697. }
  698. int unix_connect_opts(QemuOpts *opts)
  699. {
  700. fprintf(stderr, "unix sockets are not available on windows\n");
  701. errno = ENOTSUP;
  702. return -1;
  703. }
  704. int unix_listen(const char *path, char *ostr, int olen)
  705. {
  706. fprintf(stderr, "unix sockets are not available on windows\n");
  707. errno = ENOTSUP;
  708. return -1;
  709. }
  710. int unix_connect(const char *path)
  711. {
  712. fprintf(stderr, "unix sockets are not available on windows\n");
  713. errno = ENOTSUP;
  714. return -1;
  715. }
  716. #endif
  717. #ifdef _WIN32
  718. static void socket_cleanup(void)
  719. {
  720. WSACleanup();
  721. }
  722. #endif
  723. int socket_init(void)
  724. {
  725. #ifdef _WIN32
  726. WSADATA Data;
  727. int ret, err;
  728. ret = WSAStartup(MAKEWORD(2,2), &Data);
  729. if (ret != 0) {
  730. err = WSAGetLastError();
  731. fprintf(stderr, "WSAStartup: %d\n", err);
  732. return -1;
  733. }
  734. atexit(socket_cleanup);
  735. #endif
  736. return 0;
  737. }