PLOTTER new_plotter( tcb *plast, char *filename, /* if NULL, use default name from plast */ char *title, char *xlabel, char *ylabel, char *suffix) { PLOTTER pl; MFILE *f; struct plotter_info *ppi; ++plotter_ix; if (plotter_ix >= max_plotters) { plotter_makemore(); } pl = plotter_ix; ppi = &pplotters[pl]; if (filename == NULL) filename = TSGPlotName(plast,pl,suffix); else if (suffix != NULL) { char buf[100]; snprintf(buf,sizeof(buf),"%s%s", filename, suffix); filename = buf; } if (debug) fprintf(stderr,"Plotter %d file is '%s'\n", pl, filename); if ((f = Mfopen(filename,"w")) == NULL) { perror(filename); return(NO_PLOTTER); } ppi->fplot = f; ppi->p2plast = plast; ppi->filename = strdup(filename); ppi->axis_switched = FALSE; ppi->header_done = FALSE; /* Save these fields to be writtn to the plotter header later in DoPlot() */ ppi->title = strdup(title); ppi->xlabel = strdup(xlabel); ppi->ylabel = strdup(ylabel); return(pl); }
/* dump RTT samples in milliseconds */ static void dump_rtt_sample (tcptrace_context_t *context, tcb * ptcb, segment * pseg, double etime_rtt) { /* if the FILE is "-1", couldn't open file */ if (ptcb->rtt_dump_file == (MFILE *) - 1) { return; } /* if the FILE is NULL, open file */ if (ptcb->rtt_dump_file == (MFILE *) NULL) { MFILE *f; static char filename[15]; snprintf (filename, sizeof (filename), "%s2%s%s", ptcb->host_letter, ptcb->ptwin->host_letter, RTT_DUMP_FILE_EXTENSION); if ((f = Mfopen(context, filename, "w")) == NULL) { perror (filename); ptcb->rtt_dump_file = (MFILE *) - 1; } if (tcptrace_debuglevel) { fprintf (stderr, "RTT Sample file is '%s'\n", filename); } ptcb->rtt_dump_file = f; } Mfprintf (ptcb->rtt_dump_file, "%lu %lu\n", pseg->seq_firstbyte, (int) (etime_rtt / 1000) /* convert from us to ms */ ); }
pread_f *is_tcpdump(char *filename) { char errbuf[100]; char *physname = "<unknown>"; int type; #ifdef __WIN32 if ((pcap = pcap_open_offline(filename, errbuf)) == NULL) { #else if ((pcap = pcap_open_offline("-", errbuf)) == NULL) { #endif /* __WIN32 */ if (debug > 2) fprintf(stderr,"PCAP said: '%s'\n", errbuf); rewind(stdin); return(NULL); } if (debug) { printf("Using 'pcap' version of tcpdump\n"); if (debug > 1) { printf("\tversion_major: %d\n", pcap_major_version(pcap)); printf("\tversion_minor: %d\n", pcap_minor_version(pcap)); printf("\tsnaplen: %d\n", pcap_snapshot(pcap)); printf("\tlinktype: %d\n", pcap_datalink(pcap)); printf("\tswapped: %d\n", pcap_is_swapped(pcap)); } } /* check the phys type (pretend everything is ethernet) */ memset(ð_header,0,EH_SIZE); switch (type = pcap_datalink(pcap)) { case 100: case PCAP_DLT_EN10MB: /* OK, we understand this one */ physname = "Ethernet"; break; case PCAP_DLT_IEEE802: /* just pretend it's normal ethernet */ physname = "Ethernet"; break; case PCAP_DLT_SLIP: eth_header.ether_type = htons(ETHERTYPE_IP); physname = "Slip"; break; case PCAP_DLT_PPP: eth_header.ether_type = htons(ETHERTYPE_IP); physname = "PPP or HDLC PPP"; break; case PCAP_DLT_FDDI: eth_header.ether_type = htons(ETHERTYPE_IP); physname = "FDDI"; break; case PCAP_DLT_NULL: eth_header.ether_type = htons(ETHERTYPE_IP); physname = "NULL"; break; case PCAP_DLT_ATM_RFC1483: eth_header.ether_type = htons(ETHERTYPE_IP); physname = "ATM, LLC/SNAP encapsulated"; break; case PCAP_DLT_RAW: eth_header.ether_type = htons(ETHERTYPE_IP); physname = "RAW_IP"; break; case PCAP_DLT_LINUX_SLL: /* linux cooked socket type */ eth_header.ether_type = htons(ETHERTYPE_IP); physname = "Linux Cooked Socket"; break; case PCAP_DLT_IEEE802_11: eth_header.ether_type = htons(ETHERTYPE_IP); physname = "IEEE802_11"; break; case PCAP_DLT_IEEE802_11_RADIO: eth_header.ether_type = htons(ETHERTYPE_IP); physname = "IEEE802_11_RADIO"; break; case PCAP_DLT_PRISM2: eth_header.ether_type = htons(ETHERTYPE_IP); physname = "PRISM2"; break; case PCAP_DLT_C_HDLC: eth_header.ether_type = htons(ETHERTYPE_IP); physname = "Cisco HDLC"; break; default: fprintf(stderr,"tcptrace did not understand link format (%d)!\n",type); fprintf(stderr, "\t If you can give us a capture file with this link format\n\ \t or even better, a patch to decipher this format, we shall add it in, \n\ \t in a future release.\n"); rewind(stdin); return(NULL); } if (debug) fprintf(stderr,"Tcpdump format, physical type is %d (%s)\n", type, physname); /* set up some stuff */ ip_buf = MallocZ(IP_MAXPACKET); return(pread_tcpdump); } /* support for writing a new pcap file */ void PcapSavePacket( char *filename, struct ip *pip, void *plast) { static MFILE *f_savefile = NULL; struct pcap_pkthdr phdr; int wlen; if (f_savefile == NULL) { struct pcap_file_header fhdr; /* try to open the file */ if ((f_savefile = Mfopen(filename, "w")) == NULL) { perror(filename); exit(-1); } /* make up the header info it wants */ /* this comes from version 2.4, no pcap routine handy :-( */ fhdr.magic = TCPDUMP_MAGIC; fhdr.version_major = PCAP_VERSION_MAJOR; fhdr.version_minor = PCAP_VERSION_MINOR; fhdr.thiszone = 0; /* don't have this info, just make it up */ fhdr.snaplen = 1000000; /* don't have this info, just make it up */ fhdr.linktype = PCAP_DLT_EN10MB; /* always Ethernet (10Mb) */ fhdr.sigfigs = 0; /* write the header */ Mfwrite((char *)&fhdr, sizeof(fhdr), 1, f_savefile); if (debug) fprintf(stderr,"Created pcap save file '%s'\n", filename); } /* create the packet header */ /* (copying time structure in 2 steps to avoid RedHat brain damage) */ phdr.ts.tv_sec = current_time.tv_sec; phdr.ts.tv_usec = current_time.tv_usec; phdr.caplen = (char *)plast - (char *)pip + 1; phdr.caplen += EH_SIZE; /* add in the ether header */ phdr.len = EH_SIZE + ntohs(PIP_LEN(pip)); /* probably this */ /* write the packet header */ Mfwrite(&phdr, sizeof(phdr), 1, f_savefile); /* write a (bogus) ethernet header */ memset(ð_header,0,EH_SIZE); eth_header.ether_type = htons(ETHERTYPE_IP); Mfwrite(ð_header, sizeof(eth_header), 1, f_savefile); /* write the IP/TCP parts */ wlen = phdr.caplen - EH_SIZE; /* remove the ether header */ Mfwrite(pip, wlen, 1, f_savefile); } #else /* GROK_TCPDUMP */ void PcapSavePacket( char *filename, struct ip *pip, void *plast) { fprintf(stderr,"\ Sorry, packet writing only supported with the pcap library\n\ compiled into the program (See GROK_TCPDUMP)\n"); exit(-2); }
void traffic_done(void) { struct traffic_info *pti; struct conn_info *pci; double etime = elapsed(first_packet,last_packet); int etime_secs = etime / 1000000.0; MFILE *pmf; int i; /* roll the active connections into the port records */ for (pci=connhead; pci; pci=pci->next) { if (pci->pti1) ++pci->pti1->ttlactive; if (pci->pti2) ++pci->pti2->ttlactive; ++ports[0]->ttlactive; } AgeTraffic(); pmf = Mfopen(PORT_FILENAME,"w"); printf("Dumping port statistics into file %s\n", PORT_FILENAME); /* dump out the data */ Mfprintf(pmf,"Overall totals by port\n"); for (i=0; i < NUM_PORTS; ++i) { pti = ports[i]; if ((pti != EXCLUDE_PORT) && (pti != INCLUDE_PORT)) { if (i == 0) Mfprintf(pmf,"TOTAL "); else Mfprintf(pmf,"Port %5u ", pti->port); Mfprintf(pmf,"\ bytes: %12lu pkts: %10lu conns: %8lu tput: %8lu B/s\n", pti->ttlbytes, pti->ttlpackets, pti->ttlactive, pti->ttlbytes / etime_secs); } } Mfclose(pmf); /* dump specific stats */ pmf = Mfopen(STATS_FILENAME,"w"); printf("Dumping overall statistics into file %s\n", STATS_FILENAME); pti = ports[0]; Mfprintf(pmf, "\n\nOverall Statistics over %d seconds (%s):\n", etime_secs, elapsed2str(etime)); /* ttl bytes */ Mfprintf(pmf, "%" FS_ULL " ttl bytes sent, %.3f bytes/second\n", data_nbytes_all, (float)data_nbytes_all / ((float)etime_secs)); /* ttl bytes (nonrexmit)*/ Mfprintf(pmf, "%" FS_ULL " ttl non-rexmit bytes sent, %.3f bytes/second\n", data_nbytes_nonrexmit, (float)data_nbytes_nonrexmit / ((float)etime_secs)); /* ttl bytes (nonrexmit)*/ Mfprintf(pmf, "%" FS_ULL " ttl rexmit bytes sent, %.3f bytes/second\n", data_nbytes_all - data_nbytes_nonrexmit, (float)(data_nbytes_all - data_nbytes_nonrexmit) / ((float)etime_secs)); /* ttl packets */ Mfprintf(pmf, "%u packets sent, %.3f packets/second\n", pti->ttlpackets, (float)pti->ttlpackets / ((float)etime_secs)); /* connections opened */ Mfprintf(pmf, "%u connections opened, %.3f conns/second\n", ttl_num_opens, (float)ttl_num_opens / ((float)etime_secs)); /* dupacks */ Mfprintf(pmf, "%u dupacks sent, %.3f dupacks/second\n", ttl_dupacks, (float)ttl_dupacks / ((float)etime_secs)); /* rexmits */ Mfprintf(pmf, "%u rexmits sent, %.3f rexmits/second\n", ttl_rexmits, (float)ttl_rexmits / ((float)etime_secs)); /* RTT */ Mfprintf(pmf, "average RTT: %.3f msecs\n", ttl_rtt_ttl / (float)ttl_rtt_samples); Mfclose(pmf); printf("Plotting performed at %.3f second intervals\n", age_interval); }
static void DoHist( struct samples *psamp) { int i; struct hist3d hist3d; MFILE *f; u_long sum; int slice; int base_z; int slice_size; if (psamp->num_samples == 0) return; printf("Samples: %lu\n", psamp->num_samples); printf("Min: %u\n", psamp->min); printf("Max: %u\n", psamp->max); /* init */ hist3d.rtt.num_buckets = 0; memset(&hist3d.rtt,'\00',sizeof(struct hist)); MakeBuckets(&hist3d.rtt, psamp->num_samples); for (i=0; i < NUM_SLICES; ++i) { memset(&hist3d.rtt_diff_slices[i],'\00',sizeof(struct hist)); MakeBuckets(&hist3d.rtt_diff_slices[i], psamp->num_samples); } /* calculate the global histogram */ for (i=0; i < psamp->num_samples; ++i) { u_short rtt = psamp->samples[i]; ++hist3d.rtt.buckets[rtt]; ++hist3d.rtt.num_samples; } /* find the slices, same amount of data in each slice */ sum = 0; slice = 0; base_z = 0; slice_size = psamp->num_samples / NUM_SLICES; for (i=0; i < psamp->num_samples; ++i) { u_short count = hist3d.rtt.buckets[i]; sum += count; if (sum > slice_size) { hist3d.rtt_diff_slices[slice].z = base_z; ++slice; sum = 0; base_z = i+1; } } for (; slice < NUM_SLICES; ++slice) hist3d.rtt_diff_slices[slice].z = ULONG_MAX; /* add the slice data */ for (i=1; i < psamp->num_samples; ++i) { u_short rtt = psamp->samples[i]; u_short prev_rtt = psamp->samples[i-1]; /* see which slice holds the prev_rtt */ for (slice = NUM_SLICES-1; slice >= 0; --slice) { if (prev_rtt > hist3d.rtt_diff_slices[slice].z) break; } ++hist3d.rtt_diff_slices[slice].buckets[rtt]; ++hist3d.rtt_diff_slices[slice].num_samples; } if ((f = Mfopen("rtt.dat","w")) == NULL) { perror("rtt.dat"); exit (1); } printf("Total Histogram\n"); hist3d.rtt.z = -1; PlotHist(f,&hist3d.rtt); Mfclose(f); if ((f = Mfopen("rtt3d.dat","w")) == NULL) { perror("rtt.dat"); exit (1); } for (i=0; i < NUM_SLICES; ++i) { struct hist *phist = &hist3d.rtt_diff_slices[i]; printf("Slice %d Histogram - base: %lu ms\n", i, phist->z); PlotHist(f,phist); } /* plot the "connections" */ #ifdef BROKEN for (i=0; i < psamp->max; i+=10) { for (slice=0; slice < NUM_SLICES; ++slice) { struct hist *phist = &hist3d.rtt_diff_slices[slice]; u_long count = phist->buckets[i]; float percent = (float)count / phist->num_samples; if (phist->num_samples == 0) continue; fprintf(f,"%4d %lu %.2f\n", i, phist->z, 100 * percent); } fprintf(f,"\n"); } #endif /* BROKEN */ Mfclose(f); }