Logo Search packages:      
Sourcecode: netams version File versions  Download package

ipfw2netflow.c

/*************************************************************************
***   Authentication, authorization, accounting + firewalling package
***   Copyright 1998-2002 Anton Vinokurov <anton@netams.com>
***   Copyright 2002-2008 NeTAMS Development Team
***   This code is GPL v3
***   For latest version and more info, visit this project web page
***   located at http://www.netams.com
***
*************************************************************************/
/* $Id: ipfw2netflow.c,v 1.20 2008-02-23 08:35:02 anton Exp $ */

/*************************************************************************
*** IPFW support added by Dmitry Sergienko <dmitry@trifle.net>.
*** FreeBSD kqueue(2) support added by Roman Nikitchenko <roman@trifle.net>.
*************************************************************************/

#ifdef FREEBSD

#include "config.h"

#define NETFLOW_CLASS
#include "netflow.h"

extern u_char debug, quiet;
extern void Debug(char *msg,...);

/* defaults */
#define BLOCKSIZE 32768

u_char quit=0;

char *destination=NULL;
char *dst_host=NULL;
unsigned short dst_port=20001;
#ifdef KEVENT
struct timespec event_ts;
#endif
struct timeval tv;
u_char hupset=0;

class NetFlow *Flow;

//#define MY_MALLOC(x) new(x)
#define MY_MALLOC(x) malloc(x)
//#define MY_FREE(x) delete(x)
#define MY_FREE(x) free(x)

void termination(){
    if (debug && !quiet) {
      Flow->Status();
    }
    quit = 1;
}


void PrintUsage(FILE *f){
    fprintf(f, "Usage: ipfw2netflow {options}\nwhere {options} are:\n\
            -h\t print help screen and exit\n\
            -q\t quiet output\n\
            -d\t debug output (no daemon mode)\n\
            -e export_to\t IP address:port to export flows to\n\
            -b ipfw socket buffer size\n\
            -p ipfw tee/divert bind port\n\
            -x expire check timeout (sec)\n\
            -a active_timeout\t active flow timeout (sec.)\n\
            -i inactive_timeout\t inactive flow timeout (sec.)\n");

}

void do_hup()
{
    Debug("SIGHUP\n");
    hupset = 1;
    signal(SIGHUP, (sig_t)do_hup);
}
//---------------------------------------------------------------------------------

int main(int argc, char **argv)
{
    unsigned char       *packet;
    struct  sockaddr_in ds;         /* divert socket address */
    socklen_t size_ds = sizeof(ds);
    int     spkt;             /* divert socket */
#ifdef KEVENT
    struct kevent event;            /* kevent filter  */
    int                 event_poller;     /* kevent poller  */
    int                 filter_result;    /* main filter result   */
#else
    fd_set  allsocks;
#endif
    u_short       bindport;
    int sock_bsize = BLOCKSIZE;
    int op;
    unsigned active=0,inactive=0;
      unsigned expired =0;    

    if (debug && !quiet) {
        printf("ipfw2netflow 1.1 (c) 2002 Anton Vinokurov, anton@netams.com\n");
        printf("This is part of NeTAMS project, http://www.netams.com \n");
    }
    
    bzero(&ds, size_ds);
    ds.sin_family = AF_INET;

    while((op=getopt(argc, argv, "hqde:p:a:i:x:b:")) != EOF){
        switch(op){
        case 'h':
            PrintUsage(stdout);
            exit(-1);
            break;
        case 'd':
            debug=1;
            break;
        case 'q':
            quiet=1;
            break;
        case 'e':
            destination=(char *)calloc(strlen(optarg)+1, 1);
            strcpy(destination, optarg);
            break;
        case 'p': /* bind port */
            bindport = strtol(optarg, NULL, 10);
            ds.sin_port = htons(bindport);
            break;
        case 'a':
            active=strtol(optarg, NULL, 10);
            break;
        case 'i':
            inactive=strtol(optarg, NULL, 10);
            break;
        case 'x':
            expired=strtol(optarg, NULL, 10);
            break;
        case 'b':
            sock_bsize=strtol(optarg, NULL, 10);
            break;
        default:
            PrintUsage(stdout);
            break;
        }
    }

    if (!ds.sin_port) {
        printf("Please define tee port with -p flag!\n\n");
        PrintUsage(stdout);
        exit(1);
    }
    if (!destination)
        dst_host="127.0.0.1";
    else {
        char *c;
        c=strchr(destination, ':');
        if (c) {
            dst_port=strtol(c+1, NULL, 10);
            c[0]='\0'; dst_host=destination;
        } else
            dst_host=destination;
    }
    
    if (!active) active=10*60; // 1 min
    if (!inactive) inactive=1*60; // 10 min
      
      Flow=new NetFlow(dst_host,dst_port);   
      Flow->SetTimeouts(active,inactive,expired);     

      bzero(&tv, sizeof(struct timeval));
      tv.tv_sec = expired;

    if ((spkt = socket(PF_INET, SOCK_RAW, IPPROTO_DIVERT)) == -1)
        fprintf(stderr, "socket(IP_DIVERT)");

    if ((bind(spkt, (struct sockaddr *)&ds, sizeof(ds))) != 0)
        fprintf(stderr, "bind");

    if (!debug)
    {
        daemon(0, 1);
        chdir("/var/tmp");
        umask(077);
        fclose(stdin);
        fclose(stdout);
        fclose(stderr);
    }

#ifdef KEVENT
    event_poller = kqueue();
    if (event_poller < 0)
    {
        if (!quiet)
          fprintf(stderr, "failed to create kqueue: %s\n", strerror(errno));
        exit(5);
    }

    bzero( &event, sizeof( struct kevent ) );
    bzero( &event_ts, sizeof( struct timespec ) );

    event.ident  = spkt;
    event.filter = EVFILT_READ;
    event.flags  = EV_ADD | EV_ENABLE;

    if ( kevent( event_poller, &event, 1, NULL, 0, &event_ts ) < 0 )
    {
        if (!quiet)
          fprintf(stderr, "kevent filter failed: %s\n", strerror(errno));
        exit(5);
    }
    event_ts.tv_sec = expired;
#else
    FD_ZERO(&allsocks);
    FD_SET(spkt, &allsocks);
#endif

    if (sock_bsize)
    {
        setsockopt(spkt, SOL_SOCKET, SO_RCVBUF, &sock_bsize, sizeof(int));
        setsockopt(spkt, SOL_SOCKET, SO_SNDBUF, &sock_bsize, sizeof(int));
    }
      
      
    packet=(unsigned char*)MY_MALLOC(MAX_PKT_SIZE);  

    signal(SIGINT, (sig_t)termination);
    signal(SIGQUIT, (sig_t)termination);
    signal(SIGTERM, (sig_t)termination);
    signal(SIGHUP, (sig_t) do_hup);

    while(!quit)
    {
        long len;
#ifdef KEVENT
      struct kevent result;

        if ( (filter_result =
            kevent( event_poller, NULL, 0, &result, 1, NULL )) < 0 )
#else
        fd_set readable;

        readable = allsocks;
        if (select(spkt + 1, &readable, NULL, NULL, &tv) < 0)
#endif
      {
            if (errno != EINTR)
          {
                quit = 1;
                break;
            }
            if (hupset)
            {
                Flow->FlushAll();
                hupset=0;
            }
            continue;
        }

      Flow->Expiresearch();

        /* check for packet available */
#ifdef KEVENT
      if ( (filter_result == 1) && (((int)result.ident) == spkt) )
#else
        if (FD_ISSET(spkt, &readable))
#endif
      {
            if ((len = recvfrom(spkt, packet, MAX_PKT_SIZE, 0,
                                (struct sockaddr *)&ds, &size_ds)) != -1)
          {
                Flow->Processpacket((struct ip *)packet);
          }
        }
    }

    delete Flow;
#ifdef KEVENT
    close( event_poller );
#else
    FD_CLR(spkt, &allsocks);
#endif
    close(spkt);

    MY_FREE(packet);
    
    signal(SIGINT, SIG_DFL);
    signal(SIGQUIT, SIG_DFL);
    signal(SIGTERM, SIG_DFL);
    signal(SIGALRM, SIG_DFL);
    signal(SIGHUP, SIG_DFL);
    return 0;
}

#else

#include <stdio.h>

int main() {
        printf("This is part of NeTAMS project, http://www.netams.com \n");
      printf("This software could be started under FreeBSD operating system only\n");
}

#endif // FREEBSD

Generated by  Doxygen 1.6.0   Back to index