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