struct irec *find_all_interfaces(struct iname *names, struct iname *addrs, int port) { /* this code is adapted from Stevens, page 434. It finally destroyed my faith in the C/unix API */ int len = 100 * sizeof(struct ifreq); int lastlen = 0; char *buf, *ptr; struct ifconf ifc; struct irec *ret = NULL; int fd = socket(PF_INET, SOCK_DGRAM, 0); if (fd == -1) die("cannot create socket to enumerate interfaces: %s", NULL); while (1) { buf = safe_malloc(len); ifc.ifc_len = len; ifc.ifc_buf = buf; if (ioctl(fd, SIOCGIFCONF, &ifc) < 0) { if (errno != EINVAL || lastlen != 0) die("ioctl error while enumerating interfaces: %s", NULL); } else { if (ifc.ifc_len == lastlen) break; /* got a big enough buffer now */ lastlen = ifc.ifc_len; } len += 10* sizeof(struct ifreq); safe_free(buf); } for (ptr = buf; ptr < buf + ifc.ifc_len; ) { struct ifreq *ifr = (struct ifreq *) ptr; union mysockaddr addr; #ifdef HAVE_SOCKADDR_SA_LEN ptr += ifr->ifr_addr.sa_len + IF_NAMESIZE; #else ptr += sizeof(struct ifreq); #endif /* copy address since getting flags overwrites */ if (ifr->ifr_addr.sa_family == AF_INET) { addr.in = *((struct sockaddr_in *) &ifr->ifr_addr); addr.in.sin_port = htons(port); if (ioctl(fd, SIOCGIFFLAGS, ifr) < 0) die ("ioctl error getting interface flags: %s", NULL); ret = add_iface(ret, ifr->ifr_flags, ifr->ifr_name, &addr, names, addrs); } #ifdef HAVE_IPV6 else if (ifr->ifr_addr.sa_family == AF_INET6) { #ifdef HAVE_BROKEN_SOCKADDR_IN6 addr.in6 = *((struct my_sockaddr_in6 *) &ifr->ifr_addr); #else addr.in6 = *((struct sockaddr_in6 *) &ifr->ifr_addr); #endif addr.in6.sin6_port = htons(port); addr.in6.sin6_flowinfo = htonl(0); if (ioctl(fd, SIOCGIFFLAGS, ifr) < 0) die("ioctl error getting interface flags: %s", NULL); ret = add_iface(ret, ifr->ifr_flags, ifr->ifr_name, &addr, names, addrs); } #endif /* IPV6 */ } safe_free(buf); close(fd); #if defined(HAVE_LINUX_IPV6_PROC) && defined(HAVE_IPV6) /* IPv6 addresses don't seem to work with SIOCGIFCONF. Barf */ /* This code snarfed from net-tools 1.60 and certainly linux specific, though it shouldn't break on other Unices, and their SIOGIFCONF might work. */ { FILE *f = fopen(IP6INTERFACES, "r"); if (f) { union mysockaddr addr; unsigned int plen, scope, flags, if_idx; char devname[20], addrstring[32]; while (fscanf(f, "%32s %02x %02x %02x %02x %20s\n", addrstring, &if_idx, &plen, &scope, &flags, devname) != EOF) { int i; unsigned char *addr6p = (unsigned char *) &addr.in6.sin6_addr; memset(&addr, 0, sizeof(addr)); addr.sa.sa_family = AF_INET6; for (i=0; i<16; i++) { unsigned int byte; sscanf(addrstring+i+i, "%02x", &byte); addr6p[i] = byte; } #ifdef HAVE_SOCKADDR_SA_LEN /* For completeness - should never be defined on Linux. */ addr.in6.sin6_len = sizeof(struct sockaddr_in6); #endif addr.in6.sin6_port = htons(port); addr.in6.sin6_flowinfo = htonl(0); addr.in6.sin6_scope_id = htonl(scope); ret = add_iface(ret, flags, devname, &addr, names, addrs); } fclose(f); } } #endif /* LINUX */ /* if a whitelist provided, make sure the if names on it were OK */ while(names) { if (!names->found) die("unknown interface %s", names->name); names = names->next; } while(addrs) { if (!addrs->found) { #ifdef HAVE_IPV6 char addrbuff[INET6_ADDRSTRLEN]; #else char addrbuff[INET_ADDRSTRLEN]; #endif if (addrs->addr.sa.sa_family == AF_INET) inet_ntop(AF_INET, &addrs->addr.in.sin_addr, addrbuff, INET_ADDRSTRLEN); #ifdef HAVE_IPV6 else inet_ntop(AF_INET6, &addrs->addr.in6.sin6_addr, addrbuff, INET6_ADDRSTRLEN); #endif die("no interface with address %s", addrbuff); } addrs = addrs->next; } return ret; }
int main(int argc, char *argv[]) { char errbuf[PCAP_ERRBUF_SIZE]; char *dev; struct iface_config *ifc; int optind; int i; bzero(&cfg, sizeof(cfg)); /* Default configuration */ // cfg.ratelimit = 0; cfg.hashsize = 1; // cfg.quiet = 0; cfg.promisc_flag = 1; // cfg.ratelimit = 0; // cfg.sqlite_file = NULL; // cfg.uname = NULL; cfg.shm_data.size = DEFAULT_SHM_LOG_SIZE; cfg.shm_data.name = DEFAULT_SHM_LOG_NAME; #if HAVE_LIBSQLITE3 cfg.sqlite_table = PACKAGE; #endif log_open(PACKAGE_NAME); argp_parse(&argp, argc, argv, 0, &optind, 0); if (!cfg.hostname) { cfg.hostname_len = sysconf(_SC_HOST_NAME_MAX); cfg.hostname = (char *)calloc(cfg.hostname_len, sizeof(char)); gethostname(cfg.hostname, cfg.hostname_len); } daemonize(); save_pid(); libevent_init(); if (cfg.ratelimit > 0) log_msg(LOG_DEBUG, "Ratelimiting duplicate entries to 1 per %d seconds", cfg.ratelimit); else if (cfg.ratelimit == -1) log_msg(LOG_DEBUG, "Duplicate entries supressed indefinitely"); else log_msg(LOG_DEBUG, "Duplicate entries ratelimiting disabled"); if (cfg.promisc_flag) log_msg(LOG_DEBUG, "PROMISC mode enabled"); else log_msg(LOG_DEBUG, "PROMISC mode disabled"); if (argc > optind) { for (i = optind; i < argc; i++) add_iface(argv[i]); } else { dev = pcap_lookupdev(errbuf); if (dev != NULL) add_iface(dev); } if (!cfg.interfaces) log_msg(LOG_ERR, "No suitable interfaces found!"); if (cfg.uname) drop_root(cfg.uname); output_flatfile_init(); output_sqlite_init(); output_shm_init(); /* main loop */ #if HAVE_LIBEVENT2 event_base_dispatch(cfg.eb); #else event_dispatch(); #endif output_shm_close(); output_sqlite_close(); output_flatfile_close(); for (ifc = cfg.interfaces; ifc != NULL; ifc = del_iface(ifc)); libevent_close(); log_close(); del_pid(); blacklist_free(); free(cfg.hostname); return 0; }
int main(int argc, char *argv[]) { int sock, devs = 0, ok, i; time_t last_xmit; device *dev; parse_args(argc, argv); read_ifaces(); ok = 1; while(ifnum > 0) { if (add_iface(iflist[0], add_rt)) ok = 0; else devs = 1; iflist++; ifnum--; } if (!ok) exit(1); if (!devs) { dev = first; while (dev) { dev->active = 1; dev->add_route = add_rt; dev = dev->next; } } dev = first; ok = 0; if (!dev) { error("inarpd: no network interfaces found\n"); exit(1); } do { int ip4_cnt = 0, ip6_cnt = 0, peer = 0; if (!dev->active) continue; if (dev->has_name != 1) { error("Device %s has no name\n", dev->name); dev->active = 0; continue; } if ((dev->flags & IFF_POINTOPOINT) == 0) { if (verbose > 0 || devs) printf("Device %s is not point-to-point\n", dev->name); dev->active = 0; continue; } if (dev->has_addr != 1) { if (verbose > 0 || devs) printf("Device %s has no hw address\n", dev->name); dev->active = 0; continue; } if (dev->has_bcast != 1) { if (verbose > 0 || devs) printf("Device %s has no peer hw address\n", dev->name); dev->active = 0; continue; } if (dev->ip_cnt == 0) { if (verbose > 0 || devs) printf("Device %s has no IP address\n", dev->name); dev->active = 0; continue; } ok = 1; if (dev->type == ARPHRD_DLCI) memset(dev->addr, 0, dev->addr_len); if (!dev->add_route) continue; for (i = 0; (unsigned) i < dev->ip_cnt; i++) { if (dev->ip[i].family == AF_INET) { if (memcmp(dev->ip[i].addr, dev->ip[i].peer, IP_ADDR_LEN) || dev->ip[i].bits != IP_ADDR_LEN * 8) peer = 1; ip4_cnt++; } if (dev->ip[i].family == AF_INET6) { if (memcmp(dev->ip[i].addr, dev->ip[i].peer, IP6_ADDR_LEN) || dev->ip[i].bits != IP6_ADDR_LEN * 8) peer = 1; ip6_cnt++; } } if (ip4_cnt > 1 || ip6_cnt > 1) { if (verbose > 0 || devs) printf("Can't automatically add routes for" " device %s having more than 1 IP" " address\n", dev->name); dev->add_route = 0; } else if (peer) { if (verbose > 0 || devs) printf("Can't automatically add routes for" " device %s with peer address\n", dev->name); dev->add_route = 0; } }while ((dev = dev->next) != NULL); if (!ok) { error("inarpd: no usable interfaces found\n"); exit(1); } if (verbose > 0) { dev = first; printf("Interfaces:\n"); do { if (!dev->active) continue; printf(" %s%s", dev->name, dev->add_route ? "(r)" : ""); if (verbose <= 1) { putchar('\n'); continue; } if (dev->type == ARPHRD_DLCI) printf(" [Q922 "); else { printf(" ["); for (i = 0; (unsigned) i < dev->addr_len; i++) printf("%s%02X", i == 0 ? "" : ":", dev->addr[i]); printf("->"); } for (i = 0; (unsigned) i < dev->addr_len; i++) printf("%s%02X", i == 0 ? "" : ":", dev->bcast[i]); printf("]"); for (i = 0; (unsigned) i < dev->ip_cnt; i++) { putchar(' '); print_ip(dev->ip[i].family, dev->ip[i].addr); printf("->"); print_ip(dev->ip[i].family, dev->ip[i].peer); printf("/%u", dev->ip[i].bits); } putchar('\n'); }while ((dev = dev->next) != NULL); } if ((sock = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_ARP))) == -1) { perror("inarpd: socket() failed"); exit(-1); } if (fcntl(sock, F_SETFL, O_NONBLOCK) < 0) perror("fcntl() failed"); last_xmit = 0; while(1) { fd_set set; FD_ZERO(&set); FD_SET(sock, &set); time_t now = time(NULL); struct timeval tm; arp_packet buffer; struct sockaddr_ll addr; socklen_t addr_len = sizeof(addr); tm.tv_sec = last_xmit + INARP_DELAY - now; tm.tv_usec = 0; if (tm.tv_sec <= 0) { send_requests(sock); last_xmit = now; continue; } expire_routes(); if (verbose > 2) printf("calling select()\n"); if (select(sock + 1, &set, NULL, NULL, &tm) < 0) { perror("select() failed"); continue; } if (!FD_ISSET(sock, &set)) continue; if (verbose > 2) printf("calling recv()\n"); int len = recvfrom(sock, &buffer, sizeof(buffer), 0, (struct sockaddr*)&addr, &addr_len); dev = get_device(addr.sll_ifindex, GET_DEVICE_DONT_CREATE); if (!dev) { if (verbose > 1) printf("received packet on unknown device\n"); continue; } inbound_inarp(sock, dev, &buffer, len); } }