From: "Jim C. Brown" <jma5@umd.edu>
To: qemu-devel@nongnu.org
Subject: Re: [Qemu-devel] Connecting vde and LAN
Date: Mon, 11 Jul 2005 11:02:04 -0400 [thread overview]
Message-ID: <20050711150204.GA7933@jbrown.mylinuxbox.org> (raw)
In-Reply-To: <Pine.LNX.4.61.0507110646340.12555@filer.marasystems.com>
[-- Attachment #1: Type: text/plain, Size: 1545 bytes --]
On Mon, Jul 11, 2005 at 09:50:11AM +0200, Henrik Nordstrom wrote:
> On Sun, 10 Jul 2005, Jim C. Brown wrote:
>
> I didn't mean to implement this in qemu directly, but rather in a helper
> similar to vdeq, but the primary method should be via vde_switch. Having
> this shortcut helper is a future extension.
>
Ooooh! Like slirpvde.
> Inspired by this discussion I now have a prototype vde_packet glue for
> vde_switch at http://www.henriknordstrom.net/examples/vde_packet.c,
> connecting the vde_switch to the LAN via a packet socket.
>
Excellent work! I've attached a modified version called vde_pcap.c, which
uses libpcap to do the dirty work instead. I haven't gotten all the linuxisms
out of it yet, but it should be easy to fix. One day, this might run on Windows
hosts.
>
> b) can't talk to the host itself. This is due to the packets going
> directly to the wire and never really "seen" by the host stack. Not sure
> yet if there is an easy way out, but I suppose it may be possible to set
> up a dummy tap with the same MAC and IP address as the base Ethernet
> device and duplicate broadcasts and packet directed to the host there,
> obviously assuming the administrator does not block this in firewalling..
>
> Regards
> Henrik
>
Alas, the accepted solution to allow pcap programs to talk to the host is to
use tuntap to create a tap device and connect the program to the tap device
instead of the real ethernet device.
--
Infinite complexity begets infinite beauty.
Infinite precision begets infinite perfection.
[-- Attachment #2: vde_pcap.c --]
[-- Type: text/plain, Size: 4958 bytes --]
/* Copyright (C) 2005 Jim Brown
* Copyright (C) 2005 Henrik Nordstrom
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
*
* The VDE connection setup (open_vde) is loosely based on a similar
* functions in vdeq.c by Renzo Davoli
*/
#include <sys/socket.h>
#include <netpacket/packet.h>
#include <net/ethernet.h> /* the L2 protocols */
#include <sys/ioctl.h>
#include <fcntl.h>
#include <net/if.h>
#include <net/if_arp.h>
#include <sys/un.h>
#include <errno.h>
#include <linux/if_tun.h>
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <stdlib.h>
#include <pcap.h>
#define SWITCH_MAGIC 0xfeedface
#define BUFSIZE 2048
#define ETH_ALEN 6
#define PCAP_READ_TIMEOUT 1
enum request_type {
REQ_NEW_CONTROL
};
struct request_v3 {
uint32_t magic;
uint32_t version;
enum request_type type;
struct sockaddr_un sock;
};
static int
open_vde(char *name, int intno, int group)
{
int pid = getpid();
struct request_v3 req;
int fdctl;
int fddata;
struct sockaddr_un sock;
if ((fdctl = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
perror("socket");
exit(1);
}
sock.sun_family = AF_UNIX;
snprintf(sock.sun_path, sizeof(sock.sun_path), "%s", name);
if (connect(fdctl, (struct sockaddr *) &sock, sizeof(sock))) {
perror("connect");
exit(1);
}
memset(&req, 0, sizeof(req));
req.magic = SWITCH_MAGIC;
req.version = 3;
req.type = REQ_NEW_CONTROL + ((group > 0) ? ((geteuid() << 8) + group) << 8 : 0);
req.sock.sun_family = AF_UNIX;
sprintf(&req.sock.sun_path[1], "%5d-%2d", pid, intno);
if ((fddata = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0) {
perror("socket");
exit(1);
}
if (bind(fddata, (struct sockaddr *) &req.sock, sizeof(req.sock)) < 0) {
perror("bind");
exit(1);
}
if (send(fdctl, &req, sizeof(req), 0) < 0) {
perror("send");
exit(1);
}
if (recv(fdctl, &sock, sizeof(struct sockaddr_un), 0) < 0) {
perror("recv");
exit(1);
}
if (connect(fddata, (struct sockaddr *) &sock, sizeof(struct sockaddr_un)) < 0) {
perror("connect");
exit(1);
}
/* note: fdctl is intentionally leaked. Closed on exit by the OS. */
return fddata;
}
void
set_nonblocking(int fd)
{
int fl = fcntl(fd, F_GETFL);
fcntl(fd, F_SETFL, (fl | O_NONBLOCK));
}
void
pcap_relay(u_char *args, const struct pcap_pkthdr *header, const u_char * packet)
{
int * vde_socket = (int *)args;
send(*vde_socket, packet, header->len, 0);
}
static void
wrap_dispatch(fd_set * rfd, pcap_t * handle, int vde_socket)
{
int n;
if (FD_ISSET(pcap_get_selectable_fd(handle), rfd)) {
n = pcap_dispatch(handle, -1, pcap_relay, (u_char *)&vde_socket);
}
}
int pcap_sendpacket(pcap_t * handle, const u_char * packet, int len)
{
if (send(pcap_fileno(handle), packet, len, 0) == len)
{
return 0;
}
else
{
return -1;
}
}
static void
relay(fd_set * rfd, int vde_socket, pcap_t * handle)
{
int n;
char packet[65536];
union {
struct sockaddr_ll ll;
struct sockaddr_un un;
} sa;
socklen_t sa_len = sizeof(sa);
if (FD_ISSET(vde_socket, rfd)) {
n = recvfrom(vde_socket, packet, sizeof(packet), 0, (struct sockaddr *)&sa, &sa_len);
if (n > 0)
pcap_sendpacket(handle, packet, n);
else if (n == 0)
exit(1);
else if (errno != EINTR) {
perror("recv:");
exit(1);
}
}
}
int
main(int argc, char **argv)
{
int vde_socket;
pcap_t * handle;
char errbuf[PCAP_ERRBUF_SIZE];
const u_char * packet;
fd_set rfd;
int fds;
if (argc != 3) {
printf("Usage: %s interface vde_socket\n", argv[0]);
exit(1);
}
handle = pcap_open_live(argv[1], BUFSIZ, 1, PCAP_READ_TIMEOUT, errbuf);
if (handle == NULL)
{
printf("%s\n", errbuf);
exit(1);
}
vde_socket = open_vde(argv[2], 0, 0);
set_nonblocking(vde_socket);
fds = pcap_get_selectable_fd(handle);
if (vde_socket > fds)
fds = vde_socket;
fds += 1;
FD_ZERO(&rfd);
int i;
for (;;) {
int n;
FD_SET(pcap_get_selectable_fd(handle), &rfd);
FD_SET(vde_socket, &rfd);
n = select(fds, &rfd, NULL, NULL, NULL);
if (n > 0) {
wrap_dispatch(&rfd, handle, vde_socket);
relay(&rfd, vde_socket, handle);
} else if (n < 0 && errno != EINTR) {
perror("select:");
}
}
}
next prev parent reply other threads:[~2005-07-11 15:07 UTC|newest]
Thread overview: 29+ messages / expand[flat|nested] mbox.gz Atom feed top
2005-07-10 12:27 [Qemu-devel] Connecting vde and LAN Oliver Gerlich
2005-07-10 16:42 ` Henrik Nordstrom
2005-07-10 17:37 ` Jim C. Brown
2005-07-10 18:23 ` Oliver Gerlich
2005-07-10 18:58 ` Jim C. Brown
2005-07-11 2:21 ` Henrik Nordstrom
2005-07-11 2:33 ` Jim C. Brown
2005-07-11 7:50 ` Henrik Nordstrom
2005-07-11 15:02 ` Jim C. Brown [this message]
2005-07-11 23:01 ` Jim C. Brown
2005-07-12 2:49 ` Henrik Nordstrom
2005-07-12 22:25 ` Jim C. Brown
2005-08-04 10:14 ` Henrik Nordstrom
2005-08-05 16:54 ` Jim C. Brown
2005-08-10 19:07 ` Jim C. Brown
2005-08-11 14:56 ` Henrik Nordstrom
2005-08-11 16:24 ` Oliver Gerlich
2005-08-11 16:56 ` Jim C. Brown
2005-08-12 10:02 ` Henrik Nordstrom
2005-08-12 18:07 ` Jim C. Brown
2005-08-11 17:00 ` Paul Brook
2005-08-12 0:11 ` Herbert Poetzl
2005-08-12 9:53 ` Henrik Nordstrom
2005-07-10 17:48 ` Oliver Gerlich
2005-07-11 1:36 ` Henrik Nordstrom
2005-07-12 19:43 ` Ross Kendall Axe
2005-07-12 20:31 ` Oliver Gerlich
2005-07-13 3:02 ` Ross Kendall Axe
2005-07-10 18:27 ` Bakul Shah
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20050711150204.GA7933@jbrown.mylinuxbox.org \
--to=jma5@umd.edu \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.