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