home *** CD-ROM | disk | FTP | other *** search
- /*
- * ntrace.c
- *
- * Collects (source,dest) traces on Ethernet
- *
- * Usage:
- * ntrace ifname [-debug] [-multicast] [-broadcast] [-w filename]
- *
- * INTR to get current stats
- * QUIT to get out
- *
- */
-
- #include <sys/types.h>
- #include <sys/time.h>
- #include <sys/socket.h>
- #include <net/if.h>
- #include <net/pfilt.h>
- #include <netinet/in_systm.h>
- #include <netinet/in.h>
- #include <netinet/ip.h>
- #include <netinet/tcp.h>
- #include <netinet/udp.h>
- #include <netinet/if_ether.h>
- #include <signal.h>
- #include <stdio.h>
- #include <errno.h>
- #include <arpa/inet.h>
- #include "ntrace.h"
-
- #define TRUNCATION (sizeof(struct ether_header) + \
- sizeof(struct ip) + \
- sizeof(struct tcphdr))
-
- float atof();
-
- int MulticastOnly = 0;
- int BroadcastOnly = 0;
- int debug = 0;
- int Writing = 0;
-
- int TotDrops = 0;
- int TotMissed = 0;
- int Complex = 0;
- int Counted = 0;
-
- int dumpf = 0;
-
- long StartTime;
-
- /* signal mask: ignore everything but SIGQUIT when this is set */
- #define SMASK (0xFFFF & ~(1<<(SIGQUIT-1)))
-
- void catcher()
- {
- printf("\n"); /* after the ^C */
- DoStats(1);
- }
-
- void dostats()
- {
- DoStats(0);
- }
-
- int olddrops = -1;
- int oldmissed = 0;
-
- DoStats(force)
- int force;
- {
- if (force || (TotDrops > olddrops) || (TotMissed > oldmissed)) {
- printf("Drops %d Missed %d ", TotDrops, TotMissed);
- olddrops = TotDrops;
- oldmissed = TotMissed;
- printf("Complex %d Counted %d\n", Complex, Counted);
- }
- }
-
- void GoAway()
- {
- printf("\n");
- DoStats(1);
- exit(1);
- }
-
- main(argc, argv)
- int argc;
- char **argv;
- {
- char *ifname = argv[1];
- struct sigvec svec;
- register int i;
- struct itimerval itval;
- int EtherFid;
-
- DoOptions((argc - 2), &(argv[2]));
-
- svec.sv_handler = catcher;
- svec.sv_mask = SMASK;
- svec.sv_onstack = 0;
- sigvec(SIGINT, &svec, 0);
-
- svec.sv_handler = GoAway;
- svec.sv_mask = SMASK;
- svec.sv_onstack = 0;
- sigvec(SIGQUIT, &svec, 0);
-
- svec.sv_handler = dostats;
- svec.sv_mask = SMASK;
- svec.sv_onstack = 0;
- sigvec(SIGALRM, &svec, 0);
-
- StartTime = time(0);
-
- EtherFid = StartEther(ifname, MulticastOnly, BroadcastOnly);
-
- itval.it_interval.tv_usec = 0;
- itval.it_interval.tv_sec = 1;
- itval.it_value.tv_usec = 0;
- itval.it_value.tv_sec = 1;
- setitimer(ITIMER_REAL, &itval, 0);
-
- RecvLoop(EtherFid);
- }
-
- char buffer[1600*256]; /* big enough */
-
- RecvLoop(EtherFid)
- int EtherFid;
- {
- register int buflen;
- register int stamplen;
- register int pktlen;
- register char *bufp;
- int truncation;
-
- truncation = TRUNCATION;
- if (ioctl(EtherFid, EIOCTRUNCATE, &truncation) < 0)
- perror("ioctl/truncate");
-
- while (1) {
- buflen = read(EtherFid, buffer, (sizeof(buffer)-20));
- bufp = buffer;
- if (buflen < 0) {
- PFReadError(EtherFid, "reader");
- }
- else if (buflen == 0)
- continue;
- else {
- while (buflen > 0) {
- struct enstamp *stp = (struct enstamp *)bufp;
-
- stamplen = stp->ens_stamplen;
- if (stamplen != sizeof(struct enstamp)) {
- fprintf(stderr, "dropping bad stamp\n");
- buflen = -1;
- }
- else {
- pktlen = stp->ens_count;
- TraceIt(&(stp->ens_tstamp), pktlen,
- &(bufp[stamplen]));
- TotDrops += stp->ens_dropped;
- TotMissed = stp->ens_ifoverflows;
- if (pktlen > truncation)
- pktlen = truncation;
- if (buflen == (pktlen + stamplen))
- break;
- pktlen = ENALIGN(pktlen);
- buflen -= (pktlen + stamplen);
- bufp += (pktlen + stamplen);
- }
- }
- if (buflen < 0)
- printf(
- "Warning: part of one or more packets dropped\n");
- }
- }
- }
-
- DoOptions(optc, optv)
- int optc;
- char **optv;
- {
- while (optc > 0) {
- if (optv[0][0] == '-') {
- switch (optv[0][1]) {
-
- case 'm':
- MulticastOnly++;
- break;
-
- case 'b':
- BroadcastOnly++;
- break;
-
- case 'd':
- debug++;
- break;
-
- case 'w':
- if (optc < 2) {
- fprintf(stderr,
- "-w takes a file name argument\n");
- exit(1);
- }
- optc--;
- optv++;
- dumpf = creat(optv[0], 0666);
- if (dumpf < 0) {
- perror(optv[0]);
- exit(1);
- }
- Writing++;
- break;
-
- default:
- fprintf(stderr, "Unknown option %s\n", optv[0]);
- }
- }
- optc--;
- optv++;
- }
- }
-
- #define BUFITEMS 1024
- struct NetTrace nettrace[BUFITEMS];
- struct NetTrace *ntcur = nettrace;
- struct NetTrace *ntend = &(nettrace[BUFITEMS]);
-
- TraceIt(tvp, len, bufp)
- struct timeval *tvp;
- int len;
- char *bufp;
- {
- struct ether_header *ehp;
- struct ip *ipp;
- struct tcphdr *tcpp;
- struct udphdr *udpp;
- int remlen;
- char *ipdata;
- struct NetTrace *ntp = ntcur;
-
- ehp = (struct ether_header *)bufp;
-
- if (ehp->ether_type != ntohs(ETHERTYPE_IP)) {
- /* printf("Not IP %x\n", ehp->ether_type); */
- return;
- }
-
- remlen = len - (sizeof(*ehp) + sizeof(*ipp));
- if (remlen < 0) {
- printf("Runt, len %d\n", len);
- return;
- }
- ipp = (struct ip *)&(bufp[sizeof(*ehp)]);
- ipdata = &(bufp[(sizeof(*ehp) + sizeof(*ipp))]);
- if (ipp->ip_hl != 5) {
- Complex++;
- printf("Options present, hl %d\n", ipp->ip_hl);
- return;
- }
- if (ipp->ip_off) {
- /* printf("Not first frag, off %d\n", ntohs(ipp->ip_off)); */
- return;
- }
-
- /* looks like a keeper? */
- ntp->nt_timestamp = *tvp;
- #ifdef vax
- ntp->nt_srcaddr = ipp->ip_src;
- ntp->nt_dstaddr = ipp->ip_dst;
- #else
- /* possible unaligned access */
- ntp->nt_srcaddr.S_un.S_un_b.s_b1 = ipp->ip_src.S_un.S_un_b.s_b1;
- ntp->nt_srcaddr.S_un.S_un_b.s_b2 = ipp->ip_src.S_un.S_un_b.s_b2;
- ntp->nt_srcaddr.S_un.S_un_b.s_b3 = ipp->ip_src.S_un.S_un_b.s_b3;
- ntp->nt_srcaddr.S_un.S_un_b.s_b4 = ipp->ip_src.S_un.S_un_b.s_b4;
- ntp->nt_dstaddr.S_un.S_un_b.s_b1 = ipp->ip_dst.S_un.S_un_b.s_b1;
- ntp->nt_dstaddr.S_un.S_un_b.s_b2 = ipp->ip_dst.S_un.S_un_b.s_b2;
- ntp->nt_dstaddr.S_un.S_un_b.s_b3 = ipp->ip_dst.S_un.S_un_b.s_b3;
- ntp->nt_dstaddr.S_un.S_un_b.s_b4 = ipp->ip_dst.S_un.S_un_b.s_b4;
- #endif vax
- ntp->nt_proto = ipp->ip_p;
-
- switch (ipp->ip_p) {
- case IPPROTO_UDP:
- if (remlen < sizeof(*udpp)) {
- printf("Runt UDP header (%d short)\n",
- sizeof(*udpp) - remlen);
- return;
- }
- udpp = (struct udphdr *)ipdata;
- ntp->nt_srcport = udpp->uh_sport;
- ntp->nt_dstport = udpp->uh_dport;
- break;
- case IPPROTO_TCP:
- if (remlen < sizeof(*tcpp)) {
- printf("Runt TCP header (%d short)\n",
- sizeof(*tcpp) - remlen);
- return;
- }
- tcpp = (struct tcphdr *)ipdata;
- ntp->nt_srcport = tcpp->th_sport;
- ntp->nt_dstport = tcpp->th_dport;
- break;
- /* known but not handled protocols: */
- case IPPROTO_ICMP:
- return;
- default:
- printf("Unknown protocol %d\n", ipp->ip_p);
- return;
- }
-
- Counted++;
- if (debug)
- PrintNetTrace(ntp);
- if (ntcur++ >= ntend) {
- if (Writing)
- if (write(dumpf, nettrace, sizeof(nettrace))
- < sizeof(nettrace)) {
- perror("writing trace buffer");
- exit(1);
- }
- ntcur = nettrace;
- }
- }
-