From 15d6a32b38abc6c2f8143ebccfcdd05d204f0fcd Mon Sep 17 00:00:00 2001 From: Benjamin Date: Sat, 8 Oct 2011 07:31:33 +0000 Subject: [PATCH 28/44] Integrating Dynamips and GNS3 UDP tunnels (Patches) On 10/07/11 10:35, Jan Kiszka wrote: > > You should send out the changes as proper patch series, rebased on > current git head. See http://wiki.qemu.org/Contribute/SubmitAPatch for > further requirements. And make sure that no patch breaks the build so > that bisectability is preserved. > > Jan > Tested and used for several years by GNS3, it doesn't break the build. I could not access http://git.qemu.org/qemu.git/plain/CODING_STYLE and http://git.qemu.org/qemu.git/plain/HACKING (404) so these patches may not be 100% conform. The script didn't report any error though. Signed-off-by: Benjamin MARSILI "-net tap[,vlan=n][,name=str],ifname=name\n" " connect the host TAP network interface to VLAN 'n'\n" ---- [agraf] I combined the upstream submitted mail header with the 0.14 Uli version of the patch. If this isn't upstream by 1.1, remove in the next round! --- Makefile.objs | 1 + block/raw-win32.c | 4 +- hw/e1000.c | 2 +- net.c | 25 ++++++++++ net.h | 1 + net/udp.c | 138 +++++++++++++++++++++++++++++++++++++++++++++++++++++ net/udp.h | 32 ++++++++++++ qemu-options.hx | 2 + 8 files changed, 202 insertions(+), 3 deletions(-) create mode 100644 net/udp.c create mode 100644 net/udp.h diff --git a/Makefile.objs b/Makefile.objs index d7a6539..1a28830 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -46,6 +46,7 @@ net-obj-y = net.o net-nested-y = queue.o checksum.o util.o net-nested-y += socket.o net-nested-y += dump.o +net-nested-y += udp.o net-nested-$(CONFIG_POSIX) += tap.o net-nested-$(CONFIG_LINUX) += tap-linux.o net-nested-$(CONFIG_WIN32) += tap-win32.o diff --git a/block/raw-win32.c b/block/raw-win32.c index e4b0b75..09528ac 100644 --- a/block/raw-win32.c +++ b/block/raw-win32.c @@ -97,7 +97,7 @@ static int raw_open(BlockDriverState *bs, const char *filename, int flags) if (!(flags & BDRV_O_CACHE_WB)) overlapped |= FILE_FLAG_WRITE_THROUGH; s->hfile = CreateFile(filename, access_flags, - FILE_SHARE_READ, NULL, + FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, overlapped, NULL); if (s->hfile == INVALID_HANDLE_VALUE) { int err = GetLastError(); @@ -387,7 +387,7 @@ static int hdev_open(BlockDriverState *bs, const char *filename, int flags) if (!(flags & BDRV_O_CACHE_WB)) overlapped |= FILE_FLAG_WRITE_THROUGH; s->hfile = CreateFile(filename, access_flags, - FILE_SHARE_READ, NULL, + FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, create_flags, overlapped, NULL); if (s->hfile == INVALID_HANDLE_VALUE) { int err = GetLastError(); diff --git a/hw/e1000.c b/hw/e1000.c index 986ed9c..19ca5bf 100644 --- a/hw/e1000.c +++ b/hw/e1000.c @@ -577,7 +577,7 @@ receive_filter(E1000State *s, const uint8_t *buf, int size) if (rctl & E1000_RCTL_UPE) // promiscuous return 1; - if ((buf[0] & 1) && (rctl & E1000_RCTL_MPE)) // promiscuous mcast + if ((buf[0] & 1)) //&& (rctl & E1000_RCTL_MPE)) // promiscuous mcast return 1; if ((rctl & E1000_RCTL_BAM) && !memcmp(buf, bcast, sizeof bcast)) diff --git a/net.c b/net.c index cb52050..dc1689c 100644 --- a/net.c +++ b/net.c @@ -30,6 +30,7 @@ #include "net/dump.h" #include "net/slirp.h" #include "net/vde.h" +#include "net/udp.h" #include "net/util.h" #include "monitor.h" #include "qemu-common.h" @@ -1031,6 +1032,29 @@ static const struct { }, }, #endif + + [NET_CLIENT_TYPE_UDP] = { + .type = "udp", + .init = net_init_udp, + .desc = { + NET_COMMON_PARAMS_DESC, + { + .name = "sport", + .type = QEMU_OPT_NUMBER, + + .help = "source port number", + }, { + .name = "daddr", + .type = QEMU_OPT_STRING, + .help = "destination IP address", + }, { + .name = "dport", + .type = QEMU_OPT_NUMBER, + .help = "destination port number", + }, + { /* end of list */ } + }, + }, [NET_CLIENT_TYPE_DUMP] = { .type = "dump", .init = net_init_dump, @@ -1348,6 +1372,7 @@ void net_check_clients(void) case NET_CLIENT_TYPE_USER: case NET_CLIENT_TYPE_TAP: case NET_CLIENT_TYPE_SOCKET: + case NET_CLIENT_TYPE_UDP: case NET_CLIENT_TYPE_VDE: has_host_dev = 1; break; diff --git a/net.h b/net.h index 9f633f8..ac6118c 100644 --- a/net.h +++ b/net.h @@ -35,6 +35,7 @@ typedef enum { NET_CLIENT_TYPE_TAP, NET_CLIENT_TYPE_SOCKET, NET_CLIENT_TYPE_VDE, + NET_CLIENT_TYPE_UDP, NET_CLIENT_TYPE_DUMP, NET_CLIENT_TYPE_MAX diff --git a/net/udp.c b/net/udp.c new file mode 100644 index 0000000..6080919 --- /dev/null +++ b/net/udp.c @@ -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; +} diff --git a/net/udp.h b/net/udp.h new file mode 100644 index 0000000..9e92852 --- /dev/null +++ b/net/udp.h @@ -0,0 +1,32 @@ +/* + * 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. + */ +#ifndef QEMU_NET_UDP_H +#define QEMU_NET_UDP_H + +#include "qemu-common.h" +#include "qemu-option.h" + +int net_init_udp(QemuOpts *opts, Monitor *mon, const char *name, VLANState *vlan); + +#endif /* QEMU_NET_UDP_H */ diff --git a/qemu-options.hx b/qemu-options.hx index 83b1f38..94f946e 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -1226,6 +1226,8 @@ DEF("net", HAS_ARG, QEMU_OPTION_net, "-net socket[,vlan=n][,name=str][,fd=h][,mcast=maddr:port[,localaddr=addr]]\n" " connect the vlan 'n' to multicast maddr and port\n" " use 'localaddr=addr' to specify the host address to send packets from\n" + "-net udp[,vlan=n]sport=sport,dport=dport,daddr=host\n" + " connect the vlan 'n' to a UDP tunnel (for Dynamips/GNS3)\n" #ifdef CONFIG_VDE "-net vde[,vlan=n][,name=str][,sock=socketpath][,port=n][,group=groupname][,mode=octalmode]\n" " connect the vlan 'n' to port 'n' of a vde switch running\n" -- 1.6.0.2