/* * Copyright (c) 2000-2004 QoSient, LLC * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ /* * Copyright (c) 1993, 1994 Carnegie Mellon University. * All rights reserved. * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted, * provided that the above copyright notice appear in all copies and * that both that copyright notice and this permission notice appear * in supporting documentation, and that the name of CMU not be * used in advertising or publicity pertaining to distribution of the * software without specific, written prior permission. * * CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL * CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS * SOFTWARE. * */ /* * ArgusSource.c - Argus packet source routines. * * written by Carter Bullard * QoSient, LLC * Tue Aug 8 08:13:36 EDT 2000 * */ #ifndef ArgusSource #define ArgusSource #endif #include #include #include struct ArgusSourceStruct * ArgusNewSource() { struct ArgusSourceStruct *retn = NULL; if ((retn = (struct ArgusSourceStruct *) ArgusCalloc (1, sizeof (struct ArgusSourceStruct))) != NULL) ArgusSnapLen = getArgusSnapLen(); #ifdef ARGUSDEBUG ArgusDebug (1, "ArgusNewSource() returning 0x%x", retn); #endif return (retn); } #include #include #include #include char *ArgusWriteOutPacketFile = NULL; pcap_dumper_t *ArgusPcapOutFile = NULL; void ArgusInitSource () { int type, i; char *cmdbuf = NULL; char errbuf[PCAP_ERRBUF_SIZE]; for (i = 0; i < ARGUS_MAXINTERFACE; i++) { ArgusPd[i] = NULL; bzero ((char *)&ArgusInterface[i], sizeof(struct ArgusInterfaceStruct)); bzero ((char *)&ArgusStats[i], sizeof(struct pcap_stat)); } if (Argusrfile != NULL) { setuid(getuid()); if ((ArgusPd[0] = ArgusOpenInputPacketFile(errbuf)) == NULL) ArgusLog (LOG_ERR, "ArgusInitSource: %s", errbuf); } else { if (ArgusDeviceList == NULL) { char *interface = NULL; if ((interface = pcap_lookupdev (errbuf)) != NULL) setArgusDevice (pcap_lookupdev (errbuf)); else ArgusLog (LOG_ERR, "ArgusInitSource %s", errbuf); } if (ArgusDeviceList) { for (i = 0; i < ArgusDeviceList->count; i++) { ArgusDevice = (char *) ArgusFrontList(ArgusDeviceList); ArgusPopFrontList(ArgusDeviceList); if ((ArgusPd[i] = pcap_open_live(ArgusDevice, ArgusSnapLen, !Arguspflag, 250, errbuf)) != NULL) { ArgusInputPacketFileType = ARGUSLIBPPKTFILE; ArgusInterface[i].ArgusInterfaceType = ARGUSLIBPPKTFILE; ArgusInterface[i].ArgusDevice = ArgusDevice; if (!((pcap_lookupnet (ArgusDevice, (u_int *)&ArgusInterface[i].ArgusLocalNet, (u_int *)&ArgusInterface[i].ArgusNetMask, errbuf)) < 0)) { ArgusInterface[i].ArgusLocalNet = ntohl(ArgusInterface[i].ArgusLocalNet); ArgusInterface[i].ArgusNetMask = ntohl(ArgusInterface[i].ArgusNetMask); } } else ArgusLog (LOG_ERR, "ArgusInitSource: pcap_open_live %s", errbuf); ArgusPushBackList(ArgusDeviceList, ArgusDevice); } } setuid(getuid()); } ArgusCallBack = Arguslookup_pcap_callback(type = pcap_datalink(ArgusPd[0])); setArgusInterfaceType(ArgusInterface[0].ArgusInterfaceType); if (ArgusInfile) { cmdbuf = ArgusReadInfile(ArgusInfile); } else cmdbuf = ArgusCopyArgv(&ArgusArgv[ArgusOptind]); if (cmdbuf) { if (ArgusInputFilter) ArgusFree(ArgusInputFilter); ArgusInputFilter = cmdbuf; } bzero ((char *) &ArgusFilters[0], sizeof (struct bpf_program)); if (pcap_compile (ArgusPd[0], &ArgusFilters[0], ArgusInputFilter, getArgusOflag(), ArgusNetMask) < 0) ArgusLog (LOG_ERR, "ArgusInputFilter \"%s\" %s", ArgusInputFilter, pcap_geterr (ArgusPd[0])); if (Argusbpflag) { Argusbpf_dump (&ArgusFilters[0], Argusbpflag); exit(0); } for (i = 0; i < ARGUS_MAXINTERFACE; i++) { if (ArgusPd[i] != NULL) { if (ArgusInputPacketFileType == ARGUSLIBPPKTFILE) { if (pcap_setfilter (ArgusPd[i], &ArgusFilters[0]) < 0) ArgusLog (LOG_ERR, "%s", pcap_geterr (ArgusPd[i])); } } } if (ArgusWriteOutPacketFile) { if ((ArgusPcapOutFile = pcap_dump_open(ArgusPd[0], ArgusWriteOutPacketFile)) == NULL) ArgusLog (LOG_ERR, "%s", pcap_geterr (ArgusPd[0])); } #ifdef ARGUSDEBUG ArgusDebug (1, "ArgusInitSource() returning"); #endif } int ArgusDeleteSource() { if (ArgusSourceTask) ArgusFree (ArgusSourceTask); if (ArgusInputFilter) ArgusFree (ArgusInputFilter); if (ArgusDeviceList) ArgusDeleteList(ArgusDeviceList); if (ArgusPcapOutFile) pcap_dump_close(ArgusPcapOutFile); #ifdef ARGUSDEBUG ArgusDebug (1, "ArgusDeleteSource() deleting ArgusSourceTask 0x%x", ArgusSourceTask); #endif return (0); } int getArgusbpflag() { return (Argusbpflag); } int getArguspflag() { return (Arguspflag); } int getArgusOflag() { return (ArgusOflag); } void setArgusbpflag(int value) { Argusbpflag = value; } void setArguspflag(int value) { Arguspflag = value; } void setArgusOflag(int value) { ArgusOflag = value; } void setArgusArgv(char **value) { ArgusArgv = value; } void setArgusOptind (int value) { ArgusOptind = value; } char * getArgusDevice () { char * retn = NULL; if (ArgusDeviceList != NULL) retn = (char *) ArgusFrontList(ArgusDeviceList); #ifdef ARGUSDEBUG ArgusDebug (3, "getArgusDevice() returning %s", retn); #endif return (retn); } void setArgusDevice (char *value) { if (ArgusDeviceList == NULL) ArgusDeviceList = ArgusNewList(); if (value) ArgusPushFrontList(ArgusDeviceList, strdup(value)); #ifdef ARGUSDEBUG ArgusDebug (3, "setArgusDevice(%s) returning", value); #endif } void clearArgusDevice () { if (ArgusDeviceList != NULL) { ArgusDeleteList(ArgusDeviceList); ArgusDeviceList = NULL; } #ifdef ARGUSDEBUG ArgusDebug (3, "clearArgusDevice(%s) returning"); #endif } char * getArgusInfile () { return (ArgusInfile); } void setArgusInfile (char *value) { ArgusInfile = value; } char * getArgusrfile () { return (Argusrfile); } void setArgusrfile (char *value) { Argusrfile = value; } int getArgusMoatTshFile () { return(Argustflag); } void setArgusMoatTshFile (int value) { Argustflag = value; } void setArgusWriteOutPacketFile (char *file) { ArgusWriteOutPacketFile = strdup(file); } #define ARGUSMOATLEN 44 #define ARGUSMOATTSHTCPLEN 40 int ArgusMoatTshRead (void); int ArgusMoatTshRead () { struct ArgusMoatTshPktHdr MoatTshBuffer[2], *ArgusMoatPktHdr = &MoatTshBuffer[0]; int retn = 0, length = 0; struct ip *iphdr = NULL; bzero (ArgusMoatPktHdr, sizeof(MoatTshBuffer)); if ((retn = read(pcap_fileno(ArgusPd[0]), ArgusMoatPktHdr, ARGUSMOATLEN)) == ARGUSMOATLEN) { ArgusGlobalTime.tv_sec = ntohl(ArgusMoatPktHdr->sec); ArgusMoatPktHdr->interface = 0; ArgusGlobalTime.tv_usec = ntohl(*((int *)&ArgusMoatPktHdr->interface)); iphdr = &ArgusMoatPktHdr->ip; length = ntohs(iphdr->ip_len); ArgusThisLength = length; switch (iphdr->ip_p) { case IPPROTO_ICMP: case IPPROTO_TCP: default: ArgusSnapLength = ARGUSMOATTSHTCPLEN; break; } ArgusThisSnapEnd = (((unsigned char *)iphdr) + ArgusSnapLength); if ((ArgusFilters[0].bf_insns == NULL) || (bpf_filter(ArgusFilters[0].bf_insns, (unsigned char *)iphdr, ArgusSnapLength, ArgusSnapLen))) { ArgusProcessIpPacket (iphdr, length, &ArgusGlobalTime); } } else close(pcap_fileno(ArgusPd[0])); #ifdef ARGUSDEBUG ArgusDebug (5, "ArgusMoatTshRead() returning %d", retn); #endif return (retn); } int ArgusSnoopRead () { int retn = 0, len = 0; struct pcap_pkthdr pcap_pkthdr; struct ArgusSnoopPktHdr SnoopPktHdr; unsigned char ArgusPacketBuf[1540]; bzero (ArgusPacketBuf, sizeof(ArgusPacketBuf)); if ((retn = read(pcap_fileno(ArgusPd[0]), &SnoopPktHdr, sizeof(SnoopPktHdr))) == sizeof(SnoopPktHdr)) { SnoopPktHdr.len = ntohl(SnoopPktHdr.len); SnoopPktHdr.tlen = ntohl(SnoopPktHdr.tlen); SnoopPktHdr.argtvp.tv_sec = ntohl(SnoopPktHdr.argtvp.tv_sec); SnoopPktHdr.argtvp.tv_usec = ntohl(SnoopPktHdr.argtvp.tv_usec); if ((len = ((SnoopPktHdr.tlen + 3) & 0xFFFFFFC)) < 1500) { if ((retn = read(pcap_fileno(ArgusPd[0]), ArgusPacketBuf, len)) == len) { pcap_pkthdr.ts.tv_sec = SnoopPktHdr.argtvp.tv_sec; pcap_pkthdr.ts.tv_usec = SnoopPktHdr.argtvp.tv_usec; pcap_pkthdr.caplen = SnoopPktHdr.tlen; pcap_pkthdr.len = SnoopPktHdr.len; if ((ArgusFilters[0].bf_insns == NULL) || (bpf_filter(ArgusFilters[0].bf_insns, ArgusPacketBuf, SnoopPktHdr.tlen, ArgusSnapLen))) { ArgusCallBack (NULL, &pcap_pkthdr, ArgusPacketBuf); } } } } else { close(pcap_fileno(ArgusPd[0])); retn = -1; } #ifdef ARGUSDEBUG ArgusDebug (5, "ArgusSnoopRead() returning %d", retn); #endif return (retn); } pcap_handler Arguslookup_pcap_callback (int type) { pcap_handler retn = NULL; struct callback *callback; char *name = NULL; for (callback = callbacks; callback->function; ++callback) if (type == callback->type) { retn = callback->function; name = callback->fname; break; } #ifdef ARGUSDEBUG ArgusDebug (3, "Arguslookup_pcap_callback(%d) returning %s: 0x%x", type, name, retn); #endif return (retn); } #define MAXSTRSIZE 1024 #define ARGUS_MAXSNAPLEN 2048 u_char ArgusPacketBuffer[ARGUS_MAXSNAPLEN]; void ArgusEtherPacket (u_char *user, const struct pcap_pkthdr *h, const u_char *p) { struct ether_header *ep; struct timeval *tvp = (struct timeval *) &h->ts; struct stat statbuf; unsigned int length = h->len; unsigned int caplen = h->caplen; ArgusGlobalTime = *tvp; bcopy (p, ArgusPacketBuffer, caplen); ep = (struct ether_header *) ArgusPacketBuffer; ArgusThisLength = length; ArgusSnapLength = caplen; ArgusThisSnapEnd = ((u_char *)ep) + caplen; if (p && length) { if (ArgusProcessPacket (ep, length, tvp)) { if (ArgusWriteOutPacketFile) { if (stat(ArgusWriteOutPacketFile, &statbuf) < 0) { if (ArgusPcapOutFile != NULL) { pcap_dump_close(ArgusPcapOutFile); ArgusPcapOutFile = NULL; } if ((ArgusPcapOutFile = pcap_dump_open(ArgusPd[0], ArgusWriteOutPacketFile)) == NULL) ArgusLog (LOG_ERR, "%s", pcap_geterr (ArgusPd[0])); } } } } if (ArgusPcapOutFile != NULL) pcap_dump((u_char *)ArgusPcapOutFile, h, p); #ifdef ARGUSDEBUG ArgusDebug (6, "ArgusEtherPacket (0x%x, 0x%x, 0x%x) returning", user, h, p); #endif } #if defined(ultrix) || defined(__alpha) static int fddi_bitswap = 0; #else static int fddi_bitswap = 1; #endif int fddipad = FDDIPAD; #define FDDI_HDRLEN (sizeof(struct fddi_header)) static u_char fddi_bit_swap[] = { 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff, }; static inline void Argusextract_fddi_addrs(const struct fddi_header *fp, struct ether_header *ehdr) { char *fsrc = (char *)&ehdr->ether_shost; char *fdst = (char *)&ehdr->ether_dhost; int i; if (fddi_bitswap) { for (i = 0; i < 6; ++i) fdst[i] = fddi_bit_swap[fp->fddi_dhost[i]]; for (i = 0; i < 6; ++i) fsrc[i] = fddi_bit_swap[fp->fddi_shost[i]]; } else { bcopy ((char *) fp->fddi_dhost, fdst, 6); bcopy ((char *) fp->fddi_shost, fsrc, 6); } } int ArgusCreatePktFromFddi(const struct fddi_header *fp, struct ether_header *ep, int length) { unsigned char *ptr; unsigned int retn = 0; struct llc *llc; if ((fp->fddi_fc & FDDIFC_CLFF) == FDDIFC_LLC_ASYNC) { Argusextract_fddi_addrs (fp, ep); llc = (struct llc *)(fp + 1); if (llc->ssap == LLCSAP_SNAP && llc->dsap == LLCSAP_SNAP && llc->llcui == LLC_UI) { ((struct ether_header *) ep)->ether_type = EXTRACT_SHORT(&llc->ethertype[0]); ptr = (unsigned char *)(llc + 1); length -= (sizeof(struct fddi_header) + sizeof(struct llc)); bcopy ((char *)ptr, (char *)(ep + 1), length); retn = length + sizeof(struct ether_header); } } return (retn); } void ArgusFddiPacket(u_char *user, const struct pcap_pkthdr *h, const u_char *p) { struct ether_header *ep = (struct ether_header *) ArgusPacketBuffer; struct timeval *tvp = (struct timeval *) &h->ts; unsigned int length = h->len; unsigned int caplen = h->caplen; const struct fddi_header *fp = (struct fddi_header *)p; ArgusGlobalTime = *tvp; if (ArgusGlobalTime.tv_sec < 0) { ArgusLog (LOG_ERR, "ArgusFddiPacket (0x%x, 0x%x, 0x%x) libpcap timestamp out of range %d.%d", user, h, p, ArgusGlobalTime.tv_sec, ArgusGlobalTime.tv_usec); } ArgusThisLength = length; ArgusSnapLength = caplen; ArgusThisSnapEnd = ((u_char *)ep) + caplen; if (p && (length = ArgusCreatePktFromFddi(fp, ep, length))) { if (p && length) ArgusProcessPacket (ep, length, tvp); } #ifdef ARGUSDEBUG ArgusDebug (6, "ArgusFddiPacket (0x%x, 0x%x, 0x%x) returning", user, h, p); #endif } #define ARGUS_802_6_MAC_HDR_LEN 20 #define ARGUS_ATM_HDR_OFFSET 8 void ArgusATMPacket(u_char *user, const struct pcap_pkthdr *h, const u_char *p) { struct ether_header *ep = (struct ether_header *) ArgusPacketBuffer; struct timeval *tvp = (struct timeval *) &h->ts; unsigned int length = h->len; unsigned int caplen = h->caplen; ArgusGlobalTime = *tvp; if (ArgusGlobalTime.tv_sec < 0) { ArgusLog (LOG_ERR, "ArgusATMPacket (0x%x, 0x%x, 0x%x) libpcap timestamp out of range %d.%d", user, h, p, ArgusGlobalTime.tv_sec, ArgusGlobalTime.tv_usec); } if (caplen > 8) { if (p[0] != 0xaa || p[1] != 0xaa || p[2] != 0x03) { if (caplen > 28) { p += ARGUS_802_6_MAC_HDR_LEN; length -= ARGUS_802_6_MAC_HDR_LEN; caplen -= ARGUS_802_6_MAC_HDR_LEN; } else return; } } else return; ep->ether_type = ((p[6] << 8) | p[7]); length -= ARGUS_ATM_HDR_OFFSET; caplen -= ARGUS_ATM_HDR_OFFSET; p += ARGUS_ATM_HDR_OFFSET; bcopy (p, (char *)(ep + 1), caplen); length += sizeof(*ep); caplen += sizeof(*ep); ArgusThisLength = length; ArgusSnapLength = caplen; ArgusThisSnapEnd = ((u_char *)ep) + caplen; ArgusProcessPacket (ep, length, tvp); #ifdef ARGUSDEBUG ArgusDebug (6, "ArgusATMPacket (0x%x, 0x%x, 0x%x) returning", user, h, p); #endif } #define ARGUS_PPP_HDR_LEN 4 void ArgusPppPacket(u_char *user, const struct pcap_pkthdr *h, const u_char *p) { struct timeval *tvp = (struct timeval *) &h->ts; struct ip *ip = (struct ip *) (p + ARGUS_PPP_HDR_LEN); unsigned int length = h->len; unsigned int caplen = h->caplen; ArgusGlobalTime = *tvp; if (ArgusGlobalTime.tv_sec < 0) { ArgusLog (LOG_ERR, "ArgusPppPacket (0x%x, 0x%x, 0x%x) libpcap timestamp out of range %d.%d", user, h, p, ArgusGlobalTime.tv_sec, ArgusGlobalTime.tv_usec); } ArgusSnapLength = caplen; ArgusThisSnapEnd = ((u_char *)ip) + (caplen - ARGUS_PPP_HDR_LEN); if (p && (length > ARGUS_PPP_HDR_LEN)) { length -= ARGUS_PPP_HDR_LEN; ArgusThisLength = length; ArgusProcessIpPacket (ip, length, tvp); } #ifdef ARGUSDEBUG ArgusDebug (6, "ArgusPppPacket (0x%x, 0x%x, 0x%x) returning", user, h, p); #endif } #include #define ARGUS_PPPBSDOS_HDR_LEN 24 void ArgusPppBsdosPacket(u_char *user, const struct pcap_pkthdr *h, const u_char *p) { struct timeval *tvp = (struct timeval *) &h->ts; unsigned int length = h->len, hdrlen = 0; unsigned int caplen = h->caplen; unsigned short ptype = 0; ArgusGlobalTime = *tvp; if (ArgusGlobalTime.tv_sec < 0) { ArgusLog (LOG_ERR, "ArgusPppBsdosPacket (0x%x, 0x%x, 0x%x) libpcap timestamp out of range %d.%d", user, h, p, ArgusGlobalTime.tv_sec, ArgusGlobalTime.tv_usec); } ArgusSnapLength = caplen; ArgusThisSnapEnd = (u_char *) p + caplen; if (p[0] == PPP_ADDRESS && p[1] == PPP_CONTROL) { p += 2; hdrlen = 2; } if (*p & 01) { /* Retrieve the protocol type */ ptype = *p; /* Compressed protocol field */ p++; hdrlen += 1; } else { ptype = ntohs(*(u_short *)p); p += 2; hdrlen += 2; } length -= hdrlen; if (ptype == PPP_IP) if (p && (length > 0)) { ArgusThisLength = length; ArgusProcessIpPacket ((struct ip *) p, length, tvp); } #ifdef ARGUSDEBUG ArgusDebug (6, "ArgusPppPacket (0x%x, 0x%x, 0x%x) returning", user, h, p); #endif } #if defined(__NetBSD__) || defined(__OpenBSD__) #include #include #endif #include #include /* XXX BSD/OS 2.1 compatibility */ #if !defined(ARGUS_SLIP_HDR_LEN) && defined(SLC_BPFHDR) #define SLIP_HDRLEN SLC_BPFHDR #define SLX_DIR 0 #define SLX_CHDR (SLC_BPFHDRLEN - 1) #define CHDR_LEN (SLC_BPFHDR - SLC_BPFHDRLEN) #else #endif void ArgusSlipPacket(u_char *user, const struct pcap_pkthdr *h, const u_char *p) { struct timeval *tvp = (struct timeval *) &h->ts; struct ip *ip = (struct ip *) (p + SLIP_HDRLEN); unsigned int length = h->len; unsigned int caplen = h->caplen; ArgusGlobalTime = *tvp; if (ArgusGlobalTime.tv_sec < 0) { ArgusLog (LOG_ERR, "ArgusSlipPacket (0x%x, 0x%x, 0x%x) libpcap timestamp out of range %d.%d", user, h, p, ArgusGlobalTime.tv_sec, ArgusGlobalTime.tv_usec); } ArgusSnapLength = caplen; ArgusThisSnapEnd = ((u_char *)ip) + (caplen - SLIP_HDRLEN); if (p && (length > SLIP_HDRLEN)) { length -= SLIP_HDRLEN; ArgusThisLength = length; ArgusProcessIpPacket (ip, length, tvp); } #ifdef ARGUSDEBUG ArgusDebug (6, "ArgusSlipPacket (0x%x, 0x%x, 0x%x) returning", user, h, p); #endif } void ArgusIpPacket(u_char *user, const struct pcap_pkthdr *h, const u_char *p) { struct timeval *tvp = (struct timeval *) &h->ts; struct ip *ip = (struct ip *) p; unsigned int length = h->len; unsigned int caplen = h->caplen; ArgusGlobalTime = *tvp; if (ArgusGlobalTime.tv_sec < 0) { ArgusLog (LOG_ERR, "ArgusIpPacket (0x%x, 0x%x, 0x%x) libpcap timestamp out of range %d.%d", user, h, p, ArgusGlobalTime.tv_sec, ArgusGlobalTime.tv_usec); } ArgusSnapLength = caplen; ArgusThisSnapEnd = ((u_char *) ip) + caplen; if (p) { ArgusThisLength = length; ArgusProcessIpPacket (ip, length, tvp); } #ifdef ARGUSDEBUG ArgusDebug (6, "ArgusIpPacket (0x%x, 0x%x, 0x%x) returning", user, h, p); #endif } #include #ifndef ETHER_ADDR_LEN #define ETHER_ADDR_LEN 6 #endif void ArgusSllPacket(u_char *user, const struct pcap_pkthdr *h, const u_char *p) { unsigned int length = h->len; unsigned int caplen = h->caplen; const struct sll_header *sllp = NULL; u_short pkttype; struct timeval *tvp = (struct timeval *) &h->ts; unsigned char buf[2048]; struct ether_header *ep = (struct ether_header *)buf; ArgusGlobalTime = *tvp; if (ArgusGlobalTime.tv_sec < 0) { ArgusLog (LOG_ERR, "ArgusSllPacket (0x%x, 0x%x, 0x%x) libpcap timestamp out of range %d.%d", user, h, p, ArgusGlobalTime.tv_sec, ArgusGlobalTime.tv_usec); } sllp = (const struct sll_header *)p; memcpy((void *)&ep->ether_shost, sllp->sll_addr, ETHER_ADDR_LEN); pkttype = ntohs(sllp->sll_pkttype); if (pkttype != LINUX_SLL_OUTGOING) { if (pkttype == LINUX_SLL_BROADCAST) memset((void *)&ep->ether_dhost, 0xFF, ETHER_ADDR_LEN); else { memset((void *)&ep->ether_dhost, 0, ETHER_ADDR_LEN); if (pkttype == LINUX_SLL_MULTICAST) #if defined(HAVE_SOLARIS) ep->ether_dhost.ether_addr_octet[0] = 0x01; #else ep->ether_dhost[0] = 0x01; #endif else #if defined(HAVE_SOLARIS) ep->ether_dhost.ether_addr_octet[ETHER_ADDR_LEN-1] = 0x01; #else ep->ether_dhost[ETHER_ADDR_LEN-1] = 0x01; #endif } } else { /* * We sent this packet; we don't know whether it's * broadcast, multicast, or unicast, so just make * the destination address all 0's. */ memset((void *)&ep->ether_dhost, 0, ETHER_ADDR_LEN); } length -= SLL_HDR_LEN; caplen -= SLL_HDR_LEN; p += SLL_HDR_LEN; ep->ether_type = sllp->sll_protocol; memcpy((ep + 1), p, caplen); ArgusThisSnapEnd = (unsigned char *)(ep + caplen); ArgusThisLength = length; ArgusSnapLength = caplen; ArgusProcessPacket (ep, length, tvp); #ifdef ARGUSDEBUG ArgusDebug (6, "ArgusSllPacket (0x%x, 0x%x, 0x%x) returning", user, h, p); #endif } void ArgusGetPackets () { fd_set ArgusReadMask, ArgusWriteMask, ArgusExceptMask; struct timeval wait, tvpbuf, *tvp = &tvpbuf; int tmp, i, width = 0, noerror = 1; #if defined(HAVE_SOLARIS) sigignore (SIGPIPE); #else signal (SIGPIPE, SIG_IGN); #endif FD_ZERO(&ArgusReadMask); FD_ZERO(&ArgusWriteMask); FD_ZERO(&ArgusExceptMask); wait.tv_sec = 0; wait.tv_usec = 200000; if (ArgusPd[0] && ArgusCallBack) { int found = 0; for (i = 0; i < ARGUS_MAXINTERFACE; i++) { if (ArgusPd[i] && (pcap_fileno(ArgusPd[i]) >= 0)) { found++; FD_SET(pcap_fileno(ArgusPd[i]), &ArgusReadMask); if (width < pcap_fileno(ArgusPd[i])) width = pcap_fileno(ArgusPd[i]); } } if (!(ArgusReadingOffLine)) { do { if ((tmp = select (width + 1, &ArgusReadMask, NULL, NULL, &wait)) >= 0) { found = 0; if (tmp > 0) { for (i = 0; i < ARGUS_MAXINTERFACE; i++) { if ((ArgusPd[i]) && (pcap_fileno(ArgusPd[i]) >= 0)) { if (FD_ISSET(pcap_fileno(ArgusPd[i]), &ArgusReadMask)) { found++; ArgusInterfaceIndex = i; switch (ArgusInterface[i].ArgusInterfaceType) { case ARGUSLIBPPKTFILE: if ((pcap_read (ArgusPd[i], -1, ArgusCallBack, (u_char *) NULL)) < 0) { #ifdef ARGUSDEBUG ArgusDebug (4, "ArgusGetPackets: pcap_read() returned %s", pcap_geterr(ArgusPd[i])); #endif noerror = 0; } break; case ARGUSSNOOPKTFILE: if (ArgusSnoopRead () < 0) noerror = 0; break; case ARGUSMOATTSHPKTFILE: if (ArgusMoatTshRead () < 0) noerror = 0; break; } if (Nflag > 0) Nflag--; } } } } if (!(found)) { gettimeofday (tvp, NULL); ArgusGlobalTime = *tvp; if (ArgusGlobalTime.tv_sec < 0) { ArgusLog (LOG_ERR, "ArgusGetPackets () gettimeofday() timestamp out of range %d.%d", ArgusGlobalTime.tv_sec, ArgusGlobalTime.tv_usec); } if (ArgusUpdateTime ()) ArgusSystemTimeout(); } } else { FD_ZERO(&ArgusReadMask); #ifdef ARGUSDEBUG ArgusDebug (4, "ArgusGetPackets: select() returned %s", strerror(errno)); #endif if (errno == EINTR) break; } width = 0; found = 0; for (i = 0; i < ARGUS_MAXINTERFACE; i++) if (ArgusPd[i]) { if (pcap_fileno(ArgusPd[i]) >= 0) { found ++; FD_SET(pcap_fileno(ArgusPd[i]), &ArgusReadMask); if (width < pcap_fileno(ArgusPd[i])) width = pcap_fileno(ArgusPd[i]); } } if (!found) break; wait.tv_sec = 0; wait.tv_usec = 200000; } while (noerror && (Nflag != 0) && (!(ArgusShutDownStarted))); } else { pcap_offline_read (ArgusPd[0], -1, ArgusCallBack, (u_char *) NULL); } } gettimeofday (&ArgusEndTime, 0L); #ifdef ARGUSDEBUG ArgusDebug (4, "ArgusGetPackets () returning"); #endif } void Argusbpf_dump(struct bpf_program *p, int option) { struct bpf_insn *insn; int i, n = p->bf_len; insn = p->bf_insns; if (option > 2) { fprintf(stdout, "%d\n", n); for (i = 0; i < n; ++insn, ++i) { fprintf(stdout, "%lu %lu %lu %lu\n", (long) insn->code, (long) insn->jt, (long) insn->jf, (long) insn->k); } return ; } if (option > 1) { for (i = 0; i < n; ++insn, ++i) { fprintf(stdout, "{ 0x%x, %d, %d, 0x%08x },\n", insn->code, insn->jt, insn->jf, (int) insn->k); } return; } for (i = 0; i < n; ++insn, ++i) { #ifdef BDEBUG extern int bids[]; fprintf(stdout, bids[i] > 0 ? "[%02d]" : " -- ", bids[i] - 1); #endif fprintf (stdout, "%s", bpf_image(insn, i)); fprintf (stdout, "\n"); } #ifdef ARGUSDEBUG ArgusDebug (3, "Argusbpf_dump (0x%x, %d) returning", p, option); #endif } #include #include #include #define ARGUSSNOOPTAG "snoop" pcap_t * ArgusOpenInputPacketFile(char *errbuf) { char readbuf[256]; pcap_t *pd = NULL, *retn = NULL; int ch, rlen; bzero (errbuf, 64); if ((pd = pcap_open_offline(Argusrfile, errbuf)) != NULL) { ArgusInterface[0].ArgusInterfaceType = ARGUSLIBPPKTFILE; ArgusInputPacketFileType = ARGUSLIBPPKTFILE; ArgusInterface[0].ArgusDevice = Argusrfile; ArgusReadingOffLine++; retn = pd; } else { if (strcmp(Argusrfile, "-")) { if ((ArgusPacketInput = fopen(Argusrfile, "r")) == NULL) { snprintf (errbuf, PCAP_ERRBUF_SIZE - 1, "%s: %s\n", Argusrfile, strerror(errno)); } } else ArgusPacketInput = stdin; if (ArgusPacketInput) { if (getArgusMoatTshFile()) { ArgusInputPacketFileType = ARGUSMOATTSHPKTFILE; if (ArgusPacketInput == stdin) { ArgusPcap.fd = 0; ArgusPcap.snapshot = 1500; ArgusPcap.linktype = DLT_EN10MB; ArgusInterface[0].ArgusInterfaceType = ARGUSMOATTSHPKTFILE; ArgusInterface[0].ArgusDevice = Argusrfile; retn = (pcap_t *) &ArgusPcap; ArgusReadingOffLine++; } else if ((ArgusPcap.fd = open (Argusrfile, O_RDONLY, NULL)) >= 0) { ArgusPcap.snapshot = 1500; ArgusPcap.linktype = DLT_EN10MB; ArgusInterface[0].ArgusInterfaceType = ARGUSMOATTSHPKTFILE; ArgusInterface[0].ArgusDevice = Argusrfile; retn = (pcap_t *) &ArgusPcap; ArgusReadingOffLine++; } else ArgusLog(LOG_ERR, "ArgusOpenInputPacketFile(%s) error. %s", Argusrfile, strerror(errno)); } else if ((ch = fgetc(ArgusPacketInput)) != EOF) { ungetc(ch, ArgusPacketInput); if ((rlen = fread ((char *)readbuf, 1, sizeof(ARGUSSNOOPTAG), ArgusPacketInput)) == sizeof(ARGUSSNOOPTAG)) { if ((strncmp((char *)readbuf, ARGUSSNOOPTAG, sizeof(ARGUSSNOOPTAG)) == 0)) { fclose(ArgusPacketInput); if ((ArgusPcap.fd = open (Argusrfile, O_RDONLY, NULL)) >= 0) { lseek(ArgusPcap.fd, 16, SEEK_SET); ArgusPcap.snapshot = 1500; ArgusPcap.linktype = DLT_EN10MB; ArgusInterface[0].ArgusInterfaceType = ARGUSSNOOPKTFILE; ArgusInterface[0].ArgusDevice = Argusrfile; ArgusInputPacketFileType = ARGUSSNOOPKTFILE; retn = (pcap_t *) &ArgusPcap; ArgusReadingOffLine++; } } else { snprintf (errbuf, PCAP_ERRBUF_SIZE - 1, "Unknown packet file format"); } } else { snprintf (errbuf, PCAP_ERRBUF_SIZE - 1, "Error reading %s. Read %d bytes", Argusrfile, rlen); } } else { snprintf (errbuf, PCAP_ERRBUF_SIZE - 1, "Error reading %s. Stream Empty", Argusrfile); } } } #ifdef ARGUSDEBUG ArgusDebug (3, "ArgusOpenInputPacketFile(0x%x) returning 0x%x", errbuf, retn); #endif return (retn); } char * ArgusCopyArgv (char **argv) { char **p; int len = 0; char *buf = NULL, *src, *dst; p = argv; if (*p == 0) return 0; while (*p) len += (int) strlen (*p++) + 1; if ((buf = (char *) ArgusCalloc (1, len)) != NULL) { p = argv; dst = buf; while ((src = *p++) != NULL) { if (*src != '-') { while ((*dst++ = *src++) != '\0') ; dst[-1] = ' '; } } dst[-1] = '\0'; } #ifdef ARGUSDEBUG ArgusDebug (6, "ArgusCopyArgv(0x%x) returning 0x%x", argv, buf); #endif return buf; } #include #include char * ArgusReadInfile (char *fname) { int fd = 0; char *p = NULL; struct stat buf; char outbuf[256]; if ((fd = open(fname, O_RDONLY)) >= 0) { if (fstat(fd, &buf) < 0) { snprintf (outbuf, 255, "%s: fstat('%s') failed.", ArgusProgramName, fname); perror (outbuf); close(fd); } if ((p = (char *) ArgusCalloc (1, (u_int) buf.st_size)) != 0) { if (read (fd, p, (unsigned int)buf.st_size) != buf.st_size) { snprintf (outbuf, 255, "%s: read('%s') failed.", ArgusProgramName, fname); perror (outbuf); p = NULL; close(fd); } } close(fd); } else { snprintf (outbuf, 255, "%s: open('%s') failed.", ArgusProgramName, fname); perror (outbuf); } #ifdef ARGUSDEBUG ArgusDebug (3, "ArgusReadInfile(%s) returning 0x%x", fname, p); #endif return (p); }