From owner-p4-projects@FreeBSD.ORG Sat Aug 18 00:27:21 2007 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 2161916A41A; Sat, 18 Aug 2007 00:27:21 +0000 (UTC) Delivered-To: perforce@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id CDDCD16A417 for ; Sat, 18 Aug 2007 00:27:20 +0000 (UTC) (envelope-from mharvan@FreeBSD.org) Received: from repoman.freebsd.org (repoman.freebsd.org [IPv6:2001:4f8:fff6::29]) by mx1.freebsd.org (Postfix) with ESMTP id BA00813C46A for ; Sat, 18 Aug 2007 00:27:20 +0000 (UTC) (envelope-from mharvan@FreeBSD.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.14.1/8.14.1) with ESMTP id l7I0RKnc019768 for ; Sat, 18 Aug 2007 00:27:20 GMT (envelope-from mharvan@FreeBSD.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.14.1/8.14.1/Submit) id l7I0RKCg019765 for perforce@freebsd.org; Sat, 18 Aug 2007 00:27:20 GMT (envelope-from mharvan@FreeBSD.org) Date: Sat, 18 Aug 2007 00:27:20 GMT Message-Id: <200708180027.l7I0RKCg019765@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to mharvan@FreeBSD.org using -f From: Matus Harvan To: Perforce Change Reviews Cc: Subject: PERFORCE change 125282 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 18 Aug 2007 00:27:21 -0000 http://perforce.freebsd.org/chv.cgi?CH=125282 Change 125282 by mharvan@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 +#include +#include #include -#include #include #include #include #include +#include #include #include #include @@ -29,110 +32,129 @@ //#include //#include +/* 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; ioffset+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) <<<