ead: add support for instance ids to prevent interference from packet reception on...
authornbd <nbd@3c298f89-4303-0410-b956-a3cf2f4a3e73>
Tue, 6 Jan 2009 22:19:55 +0000 (22:19 +0000)
committernbd <nbd@3c298f89-4303-0410-b956-a3cf2f4a3e73>
Tue, 6 Jan 2009 22:19:55 +0000 (22:19 +0000)
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@13905 3c298f89-4303-0410-b956-a3cf2f4a3e73

package/ead/src/ead-client.c
package/ead/src/ead.c
package/ead/src/ead.h

index 2592c8f..7f462c1 100644 (file)
@@ -62,6 +62,7 @@ static struct t_num *A, B;
 static struct t_preconf *tcp;
 static int auth_type = EAD_AUTH_DEFAULT;
 static int timeout = EAD_TIMEOUT;
+static uint16_t sid = 0;
 
 static void
 set_nonblock(int enable)
@@ -157,6 +158,7 @@ handle_pong(void)
        auth_type = ntohs(pong->auth_type);
        if (nid == 0xffff)
                printf("%04x: %s\n", ntohs(msg->nid), pong->name);
+       sid = msg->sid;
        return true;
 }
 
@@ -320,7 +322,7 @@ int main(int argc, char **argv)
        int ch;
 
        msg->magic = htonl(EAD_MAGIC);
-       msg->tid = 0;
+       msg->sid = 0;
 
        memset(&local, 0, sizeof(local));
        memset(&remote, 0, sizeof(remote));
index 6a01ea4..9ce6f56 100644 (file)
 #define DEBUG(n, format, ...) do {} while(0)
 #endif
 
+struct ead_instance {
+       struct list_head list;
+       char ifname[16];
+       int pid;
+       char id;
+#ifdef linux
+       char bridge[16];
+       bool br_check;
+#endif
+};
+
 static char ethmac[6] = "\x00\x13\x37\x00\x00\x00"; /* last 3 bytes will be randomized */
 static pcap_t *pcap_fp = NULL;
 static pcap_t *pcap_fp_rx = NULL;
-static const char *ifname = DEFAULT_IFNAME;
 static char pktbuf_b[PCAP_MRU];
 static struct ead_packet *pktbuf = (struct ead_packet *)pktbuf_b;
 static u16_t nid = 0xffff; /* node id */
@@ -85,20 +95,7 @@ static unsigned char pw_saltbuf[MAXSALTLEN];
 static struct list_head instances;
 static const char *dev_name = DEFAULT_DEVNAME;
 static bool nonfork = false;
-
-#ifdef linux
-static const char *brname = NULL;
-#endif
-
-struct ead_instance {
-       struct list_head list;
-       char name[16];
-       int pid;
-#ifdef linux
-       char bridge[16];
-       bool br_check;
-#endif
-};
+static struct ead_instance *instance = NULL;
 
 static struct t_pwent tpe = {
        .name = username,
@@ -113,6 +110,20 @@ static struct t_server *ts = NULL;
 static struct t_num A, *B = NULL;
 unsigned char *skey;
 
+static void
+get_random_bytes(void *ptr, int len)
+{
+       int fd;
+
+       fd = open("/dev/urandom", O_RDONLY);
+       if (fd < 0) {
+               perror("open");
+               exit(1);
+       }
+       read(fd, ptr, len);
+       close(fd);
+}
+
 static bool
 prepare_password(void)
 {
@@ -539,6 +550,11 @@ parse_message(struct ead_packet *pkt, int len)
                (state != type))
                return;
 
+       if ((type != EAD_TYPE_PING) &&
+               ((ntohs(pkt->msg.sid) & EAD_INSTANCE_MASK) >>
+                EAD_INSTANCE_SHIFT) != instance->id)
+               return;
+
        switch(type) {
        case EAD_TYPE_PING:
                handler = handle_ping;
@@ -574,6 +590,7 @@ parse_message(struct ead_packet *pkt, int len)
        pktbuf->msg.magic = htonl(EAD_MAGIC);
        pktbuf->msg.type = htonl(type + 1);
        pktbuf->msg.nid = htons(nid);
+       pktbuf->msg.sid = pkt->msg.sid;
        pktbuf->msg.len = 0;
 
        if (handler(pkt, len, &nstate)) {
@@ -630,16 +647,16 @@ ead_pcap_reopen(bool first)
 
        pcap_fp_rx = NULL;
        do {
-               pcap_fp = pcap_open_live(ifname, PCAP_MRU, 1, PCAP_TIMEOUT, errbuf);
+               pcap_fp = pcap_open_live(instance->ifname, PCAP_MRU, 1, PCAP_TIMEOUT, errbuf);
 #ifdef linux
-               if (brname)
-                       pcap_fp_rx = pcap_open_live(brname, PCAP_MRU, 1, PCAP_TIMEOUT, errbuf);
+               if (instance->bridge[0])
+                       pcap_fp_rx = pcap_open_live(instance->bridge, PCAP_MRU, 1, PCAP_TIMEOUT, errbuf);
 #endif
                if (!pcap_fp_rx)
                        pcap_fp_rx = pcap_fp;
                pcap_setfilter(pcap_fp_rx, &pktfilter);
                if (first && !pcap_fp) {
-                       DEBUG(1, "WARNING: unable to open interface '%s'\n", ifname);
+                       DEBUG(1, "WARNING: unable to open interface '%s'\n", instance->ifname);
                        first = false;
                }
                if (!pcap_fp)
@@ -712,12 +729,8 @@ start_server(struct ead_instance *i)
                }
        }
 
+       instance = i;
        signal(SIGCHLD, instance_handle_sigchld);
-       ifname = i->name;
-#ifdef linux
-       if (i->bridge[0])
-               brname = i->bridge;
-#endif
        ead_pcap_reopen(true);
        ead_pktloop();
        pcap_close(pcap_fp);
@@ -779,7 +792,7 @@ check_bridge_port(const char *br, const char *port, void *arg)
        list_for_each(p, &instances) {
                in = list_entry(p, struct ead_instance, list);
 
-               if (strcmp(in->name, port) != 0)
+               if (strcmp(in->ifname, port) != 0)
                        continue;
 
                in->br_check = true;
@@ -787,7 +800,7 @@ check_bridge_port(const char *br, const char *port, void *arg)
                        break;
 
                strncpy(in->bridge, br, sizeof(in->bridge));
-               DEBUG(2, "assigning port %s to bridge %s\n", in->name, in->bridge);
+               DEBUG(2, "assigning port %s to bridge %s\n", in->ifname, in->bridge);
                stop_server(in, false);
        }
        return 0;
@@ -817,7 +830,7 @@ check_all_interfaces(void)
                if (in->br_check) {
                        in->br_check = false;
                } else if (in->bridge[0]) {
-                       DEBUG(2, "removing port %s from bridge %s\n", in->name, in->bridge);
+                       DEBUG(2, "removing port %s from bridge %s\n", in->ifname, in->bridge);
                        in->bridge[0] = 0;
                        stop_server(in, false);
                }
@@ -830,10 +843,10 @@ int main(int argc, char **argv)
 {
        struct ead_instance *in;
        struct timeval tv;
-       int fd, ch;
        const char *pidfile = NULL;
        bool background = false;
        int n_iface = 0;
+       int fd, ch;
 
        if (argc == 1)
                return usage(argv[0]);
@@ -853,9 +866,9 @@ int main(int argc, char **argv)
                        in = malloc(sizeof(struct ead_instance));
                        memset(in, 0, sizeof(struct ead_instance));
                        INIT_LIST_HEAD(&in->list);
-                       strncpy(in->name, optarg, sizeof(in->name) - 1);
+                       strncpy(in->ifname, optarg, sizeof(in->ifname) - 1);
                        list_add(&in->list, &instances);
-                       n_iface++;
+                       in->id = n_iface++;
                        break;
                case 'D':
                        dev_name = optarg;
@@ -902,13 +915,7 @@ int main(int argc, char **argv)
        }
 
        /* randomize the mac address */
-       fd = open("/dev/urandom", O_RDONLY);
-       if (fd < 0) {
-               perror("open");
-               exit(1);
-       }
-       read(fd, ethmac + 3, 3);
-       close(fd);
+       get_random_bytes(ethmac + 3, 3);
        nid = *(((u16_t *) ethmac) + 2);
 
        start_servers(false);
index 36db0f5..54505ce 100644 (file)
@@ -114,12 +114,16 @@ struct ead_msg_encrypted {
 #define EAD_DATA(_msg, _type) (&((_msg)->data[0]._type))
 #define EAD_ENC_DATA(_msg, _type) (&((_msg)->data[0].enc.data[0]._type))
 
+/* for ead_msg::sid */
+#define EAD_INSTANCE_MASK      0xf000
+#define EAD_INSTANCE_SHIFT     12
+
 struct ead_msg {
        uint32_t magic;
        uint32_t len;
        uint32_t type;
        uint16_t nid; /* node id */
-       uint16_t tid; /* transaction id */
+       uint16_t sid; /* session id */
        uint32_t ip; /* source ip for responses from the server */
        union {
                struct ead_msg_pong pong;