--- qemu-0.14.1/net/udp.c.orig Thu Jun 23 17:09:02 2011 +++ qemu-0.14.1/net/udp.c Thu Jun 23 17:10:17 2011 @@ -0,0 +1,138 @@ +/* + * 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 "net/udp.h" + +#include "config-host.h" + +#ifndef _WIN32 +#include +#include +#include +#endif + +#include "net.h" +#include "qemu-char.h" +#include "qemu-common.h" +#include "qemu-option.h" +#include "qemu_socket.h" +#include "sysemu.h" + + +typedef struct UDPState { + VLANClientState nc; + int rfd; + struct sockaddr_in sender; +} UDPState; + +static void udp_to_qemu(void *opaque) +{ + UDPState *s = opaque; + uint8_t buf[4096]; + int size; + + size = recvfrom(s->rfd, (char *)buf, sizeof(buf), 0, NULL, NULL); + if (size > 0) { + qemu_send_packet(&s->nc, buf, size); + } +} + +static ssize_t udp_receive(VLANClientState *nc, const uint8_t *buf, size_t size) +{ + UDPState *s = DO_UPCAST(UDPState, nc, nc); + int ret; + + do { + ret = sendto(s->rfd, (const char *)buf, size, 0, (struct sockaddr *)&s->sender, sizeof (s->sender)); + } while (ret < 0 && errno == EINTR); + + return ret; +} + +static void udp_cleanup(VLANClientState *nc) +{ + UDPState *s = DO_UPCAST(UDPState, nc, nc); + qemu_set_fd_handler(s->rfd, NULL, NULL, NULL); + close(s->rfd); +} + +static NetClientInfo net_udp_info = { + .type = NET_CLIENT_TYPE_UDP, + .size = sizeof(UDPState), + .receive = udp_receive, + .cleanup = udp_cleanup, +}; + +static int net_udp_init(VLANState *vlan, const char *model, + const char *name, int sport, + const char *daddr, int dport) +{ + VLANClientState *nc; + UDPState *s; + struct sockaddr_in receiver; + int ret; + + nc = qemu_new_net_client(&net_udp_info, vlan, NULL, model, name); + + snprintf(nc->info_str, sizeof(nc->info_str),"udp: %i->%s:%i", + sport, daddr, dport); + + s = DO_UPCAST(UDPState, nc, nc); + + s->rfd = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP); + receiver.sin_family = AF_INET; + receiver.sin_addr.s_addr = INADDR_ANY; + receiver.sin_port = htons(sport); + ret = bind(s->rfd, (struct sockaddr *)&receiver, sizeof(receiver)); + + if (ret == -1) { + fprintf (stderr, "bind error:%s\n", strerror(errno)); + return ret; + } + + memset((char*)&s->sender, 0,sizeof(s->sender)); + s->sender.sin_family = AF_INET; + s->sender.sin_port = htons(dport); + inet_aton(daddr, &s->sender.sin_addr); + + qemu_set_fd_handler(s->rfd, udp_to_qemu, NULL, s); + + return 0; +} + +int net_init_udp(QemuOpts *opts, Monitor *mon, const char *name, VLANState *vlan) +{ + const char *daddr; + int sport, dport; + + daddr = qemu_opt_get(opts, "daddr"); + + sport = qemu_opt_get_number(opts, "sport", 0); + dport = qemu_opt_get_number(opts, "dport", 0); + + if (net_udp_init(vlan, "udp", name, sport, daddr, dport) == -1) { + return -1; + } + + return 0; +}