#ifndef lint static char *RCSid = "$Header: /proj/freeware1.0/nfswatch/nfswatch4.1/RCS/snoop.c,v 1.1 1995/08/08 04:40:56 rck Exp $"; #endif #include "os.h" #ifdef USE_SNOOP /* * snoop.c - routines for snooping on network traffic via the SGI * provided snoop(7p) network monitoring protocol * -- works under IRIX 3.2.* and IRIX 3.3.[12] * * NOTE: must be "root" to use this * * Tim Hudson * Mincom Pty Ltd * Mincom Centre * Juliette Street * Greenslopes 4120 * Brisbane Australia * tjh@mincom.oz.au * */ #include #include #include #include #include #include #include #include #include #include #include #include #include "nfswatch.h" #include "externs.h" /* * setup_snoop_dev - set up the network interface tap. */ int setup_snoop_dev(device) char **device; { int n, s; int i, res; u_int chunksz; u_long if_flags; char buf[BUFSIZ]; struct ifconf ifc; struct snoopfilter sf; struct timeval timeout; struct ifreq ifr, *ifrp; struct sockaddr_raw sr, sn; /* * If the interface device was not specified, * get the default one. */ if (*device == NULL) { /* * Grab a socket. */ if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { error("socket"); finish(-1); } ifc.ifc_buf = buf; ifc.ifc_len = sizeof(buf); /* * See what devices we've got. */ if (ioctl(s, SIOCGIFCONF, (char *) &ifc) < 0) { error("ioctl: SIOCGIFCONF"); finish(-1); } /* * Take the first device we encounter. */ ifrp = ifc.ifc_req; for (n = ifc.ifc_len/sizeof(struct ifreq); n > 0; n--,ifrp++) { /* * Skip the loopback interface. */ if (strcmp(ifrp->ifr_name, "lo0") == 0) continue; *device = savestr(ifrp->ifr_name); break; } (void) close(s); } /* * Make the raw socket. */ if ((s = socket(PF_RAW,SOCK_RAW,RAWPROTO_SNOOP)) < 0) { error("snoop: socket"); finish(-1); } /* * Set it up for the chosen interface. */ bzero((char *)&sr, sizeof(sr)); sr.sr_family = AF_RAW; sr.sr_port = 0; strncpy(sr.sr_ifname, *device, sizeof(sr.sr_ifname)); /* * If the bind fails, there's no such device. */ if (bind(s, &sr, sizeof(sr)) < 0) { close(s); return(-1); } /* * Set up NULL filter - this is not necessary ... */ bzero((char *)&sf, sizeof(sf)); if (ioctl(s, SIOCADDSNOOP, &sf) < 0) { error("snoop: add filter"); finish(-1); } /* * Beef up the socket buffer to minimise packet losses */ i = SNOOP_BUFFER_SIZE; if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, (char *)&i, sizeof(i)) < 0) { error("snoop: set rcvbuf"); finish(-1); } return(s); } /* * flush_snoop - flush data from the snoop. */ void flush_snoop(fd) int fd; { int on = 1; int off = 0; /* * Off then on should do a flush methinks */ ioctl(fd, SIOCSNOOPING, &off); if (ioctl(fd, SIOCSNOOPING, &on) < 0) { error("snoop: snoop on"); finish(-1); } } /* * snoop_devtype - determine the type of device we're looking at. */ int snoop_devtype(device) char *device; { /* * This whole routine is a kludge. Ultrix does it the * right way; see pfilt.c. */ if (strncmp(device, "et", 2) == 0 || strncmp(device, "ec", 2) == 0 || strncmp(device, "fxp", 3) == 0 || strncmp(device, "enp", 3) == 0) return(DLT_EN10MB); if (strncmp(device, "ipg", 4) == 0) return(DLT_FDDI); fprintf(stderr, "Unknown device type: %s -- assuming ethernet.\n", device); return(DLT_EN10MB); } #endif /* USE_SNOOP */