void dir_per_packet(struct libtrace_packet_t *packet) { if (trace_get_direction(packet)==-1) return; dir_bytes[trace_get_direction(packet)]+=trace_get_wire_length(packet); ++dir_packets[trace_get_direction(packet)]; }
void per_packet(libtrace_packet_t *packet) { struct timeval ts; /* Get the timestamp for the current packet */ ts = trace_get_timeval(packet); /* If next_report is zero, then this is the first packet from the * trace so we need to determine the time at which the first report * must occur, i.e. 10 seconds from now. */ if (next_report == 0) { next_report = ts.tv_sec + 10; /* This is also a good opportunity to print column headings */ printf("Time\t\tWire Length\tCapture Length\n"); } /* Check whether we need to report average packet sizes or not. * * If the timestamp for the current packet is beyond the time when the * next report was due then we have to output our current stats and * reset it to zero. * * Note that I use a while loop here to ensure that we correctly deal * with periods in which no packets are observed. */ while (ts.tv_sec > next_report) { /* Print the timestamp for the report */ printf("%u\t", next_report); /* Calculate and print the average wire length */ printf("%.2f\t\t", ((double)wire_count) / packet_count); /* Calculate and print the average capture length */ printf("%.2f\n", ((double)capture_count) / packet_count); /* Reset the counters */ packet_count = 0; wire_count = 0; capture_count = 0; /* Determine when the next report is due */ next_report += 10; } /* Increment our counters */ /* Packet count is easy to keep track of */ packet_count += 1; /* Use trace_get_wire_length() to increment our wire length counter */ wire_count += trace_get_wire_length(packet); /* trace_get_capture_length() will tell us the capture length of the * packet */ capture_count += trace_get_capture_length(packet); }
/* Return values: * 1 = continue reading packets * 0 = stop reading packets, cos we're done * -1 = stop reading packets, we've got an error */ static int per_packet(libtrace_packet_t *packet) { double ts = trace_get_seconds(packet); if (trace_get_link_type(packet) == ~0U) { fprintf(stderr, "Halted due to being unable to determine linktype - input trace may be corrupt.\n"); return -1; } if (snaplen>0) { trace_set_capture_length(packet,snaplen); } if (ts <starttime) { return 1; } if ( ts > endtime) { //printf( "%f\t%f\n", ts, endtime); return 0; } if (firsttime==0) { time_t now = trace_get_seconds(packet); if (starttime != 0.0) { firsttime=now-((now - (int)starttime) % interval); } else { firsttime=now; } } if (output && trace_get_seconds(packet)>firsttime+interval) { trace_destroy_output(output); output=NULL; firsttime+=interval; } if (output && pktcount%count==0) { trace_destroy_output(output); output=NULL; } pktcount++; totbytes+=trace_get_capture_length(packet); if (output && totbytes-totbyteslast>=bytes) { trace_destroy_output(output); output=NULL; totbyteslast=totbytes; } if (!output) { char *buffer; bool need_ext=false; if (maxfiles <= filescreated) { return 0; } buffer=strdup(output_base); if (interval!=UINT64_MAX && maxfiles>1) { buffer=strdupcat(buffer,"-"); buffer=strdupcati(buffer,(uint64_t)firsttime); need_ext=true; } if (count!=UINT64_MAX && maxfiles>1) { buffer=strdupcat(buffer,"-"); buffer=strdupcati(buffer,(uint64_t)pktcount); need_ext=true; } if (bytes!=UINT64_MAX && maxfiles>1) { static int filenum=0; buffer=strdupcat(buffer,"-"); buffer=strdupcati(buffer,(uint64_t)++filenum); need_ext=true; } if (need_ext) { if (compress_level!=0) buffer=strdupcat(buffer,".gz"); } if (verbose>1) { fprintf(stderr,"%s:",buffer); if (count!=UINT64_MAX) fprintf(stderr," count=%" PRIu64,pktcount); if (bytes!=UINT64_MAX) fprintf(stderr," bytes=%" PRIu64,bytes); if (interval!=UINT64_MAX) { time_t filetime = firsttime; fprintf(stderr," time=%s",ctime(&filetime)); } else { fprintf(stderr,"\n"); } } output=trace_create_output(buffer); if (trace_is_err_output(output)) { trace_perror_output(output,"%s",buffer); free(buffer); return -1; } if (compress_level!=-1) { if (trace_config_output(output, TRACE_OPTION_OUTPUT_COMPRESS, &compress_level)==-1) { trace_perror_output(output,"Unable to set compression level"); } } if (trace_config_output(output, TRACE_OPTION_OUTPUT_COMPRESSTYPE, &compress_type) == -1) { trace_perror_output(output, "Unable to set compression type"); } trace_start_output(output); if (trace_is_err_output(output)) { trace_perror_output(output,"%s",buffer); free(buffer); return -1; } free(buffer); filescreated ++; } /* Some traces we have are padded (usually with 0x00), so * lets sort that out now and truncate them properly */ if (trace_get_capture_length(packet) > trace_get_wire_length(packet)) { trace_set_capture_length(packet,trace_get_wire_length(packet)); } if (trace_write_packet(output,packet)==-1) { trace_perror_output(output,"write_packet"); return -1; } return 1; }
/* Process a trace, counting packets that match filter(s) */ static void run_trace(char *uri) { struct libtrace_packet_t *packet = trace_create_packet(); int i; uint64_t count = 0; uint64_t bytes = 0; uint64_t packets; fprintf(stderr,"%s:\n",uri); trace = trace_create(uri); if (trace_is_err(trace)) { trace_perror(trace,"Failed to create trace"); return; } if (trace_start(trace)==-1) { trace_perror(trace,"Failed to start trace"); return; } for (;;) { int psize; int wlen; int match = 0; if ((psize = trace_read_packet(trace, packet)) <1) { break; } if (done) break; wlen = trace_get_wire_length(packet); for(i=0; i<filter_count; ++i) { if (filters[i].filter == NULL) continue; if(trace_apply_filter(filters[i].filter,packet) > 0) { ++filters[i].count; filters[i].bytes+=wlen; match = 1; } if (trace_is_err(trace)) { trace_perror(trace, "trace_apply_filter"); fprintf(stderr, "Removing filter from filterlist\n"); filters[i].filter = NULL; } } if(match == 1 || filter_count == 0) { libtrace_ip_t *ip_hdr = trace_get_ip(packet); if(ip_hdr != NULL) { char src_ip[INET_ADDRSTRLEN]; char dst_ip[INET_ADDRSTRLEN]; inet_ntop(AF_INET, &ip_hdr->ip_src, &src_ip[0], INET_ADDRSTRLEN); inet_ntop(AF_INET, &ip_hdr->ip_dst, &dst_ip[0], INET_ADDRSTRLEN); printf("%f\t%s\t%s\t%"PRIu16"\t%"PRIu16"\t" "%"PRIu8"\t%"PRIu16"\t%"PRIu16"\n", trace_get_seconds(packet), src_ip, dst_ip, trace_get_source_port(packet), trace_get_destination_port(packet), ip_hdr->ip_p, ntohs(ip_hdr->ip_id), ntohs(ip_hdr->ip_len) ); } } ++count; bytes+=wlen; } fprintf(stderr, "%-30s\t%12s\t%12s\t%7s\n","filter","count","bytes","%"); for(i=0; i<filter_count; ++i) { fprintf(stderr, "%30s:\t%12"PRIu64"\t%12"PRIu64"\t%7.03f\n", filters[i].expr,filters[i].count, filters[i].bytes,filters[i].count*100.0/count); filters[i].bytes=0; filters[i].count=0; } packets=trace_get_received_packets(trace); if (packets!=UINT64_MAX) fprintf(stderr,"%30s:\t%12" PRIu64"\n", "Input packets", packets); packets=trace_get_filtered_packets(trace); if (packets!=UINT64_MAX) fprintf(stderr,"%30s:\t%12" PRIu64"\n", "Filtered packets", packets); packets=trace_get_dropped_packets(trace); if (packets!=UINT64_MAX) fprintf(stderr,"%30s:\t%12" PRIu64"\n", "Dropped packets",packets); packets=trace_get_accepted_packets(trace); if (packets!=UINT64_MAX) fprintf(stderr,"%30s:\t%12" PRIu64 "\n", "Accepted Packets",packets); fprintf(stderr, "%30s:\t%12"PRIu64"\t%12" PRIu64 "\n","Total",count,bytes); totcount+=count; totbytes+=bytes; if (trace_is_err(trace)) trace_perror(trace,"%s",uri); trace_destroy(trace); }
void pkt(struct lfc *lfc, void *pdata, struct lfc_flow *lf, void *data, double ts, bool up, bool is_new, libtrace_packet_t *pkt) { struct flow *flow = data; struct stats *is; int pktlen; uint32_t iat; double diff, mean, iatd; if (is_new) { flow->up.pktlen_min = UINT16_MAX; flow->up.iat_min = UINT32_MAX; flow->down.pktlen_min = UINT16_MAX; flow->down.iat_min = UINT32_MAX; } is = (up ? &flow->up : &flow->down); is->pkts++; /* pkt length statistics */ pktlen = trace_get_wire_length(pkt); if (pktlen < is->pktlen_min) is->pktlen_min = pktlen; if (pktlen > is->pktlen_max) is->pktlen_max = pktlen; diff = pktlen - is->pktlen_mean; mean = is->pktlen_mean + diff / is->pkts; is->pktlen_std += diff * (pktlen - mean); is->pktlen_mean = mean; /* pkt inter-arrival time */ if (is->last_ts > 0) { iatd = ts - is->last_ts; if (iatd < 0) { iat = 0; } else { /* convert to us */ iatd *= 1000000; if (iatd > UINT32_MAX) iat = UINT32_MAX; else iat = iatd; } if (iat < is->iat_min) is->iat_min = iat; if (iat > is->iat_max) is->iat_max = iat; diff = iat - is->iat_mean; mean = is->iat_mean + diff / is->pkts; is->iat_std += diff * (iat - mean); is->iat_mean = mean; } /* update timestamp of last pkt in this direction */ is->last_ts = ts; }
static int pcap_write_packet(libtrace_out_t *libtrace, libtrace_packet_t *packet) { struct pcap_pkthdr pcap_pkt_hdr; void *link; libtrace_linktype_t linktype; uint32_t remaining; link = trace_get_packet_buffer(packet,&linktype,&remaining); /* We may have to convert this packet into a suitable PCAP packet */ /* If this packet cannot be converted to a pcap linktype then * pop off the top header until it can be converted */ while (libtrace_to_pcap_linktype(linktype)==TRACE_DLT_ERROR) { if (!demote_packet(packet)) { trace_set_err_out(libtrace, TRACE_ERR_NO_CONVERSION, "pcap does not support this format"); return -1; } link = trace_get_packet_buffer(packet,&linktype,&remaining); } if (!OUTPUT.trace.pcap) { int linktype=libtrace_to_pcap_dlt(trace_get_link_type(packet)); OUTPUT.trace.pcap = pcap_open_dead(linktype,65536); if (!OUTPUT.trace.pcap) { trace_set_err_out(libtrace,TRACE_ERR_INIT_FAILED, "Failed to open dead trace: %s\n", pcap_geterr(OUTPUT.trace.pcap)); } OUTPUT.trace.dump = pcap_dump_open(OUTPUT.trace.pcap, libtrace->uridata); if (!OUTPUT.trace.dump) { char *errmsg = pcap_geterr(OUTPUT.trace.pcap); trace_set_err_out(libtrace,TRACE_ERR_INIT_FAILED,"Failed to open output file: %s\n", errmsg ? errmsg : "Unknown error"); return -1; } } /* Corrupt packet, or other "non data" packet, so skip it */ if (link == NULL) { /* Return "success", but nothing written */ return 0; } /* Check if the packet was captured using one of the PCAP formats */ if (packet->trace->format == &pcap || packet->trace->format == &pcapint) { /* Yes - this means we can write it straight out */ pcap_dump((u_char*)OUTPUT.trace.dump, (struct pcap_pkthdr *)packet->header, packet->payload); } else { /* No - need to fill in a PCAP header with the appropriate * values */ /* Leave the manual copy as it is, as it gets around * some OS's having different structures in pcap_pkt_hdr */ struct timeval ts = trace_get_timeval(packet); pcap_pkt_hdr.ts.tv_sec = ts.tv_sec; pcap_pkt_hdr.ts.tv_usec = ts.tv_usec; pcap_pkt_hdr.caplen = remaining; /* trace_get_wire_length includes FCS, while pcap doesn't */ if (trace_get_link_type(packet)==TRACE_TYPE_ETH) if (trace_get_wire_length(packet) >= 4) { pcap_pkt_hdr.len = trace_get_wire_length(packet)-4; } else { pcap_pkt_hdr.len = 0; } else pcap_pkt_hdr.len = trace_get_wire_length(packet); assert(pcap_pkt_hdr.caplen<65536); assert(pcap_pkt_hdr.len<65536); pcap_dump((u_char*)OUTPUT.trace.dump, &pcap_pkt_hdr, packet->payload); } return 0; }