All of lore.kernel.org
 help / color / mirror / Atom feed
From: Julien Iguchi-Cartigny <julien.cartigny@unilim.fr>
To: user-mode-linux-devel@lists.sourceforge.net
Subject: [uml-devel] Support for dumping trafic in uml_switch
Date: Thu, 09 Jul 2009 19:30:31 +0200	[thread overview]
Message-ID: <4A562937.3090600@unilim.fr> (raw)

[-- Attachment #1: Type: text/plain, Size: 273 bytes --]

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.

[-- Attachment #2: uml_dump.patch --]
[-- Type: text/x-patch, Size: 17456 bytes --]

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
+
+

[-- Attachment #3: Type: text/plain, Size: 389 bytes --]

------------------------------------------------------------------------------
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

[-- Attachment #4: Type: text/plain, Size: 194 bytes --]

_______________________________________________
User-mode-linux-devel mailing list
User-mode-linux-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/user-mode-linux-devel

                 reply	other threads:[~2009-07-09 17:54 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

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=4A562937.3090600@unilim.fr \
    --to=julien.cartigny@unilim.fr \
    --cc=user-mode-linux-devel@lists.sourceforge.net \
    /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.