Date: Thu, 19 Jul 2007 23:27:56 GMT From: Matus Harvan <mharvan@FreeBSD.org> To: Perforce Change Reviews <perforce@FreeBSD.org> Subject: PERFORCE change 123756 for review Message-ID: <200707192327.l6JNRuia062812@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=123756 Change 123756 by mharvan@mharvan_twoflower on 2007/07/19 23:27:02 fragmentation support in the common code Affected files ... .. //depot/projects/soc2007/mharvan-mtund/mtund.src/Makefile#6 edit .. //depot/projects/soc2007/mharvan-mtund/mtund.src/plugin_icmp.c#2 edit .. //depot/projects/soc2007/mharvan-mtund/mtund.src/tunneld.c#9 edit .. //depot/projects/soc2007/mharvan-mtund/mtund.src/tunneld.h#4 edit Differences ... ==== //depot/projects/soc2007/mharvan-mtund/mtund.src/Makefile#6 (text+ko) ==== @@ -1,9 +1,10 @@ -LIBS+= -levent -LIBS+=-L/usr/local/lib # Linux needs -ldl -#LIBS+= -ldl -levent +#LIBS+= -ldl + +LIBS+=-levent -CFLAGS=-Wall -rdynamic +LIBS=-L/usr/local/lib -levent +CFLAGS+=-Wall -rdynamic CFLAGS+=-g CFLAGS+=-I/usr/local/include @@ -11,7 +12,6 @@ tunneld: tunneld.h tunneld.c tun_dev.c gcc $(CFLAGS) $(LIBS) -o tunneld tunneld.c tun_dev.c -# -ldl plugin_tcp.so: tunneld.h plugin.h plugin_tcp.c gcc $(CFLAGS) -shared -o plugin_tcp.so plugin_tcp.c ==== //depot/projects/soc2007/mharvan-mtund/mtund.src/plugin_icmp.c#2 (text+ko) ==== @@ -182,6 +182,14 @@ } else { data->state = PLUGIN_STATE_CONNECTED; } + + if (data->server) { + #ifdef __FreeBSD__ + //system("sysctl net.ipv4.icmp_echo_ignore_all=0"); + #else + system("sysctl net.ipv4.icmp_echo_ignore_all=0"); + #endif + } return 0; } else { return -1; @@ -278,8 +286,9 @@ /* } else { */ /* icmp->type = ICMP_ECHO; */ /* } */ - icmp->type = 123; - + //icmp->type = ICMP_ECHO; + icmp->type = 123; + icmp->code = 0; icmp->id = ID; icmp->seq = 0; ==== //depot/projects/soc2007/mharvan-mtund/mtund.src/tunneld.c#9 (text+ko) ==== @@ -48,8 +48,15 @@ struct event tun_ev; struct event timer_ev; + +/* sequence number for the echo request */ uint echo_seq = 0; +/* fragment id for the next packet to be fragmented */ +uint frag_id = 0; // TODO: randomize +frag_llist_t *frag_list; + +/* server host */ char *host; char *port = "12345"; @@ -216,6 +223,7 @@ void timer_ev_handler(int fd, short ev_type, void *arg) { struct timeval tv; + frag_llist_t *p, *q; plugint *pl = current_pl; fprintf(stderr, "timer fired\n"); @@ -228,6 +236,18 @@ } } + /* fragment reassembly timeout */ + // TODO: fragment reassembly timeout + for (p=frag_list; p;) { + q = p->next; + if (tv.tv_sec - p->tv_sec > FRAG_TIMEOUT) { + free(p->bitmap); + free(p->buf); + free(p); + } + p = q; + } + /* register a timer event */ tv.tv_sec=1; tv.tv_usec=0; @@ -241,6 +261,12 @@ void process_data_from_plugin(plugint *pl, char *data, int len) { u_int8_t dispatch = *data; + frag_hdr_t *frag_hdr = NULL; + frag_llist_t *p, *q, **pp; + struct timeval tv; + int i; + int dgram_reassembled; + switch (dispatch) { case DISPATCH_DATA: if (len > 0) { @@ -248,6 +274,120 @@ } tun_send(data+1, len-1); break; + case DISPATCH_FRAG: + if (len <= sizeof(frag_hdr)) { + report_plugin_error(pl, PLUGIN_ERROR_RECEIVE); + return; + } + + frag_hdr = (frag_hdr_t*) data; + data += sizeof(frag_hdr_t); + len -= sizeof(frag_hdr_t); + + /* 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); + + /* search frag info in list */ + pp = &frag_list; + for(p = frag_list; p; p = p->next) { + if (p->id == frag_hdr->id && + p->size == frag_hdr->size) { + break; + } + pp = &p; + } + /* found in list */ + if (p) { + fprintf(stderr, "found frag info in list\n"); + /* fragment info not found in list, start a new reassembly */ + } else { + fprintf(stderr, "frag info NOT found in list\n"); + /* allocate memory */ + p = malloc(sizeof(frag_llist_t)); + 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))); + + /* collect information about the fragments */ + // TODO: error checking + (void) gettimeofday(&tv, NULL); + p->next = frag_list; + frag_list = p; + p->id = frag_hdr->id; + p->size = frag_hdr->size; + memcpy(&p->tv_sec, &tv.tv_sec, sizeof(tv.tv_sec)); + } + + 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"); + } + + /* 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; +/* printf("dgram_reassembled = 0 (bitmap[%d]: 0x%x)\n", */ +/* i, p->bitmap[i]); */ + } + } + for(i=0; i < p->size%8 && dgram_reassembled; i++) { + if (! (p->bitmap[p->size/8] & (1 << i))) { + dgram_reassembled=0; +/* printf("dgram_reassembled = 0 (bitmap<<%d)\n", i); */ +/* printf("bitmap[%d]: 0x%x)\n", */ +/* p->size/8, p->bitmap[p->size/8]); */ + } + } +/* printf("bitmap: 0x"); */ +/* for(i=0; i < p->size/8 + 1; i++) { */ +/* printf("%x",p->bitmap[i]); */ +/* } */ +/* printf("\n"); */ + /* packet completely reassembled */ + if (dgram_reassembled) { + fprintf(stderr, "frag reassembly: packet complete\n"); + current_pl = pl; + tun_send(p->buf, p->size); + + /* remove fragment info from linked list */ + q = p->next; + free(p->buf); + free(p->bitmap); + free(p); + *pp = q; + } + break; case DISPATCH_ECHO_REQUEST: *data = (u_int8_t) DISPATCH_ECHO_REPLY; pl->send(pl, data, len); @@ -270,13 +410,17 @@ */ void process_data_from_tun(char *data, int len) { - int n; + int n = 0; char ldata[MTU+1]; + char *ldatap = ldata; + frag_hdr_t frag_hdr; + int mtu = 100; // TODO: add mtu to plugint if (current_pl == NULL) { fprintf(stderr, "no plugin connected yet, discarding tun data\n"); report_plugin_error(NULL, PLUGIN_ERROR_BOOTSTRAP); } else { +#ifdef NO_FRAG *ldata = DISPATCH_DATA; memcpy(ldata+1, data, min(sizeof(ldata)-1, len)); n = current_pl->send(current_pl, ldata, min(sizeof(ldata), len+1)); @@ -285,6 +429,45 @@ fprintf(stderr, "process_data_from_tun: plugind sent less " "bytes (%d) than requested (%d)\n", n, len); } +#else /* NO_FRAG */ + // mtu = current_pl->mtu; + + /* prepare the frag header */ + frag_hdr.dispatch = DISPATCH_FRAG; + frag_hdr.id = frag_id; + frag_id++; + frag_hdr.size = len; + frag_hdr.offset = 0; + + /* copy the payload */ + memcpy(ldatap + sizeof(frag_hdr), data, + min(sizeof(ldata) - sizeof(frag_hdr), len)); + len += sizeof(frag_hdr); + + while(len > sizeof(frag_hdr)) { + printf("process_data_from_tun: sending frag " + "offset %d, send_len %d, len %d\n", + frag_hdr.offset, min(mtu, len), len); + /* prepend the frag dispatch and header before the payload */ + memcpy(ldatap, &frag_hdr, sizeof(frag_hdr)); + + /* send it */ + //TODO: change the logic here, we should not fragment based + // on the return value from send() + n = min(mtu, len); + (void) current_pl->send(current_pl, ldatap, min(mtu, len)); + n -= sizeof(frag_hdr); + if (n <= 0) { + fprintf(stderr, "process_data_from_tun: failed to send" + "data (%d)\n", n); + report_plugin_error(current_pl, PLUGIN_ERROR_SEND); + return; + } + ldatap += n; + frag_hdr.offset += n; + len -= n; + } +#endif /* NO_FRAG */ } } @@ -294,6 +477,7 @@ return; } + /* server */ if (server) { if (pl) { /* reinitialize the broken plugin */ @@ -302,6 +486,7 @@ //pl->deinitialize(pl); //(void) pl->initialize(pl, server, host, 1234); } + /* client */ } else { if (pl) { /* deinitialize the broken plugin */ ==== //depot/projects/soc2007/mharvan-mtund/mtund.src/tunneld.h#4 (text+ko) ==== @@ -1,9 +1,32 @@ #ifndef _TUNNELD_H #define _TUNNELD_H -#define PACKETLEN 1400 /* encapsulated data size */ +#include <sys/types.h> + +#define PACKETLEN 1400 /* encapsulated data size */ #define SOCKET_TIMEOUT 5 /* timeout for socket operations */ +#define FRAG_TIMEOUT 60 /* encapsulated data size */ + +/* fragment header */ +typedef struct _frag_hdr_t { + 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 */ +} frag_hdr_t; +typedef struct _frag_llist_t { + 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 */ + struct _frag_llist_t *next; +} frag_llist_t; + /* * code for setting timeout on a socket: * struct timeval tv; @@ -36,6 +59,7 @@ enum { DISPATCH_ECHO_REQUEST = 1, DISPATCH_ECHO_REPLY = 2, + DISPATCH_FRAG = 3, DISPATCH_DATA = 0x42 };
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200707192327.l6JNRuia062812>