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

flowprobe.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: flowprobe.c,v 1.48 2009-08-01 09:23:55 anton Exp $ */

#ifndef NOPCAP
#include "config.h"
extern "C" {
      #include "../lib/lib.h"
}

typedef void ServiceDS_cfg;
#include "ds_libpcap.h"

#define _PATH_VARTMP "/var/tmp"

#define NETFLOW_CLASS
#include "netflow.h"

#ifdef PCAP_NEED_POLL
#include "pcap-int.h"
#endif

#undef CHECK_POLL
#define CHECK_POLL(status) {                                                            \
        if ((status = poll(&pfd, 1, POLL_TIMEOUT)) < 0 && errno != EINTR) {     \
                printf("poll: %s\n", strerror(errno));      \
                continue;                                                       \
        }                                                                       \
}

struct DLT dlt[] = {
#ifdef DLT_NULL
        {DLT_NULL, 0, 4, 4, "NULL"},
#endif
#ifdef DLT_EN10MB
        {DLT_EN10MB, 12, 14, 17, "EN10MB"},
#endif
#ifdef DLT_IEEE802
        {DLT_IEEE802, 14, 22, 17, "IEEE802"},
#endif
#ifdef DLT_ARCNET
        {DLT_ARCNET, 2 , 6, 6, "ARCNET"},
#endif
#ifdef DLT_SLIP
        {DLT_SLIP, -1, 16, 16, "SLIP"},
#endif
#ifdef DLT_PPP
        {DLT_PPP, 2, 4, 4, "PPP"},
#endif
#ifdef DLT_FDDI
        /*
        FIXME
        See gencode.c from libpcap
        */
        {DLT_FDDI, 13, 21, 16, "FDDI"},
#endif
#ifdef DLT_ATM_RFC1483
        {DLT_ATM_RFC1483, 0, 8, 3, "ATM_RFC1483"},
#endif
#ifdef DLT_RAW
        {DLT_RAW, -1, 0, 0, "RAW"},
#endif
#ifdef DLT_SLIP_BSDOS
        {DLT_SLIP_BSDOS, -1, 24, 24, "SLIP_BSDOS"},
#endif
#ifdef DLT_PPP_BSDOS
        {DLT_PPP_BSDOS, 5, 24, 24, "PPP_BSDOS"},
#endif
#ifdef DLT_ATM_CLIP
        {DLT_ATM_CLIP, 0, 8, 3, "ATM_CLIP"},
#endif
#ifdef DLT_PPP_SERIAL
        {DLT_PPP_SERIAL, 2, 4, 4, "PPP_SERIAL"},
#endif
#ifdef DLT_PPP_ETHER
        {DLT_PPP_ETHER, 6, 8, 8, "PPP_ETHER"},
#endif
#ifdef DLT_C_HDLC
        {DLT_C_HDLC, 2, 4, 4, "C_HDLC"},
#endif
#ifdef DLT_IEEE802_11
        {DLT_IEEE802_11, 24, 32, 27, "IEEE802_11"},
#endif
#ifdef DLT_LOOP
        {DLT_LOOP, 0, 4, 4, "LOOP"},
#endif
#ifdef DLT_LINUX_SLL
        {DLT_LINUX_SLL, 14, 16, 16, "LINUX_SLL"},
#endif
#ifdef DLT_LTALK
        {DLT_LTALK, -1, 0, 0, "LTALK"},
#endif
#ifdef DLT_PRISM_HEADER
        {DLT_PRISM_HEADER, 144 + 24, 144 + 30, 144 + 27, "PRISM_HEADER"},
#endif
#ifdef DLT_IP_OVER_FC
        {DLT_IP_OVER_FC, 16, 24, 19, "IP_OVER_FC"},
#endif
#ifdef DLT_SUNATM
        {DLT_SUNATM, 4, 4 + 8, 4 + 3, "SUNATM"},
#endif
#ifdef DLT_ARCNET_LINUX
        {DLT_ARCNET_LINUX, 4, 8, 8, "ARCNET_LINUX"},
#endif
#ifdef DLT_ENC
        {DLT_ENC, 0, 12, 12, "ENC"},
#endif
#ifdef DLT_FRELAY
        {DLT_FRELAY, -1, 0, 0, "FRELAY"},
#endif
#ifdef DLT_IEEE802_11_RADIO
        {DLT_IEEE802_11_RADIO, 64 + 24, 64 + 32, 64 + 27, "IEEE802_11_RADIO"},
#endif
#ifdef DLT_PFLOG
        {DLT_PFLOG, 0, 28, 28, "PFLOG"},
#endif
#ifdef DLT_LINUX_IRDA
        {DLT_LINUX_IRDA, -1, -1, -1, "LINUX_IRDA"},
#endif
#ifdef DLT_APPLE_IP_OVER_IEEE1394
        {DLT_APPLE_IP_OVER_IEEE1394, 16, 18, 0, "APPLE_IP_OVER_IEEE1394"},
#endif
#ifdef DLT_IEEE802_11_RADIO_AVS
        {DLT_IEEE802_11_RADIO_AVS, 64 + 24, 64 + 32, 64 + 27, "IEEE802_11_RADIO_AVS"},
#endif
#ifdef DLT_PFSYNC
        {DLT_PFSYNC, -1, 4, 4, "PFSYNC"},
#endif
        {-1, -1, -1, -1, "UNKNOWN"}
};

//---------------------------------------------------------------------------------
void termination(int signal);
void pcap_callback(unsigned char *args, const struct pcap_pkthdr *hdr, const unsigned char *packet);
void PrintUsage(FILE *);

class NetFlow *Flow;

char *destination=NULL;
const char *dst_host=NULL;
unsigned short dst_port=20001;

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

int offset;
int datalink;
//---------------------------------------------------------------------------------
int main(int argc, char **argv){
      char *rule=NULL;
      char *interface=NULL;
      unsigned active=0,inactive=0,expired=0, promisc=1;
      
        u_char i;

        pcap_t *pcap;
        struct bpf_program pf;
        char errbuf[PCAP_ERRBUF_SIZE];

      int op;

      while((op=getopt(argc, argv, "hqpde:r:i:1:2:")) != EOF){
      switch(op){
            case 'h': PrintUsage(stdout);
                          exit(-1);
                          break;
            case 'd': debug=1;
                          break;
            case 'q': quiet=1;
                          break;
            case 'p': promisc=0;
                          break;
            case 'e': destination=(char *)malloc(strlen(optarg)+1);
                          strcpy(destination, optarg);
                          break;
            case 'r': rule=(char *)malloc(strlen(optarg)+1);
                          strcpy(rule, optarg);
                          break;
            case 'i': interface=(char *)malloc(strlen(optarg)+1);
                          strcpy(interface, optarg);
                          break;
            case '1': active=strtol(optarg, NULL, 10);
                          break;
            case '2': inactive=strtol(optarg, NULL, 10);
                          break;
            default: break;
            }
      }

      printf("FlowProbe 1.1 (c) 2002 Anton Vinokurov, anton@netams.com\n");
      printf("This is part of NeTAMS project, http://www.netams.com/ \n");

      if (!interface && !quiet) { PrintUsage(stderr); 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 (!rule) rule="ip";
      if (!active) active=10*60; // 1 min
      if (!inactive) inactive=1*60; // 10 min

      if (!quiet) {
            printf("Exporting to:\t%s:%d\n", dst_host, dst_port);
            printf("Interface:\t%s\n", interface);
            if(rule) printf("Rule:\t\t%s\n", rule);
            if(!promisc) printf("Promisc mode is off\n");
            printf("Active timeout:\t%d seconds\n", active);
            printf("Inact timeout:\t%d seconds\n", inactive);
      }

      signal(SIGINT, (sig_t)termination);
      signal(SIGSTOP, (sig_t)termination);
      signal(SIGTERM, (sig_t)termination);

      pcap = pcap_open_live(interface, MAX_PKT_SIZE, promisc, 1000, errbuf);
        if (!pcap) {
                printf( "failed to open pcap interface: %s\n", errbuf);
                exit(errno);
        }
#ifdef PCAP_NEED_POLL
      SET_POLL(pcap->fd);
#endif

        datalink = pcap_datalink(pcap);
        for (i = 0;; i++)
                if (dlt[i].linktype == datalink || dlt[i].linktype == -1) {
                        offset = dlt[i].offset_nl;
                        break;
                }
        if (!quiet) printf("Libpcap: %s\n", dlt[i].descr);

        if (rule) {
                if (-1 == pcap_compile(pcap, &pf, rule, 1, 0)) {
                        printf( "failed to compile pcap: %s\n", pcap_geterr(pcap));
                        exit(errno);
                }
                if (-1 == pcap_setfilter(pcap, &pf)) {
                        printf( "failed to setfilter pcap: %s\n", pcap_geterr(pcap));
                        exit(errno);
                }
#ifndef NETBSD
            pcap_freecode(&pf);
#endif
        } else
                printf("no rule for pcap, capturing all \n");


        Flow=new NetFlow(dst_host,dst_port);
        Flow->SetTimeouts(active,inactive,expired);

      if (!debug) {
            daemon(0, 1); 
            chdir(_PATH_VARTMP);
      }
      
      int status;

        while(1) {
#ifdef PCAP_NEED_POLL
                CHECK_POLL(status);
                if(!status) {
                        Flow->Expiresearch();
                        continue;
                }
#endif
                status = pcap_dispatch(pcap, 1, pcap_callback, NULL);
                if (status == -1) {
                        printf("pcap dispatch error: %s\n", pcap_geterr(pcap));
                        continue;
                }
#ifndef PCAP_NEED_POLL
                if(!status) {
                        Flow->Expiresearch();
                }
#endif
        }

}           
//---------------------------------------------------------------------------------
void pcap_callback(unsigned char *args, const struct pcap_pkthdr *hdr, const unsigned char *packet){
      
        u_short ether_type;
        struct ip *ip;

      Flow->Expiresearch();

        switch (datalink) {
#ifdef DLT_EN10MB
                case DLT_EN10MB:
                        register const struct ether_header *ep;
                        ep = (struct ether_header *)packet;
                        ether_type = ntohs(ep->ether_type);
                        packet += ETHER_HDR_LEN;
                        break;
#endif
#ifdef DLT_LINUX_SLL
                case DLT_LINUX_SLL:
                        if ( hdr->len < SLL_HDR_LEN) return;     /* This should never happened */

                        register const struct sll_header *sllp;
                        sllp = (struct sll_header *)packet;

                        ether_type = ntohs(sllp->sll_protocol);
                        if (ether_type <= ETHERMTU) return; /*We got LLC layer. I don't know if IP is possible at this level*/
                        packet += SLL_HDR_LEN;
                        break;
#endif
                default:
                        ether_type = 0xFFFF;
                        break;

        }

        if (ether_type != 0xFFFF) {
recurse:
                if (ether_type == ETHERTYPE_VLAN) {
                        ether_type = ntohs(*(u_int16_t *) (packet + 2));
                        packet += 4;
                        if (ether_type > ETHERMTU)
                                goto recurse;

                }
                if (ether_type != ETHERTYPE_IP) return;

                ip = (struct ip *)packet;
        } else
                ip = (struct ip *)(packet + offset);

        Flow->Processpacket(ip);
}

//---------------------------------------------------------------------------------
void termination(int signal){
      Flow->Status();
      delete Flow;
      exit(0);
}                   
//---------------------------------------------------------------------------------

void PrintUsage(FILE *f){
      fprintf(f, "Usage: flowprobe {options}\nwhere {options} are:\n \
      -h\t print help screen and exit\n\
      -q\t quiet output\n\
      -d\t debug output\n\
      -p\t turn off promisc mode\n\
      -e export_to\t IP address to export flows to\n\
      -r rule\t\t libpcap rule to capture packets\n\
      -i interface\t network interface to listen\n\
      -1 active_timeout\t active flow timeout (sec.)\n\
      -2 inactive_timeout\t inactive flow timeout (sec.)\n");
}
//---------------------------------------------------------------------------------
//---------------------------------------------------------------------------------
#else
#include <stdio.h>

int main() {
        printf("This is part of NeTAMS project, http://www.netams.com \n");
        printf("This software could be compiled only with libpcap enabled.\n");
}
#endif

Generated by  Doxygen 1.6.0   Back to index