xref: /openbmc/qemu/net/socket.c (revision 1529ae1b)
1 /*
2  * QEMU System Emulator
3  *
4  * Copyright (c) 2003-2008 Fabrice Bellard
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22  * THE SOFTWARE.
23  */
24 #include "net/socket.h"
25 
26 #include "config-host.h"
27 
28 #include "net.h"
29 #include "qemu-char.h"
30 #include "qemu-common.h"
31 #include "qemu-error.h"
32 #include "qemu-option.h"
33 #include "qemu_socket.h"
34 
35 typedef struct NetSocketState {
36     VLANClientState nc;
37     int fd;
38     int state; /* 0 = getting length, 1 = getting data */
39     unsigned int index;
40     unsigned int packet_len;
41     uint8_t buf[4096];
42     struct sockaddr_in dgram_dst; /* contains inet host and port destination iff connectionless (SOCK_DGRAM) */
43 } NetSocketState;
44 
45 typedef struct NetSocketListenState {
46     VLANState *vlan;
47     char *model;
48     char *name;
49     int fd;
50 } NetSocketListenState;
51 
52 /* XXX: we consider we can send the whole packet without blocking */
53 static ssize_t net_socket_receive(VLANClientState *nc, const uint8_t *buf, size_t size)
54 {
55     NetSocketState *s = DO_UPCAST(NetSocketState, nc, nc);
56     uint32_t len;
57     len = htonl(size);
58 
59     send_all(s->fd, (const uint8_t *)&len, sizeof(len));
60     return send_all(s->fd, buf, size);
61 }
62 
63 static ssize_t net_socket_receive_dgram(VLANClientState *nc, const uint8_t *buf, size_t size)
64 {
65     NetSocketState *s = DO_UPCAST(NetSocketState, nc, nc);
66 
67     return sendto(s->fd, (const void *)buf, size, 0,
68                   (struct sockaddr *)&s->dgram_dst, sizeof(s->dgram_dst));
69 }
70 
71 static void net_socket_send(void *opaque)
72 {
73     NetSocketState *s = opaque;
74     int size, err;
75     unsigned l;
76     uint8_t buf1[4096];
77     const uint8_t *buf;
78 
79     size = qemu_recv(s->fd, buf1, sizeof(buf1), 0);
80     if (size < 0) {
81         err = socket_error();
82         if (err != EWOULDBLOCK)
83             goto eoc;
84     } else if (size == 0) {
85         /* end of connection */
86     eoc:
87         qemu_set_fd_handler(s->fd, NULL, NULL, NULL);
88         closesocket(s->fd);
89         return;
90     }
91     buf = buf1;
92     while (size > 0) {
93         /* reassemble a packet from the network */
94         switch(s->state) {
95         case 0:
96             l = 4 - s->index;
97             if (l > size)
98                 l = size;
99             memcpy(s->buf + s->index, buf, l);
100             buf += l;
101             size -= l;
102             s->index += l;
103             if (s->index == 4) {
104                 /* got length */
105                 s->packet_len = ntohl(*(uint32_t *)s->buf);
106                 s->index = 0;
107                 s->state = 1;
108             }
109             break;
110         case 1:
111             l = s->packet_len - s->index;
112             if (l > size)
113                 l = size;
114             if (s->index + l <= sizeof(s->buf)) {
115                 memcpy(s->buf + s->index, buf, l);
116             } else {
117                 fprintf(stderr, "serious error: oversized packet received,"
118                     "connection terminated.\n");
119                 s->state = 0;
120                 goto eoc;
121             }
122 
123             s->index += l;
124             buf += l;
125             size -= l;
126             if (s->index >= s->packet_len) {
127                 qemu_send_packet(&s->nc, s->buf, s->packet_len);
128                 s->index = 0;
129                 s->state = 0;
130             }
131             break;
132         }
133     }
134 }
135 
136 static void net_socket_send_dgram(void *opaque)
137 {
138     NetSocketState *s = opaque;
139     int size;
140 
141     size = qemu_recv(s->fd, s->buf, sizeof(s->buf), 0);
142     if (size < 0)
143         return;
144     if (size == 0) {
145         /* end of connection */
146         qemu_set_fd_handler(s->fd, NULL, NULL, NULL);
147         return;
148     }
149     qemu_send_packet(&s->nc, s->buf, size);
150 }
151 
152 static int net_socket_mcast_create(struct sockaddr_in *mcastaddr, struct in_addr *localaddr)
153 {
154     struct ip_mreq imr;
155     int fd;
156     int val, ret;
157 #ifdef __OpenBSD__
158     unsigned char loop;
159 #else
160     int loop;
161 #endif
162 
163     if (!IN_MULTICAST(ntohl(mcastaddr->sin_addr.s_addr))) {
164         fprintf(stderr, "qemu: error: specified mcastaddr \"%s\" (0x%08x) "
165                 "does not contain a multicast address\n",
166                 inet_ntoa(mcastaddr->sin_addr),
167                 (int)ntohl(mcastaddr->sin_addr.s_addr));
168         return -1;
169 
170     }
171     fd = qemu_socket(PF_INET, SOCK_DGRAM, 0);
172     if (fd < 0) {
173         perror("socket(PF_INET, SOCK_DGRAM)");
174         return -1;
175     }
176 
177     val = 1;
178     ret=setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
179                    (const char *)&val, sizeof(val));
180     if (ret < 0) {
181         perror("setsockopt(SOL_SOCKET, SO_REUSEADDR)");
182         goto fail;
183     }
184 
185     ret = bind(fd, (struct sockaddr *)mcastaddr, sizeof(*mcastaddr));
186     if (ret < 0) {
187         perror("bind");
188         goto fail;
189     }
190 
191     /* Add host to multicast group */
192     imr.imr_multiaddr = mcastaddr->sin_addr;
193     if (localaddr) {
194         imr.imr_interface = *localaddr;
195     } else {
196         imr.imr_interface.s_addr = htonl(INADDR_ANY);
197     }
198 
199     ret = setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
200                      (const char *)&imr, sizeof(struct ip_mreq));
201     if (ret < 0) {
202         perror("setsockopt(IP_ADD_MEMBERSHIP)");
203         goto fail;
204     }
205 
206     /* Force mcast msgs to loopback (eg. several QEMUs in same host */
207     loop = 1;
208     ret=setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP,
209                    (const char *)&loop, sizeof(loop));
210     if (ret < 0) {
211         perror("setsockopt(SOL_IP, IP_MULTICAST_LOOP)");
212         goto fail;
213     }
214 
215     /* If a bind address is given, only send packets from that address */
216     if (localaddr != NULL) {
217         ret = setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF,
218                          (const char *)localaddr, sizeof(*localaddr));
219         if (ret < 0) {
220             perror("setsockopt(IP_MULTICAST_IF)");
221             goto fail;
222         }
223     }
224 
225     socket_set_nonblock(fd);
226     return fd;
227 fail:
228     if (fd >= 0)
229         closesocket(fd);
230     return -1;
231 }
232 
233 static void net_socket_cleanup(VLANClientState *nc)
234 {
235     NetSocketState *s = DO_UPCAST(NetSocketState, nc, nc);
236     qemu_set_fd_handler(s->fd, NULL, NULL, NULL);
237     close(s->fd);
238 }
239 
240 static NetClientInfo net_dgram_socket_info = {
241     .type = NET_CLIENT_TYPE_SOCKET,
242     .size = sizeof(NetSocketState),
243     .receive = net_socket_receive_dgram,
244     .cleanup = net_socket_cleanup,
245 };
246 
247 static NetSocketState *net_socket_fd_init_dgram(VLANState *vlan,
248                                                 const char *model,
249                                                 const char *name,
250                                                 int fd, int is_connected)
251 {
252     struct sockaddr_in saddr;
253     int newfd;
254     socklen_t saddr_len;
255     VLANClientState *nc;
256     NetSocketState *s;
257 
258     /* fd passed: multicast: "learn" dgram_dst address from bound address and save it
259      * Because this may be "shared" socket from a "master" process, datagrams would be recv()
260      * by ONLY ONE process: we must "clone" this dgram socket --jjo
261      */
262 
263     if (is_connected) {
264         if (getsockname(fd, (struct sockaddr *) &saddr, &saddr_len) == 0) {
265             /* must be bound */
266             if (saddr.sin_addr.s_addr == 0) {
267                 fprintf(stderr, "qemu: error: init_dgram: fd=%d unbound, "
268                         "cannot setup multicast dst addr\n", fd);
269                 goto err;
270             }
271             /* clone dgram socket */
272             newfd = net_socket_mcast_create(&saddr, NULL);
273             if (newfd < 0) {
274                 /* error already reported by net_socket_mcast_create() */
275                 goto err;
276             }
277             /* clone newfd to fd, close newfd */
278             dup2(newfd, fd);
279             close(newfd);
280 
281         } else {
282             fprintf(stderr,
283                     "qemu: error: init_dgram: fd=%d failed getsockname(): %s\n",
284                     fd, strerror(errno));
285             goto err;
286         }
287     }
288 
289     nc = qemu_new_net_client(&net_dgram_socket_info, vlan, NULL, model, name);
290 
291     snprintf(nc->info_str, sizeof(nc->info_str),
292             "socket: fd=%d (%s mcast=%s:%d)",
293             fd, is_connected ? "cloned" : "",
294             inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port));
295 
296     s = DO_UPCAST(NetSocketState, nc, nc);
297 
298     s->fd = fd;
299 
300     qemu_set_fd_handler(s->fd, net_socket_send_dgram, NULL, s);
301 
302     /* mcast: save bound address as dst */
303     if (is_connected) s->dgram_dst=saddr;
304 
305     return s;
306 
307 err:
308     closesocket(fd);
309     return NULL;
310 }
311 
312 static void net_socket_connect(void *opaque)
313 {
314     NetSocketState *s = opaque;
315     qemu_set_fd_handler(s->fd, net_socket_send, NULL, s);
316 }
317 
318 static NetClientInfo net_socket_info = {
319     .type = NET_CLIENT_TYPE_SOCKET,
320     .size = sizeof(NetSocketState),
321     .receive = net_socket_receive,
322     .cleanup = net_socket_cleanup,
323 };
324 
325 static NetSocketState *net_socket_fd_init_stream(VLANState *vlan,
326                                                  const char *model,
327                                                  const char *name,
328                                                  int fd, int is_connected)
329 {
330     VLANClientState *nc;
331     NetSocketState *s;
332 
333     nc = qemu_new_net_client(&net_socket_info, vlan, NULL, model, name);
334 
335     snprintf(nc->info_str, sizeof(nc->info_str), "socket: fd=%d", fd);
336 
337     s = DO_UPCAST(NetSocketState, nc, nc);
338 
339     s->fd = fd;
340 
341     if (is_connected) {
342         net_socket_connect(s);
343     } else {
344         qemu_set_fd_handler(s->fd, NULL, net_socket_connect, s);
345     }
346     return s;
347 }
348 
349 static NetSocketState *net_socket_fd_init(VLANState *vlan,
350                                           const char *model, const char *name,
351                                           int fd, int is_connected)
352 {
353     int so_type = -1, optlen=sizeof(so_type);
354 
355     if(getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&so_type,
356         (socklen_t *)&optlen)< 0) {
357         fprintf(stderr, "qemu: error: getsockopt(SO_TYPE) for fd=%d failed\n",
358                 fd);
359         closesocket(fd);
360         return NULL;
361     }
362     switch(so_type) {
363     case SOCK_DGRAM:
364         return net_socket_fd_init_dgram(vlan, model, name, fd, is_connected);
365     case SOCK_STREAM:
366         return net_socket_fd_init_stream(vlan, model, name, fd, is_connected);
367     default:
368         /* who knows ... this could be a eg. a pty, do warn and continue as stream */
369         fprintf(stderr, "qemu: warning: socket type=%d for fd=%d is not SOCK_DGRAM or SOCK_STREAM\n", so_type, fd);
370         return net_socket_fd_init_stream(vlan, model, name, fd, is_connected);
371     }
372     return NULL;
373 }
374 
375 static void net_socket_accept(void *opaque)
376 {
377     NetSocketListenState *s = opaque;
378     NetSocketState *s1;
379     struct sockaddr_in saddr;
380     socklen_t len;
381     int fd;
382 
383     for(;;) {
384         len = sizeof(saddr);
385         fd = qemu_accept(s->fd, (struct sockaddr *)&saddr, &len);
386         if (fd < 0 && errno != EINTR) {
387             return;
388         } else if (fd >= 0) {
389             break;
390         }
391     }
392     s1 = net_socket_fd_init(s->vlan, s->model, s->name, fd, 1);
393     if (s1) {
394         snprintf(s1->nc.info_str, sizeof(s1->nc.info_str),
395                  "socket: connection from %s:%d",
396                  inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port));
397     }
398 }
399 
400 static int net_socket_listen_init(VLANState *vlan,
401                                   const char *model,
402                                   const char *name,
403                                   const char *host_str)
404 {
405     NetSocketListenState *s;
406     int fd, val, ret;
407     struct sockaddr_in saddr;
408 
409     if (parse_host_port(&saddr, host_str) < 0)
410         return -1;
411 
412     s = g_malloc0(sizeof(NetSocketListenState));
413 
414     fd = qemu_socket(PF_INET, SOCK_STREAM, 0);
415     if (fd < 0) {
416         perror("socket");
417         g_free(s);
418         return -1;
419     }
420     socket_set_nonblock(fd);
421 
422     /* allow fast reuse */
423     val = 1;
424     setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const char *)&val, sizeof(val));
425 
426     ret = bind(fd, (struct sockaddr *)&saddr, sizeof(saddr));
427     if (ret < 0) {
428         perror("bind");
429         g_free(s);
430         closesocket(fd);
431         return -1;
432     }
433     ret = listen(fd, 0);
434     if (ret < 0) {
435         perror("listen");
436         g_free(s);
437         closesocket(fd);
438         return -1;
439     }
440     s->vlan = vlan;
441     s->model = g_strdup(model);
442     s->name = name ? g_strdup(name) : NULL;
443     s->fd = fd;
444     qemu_set_fd_handler(fd, net_socket_accept, NULL, s);
445     return 0;
446 }
447 
448 static int net_socket_connect_init(VLANState *vlan,
449                                    const char *model,
450                                    const char *name,
451                                    const char *host_str)
452 {
453     NetSocketState *s;
454     int fd, connected, ret, err;
455     struct sockaddr_in saddr;
456 
457     if (parse_host_port(&saddr, host_str) < 0)
458         return -1;
459 
460     fd = qemu_socket(PF_INET, SOCK_STREAM, 0);
461     if (fd < 0) {
462         perror("socket");
463         return -1;
464     }
465     socket_set_nonblock(fd);
466 
467     connected = 0;
468     for(;;) {
469         ret = connect(fd, (struct sockaddr *)&saddr, sizeof(saddr));
470         if (ret < 0) {
471             err = socket_error();
472             if (err == EINTR || err == EWOULDBLOCK) {
473             } else if (err == EINPROGRESS) {
474                 break;
475 #ifdef _WIN32
476             } else if (err == WSAEALREADY || err == WSAEINVAL) {
477                 break;
478 #endif
479             } else {
480                 perror("connect");
481                 closesocket(fd);
482                 return -1;
483             }
484         } else {
485             connected = 1;
486             break;
487         }
488     }
489     s = net_socket_fd_init(vlan, model, name, fd, connected);
490     if (!s)
491         return -1;
492     snprintf(s->nc.info_str, sizeof(s->nc.info_str),
493              "socket: connect to %s:%d",
494              inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port));
495     return 0;
496 }
497 
498 static int net_socket_mcast_init(VLANState *vlan,
499                                  const char *model,
500                                  const char *name,
501                                  const char *host_str,
502                                  const char *localaddr_str)
503 {
504     NetSocketState *s;
505     int fd;
506     struct sockaddr_in saddr;
507     struct in_addr localaddr, *param_localaddr;
508 
509     if (parse_host_port(&saddr, host_str) < 0)
510         return -1;
511 
512     if (localaddr_str != NULL) {
513         if (inet_aton(localaddr_str, &localaddr) == 0)
514             return -1;
515         param_localaddr = &localaddr;
516     } else {
517         param_localaddr = NULL;
518     }
519 
520     fd = net_socket_mcast_create(&saddr, param_localaddr);
521     if (fd < 0)
522         return -1;
523 
524     s = net_socket_fd_init(vlan, model, name, fd, 0);
525     if (!s)
526         return -1;
527 
528     s->dgram_dst = saddr;
529 
530     snprintf(s->nc.info_str, sizeof(s->nc.info_str),
531              "socket: mcast=%s:%d",
532              inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port));
533     return 0;
534 
535 }
536 
537 static int net_socket_udp_init(VLANState *vlan,
538                                  const char *model,
539                                  const char *name,
540                                  const char *rhost,
541                                  const char *lhost)
542 {
543     NetSocketState *s;
544     int fd, val, ret;
545     struct sockaddr_in laddr, raddr;
546 
547     if (parse_host_port(&laddr, lhost) < 0) {
548         return -1;
549     }
550 
551     if (parse_host_port(&raddr, rhost) < 0) {
552         return -1;
553     }
554 
555     fd = qemu_socket(PF_INET, SOCK_DGRAM, 0);
556     if (fd < 0) {
557         perror("socket(PF_INET, SOCK_DGRAM)");
558         return -1;
559     }
560     val = 1;
561     ret = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
562                    (const char *)&val, sizeof(val));
563     if (ret < 0) {
564         perror("setsockopt(SOL_SOCKET, SO_REUSEADDR)");
565         closesocket(fd);
566         return -1;
567     }
568     ret = bind(fd, (struct sockaddr *)&laddr, sizeof(laddr));
569     if (ret < 0) {
570         perror("bind");
571         closesocket(fd);
572         return -1;
573     }
574 
575     s = net_socket_fd_init(vlan, model, name, fd, 0);
576     if (!s) {
577         return -1;
578     }
579 
580     s->dgram_dst = raddr;
581 
582     snprintf(s->nc.info_str, sizeof(s->nc.info_str),
583              "socket: udp=%s:%d",
584              inet_ntoa(raddr.sin_addr), ntohs(raddr.sin_port));
585     return 0;
586 }
587 
588 int net_init_socket(QemuOpts *opts,
589                     Monitor *mon,
590                     const char *name,
591                     VLANState *vlan)
592 {
593     if (qemu_opt_get(opts, "fd")) {
594         int fd;
595 
596         if (qemu_opt_get(opts, "listen") ||
597             qemu_opt_get(opts, "connect") ||
598             qemu_opt_get(opts, "mcast") ||
599             qemu_opt_get(opts, "localaddr")) {
600             error_report("listen=, connect=, mcast= and localaddr= is invalid with fd=");
601             return -1;
602         }
603 
604         fd = net_handle_fd_param(mon, qemu_opt_get(opts, "fd"));
605         if (fd == -1) {
606             return -1;
607         }
608 
609         if (!net_socket_fd_init(vlan, "socket", name, fd, 1)) {
610             return -1;
611         }
612     } else if (qemu_opt_get(opts, "listen")) {
613         const char *listen;
614 
615         if (qemu_opt_get(opts, "fd") ||
616             qemu_opt_get(opts, "connect") ||
617             qemu_opt_get(opts, "mcast") ||
618             qemu_opt_get(opts, "localaddr")) {
619             error_report("fd=, connect=, mcast= and localaddr= is invalid with listen=");
620             return -1;
621         }
622 
623         listen = qemu_opt_get(opts, "listen");
624 
625         if (net_socket_listen_init(vlan, "socket", name, listen) == -1) {
626             return -1;
627         }
628     } else if (qemu_opt_get(opts, "connect")) {
629         const char *connect;
630 
631         if (qemu_opt_get(opts, "fd") ||
632             qemu_opt_get(opts, "listen") ||
633             qemu_opt_get(opts, "mcast") ||
634             qemu_opt_get(opts, "localaddr")) {
635             error_report("fd=, listen=, mcast= and localaddr= is invalid with connect=");
636             return -1;
637         }
638 
639         connect = qemu_opt_get(opts, "connect");
640 
641         if (net_socket_connect_init(vlan, "socket", name, connect) == -1) {
642             return -1;
643         }
644     } else if (qemu_opt_get(opts, "mcast")) {
645         const char *mcast, *localaddr;
646 
647         if (qemu_opt_get(opts, "fd") ||
648             qemu_opt_get(opts, "connect") ||
649             qemu_opt_get(opts, "listen")) {
650             error_report("fd=, connect= and listen= is invalid with mcast=");
651             return -1;
652         }
653 
654         mcast = qemu_opt_get(opts, "mcast");
655         localaddr = qemu_opt_get(opts, "localaddr");
656 
657         if (net_socket_mcast_init(vlan, "socket", name, mcast, localaddr) == -1) {
658             return -1;
659         }
660     } else if (qemu_opt_get(opts, "udp")) {
661         const char *udp, *localaddr;
662 
663         if (qemu_opt_get(opts, "fd") ||
664             qemu_opt_get(opts, "connect") ||
665             qemu_opt_get(opts, "listen") ||
666             qemu_opt_get(opts, "mcast")) {
667             error_report("fd=, connect=, listen=\
668                          and mcast= is invalid with udp=");
669             return -1;
670         }
671 
672         udp = qemu_opt_get(opts, "udp");
673         localaddr = qemu_opt_get(opts, "localaddr");
674         if (localaddr == NULL) {
675                 error_report("localaddr= is mandatory with udp=");
676                 return -1;
677         }
678 
679         if (net_socket_udp_init(vlan, "udp", name, udp, localaddr) == -1) {
680             return -1;
681         }
682     } else {
683         error_report("-socket requires fd=, listen=, \
684                      connect=, mcast= or udp=");
685         return -1;
686     }
687     return 0;
688 }
689