blob: 00f9796d5d86d6894d0abad6466c3ad96378bd1e [file] [log] [blame]
Mark McLoughlin42281ac2009-11-25 18:48:56 +00001/*
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 */
Peter Maydell2744d922016-01-29 17:50:00 +000024#include "qemu/osdep.h"
Mark McLoughlin42281ac2009-11-25 18:48:56 +000025
Paolo Bonzini1422e322012-10-24 08:43:34 +020026#include "net/net.h"
Paolo Bonzinia245fc12012-09-17 18:43:51 +020027#include "clients.h"
Paolo Bonzini83c90892012-12-17 18:19:49 +010028#include "monitor/monitor.h"
Markus Armbrusterda34e652016-03-14 09:01:28 +010029#include "qapi/error.h"
Mark McLoughlin42281ac2009-11-25 18:48:56 +000030#include "qemu-common.h"
Paolo Bonzini1de7afc2012-12-17 18:20:00 +010031#include "qemu/error-report.h"
32#include "qemu/option.h"
33#include "qemu/sockets.h"
34#include "qemu/iov.h"
Alex Bligh6a1751b2013-08-21 16:02:47 +010035#include "qemu/main-loop.h"
Mark McLoughlin42281ac2009-11-25 18:48:56 +000036
37typedef struct NetSocketState {
Stefan Hajnoczi4e68f7a2012-07-24 16:35:13 +010038 NetClientState nc;
Zhi Yong Wu011de2b2012-07-20 14:25:53 +010039 int listen_fd;
Mark McLoughlin42281ac2009-11-25 18:48:56 +000040 int fd;
Zhang Chen16a3df42016-05-13 15:35:19 +080041 SocketReadState rs;
Stefan Hajnoczi45a7f542012-08-20 10:14:35 +010042 unsigned int send_index; /* number of bytes sent (only SOCK_STREAM) */
Mark McLoughlin42281ac2009-11-25 18:48:56 +000043 struct sockaddr_in dgram_dst; /* contains inet host and port destination iff connectionless (SOCK_DGRAM) */
Stefan Hajnoczi863f6782012-08-20 10:21:54 +010044 IOHandler *send_fn; /* differs between SOCK_STREAM/SOCK_DGRAM */
45 bool read_poll; /* waiting to receive data? */
46 bool write_poll; /* waiting to transmit data? */
Mark McLoughlin42281ac2009-11-25 18:48:56 +000047} NetSocketState;
48
Zhi Yong Wu011de2b2012-07-20 14:25:53 +010049static void net_socket_accept(void *opaque);
Stefan Hajnoczi863f6782012-08-20 10:21:54 +010050static void net_socket_writable(void *opaque);
51
Stefan Hajnoczi863f6782012-08-20 10:21:54 +010052static void net_socket_update_fd_handler(NetSocketState *s)
53{
Fam Zheng82e1cc42015-06-04 14:45:18 +080054 qemu_set_fd_handler(s->fd,
55 s->read_poll ? s->send_fn : NULL,
56 s->write_poll ? net_socket_writable : NULL,
57 s);
Stefan Hajnoczi863f6782012-08-20 10:21:54 +010058}
59
60static void net_socket_read_poll(NetSocketState *s, bool enable)
61{
62 s->read_poll = enable;
63 net_socket_update_fd_handler(s);
64}
65
66static void net_socket_write_poll(NetSocketState *s, bool enable)
67{
68 s->write_poll = enable;
69 net_socket_update_fd_handler(s);
70}
71
72static void net_socket_writable(void *opaque)
73{
74 NetSocketState *s = opaque;
75
76 net_socket_write_poll(s, false);
77
78 qemu_flush_queued_packets(&s->nc);
79}
Mark McLoughlin42281ac2009-11-25 18:48:56 +000080
Stefan Hajnoczi4e68f7a2012-07-24 16:35:13 +010081static ssize_t net_socket_receive(NetClientState *nc, const uint8_t *buf, size_t size)
Mark McLoughlin42281ac2009-11-25 18:48:56 +000082{
Mark McLoughlin564f63e2009-11-25 18:49:08 +000083 NetSocketState *s = DO_UPCAST(NetSocketState, nc, nc);
Stefan Hajnoczi45a7f542012-08-20 10:14:35 +010084 uint32_t len = htonl(size);
85 struct iovec iov[] = {
86 {
87 .iov_base = &len,
88 .iov_len = sizeof(len),
89 }, {
90 .iov_base = (void *)buf,
91 .iov_len = size,
92 },
93 };
94 size_t remaining;
95 ssize_t ret;
Mark McLoughlin42281ac2009-11-25 18:48:56 +000096
Stefan Hajnoczi45a7f542012-08-20 10:14:35 +010097 remaining = iov_size(iov, 2) - s->send_index;
98 ret = iov_send(s->fd, iov, 2, s->send_index, remaining);
99
100 if (ret == -1 && errno == EAGAIN) {
101 ret = 0; /* handled further down */
102 }
103 if (ret == -1) {
104 s->send_index = 0;
105 return -errno;
106 }
107 if (ret < (ssize_t)remaining) {
108 s->send_index += ret;
109 net_socket_write_poll(s, true);
110 return 0;
111 }
112 s->send_index = 0;
113 return size;
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000114}
115
Stefan Hajnoczi4e68f7a2012-07-24 16:35:13 +0100116static ssize_t net_socket_receive_dgram(NetClientState *nc, const uint8_t *buf, size_t size)
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000117{
Mark McLoughlin564f63e2009-11-25 18:49:08 +0000118 NetSocketState *s = DO_UPCAST(NetSocketState, nc, nc);
Stefan Hajnoczi213fd502012-08-20 10:28:53 +0100119 ssize_t ret;
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000120
Stefan Hajnoczi213fd502012-08-20 10:28:53 +0100121 do {
Stefan Weil73062df2012-09-22 21:13:28 +0200122 ret = qemu_sendto(s->fd, buf, size, 0,
123 (struct sockaddr *)&s->dgram_dst,
124 sizeof(s->dgram_dst));
Stefan Hajnoczi213fd502012-08-20 10:28:53 +0100125 } while (ret == -1 && errno == EINTR);
126
127 if (ret == -1 && errno == EAGAIN) {
128 net_socket_write_poll(s, true);
129 return 0;
130 }
131 return ret;
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000132}
133
Fam Zheng6e99c632015-06-04 14:45:16 +0800134static void net_socket_send_completed(NetClientState *nc, ssize_t len)
135{
136 NetSocketState *s = DO_UPCAST(NetSocketState, nc, nc);
137
138 if (!s->read_poll) {
139 net_socket_read_poll(s, true);
140 }
141}
142
Zhang Chen16a3df42016-05-13 15:35:19 +0800143static void net_socket_rs_finalize(SocketReadState *rs)
144{
145 NetSocketState *s = container_of(rs, NetSocketState, rs);
146
147 if (qemu_send_packet_async(&s->nc, rs->buf,
148 rs->packet_len,
149 net_socket_send_completed) == 0) {
150 net_socket_read_poll(s, false);
151 }
152}
153
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000154static void net_socket_send(void *opaque)
155{
156 NetSocketState *s = opaque;
Daniel P. Berrangeb16a44e2016-03-07 20:36:03 +0000157 int size;
Zhang Chen16a3df42016-05-13 15:35:19 +0800158 int ret;
Scott Feldmand32fcad2013-03-18 11:43:44 -0700159 uint8_t buf1[NET_BUFSIZE];
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000160 const uint8_t *buf;
161
Blue Swirl00aa0042011-07-23 20:04:29 +0000162 size = qemu_recv(s->fd, buf1, sizeof(buf1), 0);
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000163 if (size < 0) {
Daniel P. Berrangeb16a44e2016-03-07 20:36:03 +0000164 if (errno != EWOULDBLOCK)
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000165 goto eoc;
166 } else if (size == 0) {
167 /* end of connection */
168 eoc:
Stefan Hajnoczi863f6782012-08-20 10:21:54 +0100169 net_socket_read_poll(s, false);
170 net_socket_write_poll(s, false);
Zhi Yong Wu011de2b2012-07-20 14:25:53 +0100171 if (s->listen_fd != -1) {
172 qemu_set_fd_handler(s->listen_fd, net_socket_accept, NULL, s);
173 }
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000174 closesocket(s->fd);
Zhi Yong Wu011de2b2012-07-20 14:25:53 +0100175
176 s->fd = -1;
Zhang Chen3cde5ea2017-07-04 14:53:46 +0800177 net_socket_rs_init(&s->rs, net_socket_rs_finalize, false);
Zhi Yong Wu011de2b2012-07-20 14:25:53 +0100178 s->nc.link_down = true;
Zhi Yong Wu011de2b2012-07-20 14:25:53 +0100179 memset(s->nc.info_str, 0, sizeof(s->nc.info_str));
180
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000181 return;
182 }
183 buf = buf1;
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000184
Zhang Chen16a3df42016-05-13 15:35:19 +0800185 ret = net_fill_rstate(&s->rs, buf, size);
186
187 if (ret == -1) {
188 goto eoc;
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000189 }
190}
191
192static void net_socket_send_dgram(void *opaque)
193{
194 NetSocketState *s = opaque;
195 int size;
196
Zhang Chen16a3df42016-05-13 15:35:19 +0800197 size = qemu_recv(s->fd, s->rs.buf, sizeof(s->rs.buf), 0);
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000198 if (size < 0)
199 return;
200 if (size == 0) {
201 /* end of connection */
Stefan Hajnoczi863f6782012-08-20 10:21:54 +0100202 net_socket_read_poll(s, false);
203 net_socket_write_poll(s, false);
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000204 return;
205 }
Zhang Chen16a3df42016-05-13 15:35:19 +0800206 if (qemu_send_packet_async(&s->nc, s->rs.buf, size,
Fam Zheng6e99c632015-06-04 14:45:16 +0800207 net_socket_send_completed) == 0) {
208 net_socket_read_poll(s, false);
209 }
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000210}
211
Mao Zhongyic37f0bb2017-09-04 22:35:38 +0800212static int net_socket_mcast_create(struct sockaddr_in *mcastaddr,
213 struct in_addr *localaddr,
214 Error **errp)
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000215{
216 struct ip_mreq imr;
217 int fd;
218 int val, ret;
Brad23ddf2b2011-08-07 11:06:43 +0000219#ifdef __OpenBSD__
220 unsigned char loop;
221#else
222 int loop;
223#endif
224
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000225 if (!IN_MULTICAST(ntohl(mcastaddr->sin_addr.s_addr))) {
Mao Zhongyic37f0bb2017-09-04 22:35:38 +0800226 error_setg(errp, "specified mcastaddr %s (0x%08x) "
227 "does not contain a multicast address",
228 inet_ntoa(mcastaddr->sin_addr),
229 (int)ntohl(mcastaddr->sin_addr.s_addr));
Stefan Hajnoczi842480d2011-12-07 15:01:48 +0000230 return -1;
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000231 }
Mao Zhongyic37f0bb2017-09-04 22:35:38 +0800232
Kevin Wolf40ff6d72009-12-02 12:24:42 +0100233 fd = qemu_socket(PF_INET, SOCK_DGRAM, 0);
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000234 if (fd < 0) {
Mao Zhongyic37f0bb2017-09-04 22:35:38 +0800235 error_setg_errno(errp, errno, "can't create datagram socket");
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000236 return -1;
237 }
238
Sebastian Ottlikbcbe92f2013-10-02 12:23:14 +0200239 /* Allow multiple sockets to bind the same multicast ip and port by setting
240 * SO_REUSEADDR. This is the only situation where SO_REUSEADDR should be set
241 * on windows. Use socket_set_fast_reuse otherwise as it sets SO_REUSEADDR
242 * only on posix systems.
243 */
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000244 val = 1;
Stefan Weil9957fc72013-03-08 19:58:32 +0100245 ret = qemu_setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000246 if (ret < 0) {
Mao Zhongyic37f0bb2017-09-04 22:35:38 +0800247 error_setg_errno(errp, errno,
248 "can't set socket option SO_REUSEADDR");
Stefan Hajnoczi842480d2011-12-07 15:01:48 +0000249 goto fail;
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000250 }
251
252 ret = bind(fd, (struct sockaddr *)mcastaddr, sizeof(*mcastaddr));
253 if (ret < 0) {
Mao Zhongyic37f0bb2017-09-04 22:35:38 +0800254 error_setg_errno(errp, errno, "can't bind ip=%s to socket",
255 inet_ntoa(mcastaddr->sin_addr));
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000256 goto fail;
257 }
258
259 /* Add host to multicast group */
260 imr.imr_multiaddr = mcastaddr->sin_addr;
Mike Ryan3a75e742010-12-01 11:16:47 -0800261 if (localaddr) {
262 imr.imr_interface = *localaddr;
263 } else {
264 imr.imr_interface.s_addr = htonl(INADDR_ANY);
265 }
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000266
Stefan Weil9957fc72013-03-08 19:58:32 +0100267 ret = qemu_setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
268 &imr, sizeof(struct ip_mreq));
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000269 if (ret < 0) {
Mao Zhongyic37f0bb2017-09-04 22:35:38 +0800270 error_setg_errno(errp, errno,
271 "can't add socket to multicast group %s",
272 inet_ntoa(imr.imr_multiaddr));
Stefan Hajnoczi842480d2011-12-07 15:01:48 +0000273 goto fail;
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000274 }
275
276 /* Force mcast msgs to loopback (eg. several QEMUs in same host */
Brad23ddf2b2011-08-07 11:06:43 +0000277 loop = 1;
Stefan Weil9957fc72013-03-08 19:58:32 +0100278 ret = qemu_setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP,
279 &loop, sizeof(loop));
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000280 if (ret < 0) {
Mao Zhongyic37f0bb2017-09-04 22:35:38 +0800281 error_setg_errno(errp, errno,
282 "can't force multicast message to loopback");
Stefan Hajnoczi842480d2011-12-07 15:01:48 +0000283 goto fail;
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000284 }
285
Mike Ryan3a75e742010-12-01 11:16:47 -0800286 /* If a bind address is given, only send packets from that address */
287 if (localaddr != NULL) {
Stefan Weil9957fc72013-03-08 19:58:32 +0100288 ret = qemu_setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF,
289 localaddr, sizeof(*localaddr));
Mike Ryan3a75e742010-12-01 11:16:47 -0800290 if (ret < 0) {
Mao Zhongyic37f0bb2017-09-04 22:35:38 +0800291 error_setg_errno(errp, errno,
292 "can't set the default network send interface");
Mike Ryan3a75e742010-12-01 11:16:47 -0800293 goto fail;
294 }
295 }
296
Stefan Hajnoczif9e8cac2013-03-27 10:10:43 +0100297 qemu_set_nonblock(fd);
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000298 return fd;
299fail:
300 if (fd >= 0)
301 closesocket(fd);
302 return -1;
303}
304
Stefan Hajnoczi4e68f7a2012-07-24 16:35:13 +0100305static void net_socket_cleanup(NetClientState *nc)
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000306{
Mark McLoughlin564f63e2009-11-25 18:49:08 +0000307 NetSocketState *s = DO_UPCAST(NetSocketState, nc, nc);
Zhi Yong Wu011de2b2012-07-20 14:25:53 +0100308 if (s->fd != -1) {
Stefan Hajnoczi863f6782012-08-20 10:21:54 +0100309 net_socket_read_poll(s, false);
310 net_socket_write_poll(s, false);
Zhi Yong Wu011de2b2012-07-20 14:25:53 +0100311 close(s->fd);
312 s->fd = -1;
313 }
314 if (s->listen_fd != -1) {
315 qemu_set_fd_handler(s->listen_fd, NULL, NULL, NULL);
316 closesocket(s->listen_fd);
317 s->listen_fd = -1;
318 }
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000319}
320
Mark McLoughlin564f63e2009-11-25 18:49:08 +0000321static NetClientInfo net_dgram_socket_info = {
Eric Blakef394b2e2016-07-13 21:50:23 -0600322 .type = NET_CLIENT_DRIVER_SOCKET,
Mark McLoughlin564f63e2009-11-25 18:49:08 +0000323 .size = sizeof(NetSocketState),
324 .receive = net_socket_receive_dgram,
325 .cleanup = net_socket_cleanup,
326};
327
Stefan Hajnoczi4e68f7a2012-07-24 16:35:13 +0100328static NetSocketState *net_socket_fd_init_dgram(NetClientState *peer,
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000329 const char *model,
330 const char *name,
Jens Freimann0f8c2892017-08-08 22:38:57 +0200331 int fd, int is_connected,
Mao Zhongyic37f0bb2017-09-04 22:35:38 +0800332 const char *mcast,
333 Error **errp)
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000334{
335 struct sockaddr_in saddr;
336 int newfd;
Stefan Hajnoczi4e68f7a2012-07-24 16:35:13 +0100337 NetClientState *nc;
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000338 NetSocketState *s;
339
340 /* fd passed: multicast: "learn" dgram_dst address from bound address and save it
341 * Because this may be "shared" socket from a "master" process, datagrams would be recv()
342 * by ONLY ONE process: we must "clone" this dgram socket --jjo
343 */
344
Jens Freimann0f8c2892017-08-08 22:38:57 +0200345 if (is_connected && mcast != NULL) {
346 if (parse_host_port(&saddr, mcast) < 0) {
Mao Zhongyic37f0bb2017-09-04 22:35:38 +0800347 error_setg(errp, "fd=%d failed parse_host_port()", fd);
Jens Freimann0f8c2892017-08-08 22:38:57 +0200348 goto err;
349 }
Stefan Hajnoczi842480d2011-12-07 15:01:48 +0000350 /* must be bound */
351 if (saddr.sin_addr.s_addr == 0) {
Mao Zhongyic37f0bb2017-09-04 22:35:38 +0800352 error_setg(errp, "can't setup multicast destination address");
Stefan Hajnoczie5d1fca2011-12-07 15:01:49 +0000353 goto err;
Stefan Hajnoczi842480d2011-12-07 15:01:48 +0000354 }
355 /* clone dgram socket */
Mao Zhongyic37f0bb2017-09-04 22:35:38 +0800356 newfd = net_socket_mcast_create(&saddr, NULL, errp);
Stefan Hajnoczi842480d2011-12-07 15:01:48 +0000357 if (newfd < 0) {
Stefan Hajnoczie5d1fca2011-12-07 15:01:49 +0000358 goto err;
Stefan Hajnoczi842480d2011-12-07 15:01:48 +0000359 }
360 /* clone newfd to fd, close newfd */
361 dup2(newfd, fd);
362 close(newfd);
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000363
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000364 }
365
Stefan Hajnocziab5f3f82012-07-24 16:35:08 +0100366 nc = qemu_new_net_client(&net_dgram_socket_info, peer, model, name);
Mark McLoughlin564f63e2009-11-25 18:49:08 +0000367
Mark McLoughlin564f63e2009-11-25 18:49:08 +0000368 s = DO_UPCAST(NetSocketState, nc, nc);
369
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000370 s->fd = fd;
Zhi Yong Wu011de2b2012-07-20 14:25:53 +0100371 s->listen_fd = -1;
Stefan Hajnoczi863f6782012-08-20 10:21:54 +0100372 s->send_fn = net_socket_send_dgram;
Zhang Chen3cde5ea2017-07-04 14:53:46 +0800373 net_socket_rs_init(&s->rs, net_socket_rs_finalize, false);
Stefan Hajnoczi863f6782012-08-20 10:21:54 +0100374 net_socket_read_poll(s, true);
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000375
376 /* mcast: save bound address as dst */
Zhi Yong Wue34cde32012-07-20 14:25:52 +0100377 if (is_connected) {
378 s->dgram_dst = saddr;
Gonglei8db804a2014-11-20 19:35:01 +0800379 snprintf(nc->info_str, sizeof(nc->info_str),
380 "socket: fd=%d (cloned mcast=%s:%d)",
381 fd, inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port));
382 } else {
383 snprintf(nc->info_str, sizeof(nc->info_str),
384 "socket: fd=%d", fd);
Zhi Yong Wue34cde32012-07-20 14:25:52 +0100385 }
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000386
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000387 return s;
Stefan Hajnoczie5d1fca2011-12-07 15:01:49 +0000388
389err:
390 closesocket(fd);
391 return NULL;
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000392}
393
394static void net_socket_connect(void *opaque)
395{
396 NetSocketState *s = opaque;
Stefan Hajnoczi863f6782012-08-20 10:21:54 +0100397 s->send_fn = net_socket_send;
398 net_socket_read_poll(s, true);
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000399}
400
Mark McLoughlin564f63e2009-11-25 18:49:08 +0000401static NetClientInfo net_socket_info = {
Eric Blakef394b2e2016-07-13 21:50:23 -0600402 .type = NET_CLIENT_DRIVER_SOCKET,
Mark McLoughlin564f63e2009-11-25 18:49:08 +0000403 .size = sizeof(NetSocketState),
404 .receive = net_socket_receive,
405 .cleanup = net_socket_cleanup,
406};
407
Stefan Hajnoczi4e68f7a2012-07-24 16:35:13 +0100408static NetSocketState *net_socket_fd_init_stream(NetClientState *peer,
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000409 const char *model,
410 const char *name,
411 int fd, int is_connected)
412{
Stefan Hajnoczi4e68f7a2012-07-24 16:35:13 +0100413 NetClientState *nc;
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000414 NetSocketState *s;
Mark McLoughlin564f63e2009-11-25 18:49:08 +0000415
Stefan Hajnocziab5f3f82012-07-24 16:35:08 +0100416 nc = qemu_new_net_client(&net_socket_info, peer, model, name);
Mark McLoughlin564f63e2009-11-25 18:49:08 +0000417
418 snprintf(nc->info_str, sizeof(nc->info_str), "socket: fd=%d", fd);
419
420 s = DO_UPCAST(NetSocketState, nc, nc);
421
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000422 s->fd = fd;
Zhi Yong Wu011de2b2012-07-20 14:25:53 +0100423 s->listen_fd = -1;
Zhang Chen3cde5ea2017-07-04 14:53:46 +0800424 net_socket_rs_init(&s->rs, net_socket_rs_finalize, false);
Mark McLoughlin564f63e2009-11-25 18:49:08 +0000425
Stefan Hajnoczi20048d02013-02-27 15:05:47 +0100426 /* Disable Nagle algorithm on TCP sockets to reduce latency */
427 socket_set_nodelay(fd);
428
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000429 if (is_connected) {
430 net_socket_connect(s);
431 } else {
432 qemu_set_fd_handler(s->fd, NULL, net_socket_connect, s);
433 }
434 return s;
435}
436
Stefan Hajnoczi4e68f7a2012-07-24 16:35:13 +0100437static NetSocketState *net_socket_fd_init(NetClientState *peer,
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000438 const char *model, const char *name,
Mao Zhongyic37f0bb2017-09-04 22:35:38 +0800439 int fd, int is_connected,
440 const char *mc, Error **errp)
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000441{
442 int so_type = -1, optlen=sizeof(so_type);
443
444 if(getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&so_type,
445 (socklen_t *)&optlen)< 0) {
Mao Zhongyic37f0bb2017-09-04 22:35:38 +0800446 error_setg(errp, "can't get socket option SO_TYPE");
Stefan Hajnoczie5d1fca2011-12-07 15:01:49 +0000447 closesocket(fd);
Stefan Hajnoczi842480d2011-12-07 15:01:48 +0000448 return NULL;
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000449 }
450 switch(so_type) {
451 case SOCK_DGRAM:
Mao Zhongyic37f0bb2017-09-04 22:35:38 +0800452 return net_socket_fd_init_dgram(peer, model, name, fd, is_connected,
453 mc, errp);
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000454 case SOCK_STREAM:
Stefan Hajnoczid33d93b2012-07-24 16:35:05 +0100455 return net_socket_fd_init_stream(peer, model, name, fd, is_connected);
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000456 default:
Mao Zhongyie1b24b62017-09-04 22:35:37 +0800457 error_report("socket type=%d for fd=%d must be either"
458 " SOCK_DGRAM or SOCK_STREAM", so_type, fd);
459 closesocket(fd);
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000460 }
461 return NULL;
462}
463
464static void net_socket_accept(void *opaque)
465{
Zhi Yong Wu011de2b2012-07-20 14:25:53 +0100466 NetSocketState *s = opaque;
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000467 struct sockaddr_in saddr;
468 socklen_t len;
469 int fd;
470
471 for(;;) {
472 len = sizeof(saddr);
Zhi Yong Wu011de2b2012-07-20 14:25:53 +0100473 fd = qemu_accept(s->listen_fd, (struct sockaddr *)&saddr, &len);
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000474 if (fd < 0 && errno != EINTR) {
475 return;
476 } else if (fd >= 0) {
Zhi Yong Wu011de2b2012-07-20 14:25:53 +0100477 qemu_set_fd_handler(s->listen_fd, NULL, NULL, NULL);
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000478 break;
479 }
480 }
Zhi Yong Wu011de2b2012-07-20 14:25:53 +0100481
482 s->fd = fd;
483 s->nc.link_down = false;
484 net_socket_connect(s);
485 snprintf(s->nc.info_str, sizeof(s->nc.info_str),
486 "socket: connection from %s:%d",
487 inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port));
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000488}
489
Stefan Hajnoczi4e68f7a2012-07-24 16:35:13 +0100490static int net_socket_listen_init(NetClientState *peer,
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000491 const char *model,
492 const char *name,
493 const char *host_str)
494{
Zhi Yong Wu011de2b2012-07-20 14:25:53 +0100495 NetClientState *nc;
496 NetSocketState *s;
Daniel P. Berrange6701e552017-05-05 17:23:05 +0100497 struct sockaddr_in saddr;
498 int fd, ret;
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000499
Daniel P. Berrange6701e552017-05-05 17:23:05 +0100500 if (parse_host_port(&saddr, host_str) < 0)
501 return -1;
502
503 fd = qemu_socket(PF_INET, SOCK_STREAM, 0);
504 if (fd < 0) {
505 perror("socket");
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000506 return -1;
507 }
Daniel P. Berrange6701e552017-05-05 17:23:05 +0100508 qemu_set_nonblock(fd);
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000509
Daniel P. Berrange6701e552017-05-05 17:23:05 +0100510 socket_set_fast_reuse(fd);
511
512 ret = bind(fd, (struct sockaddr *)&saddr, sizeof(saddr));
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000513 if (ret < 0) {
Daniel P. Berrange6701e552017-05-05 17:23:05 +0100514 perror("bind");
515 closesocket(fd);
516 return -1;
517 }
518 ret = listen(fd, 0);
519 if (ret < 0) {
520 perror("listen");
521 closesocket(fd);
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000522 return -1;
523 }
Zhi Yong Wu011de2b2012-07-20 14:25:53 +0100524
525 nc = qemu_new_net_client(&net_socket_info, peer, model, name);
526 s = DO_UPCAST(NetSocketState, nc, nc);
527 s->fd = -1;
Daniel P. Berrange6701e552017-05-05 17:23:05 +0100528 s->listen_fd = fd;
Zhi Yong Wu011de2b2012-07-20 14:25:53 +0100529 s->nc.link_down = true;
Zhang Chen3cde5ea2017-07-04 14:53:46 +0800530 net_socket_rs_init(&s->rs, net_socket_rs_finalize, false);
Zhi Yong Wu011de2b2012-07-20 14:25:53 +0100531
532 qemu_set_fd_handler(s->listen_fd, net_socket_accept, NULL, s);
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000533 return 0;
534}
535
Stefan Hajnoczi4e68f7a2012-07-24 16:35:13 +0100536static int net_socket_connect_init(NetClientState *peer,
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000537 const char *model,
538 const char *name,
539 const char *host_str)
540{
Daniel P. Berrange6701e552017-05-05 17:23:05 +0100541 NetSocketState *s;
542 int fd, connected, ret;
543 struct sockaddr_in saddr;
Mao Zhongyic37f0bb2017-09-04 22:35:38 +0800544 Error *err = NULL;
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000545
Daniel P. Berrange6701e552017-05-05 17:23:05 +0100546 if (parse_host_port(&saddr, host_str) < 0)
547 return -1;
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000548
Daniel P. Berrange6701e552017-05-05 17:23:05 +0100549 fd = qemu_socket(PF_INET, SOCK_STREAM, 0);
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000550 if (fd < 0) {
Daniel P. Berrange6701e552017-05-05 17:23:05 +0100551 perror("socket");
552 return -1;
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000553 }
Daniel P. Berrange6701e552017-05-05 17:23:05 +0100554 qemu_set_nonblock(fd);
Paolo Bonzini61601832016-08-30 14:04:12 +0200555
Daniel P. Berrange6701e552017-05-05 17:23:05 +0100556 connected = 0;
557 for(;;) {
558 ret = connect(fd, (struct sockaddr *)&saddr, sizeof(saddr));
559 if (ret < 0) {
560 if (errno == EINTR || errno == EWOULDBLOCK) {
561 /* continue */
562 } else if (errno == EINPROGRESS ||
563 errno == EALREADY ||
564 errno == EINVAL) {
565 break;
566 } else {
567 perror("connect");
568 closesocket(fd);
569 return -1;
570 }
571 } else {
572 connected = 1;
573 break;
574 }
575 }
Mao Zhongyic37f0bb2017-09-04 22:35:38 +0800576 s = net_socket_fd_init(peer, model, name, fd, connected, NULL, &err);
577 if (!s) {
578 error_report_err(err);
Daniel P. Berrange6701e552017-05-05 17:23:05 +0100579 return -1;
Mao Zhongyic37f0bb2017-09-04 22:35:38 +0800580 }
581
Daniel P. Berrange6701e552017-05-05 17:23:05 +0100582 snprintf(s->nc.info_str, sizeof(s->nc.info_str),
583 "socket: connect to %s:%d",
584 inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port));
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000585 return 0;
586}
587
Stefan Hajnoczi4e68f7a2012-07-24 16:35:13 +0100588static int net_socket_mcast_init(NetClientState *peer,
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000589 const char *model,
590 const char *name,
Mike Ryan3a75e742010-12-01 11:16:47 -0800591 const char *host_str,
592 const char *localaddr_str)
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000593{
594 NetSocketState *s;
595 int fd;
596 struct sockaddr_in saddr;
Mike Ryan3a75e742010-12-01 11:16:47 -0800597 struct in_addr localaddr, *param_localaddr;
Mao Zhongyic37f0bb2017-09-04 22:35:38 +0800598 Error *err = NULL;
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000599
600 if (parse_host_port(&saddr, host_str) < 0)
601 return -1;
602
Mike Ryan3a75e742010-12-01 11:16:47 -0800603 if (localaddr_str != NULL) {
604 if (inet_aton(localaddr_str, &localaddr) == 0)
605 return -1;
606 param_localaddr = &localaddr;
607 } else {
608 param_localaddr = NULL;
609 }
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000610
Mao Zhongyic37f0bb2017-09-04 22:35:38 +0800611 fd = net_socket_mcast_create(&saddr, param_localaddr, &err);
612 if (fd < 0) {
613 error_report_err(err);
Stefan Hajnoczi842480d2011-12-07 15:01:48 +0000614 return -1;
Mao Zhongyic37f0bb2017-09-04 22:35:38 +0800615 }
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000616
Mao Zhongyic37f0bb2017-09-04 22:35:38 +0800617 s = net_socket_fd_init(peer, model, name, fd, 0, NULL, &err);
618 if (!s) {
619 error_report_err(err);
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000620 return -1;
Mao Zhongyic37f0bb2017-09-04 22:35:38 +0800621 }
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000622
623 s->dgram_dst = saddr;
624
Mark McLoughlin564f63e2009-11-25 18:49:08 +0000625 snprintf(s->nc.info_str, sizeof(s->nc.info_str),
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000626 "socket: mcast=%s:%d",
627 inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port));
628 return 0;
629
630}
631
Stefan Hajnoczi4e68f7a2012-07-24 16:35:13 +0100632static int net_socket_udp_init(NetClientState *peer,
Benjamin0e0e7fa2012-01-11 09:20:54 +0900633 const char *model,
634 const char *name,
635 const char *rhost,
636 const char *lhost)
637{
638 NetSocketState *s;
Sebastian Ottlikbcbe92f2013-10-02 12:23:14 +0200639 int fd, ret;
Benjamin0e0e7fa2012-01-11 09:20:54 +0900640 struct sockaddr_in laddr, raddr;
Mao Zhongyic37f0bb2017-09-04 22:35:38 +0800641 Error *err = NULL;
Benjamin0e0e7fa2012-01-11 09:20:54 +0900642
643 if (parse_host_port(&laddr, lhost) < 0) {
644 return -1;
645 }
646
647 if (parse_host_port(&raddr, rhost) < 0) {
648 return -1;
649 }
650
651 fd = qemu_socket(PF_INET, SOCK_DGRAM, 0);
652 if (fd < 0) {
653 perror("socket(PF_INET, SOCK_DGRAM)");
654 return -1;
655 }
Sebastian Ottlikbcbe92f2013-10-02 12:23:14 +0200656
657 ret = socket_set_fast_reuse(fd);
Benjamin0e0e7fa2012-01-11 09:20:54 +0900658 if (ret < 0) {
Benjamin0e0e7fa2012-01-11 09:20:54 +0900659 closesocket(fd);
660 return -1;
661 }
662 ret = bind(fd, (struct sockaddr *)&laddr, sizeof(laddr));
663 if (ret < 0) {
664 perror("bind");
665 closesocket(fd);
666 return -1;
667 }
Stefan Hajnoczifc13fa02013-03-27 10:10:44 +0100668 qemu_set_nonblock(fd);
Benjamin0e0e7fa2012-01-11 09:20:54 +0900669
Mao Zhongyic37f0bb2017-09-04 22:35:38 +0800670 s = net_socket_fd_init(peer, model, name, fd, 0, NULL, &err);
Benjamin0e0e7fa2012-01-11 09:20:54 +0900671 if (!s) {
Mao Zhongyic37f0bb2017-09-04 22:35:38 +0800672 error_report_err(err);
Benjamin0e0e7fa2012-01-11 09:20:54 +0900673 return -1;
674 }
675
676 s->dgram_dst = raddr;
677
678 snprintf(s->nc.info_str, sizeof(s->nc.info_str),
679 "socket: udp=%s:%d",
680 inet_ntoa(raddr.sin_addr), ntohs(raddr.sin_port));
681 return 0;
682}
683
Kővágó, Zoltáncebea512016-07-13 21:50:12 -0600684int net_init_socket(const Netdev *netdev, const char *name,
Markus Armbrustera30ecde2015-05-15 13:58:50 +0200685 NetClientState *peer, Error **errp)
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000686{
Markus Armbrustera30ecde2015-05-15 13:58:50 +0200687 /* FIXME error_setg(errp, ...) on failure */
Markus Armbruster1677f4c2015-02-09 14:03:19 +0100688 Error *err = NULL;
Laszlo Ersekbef8e8f2012-07-17 16:17:17 +0200689 const NetdevSocketOptions *sock;
690
Eric Blakef394b2e2016-07-13 21:50:23 -0600691 assert(netdev->type == NET_CLIENT_DRIVER_SOCKET);
692 sock = &netdev->u.socket;
Laszlo Ersekbef8e8f2012-07-17 16:17:17 +0200693
Jens Freimann0f8c2892017-08-08 22:38:57 +0200694 if (sock->has_listen + sock->has_connect + sock->has_mcast +
695 sock->has_udp > 1) {
696 error_report("exactly one of listen=, connect=, mcast= or udp="
Laszlo Ersekbef8e8f2012-07-17 16:17:17 +0200697 " is required");
698 return -1;
699 }
700
701 if (sock->has_localaddr && !sock->has_mcast && !sock->has_udp) {
702 error_report("localaddr= is only valid with mcast= or udp=");
703 return -1;
704 }
705
706 if (sock->has_fd) {
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000707 int fd;
708
Markus Armbruster1677f4c2015-02-09 14:03:19 +0100709 fd = monitor_fd_param(cur_mon, sock->fd, &err);
Stefan Hajnoczifc13fa02013-03-27 10:10:44 +0100710 if (fd == -1) {
Markus Armbruster1677f4c2015-02-09 14:03:19 +0100711 error_report_err(err);
Stefan Hajnoczifc13fa02013-03-27 10:10:44 +0100712 return -1;
713 }
714 qemu_set_nonblock(fd);
Mao Zhongyic37f0bb2017-09-04 22:35:38 +0800715 if (!net_socket_fd_init(peer, "socket", name, fd, 1, sock->mcast,
716 errp)) {
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000717 return -1;
718 }
Laszlo Ersekbef8e8f2012-07-17 16:17:17 +0200719 return 0;
720 }
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000721
Laszlo Ersekbef8e8f2012-07-17 16:17:17 +0200722 if (sock->has_listen) {
Stefan Hajnoczid33d93b2012-07-24 16:35:05 +0100723 if (net_socket_listen_init(peer, "socket", name, sock->listen) == -1) {
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000724 return -1;
725 }
Laszlo Ersekbef8e8f2012-07-17 16:17:17 +0200726 return 0;
727 }
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000728
Laszlo Ersekbef8e8f2012-07-17 16:17:17 +0200729 if (sock->has_connect) {
Stefan Hajnoczid33d93b2012-07-24 16:35:05 +0100730 if (net_socket_connect_init(peer, "socket", name, sock->connect) ==
Laszlo Ersekbef8e8f2012-07-17 16:17:17 +0200731 -1) {
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000732 return -1;
733 }
Laszlo Ersekbef8e8f2012-07-17 16:17:17 +0200734 return 0;
735 }
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000736
Laszlo Ersekbef8e8f2012-07-17 16:17:17 +0200737 if (sock->has_mcast) {
738 /* if sock->localaddr is missing, it has been initialized to "all bits
739 * zero" */
Stefan Hajnoczid33d93b2012-07-24 16:35:05 +0100740 if (net_socket_mcast_init(peer, "socket", name, sock->mcast,
Laszlo Ersekbef8e8f2012-07-17 16:17:17 +0200741 sock->localaddr) == -1) {
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000742 return -1;
743 }
Laszlo Ersekbef8e8f2012-07-17 16:17:17 +0200744 return 0;
745 }
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000746
Laszlo Ersekbef8e8f2012-07-17 16:17:17 +0200747 assert(sock->has_udp);
748 if (!sock->has_localaddr) {
749 error_report("localaddr= is mandatory with udp=");
750 return -1;
751 }
Lei Lif0e3ac72012-11-01 17:39:55 +0800752 if (net_socket_udp_init(peer, "socket", name, sock->udp, sock->localaddr) ==
Laszlo Ersekbef8e8f2012-07-17 16:17:17 +0200753 -1) {
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000754 return -1;
755 }
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000756 return 0;
757}