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