/* * QEMU System Emulator * * Copyright (c) 2003-2008 Fabrice Bellard * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "qemu/osdep.h" #include "net/net.h" #include "clients.h" #include "monitor/monitor.h" #include "qapi/error.h" #include "qemu-common.h" #include "qemu/error-report.h" #include "qemu/option.h" #include "qemu/sockets.h" #include "qemu/iov.h" #include "qemu/main-loop.h" typedef struct NetSocketState { NetClientState nc; int listen_fd; int fd; int state; /* 0 = getting length, 1 = getting data */ unsigned int index; unsigned int packet_len; unsigned int send_index; /* number of bytes sent (only SOCK_STREAM) */ uint8_t buf[NET_BUFSIZE]; struct sockaddr_in dgram_dst; /* contains inet host and port destination iff connectionless (SOCK_DGRAM) */ IOHandler *send_fn; /* differs between SOCK_STREAM/SOCK_DGRAM */ bool read_poll; /* waiting to receive data? */ bool write_poll; /* waiting to transmit data? */ } NetSocketState; static void net_socket_accept(void *opaque); static void net_socket_writable(void *opaque); static void net_socket_update_fd_handler(NetSocketState *s) { qemu_set_fd_handler(s->fd, s->read_poll ? s->send_fn : NULL, s->write_poll ? net_socket_writable : NULL, s); } static void net_socket_read_poll(NetSocketState *s, bool enable) { s->read_poll = enable; net_socket_update_fd_handler(s); } static void net_socket_write_poll(NetSocketState *s, bool enable) { s->write_poll = enable; net_socket_update_fd_handler(s); } static void net_socket_writable(void *opaque) { NetSocketState *s = opaque; net_socket_write_poll(s, false); qemu_flush_queued_packets(&s->nc); } static ssize_t net_socket_receive(NetClientState *nc, const uint8_t *buf, size_t size) { NetSocketState *s = DO_UPCAST(NetSocketState, nc, nc); uint32_t len = htonl(size); struct iovec iov[] = { { .iov_base = &len, .iov_len = sizeof(len), }, { .iov_base = (void *)buf, .iov_len = size, }, }; size_t remaining; ssize_t ret; remaining = iov_size(iov, 2) - s->send_index; ret = iov_send(s->fd, iov, 2, s->send_index, remaining); if (ret == -1 && errno == EAGAIN) { ret = 0; /* handled further down */ } if (ret == -1) { s->send_index = 0; return -errno; } if (ret < (ssize_t)remaining) { s->send_index += ret; net_socket_write_poll(s, true); return 0; } s->send_index = 0; return size; } static ssize_t net_socket_receive_dgram(NetClientState *nc, const uint8_t *buf, size_t size) { NetSocketState *s = DO_UPCAST(NetSocketState, nc, nc); ssize_t ret; do { ret = qemu_sendto(s->fd, buf, size, 0, (struct sockaddr *)&s->dgram_dst, sizeof(s->dgram_dst)); } while (ret == -1 && errno == EINTR); if (ret == -1 && errno == EAGAIN) { net_socket_write_poll(s, true); return 0; } return ret; } static void net_socket_send_completed(NetClientState *nc, ssize_t len) { NetSocketState *s = DO_UPCAST(NetSocketState, nc, nc); if (!s->read_poll) { net_socket_read_poll(s, true); } } static void net_socket_send(void *opaque) { NetSocketState *s = opaque; int size; unsigned l; uint8_t buf1[NET_BUFSIZE]; const uint8_t *buf; size = qemu_recv(s->fd, buf1, sizeof(buf1), 0); if (size < 0) { if (errno != EWOULDBLOCK) goto eoc; } else if (size == 0) { /* end of connection */ eoc: net_socket_read_poll(s, false); net_socket_write_poll(s, false); if (s->listen_fd != -1) { qemu_set_fd_handler(s->listen_fd, net_socket_accept, NULL, s); } closesocket(s->fd); s->fd = -1; s->state = 0; s->index = 0; s->packet_len = 0; s->nc.link_down = true; memset(s->buf, 0, sizeof(s->buf)); memset(s->nc.info_str, 0, sizeof(s->nc.info_str)); return; } buf = buf1; while (size > 0) { /* reassemble a packet from the network */ switch(s->state) { case 0: l = 4 - s->index; if (l > size) l = size; memcpy(s->buf + s->index, buf, l); buf += l; size -= l; s->index += l; if (s->index == 4) { /* got length */ s->packet_len = ntohl(*(uint32_t *)s->buf); s->index = 0; s->state = 1; } break;
#FIG 3.2
Landscape
Center
Inches
Letter  
100.00
Single
-2
1200 2
2 1 0 2 0 7 50 0 -1 0.000 0 0 -1 0 0 6
	 4200 3600 4200 3075 4950 2325 7425 2325 8250 3150 8250 3600
2 1 1 1 0 7 50 0 -1 4.000 0 0 -1 0 0 2
	 4200 3675 4200 5400
2 1 1 1 0 7 50 0 -1 4.000 0 0 -1 0 0 2
	 8250 3675 8250 5400
2 1 0 1 0 7 50 0 -1 4.000 0 0 -1 0 0 2
	 3675 3600 8700 3600
2 1 1 1 0 7 50 0 -1 4.000 0 0 -1 0 0 2
	 8775 3600 10200 3600
2 1 1 1 0 7 50 0 -1 4.000 0 0 -1 0 0 2
	 8325 3150 9075 3150
2 1 1 1 0 7 50 0 -1 4.000 0 0 -1 0 0 2
	 7500 2325 10200 2325
2 1 1 1 0 7 50 0 -1 4.000 0 0 -1 0 0 2
	 3600 3600 3000 3600
2 1 1 1 0 7 50 0 -1 4.000 0 0 -1 0 0 2
	 4125 3075 3000 3075
2 1 0 1 0 7 50 0 -1 4.000 0 0 -1 1 1 2
	0 0 1.00 60.00 120.00
	0 0 1.00 60.00 120.00
	 4200 5400 8175 5400
2 1 0 1 0 7 50 0 -1 4.000 0 0 -1 1 1 2
	0 0 1.00 60.00 120.00
	0 0 1.00 60.00 120.00
	 10125 2325 10125 3600
2 1 0 1 0 7 50 0 -1 4.000 0 0 -1 1 1 2
	0 0 1.00 60.00 120.00
	0 0 1.00 60.00 120.00
	 3000 3150 3000 3600
2 1 0 1 0 7 50 0 -1 4.000 0 0 -1 1 1 2
	0 0 1.00 60.00 120.00
	0 0 1.00 60.00 120.00
	 9075 3150 9075 3600
2 1 1 1 0 7 50 0 -1 4.000 0 0 -1 0 0 2
	 4950 2325 4950 1200
2 1 1 1 0 7 50 0 -1 4.000 0 0 -1 0 0 2
	 7425 2325 7425 1200
2 1 1 1 0 7 50 0 -1 4.000 0 0 -1 0 0 4
	 4200 3075 4200 2400 3600 1800 3600 1200
2 1 1 1 0 7 50 0 -1 4.000 0 0 -1 0 0 4
	 8250 3150 8250 2475 8775 1950 8775 1200
2 1 0 1 0 7 50 0 -1 4.000 0 0 -1 1 1 2
	0 0 1.00 60.00 120.00
	0 0 1.00 60.00 120.00
	 3600 1275 4950 1275
2 1 0 1 0 7 50 0 -1 4.000 0 0 -1 1 1 2
	0 0 1.00 60.00 120.00
	0 0 1.00 60.00 120.00
	 7425 1275 8700 1275
4 1 0 50 0 0 12 0.0000 4 135 1140 6075 5325 Effect duration\001
4 0 0 50 0 0 12 0.0000 4 180 1305 10200 3000 Effect magnitude\001
4 0 0 50 0 0 12 0.0000 4 135 780 9150 3450 Fade level\001
4 1 0 50 0 0 12 0.0000 4 180 1035 4275 1200 Attack length\001
4 1 0 50 0 0 12 0.0000 4 180 885 8175 1200 Fade length\001
4 2 0 50 0 0 12 0.0000 4 135 930 2925 3375 Attack level\001
ddr.sin_addr), ntohs(saddr.sin_port)); return 0; } static int net_socket_mcast_init(NetClientState *peer, const char *model, const char *name, const char *host_str, const char *localaddr_str) { NetSocketState *s; int fd; struct sockaddr_in saddr; struct in_addr localaddr, *param_localaddr; if (parse_host_port(&saddr, host_str) < 0) return -1; if (localaddr_str != NULL) { if (inet_aton(localaddr_str, &localaddr) == 0) return -1; param_localaddr = &localaddr; } else { param_localaddr = NULL; } fd = net_socket_mcast_create(&saddr, param_localaddr); if (fd < 0) return -1; s = net_socket_fd_init(peer, model, name, fd, 0); if (!s) return -1; s->dgram_dst = saddr; snprintf(s->nc.info_str, sizeof(s->nc.info_str), "socket: mcast=%s:%d", inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port)); return 0; } static int net_socket_udp_init(NetClientState *peer, const char *model, const char *name, const char *rhost, const char *lhost) { NetSocketState *s; int fd, ret; struct sockaddr_in laddr, raddr; if (parse_host_port(&laddr, lhost) < 0) { return -1; } if (parse_host_port(&raddr, rhost) < 0) { return -1; } fd = qemu_socket(PF_INET, SOCK_DGRAM, 0); if (fd < 0) { perror("socket(PF_INET, SOCK_DGRAM)"); return -1; } ret = socket_set_fast_reuse(fd); if (ret < 0) { closesocket(fd); return -1; } ret = bind(fd, (struct sockaddr *)&laddr, sizeof(laddr)); if (ret < 0) { perror("bind"); closesocket(fd); return -1; } qemu_set_nonblock(fd); s = net_socket_fd_init(peer, model, name, fd, 0); if (!s) { return -1; } s->dgram_dst = raddr; snprintf(s->nc.info_str, sizeof(s->nc.info_str), "socket: udp=%s:%d", inet_ntoa(raddr.sin_addr), ntohs(raddr.sin_port)); return 0; } int net_init_socket(const NetClientOptions *opts, const char *name, NetClientState *peer, Error **errp) { /* FIXME error_setg(errp, ...) on failure */ Error *err = NULL; const NetdevSocketOptions *sock; assert(opts->type == NET_CLIENT_OPTIONS_KIND_SOCKET); sock = opts->u.socket.data; if (sock->has_fd + sock->has_listen + sock->has_connect + sock->has_mcast + sock->has_udp != 1) { error_report("exactly one of fd=, listen=, connect=, mcast= or udp=" " is required"); return -1; } if (sock->has_localaddr && !sock->has_mcast && !sock->has_udp) { error_report("localaddr= is only valid with mcast= or udp="); return -1; } if (sock->has_fd) { int fd; fd = monitor_fd_param(cur_mon, sock->fd, &err); if (fd == -1) { error_report_err(err); return -1; } qemu_set_nonblock(fd); if (!net_socket_fd_init(peer, "socket", name, fd, 1)) { return -1; } return 0; } if (sock->has_listen) { if (net_socket_listen_init(peer, "socket", name, sock->listen) == -1) { return -1; } return 0; } if (sock->has_connect) { if (net_socket_connect_init(peer, "socket", name, sock->connect) == -1) { return -1; } return 0; } if (sock->has_mcast) { /* if sock->localaddr is missing, it has been initialized to "all bits * zero" */ if (net_socket_mcast_init(peer, "socket", name, sock->mcast, sock->localaddr) == -1) { return -1; } return 0; } assert(sock->has_udp); if (!sock->has_localaddr) { error_report("localaddr= is mandatory with udp="); return -1; } if (net_socket_udp_init(peer, "socket", name, sock->udp, sock->localaddr) == -1) { return -1; } return 0; }