Date: Tue, 7 Aug 2007 18:38:59 GMT From: Matus Harvan <mharvan@FreeBSD.org> To: Perforce Change Reviews <perforce@FreeBSD.org> Subject: PERFORCE change 124841 for review Message-ID: <200708071838.l77Icx3B006470@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=124841 Change 124841 by mharvan@mharvan_bike-planet on 2007/08/07 18:38:46 ICMP plugin now correctly implements the polling strategy - design with normal and urgent data libevent events firign with EV_TIMEOUT have to be re-added Affected files ... .. //depot/projects/soc2007/mharvan-mtund/mtund.src/Makefile#7 edit .. //depot/projects/soc2007/mharvan-mtund/mtund.src/README#3 edit .. //depot/projects/soc2007/mharvan-mtund/mtund.src/plugin.h#4 edit .. //depot/projects/soc2007/mharvan-mtund/mtund.src/plugin_icmp.c#5 edit .. //depot/projects/soc2007/mharvan-mtund/mtund.src/plugin_tcp.c#7 edit .. //depot/projects/soc2007/mharvan-mtund/mtund.src/plugin_udp.c#6 edit .. //depot/projects/soc2007/mharvan-mtund/mtund.src/tun_dev.c#2 edit .. //depot/projects/soc2007/mharvan-mtund/mtund.src/tun_dev.c.freebsd#2 edit .. //depot/projects/soc2007/mharvan-mtund/mtund.src/tun_dev.c.linux#2 edit .. //depot/projects/soc2007/mharvan-mtund/mtund.src/tun_dev.h#2 edit .. //depot/projects/soc2007/mharvan-mtund/mtund.src/tunneld.c#14 edit .. //depot/projects/soc2007/mharvan-mtund/mtund.src/tunneld.h#8 edit Differences ... ==== //depot/projects/soc2007/mharvan-mtund/mtund.src/Makefile#7 (text+ko) ==== ==== //depot/projects/soc2007/mharvan-mtund/mtund.src/README#3 (text+ko) ==== ==== //depot/projects/soc2007/mharvan-mtund/mtund.src/plugin.h#4 (text+ko) ==== @@ -69,7 +69,7 @@ * Send the data. * Return: number of bytes sent, -1 on error. */ -int plugin_send(plugint *pl, char *data, int len); +int plugin_send(plugint *pl, char *data, int len, int data_type); #endif ==== //depot/projects/soc2007/mharvan-mtund/mtund.src/plugin_icmp.c#5 (text+ko) ==== @@ -7,32 +7,36 @@ * server always queues one packet at a time from the daemon. */ +#include <arpa/inet.h> #include <stdio.h> +#include <err.h> #include <errno.h> -#include <stdlib.h> -#include <unistd.h> -#include <syslog.h> -#include <string.h> -#include <time.h> - -#include <sys/types.h> -#include <sys/socket.h> -#include <arpa/inet.h> +#include <sys/time.h> +#include <event.h> +#include <fcntl.h> #include <netdb.h> - #include <netinet/in_systm.h> #include <netinet/in.h> #include <netinet/ip.h> #include <netinet/ip_icmp.h> - +#include <stdlib.h> +#include <string.h> +#include <sysexits.h> +#include <syslog.h> +#include <sys/socket.h> +#include <sys/sysctl.h> #include <sys/types.h> -#include <sys/sysctl.h> -#include <err.h> -#include <sysexits.h> +#include <time.h> +#include <unistd.h> #include "tunneld.h" #include "plugin.h" +/* + * how often should an empty request be sent to the server - This is + * useful when the server has data to send but the client doesn't. + */ +#define PLUGIN_ICMP_KEEP_ALIVE 1 typedef struct { int fd; /* udp socket to the other endpoint */ @@ -51,12 +55,22 @@ static struct sockaddr_in dst_addr; /* address of the other endpoint */ static socklen_t dst_addr_len = sizeof(dst_addr); -char *queued_data = NULL; -int queued_data_len = 0; -u_int16_t id = 0; -u_int16_t seq = 0; +/* normal data queue - regular traffic from the tun interface, ping request */ +char *queued_normal_data = NULL; +int queued_normal_data_len = 0; +/* urgent data queue - ping replies */ +char *queued_urgent_data = NULL; +int queued_urgent_data_len = 0; +u_int16_t id = 0; /* ICMP echo ID */ +u_int16_t seq = 0; /* ICMP echo SEQ */ +/* previous value of net.inet.icmp.echo_user sysctl variable */ int old_sysctl; size_t old_sysctl_size = sizeof(old_sysctl); +struct event ev; /* used by libevent to monitor our fd */ +int data_sent_after_last_receive = 0; /* has the client sent data + * after the last reply from the + * server was received? + */ u_int16_t in_cksum(u_int16_t *addr, int len) { @@ -175,6 +189,7 @@ struct addrinfo hints, *ai; int n; int new_sysctl = 1; + int fd_flags; plugin_icmp_datat *data = (plugin_icmp_datat*) pl->data; fprintf(stderr, "starting plugin_initialize...\n"); @@ -210,14 +225,23 @@ data->fd = socket (AF_INET, SOCK_RAW, IPPROTO_ICMP); if (data->fd != -1) { - register_select_fd(data->fd, plugin_receive, pl); + /* non-blocking i/o */ + fd_flags = fcntl(data->fd, F_GETFL, 0); + if (fd_flags == -1) + errx(EX_OSFILE, "Failed to get flags from the icmp socket fd\n"); + fcntl(data->fd, F_SETFL, fd_flags|O_NONBLOCK); + if (server) { + register_select_fd(data->fd, plugin_receive, pl, -1); data->state = PLUGIN_STATE_INITIALIZED; } else { + /* the client should send keep-alive request to the server */ + register_select_fd(data->fd, plugin_receive, pl, + PLUGIN_ICMP_KEEP_ALIVE); data->state = PLUGIN_STATE_CONNECTED; } - if (data->server) { + if (server) { #ifdef __FreeBSD__ if (0 != sysctlbyname("net.inet.icmp.echo_user", &old_sysctl, &old_sysctl_size, @@ -259,10 +283,12 @@ char* packet; struct my_icmp_hdr *icmp; + printf("send_icmp_pkt(): len: %d\n", len); + packet = malloc(sizeof(struct my_icmp_hdr) + len); if (!packet) { fprintf(stderr, "plugin_send: out of memory\n"); - return PLUGIN_SEND_ERROR_MALLOC; + return SEND_ERROR_MALLOC; } memset (packet, 0, sizeof(struct my_icmp_hdr) + len); memcpy (packet+sizeof(struct my_icmp_hdr), data, len); @@ -303,130 +329,177 @@ char serv[NI_MAXSERV]; struct my_icmp_hdr *icmp = NULL; + printf("plugin_receive(ev_type: 0x%x)\n", ev_type); + if (! (data->state == PLUGIN_STATE_CONNECTED || data->state == PLUGIN_STATE_INITIALIZED)) { return; } - fprintf(stderr, "data on plugin fd\n"); + /* upon timeout send another request to the server */ + if (ev_type == EV_TIMEOUT) { + register_select_fd(data->fd, plugin_receive, arg, + PLUGIN_ICMP_KEEP_ALIVE); + //goto send_request; + } n = recvfrom(data->fd, packet, sizeof(packet), 0, (struct sockaddr *) &from, &fromlen); - if (data->state != PLUGIN_STATE_CONNECTED) { - /* client connecting for the first time */ - - if (getnameinfo((struct sockaddr *) &from, fromlen, - host, sizeof(host), serv, sizeof(serv), - NI_NUMERICHOST | NI_DGRAM) ) { - fprintf(stderr, "getnameinfo failed: %s\n", - gai_strerror(errno)); - } else { - fprintf(stderr, "received traffic from client %s:%s\n", - host, serv); + printf("plugin_receive: read %d bytes\n", n); + + /* process the packet */ + if (n > -1) { + /* check whether the packet is for us */ + if (n < 20 + sizeof(struct my_icmp_hdr)) { + warnx("plugin_icmp: plugin_receive: received data too short " + "to contain IP and ICMP headers\n"); + goto pkt_not_for_us; } + /* IP header */ + packetp += 20; + n -= 20; + /* ICMP header */ + //icmp = (struct my_icmp_header*)packetp; + icmp = (void*)packetp; + packetp += sizeof(struct my_icmp_hdr); + n -= sizeof(struct my_icmp_hdr); - memcpy(&dst_addr, &from, fromlen); - dst_addr_len = fromlen; - data->state = PLUGIN_STATE_CONNECTED; - - } else { - // TODO: fix the comparison - if (n == -1) { - report_plugin_error(pl, PLUGIN_ERROR_RECEIVE); - return; - } - if (memcmp(&dst_addr, &from, dst_addr_len) != 0) { + /* check values in the ICMP header */ + if (//(ntohs(icmp->id) == id ) && + icmp->type != ((data->server)? ICMP_ECHO : ICMP_ECHOREPLY)) + //icmp->type != ((data->server)? 123 : ICMP_ECHOREPLY)) goto pkt_not_for_us; - } - if (n < 20 + sizeof(struct my_icmp_hdr)) { - warnx("plugin_icmp: plugin_receive: received data too short " - "to contain IP and ICMP headers\n"); - } else { - /* skip the IP header */ - packetp += 20; - n -= 20; + /* payload */ + if (data->state != PLUGIN_STATE_CONNECTED) { + /* client connecting for the first time */ - /* skip the icmp header */ - //icmp = (struct my_icmp_header*)packetp; - icmp = (void*)packetp; - packetp += sizeof(struct my_icmp_hdr); - n -= sizeof(struct my_icmp_hdr); + if (getnameinfo((struct sockaddr *) &from, fromlen, + host, sizeof(host), serv, sizeof(serv), + NI_NUMERICHOST | NI_DGRAM) ) { + fprintf(stderr, "getnameinfo failed: %s\n", + gai_strerror(errno)); + } else { + fprintf(stderr, "received traffic from client %s\n", host); + } - /* check values in the ICMP header */ - if (//(ntohs(icmp->id) == id ) && - icmp->type == ((data->server)? - ICMP_ECHO : ICMP_ECHOREPLY)) - process_data_from_plugin(pl, packetp, n); - // else // pkt not for us, send back an echo reply - // goto pkt_not_for_us; + //if xxx + memcpy(&dst_addr, &from, fromlen); + dst_addr_len = fromlen; + data->state = PLUGIN_STATE_CONNECTED; + // else goto pkt_no_for_us + } else { + if (memcmp(&dst_addr, &from, dst_addr_len) != 0) { + goto pkt_not_for_us; + } + + //if (ntohs(icmp->id) != id ) { + // pkt not for us, send back an echo reply + // goto pkt_not_for_us; + } + } + data_sent_after_last_receive = 0; + if (n > 0) + process_data_from_plugin(pl, packetp, n); + + // send_request: + /* if no data was queued then ask the daemon for more data */ + if (queued_urgent_data == NULL && queued_normal_data == NULL) + plugin_report(pl, REPORT_READY_TO_SEND); - /* use the reply to send data */ - if (queued_data != NULL) { - send_icmp_pkt(pl, ntohs(icmp->id), ntohs(icmp->seq), - queued_data, queued_data_len); - free(queued_data); - queued_data = NULL; - queued_data_len = 0; - report_plugin_error(pl, PLUGIN_ERROR_PKT_SENT); - } else if (!data->server) { /* client */ - /* client should send back an empty request - * to give the server a chance to send data back - */ - if (seq == 65535) - seq = 0; + /* use the reply to send data */ + if (queued_urgent_data != NULL || queued_normal_data != NULL) { + if (queued_urgent_data != NULL) { + send_icmp_pkt(pl, ntohs(icmp->id), ntohs(icmp->seq), + queued_urgent_data, queued_urgent_data_len); + free(queued_urgent_data); + queued_urgent_data = NULL; + queued_urgent_data_len = 0; + } else { + send_icmp_pkt(pl, ntohs(icmp->id), ntohs(icmp->seq), + queued_normal_data, queued_normal_data_len); + free(queued_normal_data); + queued_normal_data = NULL; + queued_normal_data_len = 0; + } + } + /* + * The client should send back an empty request if there was not + * data to sent. This allows the server to send more data back. + */ + if (!data->server && !data_sent_after_last_receive) { + if (seq == 65535) + seq = 0; else seq++; - send_icmp_pkt(pl, id, seq, NULL, 0); - } - } - return; + send_icmp_pkt(pl, id, seq, NULL, 0); + } + return; pkt_not_for_us: fprintf(stderr, "discarding data from a different client\n"); - } } int plugin_is_ready_to_send() { - if (queued_data == NULL) - return 1; + if (queued_normal_data == NULL) + return WILL_QUEUE; else - return 0; + return QUEUE_FULL; } int -plugin_send(plugint *pl, char *data, int len) +plugin_send(plugint *pl, char *data, int len, int data_type) { + char **queued_data; + int *queued_data_len; + plugin_icmp_datat *datapl = (plugin_icmp_datat*) pl->data; int n = 0; + printf("plugin_send(): urgent_data: %d, normal_data: %d\n", + queued_urgent_data_len, queued_normal_data_len); + if (datapl->state != PLUGIN_STATE_CONNECTED) { fprintf(stderr, "no client connected yet, discarding data\n"); - return PLUGIN_SEND_ERROR; + return SEND_ERROR; } - if (datapl->server) { /* server */ - if (queued_data == NULL) { - queued_data = malloc(len); - if (queued_data == NULL) { - return PLUGIN_SEND_ERROR_MALLOC; + if (datapl->server) { /* server - queue the data */ + switch (data_type) { + case NORMAL_DATA: + queued_data = &queued_normal_data; + queued_data_len = &queued_normal_data_len; + goto process_queued_data; + case URGENT_DATA: + queued_data = &queued_urgent_data; + queued_data_len = &queued_urgent_data_len; + process_queued_data: + if (*queued_data == NULL) { + *queued_data = malloc(len); + if (*queued_data == NULL) { + return SEND_ERROR_MALLOC; + } + memcpy(*queued_data, data, len); + *queued_data_len = len; + return SEND_PKT_QUEUED; + } else { + return SEND_ERROR_QUEUE_FULL; } - memcpy(queued_data, data, len); - queued_data_len = len; - return PLUGIN_SEND_PKT_QUEUED; - } else { - return PLUGIN_SEND_ERROR_QUEUE_FULL; + default: + errx(EX_SOFTWARE, "plugin_icmp: plugin_send(): invalid data_type " + "0x%x\n", data_type); } - } else { /* client */ + } else { /* client - send the data straight away */ n = send_icmp_pkt(pl, id, seq, data, len); seq++; fprintf(stderr, "send_icmp_pkt: send returned %d\n", n); - if (n > 0) - return PLUGIN_SEND_PKT_SENT; - else - return PLUGIN_SEND_ERROR; + if (n > 0) { + data_sent_after_last_receive = 1; + return SEND_PKT_SENT; + } else + return SEND_ERROR; } } ==== //depot/projects/soc2007/mharvan-mtund/mtund.src/plugin_tcp.c#7 (text+ko) ==== @@ -1,15 +1,14 @@ +#include <arpa/inet.h> +#include <errno.h> +#include <netdb.h> #include <stdio.h> -#include <errno.h> #include <stdlib.h> -#include <unistd.h> +#include <string.h> #include <syslog.h> -#include <string.h> -#include <time.h> - #include <sys/types.h> #include <sys/socket.h> -#include <arpa/inet.h> -#include <netdb.h> +#include <time.h> +#include <unistd.h> //#include <sys/select.h> #include "tunneld.h" @@ -234,7 +233,7 @@ } if (data->fd != -1) { - register_select_fd(data->fd, plugin_receive, pl); + register_select_fd(data->fd, plugin_receive, pl, -1); return 0; } else return -1; } @@ -258,7 +257,7 @@ //fprintf(stderr, "state: %d\n", data->state); if (! (data->state == PLUGIN_STATE_CONNECTED || data->state == PLUGIN_STATE_INITIALIZED)) { - report_plugin_error(pl, PLUGIN_ERROR_RECEIVE); + plugin_report(pl, REPORT_ERROR_RECEIVE); return; } @@ -267,15 +266,15 @@ new_fd = tcp_accept(fd); if (new_fd == -1) { fprintf(stderr, "accept failed\n"); - report_plugin_error(pl, PLUGIN_ERROR_RECEIVE); + plugin_report(pl, REPORT_ERROR_RECEIVE); } else { unregister_select_fd(data->fd); tcp_close(data->fd); data->fd = new_fd; - register_select_fd(data->fd, plugin_receive, pl); + register_select_fd(data->fd, plugin_receive, pl, -1); data->state = PLUGIN_STATE_CONNECTED; fprintf(stderr, "new client connection accepted\n"); - //report_plugin_error(pl, PLUGIN_ERROR_SUCCESS); + //plugin_report(pl, REPORT_SUCCESS); } } else { /* get length of the next packet */ @@ -293,7 +292,7 @@ } } process_data_from_plugin(pl, packet, n); - //report_plugin_error(pl, PLUGIN_ERROR_SUCCESS); + //plugin_report(pl, REPORT_SUCCESS); /* packet too large */ } else { fprintf(stderr, "client sent a too large packet (len: %d)\n", @@ -312,21 +311,21 @@ /* client disconnected */ unregister_select_fd(fd); data->state = PLUGIN_STATE_DISCONNECTED; - report_plugin_error(pl, PLUGIN_ERROR_RECEIVE); + plugin_report(pl, REPORT_ERROR_RECEIVE); } } int plugin_is_ready_to_send() { - return 1; + return WILL_SEND_IMMEDIATELY; } /* * BUG: the write might not send the whole buffer in one go, should check * and call again, but then the receiver would have to reassemble packets */ -int plugin_send(plugint *pl, char *data, int len) { +int plugin_send(plugint *pl, char *data, int len, int data_type) { plugin_tcp_datat *datapl = (plugin_tcp_datat*) pl->data; int n = 0; @@ -343,8 +342,8 @@ //fprintf(stderr, "plugin_send: write returned %d\n", n); } if (n < 0 || (len != 0 && n == 0) ) { - report_plugin_error(pl, PLUGIN_ERROR_RECEIVE); + plugin_report(pl, REPORT_ERROR_RECEIVE); } //return n; - return PLUGIN_SEND_PKT_SENT; + return SEND_PKT_SENT; } ==== //depot/projects/soc2007/mharvan-mtund/mtund.src/plugin_udp.c#6 (text+ko) ==== @@ -169,7 +169,7 @@ if (server) { data->fd = udp_open(port); if (data->fd != -1) { - register_select_fd(data->fd, plugin_receive, pl); + register_select_fd(data->fd, plugin_receive, pl, -1); data->state = PLUGIN_STATE_INITIALIZED; return 0; } @@ -178,10 +178,10 @@ if (data->fd != -1) { //n = send(fd,"test",5,0); //if (n == 5) { - register_select_fd(data->fd, plugin_receive, pl); - data->state = PLUGIN_STATE_CONNECTED; - return 0; - //} + register_select_fd(data->fd, plugin_receive, pl, -1); + data->state = PLUGIN_STATE_CONNECTED; + return 0; + //} } } return -1; @@ -250,10 +250,10 @@ int plugin_is_ready_to_send() { - return 1; + return WILL_SEND_IMMEDIATELY; } -int plugin_send(plugint *pl, char *data, int len) { +int plugin_send(plugint *pl, char *data, int len, int data_type) { plugin_udp_datat *datapl = (plugin_udp_datat*) pl->data; int n = 0; if (datapl->state != PLUGIN_STATE_CONNECTED) { @@ -263,5 +263,5 @@ n = send(datapl->fd, data, len, 0); fprintf(stderr, "plugin_send: send returned %d\n", n); } - return PLUGIN_SEND_PKT_SENT; + return SEND_PKT_SENT; } ==== //depot/projects/soc2007/mharvan-mtund/mtund.src/tun_dev.c#2 (text+ko) ==== ==== //depot/projects/soc2007/mharvan-mtund/mtund.src/tun_dev.c.freebsd#2 (text+ko) ==== ==== //depot/projects/soc2007/mharvan-mtund/mtund.src/tun_dev.c.linux#2 (text+ko) ==== ==== //depot/projects/soc2007/mharvan-mtund/mtund.src/tun_dev.h#2 (text+ko) ==== ==== //depot/projects/soc2007/mharvan-mtund/mtund.src/tunneld.c#14 (text+ko) ==== @@ -40,7 +40,7 @@ /* max transfered unit - encapsulated packet size */ #define MTU 1500 /* how many pings can fail before the plugin is declared broken */ -#define PING_INTERVAL 20 +#define PING_INTERVAL 7 #define PING_FAIL 3 int server = 0; /* are we a server or a client? */ @@ -55,7 +55,7 @@ struct event timer_ev; /* sequence number for the echo request */ -uint echo_seq = 0; +uint8_t echo_seq = 0; /* fragment id for the next packet to be fragmented */ frag_hdr_t frag_hdr; @@ -83,9 +83,13 @@ } fdlt; fdlt *fdl; -void register_select_fd(int fd, - void (*ev_callback)(int, short, void *arg), void *arg) +void +register_select_fd(int fd, + void (*ev_callback)(int, short, void *arg), + void *arg, long tv_sec) { + struct timeval tv; + fdlt* nfdl = malloc(sizeof(fdlt)); if (!nfdl) { fprintf(stderr, "failed to malloc an fdlt: out of mem!\n"); @@ -95,10 +99,15 @@ nfdl->next = fdl; fdl = nfdl; - //update_fdset(); + 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); - event_set(&nfdl->ev, fd, EV_PERSIST | EV_READ, ev_callback, arg); - event_add(&nfdl->ev, NULL); } void unregister_select_fd(int fd) { @@ -136,6 +145,20 @@ return system(cmd); } +void +set_current_pl(plugint* 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 + } +} + /* read data from the tun interface and pass it to the daemon */ static void tun_receive() @@ -149,19 +172,16 @@ return; do { - /* only read from the tun device of the plugin is ready to send data */ - if (current_pl->is_ready_to_send() != 0) { - memset(packet, 0, sizeof(packet)); - nread = tun_read(tun_fd, packet, PACKETLEN); - if (nread > 0) { - nwrite = process_data_from_tun(packet, nread); - } + //memset(packet, 0, sizeof(packet)); + nread = tun_read(tun_fd, packet, PACKETLEN); + if (nread > 0) { + nwrite = process_data_from_tun(packet, nread); } /* 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 == PLUGIN_SEND_PKT_SENT); + } while (nread > 0 && nwrite == SEND_PKT_SENT); } /* send data via the tun interface */ @@ -184,7 +204,14 @@ tun_ev_handler(int fd, short ev_type, void *arg) { printf("tun_ev_handler(): ev_type: 0x%x\n", ev_type); - tun_receive(); + /* + * 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(); } /* @@ -242,13 +269,15 @@ static void send_echo_request() { - char data[10]; + int nwrite = 0; + char data[2]; plugint *pl = current_pl; if (pl) { *data = DISPATCH_ECHO_REQUEST; *(data+1) = echo_seq++; - (void) pl->send(pl, data, sizeof(data)); + nwrite = pl->send(pl, data, sizeof(data), NORMAL_DATA); pl->ping_counter--; + printf("send_cho_request(): nwrite: 0x%x\n", nwrite); } } @@ -260,12 +289,11 @@ struct frag_info *np, *np_temp; plugint *pl = current_pl; - fprintf(stderr, "timer fired\n"); - /* check if too many ping requests have not failed */ if (pl) { - if (! pl->ping_counter) { - report_plugin_error(pl, PLUGIN_ERROR_PING); + printf("ping_counter: %d\n", pl->ping_counter); + if (pl->ping_counter <= 0) { + plugin_report(pl, REPORT_ERROR_PING); } else { send_echo_request(); } @@ -305,17 +333,20 @@ struct timeval tv; int i; int dgram_reassembled; + int nwrite; + + if (len <= 0) + return; switch (dispatch) { case DISPATCH_DATA: - if (len > 0) { - current_pl = pl; - } + 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)) { - report_plugin_error(pl, PLUGIN_ERROR_RECEIVE); + plugin_report(pl, REPORT_ERROR_RECEIVE); return; } @@ -407,7 +438,7 @@ /* packet completely reassembled */ if (dgram_reassembled) { fprintf(stderr, "frag reassembly: packet complete\n"); - current_pl = pl; + set_current_pl(pl); tun_send(p->buf, p->size); /* remove fragment info from linked list */ @@ -416,22 +447,31 @@ free(p->bitmap); free(p); } + goto plugin_ok; break; case DISPATCH_ECHO_REQUEST: + printf("process_data_from_plugin(): ECHO_REQUEST\n"); *data = (u_int8_t) DISPATCH_ECHO_REPLY; - pl->send(pl, data, len); + nwrite = pl->send(pl, data, len, URGENT_DATA); fprintf(stderr, "got echo request (plugin: %s)\n", pl->name); + printf("sending reply, returned 0x%x\n", nwrite); + goto plugin_ok; break; case DISPATCH_ECHO_REPLY: + printf("process_data_from_plugin(): ECHO_REPLY\n"); fprintf(stderr, "got echo reply (plugin: %s)\n", pl->name); - pl->ping_counter++; + pl->ping_counter = PING_FAIL; + //pl->ping_counter++; + goto plugin_ok; break; default: fprintf(stderr, "unknown dispatch 0x%X in data from plugin %s\n", dispatch, pl->name); } + plugin_ok: + set_current_pl(pl); } /* @@ -446,17 +486,19 @@ if (current_pl == NULL) { fprintf(stderr, "no plugin connected yet, discarding tun data\n"); - report_plugin_error(NULL, PLUGIN_ERROR_BOOTSTRAP); - return PLUGIN_SEND_ERROR; + plugin_report(NULL, REPORT_ERROR_BOOTSTRAP); + return SEND_ERROR; } - /* no need to add the fragmentation header */ printf("process_data_from_tun: len: %d, current_pl->mtu: %d\n", len, current_pl->mtu); + /* no need to add the fragmentation header */ + //TODO: fix fragmentation if (len < current_pl->mtu || 1) { *ldata = DISPATCH_DATA; memcpy(ldata+1, data, min(sizeof(ldata)-1, len)); - return current_pl->send(current_pl, ldata, min(sizeof(ldata), len+1)); + return current_pl->send(current_pl, ldata, min(sizeof(ldata), len+1), + NORMAL_DATA); /* add the fragmentation header */ } else { @@ -484,29 +526,34 @@ // on the return value from send() n = min(current_pl->mtu, len); (void) current_pl->send(current_pl, ldatap, - min(current_pl->mtu, len)); + min(current_pl->mtu, len), NORMAL_DATA); 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 PLUGIN_SEND_ERROR; + plugin_report(current_pl, REPORT_ERROR_SEND); + return SEND_ERROR; } ldatap += n; frag_hdr.offset += n; len -= n; } - return PLUGIN_SEND_PKT_SENT; + return SEND_PKT_SENT; } } void -report_plugin_error(plugint *pl, int err) +plugin_report(plugint *pl, int err) { + if (pl) + printf("plugin_report(%s, 0x%x)\n", pl->name, err); + else + printf("plugin_report(NULL plugin, 0x%x)\n", err); + switch (err) { - case PLUGIN_ERROR_SUCCESS: - return; - case PLUGIN_ERROR_PKT_SENT: +/* case PLUGIN_REPORT_SUCCESS: */ +/* return; */ + case REPORT_READY_TO_SEND: /* plugin is ready to send the next packet */ tun_receive(); return; @@ -541,7 +588,7 @@ fprintf(stderr, "initalizing plugin: %s...\n", pl->name); if (((pl->initialize)(pl, server, host, pl->name+4)) == 0) { fprintf(stderr, "found a working plugin: %s\n", pl->name); - current_pl = pl; + set_current_pl(pl); return; } else { fprintf(stderr, "plugin %s failed to initialize\n", @@ -655,7 +702,6 @@ fcntl(tun_fd, F_SETFL, tun_flags|O_NONBLOCK); /* watch the tun device with libevent */ event_set(&tun_ev, tun_fd, EV_PERSIST | EV_READ, tun_ev_handler, NULL); - event_add(&tun_ev, NULL); printf("Created tunnel device: %s\n", tun_dev); /* configure the tun interface */ @@ -709,7 +755,7 @@ } } else { /* initialize a working plugin */ - report_plugin_error(NULL, PLUGIN_ERROR_BOOTSTRAP); + plugin_report(NULL, REPORT_ERROR_BOOTSTRAP); } /* kick off the timer event, it will re-register itself */ ==== //depot/projects/soc2007/mharvan-mtund/mtund.src/tunneld.h#8 (text+ko) ==== @@ -43,39 +43,47 @@ int (*initialize)(struct _plugint*, int, char*, char*); void (*deinitialize)(struct _plugint*); void (*receive)(int fd, short ev_type, void *arg); /* select fired on some fd - check for data */ - int (*send)(struct _plugint*, char*, int); + int (*send)(struct _plugint*, char*, int, int); int (*is_ready_to_send)(); void* data; int mtu; struct _plugint *next; } plugint; -/* report_plugin_error() argument values */ +/* plugin_report() argument values */ +enum { + REPORT_READY_TO_SEND, /* ready to send the next packet */ + REPORT_ERROR_BOOTSTRAP, /* no plugin initialized yet */ + REPORT_ERROR_SEND, /* problem with sending */ + REPORT_ERROR_RECEIVE, /* problem with receiving */ + REPORT_ERROR_TIMEOUT, + REPORT_ERROR_PING, +}; + +/* plugin_is_ready_to_send() return values */ +enum { + WILL_SEND_IMMEDIATELY, + WILL_QUEUE, + QUEUE_FULL +}; + +/* plugin_send() argument */ enum { - PLUGIN_ERROR_SUCCESS = 0, - PLUGIN_ERROR_PKT_SENT, /* packet has been sent, - * ready to send the next one - */ - PLUGIN_ERROR_BOOTSTRAP, /* no plugin initialized yet */ - PLUGIN_ERROR_SEND, /* problem with sending */ - PLUGIN_ERROR_RECEIVE, /* problem with receiving */ - PLUGIN_ERROR_TIMEOUT, - PLUGIN_ERROR_PING, + NORMAL_DATA, /* normal data */ + URGENT_DATA /* urgent data */ }; /* plugin_send() return values */ enum { - PLUGIN_SEND_PKT_SENT = 0, /* packet has been sent, + SEND_PKT_SENT = 0, /* packet has been sent, * ready to send the next one */ - PLUGIN_SEND_PKT_QUEUED, /* packet queued, not yet ready + SEND_PKT_QUEUED, /* packet queued, not yet ready * to send the next one */ - PLUGIN_SEND_ERROR_MALLOC, /* malloc failed */ - PLUGIN_SEND_ERROR_QUEUE_FULL, /* packet queue is full, cannot yet - * send more packets - */ - PLUGIN_SEND_ERROR /* sending the packet failed */ + SEND_ERROR_MALLOC, /* malloc failed, packet dropped */ + SEND_ERROR_QUEUE_FULL, /* queue is full, packet dropped */ + SEND_ERROR /* sending the packet failed */ }; /* dispatch type - prepended before the payload */ @@ -90,8 +98,8 @@ /* * Register file descriptor fd to be watched by the main select(). */ -void register_select_fd(int fd, - void (*ev_callback)(int, short, void *arg), void *arg); +void register_select_fd(int fd, void (*ev_callback)(int, short, void *arg), + void *arg, long tv_sec); /* * Unregister file descriptor fd to no longer be watched by the main * select(). @@ -110,6 +118,6 @@ /* * Report a problem in the plugin to the daemon. */ -void report_plugin_error(plugint *pl, int err); +void plugin_report(plugint *pl, int err); #endif
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200708071838.l77Icx3B006470>