ead: add support for instance ids to prevent interference from packet reception on...
[openwrt.git] / package / ead / src / ead.c
1 /*
2  * Emergency Access Daemon
3  * Copyright (C) 2008 Felix Fietkau <nbd@openwrt.org>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2
7  * as published by the Free Software Foundation
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  */
14
15 #include <sys/types.h>
16 #include <sys/time.h>
17 #include <sys/select.h>
18 #include <stdio.h>
19 #include <stddef.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <unistd.h>
23 #include <stdbool.h>
24 #include <fcntl.h>
25 #include <signal.h>
26 #include <pcap.h>
27 #include <pcap-bpf.h>
28 #include <t_pwd.h>
29 #include <t_read.h>
30 #include <t_sha.h>
31 #include <t_defines.h>
32 #include <t_server.h>
33
34 #include "list.h"
35 #include "ead.h"
36 #include "ead-pcap.h"
37 #include "ead-crypt.h"
38
39 #include "filter.c"
40
41 #ifdef linux
42 #include "libbridge_init.c"
43 #endif
44
45 #define PASSWD_FILE     "/etc/passwd"
46
47 #ifndef DEFAULT_IFNAME
48 #define DEFAULT_IFNAME "eth0"
49 #endif
50
51 #ifndef DEFAULT_DEVNAME
52 #define DEFAULT_DEVNAME "Unknown"
53 #endif
54
55 #define PCAP_MRU                1600
56 #define PCAP_TIMEOUT    200
57
58 #if EAD_DEBUGLEVEL >= 1
59 #define DEBUG(n, format, ...) do { \
60         if (EAD_DEBUGLEVEL >= n) \
61                 fprintf(stderr, format, ##__VA_ARGS__); \
62 } while (0);
63
64 #else
65 #define DEBUG(n, format, ...) do {} while(0)
66 #endif
67
68 struct ead_instance {
69         struct list_head list;
70         char ifname[16];
71         int pid;
72         char id;
73 #ifdef linux
74         char bridge[16];
75         bool br_check;
76 #endif
77 };
78
79 static char ethmac[6] = "\x00\x13\x37\x00\x00\x00"; /* last 3 bytes will be randomized */
80 static pcap_t *pcap_fp = NULL;
81 static pcap_t *pcap_fp_rx = NULL;
82 static char pktbuf_b[PCAP_MRU];
83 static struct ead_packet *pktbuf = (struct ead_packet *)pktbuf_b;
84 static u16_t nid = 0xffff; /* node id */
85 static char username[32] = "";
86 static int state = EAD_TYPE_SET_USERNAME;
87 static const char *passwd_file = PASSWD_FILE;
88 static const char password[MAXPARAMLEN];
89 static bool child_pending = false;
90
91 static unsigned char abuf[MAXPARAMLEN + 1];
92 static unsigned char pwbuf[MAXPARAMLEN];
93 static unsigned char saltbuf[MAXSALTLEN];
94 static unsigned char pw_saltbuf[MAXSALTLEN];
95 static struct list_head instances;
96 static const char *dev_name = DEFAULT_DEVNAME;
97 static bool nonfork = false;
98 static struct ead_instance *instance = NULL;
99
100 static struct t_pwent tpe = {
101         .name = username,
102         .index = 1,
103         .password.data = pwbuf,
104         .password.len = 0,
105         .salt.data = saltbuf,
106         .salt.len = 0,
107 };
108 struct t_confent *tce = NULL;
109 static struct t_server *ts = NULL;
110 static struct t_num A, *B = NULL;
111 unsigned char *skey;
112
113 static void
114 get_random_bytes(void *ptr, int len)
115 {
116         int fd;
117
118         fd = open("/dev/urandom", O_RDONLY);
119         if (fd < 0) {
120                 perror("open");
121                 exit(1);
122         }
123         read(fd, ptr, len);
124         close(fd);
125 }
126
127 static bool
128 prepare_password(void)
129 {
130         static char lbuf[1024];
131         unsigned char dig[SHA_DIGESTSIZE];
132         BigInteger x, v, n, g;
133         SHA1_CTX ctxt;
134         int ulen = strlen(username);
135         FILE *f;
136
137         lbuf[sizeof(lbuf) - 1] = 0;
138
139         f = fopen(passwd_file, "r");
140         if (!f)
141                 return false;
142
143         while (fgets(lbuf, sizeof(lbuf) - 1, f) != NULL) {
144                 char *str, *s2;
145
146                 if (strncmp(lbuf, username, ulen) != 0)
147                         continue;
148
149                 if (lbuf[ulen] != ':')
150                         continue;
151
152                 str = &lbuf[ulen + 1];
153
154                 if (strncmp(str, "$1$", 3) != 0)
155                         continue;
156
157                 s2 = strchr(str + 3, '$');
158                 if (!s2)
159                         continue;
160
161                 if (s2 - str >= MAXSALTLEN)
162                         continue;
163
164                 strncpy((char *) pw_saltbuf, str, s2 - str);
165                 pw_saltbuf[s2 - str] = 0;
166
167                 s2 = strchr(s2, ':');
168                 if (!s2)
169                         continue;
170
171                 *s2 = 0;
172                 if (s2 - str >= MAXPARAMLEN)
173                         continue;
174
175                 strncpy((char *)password, str, MAXPARAMLEN);
176                 fclose(f);
177                 goto hash_password;
178         }
179
180         /* not found */
181         fclose(f);
182         return false;
183
184 hash_password:
185         tce = gettcid(tpe.index);
186         do {
187                 t_random(tpe.password.data, SALTLEN);
188         } while (memcmp(saltbuf, (char *)dig, sizeof(saltbuf)) == 0);
189         if (saltbuf[0] == 0)
190                 saltbuf[0] = 0xff;
191
192         n = BigIntegerFromBytes(tce->modulus.data, tce->modulus.len);
193         g = BigIntegerFromBytes(tce->generator.data, tce->generator.len);
194         v = BigIntegerFromInt(0);
195
196         SHA1Init(&ctxt);
197         SHA1Update(&ctxt, (unsigned char *) username, strlen(username));
198         SHA1Update(&ctxt, (unsigned char *) ":", 1);
199         SHA1Update(&ctxt, (unsigned char *) password, strlen(password));
200         SHA1Final(dig, &ctxt);
201
202         SHA1Init(&ctxt);
203         SHA1Update(&ctxt, saltbuf, tpe.salt.len);
204         SHA1Update(&ctxt, dig, sizeof(dig));
205         SHA1Final(dig, &ctxt);
206
207         /* x = H(s, H(u, ':', p)) */
208         x = BigIntegerFromBytes(dig, sizeof(dig));
209
210         BigIntegerModExp(v, g, x, n);
211         tpe.password.len = BigIntegerToBytes(v, (unsigned char *)pwbuf);
212
213         BigIntegerFree(v);
214         BigIntegerFree(x);
215         BigIntegerFree(g);
216         BigIntegerFree(n);
217         return true;
218 }
219
220 static u16_t
221 chksum(u16_t sum, const u8_t *data, u16_t len)
222 {
223         u16_t t;
224         const u8_t *dataptr;
225         const u8_t *last_byte;
226
227         dataptr = data;
228         last_byte = data + len - 1;
229
230         while(dataptr < last_byte) {    /* At least two more bytes */
231                 t = (dataptr[0] << 8) + dataptr[1];
232                 sum += t;
233                 if(sum < t) {
234                         sum++;          /* carry */
235                 }
236                 dataptr += 2;
237         }
238
239         if(dataptr == last_byte) {
240                 t = (dataptr[0] << 8) + 0;
241                 sum += t;
242                 if(sum < t) {
243                         sum++;          /* carry */
244                 }
245         }
246
247         /* Return sum in host byte order. */
248         return sum;
249 }
250
251 static void
252 ead_send_packet_clone(struct ead_packet *pkt)
253 {
254         u16_t len, sum;
255
256         memcpy(pktbuf, pkt, offsetof(struct ead_packet, msg));
257         memcpy(pktbuf->eh.ether_shost, ethmac, 6);
258         memcpy(pktbuf->eh.ether_dhost, pkt->eh.ether_shost, 6);
259
260         /* ip header */
261         len = sizeof(struct ead_packet) - sizeof(struct ether_header) + ntohl(pktbuf->msg.len);
262         pktbuf->len[0] = len >> 8;
263         pktbuf->len[1] = len & 0xff;
264         memcpy(pktbuf->srcipaddr, &pkt->msg.ip, 4);
265         memcpy(pktbuf->destipaddr, pkt->srcipaddr, 4);
266
267         /* ip checksum */
268         pktbuf->ipchksum = 0;
269         sum = chksum(0, (void *) &pktbuf->vhl, UIP_IPH_LEN);
270         if (sum == 0)
271                 sum = 0xffff;
272         pktbuf->ipchksum = htons(~sum);
273
274         /* udp header */
275         pktbuf->srcport = pkt->destport;
276         pktbuf->destport = pkt->srcport;
277
278         /* udp checksum */
279         len -= UIP_IPH_LEN;
280         pktbuf->udplen = htons(len);
281         pktbuf->udpchksum = 0;
282         sum = len + UIP_PROTO_UDP;
283         sum = chksum(sum, (void *) &pktbuf->srcipaddr[0], 8); /* src, dest ip */
284         sum = chksum(sum, (void *) &pktbuf->srcport, len);
285         if (sum == 0)
286                 sum = 0xffff;
287         pktbuf->udpchksum = htons(~sum);
288         pcap_sendpacket(pcap_fp, (void *) pktbuf, sizeof(struct ead_packet) + ntohl(pktbuf->msg.len));
289 }
290
291 static void
292 set_state(int nstate)
293 {
294         if (state == nstate)
295                 return;
296
297         if (nstate < state) {
298                 if ((nstate < EAD_TYPE_GET_PRIME) &&
299                         (state >= EAD_TYPE_GET_PRIME)) {
300                         t_serverclose(ts);
301                         ts = NULL;
302                 }
303                 goto done;
304         }
305
306         switch(state) {
307         case EAD_TYPE_SET_USERNAME:
308                 if (!prepare_password())
309                         goto error;
310                 ts = t_serveropenraw(&tpe, tce);
311                 if (!ts)
312                         goto error;
313                 break;
314         case EAD_TYPE_GET_PRIME:
315                 B = t_servergenexp(ts);
316                 break;
317         case EAD_TYPE_SEND_A:
318                 skey = t_servergetkey(ts, &A);
319                 if (!skey)
320                         goto error;
321
322                 ead_set_key(skey);
323                 break;
324         }
325 done:
326         state = nstate;
327 error:
328         return;
329 }
330
331 static bool
332 handle_ping(struct ead_packet *pkt, int len, int *nstate)
333 {
334         struct ead_msg *msg = &pktbuf->msg;
335         struct ead_msg_pong *pong = EAD_DATA(msg, pong);
336         int slen;
337
338         slen = strlen(dev_name);
339         if (slen > 1024)
340                 slen = 1024;
341
342         msg->len = htonl(sizeof(struct ead_msg_pong) + slen);
343         strncpy(pong->name, dev_name, slen);
344         pong->name[slen] = 0;
345         pong->auth_type = htons(EAD_AUTH_MD5);
346
347         return true;
348 }
349
350 static bool
351 handle_set_username(struct ead_packet *pkt, int len, int *nstate)
352 {
353         struct ead_msg *msg = &pkt->msg;
354         struct ead_msg_user *user = EAD_DATA(msg, user);
355
356         set_state(EAD_TYPE_SET_USERNAME); /* clear old state */
357         strncpy(username, user->username, sizeof(username));
358         username[sizeof(username) - 1] = 0;
359
360         msg = &pktbuf->msg;
361         msg->len = 0;
362
363         *nstate = EAD_TYPE_GET_PRIME;
364         return true;
365 }
366
367 static bool
368 handle_get_prime(struct ead_packet *pkt, int len, int *nstate)
369 {
370         struct ead_msg *msg = &pktbuf->msg;
371         struct ead_msg_salt *salt = EAD_DATA(msg, salt);
372
373         msg->len = htonl(sizeof(struct ead_msg_salt));
374         salt->prime = tce->index - 1;
375         salt->len = ts->s.len;
376         memcpy(salt->salt, ts->s.data, ts->s.len);
377         memcpy(salt->ext_salt, pw_saltbuf, MAXSALTLEN);
378
379         *nstate = EAD_TYPE_SEND_A;
380         return true;
381 }
382
383 static bool
384 handle_send_a(struct ead_packet *pkt, int len, int *nstate)
385 {
386         struct ead_msg *msg = &pkt->msg;
387         struct ead_msg_number *number = EAD_DATA(msg, number);
388         len = ntohl(msg->len) - sizeof(struct ead_msg_number);
389
390         if (len > MAXPARAMLEN + 1)
391                 return false;
392
393         A.len = len;
394         A.data = abuf;
395         memcpy(A.data, number->data, len);
396
397         msg = &pktbuf->msg;
398         number = EAD_DATA(msg, number);
399         msg->len = htonl(sizeof(struct ead_msg_number) + B->len);
400         memcpy(number->data, B->data, B->len);
401
402         *nstate = EAD_TYPE_SEND_AUTH;
403         return true;
404 }
405
406 static bool
407 handle_send_auth(struct ead_packet *pkt, int len, int *nstate)
408 {
409         struct ead_msg *msg = &pkt->msg;
410         struct ead_msg_auth *auth = EAD_DATA(msg, auth);
411
412         if (t_serververify(ts, auth->data) != 0) {
413                 DEBUG(2, "Client authentication failed\n");
414                 *nstate = EAD_TYPE_SET_USERNAME;
415                 return false;
416         }
417
418         msg = &pktbuf->msg;
419         auth = EAD_DATA(msg, auth);
420         msg->len = htonl(sizeof(struct ead_msg_auth));
421
422         DEBUG(2, "Client authentication successful\n");
423         memcpy(auth->data, t_serverresponse(ts), sizeof(auth->data));
424
425         *nstate = EAD_TYPE_SEND_CMD;
426         return true;
427 }
428
429 static bool
430 handle_send_cmd(struct ead_packet *pkt, int len, int *nstate)
431 {
432         struct ead_msg *msg = &pkt->msg;
433         struct ead_msg_cmd *cmd = EAD_ENC_DATA(msg, cmd);
434         struct ead_msg_cmd_data *cmddata;
435         struct timeval tv, to, tn;
436         int pfd[2], fd;
437         fd_set fds;
438         pid_t pid;
439         bool stream = false;
440         int timeout;
441         int type;
442         int datalen;
443
444         datalen = ead_decrypt_message(msg) - sizeof(struct ead_msg_cmd);
445         if (datalen <= 0)
446                 return false;
447
448         type = ntohs(cmd->type);
449         timeout = ntohs(cmd->timeout);
450
451         FD_ZERO(&fds);
452         cmd->data[datalen] = 0;
453         switch(type) {
454         case EAD_CMD_NORMAL:
455                 if (pipe(pfd) < 0)
456                         return false;
457
458                 fcntl(pfd[0], F_SETFL, O_NONBLOCK | fcntl(pfd[0], F_GETFL));
459                 child_pending = true;
460                 pid = fork();
461                 if (pid == 0) {
462                         close(pfd[0]);
463                         fd = open("/dev/null", O_RDWR);
464                         if (fd > 0) {
465                                 dup2(fd, 0);
466                                 dup2(pfd[1], 1);
467                                 dup2(pfd[1], 2);
468                         }
469                         system((char *)cmd->data);
470                         exit(0);
471                 } else if (pid > 0) {
472                         close(pfd[1]);
473                         if (!timeout)
474                                 timeout = EAD_CMD_TIMEOUT;
475
476                         stream = true;
477                         break;
478                 }
479                 return false;
480         case EAD_CMD_BACKGROUND:
481                 pid = fork();
482                 if (pid == 0) {
483                         /* close stdin, stdout, stderr, replace with fd to /dev/null */
484                         fd = open("/dev/null", O_RDWR);
485                         if (fd > 0) {
486                                 dup2(fd, 0);
487                                 dup2(fd, 1);
488                                 dup2(fd, 2);
489                         }
490                         system((char *)cmd->data);
491                         exit(0);
492                 } else if (pid > 0) {
493                         break;
494                 }
495                 return false;
496         default:
497                 return false;
498         }
499
500         msg = &pktbuf->msg;
501         cmddata = EAD_ENC_DATA(msg, cmd_data);
502
503         if (stream) {
504                 int nfds, bytes;
505
506                 /* send keepalive packets every 200 ms so that the client doesn't timeout */
507                 gettimeofday(&to, NULL);
508                 memcpy(&tn, &to, sizeof(tn));
509                 tv.tv_usec = PCAP_TIMEOUT * 1000;
510                 tv.tv_sec = 0;
511                 do {
512                         cmddata->done = 0;
513                         FD_SET(pfd[0], &fds);
514                         nfds = select(pfd[0] + 1, &fds, NULL, NULL, &tv);
515                         bytes = 0;
516                         if (nfds > 0) {
517                                 bytes = read(pfd[0], cmddata->data, 1024);
518                                 if (bytes < 0)
519                                         bytes = 0;
520                         }
521                         if (!bytes && !child_pending)
522                                 break;
523                         DEBUG(3, "Sending %d bytes of console data, type=%d, timeout=%d\n", bytes, ntohl(msg->type), timeout);
524                         ead_encrypt_message(msg, sizeof(struct ead_msg_cmd_data) + bytes);
525                         ead_send_packet_clone(pkt);
526                         gettimeofday(&tn, NULL);
527                 } while (tn.tv_sec < to.tv_sec + timeout);
528                 if (child_pending) {
529                         kill(pid, SIGKILL);
530                         return false;
531                 }
532         }
533         cmddata->done = 1;
534         ead_encrypt_message(msg, sizeof(struct ead_msg_cmd_data));
535
536         return true;
537 }
538
539
540
541 static void
542 parse_message(struct ead_packet *pkt, int len)
543 {
544         bool (*handler)(struct ead_packet *pkt, int len, int *nstate);
545         int min_len = sizeof(struct ead_packet);
546         int nstate = state;
547         int type = ntohl(pkt->msg.type);
548
549         if ((type >= EAD_TYPE_GET_PRIME) &&
550                 (state != type))
551                 return;
552
553         if ((type != EAD_TYPE_PING) &&
554                 ((ntohs(pkt->msg.sid) & EAD_INSTANCE_MASK) >>
555                  EAD_INSTANCE_SHIFT) != instance->id)
556                 return;
557
558         switch(type) {
559         case EAD_TYPE_PING:
560                 handler = handle_ping;
561                 break;
562         case EAD_TYPE_SET_USERNAME:
563                 handler = handle_set_username;
564                 min_len += sizeof(struct ead_msg_user);
565                 break;
566         case EAD_TYPE_GET_PRIME:
567                 handler = handle_get_prime;
568                 break;
569         case EAD_TYPE_SEND_A:
570                 handler = handle_send_a;
571                 min_len += sizeof(struct ead_msg_number);
572                 break;
573         case EAD_TYPE_SEND_AUTH:
574                 handler = handle_send_auth;
575                 min_len += sizeof(struct ead_msg_auth);
576                 break;
577         case EAD_TYPE_SEND_CMD:
578                 handler = handle_send_cmd;
579                 min_len += sizeof(struct ead_msg_cmd) + sizeof(struct ead_msg_encrypted);
580                 break;
581         default:
582                 return;
583         }
584
585         if (len < min_len) {
586                 DEBUG(2, "discarding packet: message too small\n");
587                 return;
588         }
589
590         pktbuf->msg.magic = htonl(EAD_MAGIC);
591         pktbuf->msg.type = htonl(type + 1);
592         pktbuf->msg.nid = htons(nid);
593         pktbuf->msg.sid = pkt->msg.sid;
594         pktbuf->msg.len = 0;
595
596         if (handler(pkt, len, &nstate)) {
597                 DEBUG(2, "sending response to packet type %d: %d\n", type + 1, ntohl(pktbuf->msg.len));
598                 /* format response packet */
599                 ead_send_packet_clone(pkt);
600         }
601         set_state(nstate);
602 }
603
604 static void
605 handle_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *bytes)
606 {
607         struct ead_packet *pkt = (struct ead_packet *) bytes;
608
609         if (h->len < sizeof(struct ead_packet))
610                 return;
611
612         if (pkt->eh.ether_type != htons(ETHERTYPE_IP))
613                 return;
614
615         if (memcmp(pkt->eh.ether_dhost, "\xff\xff\xff\xff\xff\xff", 6) != 0)
616                 return;
617
618         if (pkt->proto != UIP_PROTO_UDP)
619                 return;
620
621         if (pkt->destport != htons(EAD_PORT))
622                 return;
623
624         if (pkt->msg.magic != htonl(EAD_MAGIC))
625                 return;
626
627         if (h->len < sizeof(struct ead_packet) + ntohl(pkt->msg.len))
628                 return;
629
630         if ((pkt->msg.nid != 0xffff) &&
631                 (pkt->msg.nid != htons(nid)))
632                 return;
633
634         parse_message(pkt, h->len);
635 }
636
637 static void
638 ead_pcap_reopen(bool first)
639 {
640         static char errbuf[PCAP_ERRBUF_SIZE] = "";
641
642         if (pcap_fp_rx && (pcap_fp_rx != pcap_fp))
643                 pcap_close(pcap_fp_rx);
644
645         if (pcap_fp)
646                 pcap_close(pcap_fp);
647
648         pcap_fp_rx = NULL;
649         do {
650                 pcap_fp = pcap_open_live(instance->ifname, PCAP_MRU, 1, PCAP_TIMEOUT, errbuf);
651 #ifdef linux
652                 if (instance->bridge[0])
653                         pcap_fp_rx = pcap_open_live(instance->bridge, PCAP_MRU, 1, PCAP_TIMEOUT, errbuf);
654 #endif
655                 if (!pcap_fp_rx)
656                         pcap_fp_rx = pcap_fp;
657                 pcap_setfilter(pcap_fp_rx, &pktfilter);
658                 if (first && !pcap_fp) {
659                         DEBUG(1, "WARNING: unable to open interface '%s'\n", instance->ifname);
660                         first = false;
661                 }
662                 if (!pcap_fp)
663                         sleep(1);
664         } while (!pcap_fp);
665 }
666
667
668 static void
669 ead_pktloop(void)
670 {
671         while (1) {
672                 if (pcap_dispatch(pcap_fp_rx, 1, handle_packet, NULL) < 0) {
673                         ead_pcap_reopen(false);
674                         continue;
675                 }
676         }
677 }
678
679
680 static int
681 usage(const char *prog)
682 {
683         fprintf(stderr, "Usage: %s [<options>]\n"
684                 "Options:\n"
685                 "\t-B             Run in background mode\n"
686                 "\t-d <device>    Set the device to listen on\n"
687                 "\t-D <name>      Set the name of the device visible to clients\n"
688                 "\t-p <file>      Set the password file for authenticating\n"
689                 "\t-P <file>      Write a pidfile\n"
690                 "\n", prog);
691         return -1;
692 }
693
694 static void
695 server_handle_sigchld(int sig)
696 {
697         struct ead_instance *in;
698         struct list_head *p;
699         int pid = 0;
700         wait(&pid);
701
702         list_for_each(p, &instances) {
703                 in = list_entry(p, struct ead_instance, list);
704                 if (pid != in->pid)
705                         continue;
706
707                 in->pid = 0;
708                 break;
709         }
710 }
711
712 static void
713 instance_handle_sigchld(int sig)
714 {
715         int pid = 0;
716         wait(&pid);
717         child_pending = false;
718 }
719
720 static void
721 start_server(struct ead_instance *i)
722 {
723         if (!nonfork) {
724                 i->pid = fork();
725                 if (i->pid != 0) {
726                         if (i->pid < 0)
727                                 i->pid = 0;
728                         return;
729                 }
730         }
731
732         instance = i;
733         signal(SIGCHLD, instance_handle_sigchld);
734         ead_pcap_reopen(true);
735         ead_pktloop();
736         pcap_close(pcap_fp);
737         if (pcap_fp_rx != pcap_fp)
738                 pcap_close(pcap_fp_rx);
739
740         exit(0);
741 }
742
743
744 static void
745 start_servers(bool restart)
746 {
747         struct ead_instance *in;
748         struct list_head *p;
749
750         list_for_each(p, &instances) {
751                 in = list_entry(p, struct ead_instance, list);
752                 if (in->pid > 0)
753                         continue;
754
755                 sleep(1);
756                 start_server(in);
757         }
758 }
759
760 static void
761 stop_server(struct ead_instance *in, bool do_free)
762 {
763         if (in->pid > 0)
764                 kill(in->pid, SIGKILL);
765         in->pid = 0;
766         if (do_free) {
767                 list_del(&in->list);
768                 free(in);
769         }
770 }
771
772 static void
773 server_handle_sigint(int sig)
774 {
775         struct ead_instance *in;
776         struct list_head *p, *tmp;
777
778         list_for_each_safe(p, tmp, &instances) {
779                 in = list_entry(p, struct ead_instance, list);
780                 stop_server(in, true);
781         }
782         exit(1);
783 }
784
785 #ifdef linux
786 static int
787 check_bridge_port(const char *br, const char *port, void *arg)
788 {
789         struct ead_instance *in;
790         struct list_head *p, *tmp;
791
792         list_for_each(p, &instances) {
793                 in = list_entry(p, struct ead_instance, list);
794
795                 if (strcmp(in->ifname, port) != 0)
796                         continue;
797
798                 in->br_check = true;
799                 if (strcmp(in->bridge, br) == 0)
800                         break;
801
802                 strncpy(in->bridge, br, sizeof(in->bridge));
803                 DEBUG(2, "assigning port %s to bridge %s\n", in->ifname, in->bridge);
804                 stop_server(in, false);
805         }
806         return 0;
807 }
808
809 static int
810 check_bridge(const char *name, void *arg)
811 {
812         br_foreach_port(name, check_bridge_port, arg);
813         return 0;
814 }
815 #endif
816
817 static void
818 check_all_interfaces(void)
819 {
820 #ifdef linux
821         struct ead_instance *in;
822         struct list_head *p, *tmp;
823
824         br_foreach_bridge(check_bridge, NULL);
825
826         /* look for interfaces that are no longer part of a bridge */
827         list_for_each(p, &instances) {
828                 in = list_entry(p, struct ead_instance, list);
829
830                 if (in->br_check) {
831                         in->br_check = false;
832                 } else if (in->bridge[0]) {
833                         DEBUG(2, "removing port %s from bridge %s\n", in->ifname, in->bridge);
834                         in->bridge[0] = 0;
835                         stop_server(in, false);
836                 }
837         }
838 #endif
839 }
840
841
842 int main(int argc, char **argv)
843 {
844         struct ead_instance *in;
845         struct timeval tv;
846         const char *pidfile = NULL;
847         bool background = false;
848         int n_iface = 0;
849         int fd, ch;
850
851         if (argc == 1)
852                 return usage(argv[0]);
853
854         INIT_LIST_HEAD(&instances);
855         while ((ch = getopt(argc, argv, "Bd:D:fhp:P:")) != -1) {
856                 switch(ch) {
857                 case 'B':
858                         background = true;
859                         break;
860                 case 'f':
861                         nonfork = true;
862                         break;
863                 case 'h':
864                         return usage(argv[0]);
865                 case 'd':
866                         in = malloc(sizeof(struct ead_instance));
867                         memset(in, 0, sizeof(struct ead_instance));
868                         INIT_LIST_HEAD(&in->list);
869                         strncpy(in->ifname, optarg, sizeof(in->ifname) - 1);
870                         list_add(&in->list, &instances);
871                         in->id = n_iface++;
872                         break;
873                 case 'D':
874                         dev_name = optarg;
875                         break;
876                 case 'p':
877                         passwd_file = optarg;
878                         break;
879                 case 'P':
880                         pidfile = optarg;
881                         break;
882                 }
883         }
884         signal(SIGCHLD, server_handle_sigchld);
885         signal(SIGINT, server_handle_sigint);
886         signal(SIGTERM, server_handle_sigint);
887         signal(SIGKILL, server_handle_sigint);
888
889         if (!n_iface) {
890                 fprintf(stderr, "Error: ead needs at least one interface\n");
891                 return -1;
892         }
893
894         if (background) {
895                 if (fork() > 0)
896                         exit(0);
897
898                 fd = open("/dev/null", O_RDWR);
899                 dup2(fd, 0);
900                 dup2(fd, 1);
901                 dup2(fd, 2);
902         }
903
904         if (pidfile) {
905                 char pid[8];
906                 int len;
907
908                 unlink(pidfile);
909                 fd = open(pidfile, O_CREAT|O_WRONLY|O_EXCL, 0644);
910                 if (fd > 0) {
911                         len = sprintf(pid, "%d\n", getpid());
912                         write(fd, pid, len);
913                         close(fd);
914                 }
915         }
916
917         /* randomize the mac address */
918         get_random_bytes(ethmac + 3, 3);
919         nid = *(((u16_t *) ethmac) + 2);
920
921         start_servers(false);
922 #ifdef linux
923         br_init();
924 #endif
925         tv.tv_sec = 1;
926         tv.tv_usec = 0;
927         while (1) {
928                 check_all_interfaces();
929                 start_servers(true);
930                 sleep(1);
931         }
932 #ifdef linux
933         br_shutdown();
934 #endif
935
936         return 0;
937 }