PERFORCE change 125282 for review

Matus Harvan mharvan at FreeBSD.org
Fri Aug 17 17:27:21 PDT 2007


http://perforce.freebsd.org/chv.cgi?CH=125282

Change 125282 by mharvan at mharvan_bike-planet on 2007/08/18 00:27:02

	multi-user support
		* daemon
		* tcp plugin
		* udp plugin
		* icmp plugin - almost

Affected files ...

.. //depot/projects/soc2007/mharvan-mtund/mtund.src/Makefile#9 edit
.. //depot/projects/soc2007/mharvan-mtund/mtund.src/mtund.c#3 edit
.. //depot/projects/soc2007/mharvan-mtund/mtund.src/mtund.h#2 edit
.. //depot/projects/soc2007/mharvan-mtund/mtund.src/plugin.h#6 edit
.. //depot/projects/soc2007/mharvan-mtund/mtund.src/plugin_icmp.c#9 edit
.. //depot/projects/soc2007/mharvan-mtund/mtund.src/plugin_tcp.c#11 edit
.. //depot/projects/soc2007/mharvan-mtund/mtund.src/plugin_udp.c#9 edit
.. //depot/projects/soc2007/mharvan-mtund/sys.patches/tcp_catchall/catchalld.c#2 delete
.. //depot/projects/soc2007/mharvan-mtund/sys.patches/tcp_catchall/dmesg_tail#2 delete
.. //depot/projects/soc2007/mharvan-mtund/sys.patches/tcp_catchall/sys.patch#4 delete
.. //depot/projects/soc2007/mharvan-mtund/sys.patches/tcp_catchall/usr.patch#2 delete

Differences ...

==== //depot/projects/soc2007/mharvan-mtund/mtund.src/Makefile#9 (text+ko) ====


==== //depot/projects/soc2007/mharvan-mtund/mtund.src/mtund.c#3 (text+ko) ====

@@ -10,12 +10,15 @@
  * > VTun - Virtual Tunnel over TCP/IP network.
  */
 
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/socket.h>
 #include <dlfcn.h>
-#include <sys/time.h>
 #include <event.h>
 #include <err.h>
 #include <fcntl.h>
 #include <getopt.h>
+#include <netdb.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -29,110 +32,129 @@
 //#include <stdarg.h>
 //#include <sys/types.h>
 
+/* max transfered unit - encapsulated packet size */
+#define MTU 1500
+/* how many pings can fail before the plugin is declared broken */
+#define PING_INTERVAL 2
+#define PING_FAIL_PLUGIN 3
+#define PING_FAIL_COMPLETE 10
+#define IDREQUEST_RETRIES 3
+
 #define min(a,b) ( (a>b) ? b : a )
 
+/* DATA TYPES */
+/* fragment header */
+struct frag_hdr {
+	u_int8_t dispatch;
+	uint id;   /* Id of the whole packet, same in each fragment */
+	uint size; /* length of the whole packet, same in each fragment */
+	uint offset;   /* fragment offset (in bytes) from the beginning
+		     * of the packet */
+};
+
+/* info about a packet being reassembled from fragments */
+struct frag_info {
+	uint id;	/* Id of the whole packet, same in each fragment */
+	uint size;	/* length of the whole packet, same in each fragment */
+	time_t tv_sec;	/* seconds after epoch when reassembly
+			 * of this packet started */
+	u_int8_t *bitmap;  /* bitmap representing already 
+			    * received parts of the packet */
+	char *buf;	/* buffer into which the fragment is reassembled */
+    LIST_ENTRY(frag_info) frag_infos;
+};
+
+struct client {
+	clientid_t clid; /* client ID */
+	int used;	 /* client active or not */
+	long reqid; /* request ID used for the client ID request */
+	struct plugin* pl;
+	
+	/* tunnel device */
+	char tun_dev[16];
+	int tun_fd;
+	struct event tun_ev;
+
+	/* ping */
+	int ping_counter;
+	uint8_t echo_seq;
+
+	/* fragmentation */
+	struct frag_hdr frag_hdr;
+	char frag_data[MTU+sizeof(struct frag_hdr)];
+	char *frag_datap;
+	int frag_data_len;
+	uint frag_id;		/* id for the next packet to be fragmented */
+	// TODO: randomize initial value of frag_id
+
+	/* fragmentat reassembly */
+	LIST_HEAD(frag_infos_head, frag_info) frag_infos;
+};
+//TODO: init: frag_datap, frag_data_len, frag_id, echo_seq, client id,
+//            frag_info_list
+//    pl->ping_counter = PING_FAIL;
+
+struct client clients[MAXCLIENTS];
+
+/* FUNCTION HEADERS */
 /*
  * Pass data received from the tun interface to the daemon.
  */
-static int process_data_from_tun(char *data, int len);
+static int process_data_from_tun(struct client *cl,char *data, int len);
 
 static int send_next_frag();
+static void cleanup();
 
-/* max transfered unit - encapsulated packet size */
-#define MTU 1500
-/* how many pings can fail before the plugin is declared broken */
-#define PING_INTERVAL 7
-#define PING_FAIL 3
-
+/* GLOBAL VARIABLES */
 int server = 0; /* are we a server or a client? */
-plugint *plugins = NULL; /* linked list of loaded plugins */
-int pl_fd = 0; /* plugin socket */
-plugint *current_pl = NULL; /* currently active plugin if we are a client */
-fd_set fdset;
-char tun_dev[16];
-int tun_fd = 0; /* tunnel device */
-struct event tun_ev;
+TAILQ_HEAD(plugins_head, plugin) plugins =
+	TAILQ_HEAD_INITIALIZER(plugins);
 
-struct event timer_ev;
+static struct event timer_ev;
 
-/* sequence number for the echo request */
-uint8_t echo_seq = 0;
-
-/* fragment id for the next packet to be fragmented */
-frag_hdr_t frag_hdr;
-char frag_data[MTU+sizeof(frag_hdr_t)];
-char *frag_datap = NULL;
-int frag_data_len = 0;
-uint frag_id = 0; // TODO: randomize
+static uint8_t myclid = 0; /* client ID of this client (client only) */
 
-/* fragmentat reassembly info list */
-LIST_HEAD(frag_info_list_head, frag_info) frag_info_list =
-	LIST_HEAD_INITIALIZER(frag_info_list);
-
 /* server host */
+struct addrinfo *ai;
 char *host;
 char *port = "12345";
-    
 
-/* 
- * helper function to register/unregisted/check file descriptors to be
- * watched by select
- */
+//static int client_state;    
 
-/* helper structure to put file descriptors into a linked list */
-typedef struct _fdlt {
-    int fd;
-    struct event ev;
-    struct _fdlt *next;
-} fdlt;
-fdlt *fdl;
-
-void
-register_select_fd(int fd, 
-		   void (*ev_callback)(int, short, void *arg),
-		   void *arg, long tv_sec)
+static void
+dump_data(char *data, int len)
 {
-    struct timeval tv;
-
-    fdlt* nfdl = malloc(sizeof(fdlt));
-    if (!nfdl) {
-	fprintf(stderr, "failed to malloc an fdlt: out of mem!\n");
-	exit(EXIT_FAILURE);
-    }
-    nfdl->fd = fd;
-    nfdl->next = fdl;
-    fdl = nfdl;
-
-    event_set(&nfdl->ev, fd, EV_PERSIST | EV_READ, ev_callback, arg);
-
-    if (tv_sec > -1) {
-	tv.tv_sec = tv_sec;
-	tv.tv_usec = 0;
-	event_add(&nfdl->ev, &tv);
-    } else
-	event_add(&nfdl->ev, NULL);
-
+	int i;
+	printf("(%d bytes) ", len);
+	for(i = 0; i < len; i++)
+		printf("%02hhx ", *(data+i));
+	printf("\n");
 }
 
-void unregister_select_fd(int fd) {
-    fdlt *p, **q;
-    for(q = &fdl, p = fdl; p; q = &(p->next), p=p->next) {
-	if (p->fd == fd) {
-	    *q = p->next;
-
-	    //event_set(&nfdl->ev, fd, EV_READ, ev_callback, arg);
-	    //event_set(&p->ev, fd, EV_READ, NULL, NULL);
-	    event_del(&p->ev);
-
-	    free(p);
-	    break;
-	}
-    }
-    //update_fdset();
+int
+mylog(const char *fmt, ...)
+{
+	int out;
+	va_list ap;
+	
+	va_start(ap, fmt);
+	out = vprintf(fmt, ap);
+	va_end(ap);
+	
+	return out;
 }
 
-int fd_isset(int fd) {
-    return FD_ISSET(fd, &fdset);
+int
+debug(const char *fmt, ...)
+{
+	int out;
+	va_list ap;
+	
+	va_start(ap, fmt);
+	out = vprintf(fmt, ap);
+	va_end(ap);
+	
+	return out;
 }
 
 int
@@ -144,60 +166,85 @@
   vsnprintf(cmd, sizeof(cmd), fmt, ap);
   va_end(ap);
   fprintf(stderr, "%s\n", cmd);
-  //fflush(stderr);
-  //fflush(stdout);
   return system(cmd);
 }
 
-void
-set_current_pl(plugint* pl)
+/* lookup client by ID */
+static struct client *
+lookup_clid(clientid_t clid)
+{
+	if (server)
+		return &clients[clid];
+	else
+		return clients;
+}
+
+/*
+ * change the plugin a client is using - closes the connection in the
+ * old plugin and adds/deletes the tunnel event depending on the
+ * plugin type (polling or direct)
+ */
+static void
+set_client_pl(struct client *cl, struct plugin* pl)
 {
-    if (current_pl) {
-	event_del(&tun_ev);
-    }
-    current_pl = pl;
-    if (pl) {
-	if (pl->is_ready_to_send() == WILL_SEND_IMMEDIATELY)
-	    event_add(&tun_ev, NULL);
-	// otherwise the tun read is timed by the plugin
-    }
+	if (cl->pl == pl)
+		return;
+
+	if (cl->pl != NULL) {
+		cl->pl->conn_close(pl, cl->clid);
+		if  (cl->tun_fd != -1)
+			event_del(&cl->tun_ev);
+	}
+	
+	cl->pl = pl;
+	cl->ping_counter = 0;
+
+	if (pl != NULL && cl->tun_fd != -1) {
+		if (cl->pl->is_ready_to_send(cl->pl, cl->clid) ==
+		    WILL_SEND_IMMEDIATELY)
+			event_add(&cl->tun_ev, NULL);
+		// else the tun read is timed by the plugin
+	}
 }
 
-/* read data from the tun interface and pass it to the daemon */
+/*
+ * entry function if a polling plugin can send more data - if
+ * fragments pending, send these; otherwise read data from the tun
+ * interface and pass it to the daemon
+ */
 static void 
-tun_receive()
+request_tun_data(struct client *cl)
 {
-    char packet[PACKETLEN];
-    int nread = 0;
-    int nwrite = 0;
-    
-    printf("tun_receive()\n");
-    if (current_pl == NULL)
-	return;
-    
-    if (frag_datap != NULL) {
-	send_next_frag();
-	return;
-    }
-
-    do {
-	//memset(packet, 0, sizeof(packet));
-	nread = tun_read(tun_fd, packet, PACKETLEN);
-	if (nread > 0) {
-	    nwrite = process_data_from_tun(packet, nread);
+	char packet[PACKETLEN];
+	int nread = 0;
+	int nwrite = 0;
+	
+	printf("request_tun_data()\n");
+	if (cl->pl == NULL)
+		return;
+	
+	if (cl->frag_datap != NULL) {
+		send_next_frag(cl);
+		return;
 	}
-	/* continue the loop if we read something
-	 * and the plugin has sent it immediately
-	 */
-	printf("tun_receive: nread: %d, nwrite: %d\n", nread, nwrite);
-    } while (nread > 0 && nwrite == SEND_PKT_SENT);
+	
+	do {
+		nread = tun_read(cl->tun_fd, packet, PACKETLEN);
+		if (nread > 0) {
+			nwrite = process_data_from_tun(cl, packet, nread);
+		}
+		/* continue the loop if we read something
+		 * and the plugin has sent it immediately
+		 */
+		printf("request_tun_data: nread: %d, nwrite: %d\n", nread, nwrite);
+	} while (nread > 0 && nwrite == SEND_PKT_SENT);
 }
 
-/* send data via the tun interface */
+/* send data via the tun interface for the client */
 static int
-tun_send(char *data, int len) {
+tun_send(struct client *cl, char *data, int len) {
     int n;
-    n = tun_write(tun_fd, data, len);
+    n = tun_write(cl->tun_fd, data, len);
     /*
     if (n != len) {
 	fprintf(stderr, "tun_send: tun_write wrote less bytes (%d) than "
@@ -209,66 +256,168 @@
 }
 
 /* handler function for events on the tun device - called by libevent */
+void
+tun_ev_handler(int fd, short ev_type, void *arg)
+{
+	struct client *cl = arg;
+	printf("tun_ev_handler(): ev_type: 0x%x\n", ev_type);
+	/*
+	 * Only read from the tun device can send the data immediately.
+	 * Otherwise, we will be notified via plugin_report() when data
+	 * can be sent.
+	 */
+	if (cl->pl != NULL)
+		if (cl->pl->is_ready_to_send(cl->pl, cl->clid) ==
+		    WILL_SEND_IMMEDIATELY)
+			request_tun_data(cl);
+}
+
+ int
+tun_init(struct client *cl)
+{
+	int tun_flags;
+	
+	/* create the tunnel device */
+	sprintf(cl->tun_dev, "tun%i", cl->clid);
+	cl->tun_fd = tun_open(cl->tun_dev);
+	if (cl->tun_fd < 1) {
+		printf("Could not create tunnel device\n");
+		return 1;
+	}
+	/* non-blocking i/o */
+	tun_flags = fcntl(cl->tun_fd, F_GETFL, 0);
+	if (tun_flags == -1)
+		errx(EX_OSFILE, "Failed to get flags from the tun device\n");
+	fcntl(cl->tun_fd, F_SETFL, tun_flags|O_NONBLOCK);
+
+ 	event_set(&cl->tun_ev, cl->tun_fd, EV_PERSIST | EV_READ,
+ 		  tun_ev_handler, cl);
+
+	printf("Created tunnel device: %s\n", cl->tun_dev);
+
+	/* configure the tun interface */
+	char cmd[123];
+	if (server) {
+#ifdef __FreeBSD__
+		sprintf(cmd,
+		    "ifconfig %s mtu 1400 192.168.0.%d 192.168.0.%d",
+		    cl->tun_dev, cl->clid * 2, cl->clid * 2 + 1);
+		ssystem(cmd);
+#else
+		warnx("Please configure %s yourself...\n", cl->tun_dev);
+#endif
+/* #ifdef __linux */
+/* 		ssystem("ifconfig tun0 mtu 1400 192.168.0.1"); */
+/* 		ssystem("route add 192.168.0.2 tun0"); */
+/* #endif */
+		
+	} else {
+#ifdef __FreeBSD__
+		sprintf(cmd,
+		    "ifconfig %s mtu 1400 192.168.0.%d 192.168.0.%d",
+		    cl->tun_dev, cl->clid * 2 + 1, cl->clid * 2);
+		ssystem(cmd);
+#else
+		warnx("Please configure %s yourself...\n", cl->tun_dev);
+#endif
+/* #ifdef __linux */
+/* 		ssystem("ifconfig tun0 mtu 1400 192.168.0.2"); */
+/* 		ssystem("route add 192.168.0.1 tun0"); */
+/* #endif */
+	}
+	
+	if (cl->pl != NULL) {
+		if (cl->pl->is_ready_to_send(cl->pl, cl->clid) ==
+		    WILL_SEND_IMMEDIATELY)
+			event_add(&cl->tun_ev, NULL);
+		// else the tun read is timed by the plugin
+	}
+
+	return 0;
+}
+
 static void
-tun_ev_handler(int fd, short ev_type, void *arg)
+tun_deinit(struct client *cl)
 {
-    printf("tun_ev_handler(): ev_type: 0x%x\n", ev_type);
-    /*
-     * Only read from the tun device can send the data immediately.
-     * Otherwise, we will be notified via plugin_report() when data
-     * can be sent.
-     */
-    if (current_pl != NULL)
-	if (current_pl->is_ready_to_send() == WILL_SEND_IMMEDIATELY)
-	    tun_receive();
+	if (!server) {
+		// TODO: fix routing table
+	}
+
+	if (cl->tun_fd != -1) {
+		event_del(&cl->tun_ev);
+		tun_close(cl->tun_fd, cl->tun_dev);
+	}
 }
 
-/* 
- * BUGS: if dlclose() is called, I get a segfault when trying to use
- * the loaded functions. Maybe I'm not passing the right flags to
- * dlopen()? Well, RTLD_NODELETE seems to help here, at least on
- * linux.
+/*
+ * load a plugin from file and register it
+ * returns a pointer to the plugin on success or NULL on failure
  */
-static int
+static struct plugin *
 load_plugin(char *path) {
-    plugint *pl;
-    int (*plugin_register)(plugint*);
+    struct plugin *pl;
+    int (*plugin_register)(struct plugin*);
     void *handle;
     const char *error;
-    pl = (plugint*) malloc(sizeof(plugint));
+    pl = malloc(sizeof(struct plugin));
     if (!pl) {
-	fprintf(stderr, "failed to malloc plugint: out of memory!\n");
-	return -1;
+	warnx("failed to malloc plugin: out of memory!\n");
+	return NULL;
     }
 
     /* open the library */
     handle = dlopen (path, RTLD_NOW);
     if (!handle) {
 	fputs(dlerror(), stderr);
-	return 1;
+	return NULL;
     }
-    
     /* load the plugin */
-    pl = (plugint *) malloc(sizeof(plugint));
     plugin_register = dlsym(handle, "plugin_register");
-    if ((error = dlerror()) != NULL) goto error;
+    if ((error = dlerror()) != NULL)
+	    goto error;
+    /* prepare the plugin for registration */
     plugin_register(pl);
 
-    //dlclose(handle);
-
     /* add plugin to the list of loaded plugins */
-    pl->next = plugins;
-    plugins = pl;
-
-    pl->ping_counter = PING_FAIL;
+    TAILQ_INSERT_TAIL(&plugins, pl, plugins);
 
     fprintf(stderr, "successfully loaded plugin %s\n", pl->name);
-    return 0;
+    return pl;
 
  error:
 	fputs(error, stderr);
 	free(pl);
-	return 2;
+	return NULL;
+}
+
+/* initialize the client datastructure */
+static struct client *
+client_init(clientid_t clid)
+{
+	struct client *cl = lookup_clid(clid);
+	
+	if (cl->used) {
+		warnx("client_init: client ID already exists\n");
+		return NULL;
+	}
+	
+	memset(cl, 0, sizeof(*cl));
+	cl->clid = clid;
+	cl->tun_fd = -1;
+	cl->pl = NULL;
+	cl->used = 1;
+
+	return cl;
+}
+
+/* deinitialize the client datastructure, corresponding tun device,... */
+static void
+client_deinit(struct client *cl)
+{
+	//TODO
+	//TODO close conn
+	tun_deinit(cl);
+	cl->used = 0;
 }
 
 /*
@@ -276,50 +425,111 @@
  * from ICMP echo.
  */
 static void
-send_echo_request()
+send_echo_request(struct client *cl)
+{
+	int nwrite = 0;
+	char data[10];
+	char *datap = data;
+	int len=0;
+
+	cl->ping_counter++;
+
+	if (cl->pl != NULL) {
+		/* client prepends the client ID */
+		if (!server) {
+			*datap = cl->clid;
+			datap++;
+			len++;
+		}
+		
+		*datap = DISPATCH_ECHO_REQUEST;
+		datap++;
+		len++;
+
+		*datap = cl->echo_seq++;
+		datap++;
+		len++;
+		
+		nwrite =  cl->pl->send(cl->pl, cl->clid,
+				      data, len, NORMAL_DATA);
+		printf("send_echo_request(): nwrite: 0x%x\n", nwrite);
+	}
+}
+
+/*
+ * send a request for a client ID - used only by the client
+ */
+static void
+send_id_request()
 {
-    int nwrite = 0;
-    char data[2];
-    plugint *pl = current_pl;
-    if (pl) {
-	*data = DISPATCH_ECHO_REQUEST;
-	*(data+1) = echo_seq++;
-	nwrite =  pl->send(pl, data, sizeof(data), NORMAL_DATA);
-	pl->ping_counter--;
-	printf("send_cho_request(): nwrite: 0x%x\n", nwrite);
-    }
+	struct client *cl = clients;
+	int nwrite = 0;
+	char data[10];
+	char *pdata = data;
+	if (cl->pl != NULL) {
+		/* client ID */
+		*pdata = 0;
+		pdata++;
+		
+		/* dispatch */
+		*pdata = DISPATCH_ID_REQUEST;
+		pdata++;
+
+		/* request ID */
+		memcpy(pdata, &cl->reqid, sizeof(cl->reqid));
+		pdata += sizeof(cl->reqid);
+		
+		nwrite =  cl->pl->send(cl->pl, cl->clid,
+				       data, pdata - data, NORMAL_DATA);
+		//pl->ping_counter--;
+		printf("send_id_request(): nwrite: 0x%x\n", nwrite);
+	}
 }
 
+
+
 /* handler function for the libevent timer event */
 static void 
 timer_ev_handler(int fd, short ev_type, void *arg)
 {
     struct timeval tv;
     struct frag_info *np, *np_temp;
-    plugint *pl = current_pl;
+    struct client *cl;
+    int i;
 
     /* check if too many ping requests have not failed */
-    if (pl) {
-	printf("ping_counter: %d\n", pl->ping_counter);
-	if (pl->ping_counter <= 0) {
-	    plugin_report(pl, REPORT_ERROR_PING);
-	} else {
-	    send_echo_request();
-	}
+    for(i = 0; i < MAXCLIENTS; i++) {
+	    cl = &clients[i];
+	    if (cl->used == 0)
+		    continue;
+
+	    printf("ping_counter: %d\n", cl->ping_counter);
+	    if (cl->ping_counter > PING_FAIL_COMPLETE &&
+		server)
+		    client_deinit(cl);
+	    else if (cl->pl) {
+		    if (cl->ping_counter > PING_FAIL_PLUGIN)
+			    plugin_report(cl->pl, cl->clid,
+					  REPORT_ERROR_PING);
+		    send_echo_request(cl);
+	    }
     }
 
     /* fragment reassembly timeout */
-    if (gettimeofday(&tv, NULL) != 0) {
-	err(EX_OSERR, "gettimeofday() failed");
-    } else {
-	LIST_FOREACH_SAFE(np, &frag_info_list, frag_infos, np_temp) {
-	    if (tv.tv_sec - np->tv_sec > FRAG_TIMEOUT) {
-		LIST_REMOVE(np, frag_infos);
-		free(np->bitmap);
-		free(np->buf);
-		free(np);
+    gettimeofday(&tv, NULL);
+    for(i = 0; i < MAXCLIENTS; i++) {
+	    cl = &clients[i];
+	    if (cl->used == 0)
+		    continue;
+
+	    LIST_FOREACH_SAFE(np, &cl->frag_infos, frag_infos, np_temp) {
+		    if (tv.tv_sec - np->tv_sec > FRAG_TIMEOUT) {
+			    LIST_REMOVE(np, frag_infos);
+			    free(np->bitmap);
+			    free(np->buf);
+			    free(np);
+		    }
 	    }
-	}
     }
     
     /* register a timer event again */
@@ -331,326 +541,566 @@
 
 /*
  * Pass data received by the plugin to the daemon.
+ * 
+ * called 1st time: *conn == NULL
+ *	lookup client's conn by client ID and return
+ *
+ * called 2nd time: *conn != NULL
+ * 
  */
 void
-process_data_from_plugin(plugint *pl, char *data, int len)
+process_data_from_plugin(struct plugin *pl, char *data, int len,
+    uint8_t *clid, int *conn_flag)
 {
-    u_int8_t dispatch = *data;
-    frag_hdr_t *frag_hdr = NULL;
-    struct frag_info *p;/* pointer to frag info about the processed fragment */
-    struct frag_info *np;
-    struct timeval tv;
-    int i;
-    int dgram_reassembled;
-    int nwrite;
+	u_int8_t dispatch;
+	int i;
+	int nwrite;
+	struct client *cl = NULL;
+
+	/* fragment reassembly */
+	struct frag_hdr *frag_hdr = NULL;
+	struct frag_info *p;	/* pointer to frag info about the
+				 * processed fragment */
+	struct frag_info *np;
+	struct timeval tv;
+	int dgram_reassembled;
+
+	printf("data from plugin: ");
+	dump_data(data, len);
+
+	*conn_flag = CONN_DISCARD;
 
-    if (len <= 0)
-	return;
+	if (len <= 0)
+		return;
 
-    switch (dispatch) {
-    case DISPATCH_DATA:
-	printf("process_data_from_plugin(): DATA\n");
-	tun_send(data+1, len-1);
-	goto plugin_ok;
-	break;
-    case DISPATCH_FRAG:
-	if (len <= sizeof(frag_hdr)) {
-	    plugin_report(pl, REPORT_ERROR_RECEIVE);
-	    return;
+	/* process the client ID */
+	if (server) {
+		/* payload from the client starts with the client ID */
+		*clid = *data;
+		data++;
+		len--;
+	} else { /* client */
+		/* payload from the server does NOT contain the client ID */
+		*clid = 0;
 	}
+	cl = lookup_clid(*clid);
 
-	frag_hdr = (frag_hdr_t*) data;
-	data += sizeof(frag_hdr_t);
-	len -= sizeof(frag_hdr_t);
+	/* process the dispatch */
+	dispatch = *data;
+
+	printf("clid: %hhd, dispatch: 0x%02hhx\n", *clid, dispatch);
+
+	switch (dispatch) {
+	case DISPATCH_DATA:
+		printf("process_data_from_plugin(): DATA\n");
+		/* only associated clients can send DATA to the server */
+		if (server && *clid == 0) {
+			*conn_flag = CONN_DISCARD;
+			pl->conn_map(pl, *clid, *conn_flag);
+			return;
+		}
 
-	/* debugging output */
-	fprintf(stderr, "got a frag header: id %d, size %d, off %d, len %d\n",
-		frag_hdr->id, frag_hdr->size, frag_hdr->offset, len);
+		*conn_flag = CONN_PERM;
+		pl->conn_map(pl, *clid, CONN_PERM);
+		
+		/* update the current plugin for this client */
+		set_client_pl(cl, pl);
+		
+		tun_send(cl, data+1, len-1);
 
-	/* check if reassembly for this fragment has already started */
-	p = NULL;
-	LIST_FOREACH(np, &frag_info_list, frag_infos) {
-	    if (np->id == frag_hdr->id &&
-		np->size == frag_hdr->size) {
-		/* found in list */
-		fprintf(stderr, "found frag info in list\n");
-		p = np;
 		break;
-	    }
-	}
+
+	case DISPATCH_FRAG: /* fragment reassembly */
+		pl->conn_map(pl, *clid, CONN_PERM);
+
+		if (len <= sizeof(*frag_hdr)) {
+			plugin_report(pl, *clid, REPORT_ERROR_RECEIVE);
+			return;
+		}
+
+		frag_hdr = (struct frag_hdr*) data;
+		data += sizeof(struct frag_hdr);
+		len -= sizeof(struct frag_hdr);
+		
+		/* debugging output */
+		debug("got a frag header: id %d, size %d, off %d, len %d\n",
+		    frag_hdr->id, frag_hdr->size, frag_hdr->offset, len);
+
+		/* check if reassembly for this fragment has already started */
+		p = NULL;
+		LIST_FOREACH(np, &cl->frag_infos, frag_infos) {
+			if (np->id == frag_hdr->id &&
+			    np->size == frag_hdr->size) {
+				/* found in list */
+				fprintf(stderr, "found frag info in list\n");
+				p = np;
+				break;
+			}
+		}
 
-	/* fragment info not found in list, start a new reassembly */
-	if (p == NULL) { 
-	    fprintf(stderr, "frag info NOT found in list\n");
-	    /* allocate memory */
-	    p = malloc(sizeof(struct frag_info));
-	    if (!p) {
-		fprintf(stderr, "process_data_from_plugin - "
-			"fragment reassembly: out of memory\n");
-		return;
-	    }
-	    memset(p, 0, sizeof(*p));
-	    p->buf = malloc(frag_hdr->size);
-	    if (!p->buf) {
-		free(p);
-		fprintf(stderr, "process_data_from_plugin - "
-			"fragment reassembly: out of memory\n");
-		return;
-	    }
-	    p->bitmap = malloc(frag_hdr->size/8 + 1);
-	    if (!p->bitmap) {
-		free(p->buf);
-		free(p);
-		fprintf(stderr, "process_data_from_plugin - "
-			"fragment reassembly: out of memory\n");
-		return;
-	    }
-	    memset(p->bitmap, 0, sizeof(*(p->bitmap)));
+		/* fragment info not found in list, start a new reassembly */
+		if (p == NULL) {
+			fprintf(stderr, "frag info NOT found in list\n");
+			/* allocate memory */
+			p = malloc(sizeof(struct frag_info));
+			if (!p) {
+				warnx("process_data_from_plugin - "
+				    "fragment reassembly: out of memory\n");
+				return;
+			}
+			memset(p, 0, sizeof(*p));
+			p->buf = malloc(frag_hdr->size);
+			if (!p->buf) {
+				free(p);
+				warnx("process_data_from_plugin - "
+				    "fragment reassembly: out of memory\n");
+				return;
+			}
+			p->bitmap = malloc(frag_hdr->size/8 + 1);
+			if (!p->bitmap) {
+				free(p->buf);
+				free(p);
+				warnx("process_data_from_plugin - "
+				    "fragment reassembly: out of memory\n");
+				return;
+			}
+			memset(p->bitmap, 0, sizeof(*(p->bitmap)));
 	    
-	    /* collect information about the fragments */
-	    if (gettimeofday(&tv, NULL) != 0) {
-		err(EX_OSERR, "gettimeofday() failed");
-	    }
-	    p->id = frag_hdr->id;
-	    p->size = frag_hdr->size;
-	    memcpy(&p->tv_sec, &tv.tv_sec, sizeof(tv.tv_sec));
-	    LIST_INSERT_HEAD(&frag_info_list, p, frag_infos);
-	}
+			/* collect information about the fragments */
+			gettimeofday(&tv, NULL);
+			p->id = frag_hdr->id;
+			p->size = frag_hdr->size;
+			memcpy(&p->tv_sec, &tv.tv_sec, sizeof(tv.tv_sec));
+			LIST_INSERT_HEAD(&cl->frag_infos, p, frag_infos);
+		}
 	
-	if (frag_hdr->offset + len <= p->size) {
-	    /* copy the data */
-	    memcpy(p->buf + frag_hdr->offset, data, len);
-	    /* update the bitmap */
-	    // TODO: we ignore overlaps, but that should be caught
-	    //       by the upper layer checksum
-	    for(i = frag_hdr->offset; i<frag_hdr->offset+len; i++) {
-		p->bitmap[i/8] |= (0x1 << (i%8));
-	    }
-	} else {
-	    fprintf(stderr, "fragment outside of packet payload\n");
-	    return;
-	}
+		if (frag_hdr->offset + len <= p->size) {
+			/* copy the data */
+			memcpy(p->buf + frag_hdr->offset, data, len);
+			/* update the bitmap */
+			// TODO: we ignore overlaps, but that should be caught
+			//       by the upper layer checksum
+			for (i = frag_hdr->offset; i < frag_hdr->offset+len;
+			     i++)
+				p->bitmap[i/8] |= (0x1 << (i%8));
+		} else {
+			warnx("fragment outside of packet payload\n");
+			return;
+		}
+
+		set_client_pl(cl, pl);
 	
-	/* check if the complete packet has been reassembled */
-	dgram_reassembled = 1;
-	/* examine the bitmap */
-	for(i=0; i < p->size/8 && dgram_reassembled; i++) {
-	    if (p->bitmap[i] != 0xff) {
-		dgram_reassembled = 0;
-	    }
-	}
-	for(i=0; i < p->size%8 && dgram_reassembled; i++) {
-	    if (! (p->bitmap[p->size/8] & (1 << i))) {
-		dgram_reassembled=0;
-	    }
-	}
-	/* packet completely reassembled */
-	if (dgram_reassembled) {
-	    fprintf(stderr, "frag reassembly: packet complete\n");
-	    set_current_pl(pl);
-	    tun_send(p->buf, p->size);
+		/* check if the complete packet has been reassembled */
+		dgram_reassembled = 1;
+		/* examine the bitmap */
+		for(i=0; i < p->size/8 && dgram_reassembled; i++) {
+			if (p->bitmap[i] != 0xff) {
+				dgram_reassembled = 0;
+			}
+		}
+		for(i=0; i < p->size%8 && dgram_reassembled; i++) {
+			if (! (p->bitmap[p->size/8] & (1 << i))) {
+				dgram_reassembled=0;
+			}
+		}
+		
+		/* packet completely reassembled */

>>> TRUNCATED FOR MAIL (1000 lines) <<<


More information about the p4-projects mailing list