PERFORCE change 122228 for review
Matus Harvan
mharvan at FreeBSD.org
Sun Jun 24 12:58:55 UTC 2007
http://perforce.freebsd.org/chv.cgi?CH=122228
Change 122228 by mharvan at 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 <stdlib.h>
#include <getopt.h>
-#include <sys/select.h>
+//#include <sys/select.h>
#include <dlfcn.h>
+#include <signal.h>
+#include <sys/time.h>
+#include <event.h>
#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
More information about the p4-projects
mailing list