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