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