static bool is_allowed(const struct sockaddr *sa, socklen_t salen, const struct addrinfo *hints, const char *address, const char *service) { struct sockaddr_storage ss; socklen_t len; if (getbluezaddr(address, service, hints, (struct sockaddr *)&ss, &len)) return false; return sockaddr_compare(sa, salen, (const struct sockaddr *)&ss, len); }
int get_imtu(int fd) /* returns interface mtu */ { struct sockaddr_storage sa; socklen_t sl = sizeof(sa); struct ifreq ifreqs[20]; struct ifconf ifconf; int nifaces, i, mtu = 0; memset(&ifconf,0,sizeof(ifconf)); ifconf.ifc_buf = (char*)(ifreqs); ifconf.ifc_len = sizeof(ifreqs); if (getsockname(fd, (struct sockaddr *)&sa, &sl) < 0) return 0; if (ioctl(fd, SIOCGIFCONF, &ifconf) < 0) return 0; nifaces = ifconf.ifc_len/sizeof(struct ifreq); for(i = 0; i < nifaces; i++) { if (sockaddr_compare((struct sockaddr *)&ifreqs[i].ifr_addr, (struct sockaddr *)&sa)) break; } if (ioctl(fd, SIOCGIFMTU, &ifreqs[i]) < 0) return 0; DEBUG_MSG(LOG_NOTICE, "interface %s (%s) has mtu %d", ifreqs[i].ifr_name, fg_nameinfo((struct sockaddr *)&ifreqs[i].ifr_addr, sizeof(struct sockaddr)), ifreqs[i].ifr_mtu); mtu = ifreqs[i].ifr_mtu; if (mtu > 0) return mtu; else return 0; }
static void* fg_pcap_work(void* arg) { /* note: all the wierd casts in this function are completely useless, * execpt they cirumvent strange compiler warnings because of libpcap * typedef woo's */ #ifdef DEBUG struct pcap_stat p_stats; #endif /* DEBUG */ int rc; struct _flow * flow; flow = (struct _flow *) arg; pcap_if_t *d; struct sockaddr_storage sa; socklen_t sl = sizeof(sa); char found = 0; uint32_t net = 0; uint32_t mask = 0; char dump_filename[500]; char hostname[100]; struct bpf_program pcap_program; struct timespec now; char buf[60]; DEBUG_MSG(LOG_DEBUG, "fg_pcap_thread() called for flow %d", flow->id); /* make sure all resources are released when finished */ pthread_detach(pthread_self()); pthread_cleanup_push(fg_pcap_cleanup, (void*) flow); if (getsockname(flow->fd, (struct sockaddr *)&sa, &sl) == -1) { logging_log(LOG_WARNING, "getsockname() failed. Eliding " "packet capture for flow."); goto remove; } /* find appropriate (used for test) interface to dump */ for (d = alldevs; d; d = d->next) { pcap_addr_t *a; for (a = d->addresses; a; a = a->next) { if (!a->addr) continue; if (sockaddr_compare(a->addr, (struct sockaddr *)&sa)) { DEBUG_MSG(LOG_NOTICE, "pcap: data connection " "inbound from %s (%s)", d->name, fg_nameinfo(a->addr, sizeof(struct sockaddr))); found = 1; break; } } if (found) break; } if (!found) { logging_log(LOG_WARNING, "Failed to determine interface " "for data connection. No pcap support."); goto remove; } /* Make sure errbuf contains zero-length string in order to enable * pcap_open_live to report warnings. */ errbuf[0] = '\0'; flow->pcap_handle = (struct pcap_t *)pcap_open_live(d->name, PCAP_SNAPLEN, PCAP_PROMISC, 0, /* no read timeout */ errbuf); if (!flow->pcap_handle) { logging_log(LOG_WARNING, "Failed to init pcap on device %s:" " %s", d->name, errbuf); goto remove; } if (pcap_lookupnet(d->name, &net, &mask, errbuf) < 0) { logging_log(LOG_WARNING, "pcap: netmask lookup failed: %s", errbuf); goto remove; } /* We rely on a non-blocking dispatch loop */ if (pcap_setnonblock((pcap_t *)flow->pcap_handle, 1 /* non-blocking */, errbuf) < 0) { logging_log(LOG_WARNING, "pcap: failed to set non-blocking: " "%s", errbuf); goto remove; } /* compile filter */ if (pcap_compile((pcap_t *)flow->pcap_handle, &pcap_program, PCAP_FILTER, 1, mask) < 0) { logging_log(LOG_WARNING, "pcap: failed compiling filter " "'%s': %s", PCAP_FILTER, pcap_geterr((pcap_t *)flow->pcap_handle)); goto remove; } /* attach filter to interface */ if (pcap_setfilter((pcap_t *)flow->pcap_handle, &pcap_program) < 0) { logging_log(LOG_WARNING, "pcap: failed to set filter: " "%s", pcap_geterr((pcap_t *)flow->pcap_handle)); goto remove; } /* generate a nice filename */ dump_filename[0] = '\0'; /* dir and prefix */ if (dump_dir) strcat(dump_filename, dump_dir); if (dump_prefix) strcat(dump_filename, dump_prefix); /* timestamp */ gettime(&now); strftime(buf, sizeof(buf), "%Y-%m-%d-%H:%M:%S", localtime(&now.tv_sec)); strcat(dump_filename, buf); /* hostname */ hostname[0]= '\0'; if (!gethostname(hostname, 59)) { strcat(dump_filename, "-"); strcat(dump_filename, hostname); } /* interface */ strcat(dump_filename, "-"); strcat(dump_filename, d->name); /* suffix */ strcat(dump_filename, ".pcap"); DEBUG_MSG(LOG_NOTICE, "dumping to \"%s\"", dump_filename); flow->pcap_dumper = (struct pcap_dumper_t *)pcap_dump_open( (pcap_t *)flow->pcap_handle, dump_filename); if (!flow->pcap_dumper) { logging_log(LOG_WARNING, "pcap: failed to open dump file " "writing: %s", pcap_geterr((pcap_t *)flow->pcap_handle)); goto remove; } /* barrier: dump is ready */ #ifndef __DARWIN__ pthread_barrier_wait(&pcap_barrier); #endif /* __DARWIN__ */ for (;;) { rc = pcap_dispatch((pcap_t *)flow->pcap_handle, -1, &pcap_dump, (u_char *)flow->pcap_dumper); if (rc < 0) { logging_log(LOG_WARNING, "pcap_dispatch() failed. " "Packet dumping stopped for flow %d.", flow->id); /* cleanup automatically called */ pthread_exit(0); } #ifdef DEBUG pcap_stats((pcap_t *)flow->pcap_handle, &p_stats); #endif /* DEBUG */ DEBUG_MSG(LOG_NOTICE, "pcap: finished dumping %u packets for " "flow %d", rc, flow->id); DEBUG_MSG(LOG_NOTICE, "pcap: %d packets received by filter for " "flow %d", p_stats.ps_recv, flow->id); DEBUG_MSG(LOG_NOTICE, "pcap: %d packets dropped by kernel for " "flow %d", p_stats.ps_drop, flow->id); if (rc == 0) /* if no packets are received try * if we should cancel */ pthread_testcancel(); } pthread_cleanup_pop(1); remove: #ifndef __DARWIN__ pthread_barrier_wait(&pcap_barrier); #endif /* __DARWIN__ */ return 0; }