📄 snort.c
字号:
/* $Id: snort.c,v 1.44 2000/03/20 08:40:58 roesch Exp $ */
/*
** Copyright (C) 1998,1999,2000 Martin Roesch <roesch@clark.net>
**
** 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.
*/
/******************************************************************************
*
* Program: Snort
*
* Purpose: Check out the README file for info on what you can do
* with Snort.
*
* Author: Martin Roesch (roesch@clark.net)
*
* Comments: Ideas and code stolen liberally from Mike Borella's IP Grab
* program. Check out his stuff at http://www.borella.net. I
* also have ripped some util functions from TCPdump, plus Mike's
* prog is derived from it as well. All hail TCPdump....
*
* HP-UX 10.x note from Chris Sylvain:
* if you run snort and receive the error message
* "ERROR: OpenPcap() device lan0 open:
* recv_ack: promisc_phys: Invalid argument"
* it's because there's another program running using the DLPI service.
* The HP-UX implementation doesn't allow more than one libpcap program
* at a time to run, unlike Linux.
*
******************************************************************************/
/* I N C L U D E S **********************************************************/
#include "snort.h"
extern OutputFuncNode *AlertList;
extern OutputFuncNode *LogList;
/****************************************************************************
*
* Function: main(int, char *)
*
* Purpose: Handle program entry and exit, call main prog sections
*
* Arguments: See command line args in README file
*
* Returns: 0 => normal exit, 1 => exit on error
*
****************************************************************************/
int main(int argc, char *argv[])
{
#if defined(LINUX) || defined (FREEBSD) || defined(OPENBSD) || defined(SOLARIS)
sigset_t set;
sigemptyset(&set);
sigprocmask(SIG_SETMASK, &set, NULL);
#else
sigsetmask(0);
#endif
/* make this prog behave nicely when signals come along */
signal(SIGKILL, CleanExit);
signal(SIGTERM, CleanExit);
signal(SIGINT, CleanExit);
signal(SIGQUIT, CleanExit);
signal(SIGHUP, CleanExit);
/* sane permissions */
umask(077);
/* set a global ptr to the program name so other functions can tell
what the program name is */
progname = argv[0];
progargs = argv;
InitNetmasks();
InitProtoNames();
/* initialize the packet counter to loop forever */
pv.pkt_cnt = -1;
/* set the default alert mode */
pv.alert_mode = ALERT_FULL;
/* set the timezone (ripped from tcpdump) */
thiszone = gmt2local(0);
pv.quiet_flag = 0;
/* chew up the command line */
ParseCmdLine(argc, argv);
#ifdef ENABLE_RESPONSE
#ifdef DEBUG
printf("Opening Raw Socket for Sending\n");
#endif
if ((nd = libnet_open_raw_sock(IPPROTO_RAW)) < 0)
{
FatalError("ERROR: cannot open raw socket for libnet, exiting...\n");
}
#endif
if (!pv.readmode_flag)
{
#ifdef DEBUG
printf("Opening interface: %s\n", pv.interface);
#endif
/* open up our libpcap packet capture interface */
OpenPcap(pv.interface);
}
else
{
#ifdef DEBUG
printf("Opening file: %s\n", pv.readfile);
#endif
OpenPcap(pv.readfile);
}
CreatePidFile(pv.interface);
if(pv.chroot_dir != NULL)
{
if(chdir(pv.chroot_dir) < 0)
FatalError("Can not chdir to \"%s\"\n",pv.chroot_dir);
if(chroot(pv.chroot_dir) < 0)
FatalError("Can not chroot to %s\n",pv.chroot_dir);
if(chdir("/") < 0)
FatalError("Can not chdir to \"/\"\n");
}
/* set safe userID/groupID if needed */
SetUidGid();
/* if the logging flag hasn't been set yet... */
if(!pv.log_flag)
{
/* ...set the default logging dir */
strncpy(pv.log_dir,DEFAULT_LOG_DIR,strlen(DEFAULT_LOG_DIR)+1);
}
if (pv.use_rules || pv.log_flag)
{
/* perform some sanity checks on the output directory, etc*/
SanityChecks();
}
if (pv.use_rules && pv.rules_order_flag)
{
printf("Rule application order changed to Pass->Alert->Log\n");
}
/* we're not using rules, sniffing to the screen, or logging packets
so we don't really need to run... */
if (!pv.use_rules && !pv.verbose_flag && !pv.log_flag)
{
/* give them a nice little reminder that Snort needs to be told what
to do */
printf("\n\nUh, you need to tell me to do something....\n\n");
DisplayBanner();
ShowUsage(progname);
exit(0);
}
/* if daemon mode requested, fork daemon first, otherwise
* on linux interface will be reset.
*/
if (pv.daemon_flag)
{
#ifdef DEBUG
printf("Entering daemon mode\n");
#endif
GoDaemon();
}
/* if (!pv.readmode_flag)
{
#ifdef DEBUG
printf("Opening interface: %s\n", pv.interface);
#endif
OpenPcap(pv.interface);
}
else
{
#ifdef DEBUG
printf("Opening file: %s\n", pv.readfile);
#endif
OpenPcap(pv.readfile);
}
CreatePidFile(pv.interface);
*/
#ifdef DEBUG
printf("Setting Packet Processor\n");
#endif
/* set the packet processor (ethernet, slip or raw)*/
SetPktProcessor();
if (pv.use_rules)
{
InitPreprocessors();
InitPlugIns();
InitOutputPlugins();
#ifdef DEBUG
DumpPreprocessors();
DumpPlugIns();
DumpOutputPlugins();
#endif
ParseRulesFile(pv.config_file, 0);
}
/* Tell 'em who wrote it, and what "it" is */
if ( !pv.quiet_flag )
DisplayBanner();
if (pv.alert_cmd_override)
{
/* if a command line alert override has been specified, setup the
approriate function pointer */
/* if we're using syslog alerting set the alert function pointer to
the syslog alerting function */
if (pv.syslog_flag)
{
AddFuncToOutputList(SyslogAlert, NT_OUTPUT_ALERT, NULL);
openlog("snort", LOG_PID|LOG_NDELAY|LOG_NOWAIT, LOG_AUTH);
}
else if (pv.smbmsg_flag)
{
#ifdef ENABLE_SMB_ALERTS
AddFuncToOutputList(SmbAlert, NT_OUTPUT_ALERT, NULL);
#else
FatalError("ERROR: SMB support not compiled into program, exiting...\n");
#endif
}
else
{
switch (pv.alert_mode)
{
case ALERT_FAST:
alert = OpenAlertFile(NULL);
AddFuncToOutputList(FastAlert, NT_OUTPUT_ALERT, NULL);
break;
case ALERT_FULL:
alert = OpenAlertFile(NULL);
AddFuncToOutputList(FullAlert, NT_OUTPUT_ALERT, NULL);
break;
case ALERT_NONE:
SetOutputList(NoAlert, NT_OUTPUT_ALERT, NULL);
break;
case ALERT_UNSOCK:
AddFuncToOutputList(UnixSockAlert, NT_OUTPUT_ALERT, NULL);
OpenAlertSock();
break;
}
}
}
if (AlertList == NULL && pv.use_rules) {
alert = OpenAlertFile(NULL);
AddFuncToOutputList(FullAlert, NT_OUTPUT_ALERT, NULL);
}
AlertFunc = CallAlertPlugins;
if (pv.log_cmd_override)
{
if (pv.logbin_flag)
{
#ifdef DEBUG
printf("Initializing output file\n");
#endif
InitBinLogFile();
AddFuncToOutputList(LogBin, NT_OUTPUT_LOG, NULL);
}
else /* if we're not logging in tcpdump format... */
{
/* set the logging function pointer */
if (!pv.nolog_flag)
AddFuncToOutputList(LogPkt, NT_OUTPUT_LOG, NULL);
else
SetOutputList(NoLog, NT_OUTPUT_LOG, NULL);
}
}
if (LogList == NULL)
AddFuncToOutputList(LogPkt, NT_OUTPUT_LOG, NULL);
LogFunc = CallLogPlugins;
/*
#ifdef ENABLE_RESPONSE
#ifdef DEBUG
printf("Opening Raw Socket for Sending\n");
#endif
if ((nd = libnet_open_raw_sock(IPPROTO_RAW)) < 0)
{
FatalError("ERROR: cannot open raw socket for libnet, exiting...\n");
}
#endif
if(pv.chroot_dir != NULL)
{
if(chdir(pv.chroot_dir) < 0)
FatalError("Can not chdir to \"%s\"\n",pv.chroot_dir);
if(chroot(pv.chroot_dir) < 0)
FatalError("Can not chroot to %s\n",pv.chroot_dir);
if(chdir("/") < 0)
FatalError("Can not chdir to \"/\"\n");
}
SetUidGid();
*/
#ifdef DEBUG
printf("Entering pcap loop\n");
#endif
/* Read all packets on the device. Continue until cnt packets read */
if (pcap_loop(pd, pv.pkt_cnt, (pcap_handler)ProcessPacket, NULL) < 0)
{
if (pv.daemon_flag)
syslog(LOG_CONS|LOG_DAEMON,"pcap_loop: %s", pcap_geterr(pd));
else
PrintFmtError("pcap_loop: %s", pcap_geterr(pd));
CleanExit(SIGQUIT);
}
/* close the capture interface */
pcap_close(pd);
CleanExit(SIGQUIT);
return 0;
}
void ProcessPacket(char *user, struct pcap_pkthdr *pkthdr, u_char *pkt)
{
Packet p;
/* call the packet decoder */
(*grinder)(&p, pkthdr, pkt);
/* print the packet to the screen */
if (pv.verbose_flag)
{
if (p.iph != NULL)
{
PrintIPPkt(stdout, p.iph->ip_proto, &p);
}
else if (p.ah != NULL && pv.showarp_flag)
{
PrintArpHeader(stdout, &p);
if (pv.log_flag)
{
LogArpPkt(&p);
}
}
}
/* check or log the packet as necessary */
if (!pv.use_rules)
{
if (pv.log_flag)
{
if (pv.logbin_flag)
{
LogBin(&p, NULL, NULL);
}
else
{
if (p.iph != NULL)
LogPkt(&p, NULL, NULL);
if (p.ah != NULL)
{
if (!pv.nolog_flag)
{
OpenLogFile(ARP, &p);
PrintArpHeader(log_ptr, &p);
fclose(log_ptr);
}
}
}
}
}
else
{
Preprocess(&p);
}
ClearDumpBuf();
}
/****************************************************************************
*
* Function: ShowUsage(char *)
*
* Purpose: Display the program options and exit
*
* Arguments: progname => name of the program (argv[0])
*
* Returns: 0 => success
*
****************************************************************************/
int ShowUsage(char *progname)
{
printf("USAGE: %s [-options] <filter options>\n", progname);
puts("Options:");
puts(" -A Set alert mode: fast, full, or none "
" (alert file alerts only)"
"\n \"unsock\" enables UNIX socket logging (experimental).");
puts(" -a Display ARP packets");
puts(" -b Log packets in tcpdump format (much faster!)");
puts(" -c <rules> Use Rules File <rules>");
puts(" -C Print out payloads with character data only (no hex)");
puts(" -d Dump the Application Layer");
puts(" -D Run Snort in background (daemon) mode");
puts(" -e Display the second layer header info");
puts(" -F <bpf> Read BPF filters from file <bpf>");
puts(" -g <gname> Run snort gid as `gname' user or uid after initialization");
puts(" -h <hn> Home network = <hn>");
puts(" -i <if> Listen on interface <if>");
puts(" -l <ld> Log to directory <ld>");
#ifdef ENABLE_SMB_ALERTS
puts(" -M <wrkst> Sends SMB message to workstations in file <wrkst>");
puts(" (Requires smbclient to be in PATH)");
#endif
puts(" -n <cnt> Exit after receiving <cnt> packets");
puts(" -N Turn off logging (alerts still work)");
puts(" -o Change the rule testing order to Pass|Alert|Log");
puts(" -O Obfuscate the logged IP addresses");
puts(" -p Disable promiscuous mode sniffing");
printf(" -P <snap> set explicit snaplen of packet (default: %d)\n",
SNAPLEN);
puts(" -q Quiet. Don't show banner and status report");
puts(" -r <tf> Read and process tcpdump file <tf>");
puts(" -s Log alert messages to syslog");
puts(" -S <n=v> Set rules file variable n equal to value v");
puts(" -t <chrt> Chroots process to <chrt> after initialisaton");
puts(" -u <uname> Run snort uid as `uname' user (or uid) after initialization");
puts(" -v Be verbose");
puts(" -V Show version number");
puts(" -X Dump the raw packet data starting at the link layer");
/* Nobody really uses this, do they?
puts(" -6 Display IPv6 packets");
puts(" -x Display IPX packets");
*/
puts(" -? Show this information");
puts("<Filter Options> are standard BPF options, as seen in TCPDump");
fflush(stdout);
return 0;
}
/****************************************************************************
*
* Function: ParseCmdLine(int, char *)
*
* Purpose: Parse command line args
*
* Arguments: argc => count of arguments passed to the routine
* argv => 2-D character array, contains list of command line args
*
* Returns: 0 => success, 1 => exit on error
*
****************************************************************************/
extern char *optarg; /* for getopt */
extern int optind; /* for getopt */
int ParseCmdLine(int argc, char *argv[])
{
int ch; /* storage var for getopt info */
int read_bpf = 0;
char bpf_file[STD_BUF];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -