b6a9310f0fb3382d76ec109524d23806c1b1d49a
[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 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[slen] = 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_rx != pcap_fp))
626 pcap_close(pcap_fp_rx);
627
628 if (pcap_fp)
629 pcap_close(pcap_fp);
630
631 pcap_fp_rx = NULL;
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 #endif
638 if (!pcap_fp_rx)
639 pcap_fp_rx = pcap_fp;
640 pcap_setfilter(pcap_fp_rx, &pktfilter);
641 if (first && !pcap_fp) {
642 DEBUG(1, "WARNING: unable to open interface '%s'\n", ifname);
643 first = false;
644 }
645 if (!pcap_fp)
646 sleep(1);
647 } while (!pcap_fp);
648 }
649
650
651 static void
652 ead_pktloop(void)
653 {
654 while (1) {
655 if (pcap_dispatch(pcap_fp_rx, 1, handle_packet, NULL) < 0) {
656 ead_pcap_reopen(false);
657 continue;
658 }
659 }
660 }
661
662
663 static int
664 usage(const char *prog)
665 {
666 fprintf(stderr, "Usage: %s [<options>]\n"
667 "Options:\n"
668 "\t-B Run in background mode\n"
669 "\t-d <device> Set the device to listen on\n"
670 "\t-D <name> Set the name of the device visible to clients\n"
671 "\t-p <file> Set the password file for authenticating\n"
672 "\t-P <file> Write a pidfile\n"
673 "\n", prog);
674 return -1;
675 }
676
677 static void
678 server_handle_sigchld(int sig)
679 {
680 struct ead_instance *in;
681 struct list_head *p;
682 int pid = 0;
683 wait(&pid);
684
685 list_for_each(p, &instances) {
686 in = list_entry(p, struct ead_instance, list);
687 if (pid != in->pid)
688 continue;
689
690 in->pid = 0;
691 break;
692 }
693 }
694
695 static void
696 instance_handle_sigchld(int sig)
697 {
698 int pid = 0;
699 wait(&pid);
700 child_pending = false;
701 }
702
703 static void
704 start_server(struct ead_instance *i)
705 {
706 if (!nonfork) {
707 i->pid = fork();
708 if (i->pid != 0) {
709 if (i->pid < 0)
710 i->pid = 0;
711 return;
712 }
713 }
714
715 signal(SIGCHLD, instance_handle_sigchld);
716 ifname = i->name;
717 #ifdef linux
718 if (i->bridge[0])
719 brname = i->bridge;
720 #endif
721 ead_pcap_reopen(true);
722 ead_pktloop();
723 pcap_close(pcap_fp);
724 if (pcap_fp_rx != pcap_fp)
725 pcap_close(pcap_fp_rx);
726
727 exit(0);
728 }
729
730
731 static void
732 start_servers(bool restart)
733 {
734 struct ead_instance *in;
735 struct list_head *p;
736
737 list_for_each(p, &instances) {
738 in = list_entry(p, struct ead_instance, list);
739 if (in->pid > 0)
740 continue;
741
742 sleep(1);
743 start_server(in);
744 }
745 }
746
747 static void
748 stop_server(struct ead_instance *in, bool do_free)
749 {
750 if (in->pid > 0)
751 kill(in->pid, SIGKILL);
752 in->pid = 0;
753 if (do_free) {
754 list_del(&in->list);
755 free(in);
756 }
757 }
758
759 static void
760 server_handle_sigint(int sig)
761 {
762 struct ead_instance *in;
763 struct list_head *p, *tmp;
764
765 list_for_each_safe(p, tmp, &instances) {
766 in = list_entry(p, struct ead_instance, list);
767 stop_server(in, true);
768 }
769 exit(1);
770 }
771
772 #ifdef linux
773 static int
774 check_bridge_port(const char *br, const char *port, void *arg)
775 {
776 struct ead_instance *in;
777 struct list_head *p, *tmp;
778
779 list_for_each(p, &instances) {
780 in = list_entry(p, struct ead_instance, list);
781
782 if (strcmp(in->name, port) != 0)
783 continue;
784
785 in->br_check = true;
786 if (strcmp(in->bridge, br) == 0)
787 break;
788
789 strncpy(in->bridge, br, sizeof(in->bridge));
790 DEBUG(2, "assigning port %s to bridge %s\n", in->name, in->bridge);
791 stop_server(in, false);
792 }
793 return 0;
794 }
795
796 static int
797 check_bridge(const char *name, void *arg)
798 {
799 br_foreach_port(name, check_bridge_port, arg);
800 return 0;
801 }
802 #endif
803
804 static void
805 check_all_interfaces(void)
806 {
807 #ifdef linux
808 struct ead_instance *in;
809 struct list_head *p, *tmp;
810
811 br_foreach_bridge(check_bridge, NULL);
812
813 /* look for interfaces that are no longer part of a bridge */
814 list_for_each(p, &instances) {
815 in = list_entry(p, struct ead_instance, list);
816
817 if (in->br_check) {
818 in->br_check = false;
819 } else if (in->bridge[0]) {
820 DEBUG(2, "removing port %s from bridge %s\n", in->name, in->bridge);
821 in->bridge[0] = 0;
822 stop_server(in, false);
823 }
824 }
825 #endif
826 }
827
828
829 int main(int argc, char **argv)
830 {
831 struct ead_instance *in;
832 struct timeval tv;
833 int fd, ch;
834 const char *pidfile = NULL;
835 bool background = false;
836 int n_iface = 0;
837
838 if (argc == 1)
839 return usage(argv[0]);
840
841 INIT_LIST_HEAD(&instances);
842 while ((ch = getopt(argc, argv, "Bd:D:fhp:P:")) != -1) {
843 switch(ch) {
844 case 'B':
845 background = true;
846 break;
847 case 'f':
848 nonfork = true;
849 break;
850 case 'h':
851 return usage(argv[0]);
852 case 'd':
853 in = malloc(sizeof(struct ead_instance));
854 memset(in, 0, sizeof(struct ead_instance));
855 INIT_LIST_HEAD(&in->list);
856 strncpy(in->name, optarg, sizeof(in->name) - 1);
857 list_add(&in->list, &instances);
858 n_iface++;
859 break;
860 case 'D':
861 dev_name = optarg;
862 break;
863 case 'p':
864 passwd_file = optarg;
865 break;
866 case 'P':
867 pidfile = optarg;
868 break;
869 }
870 }
871 signal(SIGCHLD, server_handle_sigchld);
872 signal(SIGINT, server_handle_sigint);
873 signal(SIGTERM, server_handle_sigint);
874 signal(SIGKILL, server_handle_sigint);
875
876 if (!n_iface) {
877 fprintf(stderr, "Error: ead needs at least one interface\n");
878 return -1;
879 }
880
881 if (background) {
882 if (fork() > 0)
883 exit(0);
884
885 fd = open("/dev/null", O_RDWR);
886 dup2(fd, 0);
887 dup2(fd, 1);
888 dup2(fd, 2);
889 }
890
891 if (pidfile) {
892 char pid[8];
893 int len;
894
895 unlink(pidfile);
896 fd = open(pidfile, O_CREAT|O_WRONLY|O_EXCL, 0644);
897 if (fd > 0) {
898 len = sprintf(pid, "%d\n", getpid());
899 write(fd, pid, len);
900 close(fd);
901 }
902 }
903
904 /* randomize the mac address */
905 fd = open("/dev/urandom", O_RDONLY);
906 if (fd < 0) {
907 perror("open");
908 exit(1);
909 }
910 read(fd, ethmac + 3, 3);
911 close(fd);
912 nid = *(((u16_t *) ethmac) + 2);
913
914 start_servers(false);
915 #ifdef linux
916 br_init();
917 #endif
918 tv.tv_sec = 1;
919 tv.tv_usec = 0;
920 while (1) {
921 check_all_interfaces();
922 start_servers(true);
923 sleep(1);
924 }
925 #ifdef linux
926 br_shutdown();
927 #endif
928
929 return 0;
930 }
This page took 0.100339 seconds and 3 git commands to generate.