From owner-p4-projects@FreeBSD.ORG Sun Jun 24 12:58:55 2007 Return-Path: X-Original-To: p4-projects@freebsd.org Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id CB64716A421; Sun, 24 Jun 2007 12:58:54 +0000 (UTC) X-Original-To: perforce@FreeBSD.org Delivered-To: perforce@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id 9104416A400 for ; Sun, 24 Jun 2007 12:58:54 +0000 (UTC) (envelope-from mharvan@FreeBSD.org) Received: from repoman.freebsd.org (repoman.freebsd.org [69.147.83.41]) by mx1.freebsd.org (Postfix) with ESMTP id 7F9EA13C44C for ; Sun, 24 Jun 2007 12:58:54 +0000 (UTC) (envelope-from mharvan@FreeBSD.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.13.8/8.13.8) with ESMTP id l5OCwsqP030996 for ; Sun, 24 Jun 2007 12:58:54 GMT (envelope-from mharvan@FreeBSD.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.13.8/8.13.8/Submit) id l5OCws3V030993 for perforce@freebsd.org; Sun, 24 Jun 2007 12:58:54 GMT (envelope-from mharvan@FreeBSD.org) Date: Sun, 24 Jun 2007 12:58:54 GMT Message-Id: <200706241258.l5OCws3V030993@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 122228 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: Sun, 24 Jun 2007 12:58:55 -0000 http://perforce.freebsd.org/chv.cgi?CH=122228 Change 122228 by mharvan@mharvan_home on 2007/06/24 12:58:32 rewrite to use libevent to report errors plugins now call a special function in the daemon Affected files ... .. //depot/projects/soc2007/mharvan-mtund/mtund.src/Makefile#2 edit .. //depot/projects/soc2007/mharvan-mtund/mtund.src/plugin.h#2 edit .. //depot/projects/soc2007/mharvan-mtund/mtund.src/plugin_tcp.c#2 edit .. //depot/projects/soc2007/mharvan-mtund/mtund.src/plugin_udp.c#2 edit .. //depot/projects/soc2007/mharvan-mtund/mtund.src/tunneld.c#2 edit .. //depot/projects/soc2007/mharvan-mtund/mtund.src/tunneld.h#2 edit Differences ... ==== //depot/projects/soc2007/mharvan-mtund/mtund.src/Makefile#2 (text+ko) ==== @@ -1,6 +1,10 @@ # Linux needs -ldl -#LIBS= -ldl -CFLAGS=-Wall -rdynamic -g +#LIBS+= -ldl + +LIBS=-L/usr/local/lib -levent +CFLAGS=-Wall -rdynamic +CFLAGS+=-g +CFLAGS+=-I/usr/local/include all: tunneld plugin_tcp.so plugin_udp.so ==== //depot/projects/soc2007/mharvan-mtund/mtund.src/plugin.h#2 (text+ko) ==== @@ -57,7 +57,7 @@ * from the client was accepted, return >0 so that it becomes the * current_pl! */ -int plugin_receive(plugint *pl); +void plugin_receive(int fd, short ev_type, void *arg); /* * Send the data. ==== //depot/projects/soc2007/mharvan-mtund/mtund.src/plugin_tcp.c#2 (text+ko) ==== @@ -228,7 +228,7 @@ } if (data->fd != -1) { - register_select_fd(data->fd); + register_select_fd(data->fd, plugin_receive, pl); return 0; } else return -1; } @@ -240,7 +240,8 @@ data->state = PLUGIN_STATE_UNINITIALIZED; } -int plugin_receive(plugint *pl) { +void plugin_receive(int fd, short ev_type, void *arg) { + plugint *pl = (plugint *) arg; plugin_tcp_datat *data = (plugin_tcp_datat*) pl->data; int n = 0; char packet[PACKETLEN]; @@ -249,41 +250,38 @@ //fprintf(stderr, "state: %d\n", data->state); if (! (data->state == PLUGIN_STATE_CONNECTED || data->state == PLUGIN_STATE_INITIALIZED)) { - return -1; + report_plugin_error(pl, PLUGIN_ERROR_RECEIVE); } - if (fd_isset(data->fd)) { - //fprintf(stderr, "data on plugin fd\n"); - - if (data->state != PLUGIN_STATE_CONNECTED) { - new_fd = tcp_accept(data->fd); - if (new_fd == -1) { - fprintf(stderr, "accept failed\n"); - return -1; - } else { - unregister_select_fd(data->fd); - tcp_close(data->fd); - data->fd = new_fd; - register_select_fd(data->fd); - data->state = PLUGIN_STATE_CONNECTED; - fprintf(stderr, "new client connection accepted\n"); - return 1; - } + //fprintf(stderr, "data on plugin fd\n"); + if (data->state != PLUGIN_STATE_CONNECTED) { + new_fd = tcp_accept(fd); + if (new_fd == -1) { + fprintf(stderr, "accept failed\n"); + report_plugin_error(pl, PLUGIN_ERROR_RECEIVE); } else { - //n = read(data->fd, packet, sizeof(packet)); - n = recv(data->fd, packet, sizeof(packet),0); - fprintf(stderr, "n: %d\n", n); - if (n <= 0) { - /* client disconnected */ - unregister_select_fd(data->fd); - data->state = PLUGIN_STATE_DISCONNECTED; - return -1; - } else if (n > 0) { - return tun_send(packet, n); - } + unregister_select_fd(data->fd); + tcp_close(data->fd); + data->fd = new_fd; + register_select_fd(data->fd, plugin_receive, pl); + data->state = PLUGIN_STATE_CONNECTED; + fprintf(stderr, "new client connection accepted\n"); + //report_plugin_error(pl, PLUGIN_ERROR_SUCCESS); + } + } else { + //n = read(data->fd, packet, sizeof(packet)); + n = recv(fd, packet, sizeof(packet),0); + //fprintf(stderr, "n: %d\n", n); + if (n <= 0) { + /* client disconnected */ + unregister_select_fd(fd); + data->state = PLUGIN_STATE_DISCONNECTED; + report_plugin_error(pl, PLUGIN_ERROR_RECEIVE); + } else if (n > 0) { + process_data_from_plugin(pl, packet, n); } } - return 0; + //report_plugin_error(pl, PLUGIN_ERROR_SUCCESS); } /* @@ -299,8 +297,11 @@ } else { //n = write(datapl->fd, data, len); n = send(datapl->fd, data, len, 0); - fprintf(stderr, "plugin_send: fd: %d\n", datapl->fd); - fprintf(stderr, "plugin_send: write returned %d\n", n); + //fprintf(stderr, "plugin_send: fd: %d\n", datapl->fd); + //fprintf(stderr, "plugin_send: write returned %d\n", n); + } + if (n < 0 || (len != 0 && n == 0) ) { + report_plugin_error(pl, PLUGIN_ERROR_RECEIVE); } return n; } ==== //depot/projects/soc2007/mharvan-mtund/mtund.src/plugin_udp.c#2 (text+ko) ==== @@ -165,7 +165,7 @@ if (server) { data->fd = udp_open(port); if (data->fd != -1) { - register_select_fd(data->fd); + register_select_fd(data->fd, plugin_receive, pl); data->state = PLUGIN_STATE_INITIALIZED; return 0; } @@ -174,7 +174,7 @@ if (data->fd != -1) { //n = send(fd,"test",5,0); //if (n == 5) { - register_select_fd(data->fd); + register_select_fd(data->fd, plugin_receive, pl); data->state = PLUGIN_STATE_CONNECTED; return 0; //} @@ -190,7 +190,8 @@ data->state = PLUGIN_STATE_UNINITIALIZED; } -int plugin_receive(plugint *pl) { +void plugin_receive(int fd, short ev_type, void *arg) { + plugint *pl = (plugint *) arg; plugin_udp_datat *data = (plugin_udp_datat*) pl->data; int n = 0; char packet[PACKETLEN]; @@ -201,46 +202,45 @@ if (! (data->state == PLUGIN_STATE_CONNECTED || data->state == PLUGIN_STATE_INITIALIZED)) { - return -1; + //return -1; } - if (fd_isset(data->fd)) { - fprintf(stderr, "data on plugin fd\n"); + fprintf(stderr, "data on plugin fd\n"); - if (data->state != PLUGIN_STATE_CONNECTED) { - /* client connecting for the first time, connect back */ - n = recvfrom(data->fd, packet, sizeof(packet), 0, - (struct sockaddr *) &from, &fromlen); - - 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); - } - - if (connect(data->fd, (struct sockaddr *) &from, fromlen) == 0) { - data->state = PLUGIN_STATE_CONNECTED; - fprintf(stderr, "connected to client %s:%s\n", host, serv); + if (data->state != PLUGIN_STATE_CONNECTED) { + /* client connecting for the first time, connect back */ + n = recvfrom(data->fd, packet, sizeof(packet), 0, + (struct sockaddr *) &from, &fromlen); + + 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); + } + + if (connect(data->fd, (struct sockaddr *) &from, fromlen) == 0) { + data->state = PLUGIN_STATE_CONNECTED; + fprintf(stderr, "connected to client %s:%s\n", host, serv); } else { fprintf(stderr, "failed to connect to client %s:%s\n", host, serv); } - } else { - n = recv(data->fd, packet, sizeof(packet), 0); - } - - if (n == -1) { - return -1; - } else if (n > 0) { - return tun_send(packet, n); - } - fprintf(stderr, "plugin_receive: recv return 0\n"); + } else { + n = recv(data->fd, packet, sizeof(packet), 0); + } + + if (n == -1) { + //return -1; + } else if (n > 0) { + process_data_from_plugin(pl, packet, n); + //return tun_send(packet, n); } - return 0; + fprintf(stderr, "plugin_receive: recv return 0\n"); + //return 0; } int plugin_send(plugint *pl, char *data, int len) { ==== //depot/projects/soc2007/mharvan-mtund/mtund.src/tunneld.c#2 (text+ko) ==== @@ -16,8 +16,11 @@ #include #include -#include +//#include #include +#include +#include +#include #include "tun_dev.h" @@ -28,11 +31,17 @@ int server = 0; /* are we a server or a client? */ plugint *plugins = NULL; /* linked list of loaded plugins */ -int tun_fd = 0; /* tunnel device */ 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; +char *host; +char *port = "12345"; + + /* * helper function to register/unregisted/check file descriptors to be * watched by select @@ -41,20 +50,14 @@ /* helper structure to put file descriptors into a linked list */ typedef struct _fdlt { int fd; + struct event ev; struct _fdlt *next; } fdlt; fdlt *fdl; -static void update_fdset() { - fdlt *p; - - FD_ZERO(&fdset); - for(p = fdl; p; p=p->next) { - FD_SET(p->fd, &fdset); - } -} - -void register_select_fd(int fd) { +void register_select_fd(int fd, + void (*ev_callback)(int, short, void *arg), void *arg) +{ fdlt* nfdl = malloc(sizeof(fdlt)); if (!nfdl) { fprintf(stderr, "failed to malloc an fdlt: out of mem!\n"); @@ -63,7 +66,11 @@ nfdl->fd = fd; nfdl->next = fdl; fdl = nfdl; + //update_fdset(); + + event_set(&nfdl->ev, fd, EV_PERSIST | EV_READ, ev_callback, arg); + event_add(&nfdl->ev, NULL); } void unregister_select_fd(int fd) { @@ -71,6 +78,11 @@ 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; } @@ -82,94 +94,55 @@ return FD_ISSET(fd, &fdset); } -static int max_fd() { - int m = -1; - fdlt *p; - for(p = fdl;p;p=p->next) { - fprintf(stderr, "p->fd: %d\n", p->fd); - if (p->fd > m) - m = p->fd; - } - fprintf(stderr, "maxfd: %d\n", m); - return m; +int +ssystem(const char *fmt, ...) +{ + char cmd[128]; + va_list ap; + va_start(ap, fmt); + vsnprintf(cmd, sizeof(cmd), fmt, ap); + va_end(ap); + fprintf(stderr, "%s\n", cmd); + //fflush(stderr); + //fflush(stdout); + return system(cmd); } /* tun functions - this could be turned into a plugin as well */ -int tun_receive() { +void tun_receive(int fd, short ev_type, void *arg) { char packet[PACKETLEN]; int result = 0; - if (fd_isset(tun_fd)) { - /* data available on tunnel device */ - memset(packet, 0, sizeof(packet)); - result = tun_read(tun_fd, packet, PACKETLEN); - if (!result) { - return 0; - } else if (result==-1) { - perror ("read"); - return -1; - } - fprintf(stderr, "data on tun interface\n"); - if (current_pl == NULL) { - fprintf(stderr, "no plugin connected yet, discarding tun data\n"); - return 0; - } - result = current_pl->send(current_pl, packet, result); - if (result==-1) { - perror ("plugin_send returned -1"); - } + /* data available on tunnel device */ + memset(packet, 0, sizeof(packet)); + result = tun_read(tun_fd, packet, PACKETLEN); + + if (!result) { + //return 0; + } else if (result==-1) { + perror ("read"); + //return -1; } - return result; + //fprintf(stderr, "data on tun interface\n"); + process_data_from_tun(packet, result); + //return result; } int tun_send(char *data, int len) { int n; n = tun_write(tun_fd, data, len); - fprintf(stderr, "tun_send: send returned %d\n", n); + /* + if (n != len) { + fprintf(stderr, "tun_send: tun_write wrote less bytes (%d) than " + "requested (%d)\n", n, len); + // report error + } + */ return n; } /* - * sit in select - * call tun_receive and plugin_receive when select fires - */ -static int tunnel_select() { - int result_tun = 0; - int result_plugin = 0; - int n = 0; - plugint *pl; - - while (result_tun >= 0 && result_plugin >= 0) { - update_fdset(); - select (max_fd()+1, &fdset, NULL, NULL, NULL); - fprintf(stderr, "tunnel_select: select fired\n"); - - fprintf(stderr, "tunnel_select: server: %d\n", server); - - result_tun = tun_receive(); - if (server) { - /* check all plugins */ - result_plugin = -1; - for (pl=plugins; pl; pl = pl->next) { - fprintf(stderr, "select - calling \"%s\"->receive()...", - pl->name); - n = pl->receive(pl); - fprintf(stderr, "%d\n", n); - if (n > 0) current_pl = pl; - if (n > result_plugin) result_plugin = n; - } - } else { - result_plugin = (current_pl->receive)(current_pl); - } - - fprintf(stderr, "tunnel_select: result_tun: %d, result_plugin: %d\n", - result_tun, result_plugin); - } - return 0; -} - -/* * 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 @@ -214,6 +187,87 @@ return 2; } +/* + * Pass data received by the plugin to the daemon. + */ +void process_data_from_plugin(plugint *pl, char *data, int len) +{ + tun_send(data, len); +} + +/* + * Pass data received from the tun interface to the daemon. + */ +void process_data_from_tun(char *data, int len) +{ + int n; + + if (current_pl == NULL) { + fprintf(stderr, "no plugin connected yet, discarding tun data\n"); + report_plugin_error(NULL, PLUGIN_ERROR_BOOTSTRAP); + } + + n = current_pl->send(current_pl, data, len); + + if (n < len) { + fprintf(stderr, "process_data_from_tun: plugind sent less " + "bytes (%d) than requested (%d)\n", n, len); + } +} + +void report_plugin_error(plugint *pl, int err) +{ + if (err == PLUGIN_ERROR_SUCCESS) { + return; + } + + if (!server) { + if (pl) { + /* deinitialize the broken plugin */ + fprintf(stderr, "plugin failed: %s\n", pl->name); + pl->deinitialize(pl); + } + + /* scan - find a working plugin */ + //for (pl=plugins; pl; pl = pl->next) { + if (!pl) pl=plugins; + for (; pl; pl = pl->next) { + /* try to initialize plugin */ + //if (((pl->initialize)(server, host, port)) == 0) { + 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; + return; + } else { + fprintf(stderr, "plugin %s failed to initialize\n", pl->name); + } + } + } +} + +void cleanup() +{ + plugint *pl; + + event_del(&tun_ev); + tun_close(tun_fd, tun_dev); + + /* deinitialize all plugins and free memory */ + while(plugins) { + pl = plugins; + plugins=plugins->next; + pl->deinitialize(pl); + free(pl); + } + exit(0); +} + +void sigcb(int sig) +{ + cleanup(); +} + void usage() { fprintf(stderr, "usage:\n"); fprintf(stderr, "server: tunneld -s -p port\n"); @@ -221,13 +275,9 @@ } int main(int argc, char **argv) { - char dev[16]; plugint *pl; char opt; - char *host; - char *port = "12345"; - /* argument parsing */ while((opt=getopt(argc, argv, "scp:")) != EOF) { switch(opt) { @@ -263,15 +313,33 @@ } } + /* Initalize the event library */ + event_init(); + /* create the tunnel device */ - dev[0] = 0; - tun_fd = tun_open(dev); + tun_dev[0] = 0; + tun_fd = tun_open(tun_dev); if (tun_fd < 1) { printf("Could not create tunnel device\n"); return 1; } - register_select_fd(tun_fd); - printf("Created tunnel device: %s\n", dev); + /* Initalize one event */ + event_set(&tun_ev, tun_fd, EV_PERSIST | EV_READ, tun_receive, NULL); + /* Add it to the active events, without a timeout */ + event_add(&tun_ev, NULL); + //register_select_fd(tun_fd); + printf("Created tunnel device: %s\n", tun_dev); + + /* setup the tun interface */ + if (server) { + system("ifconfig tun0 mtu 1400 192.168.0.1 192.168.0.2"); + } else { + system("ifconfig tun0 mtu 1400 192.168.0.2 192.168.0.1"); + } + + signal(SIGHUP, sigcb); + signal(SIGINT, sigcb); + signal(SIGTERM, sigcb); /* load plugins */ load_plugin("./plugin_udp.so"); @@ -282,7 +350,7 @@ plugins->name = "tcp_2222"; load_plugin("./plugin_tcp.so"); plugins->name = "tcp_3333"; - + if (server) { /* initialize all plugins */ for (pl=plugins; pl; pl = pl->next) { @@ -290,43 +358,14 @@ (void) (pl->initialize)(pl, server, host, pl->name+4); /* we should unload plugins which fail to initialize */ } - /* - * start tunneling - * - wait in select to see which plugin will be used (its fd will fire) - */ - tunnel_select(); - - /* deinitialize all plugins */ - for (pl=plugins; pl; pl = pl->next) { - pl->deinitialize(pl); - } } else { - /* scan - find a working plugin */ - for (pl=plugins; pl; pl = pl->next) { - /* try to initialize plugin */ - //if (((pl->initialize)(server, host, port)) == 0) { - if (((pl->initialize)(pl, server, host, pl->name+4)) == 0) { - fprintf(stderr, "found a working plugin: %s\n", pl->name); - current_pl = pl; - - /* start tunneling */ - tunnel_select(); - - fprintf(stderr, "plugin failed: %s\n", pl->name); - pl->deinitialize(pl); - } else { - fprintf(stderr, "plugin %s failed to initialize\n", pl->name); - } - } + /* initialize a working plugin */ + report_plugin_error(NULL, PLUGIN_ERROR_BOOTSTRAP); } - tun_close(tun_fd, dev); - - while(plugins) { - pl = plugins; - plugins=plugins->next; - free(pl); - } - - return 0; + /* start tunneling */ + event_dispatch(); + + cleanup(); + return 1; } ==== //depot/projects/soc2007/mharvan-mtund/mtund.src/tunneld.h#2 (text+ko) ==== @@ -18,16 +18,25 @@ int (*initialize)(struct _plugint*, int, char*, char*); void (*deinitialize)(struct _plugint*); int (*send)(struct _plugint*, char*, int); - int (*receive)(struct _plugint*); /* select fired on some fd - check for data */ + void (*receive)(int fd, short ev_type, void *arg); /* select fired on some fd - check for data */ void* data; struct _plugint *next; } plugint; +enum { + PLUGIN_ERROR_SUCCESS = 0, + PLUGIN_ERROR_BOOTSTRAP, + PLUGIN_ERROR_SEND, + PLUGIN_ERROR_RECEIVE, + PLUGIN_ERROR_TIMEOUT +}; + /* --- select() --- */ /* * Register file descriptor fd to be watched by the main select(). */ -void register_select_fd(int fd); +void register_select_fd(int fd, + void (*ev_callback)(int, short, void *arg), void *arg); /* * Unregister file descriptor fd to no longer be watched by the main * select(). @@ -36,12 +45,27 @@ /* * Check whether select fired on the file descriptor - wrapper for FD_ISSET. */ -int fd_isset(int fd); +//int fd_isset(int fd); /* --- tunnel --- */ /* * Send data over the tun interface. */ -int tun_send(char *data, int len); +//int tun_send(char *data, int len); + +/* + * Pass data received by the plugin to the daemon. + */ +void process_data_from_plugin(plugint *pl, char *data, int len); + +/* + * Pass data received from the tun interface to the daemon. + */ +void process_data_from_tun(char *data, int len); + +/* + * Report a problem in the plugin to the daemon. + */ +void report_plugin_error(plugint *pl, int err); #endif