/***** * * Copyright (C) 2003 Nicolas Delon * All Rights Reserved * * This file is part of the Prelude program. * * 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; see the file COPYING. If not, write to * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * *****/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "alert.h" #include "process_packet.h" #include "config.h" #define DEFAULT_SNAPLEN 96 #define DEFAULT_INTERFACE "pflog0" static char *pidfile = NULL; static char *interface = DEFAULT_INTERFACE; static int bring_interface_down_at_shutdown = 0; static int print_help(prelude_option_t *opt, const char *arg) { prelude_option_print(CLI_HOOK, 25); return prelude_option_end; } static int print_version(prelude_option_t *opt, const char *arg) { printf("prelude-pflogger %s\n", VERSION); return prelude_option_end; } static int set_daemon_mode(prelude_option_t *opt, const char *arg) { prelude_daemonize(pidfile); if ( pidfile ) free(pidfile); prelude_log_use_syslog(); return prelude_option_success; } static int set_pidfile(prelude_option_t *opt, const char *arg) { pidfile = strdup(arg); if ( ! pidfile ) { log(LOG_ERR, "memory exhausted.\n"); return prelude_option_error; } return prelude_option_success; } static int init_sensor(int argc, char **argv) { prelude_option_t *opt; int retval; prelude_option_add(NULL, CLI_HOOK, 'v', "version", "Print version number", no_argument, print_version, NULL); prelude_option_add(NULL, CLI_HOOK, 'h', "help", "Print this help", no_argument, print_help, NULL); prelude_option_add(NULL, CLI_HOOK | CFG_HOOK, 'd', "daemon", "Run in daemon mode", no_argument, set_daemon_mode, NULL); opt = prelude_option_add(NULL, CLI_HOOK | CFG_HOOK, 'P', "pidfile", "Write Prelude PFlogger pid to the specified pidfile", required_argument, set_pidfile, NULL); prelude_option_set_priority(opt, option_run_first); retval = prelude_sensor_init("prelude-pflogger", PRELUDE_CONF, argc, argv); if ( retval == prelude_option_end ) exit(0); if ( retval == prelude_option_error ) { log(LOG_ERR, "prelude_sensor_init failed\n"); return -1; } if ( prelude_async_init() < 0 ) { log(LOG_ERR, "prelude_async_init failed\n"); return -1; } return 0; } /* * Check if interface is up * if not, bring it up and set a flag so that * the interface will be brought down when pflogger shutdown */ static int init_interface(void) { int sock; struct ifreq ifreq; sock = socket(AF_INET, SOCK_DGRAM, 0); if ( sock < 0 ) { log(LOG_ERR, "socket failed\n"); return -1; } strncpy(ifreq.ifr_name, interface, sizeof (ifreq.ifr_name)); if ( ioctl(sock, SIOCGIFFLAGS, &ifreq) < 0 ) { log(LOG_ERR, "ioctl SIOCGIFFLAGS\n"); close(sock); return -1; } if ( !(ifreq.ifr_flags & IFF_UP) ) { log(LOG_INFO, "interface %s is down, bring it up\n", interface); ifreq.ifr_flags |= IFF_UP; if ( ioctl(sock, SIOCSIFFLAGS, &ifreq) ) { log(LOG_ERR, "ioctl SIOCSIFFLAGS failed\n"); return -1; } bring_interface_down_at_shutdown = 1; } close(sock); return 0; } static int shutdown_interface(void) { int sock; struct ifreq ifreq; if ( ! bring_interface_down_at_shutdown ) return 0; sock = socket(AF_INET, SOCK_DGRAM, 0); if ( sock < 0 ) { log(LOG_ERR, "socket failed\n"); return -1; } strncpy(ifreq.ifr_name, interface, sizeof (ifreq.ifr_name)); if ( ioctl(sock, SIOCGIFFLAGS, &ifreq) < 0 ) { log(LOG_ERR, "ioctl SIOCGIFFLAGS\n"); close(sock); return -1; } ifreq.ifr_flags &= ~IFF_UP; if ( ioctl(sock, SIOCSIFFLAGS, &ifreq) ) { log(LOG_ERR, "ioctl SIOCSIFFLAGS failed\n"); return -1; } close(sock); return 0; } static void pflogger_shutdown(void) { process_packet_stop(); (void) shutdown_interface(); } static void signal_handler(int signo) { log(LOG_INFO, "caught signal %d\n", signo); pflogger_shutdown(); exit(0); } static void init_signal_handlers(void) { signal(SIGINT, signal_handler); signal(SIGTERM, signal_handler); signal(SIGQUIT, signal_handler); signal(SIGHUP, signal_handler); } int main(int argc, char **argv) { if ( init_sensor(argc, argv) < 0 ) { log(LOG_ERR, "could not init sensor\n"); return 1; } if ( init_interface() < 0 ) { log(LOG_ERR, "could not init interface\n"); return 1; } if ( process_packet_init(interface, DEFAULT_SNAPLEN) < 0 ) { log(LOG_ERR, "could not init pcap\n"); return 1; } init_signal_handlers(); if ( alert_init_subsystem() < 0 ) { log(LOG_ERR, "could not init alert subsystem\n"); return 1; } if ( process_packet_mainloop() < 0 ) { log(LOG_ERR, "error while processing packets\n"); return 1; } pflogger_shutdown(); return 0; }