www.pudn.com > ids_snort.zip > log.c
/* $Id: log.c,v 1.31 2001/01/26 16:40:44 roesch Exp $ */ /* ** Copyright (C) 1998,1999,2000,2001 Martin Roesch** ** 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 of the License, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "log.h" extern OptTreeNode *otn_tmp; /* global ptr to current rule data */ char *data_dump_buffer; /* printout buffer for PrintNetData */ int dump_ready; /* flag to indicate status of printout buffer */ int dump_size; /* size of printout buffer */ static unsigned char ezero[6]; /* crap for ARP */ /* * Function: OpenLogFile() * * Purpose: Create the log directory and file to put the packet log into. * This function sucks, I've got to find a better way to do this * this stuff. * * Arguments: None. * * Returns: 0 on success, exits on error */ int OpenLogFile(int mode, Packet * p) { char log_path[STD_BUF+1]; /* path to log file */ char log_file[STD_BUF+1]; /* name of log file */ char proto[5]; /* logged packet protocol */ /* zero out our buffers */ bzero((char *) log_path, STD_BUF+1); bzero((char *) log_file, STD_BUF+1); bzero((char *) proto, 5); if(mode == GENERIC_LOG) { snprintf(log_file, STD_BUF, "%s%s/log", chrootdir == NULL ? "" : chrootdir, pv.log_dir); if((log_ptr = fopen(log_file, "a")) == NULL) { FatalError("ERROR: OpenLogFile() => fopen(%s) log file: %s\n", log_file, strerror(errno)); } return 0; } if(mode == DUMP) { snprintf(log_file, STD_BUF, "%s%s/PACKET_FRAG", chrootdir == NULL ? "" : chrootdir, pv.log_dir); if((log_ptr = fopen(log_file, "a")) == NULL) { FatalError("ERROR: OpenLogFile() => fopen(%s) log file: %s\n", log_file, strerror(errno)); } return 0; } if(mode == BOGUS) { snprintf(log_file, STD_BUF, "%s%s/PACKET_BOGUS", chrootdir == NULL ? "" : chrootdir, pv.log_dir); if((log_ptr = fopen(log_file, "a")) == NULL) { FatalError("ERROR: OpenLogFile() => fopen(%s) log file: %s\n", log_file, strerror(errno)); } return 0; } if(mode == NON_IP) { snprintf(log_file, STD_BUF, "%s%s/PACKET_NONIP", chrootdir == NULL ? "" : chrootdir, pv.log_dir); if((log_ptr = fopen(log_file, "a")) == NULL) { FatalError("ERROR: OpenLogFile() => fopen(%s) log file: %s\n", log_file, strerror(errno)); } return 0; } if(mode == ARP) { snprintf(log_file, STD_BUF, "%s%s/ARP", chrootdir == NULL ? "" : chrootdir, pv.log_dir); if((log_ptr = fopen(log_file, "a")) == NULL) { FatalError("ERROR: OpenLogFile() => fopen(%s) log file: %s\n", log_file, strerror(errno)); } return 0; } if(otn_tmp != NULL) { if(otn_tmp->logto != NULL) { snprintf(log_file, STD_BUF, "%s%s/%s", chrootdir == NULL ? "" : chrootdir, pv.log_dir, otn_tmp->logto); if((log_ptr = fopen(log_file, "a")) == NULL) { FatalError("ERROR: OpenLogFile() => fopen(%s) log file: %s\n", log_file, strerror(errno)); } return 0; } } /* figure out which way this packet is headed in relation to the homenet */ if((p->iph->ip_dst.s_addr & pv.netmask) == pv.homenet) { if((p->iph->ip_src.s_addr & pv.netmask) != pv.homenet) { snprintf(log_path, STD_BUF, "%s%s/%s", chrootdir == NULL ? "" : chrootdir, pv.log_dir, inet_ntoa(p->iph->ip_src)); } else { if(p->sp >= p->dp) { snprintf(log_path, STD_BUF, "%s%s/%s", chrootdir == NULL ? "" : chrootdir, pv.log_dir, inet_ntoa(p->iph->ip_src)); } else { snprintf(log_path, STD_BUF, "%s%s/%s", chrootdir == NULL ? "" : chrootdir, pv.log_dir, inet_ntoa(p->iph->ip_dst)); } } } else { if((p->iph->ip_src.s_addr & pv.netmask) == pv.homenet) { snprintf(log_path, STD_BUF, "%s%s/%s", chrootdir == NULL ? "" : chrootdir, pv.log_dir, inet_ntoa(p->iph->ip_dst)); } else { if(p->sp >= p->dp) { snprintf(log_path, STD_BUF, "%s%s/%s", chrootdir == NULL ? "" : chrootdir, pv.log_dir, inet_ntoa(p->iph->ip_src)); } else { snprintf(log_path, STD_BUF, "%s%s/%s", chrootdir == NULL ? "" : chrootdir, pv.log_dir, inet_ntoa(p->iph->ip_dst)); } } } #ifdef DEBUG ErrorMessage("Creating directory: %s\n", log_path); #endif /* build the log directory */ if(mkdir(log_path, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)) { if(errno != EEXIST) { FatalError("ERROR: OpenLogFile() => mkdir(%s) log directory: %s\n", log_path, strerror(errno)); } } #ifdef DEBUG printf("Directory Created!\n"); #endif /* build the log filename */ if(p->iph->ip_proto == IPPROTO_TCP || p->iph->ip_proto == IPPROTO_UDP) { if(p->frag_flag) { #ifdef WIN32 snprintf(log_file, STD_BUF, "%s/IP_FRAG.ids", log_path); #else snprintf(log_file, STD_BUF, "%s/IP_FRAG", log_path); #endif } else { if(p->sp >= p->dp) { #ifdef WIN32 snprintf(log_file, STD_BUF, "%s/%s_%d-%d.ids", log_path, #else snprintf(log_file, STD_BUF, "%s/%s:%d-%d", log_path, #endif protocol_names[p->iph->ip_proto], p->sp, p->dp); } else { #ifdef WIN32 snprintf(log_file, STD_BUF, "%s/%s_%d-%d.ids", log_path, #else snprintf(log_file, STD_BUF, "%s/%s:%d-%d", log_path, #endif protocol_names[p->iph->ip_proto], p->dp, p->sp); } } } else { if(p->frag_flag) { #ifdef WIN32 snprintf(log_file, STD_BUF, "%s/IP_FRAG.ids", log_path); #else snprintf(log_file, STD_BUF, "%s/IP_FRAG", log_path); #endif } else { if(p->iph->ip_proto == IPPROTO_ICMP) { #ifdef WIN32 snprintf(log_file, STD_BUF, "%s/%s_%s.ids", log_path, "ICMP", IcmpFileName(p)); #else snprintf(log_file, STD_BUF, "%s/%s_%s", log_path, "ICMP", IcmpFileName(p)); #endif } else { #ifdef WIN32 snprintf(log_file, STD_BUF, "%s/PROTO%d.ids", log_path, p->iph->ip_proto); #else snprintf(log_file, STD_BUF, "%s/PROTO%d", log_path, p->iph->ip_proto); #endif } } } #ifdef DEBUG printf("Opening file: %s\n", log_file); #endif /* finally open the log file */ if((log_ptr = fopen(log_file, "a")) == NULL) { FatalError("ERROR: OpenLogFile() => fopen(%s) log file: %s\n", log_file, strerror(errno)); } #ifdef DEBUG printf("File opened...\n"); #endif return 0; } /* * Function: PrintNetData(FILE *, u_char *,int) * * Purpose: Do a side by side dump of a buffer, hex dump of buffer bytes on * the left, decoded ASCII on the right. * * Arguments: fp => ptr to stream to print to * start => pointer to buffer data * len => length of data buffer * * Returns: void function */ void PrintNetData(FILE * fp, u_char * start, const int len) { char *end; /* ptr to buffer end */ int i; /* counter */ int j; /* counter */ int dbuf_size; /* data buffer size */ int done; /* flag */ char *data; /* index pointer */ char *frame_ptr; /* we use 66 byte frames for a printed line */ char *d_ptr; /* data pointer into the frame */ char *c_ptr; /* char pointer into the frame */ char conv[] = "0123456789ABCDEF"; /* xlation lookup table */ /* initialization */ done = 0; if(start == NULL) { printf("Got NULL ptr in PrintNetData()\n"); return; } /* zero, print a and get out */ if(!len) { fputc('\n', fp); return; } /* * if we've already prepared this particular data buffer, just print it * out again to save time */ if(dump_ready) { fwrite(data_dump_buffer, dump_size, 1, fp); fflush(fp); return; } end = start + (len - 1); /* set the end of buffer ptr */ if(len > pv.mtus[0]) { if(pv.verbose_flag) { printf("Got bogus buffer length (%d) for PrintNetData, defaulting to 16 bytes!\n", len); } if(pv.verbose_bytedump_flag == 1) { dbuf_size = (FRAME_SIZE + 8) + (FRAME_SIZE + 8) + 1; } else { dbuf_size = FRAME_SIZE + FRAME_SIZE + 1; } /* dbuf_size = 66 + 67; */ end = start + 15; } else { if(pv.verbose_bytedump_flag == 1) { /* figure out how big the printout data buffer has to be */ dbuf_size = ((len / 16) * (FRAME_SIZE + 8)) + (FRAME_SIZE + 8) + 1; } else { /* figure out how big the printout data buffer has to be */ dbuf_size = ((len / 16) * FRAME_SIZE) + FRAME_SIZE + 1; } /* dbuf_size = ((len / 16) * 66) + 67; */ } /* generate the buffer */ data_dump_buffer = (char *) malloc(dbuf_size); /* make sure it got allocated properly */ if(data_dump_buffer == NULL) { ErrorMessage("Failed allocating %X bytes! (Length: %X)\n", dbuf_size, len); perror("PrintNetData()"); CleanExit(SIGQUIT); } /* clean it out */ memset(data_dump_buffer, 0x20, dbuf_size); /* set the byte buffer pointer to step thru the data buffer */ data = start; /* set the frame pointer to the start of the printout buffer */ frame_ptr = data_dump_buffer; /* initialize counters and frame index pointers */ i = 0; j = 0; /* loop thru the whole buffer */ while(!done) { if(pv.verbose_bytedump_flag == 1) { d_ptr = frame_ptr + 8; c_ptr = (frame_ptr + 8 + C_OFFSET); sprintf(frame_ptr, "0x%04X: ", j); j += 16; } else { d_ptr = frame_ptr; c_ptr = (frame_ptr + C_OFFSET); } /* process 16 bytes per frame */ for(i = 0; i < 16; i++) { /* * look up the ASCII value of the first nybble of the current * data buffer */ *d_ptr = conv[((*data & 0xFF) >> 4)]; d_ptr++; /* look up the second nybble */ *d_ptr = conv[((*data & 0xFF) & 0x0F)]; d_ptr++; /* put a space in between */ *d_ptr = 0x20; d_ptr++; /* print out the char equivalent */ if(*data > 0x1F && *data < 0x7F) *c_ptr = (*data & 0xFF); else *c_ptr = 0x2E; c_ptr++; /* increment the pointer or finish up */ if(data < end) data++; else { /* finish up the buffer printout and set the "ready" flags */ done = 1; dump_ready = 1; *c_ptr = '\n'; c_ptr++; *c_ptr = '\n'; c_ptr++; *c_ptr = 0; dump_size = (int) (c_ptr - data_dump_buffer); fwrite(data_dump_buffer, dump_size, 1, fp); return; } } *c_ptr = '\n'; if(pv.verbose_bytedump_flag == 1) { frame_ptr += (FRAME_SIZE + 8); } else { frame_ptr += FRAME_SIZE; } } } /* * Function: PrintCharData(FILE *, char *,int) * * Purpose: Dump the ASCII data from a packet * the left, decoded ASCII on the right. * * Arguments: fp => ptr to stream to print to * data => pointer to buffer data * data_len => length of data buffer * * Returns: void function */ void PrintCharData(FILE * fp, char *data, int data_len) { int bytes_processed; /* count of bytes in the data buffer * processed so far */ int linecount = 0; /* number of lines in this dump */ char *index; /* index pointer into the data buffer */ char *ddb_ptr; /* index pointer into the data_dump_buffer */ /* if there's no data, return */ if(data == NULL) { return; } /* if we've already setup the buffer, just reprint it */ if(dump_ready) { fwrite(data_dump_buffer, dump_size, 1, fp); fflush(fp); return; } /* setup the pointers and counters */ bytes_processed = data_len; index = data; /* allocate a buffer to print the data to */ data_dump_buffer = (char *) calloc(data_len + (data_len >> 6) + 2, sizeof(char)); ddb_ptr = data_dump_buffer; /* loop thru the bytes in the data buffer */ while(bytes_processed) { if(*index > 0x1F && *index < 0x7F) { *ddb_ptr = *index; } else { *ddb_ptr = '.'; } if(++linecount == 64) { ddb_ptr++; *ddb_ptr = '\n'; linecount = 0; } ddb_ptr++; index++; bytes_processed--; } /* slam a \n on the back */ ddb_ptr++; *ddb_ptr = '\n'; ddb_ptr++; /* setup the globals */ dump_ready = 1; dump_size = (int) (ddb_ptr - data_dump_buffer); fwrite(data_dump_buffer, dump_size, 1, fp); } /* * Function: PrintIPPkt(FILE *, int, Packet *) * * Purpose: Dump the packet to the stream pointer * * Arguments: fp => pointer to print data to * type => packet protocol * p => pointer to decoded packet struct * * Returns: void function */ void PrintIPPkt(FILE * fp, int type, Packet * p) { char timestamp[23]; #ifdef DEBUG printf("PrintIPPkt type = %d\n", type); #endif bzero((char *) timestamp, 23); ts_print((struct timeval *) & p->pkth->ts, timestamp); /* dump the timestamp */ fwrite(timestamp, 22, 1, fp); /* dump the ethernet header if we're doing that sort of thing */ if(pv.show2hdr_flag) { Print2ndHeader(fp, p); } /* etc */ PrintIPHeader(fp, p); /* if this isn't a fragment, print the other header info */ if(!p->frag_flag) { switch(p->iph->ip_proto) { case IPPROTO_TCP: if(p->tcph != NULL) { PrintTCPHeader(fp, p); } else { PrintNetData(fp, (char *) (p->iph + (p->iph->ip_hlen << 2)), (p->iph->ip_len - (p->iph->ip_hlen << 2))); } break; case IPPROTO_UDP: if(p->udph != NULL) { PrintUDPHeader(fp, p); } else { PrintNetData(fp, (char *) (p->iph + (p->iph->ip_hlen << 2)), (p->iph->ip_len - (p->iph->ip_hlen << 2))); } break; case IPPROTO_ICMP: if(p->icmph != NULL) { PrintICMPHeader(fp, p); } else { PrintNetData(fp, (char *) (p->iph + (p->iph->ip_hlen << 2)), (p->iph->ip_len - (p->iph->ip_hlen << 2))); } break; default: break; } } /* dump the application layer data */ if(pv.data_flag && !pv.verbose_bytedump_flag) { if(pv.char_data_flag) PrintCharData(fp, p->data, p->dsize); else PrintNetData(fp, p->data, p->dsize); } else if(pv.verbose_bytedump_flag) { PrintNetData(fp, p->pkt, p->pkth->caplen); } fprintf(fp, "=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+\n\n"); } /* * Function: OpenAlertSock * * Purpose: Connect to UNIX socket for alert logging.. * * Arguments: none.. * * Returns: void function */ void OpenAlertSock() { char *srv = UNSOCK_FILE; if(access(srv, W_OK)) { ErrorMessage("WARNING: %s file doesn't exist or isn't writable!\n", srv); } bzero((char *) &alertaddr, sizeof(alertaddr)); bcopy((const void *) srv, (void *) alertaddr.sun_path, strlen(srv)); /* we trust what we * define */ alertaddr.sun_family = AF_UNIX; if((alertsd = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0) { FatalError("socket() call failed: %s", strerror(errno)); } } /**************************************************************************** * * Function: OpenAlertFile(char *) * * Purpose: Set up the file pointer/file for alerting * * Arguments: filearg => the filename to open * * Returns: file handle * ***************************************************************************/ FILE *OpenAlertFile(char *filearg) { char filename[STD_BUF + 1]; FILE *file; if(filearg == NULL) { if(!pv.daemon_flag) #ifdef WIN32 snprintf(filename, STD_BUF, "%s%s/alert.ids", chrootdir == NULL ? #else snprintf(filename, STD_BUF, "%s%s/alert", chrootdir == NULL ? #endif "" : chrootdir, pv.log_dir); else snprintf(filename, STD_BUF, "%s%s/%s", chrootdir == NULL ? "" : chrootdir, pv.log_dir, DEFAULT_DAEMON_ALERT_FILE); } else { snprintf(filename, STD_BUF, "%s%s", chrootdir == NULL ? "" : chrootdir, filearg); } #ifdef DEBUG printf("Opening alert file: %s\n", filename); #endif if((file = fopen(filename, "a")) == NULL) { FatalError("ERROR in OpenAlertFile() => fopen() alert file %s: %s\n", filename, strerror(errno)); } #ifdef WIN32 /* Do not buffer in WIN32 */ setvbuf(file, (char *) NULL, _IONBF, (size_t) 0); #else setvbuf(file, (char *) NULL, _IOLBF, (size_t) 0); #endif return file; } /* * * Function: ClearDumpBuf() * * Purpose: Clear out the buffer that PrintNetData() generates * * Arguments: None. * * Returns: void function * */ void ClearDumpBuf() { if(data_dump_buffer != NULL && dump_ready) free(data_dump_buffer); else return; data_dump_buffer = NULL; dump_ready = 0; } /* * Function: FullAlert(Packet *, char *, void *) * * Purpose: Stub function for compatability * * Arguments: p => ptr to packet data * msg => message to send to alert facility * arg => arguments to the alert facility * * Returns: void function */ void FullAlert(Packet * p, char *msg, void *arg) { AlertFull(p, msg, alert); return; } /* * * Function: AlertFull(char *) * * Purpose: Write a full and informative alert message * * Arguments: p => packet. (could be NULL) * msg => the message to send * file => file pointer to print data to * * Returns: void function * */ void AlertFull(Packet * p, char *msg, FILE * file) { char timestamp[23]; if(msg != NULL) { if(pv.alert_interface_flag) { fwrite("[**] ", 5, 1, file); #ifdef WIN32 fprintf(file, " <%s> ", print_interface(pv.interfaces[0])); #else fprintf(file, " <%s> ", pv.interfaces[0]); #endif fwrite(msg, strlen(msg), 1, file); fwrite(" [**]\n", 6, 1, file); } else { fwrite("[**] ", 5, 1, file); fwrite(msg, strlen(msg), 1, file); fwrite(" [**]\n", 6, 1, file); } } else { fwrite("[**] Snort Alert! [**]\n", 22, 1, file); } #ifdef DEBUG printf("Logging Alert data!\n"); #endif bzero((char *) timestamp, 23); ts_print(p == NULL ? NULL : (struct timeval *) & p->pkth->ts, timestamp); /* dump the timestamp */ fwrite(timestamp, 22, 1, file); if(p) { /* print the packet header to the alert file */ if(pv.show2hdr_flag) { Print2ndHeader(file, p); } PrintIPHeader(file, p); /* if this isn't a fragment, print the other header info */ if(!p->frag_flag) { switch(p->iph->ip_proto) { case IPPROTO_TCP: PrintTCPHeader(file, p); break; case IPPROTO_UDP: PrintUDPHeader(file, p); break; case IPPROTO_ICMP: PrintICMPHeader(file, p); break; default: break; } } } /* End of if(p) */ fputc('\n', file); return; } void FastAlert(Packet * p, char *msg, void *arg) { AlertFast(p, msg, alert); return; } /**************************************************************************** * * Function: FastAlert(Packet *, char *) * * Purpose: Write a minimal alert message to the alert file * * Arguments: p => pointer to the packet data struct (could be NULL) * msg => the message to print in the alert * * Returns: void function * ***************************************************************************/ void AlertFast(Packet * p, char *msg, FILE * file) { char timestamp[23]; bzero((char *) timestamp, 23); ts_print(p == NULL ? NULL : (struct timeval *) & p->pkth->ts, timestamp); /* dump the timestamp */ fwrite(timestamp, 22, 1, file); if(msg != NULL) { if(pv.alert_interface_flag) { fwrite(" [**] ", 6, 1, file); #ifdef WIN32 fprintf(file, " <%s> ", print_interface(pv.interfaces[0])); #else fprintf(file, " <%s> ", pv.interfaces[0]); #endif fwrite(msg, strlen(msg), 1, file); fwrite(" [**] ", 6, 1, file); } else { fwrite(" [**] ", 6, 1, file); fwrite(msg, strlen(msg), 1, file); fwrite(" [**] ", 6, 1, file); } } /* print the packet header to the alert file */ if(p) { if(p->frag_flag) { /* just print the straight IP header */ fputs(inet_ntoa(p->iph->ip_src), file); fwrite(" -> ", 4, 1, file); fputs(inet_ntoa(p->iph->ip_dst), file); } else { switch(p->iph->ip_proto) { case IPPROTO_UDP: case IPPROTO_TCP: /* print the header complete with port information */ fputs(inet_ntoa(p->iph->ip_src), file); fprintf(file, ":%d -> ", p->sp); fputs(inet_ntoa(p->iph->ip_dst), file); fprintf(file, ":%d", p->dp); break; case IPPROTO_ICMP: default: /* just print the straight IP header */ fputs(inet_ntoa(p->iph->ip_src), file); fwrite(" -> ", 4, 1, file); fputs(inet_ntoa(p->iph->ip_dst), file); } } } /* end of if (p) */ fputc('\n', file); return; } /**************************************************************************** * * Function: SyslogAlert(Packet *, char *) * * Purpose: Send the current alert to syslog * * Arguments: p => pointer to the packet data struct * msg => the message to print in the alert * * Returns: void function * ***************************************************************************/ void SyslogAlert(Packet * p, char *msg, void *arg) { char sip[16]; char dip[16]; /* * have to do this since inet_ntoa is fucked up and writes to a static * memory location */ if(p) { strncpy(sip, inet_ntoa(p->iph->ip_src), 16); strncpy(dip, inet_ntoa(p->iph->ip_dst), 16); if((p->iph->ip_proto != IPPROTO_TCP && p->iph->ip_proto != IPPROTO_UDP) || p->frag_flag) { if(msg != NULL) { if(pv.alert_interface_flag) { /* ICMP packets don't get port info... */ syslog(LOG_AUTHPRIV | LOG_ALERT, "<%s> %s: %s -> %s", #ifdef WIN32 print_interface(pv.interfaces[0]), msg, sip, dip); #else pv.interfaces[0], msg, sip, dip); #endif } else { /* ICMP packets don't get port info... */ syslog(LOG_AUTHPRIV | LOG_ALERT, "%s: %s -> %s", msg, sip, dip); } } else { /* ICMP packets don't get port info... */ syslog(LOG_AUTHPRIV | LOG_ALERT, "ALERT: %s -> %s", sip, dip); } } else { if(msg != NULL) { if(pv.alert_interface_flag) { syslog(LOG_AUTHPRIV | LOG_ALERT, "<%s> %s: %s:%i -> %s:%i", #ifdef WIN32 print_interface(pv.interfaces[0]), msg, sip, p->sp, dip, p->dp); #else pv.interfaces[0], msg, sip, p->sp, dip, p->dp); #endif } else { syslog(LOG_AUTHPRIV | LOG_ALERT, "%s: %s:%i -> %s:%i", msg, sip, p->sp, dip, p->dp); } } else { syslog(LOG_AUTHPRIV | LOG_ALERT, "ALERT: %s:%i -> %s:%i", sip, p->sp, dip, p->dp); } } } else /* p == NULL */ { syslog(LOG_AUTHPRIV | LOG_ALERT, "%s", msg == NULL ? "ALERT!" : msg); } return; } /**************************************************************************** * * Function: SmbAlert(Packet *, char *) * * Purpose: Send the current alert to a waiting WinPopup client * * Arguments: p => pointer to the packet data struct * msg => the message to print in the alert * * Returns: void function * ***************************************************************************/ #ifdef ENABLE_SMB_ALERTS void SmbAlert(Packet * p, char *msg, void *arg) { char command_line[2048]; FILE *output; FILE *workstations; char *tempmsg; char workfile[STD_BUF]; char tempwork[STD_BUF]; char timestamp[23]; int msg_str_size; bzero((char *) timestamp, 23); ts_print(p == NULL ? NULL : (struct timeval *) & p->pkth->ts, timestamp); #ifdef DEBUG printf("Generating SMB alert!\n"); #endif /* set the workstation name filename */ sprintf(workfile, "%s", pv.smbmsg_dir); /* message size + IP addrs + ports + pad space */ msg_str_size = strlen(msg) + 32 + 10 + 150; if((tempmsg = (char *) calloc(msg_str_size, sizeof(char))) == NULL) { FatalError("[!] ERROR: SmbAlert() unable to allocate space for tempmsg: %s\n", strerror(errno)); } /* open the message file and the workstation names file */ if((workstations = fopen(workfile, "r")) != NULL) { /* clear the read buffers */ bzero((char *) workfile, STD_BUF); if(p != NULL) { if(p->frag_flag || (p->iph->ip_proto != IPPROTO_TCP && p->iph->ip_proto != IPPROTO_UDP)) { /* write the alert message into the buffer */ sprintf(tempmsg, "SNORT ALERT - Possible Network Attack or Probe:\n [**] %s [**]\n%s %s->%s", msg, timestamp, inet_ntoa(p->iph->ip_src), inet_ntoa(p->iph->ip_dst)); } else { /* write the alert message into the buffer */ sprintf(tempmsg, "SNORT ALERT - Possible Network Attack or Probe:\n [**] %s [**]\n%s %s:%d->%s:%d", msg, timestamp, inet_ntoa(p->iph->ip_src), p->sp, inet_ntoa(p->iph->ip_dst), p->dp); } } else { /* * write the alert message into the buffer - this part is for * alerts with NULL packets (like portscans) */ sprintf(tempmsg, "SNORT ALERT - Possible Network Attack or Probe:\n [**] %s [**]\n", msg); } bzero((char *) tempwork, STD_BUF); bzero((char *) command_line, 2048); /* read in the name of each workstation to send the message to */ while((fgets(tempwork, STD_BUF - 1, workstations)) != NULL) { /* if the line isn't blank */ if(tempwork[0] != 0x0A) { /* chop the */ strip(tempwork); if(strlen(tempmsg) + strlen(tempwork) + 50 < 2048) { /* build the command line */ sprintf(command_line, "echo \"%s\" | smbclient -U Snort -M %s", tempmsg, tempwork); /* run the command */ output = popen(command_line, "r"); pclose(output); } else { ErrorMessage("[!] WARNING: Unable to send alert to %s, command buffer size exceeded!\n", tempwork); } #ifdef DEBUG printf("Sending WinPopup alert to: %s\n", tempwork); printf("Command Line: %s\n", command_line); #endif bzero((char *) tempwork, STD_BUF); bzero((char *) command_line, 2048); } } fclose(workstations); } free(tempmsg); } #endif /**************************************************************************** * * Function: NoAlert(Packet *, char *) * * Purpose: Don't alert at all * * Arguments: p => pointer to the packet data struct * msg => the message to not print in the alert * * Returns: void function * ***************************************************************************/ void NoAlert(Packet * p, char *msg, void *arg) { return; } /**************************************************************************** * * Function: LogPkt(Packet *) * * Purpose: Log packets that match one of the Snort rules, plus the rules * message * * Arguments: p => pointer to the packet data structure * * Returns: void function * ***************************************************************************/ void LogPkt(Packet * p, char *msg, void *arg) { /* * some plugins may pass NULL as 'p' structure here (f.e. if they only * want to log message */ if(p) OpenLogFile(0, p); else OpenLogFile(GENERIC_LOG, p); if(msg != NULL) { fwrite("[**] ", 5, 1, log_ptr); fwrite(msg, strlen(msg), 1, log_ptr); fwrite(" [**]\n", 6, 1, log_ptr); } if(p) PrintIPPkt(log_ptr, p->iph->ip_proto, p); fclose(log_ptr); } /**************************************************************************** * * Function: LogArpPkt(Packet *) * * Purpose: Log ARP packets * * Arguments: p => pointer to the packet data structure * * Returns: void function * ***************************************************************************/ void LogArpPkt(Packet * p) { if(p) { if(pv.logbin_flag) { /* LogBin(p); */ } else if(!pv.nolog_flag) { OpenLogFile(ARP, p); PrintArpHeader(log_ptr, p); fclose(log_ptr); } } else { /* let's just make sure we don't coredump if we have some logic error in one * of plugins/preprocessors... */ ErrorMessage("WARNING: Null Packet pointer in LogArpPkt. Please report.\n"); } } /**************************************************************************** * * Function: NoLog(Packet *) * * Purpose: Don't log anything * * Arguments: p => packet to not log * * Returns: void function * ***************************************************************************/ void NoLog(Packet * p, char *msg, void *arg) { return; } /**************************************************************************** * * Function: Print2ndHeader(FILE *, Packet p) * * Purpose: Print2ndHeader -- prints second layber header info. * * Arguments: fp => file stream to print to * * Returns: void function * ***************************************************************************/ void Print2ndHeader(FILE * fp, Packet * p) { if(p && p->eh) PrintEthHeader(fp, p); if(p && p->trh) PrintTrHeader(fp, p); } /**************************************************************************** * * Function: PrintTrHeader(FILE *, Packet p) & * Purpose: Print the packet TokenRing header to the specified stream * * Arguments: fp => file stream to print to * * Returns: void function ***************************************************************************/ void PrintTrHeader(FILE * fp, Packet * p) { fprintf(fp, "%X:%X:%X:%X:%X:%X -> ", p->trh->saddr[0], p->trh->saddr[1], p->trh->saddr[2], p->trh->saddr[3], p->trh->saddr[4], p->trh->saddr[5]); fprintf(fp, "%X:%X:%X:%X:%X:%X\n", p->trh->daddr[0], p->trh->daddr[1], p->trh->daddr[2], p->trh->daddr[3], p->trh->daddr[4], p->trh->daddr[5]); fprintf(fp, "access control:0x%X frame control:0x%X\n", p->trh->ac, p->trh->fc); if(!p->trhllc) return; fprintf(fp, "DSAP: 0x%X SSAP 0x%X protoID: %X%X%X Ethertype: %X\n", p->trhllc->dsap, p->trhllc->ssap, p->trhllc->protid[0], p->trhllc->protid[1], p->trhllc->protid[2], p->trhllc->ethertype); if(p->trhmr) { fprintf(fp, "RIF structure is present:\n"); fprintf(fp, "bcast: 0x%X length: 0x%X direction: 0x%X largest" "fr. size: 0x%X res: 0x%X\n", p->trhmr->bcast, p->trhmr->len, p->trhmr->dir, p->trhmr->lf, p->trhmr->res); fprintf(fp, "rseg -> %X:%X:%X:%X:%X:%X:%X:%X\n", p->trhmr->rseg[0], p->trhmr->rseg[1], p->trhmr->rseg[2], p->trhmr->rseg[3], p->trhmr->rseg[4], p->trhmr->rseg[5], p->trhmr->rseg[6], p->trhmr->rseg[7]); } } /**************************************************************************** * * Function: PrintEthHeader(FILE *) * * Purpose: Print the packet Ethernet header to the specified stream * * Arguments: fp => file stream to print to * * Returns: void function * ***************************************************************************/ void PrintEthHeader(FILE * fp, Packet * p) { /* src addr */ fprintf(fp, "%X:%X:%X:%X:%X:%X -> ", p->eh->ether_src[0], p->eh->ether_src[1], p->eh->ether_src[2], p->eh->ether_src[3], p->eh->ether_src[4], p->eh->ether_src[5]); /* dest addr */ fprintf(fp, "%X:%X:%X:%X:%X:%X ", p->eh->ether_dst[0], p->eh->ether_dst[1], p->eh->ether_dst[2], p->eh->ether_dst[3], p->eh->ether_dst[4], p->eh->ether_dst[5]); /* protocol and pkt size */ fprintf(fp, "type:0x%X len:0x%X\n", ntohs(p->eh->ether_type), p->pkth->len); } void PrintArpHeader(FILE * fp, Packet * p) { struct in_addr ip_addr; char timestamp[23]; bzero((char *) timestamp, 23); ts_print((struct timeval *) & p->pkth->ts, timestamp); /* dump the timestamp */ fwrite(timestamp, 22, 1, fp); if(ntohs(p->ah->ea_hdr.ar_pro) != ETHERNET_TYPE_IP) { fprintf(fp, "ARP #%d for protocol #%.4X (%d) hardware #%d (%d)\n", ntohs(p->ah->ea_hdr.ar_op), ntohs(p->ah->ea_hdr.ar_pro), p->ah->ea_hdr.ar_pln, ntohs(p->ah->ea_hdr.ar_hrd), p->ah->ea_hdr.ar_hln); return; } switch(ntohs(p->ah->ea_hdr.ar_op)) { case ARPOP_REQUEST: bcopy((void *)p->ah->arp_tpa, (void *) &ip_addr, sizeof(ip_addr)); fprintf(fp, "ARP who-has %s", inet_ntoa(ip_addr)); if(memcmp((char *) ezero, (char *) p->ah->arp_tha, 6) != 0) { fprintf(fp, " (%X:%X:%X:%X:%X:%X)", p->ah->arp_tha[0], p->ah->arp_tha[1], p->ah->arp_tha[2], p->ah->arp_tha[3], p->ah->arp_tha[4], p->ah->arp_tha[5]); } bcopy((void *)p->ah->arp_spa, (void *) &ip_addr, sizeof(ip_addr)); fprintf(fp, " tell %s", inet_ntoa(ip_addr)); if(memcmp((char *) p->eh->ether_src, (char *) p->ah->arp_sha, 6) != 0) { fprintf(fp, " (%X:%X:%X:%X:%X:%X)", p->ah->arp_sha[0], p->ah->arp_sha[1], p->ah->arp_sha[2], p->ah->arp_sha[3], p->ah->arp_sha[4], p->ah->arp_sha[5]); } break; case ARPOP_REPLY: bcopy((void *)p->ah->arp_spa, (void *) &ip_addr, sizeof(ip_addr)); fprintf(fp, "ARP reply %s", inet_ntoa(ip_addr)); if(memcmp((char *) p->eh->ether_src, (char *) p->ah->arp_sha, 6) != 0) { fprintf(fp, " (%X:%X:%X:%X:%X:%X)", p->ah->arp_sha[0], p->ah->arp_sha[1], p->ah->arp_sha[2], p->ah->arp_sha[3], p->ah->arp_sha[4], p->ah->arp_sha[5]); } fprintf(fp, " is-at %X:%X:%X:%X:%X:%X", p->ah->arp_sha[0], p->ah->arp_sha[1], p->ah->arp_sha[2], p->ah->arp_sha[3], p->ah->arp_sha[4], p->ah->arp_sha[5]); if(memcmp((char *) p->eh->ether_dst, (char *) p->ah->arp_tha, 6) != 0) { fprintf(fp, " (%X:%X:%X:%X:%X:%X)", p->ah->arp_tha[0], p->ah->arp_tha[1], p->ah->arp_tha[2], p->ah->arp_tha[3], p->ah->arp_tha[4], p->ah->arp_tha[5]); } break; case ARPOP_RREQUEST: fprintf(fp, "RARP who-is %X:%X:%X:%X:%X:%X tell %X:%X:%X:%X:%X:%X", p->ah->arp_tha[0], p->ah->arp_tha[1], p->ah->arp_tha[2], p->ah->arp_tha[3], p->ah->arp_tha[4], p->ah->arp_tha[5], p->ah->arp_sha[0], p->ah->arp_sha[1], p->ah->arp_sha[2], p->ah->arp_sha[3], p->ah->arp_sha[4], p->ah->arp_sha[5]); break; case ARPOP_RREPLY: bcopy((void *)p->ah->arp_tpa, (void *) &ip_addr, sizeof(ip_addr)); fprintf(fp, "RARP reply %X:%X:%X:%X:%X:%X at %s", p->ah->arp_tha[0], p->ah->arp_tha[1], p->ah->arp_tha[2], p->ah->arp_tha[3], p->ah->arp_tha[4], p->ah->arp_tha[5], inet_ntoa(ip_addr)); break; default: fprintf(fp, "Unknown operation: %d", ntohs(p->ah->ea_hdr.ar_op)); break; } fprintf(fp, "\n\n"); } /**************************************************************************** * * Function: PrintIPHeader(FILE *) * * Purpose: Dump the IP header info to the specified stream * * Arguments: fp => stream to print to * * Returns: void function * ***************************************************************************/ void PrintIPHeader(FILE * fp, Packet * p) { if(p->iph == NULL) { fprintf(fp, "IP header truncated\n"); return; } if(p->frag_flag) { /* just print the straight IP header */ fputs(inet_ntoa(p->iph->ip_src), fp); fwrite(" -> ", 4, 1, fp); fputs(inet_ntoa(p->iph->ip_dst), fp); } else { if(p->iph->ip_proto != IPPROTO_TCP && p->iph->ip_proto != IPPROTO_UDP) { /* just print the straight IP header */ fputs(inet_ntoa(p->iph->ip_src), fp); fwrite(" -> ", 4, 1, fp); fputs(inet_ntoa(p->iph->ip_dst), fp); } else { if(!pv.obfuscation_flag) { /* print the header complete with port information */ fputs(inet_ntoa(p->iph->ip_src), fp); fprintf(fp, ":%d -> ", p->sp); fputs(inet_ntoa(p->iph->ip_dst), fp); fprintf(fp, ":%d", p->dp); } else { /* print the header complete with port information */ fprintf(fp, "xxx.xxx.xxx.xxx:%d -> xxx.xxx.xxx.xxx:%d", p->sp, p->dp); } } } if(!pv.show2hdr_flag) { fputc('\n', fp); } else { fputc(' ', fp); } fprintf(fp, "%s TTL:%d TOS:0x%X ID:%d IpLen:%d DgmLen:%d", protocol_names[p->iph->ip_proto], p->iph->ip_ttl, p->iph->ip_tos, ntohs(p->iph->ip_id), p->iph->ip_hlen << 2, ntohs(p->iph->ip_len)); /* print the reserved bit if it's set */ if(p->rf) { fprintf(fp, " RB"); } /* printf more frags/don't frag bits */ if(p->df) fprintf(fp, " DF"); if(p->mf) fprintf(fp, " MF"); fputc('\n', fp); /* print IP options */ if(p->ip_option_count != 0) { PrintIpOptions(fp, p); } /* print fragment info if necessary */ if(p->frag_flag) { fprintf(fp, "Frag Offset: 0x%X Frag Size: 0x%X", (p->frag_offset & 0xFFFF), p->dsize); fputc('\n', fp); } } /**************************************************************************** * * Function: PrintTCPHeader(FILE *) * * Purpose: Dump the TCP header info to the specified stream * * Arguments: fp => file stream to print data to * * Returns: void function * ***************************************************************************/ void PrintTCPHeader(FILE * fp, Packet * p) { char tcpFlags[9]; if(p->tcph == NULL) { fprintf(fp, "TCP header truncated\n"); return; } /* print TCP flags */ CreateTCPFlagString(p, tcpFlags); fwrite(tcpFlags, 8, 1, fp); /* We don't care about the NULL */ /* print other TCP info */ fprintf(fp, " Seq: 0x%lX Ack: 0x%lX Win: 0x%X TcpLen: %d", (u_long) ntohl(p->tcph->th_seq), (u_long) ntohl(p->tcph->th_ack), ntohs(p->tcph->th_win), p->tcph->th_off << 2); if((p->tcph->th_flags & TH_URG) != 0) { fprintf(fp, " UrgPtr: 0x%X\n", (u_int16_t) ntohs(p->tcph->th_urp)); } else { fputc((int) '\n', fp); } /* dump the TCP options */ if(p->tcp_option_count != 0) { PrintTcpOptions(fp, p); } } /* Input is packet and an nine-byte (including NULL) character array. Results * are put into the character array. */ void CreateTCPFlagString(Packet * p, char *flagBuffer) { memset(flagBuffer, '\0', 9); /* parse TCP flags */ *flagBuffer++ = (p->tcph->th_flags & TH_RES1) ? '1' : '*'; *flagBuffer++ = (p->tcph->th_flags & TH_RES2) ? '2' : '*'; *flagBuffer++ = (p->tcph->th_flags & TH_URG) ? 'U' : '*'; *flagBuffer++ = (p->tcph->th_flags & TH_ACK) ? 'A' : '*'; *flagBuffer++ = (p->tcph->th_flags & TH_PUSH) ? 'P' : '*'; *flagBuffer++ = (p->tcph->th_flags & TH_RST) ? 'R' : '*'; *flagBuffer++ = (p->tcph->th_flags & TH_SYN) ? 'S' : '*'; *flagBuffer++ = (p->tcph->th_flags & TH_FIN) ? 'F' : '*'; }; /**************************************************************************** * * Function: PrintUDPHeader(FILE *) * * Purpose: Dump the UDP header to the specified file stream * * Arguments: fp => file stream * * Returns: void function * ***************************************************************************/ void PrintUDPHeader(FILE * fp, Packet * p) { if(p->udph == NULL) { fprintf(fp, "UDP header truncated\n"); return; } /* not much to do here... */ fprintf(fp, "Len: %d\n", ntohs(p->udph->uh_len)); } /**************************************************************************** * * Function: PrintICMPHeader(FILE *) * * Purpose: Print ICMP header * * Arguments: fp => file stream * * Returns: void function * ***************************************************************************/ void PrintICMPHeader(FILE * fp, Packet * p) { if(p->icmph == NULL) { fprintf(fp, "ICMP header truncated\n"); return; } fprintf(fp, "Type:%d Code:%d ", p->icmph->type, p->icmph->code); switch(p->icmph->type) { case ICMP_ECHOREPLY: fprintf(fp, "ID:%d Seq:%d ", ntohs(p->ext->id), ntohs(p->ext->seqno)); fwrite("ECHO REPLY\n", 10, 1, fp); break; case ICMP_DEST_UNREACH: fwrite("DESTINATION UNREACHABLE: ", 25, 1, fp); switch(p->icmph->code) { case ICMP_NET_UNREACH: fwrite("NET UNREACHABLE", 15, 1, fp); break; case ICMP_HOST_UNREACH: fwrite("HOST UNREACHABLE", 16, 1, fp); break; case ICMP_PROT_UNREACH: fwrite("PROTOCOL UNREACHABLE", 20, 1, fp); break; case ICMP_PORT_UNREACH: fwrite("PORT UNREACHABLE", 16, 1, fp); break; case ICMP_FRAG_NEEDED: fwrite("FRAGMENTATION NEEDED", 20, 1, fp); break; case ICMP_SR_FAILED: fwrite("SOURCE ROUTE FAILED", 19, 1, fp); break; case ICMP_NET_UNKNOWN: fwrite("NET UNKNOWN", 11, 1, fp); break; case ICMP_HOST_UNKNOWN: fwrite("HOST UNKNOWN", 12, 1, fp); break; case ICMP_HOST_ISOLATED: fwrite("HOST ISOLATED", 13, 1, fp); break; case ICMP_NET_ANO: fwrite("NET ANO", 7, 1, fp); break; case ICMP_HOST_ANO: fwrite("HOST ANO", 8, 1, fp); break; case ICMP_NET_UNR_TOS: fwrite("NET UNREACHABLE TOS", 19, 1, fp); break; case ICMP_HOST_UNR_TOS: fwrite("HOST UNREACHABLE TOS", 20, 1, fp); break; case ICMP_PKT_FILTERED: fwrite("PACKET FILTERED", 15, 1, fp); break; case ICMP_PREC_VIOLATION: fwrite("PREC VIOLATION", 14, 1, fp); break; case ICMP_PREC_CUTOFF: fwrite("PREC CUTOFF", 12, 1, fp); break; default: fwrite("UNKNOWN", 7, 1, fp); break; } { Packet orig_p; bzero((char *) &orig_p, sizeof(Packet)); orig_p.iph = p->orig_iph; orig_p.tcph = p->orig_tcph; orig_p.udph = p->orig_udph; orig_p.sp = p->orig_sp; orig_p.dp = p->orig_dp; if(orig_p.iph != NULL) { fprintf(fp, "\n** ORIGINAL DATAGRAM DUMP:\n"); PrintIPHeader(fp, &orig_p); switch(orig_p.iph->ip_proto) { case IPPROTO_TCP: if(orig_p.tcph != NULL) PrintTCPHeader(fp, &orig_p); break; case IPPROTO_UDP: if(orig_p.udph != NULL) PrintUDPHeader(fp, &orig_p); break; case IPPROTO_ICMP: if(orig_p.icmph != NULL) PrintICMPHeader(fp, &orig_p); break; default: fprintf(fp, "Protocol: 0x%X (unknown or header truncated)", orig_p.iph->ip_proto); break; } /* switch */ fprintf(fp, "** END OF DUMP"); } /* if (orig_p.iph..) */ else { fprintf(fp, "\nORIGINAL DATAGRAM TRUNCATED"); } } break; case ICMP_SOURCE_QUENCH: fwrite("SOURCE QUENCH", 13, 1, fp); break; case ICMP_REDIRECT: fwrite("REDIRECT", 8, 1, fp); break; case ICMP_ECHO: fprintf(fp, "ID:%d Seq:%d ", ntohs(p->ext->id), ntohs(p->ext->seqno)); fwrite("ECHO", 4, 1, fp); break; case ICMP_TIME_EXCEEDED: fwrite("TTL EXCEEDED", 12, 1, fp); break; case ICMP_PARAMETERPROB: fwrite("PARAMETER PROBLEM", 17, 1, fp); break; case ICMP_TIMESTAMP: fwrite("TIMESTAMP REQUEST", 17, 1, fp); break; case ICMP_TIMESTAMPREPLY: fwrite("TIMESTAMP REPLY", 15, 1, fp); break; case ICMP_INFO_REQUEST: fwrite("INFO REQUEST", 12, 1, fp); break; case ICMP_INFO_REPLY: fwrite("INFO REPLY", 10, 1, fp); break; case ICMP_ADDRESS: fwrite("ADDRESS REQUEST", 15, 1, fp); break; case ICMP_ADDRESSREPLY: fwrite("ADDRESS REPLY", 13, 1, fp); break; default: fwrite("UNKNOWN", 7, 1, fp); break; } putc('\n', fp); } void PrintIpOptions(FILE * fp, Packet * p) { int i; int j; u_long init_offset; u_long print_offset; init_offset = ftell(fp); if(!p->ip_option_count) return; fprintf(fp, "IP Options (%d) => ", p->ip_option_count); for(i = 0; i < (int)p->ip_option_count; i++) { print_offset = ftell(fp); if((print_offset - init_offset) > 60) { fwrite("\nIP Options => ", 15, 1, fp); init_offset = ftell(fp); } switch(p->ip_options[i].code) { case IPOPT_RR: fwrite("RR ", 3, 1, fp); break; case IPOPT_EOL: fwrite("EOL ", 4, 1, fp); break; case IPOPT_NOP: fwrite("NOP ", 4, 1, fp); break; case IPOPT_TS: fwrite("TS ", 3, 1, fp); break; case IPOPT_SECURITY: fwrite("SEC ", 4, 1, fp); break; case IPOPT_LSRR: case IPOPT_LSRR_E: fwrite("LSRR ", 5, 1, fp); break; case IPOPT_SATID: fwrite("SID ", 4, 1, fp); break; case IPOPT_SSRR: fwrite("SSRR ", 5, 1, fp); break; case IPOPT_RTRALT: fwrite("RTRALT ", 7, 1, fp); break; default: fprintf(fp, "Opt %d: ", p->ip_options[i].code); if(p->ip_options[i].len) { for(j = 0; j < (int)p->ip_options[i].len - 2; j += 2) { fprintf(fp, "%02X%02X ", p->ip_options[i].data[j], p->ip_options[i].data[j + 1]); } } break; } } fwrite("\n", 1, 1, fp); } void PrintTcpOptions(FILE * fp, Packet * p) { int i; int j; u_char tmp[5]; u_long init_offset; u_long print_offset; init_offset = ftell(fp); fprintf(fp, "TCP Options (%d) => ", p->tcp_option_count); for(i = 0; i < (int)p->tcp_option_count; i++) { print_offset = ftell(fp); if((print_offset - init_offset) > 60) { fwrite("\nTCP Options => ", 16, 1, fp); init_offset = ftell(fp); } switch(p->tcp_options[i].code) { case TCPOPT_MAXSEG: bzero((char *) tmp, 5); fwrite("MSS: ", 5, 1, fp); strncpy(tmp, p->tcp_options[i].data, 2); fprintf(fp, "%u ", EXTRACT_16BITS(tmp)); break; case TCPOPT_EOL: fwrite("EOL ", 4, 1, fp); break; case TCPOPT_NOP: fwrite("NOP ", 4, 1, fp); break; case TCPOPT_WSCALE: fprintf(fp, "WS: %u ", p->tcp_options[i].data[0]); break; case TCPOPT_SACK: bzero((char *) tmp, 5); memcpy(tmp, p->tcp_options[i].data, 2); fprintf(fp, "Sack: %u@", EXTRACT_16BITS(tmp)); bzero((char *) tmp, 5); memcpy(tmp, (p->tcp_options[i].data) + 2, 2); fprintf(fp, "%u ", EXTRACT_16BITS(tmp)); break; case TCPOPT_SACKOK: fwrite("SackOK ", 7, 1, fp); break; case TCPOPT_ECHO: bzero((char *) tmp, 5); memcpy(tmp, p->tcp_options[i].data, 4); fprintf(fp, "Echo: %u ", EXTRACT_32BITS(tmp)); break; case TCPOPT_ECHOREPLY: bzero((char *) tmp, 5); memcpy(tmp, p->tcp_options[i].data, 4); fprintf(fp, "Echo Rep: %u ", EXTRACT_32BITS(tmp)); break; case TCPOPT_TIMESTAMP: bzero((char *) tmp, 5); memcpy(tmp, p->tcp_options[i].data, 4); fprintf(fp, "TS: %u ", EXTRACT_32BITS(tmp)); bzero((char *) tmp, 5); memcpy(tmp, (p->tcp_options[i].data) + 4, 4); fprintf(fp, "%u ", EXTRACT_32BITS(tmp)); break; case TCPOPT_CC: bzero((char *) tmp, 5); memcpy(tmp, p->tcp_options[i].data, 4); fprintf(fp, "CC %u ", EXTRACT_32BITS(tmp)); break; case TCPOPT_CCNEW: bzero((char *) tmp, 5); memcpy(tmp, p->tcp_options[i].data, 4); fprintf(fp, "CCNEW: %u ", EXTRACT_32BITS(tmp)); break; case TCPOPT_CCECHO: bzero((char *) tmp, 5); memcpy(tmp, p->tcp_options[i].data, 4); fprintf(fp, "CCECHO: %u ", EXTRACT_32BITS(tmp)); break; default: if(p->tcp_options[i].len > 2) { fprintf(fp, "Opt %d (%d): ", p->tcp_options[i].code, (int) p->tcp_options[i].len); for(j = 0; j < (int)p->tcp_options[i].len - 2; j += 2) { fprintf(fp, "%02X%02X ", p->tcp_options[i].data[j], p->tcp_options[i].data[j + 1]); } } else { fprintf(fp, "Opt %d ", p->tcp_options[i].code); } break; } } fwrite("\n", 1, 1, fp); } /**************************************************************************** * * Function: LogBin() * * Purpose: Log packets in binary (tcpdump) format * * Arguments: None. * * Returns: void function * ***************************************************************************/ void LogBin(Packet * p, char *msg, void *arg) { if(p != NULL) { pcap_dump((u_char *) dumpd, p->pkth, p->pkt); fflush((FILE *) dumpd); } } /**************************************************************************** * * Function: IcmpFileName(Packet *p) * * Purpose: Set the filename of an ICMP output log according to its type * * Arguments: p => Packet data struct * * Returns: the name of the file to set * ***************************************************************************/ char *IcmpFileName(Packet * p) { switch(p->icmph->type) { case ICMP_ECHOREPLY: return "ECHO_REPLY"; case ICMP_DEST_UNREACH: switch(p->icmph->code) { case ICMP_NET_UNREACH: return "NET_UNRCH"; case ICMP_HOST_UNREACH: return "HST_UNRCH"; case ICMP_PROT_UNREACH: return "PROTO_UNRCH"; case ICMP_PORT_UNREACH: return "PORT_UNRCH"; case ICMP_FRAG_NEEDED: return "UNRCH_FRAG_NEEDED"; case ICMP_SR_FAILED: return "UNRCH_SOURCE_ROUTE_FAILED"; case ICMP_NET_UNKNOWN: return "UNRCH_NETWORK_UNKNOWN"; case ICMP_HOST_UNKNOWN: return "UNRCH_HOST_UNKNOWN"; case ICMP_HOST_ISOLATED: return "UNRCH_HOST_ISOLATED"; case ICMP_NET_ANO: return "UNRCH_NET_ANO"; case ICMP_HOST_ANO: return "UNRCH_HOST_ANO"; case ICMP_NET_UNR_TOS: return "UNRCH_NET_UNR_TOS"; case ICMP_HOST_UNR_TOS: return "UNRCH_HOST_UNR_TOS"; case ICMP_PKT_FILTERED: return "UNRCH_PACKET_FILT"; case ICMP_PREC_VIOLATION: return "UNRCH_PREC_VIOL"; case ICMP_PREC_CUTOFF: return "UNRCH_PREC_CUTOFF"; default: return "UNKNOWN"; } case ICMP_SOURCE_QUENCH: return "SRC_QUENCH"; case ICMP_REDIRECT: return "REDIRECT"; case ICMP_ECHO: return "ECHO"; case ICMP_TIME_EXCEEDED: return "TTL_EXCEED"; case ICMP_PARAMETERPROB: return "PARAM_PROB"; case ICMP_TIMESTAMP: return "TIMESTAMP"; case ICMP_TIMESTAMPREPLY: return "TIMESTAMP_RPL"; case ICMP_INFO_REQUEST: return "INFO_REQ"; case ICMP_INFO_REPLY: return "INFO_RPL"; case ICMP_ADDRESS: return "ADDR"; case ICMP_ADDRESSREPLY: return "ADDR_RPL"; default: return "UNKNOWN"; } } /**************************************************************************** * * Function: InitLogFile(char *logname) * * Purpose: Initialize the tcpdump log file header * * Arguments: None. * * Returns: void function * ***************************************************************************/ void InitBinLogFile(char *logname) { time_t curr_time; /* place to stick the clock data */ struct tm *loc_time; /* place to stick the adjusted clock data */ char timebuf[10]; char logdir[STD_BUF]; bzero((char *) timebuf, 10); curr_time = time(NULL); loc_time = localtime(&curr_time); strftime(timebuf, 91, "%m%d@%H%M", loc_time); /* bzero((char *) logdir, STD_BUF); if(strlen(pv.log_dir) + strlen(timebuf) + 12 < STD_BUF) sprintf(logdir, "%s/snort-%s.log", pv.log_dir, timebuf);*/ if (logname != NULL && strlen(logname) != 0) { if (strlen(pv.log_dir) + strlen(logname) + strlen( chrootdir == NULL ? "" : chrootdir) + 2 < sizeof(logdir)) { snprintf (logdir, sizeof(logdir) -1, "%s%s/%s", chrootdir == NULL ? "" : chrootdir, pv.log_dir, logname); } else { FatalError("ERROR => InitBinLogFile(logname) %s\n", logname); } } else { bzero((char *) timebuf, 10); curr_time = time(NULL); loc_time = localtime(&curr_time); strftime(timebuf, 91, "%m%d@%H%M", loc_time); bzero((char *) logdir, sizeof(logdir)); if(strlen(pv.log_dir) + strlen(timebuf) + strlen( chrootdir == NULL ? "" : chrootdir) + 12 < sizeof(logdir)) { snprintf(logdir, sizeof(logdir) -1, "%s%s/snort-%s.log", chrootdir == NULL ? "" : chrootdir, pv.log_dir, timebuf); } } #ifdef DEBUG printf("Opening %s\n", logdir); #endif if((dumpd = pcap_dump_open(pd, logdir)) == NULL) { FatalError("ERROR => InitBinLogFile(%s) pcap_dump_open: %s\n", logdir, strerror(errno)); } #ifdef DEBUG printf("BinLogFile file initialized\n"); #endif return; }