blob: 90ef3517beb8984d742a4983766b7edd440bd828 [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) {
Mao Zhongyibcd4dfd2017-09-04 22:35:39 +0800346 if (parse_host_port(&saddr, mcast, errp) < 0) {
Jens Freimann0f8c2892017-08-08 22:38:57 +0200347 goto err;
348 }
Stefan Hajnoczi842480d2011-12-07 15:01:48 +0000349 /* must be bound */
350 if (saddr.sin_addr.s_addr == 0) {
Mao Zhongyic37f0bb2017-09-04 22:35:38 +0800351 error_setg(errp, "can't setup multicast destination address");
Stefan Hajnoczie5d1fca2011-12-07 15:01:49 +0000352 goto err;
Stefan Hajnoczi842480d2011-12-07 15:01:48 +0000353 }
354 /* clone dgram socket */
Mao Zhongyic37f0bb2017-09-04 22:35:38 +0800355 newfd = net_socket_mcast_create(&saddr, NULL, errp);
Stefan Hajnoczi842480d2011-12-07 15:01:48 +0000356 if (newfd < 0) {
Stefan Hajnoczie5d1fca2011-12-07 15:01:49 +0000357 goto err;
Stefan Hajnoczi842480d2011-12-07 15:01:48 +0000358 }
359 /* clone newfd to fd, close newfd */
360 dup2(newfd, fd);
361 close(newfd);
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000362
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000363 }
364
Stefan Hajnocziab5f3f82012-07-24 16:35:08 +0100365 nc = qemu_new_net_client(&net_dgram_socket_info, peer, model, name);
Mark McLoughlin564f63e2009-11-25 18:49:08 +0000366
Mark McLoughlin564f63e2009-11-25 18:49:08 +0000367 s = DO_UPCAST(NetSocketState, nc, nc);
368
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000369 s->fd = fd;
Zhi Yong Wu011de2b2012-07-20 14:25:53 +0100370 s->listen_fd = -1;
Stefan Hajnoczi863f6782012-08-20 10:21:54 +0100371 s->send_fn = net_socket_send_dgram;
Zhang Chen3cde5ea2017-07-04 14:53:46 +0800372 net_socket_rs_init(&s->rs, net_socket_rs_finalize, false);
Stefan Hajnoczi863f6782012-08-20 10:21:54 +0100373 net_socket_read_poll(s, true);
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000374
375 /* mcast: save bound address as dst */
Jens Freimannbb160b52017-11-06 15:05:46 +0100376 if (is_connected && mcast != NULL) {
Zhi Yong Wue34cde32012-07-20 14:25:52 +0100377 s->dgram_dst = saddr;
Gonglei8db804a2014-11-20 19:35:01 +0800378 snprintf(nc->info_str, sizeof(nc->info_str),
379 "socket: fd=%d (cloned mcast=%s:%d)",
380 fd, inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port));
381 } else {
382 snprintf(nc->info_str, sizeof(nc->info_str),
383 "socket: fd=%d", fd);
Zhi Yong Wue34cde32012-07-20 14:25:52 +0100384 }
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000385
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000386 return s;
Stefan Hajnoczie5d1fca2011-12-07 15:01:49 +0000387
388err:
389 closesocket(fd);
390 return NULL;
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000391}
392
393static void net_socket_connect(void *opaque)
394{
395 NetSocketState *s = opaque;
Stefan Hajnoczi863f6782012-08-20 10:21:54 +0100396 s->send_fn = net_socket_send;
397 net_socket_read_poll(s, true);
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000398}
399
Mark McLoughlin564f63e2009-11-25 18:49:08 +0000400static NetClientInfo net_socket_info = {
Eric Blakef394b2e2016-07-13 21:50:23 -0600401 .type = NET_CLIENT_DRIVER_SOCKET,
Mark McLoughlin564f63e2009-11-25 18:49:08 +0000402 .size = sizeof(NetSocketState),
403 .receive = net_socket_receive,
404 .cleanup = net_socket_cleanup,
405};
406
Stefan Hajnoczi4e68f7a2012-07-24 16:35:13 +0100407static NetSocketState *net_socket_fd_init_stream(NetClientState *peer,
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000408 const char *model,
409 const char *name,
410 int fd, int is_connected)
411{
Stefan Hajnoczi4e68f7a2012-07-24 16:35:13 +0100412 NetClientState *nc;
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000413 NetSocketState *s;
Mark McLoughlin564f63e2009-11-25 18:49:08 +0000414
Stefan Hajnocziab5f3f82012-07-24 16:35:08 +0100415 nc = qemu_new_net_client(&net_socket_info, peer, model, name);
Mark McLoughlin564f63e2009-11-25 18:49:08 +0000416
417 snprintf(nc->info_str, sizeof(nc->info_str), "socket: fd=%d", fd);
418
419 s = DO_UPCAST(NetSocketState, nc, nc);
420
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000421 s->fd = fd;
Zhi Yong Wu011de2b2012-07-20 14:25:53 +0100422 s->listen_fd = -1;
Zhang Chen3cde5ea2017-07-04 14:53:46 +0800423 net_socket_rs_init(&s->rs, net_socket_rs_finalize, false);
Mark McLoughlin564f63e2009-11-25 18:49:08 +0000424
Stefan Hajnoczi20048d02013-02-27 15:05:47 +0100425 /* Disable Nagle algorithm on TCP sockets to reduce latency */
426 socket_set_nodelay(fd);
427
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000428 if (is_connected) {
429 net_socket_connect(s);
430 } else {
431 qemu_set_fd_handler(s->fd, NULL, net_socket_connect, s);
432 }
433 return s;
434}
435
Stefan Hajnoczi4e68f7a2012-07-24 16:35:13 +0100436static NetSocketState *net_socket_fd_init(NetClientState *peer,
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000437 const char *model, const char *name,
Mao Zhongyic37f0bb2017-09-04 22:35:38 +0800438 int fd, int is_connected,
439 const char *mc, Error **errp)
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000440{
441 int so_type = -1, optlen=sizeof(so_type);
442
443 if(getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&so_type,
444 (socklen_t *)&optlen)< 0) {
Mao Zhongyic37f0bb2017-09-04 22:35:38 +0800445 error_setg(errp, "can't get socket option SO_TYPE");
Stefan Hajnoczie5d1fca2011-12-07 15:01:49 +0000446 closesocket(fd);
Stefan Hajnoczi842480d2011-12-07 15:01:48 +0000447 return NULL;
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000448 }
449 switch(so_type) {
450 case SOCK_DGRAM:
Mao Zhongyic37f0bb2017-09-04 22:35:38 +0800451 return net_socket_fd_init_dgram(peer, model, name, fd, is_connected,
452 mc, errp);
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000453 case SOCK_STREAM:
Stefan Hajnoczid33d93b2012-07-24 16:35:05 +0100454 return net_socket_fd_init_stream(peer, model, name, fd, is_connected);
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000455 default:
Markus Armbruster8c42dbe2018-10-17 10:26:38 +0200456 error_setg(errp, "socket type=%d for fd=%d must be either"
457 " SOCK_DGRAM or SOCK_STREAM", so_type, fd);
Mao Zhongyie1b24b62017-09-04 22:35:37 +0800458 closesocket(fd);
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000459 }
460 return NULL;
461}
462
463static void net_socket_accept(void *opaque)
464{
Zhi Yong Wu011de2b2012-07-20 14:25:53 +0100465 NetSocketState *s = opaque;
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000466 struct sockaddr_in saddr;
467 socklen_t len;
468 int fd;
469
470 for(;;) {
471 len = sizeof(saddr);
Zhi Yong Wu011de2b2012-07-20 14:25:53 +0100472 fd = qemu_accept(s->listen_fd, (struct sockaddr *)&saddr, &len);
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000473 if (fd < 0 && errno != EINTR) {
474 return;
475 } else if (fd >= 0) {
Zhi Yong Wu011de2b2012-07-20 14:25:53 +0100476 qemu_set_fd_handler(s->listen_fd, NULL, NULL, NULL);
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000477 break;
478 }
479 }
Zhi Yong Wu011de2b2012-07-20 14:25:53 +0100480
481 s->fd = fd;
482 s->nc.link_down = false;
483 net_socket_connect(s);
484 snprintf(s->nc.info_str, sizeof(s->nc.info_str),
485 "socket: connection from %s:%d",
486 inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port));
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000487}
488
Stefan Hajnoczi4e68f7a2012-07-24 16:35:13 +0100489static int net_socket_listen_init(NetClientState *peer,
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000490 const char *model,
491 const char *name,
Mao Zhongyi0522a952017-09-04 22:35:40 +0800492 const char *host_str,
493 Error **errp)
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000494{
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
Mao Zhongyi0522a952017-09-04 22:35:40 +0800500 if (parse_host_port(&saddr, host_str, errp) < 0) {
Daniel P. Berrange6701e552017-05-05 17:23:05 +0100501 return -1;
Mao Zhongyibcd4dfd2017-09-04 22:35:39 +0800502 }
Daniel P. Berrange6701e552017-05-05 17:23:05 +0100503
504 fd = qemu_socket(PF_INET, SOCK_STREAM, 0);
505 if (fd < 0) {
Mao Zhongyi0522a952017-09-04 22:35:40 +0800506 error_setg_errno(errp, errno, "can't create stream socket");
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000507 return -1;
508 }
Daniel P. Berrange6701e552017-05-05 17:23:05 +0100509 qemu_set_nonblock(fd);
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000510
Daniel P. Berrange6701e552017-05-05 17:23:05 +0100511 socket_set_fast_reuse(fd);
512
513 ret = bind(fd, (struct sockaddr *)&saddr, sizeof(saddr));
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000514 if (ret < 0) {
Mao Zhongyi0522a952017-09-04 22:35:40 +0800515 error_setg_errno(errp, errno, "can't bind ip=%s to socket",
516 inet_ntoa(saddr.sin_addr));
Daniel P. Berrange6701e552017-05-05 17:23:05 +0100517 closesocket(fd);
518 return -1;
519 }
520 ret = listen(fd, 0);
521 if (ret < 0) {
Mao Zhongyi0522a952017-09-04 22:35:40 +0800522 error_setg_errno(errp, errno, "can't listen on socket");
Daniel P. Berrange6701e552017-05-05 17:23:05 +0100523 closesocket(fd);
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000524 return -1;
525 }
Zhi Yong Wu011de2b2012-07-20 14:25:53 +0100526
527 nc = qemu_new_net_client(&net_socket_info, peer, model, name);
528 s = DO_UPCAST(NetSocketState, nc, nc);
529 s->fd = -1;
Daniel P. Berrange6701e552017-05-05 17:23:05 +0100530 s->listen_fd = fd;
Zhi Yong Wu011de2b2012-07-20 14:25:53 +0100531 s->nc.link_down = true;
Zhang Chen3cde5ea2017-07-04 14:53:46 +0800532 net_socket_rs_init(&s->rs, net_socket_rs_finalize, false);
Zhi Yong Wu011de2b2012-07-20 14:25:53 +0100533
534 qemu_set_fd_handler(s->listen_fd, net_socket_accept, NULL, s);
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000535 return 0;
536}
537
Stefan Hajnoczi4e68f7a2012-07-24 16:35:13 +0100538static int net_socket_connect_init(NetClientState *peer,
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000539 const char *model,
540 const char *name,
Mao Zhongyi0522a952017-09-04 22:35:40 +0800541 const char *host_str,
542 Error **errp)
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000543{
Daniel P. Berrange6701e552017-05-05 17:23:05 +0100544 NetSocketState *s;
545 int fd, connected, ret;
546 struct sockaddr_in saddr;
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000547
Mao Zhongyi0522a952017-09-04 22:35:40 +0800548 if (parse_host_port(&saddr, host_str, errp) < 0) {
Daniel P. Berrange6701e552017-05-05 17:23:05 +0100549 return -1;
Mao Zhongyibcd4dfd2017-09-04 22:35:39 +0800550 }
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000551
Daniel P. Berrange6701e552017-05-05 17:23:05 +0100552 fd = qemu_socket(PF_INET, SOCK_STREAM, 0);
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000553 if (fd < 0) {
Mao Zhongyi0522a952017-09-04 22:35:40 +0800554 error_setg_errno(errp, errno, "can't create stream socket");
Daniel P. Berrange6701e552017-05-05 17:23:05 +0100555 return -1;
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000556 }
Daniel P. Berrange6701e552017-05-05 17:23:05 +0100557 qemu_set_nonblock(fd);
Paolo Bonzini61601832016-08-30 14:04:12 +0200558
Daniel P. Berrange6701e552017-05-05 17:23:05 +0100559 connected = 0;
560 for(;;) {
561 ret = connect(fd, (struct sockaddr *)&saddr, sizeof(saddr));
562 if (ret < 0) {
563 if (errno == EINTR || errno == EWOULDBLOCK) {
564 /* continue */
565 } else if (errno == EINPROGRESS ||
566 errno == EALREADY ||
567 errno == EINVAL) {
568 break;
569 } else {
Mao Zhongyi0522a952017-09-04 22:35:40 +0800570 error_setg_errno(errp, errno, "can't connect socket");
Daniel P. Berrange6701e552017-05-05 17:23:05 +0100571 closesocket(fd);
572 return -1;
573 }
574 } else {
575 connected = 1;
576 break;
577 }
578 }
Mao Zhongyi0522a952017-09-04 22:35:40 +0800579 s = net_socket_fd_init(peer, model, name, fd, connected, NULL, errp);
Mao Zhongyic37f0bb2017-09-04 22:35:38 +0800580 if (!s) {
Daniel P. Berrange6701e552017-05-05 17:23:05 +0100581 return -1;
Mao Zhongyic37f0bb2017-09-04 22:35:38 +0800582 }
583
Daniel P. Berrange6701e552017-05-05 17:23:05 +0100584 snprintf(s->nc.info_str, sizeof(s->nc.info_str),
585 "socket: connect to %s:%d",
586 inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port));
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000587 return 0;
588}
589
Stefan Hajnoczi4e68f7a2012-07-24 16:35:13 +0100590static int net_socket_mcast_init(NetClientState *peer,
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000591 const char *model,
592 const char *name,
Mike Ryan3a75e742010-12-01 11:16:47 -0800593 const char *host_str,
Mao Zhongyi0522a952017-09-04 22:35:40 +0800594 const char *localaddr_str,
595 Error **errp)
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000596{
597 NetSocketState *s;
598 int fd;
599 struct sockaddr_in saddr;
Mike Ryan3a75e742010-12-01 11:16:47 -0800600 struct in_addr localaddr, *param_localaddr;
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000601
Mao Zhongyi0522a952017-09-04 22:35:40 +0800602 if (parse_host_port(&saddr, host_str, errp) < 0) {
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000603 return -1;
Mao Zhongyibcd4dfd2017-09-04 22:35:39 +0800604 }
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000605
Mike Ryan3a75e742010-12-01 11:16:47 -0800606 if (localaddr_str != NULL) {
Mao Zhongyi0522a952017-09-04 22:35:40 +0800607 if (inet_aton(localaddr_str, &localaddr) == 0) {
608 error_setg(errp, "localaddr '%s' is not a valid IPv4 address",
609 localaddr_str);
Mike Ryan3a75e742010-12-01 11:16:47 -0800610 return -1;
Mao Zhongyi0522a952017-09-04 22:35:40 +0800611 }
Mike Ryan3a75e742010-12-01 11:16:47 -0800612 param_localaddr = &localaddr;
613 } else {
614 param_localaddr = NULL;
615 }
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000616
Mao Zhongyi0522a952017-09-04 22:35:40 +0800617 fd = net_socket_mcast_create(&saddr, param_localaddr, errp);
Mao Zhongyic37f0bb2017-09-04 22:35:38 +0800618 if (fd < 0) {
Stefan Hajnoczi842480d2011-12-07 15:01:48 +0000619 return -1;
Mao Zhongyic37f0bb2017-09-04 22:35:38 +0800620 }
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000621
Mao Zhongyi0522a952017-09-04 22:35:40 +0800622 s = net_socket_fd_init(peer, model, name, fd, 0, NULL, errp);
Mao Zhongyic37f0bb2017-09-04 22:35:38 +0800623 if (!s) {
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000624 return -1;
Mao Zhongyic37f0bb2017-09-04 22:35:38 +0800625 }
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000626
627 s->dgram_dst = saddr;
628
Mark McLoughlin564f63e2009-11-25 18:49:08 +0000629 snprintf(s->nc.info_str, sizeof(s->nc.info_str),
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000630 "socket: mcast=%s:%d",
631 inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port));
632 return 0;
633
634}
635
Stefan Hajnoczi4e68f7a2012-07-24 16:35:13 +0100636static int net_socket_udp_init(NetClientState *peer,
Benjamin0e0e7fa2012-01-11 09:20:54 +0900637 const char *model,
638 const char *name,
639 const char *rhost,
Mao Zhongyi0522a952017-09-04 22:35:40 +0800640 const char *lhost,
641 Error **errp)
Benjamin0e0e7fa2012-01-11 09:20:54 +0900642{
643 NetSocketState *s;
Sebastian Ottlikbcbe92f2013-10-02 12:23:14 +0200644 int fd, ret;
Benjamin0e0e7fa2012-01-11 09:20:54 +0900645 struct sockaddr_in laddr, raddr;
646
Mao Zhongyi0522a952017-09-04 22:35:40 +0800647 if (parse_host_port(&laddr, lhost, errp) < 0) {
Benjamin0e0e7fa2012-01-11 09:20:54 +0900648 return -1;
649 }
650
Mao Zhongyi0522a952017-09-04 22:35:40 +0800651 if (parse_host_port(&raddr, rhost, errp) < 0) {
Benjamin0e0e7fa2012-01-11 09:20:54 +0900652 return -1;
653 }
654
655 fd = qemu_socket(PF_INET, SOCK_DGRAM, 0);
656 if (fd < 0) {
Mao Zhongyi0522a952017-09-04 22:35:40 +0800657 error_setg_errno(errp, errno, "can't create datagram socket");
Benjamin0e0e7fa2012-01-11 09:20:54 +0900658 return -1;
659 }
Sebastian Ottlikbcbe92f2013-10-02 12:23:14 +0200660
661 ret = socket_set_fast_reuse(fd);
Benjamin0e0e7fa2012-01-11 09:20:54 +0900662 if (ret < 0) {
Mao Zhongyi0522a952017-09-04 22:35:40 +0800663 error_setg_errno(errp, errno,
664 "can't set socket option SO_REUSEADDR");
Benjamin0e0e7fa2012-01-11 09:20:54 +0900665 closesocket(fd);
666 return -1;
667 }
668 ret = bind(fd, (struct sockaddr *)&laddr, sizeof(laddr));
669 if (ret < 0) {
Mao Zhongyi0522a952017-09-04 22:35:40 +0800670 error_setg_errno(errp, errno, "can't bind ip=%s to socket",
671 inet_ntoa(laddr.sin_addr));
Benjamin0e0e7fa2012-01-11 09:20:54 +0900672 closesocket(fd);
673 return -1;
674 }
Stefan Hajnoczifc13fa02013-03-27 10:10:44 +0100675 qemu_set_nonblock(fd);
Benjamin0e0e7fa2012-01-11 09:20:54 +0900676
Mao Zhongyi0522a952017-09-04 22:35:40 +0800677 s = net_socket_fd_init(peer, model, name, fd, 0, NULL, errp);
Benjamin0e0e7fa2012-01-11 09:20:54 +0900678 if (!s) {
679 return -1;
680 }
681
682 s->dgram_dst = raddr;
683
684 snprintf(s->nc.info_str, sizeof(s->nc.info_str),
685 "socket: udp=%s:%d",
686 inet_ntoa(raddr.sin_addr), ntohs(raddr.sin_port));
687 return 0;
688}
689
Kővágó, Zoltáncebea512016-07-13 21:50:12 -0600690int net_init_socket(const Netdev *netdev, const char *name,
Markus Armbrustera30ecde2015-05-15 13:58:50 +0200691 NetClientState *peer, Error **errp)
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000692{
Laszlo Ersekbef8e8f2012-07-17 16:17:17 +0200693 const NetdevSocketOptions *sock;
694
Eric Blakef394b2e2016-07-13 21:50:23 -0600695 assert(netdev->type == NET_CLIENT_DRIVER_SOCKET);
696 sock = &netdev->u.socket;
Laszlo Ersekbef8e8f2012-07-17 16:17:17 +0200697
Jens Freimannff86d572017-09-27 17:21:18 +0200698 if (sock->has_fd + sock->has_listen + sock->has_connect + sock->has_mcast +
699 sock->has_udp != 1) {
Mao Zhongyi0522a952017-09-04 22:35:40 +0800700 error_setg(errp, "exactly one of listen=, connect=, mcast= or udp="
701 " is required");
Laszlo Ersekbef8e8f2012-07-17 16:17:17 +0200702 return -1;
703 }
704
705 if (sock->has_localaddr && !sock->has_mcast && !sock->has_udp) {
Mao Zhongyi0522a952017-09-04 22:35:40 +0800706 error_setg(errp, "localaddr= is only valid with mcast= or udp=");
Laszlo Ersekbef8e8f2012-07-17 16:17:17 +0200707 return -1;
708 }
709
710 if (sock->has_fd) {
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000711 int fd;
712
Mao Zhongyi0522a952017-09-04 22:35:40 +0800713 fd = monitor_fd_param(cur_mon, sock->fd, errp);
Stefan Hajnoczifc13fa02013-03-27 10:10:44 +0100714 if (fd == -1) {
715 return -1;
716 }
717 qemu_set_nonblock(fd);
Mao Zhongyic37f0bb2017-09-04 22:35:38 +0800718 if (!net_socket_fd_init(peer, "socket", name, fd, 1, sock->mcast,
719 errp)) {
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000720 return -1;
721 }
Laszlo Ersekbef8e8f2012-07-17 16:17:17 +0200722 return 0;
723 }
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000724
Laszlo Ersekbef8e8f2012-07-17 16:17:17 +0200725 if (sock->has_listen) {
Mao Zhongyi0522a952017-09-04 22:35:40 +0800726 if (net_socket_listen_init(peer, "socket", name, sock->listen, errp)
727 < 0) {
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000728 return -1;
729 }
Laszlo Ersekbef8e8f2012-07-17 16:17:17 +0200730 return 0;
731 }
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000732
Laszlo Ersekbef8e8f2012-07-17 16:17:17 +0200733 if (sock->has_connect) {
Mao Zhongyi0522a952017-09-04 22:35:40 +0800734 if (net_socket_connect_init(peer, "socket", name, sock->connect, errp)
735 < 0) {
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000736 return -1;
737 }
Laszlo Ersekbef8e8f2012-07-17 16:17:17 +0200738 return 0;
739 }
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000740
Laszlo Ersekbef8e8f2012-07-17 16:17:17 +0200741 if (sock->has_mcast) {
742 /* if sock->localaddr is missing, it has been initialized to "all bits
743 * zero" */
Stefan Hajnoczid33d93b2012-07-24 16:35:05 +0100744 if (net_socket_mcast_init(peer, "socket", name, sock->mcast,
Mao Zhongyi0522a952017-09-04 22:35:40 +0800745 sock->localaddr, errp) < 0) {
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000746 return -1;
747 }
Laszlo Ersekbef8e8f2012-07-17 16:17:17 +0200748 return 0;
749 }
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000750
Laszlo Ersekbef8e8f2012-07-17 16:17:17 +0200751 assert(sock->has_udp);
752 if (!sock->has_localaddr) {
Mao Zhongyi0522a952017-09-04 22:35:40 +0800753 error_setg(errp, "localaddr= is mandatory with udp=");
Laszlo Ersekbef8e8f2012-07-17 16:17:17 +0200754 return -1;
755 }
Mao Zhongyi0522a952017-09-04 22:35:40 +0800756 if (net_socket_udp_init(peer, "socket", name, sock->udp, sock->localaddr,
757 errp) < 0) {
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000758 return -1;
759 }
Mark McLoughlin42281ac2009-11-25 18:48:56 +0000760 return 0;
761}