Hello,
This is a simple patch for uml tools with a program (uml_dump) which can
connect to instance of uml_switch and then dump packets in cap format.
Very useful to see communications between uml instances in wireshark or
tcpdump.
Cheers,
Julien, Benoit and Jean-paul.
diff -rupN tools-original/Makefile tools/Makefile
--- tools-original/Makefile 2004-04-08 03:42:59.000000000 +0200
+++ tools/Makefile 2009-05-01 23:31:00.106571852 +0200
@@ -1,7 +1,7 @@
TUNCTL = $(shell [ -e /usr/include/linux/if_tun.h ] && echo tunctl)
SUBDIRS = jail jailtest humfsify mconsole moo port-helper $(TUNCTL) uml_net \
- uml_router watchdog
+ uml_router watchdog uml_dump
UMLVER = $(shell date +%Y%m%d)
TARBALL = uml_utilities_$(UMLVER).tar
BIN_DIR = /usr/bin
diff -rupN tools-original/uml_dump/Makefile tools/uml_dump/Makefile
--- tools-original/uml_dump/Makefile 1970-01-01 01:00:00.000000000 +0100
+++ tools/uml_dump/Makefile 2009-05-01 23:31:15.860900482 +0200
@@ -0,0 +1,17 @@
+OBJS = uml_dump.o
+BIN = uml_dump
+CFLAGS = -g -Wall
+
+BIN_DIR ?= /usr/bin
+
+all : $(BIN)
+
+$(BIN) : $(OBJS)
+ $(CC) $(CFLAGS) -o $(BIN) $(OBJS)
+
+clean :
+ rm -f $(BIN) $(OBJS) *~
+
+install : $(BIN)
+ install -d $(DESTDIR)$(BIN_DIR)
+ install -s $(BIN) $(DESTDIR)$(BIN_DIR)
diff -rupN tools-original/uml_dump/uml_dump.c tools/uml_dump/uml_dump.c
--- tools-original/uml_dump/uml_dump.c 1970-01-01 01:00:00.000000000 +0100
+++ tools/uml_dump/uml_dump.c 2009-05-17 13:42:58.692577826 +0200
@@ -0,0 +1,276 @@
+/*
+ * Copyright 2008
+ * Authors:
+ * - Julien Iguchi-Cartigny
+ * - Jean-Baptiste Machemie
+ * - Benoit Bitarelle
+ * Licensed under the GPL
+ *
+ * TODO: receive packets from multiple uml switchs
+ *
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/socket.h>
+#include <sys/poll.h>
+#include <sys/time.h>
+#include <sys/un.h>
+#include <unistd.h>
+#include <signal.h>
+#include <stdio.h>
+
+#include "../uml_router/switch.h"
+#include "../uml_router/uml_switch.h"
+#include "../uml_router/port.h"
+
+/***************** PCAP Part *****************/
+
+int output_fd;
+
+unsigned char pcap_file_header[] = {
+ 0xd4, 0xc3, 0xb2, 0Xa1, // magic number
+ 0x02, 0x00, 0x04, 0x00, // major and minor version number: 2.4
+ 0x00, 0x00, 0x00, 0x00, // thiszone: GMT
+ 0x00, 0x00, 0x00, 0x00, // accuracy: 0
+ 0xEA, 0x05, 0x00, 0x00, // max length of captured packet: 1514
+ 0x01, 0x00, 0x00, 0x00 // data link type: ethernet
+};
+
+unsigned int pcap_packet_header[] = {
+ 0, // timestamp second
+ 0, // timestamp microsecond
+ 0, // number of octets of packet saved in file
+ 0 // actual length of packet
+};
+
+struct timeval tv;
+
+void dump_packet(struct packet *packet, int size) {
+
+ int w;
+
+ gettimeofday(&tv, (void*)0);
+
+ pcap_packet_header[0] = tv.tv_sec;
+ pcap_packet_header[1] = tv.tv_usec;
+ pcap_packet_header[2] = size;
+ pcap_packet_header[3] = size;
+
+ w = fwrite(pcap_packet_header, sizeof(unsigned char),
+ sizeof(pcap_packet_header), stdout);
+
+ if(w<=0)
+ perror("error when writing packet header to stdout");
+
+ w = fwrite((unsigned char*)packet, sizeof(unsigned char), size, stdout);
+
+ if(w<=0)
+ perror("error when writing packet data to stdout");
+
+ w = fflush(stdout);
+
+ if(w!=0)
+ perror("error flushing stdout");
+}
+
+/***************** UML Part *****************/
+
+static char *prog;
+
+static char *ctl_socket = "/tmp/uml.ctl";
+
+int connect_fd, data_out_fd, data_in_fd;
+
+void cleanup() {
+ close(connect_fd);
+ close(data_out_fd);
+}
+
+static void sig_handler(int sig)
+{
+ fprintf(stderr,"Caught signal %d, cleaning up and exiting\n", sig);
+ cleanup();
+ signal(sig, SIG_DFL);
+ kill(getpid(), sig);
+}
+
+static void usage(void)
+{
+ fprintf(stderr, "Usage : %s control-socket\n"
+ "if no parameter %s is used as control socket\n",
+ prog, ctl_socket);
+ exit(1);
+}
+
+
+int main(int argc, char *argv[]) {
+
+ prog = argv[0];
+ argv++;
+ argc--;
+
+ /* parameter -help */
+ if(argc == 1) {
+
+ if(!strcmp(argv[0], "-help")){
+ usage();
+ }
+
+ ctl_socket = argv[0];
+ }
+
+ if(argc > 1) {
+ usage();
+ }
+
+ /* ask for the data in socket */
+ if((data_in_fd = socket(PF_UNIX, SOCK_DGRAM, 0)) < 0){
+ perror("socket");
+ exit(1);
+ }
+
+ if(fcntl(data_in_fd, F_SETFL, O_NONBLOCK) < 0){
+ perror("setting O_NONBLOCK on data in fd");
+ exit(1);
+ }
+
+ /* prepare the data in structure */
+ struct sockaddr_un data_in_sun;
+
+ struct {
+ char zero;
+ int pid;
+ int usecs;
+ } name;
+
+ struct timeval tv;
+
+ name.zero = 0;
+ name.pid = getpid();
+ gettimeofday(&tv, NULL);
+ name.usecs = tv.tv_usec;
+
+ data_in_sun.sun_family = AF_UNIX;
+ memcpy(data_in_sun.sun_path, &name, sizeof(name));
+
+ /* bind data_in_socket */
+ if(bind(data_in_fd, (struct sockaddr*) &data_in_sun,
+ sizeof(data_in_sun)) < 0){
+ perror("binding to data in socket");
+ exit(1);
+ }
+
+ /* ask for the connect socket */
+ if((connect_fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0){
+ perror("socket connect");
+ exit(1);
+ }
+
+ /* start the connect socket */
+ struct sockaddr_un connect_sun;
+
+ connect_sun.sun_family = AF_UNIX;
+ strncpy(connect_sun.sun_path, ctl_socket, sizeof(connect_sun.sun_path));
+
+ if(connect(connect_fd, (struct sockaddr *)&connect_sun,
+ sizeof(connect_sun)) < 0){
+ perror("connect connect");
+ fprintf(stderr,"check the path to control socket: %s\n", ctl_socket);
+ exit(1);
+ }
+
+ /* prepare the request */
+ struct request_v3 request;
+ request.magic = 0xfeedface;
+ request.version = 3;
+ request.type = REQ_NEW_DUMP;
+ request.sock = data_in_sun;
+
+ int n;
+
+ /* send the request */
+ n = send(connect_fd, &request, sizeof(request), 0);
+
+ if(n < sizeof(request)) {
+ fprintf(stderr,"not enough byte sent or error: %d\n", n);
+ exit(1);
+ }
+
+ /* receive the data out socket addr (we don't really care about it) */
+ struct sockaddr_un data_out_sun;
+
+ n = recv(connect_fd, &data_out_sun, sizeof(data_out_sun), 0);
+
+ if(n < sizeof(data_out_sun)) {
+ fprintf(stderr,"not enough byte received or error: %d\n", n);
+ exit(1);
+ }
+
+ /* prepare the pool */
+ struct pollfd p[2];
+
+ p[0].fd = connect_fd;
+ p[0].events = POLLIN;
+ p[1].fd = data_in_fd;
+ p[1].events = POLLIN;
+
+ /* setup the signal handler for CTRL-C */
+ if(signal(SIGINT, sig_handler) < 0)
+ perror("Setting handler for SIGINT");
+
+ /* setup the signal handler for closed pipe by reader */
+ if(signal(SIGPIPE, sig_handler) < 0)
+ perror("Setting handler for SIGPIPE");
+
+ /* writing pcap header to stdout */
+ int w = fwrite(pcap_file_header, sizeof(unsigned char),
+ sizeof(pcap_file_header), stdout);
+
+ if(w<=0)
+ perror("error when writing cap header to stdout");
+
+ struct packet packet;
+
+ /* the main loop */
+ while(1) {
+
+ /* waiting */
+ n = poll(p, 2, -1);
+
+ if(n < 0){
+ if(errno == EINTR) continue; /* if poll stop by a signal */
+ perror("poll");
+ break;
+ }
+
+ /* check control socket */
+ if(p[0].revents) {
+ if(p[0].revents & POLLHUP){
+ fprintf(stderr,"uml_switch disconnected\n");
+ break;
+ } else {
+ fprintf(stderr,"control packet in excess ?\n");
+ exit(1);
+ }
+ }
+
+ /* check data out socket */
+ if(p[1].revents) {
+
+ n = recv(data_in_fd, &packet, sizeof(packet), 0);
+ if(n < 0 && errno != EAGAIN) {
+ perror("recv data out socket\n");
+ exit(1);
+ }
+
+ dump_packet(&packet,n);
+ }
+ }
+
+ cleanup();
+
+ return 0;
+}
diff -rupN tools-original/uml_router/Makefile tools/uml_router/Makefile
--- tools-original/uml_router/Makefile 2003-02-19 01:16:27.000000000 +0100
+++ tools/uml_router/Makefile 2009-05-01 23:31:20.088977298 +0200
@@ -1,6 +1,6 @@
TUNTAP = $(shell [ -e /usr/include/linux/if_tun.h ] && echo -DTUNTAP)
-OBJS = hash.o port.o uml_switch.o
+OBJS = hash.o port.o uml_switch.o
BIN = uml_switch
CFLAGS = -g -Wall $(TUNTAP)
diff -rupN tools-original/uml_router/port.c tools/uml_router/port.c
--- tools-original/uml_router/port.c 2003-03-12 17:35:03.000000000 +0100
+++ tools/uml_router/port.c 2009-05-01 23:31:20.593666238 +0200
@@ -8,25 +8,6 @@
#include "hash.h"
#include "port.h"
-struct packet {
- struct {
- unsigned char dest[ETH_ALEN];
- unsigned char src[ETH_ALEN];
- unsigned char proto[2];
- } header;
- unsigned char data[1500];
-};
-
-struct port {
- struct port *next;
- struct port *prev;
- int control;
- void *data;
- int data_len;
- unsigned char src[ETH_ALEN];
- void (*sender)(int fd, void *packet, int len, void *data);
-};
-
static struct port *head = NULL;
#define IS_BROADCAST(addr) ((addr[0] & 1) == 1)
@@ -107,7 +88,16 @@ static void send_dst(struct port *port,
(*p->sender)(p->control, packet, len, p->data);
}
}
- else (*target->sender)(target->control, packet, len, target->data);
+ else {
+
+ /* looking for dump port */
+ for(p = head; p != NULL; p = p->next){
+ if(p == port) continue;
+ if(p->dump)
+ (*p->sender)(p->control, packet, len, p->data);
+ }
+ (*target->sender)(target->control, packet, len, target->data);
+ }
}
static void handle_data(int fd, int hub, struct packet *packet, int len,
@@ -149,7 +139,7 @@ void handle_tap_data(int fd, int hub)
}
int setup_port(int fd, void (*sender)(int fd, void *packet, int len,
- void *data), void *data, int data_len)
+ void *data), void *data, int data_len, int dump)
{
struct port *port;
@@ -165,6 +155,7 @@ int setup_port(int fd, void (*sender)(in
port->data = data;
port->data_len = data_len;
port->sender = sender;
+ port->dump = dump;
head = port;
printf("New connection\n");
return(0);
@@ -215,7 +206,7 @@ void handle_sock_data(int fd, int hub)
handle_data(fd, hub, &packet, len, &data, match_sock);
}
-int setup_sock_port(int fd, struct sockaddr_un *name, int data_fd)
+int setup_sock_port(int fd, struct sockaddr_un *name, int data_fd, int dump)
{
struct sock_data *data;
@@ -226,7 +217,7 @@ int setup_sock_port(int fd, struct socka
}
*data = ((struct sock_data) { fd : data_fd,
sock : *name });
- return(setup_port(fd, send_sock, data, sizeof(*data)));
+ return(setup_port(fd, send_sock, data, sizeof(*data), dump));
}
static void service_port(struct port *port)
@@ -235,9 +226,12 @@ static void service_port(struct port *po
char c;
n = read(port->control, &c, sizeof(c));
- if(n < 0) perror("Reading request");
- else if(n == 0) printf("Disconnect\n");
- else printf("Bad request\n");
+ if(n < 0)
+ perror("Reading request");
+ else if(n == 0)
+ printf("Disconnect\n");
+ else
+ printf("Bad request\n");
}
int handle_port(int fd)
@@ -252,4 +246,3 @@ int handle_port(int fd)
}
return(1);
}
-
diff -rupN tools-original/uml_router/port.h tools/uml_router/port.h
--- tools-original/uml_router/port.h 2002-04-10 22:08:09.000000000 +0200
+++ tools/uml_router/port.h 2009-05-01 23:31:20.717552166 +0200
@@ -8,12 +8,32 @@
#include <sys/socket.h>
#include <sys/un.h>
+struct packet {
+ struct {
+ unsigned char dest[ETH_ALEN];
+ unsigned char src[ETH_ALEN];
+ unsigned char proto[2];
+ } header;
+ unsigned char data[1500];
+};
+
+struct port {
+ struct port *next;
+ struct port *prev;
+ int control;
+ void *data;
+ int data_len;
+ unsigned char src[ETH_ALEN];
+ void (*sender)(int fd, void *packet, int len, void *data);
+ int dump;
+};
+
extern int handle_port(int fd);
extern void close_port(int fd);
-extern int setup_sock_port(int fd, struct sockaddr_un *name, int data_fd);
+extern int setup_sock_port(int fd, struct sockaddr_un *name, int data_fd, int dump);
extern int setup_port(int fd, void (*sender)(int fd, void *packet, int len,
void *data), void *data,
- int data_len);
+ int data_len, int dump);
extern void handle_tap_data(int fd, int hub);
extern void handle_sock_data(int fd, int hub);
diff -rupN tools-original/uml_router/tuntap.c tools/uml_router/tuntap.c
--- tools-original/uml_router/tuntap.c 2002-04-27 19:02:16.000000000 +0200
+++ tools/uml_router/tuntap.c 2009-05-01 23:31:21.088773438 +0200
@@ -6,6 +6,7 @@
#include <sys/ioctl.h>
#include <net/if.h>
#include <linux/if_tun.h>
+#include "switch.h"
#include "port.h"
static void send_tap(int fd, void *packet, int len, void *unused)
@@ -35,7 +36,7 @@ int open_tap(char *dev)
close(fd);
return(-1);
}
- err = setup_port(fd, send_tap, NULL, 0);
+ err = setup_port(fd, send_tap, NULL, 0, 0);
if(err) return(err);
return(fd);
}
diff -rupN tools-original/uml_router/uml_switch.c tools/uml_router/uml_switch.c
--- tools-original/uml_router/uml_switch.c 2003-09-03 22:16:32.000000000 +0200
+++ tools/uml_router/uml_switch.c 2009-05-01 23:31:21.665168486 +0200
@@ -7,9 +7,7 @@
#include <stdlib.h>
#include <signal.h>
#include <fcntl.h>
-#include <stdint.h>
#include <sys/socket.h>
-#include <sys/un.h>
#include <sys/poll.h>
#include <sys/time.h>
#include <unistd.h>
@@ -19,6 +17,7 @@
#ifdef TUNTAP
#include "tuntap.h"
#endif
+#include "uml_switch.h"
#ifdef notdef
#include <stddef.h>
@@ -26,58 +25,6 @@
static int hub = 0;
static int compat_v0 = 0;
-
-enum request_type { REQ_NEW_CONTROL };
-
-struct request_v0 {
- enum request_type type;
- union {
- struct {
- unsigned char addr[ETH_ALEN];
- struct sockaddr_un name;
- } new_control;
- } u;
-};
-
-#define SWITCH_MAGIC 0xfeedface
-
-struct request_v1 {
- uint32_t magic;
- enum request_type type;
- union {
- struct {
- unsigned char addr[ETH_ALEN];
- struct sockaddr_un name;
- } new_control;
- } u;
-};
-
-struct request_v2 {
- uint32_t magic;
- uint32_t version;
- enum request_type type;
- struct sockaddr_un sock;
-};
-
-struct reply_v2 {
- unsigned char mac[ETH_ALEN];
- struct sockaddr_un sock;
-};
-
-struct request_v3 {
- uint32_t magic;
- uint32_t version;
- enum request_type type;
- struct sockaddr_un sock;
-};
-
-union request {
- struct request_v0 v0;
- struct request_v1 v1;
- struct request_v2 v2;
- struct request_v3 v3;
-};
-
static char *ctl_socket = "/tmp/uml.ctl";
static char *data_socket = NULL;
@@ -149,7 +96,11 @@ static void new_port_v0(int fd, struct r
{
switch(req->type){
case REQ_NEW_CONTROL:
- setup_sock_port(fd, &req->u.new_control.name, data_fd);
+ setup_sock_port(fd, &req->u.new_control.name, data_fd, 0);
+ break;
+ case REQ_NEW_DUMP:
+ printf("REQ_NEW_DUMP for version 0 not supported\n");
+ close_descriptor(fd);
break;
default:
printf("Bad request type : %d\n", req->type);
@@ -164,7 +115,8 @@ static void new_port_v1_v3(int fd, enum
switch(type){
case REQ_NEW_CONTROL:
- err = setup_sock_port(fd, sock, data_fd);
+ case REQ_NEW_DUMP:
+ err = setup_sock_port(fd, sock, data_fd, (type == REQ_NEW_DUMP));
if(err) return;
n = write(fd, &data_sun, sizeof(data_sun));
if(n != sizeof(data_sun)){
@@ -203,14 +155,28 @@ static void new_port(int fd, int data_fd
return;
}
if(req.v1.magic == SWITCH_MAGIC){
- if(req.v2.version == 2) new_port_v2(fd, &req.v2, data_fd);
+
+ /* version 2*/
+ if(req.v2.version == 2)
+ new_port_v2(fd, &req.v2, data_fd);
+
+ /* version 3 */
if(req.v3.version == 3)
new_port_v1_v3(fd, req.v3.type, &req.v3.sock, data_fd);
+
+ /* version unknow */
else if(req.v2.version > 2)
fprintf(stderr, "Request for a version %d port, which this "
"uml_switch doesn't support\n", req.v2.version);
+
+ /* version 1 */
+ else if(req.v1.type == REQ_NEW_DUMP)
+ fprintf(stderr, "REQ_NEW_DUMP request for version 1, which this "
+ "uml_switch doesn't support\n");
else new_port_v1_v3(fd, req.v1.type, &req.v1.u.new_control.name, data_fd);
}
+
+ /* version 0*/
else new_port_v0(fd, &req.v0, data_fd);
}
@@ -528,6 +494,8 @@ int main(int argc, char **argv)
}
for(i = 0; i < nfds; i++){
if(fds[i].revents == 0) continue;
+
+ /* stdin */
if(fds[i].fd == 0){
if(fds[i].revents & POLLHUP){
printf("EOF on stdin, cleaning up and exiting\n");
diff -rupN tools-original/uml_router/uml_switch.h tools/uml_router/uml_switch.h
--- tools-original/uml_router/uml_switch.h 1970-01-01 01:00:00.000000000 +0100
+++ tools/uml_router/uml_switch.h 2009-05-01 23:31:21.784787672 +0200
@@ -0,0 +1,67 @@
+/* Copyright 2008 Jeff Dike & Kartoch
+ * Licensed under the GPL
+ */
+
+#ifndef __UML_SWITCH_H__
+#define __UML_SWITCH_H__
+
+#include <stdint.h>
+#include <sys/un.h>
+
+enum request_type {
+ REQ_NEW_CONTROL,
+ REQ_NEW_DUMP
+};
+
+struct request_v0 {
+ enum request_type type;
+ union {
+ struct {
+ unsigned char addr[ETH_ALEN];
+ struct sockaddr_un name;
+ } new_control;
+ } u;
+};
+
+#define SWITCH_MAGIC 0xfeedface
+
+struct request_v1 {
+ uint32_t magic;
+ enum request_type type;
+ union {
+ struct {
+ unsigned char addr[ETH_ALEN];
+ struct sockaddr_un name;
+ } new_control;
+ } u;
+};
+
+struct request_v2 {
+ uint32_t magic;
+ uint32_t version;
+ enum request_type type;
+ struct sockaddr_un sock;
+};
+
+struct reply_v2 {
+ unsigned char mac[ETH_ALEN];
+ struct sockaddr_un sock;
+};
+
+struct request_v3 {
+ uint32_t magic;
+ uint32_t version;
+ enum request_type type;
+ struct sockaddr_un sock;
+};
+
+union request {
+ struct request_v0 v0;
+ struct request_v1 v1;
+ struct request_v2 v2;
+ struct request_v3 v3;
+};
+
+#endif
+
+
------------------------------------------------------------------------------
Enter the BlackBerry Developer Challenge
This is your chance to win up to $100,000 in prizes! For a limited time,
vendors submitting new applications to BlackBerry App World(TM) will have
the opportunity to enter the BlackBerry Developer Challenge. See full prize
details at: http://p.sf.net/sfu/Challenge
_______________________________________________
User-mode-linux-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/user-mode-linux-devel