void set_interface(interface *inter, struct ifaddrs *ifa) { get_name(inter,ifa->ifa_name); get_status(inter,ifa); if (ifa->ifa_addr->sa_family == AF_INET) { get_ipv4(inter,ifa); get_mask(inter,ifa); } if (ifa->ifa_addr->sa_family == AF_INET6) get_ipv6(inter,ifa); if (ifa->ifa_addr->sa_family == AF_PACKET) get_hwaddr(inter,ifa); }
int main(int argc, char **argv) { char *src, *target = NULL, *hw; struct timeval tv; gettimeofday(&tv, NULL); srand(tv.tv_usec); take_lock(); signal(SIGSEGV,sighandler); signal(SIGKILL,sighandler); signal(SIGTERM,sighandler); signal(SIGSEGV,sighandler); signal(SIGALRM,sighandler); alarm(10); src = getenv("INTERFACE"); if (!src) goto out_unlock; configs = get_configs(); hw = get_hwaddr(src); if (!hw) goto out_unlock; // target = get_config_by_hwaddr(hw, src); if (!target) { char *path = NULL; char *contents = NULL; if (asprintf(&path, "/sys/class/net/%s/ifindex", src) == -1) goto out_unlock ; g_file_get_contents(path, &contents, NULL, NULL); free(path); printf("eth%u", atoi(contents) - 2); } out_unlock: unlink(LOCKFILE); exit(0); }
void send_host_info(int fd) { char hostname[100]; char hwaddrbuf[20]; char buf[200]; //struct request req; struct ether_addr hwaddr; gethostname(hostname, 100); get_hwaddr(&hwaddr); sprintf(hwaddrbuf,"%.2x:%.2x:%.2x:%.2x:%.2x:%.2x", (unsigned char)hwaddr.ether_addr_octet[0], (unsigned char)hwaddr.ether_addr_octet[1], (unsigned char)hwaddr.ether_addr_octet[2], (unsigned char)hwaddr.ether_addr_octet[3], (unsigned char)hwaddr.ether_addr_octet[4], (unsigned char)hwaddr.ether_addr_octet[5]); sprintf(buf,"INFO\n\n%s\n%s\n\n", hostname, hwaddrbuf); write(fd, buf, 200); syslog(LOG_DEBUG, "name and hw are sent %s",buf); //request(fd, INFO, buf, &req); }
void * time_stamper() { time_t now; while(1){ sleep(1); time(&now); if(sleeping && now - sleep_time > 5){ syslog(LOG_DEBUG, "i slept"); struct ether_addr hwaddr; struct in_addr ipaddr; get_hwaddr(&hwaddr); get_ipaddr(&ipaddr); send_poison_packet(&ipaddr,&hwaddr, NULL); initialize(); sleeping = 0; //i slept } time(&sleep_time); } }
static void loop_detect_run(void * param) { char *ifname[6] = {"lan1","lan2", "lan3", "lan4", "lan5", "lan6"}; if(init_epoll() !=0 ){ ERROR(DEFAULT_GROUP, "init_epoll faild\n"); } if(packet_sock_init() != 0){ ERROR(DEFAULT_GROUP, "packet sock init faild\n"); } if(netsock_init() != 0){ ERROR(DEFAULT_GROUP, "net sock init faild\n"); } // add port to loop detect module struct LoopDetectDriver lpdDriver; lpdDriver.globalEn = false; lpdDriver.set_port_state = set_port_state; lpdDriver.set_port_shutdown = set_port_shutdown; lpdDriver.set_port_no_shutdown = set_port_no_shutdown; lpdDriver.set_port_no_learn = set_port_no_learn; lpdDriver.set_port_learn = set_port_learn; lpdDriver.alert_push = alert_push; LOOP_INIT(&lpdDriver); //PTN 705 for(int i=0; i< 6; i++){ port_t *prt = malloc(sizeof(port_t)); prt->if_index = get_index(ifname[i], "port"); get_hwaddr(ifname[i], prt->macaddr); strcpy(prt->name, ifname[i]); LOOP_IN_add_port(prt, i); } INFO(DEFAULT_GROUP, "loop detect ready\n"); epoll_main_loop(); pthread_exit(0); }
int main(int argc, char * argv[]) { int i, rc, j , k, l ; int num_devices = 0; struct dev_details * dev_d; int tid; struct thread_context * tctx; void * join_status; struct nw_setup nw_topology[MAX_INTERFACE]; if(argc < 3) { #ifdef __HTX_LINUX__ printf("Usage %s : eth0 eth1 \n", argv[0] ); #else printf("Usage %s : en0 en1 \n", argv[0] ); #endif return(-1); } num_devices = argc - 1; if(num_devices > MAX_INTERFACE) num_devices = MAX_INTERFACE; /* Allocate space for each device details structure */ dev_d = (struct dev_details *)malloc(sizeof(struct dev_details) * num_devices); if(dev_d == (struct dev_details *)NULL) { printf("Unable to allocate space for device sturcture, errno = %d \n", errno); return(-1); } for(i = 0; i < num_devices; i++) { strcpy(&dev_d[i].name, argv[i + 1]); /* Find the mac-address of each interfaces */ rc = get_hwaddr(&dev_d[i].name, dev_d[i].mac_addr); if(rc == -1) { printf(" Unable to get mac address for interface = %s \n", dev_d->name); return(-1); } } /* for(i = 0; i < num_devices; i++) { printf("dev_name=%s, ",dev_d[i].name ); pit("mac_address=",dev_d[i].mac_addr, 6); printf("\n"); } */ /* Now create pthreads for each interface * One thread will send and other will recv. So 2 * threads per interface */ pthread_attr_init(&thread_attrs); pthread_attr_setdetachstate(&thread_attrs, PTHREAD_CREATE_JOINABLE); pthread_attr_setscope(&thread_attrs, PTHREAD_SCOPE_PROCESS); pthread_mutex_init(&create_thread_mutex, NULL); pthread_cond_init(&create_thread_cond, NULL); pthread_cond_init(&start_thread_cond, NULL); rc = pthread_mutex_lock(&create_thread_mutex); if (rc) { printf( "pthread_mutex_lock failed with rc = %d, errno = %d \n", rc, errno); return (rc); } for(tid = 0; tid < num_devices; tid++) { tctx = &t_ctx[tid]; tctx->tid = tid; tctx->retries = NUM_RETRIES; memcpy(&tctx->source.name[0], &dev_d[tid].name[0], 32); memcpy(&tctx->source.mac_addr[0], &dev_d[tid].mac_addr[0], 6); memset(&tctx->dest, 0, sizeof(struct dev_details)); memcpy(&tctx->dev_list, dev_d, (sizeof(struct dev_details) * num_devices)); tctx->num_devices = num_devices; /* Create the worker thread */ rc = pthread_create(&tctx->worker, &thread_attrs, tc_worker_thread, (void *)tctx); if(rc ) { printf(" failed to create worker thread with rc = %d, errnp = %d \n", rc, errno); break; } rc = pthread_cond_wait(&create_thread_cond, &create_thread_mutex); if(rc) { printf("pthread_cond_wait failed with rc = %d, errno = %d \n", rc, errno); break; } if(rc) { break; } } /* check if we are here due to error in creating threads */ if(rc) { printf("No of thread actually created = %d \n", tid); for(i = 0; i < tid; i++) { printf(" Cancelling thread tid = %d, id = %d icoz of error \n", tid, tctx->worker); pthread_cancel(tctx->worker); } return(rc); } else { /* All the worker thread created successfully, start them */ rc = pthread_cond_broadcast(&start_thread_cond); if(rc) { printf("pthread_cond_broadcast failed with rc = %d, errno = %d \n", rc, errno); return(rc); } rc = pthread_mutex_unlock(&create_thread_mutex); if (rc) { printf(" pthread_mutex_unlock failed with rc = %d, errno = %d \n", rc, errno); return(rc); } /* Worker thread started, wait for completion */ for(i = 0; i < tid; i++) { rc = pthread_join(t_ctx[i].worker, &join_status); if(rc) { t_ctx[i].worker_join_rc = *((int *)join_status); printf("tid = %d, rc = %d, join status = %x \n", i, rc, t_ctx[i].worker_join_rc); break; } } } memset(nw_topology, 0, sizeof(struct nw_setup) * MAX_INTERFACE); int count = 0, found_unique = 0; for(i = 0; i < tid; i ++) { if(t_ctx[i].rcvd_reply) { for(j = 0; j < t_ctx[i].num_reply; j++) { found_unique = 0; for(k = 0; k < count; k++) { if(strcmp(&nw_topology[k].src[0], &t_ctx[i].source.name[0]) && strcmp(&nw_topology[k].dest[0], &t_ctx[i].dest[j].name[0]) && strcmp(&nw_topology[k].src[0], &t_ctx[i].dest[j].name[0])&& strcmp(&nw_topology[k].dest[0], &t_ctx[i].source.name[0])) { found_unique++; } } if(found_unique == count ) { strcpy(&nw_topology[count].src[0], &t_ctx[i].source.name[0]); strcpy(&nw_topology[count].dest[0], &t_ctx[i].dest[j].name[0]); printf("%s -> %s \n", &nw_topology[count].src[0], &nw_topology[count].dest[0]); fflush(stdout); count++; found_unique = 0 ; break; } } } } fflush(stdout); /* free thread storage area */ pthread_attr_destroy(&thread_attrs); pthread_cond_destroy(&create_thread_cond); pthread_cond_destroy(&start_thread_cond); pthread_mutex_destroy(&create_thread_mutex); return(0); }
int send_run(int sock) #endif { log_debug("send", "thread started"); pthread_mutex_lock(&send_mutex); #ifdef ZMAP_PCAP_INJECT /* Using pcap, mirror the linux SOCK_RAW behaviour as closely as possible */ unsigned char mac[ETHER_ADDR_LEN]; struct in_addr src_ip = {0}; //pcap_t *pc = get_pcap_t(); /* We don't need the index; we have a pcap handle to the proper interface */ get_hwaddr(mac); get_ipaddr(&src_ip); #else //int sock = get_socket(); struct sockaddr_ll sockaddr; // get source interface index struct ifreq if_idx; memset(&if_idx, 0, sizeof(struct ifreq)); if (strlen(zconf.iface) >= IFNAMSIZ) { log_error("send", "device interface name (%s) too long\n", zconf.iface); return -1; } strncpy(if_idx.ifr_name, zconf.iface, IFNAMSIZ-2); if (ioctl(sock, SIOCGIFINDEX, &if_idx) < 0) { perror("SIOCGIFINDEX"); return -1; } int ifindex = if_idx.ifr_ifindex; // get source interface mac struct ifreq if_mac; memset(&if_mac, 0, sizeof(struct ifreq)); strncpy(if_mac.ifr_name, zconf.iface, IFNAMSIZ-1); if (ioctl(sock, SIOCGIFHWADDR, &if_mac) < 0) { perror("SIOCGIFHWADDR"); return -1; } // find source IP address associated with the dev from which we're sending. // while we won't use this address for sending packets, we need the address // to set certain socket options and it's easiest to just use the primary // address the OS believes is associated. struct ifreq if_ip; memset(&if_ip, 0, sizeof(struct ifreq)); strncpy(if_ip.ifr_name, zconf.iface, IFNAMSIZ-1); if (ioctl(sock, SIOCGIFADDR, &if_ip) < 0) { perror("SIOCGIFADDR"); return -1; } // wbk TODO: gateway MAC. // destination address for the socket memset((void*) &sockaddr, 0, sizeof(struct sockaddr_ll)); sockaddr.sll_ifindex = ifindex; sockaddr.sll_halen = ETH_ALEN; memcpy(sockaddr.sll_addr, zconf.gw_mac, ETH_ALEN); #endif /* not ZMAP_PCAP_INJECT */ /* may move down... TODO wbk */ char buf[MAX_PACKET_SIZE]; memset(buf, 0, MAX_PACKET_SIZE); zconf.probe_module->thread_initialize(buf, #ifdef ZMAP_PCAP_INJECT mac, #else (unsigned char *)if_mac.ifr_hwaddr.sa_data, #endif zconf.gw_mac, zconf.target_port); pthread_mutex_unlock(&send_mutex); // adaptive timing to hit target rate uint32_t count = 0; uint32_t last_count = count; double last_time = now(); uint32_t delay = 0; int interval = 0; volatile int vi; if (zconf.rate > 0) { // estimate initial rate delay = 10000; for (vi = delay; vi--; ) ; delay *= 1 / (now() - last_time) / (zconf.rate / zconf.senders); interval = (zconf.rate / zconf.senders) / 20; last_time = now(); } while (1) { // adaptive timing delay if (delay > 0) { count++; for (vi = delay; vi--; ) ; if (!interval || (count % interval == 0)) { double t = now(); delay *= (double)(count - last_count) / (t - last_time) / (zconf.rate / zconf.senders); if (delay < 1) delay = 1; last_count = count; last_time = t; } } // generate next ip from cyclic group and update global state // (everything locked happens here) pthread_mutex_lock(&send_mutex); if (zsend.complete) { pthread_mutex_unlock(&send_mutex); break; } if (zsend.sent >= zconf.max_targets) { zsend.complete = 1; zsend.finish = now(); pthread_mutex_unlock(&send_mutex); break; } if (zconf.max_runtime && zconf.max_runtime <= now() - zsend.start) { zsend.complete = 1; zsend.finish = now(); pthread_mutex_unlock(&send_mutex); break; } uint32_t curr = cyclic_get_next_ip(); if (curr == zsend.first_scanned) { zsend.complete = 1; zsend.finish = now(); } zsend.sent++; pthread_mutex_unlock(&send_mutex); for (int i=0; i < zconf.packet_streams; i++) { uint32_t src_ip = get_src_ip(curr, i); uint32_t validation[VALIDATE_BYTES/sizeof(uint32_t)]; validate_gen(src_ip, curr, (uint8_t *)validation); zconf.probe_module->make_packet(buf, src_ip, curr, validation, i); if (zconf.dryrun) { zconf.probe_module->print_packet(stdout, buf); } else { int l = zconf.probe_module->packet_length; #ifdef ZMAP_PCAP_INJECT int rc = pcap_inject(pc, buf, (size_t)l); if (rc == -1) { struct in_addr addr; addr.s_addr = curr; log_fatal("send", "pcap_inject() failed for %s. %s", /* TODO: make log_debug */ inet_ntoa(addr), strerror(errno)); pthread_mutex_lock(&send_mutex); zsend.sendto_failures++; pthread_mutex_unlock(&send_mutex); } #else /* TODO: error handling can be shared. */ int rc = sendto(sock, buf + zconf.send_ip_pkts*sizeof(struct ethhdr), l, 0, (struct sockaddr *)&sockaddr, sizeof(struct sockaddr_ll)); if (rc < 0) { struct in_addr addr; addr.s_addr = curr; log_debug("send", "sendto failed for %s. %s", inet_ntoa(addr), strerror(errno)); pthread_mutex_lock(&send_mutex); zsend.sendto_failures++; pthread_mutex_unlock(&send_mutex); } #endif } } } log_debug("send", "thread finished"); return EXIT_SUCCESS; }
int main() { int optval = 1; int s; /* socket */ struct arpMsg arp; fd_set fdset; struct timeval tm; int i = 0; char ipaddr[50]; char interface[10]; struct in_addr dst; char sou_mac[7]; /*source hardware address*/ if ((s = socket (PF_PACKET, SOCK_PACKET, htons(ETH_P_ARP))) == -1) { printf("Could not open raw socket\n"); return -1; } if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, &optval, sizeof(optval)) == -1) { printf( "Could not setsocketopt on raw socket\n"); close(s); return -1; } while (1) { //wait network ok. while(get_net_status(interface, ipaddr)){ sleep(2); } inet_aton(ipaddr, &dst); get_hwaddr(interface, sou_mac); /* wait arp reply, and check it */ FD_ZERO(&fdset); FD_SET(s, &fdset); if (select(s + 1, &fdset, (fd_set *) NULL, (fd_set *) NULL, NULL) < 0) { LOGE("Error on ARPING request: %s\n", strerror(errno)); } else if (FD_ISSET(s, &fdset)) { if (recv(s, &arp, sizeof(arp), 0) < 0 ) LOGE("recv error:%s", strerror(errno)); if(memcmp(arp.sHaddr, sou_mac, 6) == 0) { LOGE("sw_arprecv: IS MYself arp package."); break; } if (arp.operation == htons(ARPOP_REQUEST) && (memcmp(arp.ethhdr.h_dest, "\xff\xff\xff\xff\xff\xff", 6) == 0 || memcmp(arp.ethhdr.h_dest, "\x00\x00\x00\x00\x00\x00", 6) == 0) && memcmp(arp.sInaddr, &dst.s_addr, sizeof(dst.s_addr)) == 0) { LOGD( "Valid arp REQUAST receved from this address,MACaddris:"); LOGE("%02x:%02x:%02x:%02x:%02x:%02x",arp.sHaddr[0],arp.sHaddr[1],arp.sHaddr[2],arp.sHaddr[3],arp.sHaddr[4],arp.sHaddr[5]); send_arp_pkg(s, arp.sHaddr, dst.s_addr, interface, sou_mac); } LOGD("----------------------------------->"); } } close(s); return 0; }
static void device_send_router_solicitation (NMIP6Device *device, const char *why) { int sock, hops; struct sockaddr_in6 sin6; struct nd_router_solicit rs; struct nd_opt_hdr lladdr_hdr; guint8 hwaddr[NM_UTILS_HWADDR_LEN_MAX + 7]; int hwaddr_len; static const guint8 local_routers_addr[] = { 0xFF, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 }; struct msghdr mhdr; struct iovec iov[3]; struct cmsghdr *cmsg; struct in6_pktinfo *ipi; guint8 cmsgbuf[128]; int cmsglen = 0; time_t now; now = time (NULL); if (device->last_solicitation > now - 5) return; device->last_solicitation = now; nm_log_dbg (LOGD_IP6, "(%s): %s: sending router solicitation", device->iface, why); sock = socket (AF_INET6, SOCK_RAW, IPPROTO_ICMPV6); if (sock < 0) { nm_log_dbg (LOGD_IP6, "(%s): could not create ICMPv6 socket: %s", device->iface, g_strerror (errno)); return; } hops = 255; if ( setsockopt (sock, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &hops, sizeof (hops)) == -1 || setsockopt (sock, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &hops, sizeof (hops)) == -1) { nm_log_dbg (LOGD_IP6, "(%s): could not set hop limit on ICMPv6 socket: %s", device->iface, g_strerror (errno)); close (sock); return; } /* Use the "all link-local routers" multicast address */ memset (&sin6, 0, sizeof (sin6)); memcpy (&sin6.sin6_addr, local_routers_addr, sizeof (sin6.sin6_addr)); mhdr.msg_name = &sin6; mhdr.msg_namelen = sizeof (sin6); /* Build the router solicitation */ mhdr.msg_iov = iov; memset (&rs, 0, sizeof (rs)); rs.nd_rs_type = ND_ROUTER_SOLICIT; iov[0].iov_len = sizeof (rs); iov[0].iov_base = &rs; memset (hwaddr, 0, sizeof (hwaddr)); hwaddr_len = get_hwaddr (device->ifindex, hwaddr); if (hwaddr_len > 0) { memset (&lladdr_hdr, 0, sizeof (lladdr_hdr)); lladdr_hdr.nd_opt_type = ND_OPT_SOURCE_LINKADDR; lladdr_hdr.nd_opt_len = (sizeof (lladdr_hdr) + hwaddr_len + 7) % 8; iov[1].iov_len = sizeof (lladdr_hdr); iov[1].iov_base = &lladdr_hdr; iov[2].iov_len = (lladdr_hdr.nd_opt_len * 8) - 2; iov[2].iov_base = hwaddr; mhdr.msg_iovlen = 3; } else mhdr.msg_iovlen = 1; /* Force this to go on the right device */ memset (cmsgbuf, 0, sizeof (cmsgbuf)); cmsg = (struct cmsghdr *) cmsgbuf; cmsglen = CMSG_SPACE (sizeof (*ipi)); cmsg->cmsg_len = CMSG_LEN (sizeof (*ipi)); cmsg->cmsg_level = SOL_IPV6; cmsg->cmsg_type = IPV6_PKTINFO; ipi = (struct in6_pktinfo *) CMSG_DATA (cmsg); ipi->ipi6_ifindex = device->ifindex; mhdr.msg_control = cmsg; mhdr.msg_controllen = cmsglen; if (sendmsg (sock, &mhdr, 0) == -1) { nm_log_dbg (LOGD_IP6, "(%s): could not send router solicitation: %s", device->iface, g_strerror (errno)); } close (sock); }
int main(int argc, char **argv) { int fd; int cmd, flag; struct ifreq ifr; char dev[40]; struct bpq_ethaddr addr; flag = 0; while ((cmd = getopt(argc, argv, "d:a:vVh")) != EOF) { switch (cmd) { case 'd': flag |= 1; if (get_hwaddr(addr.destination, optarg)) { fprintf(stderr, "bpqparms: invalid 'destination' address %s\n", optarg); return 1; } break; case 'a': flag |= 2; if (get_hwaddr(addr.accept, optarg)) { fprintf(stderr, "bpqparms: invalid 'accept' address %s\n", optarg); return 1; } break; case 'V': printf("bpqparms version " VERSION "\n"); printf("Copyright 1996, Jörg Reuter ([email protected])\n"); printf("This program is free software; you can redistribute it and/or modify\n"); printf("it under the terms of the GNU General Public License as published by\n"); printf("the Free Software Foundation; either version 2 of the License, or\n"); printf(" (at your option) any later version.\n\n"); printf("This program is distributed in the hope that it will be useful,\n"); printf("but WITHOUT ANY WARRANTY; without even the implied warranty of\n"); printf("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"); return 0; case 'v': printf("bpqparms: %s\n", VERSION); return(0); case 'h': case ':': case '?': usage(); } } if (!(flag & 0x01) || optind+1 > argc) usage(); strcpy(dev, argv[optind]); if ((flag & 0x02) == 0) memcpy(addr.accept, addr.destination, ETH_ALEN); fd = socket(AF_INET, SOCK_DGRAM, 0); strcpy(ifr.ifr_name, dev); ifr.ifr_data = (caddr_t) &addr; if (ioctl(fd, SIOCSBPQETHADDR, &ifr) < 0) { perror("bpqparms SIOCSBPQETHADDR"); close(fd); return 1; } close(fd); return 0; }
int do_get_hwaddr(char *ifname, __u8 *hwaddr) { return get_hwaddr(ifname, hwaddr); }
// -1: error; don't call us anymore. 0: handled frame. 1: interrupted; we // return for a cancellation check, and the frameptr oughtn't be advanced. The // interface lock must be held upon entry. int handle_ring_packet(interface *iface,int fd,void *frame){ const struct omphalos_ctx *ctx = get_octx(); const omphalos_iface *octx = &ctx->iface; struct tpacket_hdr *thdr = frame; omphalos_packet packet; int len; memset(&packet,0,sizeof(packet)); packet.i = iface; while(thdr->tp_status == 0){ struct pollfd pfd[1]; int events,msec; pfd[0].fd = fd; pfd[0].revents = 0; pfd[0].events = POLLIN | POLLRDNORM | POLLERR; msec = IFACE_TIMESTAT_USECS / 1000; pthread_mutex_unlock(&iface->lock); events = poll(pfd,sizeof(pfd) / sizeof(*pfd),msec); pthread_mutex_lock(&iface->lock); if(events == 0){ gettimeofday(&packet.tv,NULL); timestat_inc(&iface->fps,&packet.tv,0); timestat_inc(&iface->bps,&packet.tv,0); if(octx->packet_read){ octx->packet_read(&packet); } return 1; }else if(events < 0){ if(errno != EINTR){ diagnostic("Error in poll() on %s (%s?)", iface->name,strerror(errno)); return -1; } return 1; }else if(pfd[0].revents & POLLERR){ // FIXME don't want to print this every time a device // is removed from underneath us, but also don't want // to race against notification...check to see if // device is down here? FIXME //diagnostic("Error polling psocket %d on %s",fd,i->name); return -1; } } ++iface->frames; packet.tv.tv_sec = thdr->tp_sec; packet.tv.tv_usec = thdr->tp_usec; timestat_inc(&iface->fps,&packet.tv,1); if(thdr->tp_status & TP_STATUS_LOSING){ struct tpacket_stats tstats; socklen_t slen; // FIXME only call once for each burst of TP_STATUS_LOSING slen = sizeof(tstats); if(getsockopt(fd,SOL_PACKET,PACKET_STATISTICS,&tstats,&slen)){ diagnostic("Error reading stats on %s (%s?)",iface->name,strerror(errno)); }else if(tstats.tp_drops){ iface->drops += tstats.tp_drops; diagnostic("[%s] %u/%ju drops",iface->name,tstats.tp_drops,iface->drops); } } if((thdr->tp_status & TP_STATUS_COPY) || thdr->tp_snaplen != thdr->tp_len){ ++iface->truncated; if((len = recover_truncated_packet(iface,fd,thdr->tp_len)) <= 0){ diagnostic("Partial capture on %s (%u/%ub)", iface->name,thdr->tp_snaplen,thdr->tp_len); frame = (char *)frame + thdr->tp_mac; len = thdr->tp_snaplen; }else{ frame = iface->truncbuf; ++iface->truncated_recovered; len = thdr->tp_len; } }else{ frame = (char *)frame + thdr->tp_mac; len = thdr->tp_len; } timestat_inc(&iface->bps,&packet.tv,len); iface->bytes += len; iface->analyzer(&packet,frame,len); thdr->tp_status = TP_STATUS_KERNEL; // return the frame if(packet.l2s){ l2srcpkt(packet.l2s); } if(packet.l2d){ l2dstpkt(packet.l2d); } if(packet.l3s){ l3_srcpkt(packet.l3s); } if(packet.l3d){ l3_dstpkt(packet.l3d); } if(packet.malformed || packet.noproto){ if(packet.malformed){ ++iface->malformed; } if(packet.noproto){ ++iface->noprotocol; } if(packet.pcap_ethproto){ struct pcap_pkthdr pcap; size_t scribble = 0; struct pcap_ll pll; if(frame != iface->truncbuf){ scribble = thdr->tp_mac; frame -= thdr->tp_mac; }else{ scribble = 0; } pcap.caplen = pcap.len = len + scribble; pcap.ts = packet.tv; memset(&pll,0,sizeof(pll)); pll.arphrd = htons(packet.i->arptype); pll.llen = htons(packet.i->addrlen); if(packet.l2s){ hwaddrint hw = get_hwaddr(packet.l2s); memcpy(&pll.haddr,&hw,packet.i->addrlen > sizeof(pll.haddr) ? sizeof(pll.haddr) : packet.i->addrlen); // FIXME handle other pkttypes if(memcmp(&hw,packet.i->addr,packet.i->addrlen) == 0){ pll.pkttype = htons(4); } } pll.ethproto = htons(packet.pcap_ethproto); // 'frame' starts at the L2 header, *not* the tpacket_thdr log_pcap_packet(&pcap,frame,packet.i->l2hlen + scribble,&pll); if(scribble){ frame += thdr->tp_mac; } } } if(octx->packet_read){ octx->packet_read(&packet); } return 0; }