PERFORCE change 124841 for review
Matus Harvan
mharvan at FreeBSD.org
Tue Aug 7 11:39:00 PDT 2007
http://perforce.freebsd.org/chv.cgi?CH=124841
Change 124841 by mharvan at 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
More information about the p4-projects
mailing list