root / qemu-sockets.c @ 94a943ef
History | View | Annotate | Download (12 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 | 305b0eb2 | aliguori | */
|
15 | d247d25f | aliguori | #include <stdio.h> |
16 | d247d25f | aliguori | #include <stdlib.h> |
17 | d247d25f | aliguori | #include <string.h> |
18 | d247d25f | aliguori | #include <ctype.h> |
19 | d247d25f | aliguori | #include <errno.h> |
20 | d247d25f | aliguori | #include <unistd.h> |
21 | d247d25f | aliguori | |
22 | d247d25f | aliguori | #include "qemu_socket.h" |
23 | 47398b9c | blueswir1 | #include "qemu-common.h" /* for qemu_isdigit */ |
24 | d247d25f | aliguori | |
25 | d247d25f | aliguori | #ifndef AI_ADDRCONFIG
|
26 | d247d25f | aliguori | # define AI_ADDRCONFIG 0 |
27 | d247d25f | aliguori | #endif
|
28 | d247d25f | aliguori | |
29 | d247d25f | aliguori | static int sockets_debug = 0; |
30 | d247d25f | aliguori | static const int on=1, off=0; |
31 | d247d25f | aliguori | |
32 | d247d25f | aliguori | static int inet_getport(struct addrinfo *e) |
33 | d247d25f | aliguori | { |
34 | d247d25f | aliguori | struct sockaddr_in *i4;
|
35 | d247d25f | aliguori | struct sockaddr_in6 *i6;
|
36 | d247d25f | aliguori | |
37 | d247d25f | aliguori | switch (e->ai_family) {
|
38 | d247d25f | aliguori | case PF_INET6:
|
39 | d247d25f | aliguori | i6 = (void*)e->ai_addr;
|
40 | d247d25f | aliguori | return ntohs(i6->sin6_port);
|
41 | d247d25f | aliguori | case PF_INET:
|
42 | d247d25f | aliguori | i4 = (void*)e->ai_addr;
|
43 | d247d25f | aliguori | return ntohs(i4->sin_port);
|
44 | d247d25f | aliguori | default:
|
45 | d247d25f | aliguori | return 0; |
46 | d247d25f | aliguori | } |
47 | d247d25f | aliguori | } |
48 | d247d25f | aliguori | |
49 | d247d25f | aliguori | static void inet_setport(struct addrinfo *e, int port) |
50 | d247d25f | aliguori | { |
51 | d247d25f | aliguori | struct sockaddr_in *i4;
|
52 | d247d25f | aliguori | struct sockaddr_in6 *i6;
|
53 | d247d25f | aliguori | |
54 | d247d25f | aliguori | switch (e->ai_family) {
|
55 | d247d25f | aliguori | case PF_INET6:
|
56 | d247d25f | aliguori | i6 = (void*)e->ai_addr;
|
57 | d247d25f | aliguori | i6->sin6_port = htons(port); |
58 | d247d25f | aliguori | break;
|
59 | d247d25f | aliguori | case PF_INET:
|
60 | d247d25f | aliguori | i4 = (void*)e->ai_addr;
|
61 | d247d25f | aliguori | i4->sin_port = htons(port); |
62 | d247d25f | aliguori | break;
|
63 | d247d25f | aliguori | } |
64 | d247d25f | aliguori | } |
65 | d247d25f | aliguori | |
66 | d247d25f | aliguori | static const char *inet_strfamily(int family) |
67 | d247d25f | aliguori | { |
68 | d247d25f | aliguori | switch (family) {
|
69 | d247d25f | aliguori | case PF_INET6: return "ipv6"; |
70 | d247d25f | aliguori | case PF_INET: return "ipv4"; |
71 | d247d25f | aliguori | case PF_UNIX: return "unix"; |
72 | d247d25f | aliguori | } |
73 | d247d25f | aliguori | return "????"; |
74 | d247d25f | aliguori | } |
75 | d247d25f | aliguori | |
76 | d247d25f | aliguori | static void inet_print_addrinfo(const char *tag, struct addrinfo *res) |
77 | d247d25f | aliguori | { |
78 | d247d25f | aliguori | struct addrinfo *e;
|
79 | d247d25f | aliguori | char uaddr[INET6_ADDRSTRLEN+1]; |
80 | d247d25f | aliguori | char uport[33]; |
81 | d247d25f | aliguori | |
82 | d247d25f | aliguori | for (e = res; e != NULL; e = e->ai_next) { |
83 | d247d25f | aliguori | getnameinfo((struct sockaddr*)e->ai_addr,e->ai_addrlen,
|
84 | d247d25f | aliguori | uaddr,INET6_ADDRSTRLEN,uport,32,
|
85 | d247d25f | aliguori | NI_NUMERICHOST | NI_NUMERICSERV); |
86 | d247d25f | aliguori | fprintf(stderr,"%s: getaddrinfo: family %s, host %s, port %s\n",
|
87 | d247d25f | aliguori | tag, inet_strfamily(e->ai_family), uaddr, uport); |
88 | d247d25f | aliguori | } |
89 | d247d25f | aliguori | } |
90 | d247d25f | aliguori | |
91 | d247d25f | aliguori | int inet_listen(const char *str, char *ostr, int olen, |
92 | d247d25f | aliguori | int socktype, int port_offset) |
93 | d247d25f | aliguori | { |
94 | d247d25f | aliguori | struct addrinfo ai,*res,*e;
|
95 | d247d25f | aliguori | char addr[64]; |
96 | d247d25f | aliguori | char port[33]; |
97 | d247d25f | aliguori | char uaddr[INET6_ADDRSTRLEN+1]; |
98 | d247d25f | aliguori | char uport[33]; |
99 | d247d25f | aliguori | const char *opts, *h; |
100 | d247d25f | aliguori | int slisten,rc,pos,to,try_next;
|
101 | d247d25f | aliguori | |
102 | d247d25f | aliguori | memset(&ai,0, sizeof(ai)); |
103 | d247d25f | aliguori | ai.ai_flags = AI_PASSIVE | AI_ADDRCONFIG; |
104 | d247d25f | aliguori | ai.ai_family = PF_UNSPEC; |
105 | d247d25f | aliguori | ai.ai_socktype = socktype; |
106 | d247d25f | aliguori | |
107 | d247d25f | aliguori | /* parse address */
|
108 | d247d25f | aliguori | if (str[0] == ':') { |
109 | d247d25f | aliguori | /* no host given */
|
110 | bc575e95 | blueswir1 | addr[0] = '\0'; |
111 | d247d25f | aliguori | if (1 != sscanf(str,":%32[^,]%n",port,&pos)) { |
112 | d247d25f | aliguori | fprintf(stderr, "%s: portonly parse error (%s)\n",
|
113 | d247d25f | aliguori | __FUNCTION__, str); |
114 | d247d25f | aliguori | return -1; |
115 | d247d25f | aliguori | } |
116 | d247d25f | aliguori | } else if (str[0] == '[') { |
117 | d247d25f | aliguori | /* IPv6 addr */
|
118 | d247d25f | aliguori | if (2 != sscanf(str,"[%64[^]]]:%32[^,]%n",addr,port,&pos)) { |
119 | d247d25f | aliguori | fprintf(stderr, "%s: ipv6 parse error (%s)\n",
|
120 | d247d25f | aliguori | __FUNCTION__, str); |
121 | d247d25f | aliguori | return -1; |
122 | d247d25f | aliguori | } |
123 | d247d25f | aliguori | ai.ai_family = PF_INET6; |
124 | 47398b9c | blueswir1 | } else if (qemu_isdigit(str[0])) { |
125 | d247d25f | aliguori | /* IPv4 addr */
|
126 | d247d25f | aliguori | if (2 != sscanf(str,"%64[0-9.]:%32[^,]%n",addr,port,&pos)) { |
127 | d247d25f | aliguori | fprintf(stderr, "%s: ipv4 parse error (%s)\n",
|
128 | d247d25f | aliguori | __FUNCTION__, str); |
129 | d247d25f | aliguori | return -1; |
130 | d247d25f | aliguori | } |
131 | d247d25f | aliguori | ai.ai_family = PF_INET; |
132 | d247d25f | aliguori | } else {
|
133 | d247d25f | aliguori | /* hostname */
|
134 | d247d25f | aliguori | if (2 != sscanf(str,"%64[^:]:%32[^,]%n",addr,port,&pos)) { |
135 | d247d25f | aliguori | fprintf(stderr, "%s: hostname parse error (%s)\n",
|
136 | d247d25f | aliguori | __FUNCTION__, str); |
137 | d247d25f | aliguori | return -1; |
138 | d247d25f | aliguori | } |
139 | d247d25f | aliguori | } |
140 | d247d25f | aliguori | |
141 | d247d25f | aliguori | /* parse options */
|
142 | d247d25f | aliguori | opts = str + pos; |
143 | d247d25f | aliguori | h = strstr(opts, ",to=");
|
144 | d247d25f | aliguori | to = h ? atoi(h+4) : 0; |
145 | d247d25f | aliguori | if (strstr(opts, ",ipv4")) |
146 | d247d25f | aliguori | ai.ai_family = PF_INET; |
147 | d247d25f | aliguori | if (strstr(opts, ",ipv6")) |
148 | d247d25f | aliguori | ai.ai_family = PF_INET6; |
149 | d247d25f | aliguori | |
150 | d247d25f | aliguori | /* lookup */
|
151 | d247d25f | aliguori | if (port_offset)
|
152 | d247d25f | aliguori | snprintf(port, sizeof(port), "%d", atoi(port) + port_offset); |
153 | d247d25f | aliguori | rc = getaddrinfo(strlen(addr) ? addr : NULL, port, &ai, &res);
|
154 | d247d25f | aliguori | if (rc != 0) { |
155 | d247d25f | aliguori | fprintf(stderr,"%s: getaddrinfo(%s,%s): %s\n", __FUNCTION__,
|
156 | d247d25f | aliguori | addr, port, gai_strerror(rc)); |
157 | d247d25f | aliguori | return -1; |
158 | d247d25f | aliguori | } |
159 | d247d25f | aliguori | if (sockets_debug)
|
160 | d247d25f | aliguori | inet_print_addrinfo(__FUNCTION__, res); |
161 | d247d25f | aliguori | |
162 | d247d25f | aliguori | /* create socket + bind */
|
163 | d247d25f | aliguori | for (e = res; e != NULL; e = e->ai_next) { |
164 | 39b6efc8 | vibi | getnameinfo((struct sockaddr*)e->ai_addr,e->ai_addrlen,
|
165 | 39b6efc8 | vibi | uaddr,INET6_ADDRSTRLEN,uport,32,
|
166 | 39b6efc8 | vibi | NI_NUMERICHOST | NI_NUMERICSERV); |
167 | d247d25f | aliguori | slisten = socket(e->ai_family, e->ai_socktype, e->ai_protocol); |
168 | 39b6efc8 | vibi | if (slisten < 0) { |
169 | d247d25f | aliguori | fprintf(stderr,"%s: socket(%s): %s\n", __FUNCTION__,
|
170 | d247d25f | aliguori | inet_strfamily(e->ai_family), strerror(errno)); |
171 | 39b6efc8 | vibi | continue;
|
172 | 39b6efc8 | vibi | } |
173 | d247d25f | aliguori | |
174 | d247d25f | aliguori | setsockopt(slisten,SOL_SOCKET,SO_REUSEADDR,(void*)&on,sizeof(on)); |
175 | d247d25f | aliguori | #ifdef IPV6_V6ONLY
|
176 | d247d25f | aliguori | if (e->ai_family == PF_INET6) {
|
177 | d247d25f | aliguori | /* listen on both ipv4 and ipv6 */
|
178 | 39b6efc8 | vibi | setsockopt(slisten,IPPROTO_IPV6,IPV6_V6ONLY,(void*)&off,
|
179 | 39b6efc8 | vibi | sizeof(off));
|
180 | d247d25f | aliguori | } |
181 | d247d25f | aliguori | #endif
|
182 | d247d25f | aliguori | |
183 | d247d25f | aliguori | for (;;) {
|
184 | d247d25f | aliguori | if (bind(slisten, e->ai_addr, e->ai_addrlen) == 0) { |
185 | d247d25f | aliguori | if (sockets_debug)
|
186 | d247d25f | aliguori | fprintf(stderr,"%s: bind(%s,%s,%d): OK\n", __FUNCTION__,
|
187 | 39b6efc8 | vibi | inet_strfamily(e->ai_family), uaddr, inet_getport(e)); |
188 | d247d25f | aliguori | goto listen;
|
189 | d247d25f | aliguori | } |
190 | d247d25f | aliguori | try_next = to && (inet_getport(e) <= to + port_offset); |
191 | d247d25f | aliguori | if (!try_next || sockets_debug)
|
192 | d247d25f | aliguori | fprintf(stderr,"%s: bind(%s,%s,%d): %s\n", __FUNCTION__,
|
193 | d247d25f | aliguori | inet_strfamily(e->ai_family), uaddr, inet_getport(e), |
194 | d247d25f | aliguori | strerror(errno)); |
195 | d247d25f | aliguori | if (try_next) {
|
196 | d247d25f | aliguori | inet_setport(e, inet_getport(e) + 1);
|
197 | d247d25f | aliguori | continue;
|
198 | d247d25f | aliguori | } |
199 | d247d25f | aliguori | break;
|
200 | d247d25f | aliguori | } |
201 | d247d25f | aliguori | closesocket(slisten); |
202 | d247d25f | aliguori | } |
203 | d247d25f | aliguori | fprintf(stderr, "%s: FAILED\n", __FUNCTION__);
|
204 | d247d25f | aliguori | freeaddrinfo(res); |
205 | d247d25f | aliguori | return -1; |
206 | d247d25f | aliguori | |
207 | d247d25f | aliguori | listen:
|
208 | d247d25f | aliguori | if (listen(slisten,1) != 0) { |
209 | d247d25f | aliguori | perror("listen");
|
210 | d247d25f | aliguori | closesocket(slisten); |
211 | 39b6efc8 | vibi | freeaddrinfo(res); |
212 | d247d25f | aliguori | return -1; |
213 | d247d25f | aliguori | } |
214 | d247d25f | aliguori | if (ostr) {
|
215 | d247d25f | aliguori | if (e->ai_family == PF_INET6) {
|
216 | d247d25f | aliguori | snprintf(ostr, olen, "[%s]:%d%s", uaddr,
|
217 | d247d25f | aliguori | inet_getport(e) - port_offset, opts); |
218 | d247d25f | aliguori | } else {
|
219 | d247d25f | aliguori | snprintf(ostr, olen, "%s:%d%s", uaddr,
|
220 | d247d25f | aliguori | inet_getport(e) - port_offset, opts); |
221 | d247d25f | aliguori | } |
222 | d247d25f | aliguori | } |
223 | d247d25f | aliguori | freeaddrinfo(res); |
224 | d247d25f | aliguori | return slisten;
|
225 | d247d25f | aliguori | } |
226 | d247d25f | aliguori | |
227 | d247d25f | aliguori | int inet_connect(const char *str, int socktype) |
228 | d247d25f | aliguori | { |
229 | d247d25f | aliguori | struct addrinfo ai,*res,*e;
|
230 | d247d25f | aliguori | char addr[64]; |
231 | d247d25f | aliguori | char port[33]; |
232 | d247d25f | aliguori | char uaddr[INET6_ADDRSTRLEN+1]; |
233 | d247d25f | aliguori | char uport[33]; |
234 | d247d25f | aliguori | int sock,rc;
|
235 | d247d25f | aliguori | |
236 | d247d25f | aliguori | memset(&ai,0, sizeof(ai)); |
237 | d247d25f | aliguori | ai.ai_flags = AI_CANONNAME | AI_ADDRCONFIG; |
238 | d247d25f | aliguori | ai.ai_family = PF_UNSPEC; |
239 | d247d25f | aliguori | ai.ai_socktype = socktype; |
240 | d247d25f | aliguori | |
241 | d247d25f | aliguori | /* parse address */
|
242 | d247d25f | aliguori | if (str[0] == '[') { |
243 | d247d25f | aliguori | /* IPv6 addr */
|
244 | d247d25f | aliguori | if (2 != sscanf(str,"[%64[^]]]:%32[^,]",addr,port)) { |
245 | d247d25f | aliguori | fprintf(stderr, "%s: ipv6 parse error (%s)\n",
|
246 | d247d25f | aliguori | __FUNCTION__, str); |
247 | d247d25f | aliguori | return -1; |
248 | d247d25f | aliguori | } |
249 | d247d25f | aliguori | ai.ai_family = PF_INET6; |
250 | 47398b9c | blueswir1 | } else if (qemu_isdigit(str[0])) { |
251 | d247d25f | aliguori | /* IPv4 addr */
|
252 | d247d25f | aliguori | if (2 != sscanf(str,"%64[0-9.]:%32[^,]",addr,port)) { |
253 | d247d25f | aliguori | fprintf(stderr, "%s: ipv4 parse error (%s)\n",
|
254 | d247d25f | aliguori | __FUNCTION__, str); |
255 | d247d25f | aliguori | return -1; |
256 | d247d25f | aliguori | } |
257 | d247d25f | aliguori | ai.ai_family = PF_INET; |
258 | d247d25f | aliguori | } else {
|
259 | d247d25f | aliguori | /* hostname */
|
260 | d247d25f | aliguori | if (2 != sscanf(str,"%64[^:]:%32[^,]",addr,port)) { |
261 | d247d25f | aliguori | fprintf(stderr, "%s: hostname parse error (%s)\n",
|
262 | d247d25f | aliguori | __FUNCTION__, str); |
263 | d247d25f | aliguori | return -1; |
264 | d247d25f | aliguori | } |
265 | d247d25f | aliguori | } |
266 | d247d25f | aliguori | |
267 | d247d25f | aliguori | /* parse options */
|
268 | d247d25f | aliguori | if (strstr(str, ",ipv4")) |
269 | d247d25f | aliguori | ai.ai_family = PF_INET; |
270 | d247d25f | aliguori | if (strstr(str, ",ipv6")) |
271 | d247d25f | aliguori | ai.ai_family = PF_INET6; |
272 | d247d25f | aliguori | |
273 | d247d25f | aliguori | /* lookup */
|
274 | d247d25f | aliguori | if (0 != (rc = getaddrinfo(addr, port, &ai, &res))) { |
275 | d247d25f | aliguori | fprintf(stderr,"getaddrinfo(%s,%s): %s\n", gai_strerror(rc),
|
276 | d247d25f | aliguori | addr, port); |
277 | d247d25f | aliguori | return -1; |
278 | d247d25f | aliguori | } |
279 | d247d25f | aliguori | if (sockets_debug)
|
280 | d247d25f | aliguori | inet_print_addrinfo(__FUNCTION__, res); |
281 | d247d25f | aliguori | |
282 | d247d25f | aliguori | for (e = res; e != NULL; e = e->ai_next) { |
283 | 39b6efc8 | vibi | if (getnameinfo((struct sockaddr*)e->ai_addr,e->ai_addrlen, |
284 | 39b6efc8 | vibi | uaddr,INET6_ADDRSTRLEN,uport,32,
|
285 | 39b6efc8 | vibi | NI_NUMERICHOST | NI_NUMERICSERV) != 0) {
|
286 | d247d25f | aliguori | fprintf(stderr,"%s: getnameinfo: oops\n", __FUNCTION__);
|
287 | 39b6efc8 | vibi | continue;
|
288 | 39b6efc8 | vibi | } |
289 | d247d25f | aliguori | sock = socket(e->ai_family, e->ai_socktype, e->ai_protocol); |
290 | 39b6efc8 | vibi | if (sock < 0) { |
291 | d247d25f | aliguori | fprintf(stderr,"%s: socket(%s): %s\n", __FUNCTION__,
|
292 | 39b6efc8 | vibi | inet_strfamily(e->ai_family), strerror(errno)); |
293 | 39b6efc8 | vibi | continue;
|
294 | 39b6efc8 | vibi | } |
295 | d247d25f | aliguori | setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,(void*)&on,sizeof(on)); |
296 | d247d25f | aliguori | |
297 | 39b6efc8 | vibi | /* connect to peer */
|
298 | 39b6efc8 | vibi | if (connect(sock,e->ai_addr,e->ai_addrlen) < 0) { |
299 | d247d25f | aliguori | if (sockets_debug || NULL == e->ai_next) |
300 | d247d25f | aliguori | fprintf(stderr, "%s: connect(%s,%s,%s,%s): %s\n", __FUNCTION__,
|
301 | d247d25f | aliguori | inet_strfamily(e->ai_family), |
302 | d247d25f | aliguori | e->ai_canonname, uaddr, uport, strerror(errno)); |
303 | d247d25f | aliguori | closesocket(sock); |
304 | 39b6efc8 | vibi | continue;
|
305 | 39b6efc8 | vibi | } |
306 | d247d25f | aliguori | if (sockets_debug)
|
307 | d247d25f | aliguori | fprintf(stderr, "%s: connect(%s,%s,%s,%s): OK\n", __FUNCTION__,
|
308 | d247d25f | aliguori | inet_strfamily(e->ai_family), |
309 | d247d25f | aliguori | e->ai_canonname, uaddr, uport); |
310 | d247d25f | aliguori | freeaddrinfo(res); |
311 | 39b6efc8 | vibi | return sock;
|
312 | d247d25f | aliguori | } |
313 | d247d25f | aliguori | freeaddrinfo(res); |
314 | d247d25f | aliguori | return -1; |
315 | d247d25f | aliguori | } |
316 | d247d25f | aliguori | |
317 | d247d25f | aliguori | #ifndef _WIN32
|
318 | d247d25f | aliguori | |
319 | d247d25f | aliguori | int unix_listen(const char *str, char *ostr, int olen) |
320 | d247d25f | aliguori | { |
321 | d247d25f | aliguori | struct sockaddr_un un;
|
322 | d247d25f | aliguori | char *path, *opts;
|
323 | d247d25f | aliguori | int sock, fd, len;
|
324 | d247d25f | aliguori | |
325 | d247d25f | aliguori | sock = socket(PF_UNIX, SOCK_STREAM, 0);
|
326 | d247d25f | aliguori | if (sock < 0) { |
327 | 39b6efc8 | vibi | perror("socket(unix)");
|
328 | 39b6efc8 | vibi | return -1; |
329 | d247d25f | aliguori | } |
330 | d247d25f | aliguori | |
331 | d247d25f | aliguori | opts = strchr(str, ',');
|
332 | d247d25f | aliguori | if (opts) {
|
333 | d247d25f | aliguori | len = opts - str; |
334 | 39b6efc8 | vibi | path = qemu_malloc(len+1);
|
335 | d247d25f | aliguori | snprintf(path, len+1, "%.*s", len, str); |
336 | d247d25f | aliguori | } else
|
337 | 39b6efc8 | vibi | path = qemu_strdup(str); |
338 | d247d25f | aliguori | |
339 | d247d25f | aliguori | memset(&un, 0, sizeof(un)); |
340 | d247d25f | aliguori | un.sun_family = AF_UNIX; |
341 | d247d25f | aliguori | if (path && strlen(path)) {
|
342 | d247d25f | aliguori | snprintf(un.sun_path, sizeof(un.sun_path), "%s", path); |
343 | d247d25f | aliguori | } else {
|
344 | d247d25f | aliguori | char *tmpdir = getenv("TMPDIR"); |
345 | d247d25f | aliguori | snprintf(un.sun_path, sizeof(un.sun_path), "%s/qemu-socket-XXXXXX", |
346 | d247d25f | aliguori | tmpdir ? tmpdir : "/tmp");
|
347 | d247d25f | aliguori | /*
|
348 | d247d25f | aliguori | * This dummy fd usage silences the mktemp() unsecure warning.
|
349 | d247d25f | aliguori | * Using mkstemp() doesn't make things more secure here
|
350 | d247d25f | aliguori | * though. bind() complains about existing files, so we have
|
351 | d247d25f | aliguori | * to unlink first and thus re-open the race window. The
|
352 | d247d25f | aliguori | * worst case possible is bind() failing, i.e. a DoS attack.
|
353 | d247d25f | aliguori | */
|
354 | d247d25f | aliguori | fd = mkstemp(un.sun_path); close(fd); |
355 | d247d25f | aliguori | } |
356 | d247d25f | aliguori | snprintf(ostr, olen, "%s%s", un.sun_path, opts ? opts : ""); |
357 | d247d25f | aliguori | |
358 | d247d25f | aliguori | unlink(un.sun_path); |
359 | d247d25f | aliguori | if (bind(sock, (struct sockaddr*) &un, sizeof(un)) < 0) { |
360 | d247d25f | aliguori | fprintf(stderr, "bind(unix:%s): %s\n", un.sun_path, strerror(errno));
|
361 | d247d25f | aliguori | goto err;
|
362 | d247d25f | aliguori | } |
363 | d247d25f | aliguori | if (listen(sock, 1) < 0) { |
364 | d247d25f | aliguori | fprintf(stderr, "listen(unix:%s): %s\n", un.sun_path, strerror(errno));
|
365 | d247d25f | aliguori | goto err;
|
366 | d247d25f | aliguori | } |
367 | d247d25f | aliguori | |
368 | d247d25f | aliguori | if (sockets_debug)
|
369 | d247d25f | aliguori | fprintf(stderr, "bind(unix:%s): OK\n", un.sun_path);
|
370 | 39b6efc8 | vibi | qemu_free(path); |
371 | d247d25f | aliguori | return sock;
|
372 | d247d25f | aliguori | |
373 | d247d25f | aliguori | err:
|
374 | 39b6efc8 | vibi | qemu_free(path); |
375 | d247d25f | aliguori | closesocket(sock); |
376 | d247d25f | aliguori | return -1; |
377 | d247d25f | aliguori | } |
378 | d247d25f | aliguori | |
379 | d247d25f | aliguori | int unix_connect(const char *path) |
380 | d247d25f | aliguori | { |
381 | d247d25f | aliguori | struct sockaddr_un un;
|
382 | d247d25f | aliguori | int sock;
|
383 | d247d25f | aliguori | |
384 | d247d25f | aliguori | sock = socket(PF_UNIX, SOCK_STREAM, 0);
|
385 | d247d25f | aliguori | if (sock < 0) { |
386 | 39b6efc8 | vibi | perror("socket(unix)");
|
387 | 39b6efc8 | vibi | return -1; |
388 | d247d25f | aliguori | } |
389 | d247d25f | aliguori | |
390 | d247d25f | aliguori | memset(&un, 0, sizeof(un)); |
391 | d247d25f | aliguori | un.sun_family = AF_UNIX; |
392 | d247d25f | aliguori | snprintf(un.sun_path, sizeof(un.sun_path), "%s", path); |
393 | d247d25f | aliguori | if (connect(sock, (struct sockaddr*) &un, sizeof(un)) < 0) { |
394 | d247d25f | aliguori | fprintf(stderr, "connect(unix:%s): %s\n", path, strerror(errno));
|
395 | d247d25f | aliguori | return -1; |
396 | d247d25f | aliguori | } |
397 | d247d25f | aliguori | |
398 | d247d25f | aliguori | if (sockets_debug)
|
399 | d247d25f | aliguori | fprintf(stderr, "connect(unix:%s): OK\n", path);
|
400 | d247d25f | aliguori | return sock;
|
401 | d247d25f | aliguori | } |
402 | d247d25f | aliguori | |
403 | d247d25f | aliguori | #else
|
404 | d247d25f | aliguori | |
405 | d247d25f | aliguori | int unix_listen(const char *path, char *ostr, int olen) |
406 | d247d25f | aliguori | { |
407 | d247d25f | aliguori | fprintf(stderr, "unix sockets are not available on windows\n");
|
408 | d247d25f | aliguori | return -1; |
409 | d247d25f | aliguori | } |
410 | d247d25f | aliguori | |
411 | d247d25f | aliguori | int unix_connect(const char *path) |
412 | d247d25f | aliguori | { |
413 | d247d25f | aliguori | fprintf(stderr, "unix sockets are not available on windows\n");
|
414 | d247d25f | aliguori | return -1; |
415 | d247d25f | aliguori | } |
416 | d247d25f | aliguori | |
417 | d247d25f | aliguori | #endif |