/*

    File: ftpp/scantool.cc

    Copyright (C) 2002  Dmitry Udalov
    Email: uddm@penza.net
  
    This software 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.
    
 */


#include "scantool.h"
#include "adbmtool.h"
#include "ftpproxy.h"

int fNSNeedUpdate=FALSE;//fNSNeedTerm=FALSE,
pcap_t *pcap;

int netscan();
void nssighandler(int iSigNo);

int scan(){
//    logex(0,"scan start");
    //set signal handlers
    struct sigaction act,oact;
    sigemptyset(&act.sa_mask);
    act.sa_flags=0;
    act.sa_handler=nssighandler;
    sigaction(SIGHUP,&act,&oact);
    sigaction(SIGSEGV,&act,&oact);
    sigaction(SIGKILL,&act,&oact);
    sigaction(SIGTERM,&act,&oact);
    sigaction(SIGPIPE,&act,&oact);
    sigaction(SIGINT,&act,&oact);
    //scan net while not SIGHUP received
    while(netscan()==TRUE){
        fNSNeedUpdate=FALSE;
    }
    return TRUE;
}

//scan netware
int netscan(){
    //load cfg
    if(getparam("NETINTERFACE",szNetInterface)==FALSE)
        strcpy(szNetInterface,NETINTERFACE);
    if(getparam("SCANFILTER",szScanFilter)==FALSE)
        strcpy(szScanFilter,SCANFILTER);

    char cBuf[PCAP_ERRBUF_SIZE];
    bpf_u_int32 SubNet,NetMask;
    struct bpf_program filter;
    //Set filter
    pcap=pcap_open_live(szNetInterface, BUF_SIZE, 1, 50 ,cBuf);
    if (pcap==NULL){
        logex(0,"pcap_openlive error, Interface: %s",szNetInterface);
        kill(getppid(),SIGTERM);
        return FALSE;
    }
    if (pcap_lookupnet(szNetInterface, &SubNet, &NetMask, cBuf)<0){
        logex(0,"pcap_lookupnet error");
        kill(getppid(),SIGTERM);
        return FALSE;
    }
    if (pcap_compile(pcap, &filter, szScanFilter, 1, NetMask)<0){
        logex(0,"pcap_compile error, filter: %s",szScanFilter);
        kill(getppid(),SIGTERM);
        return FALSE;
    }
    if (pcap_setfilter(pcap, &filter)<0){
        logex(0,"pcap_setfilter error");
        kill(getppid(),SIGTERM);
        return FALSE;
    }
    u_char* buf;
    struct pcap_pkthdr hdr;
    while(TRUE){
        if(fNSNeedUpdate==TRUE){//(fNSNeedTerm==TRUE)||
            break;
        }
        //get next packet
        buf = (u_char*)pcap_next(pcap, &hdr);
        if (!buf){
            continue;
        }
        struct ethhdr * eth;
        struct iphdr * ip;
        struct tcphdr * tcp;
        eth = (struct ethhdr*) (buf);
        ip  = (struct iphdr* ) (buf+ETH_H);
        tcp = (struct tcphdr*) (buf+ETH_H+IP_H);
        
        if (ntohs(eth->h_proto)!=ETH_P_IP){
	    return FALSE;
        }
        if (ip->protocol==IPPROTO_TCP){
//            struct in_addr srcip,dstip;
//            srcip.s_addr=ip->saddr,dstip.s_addr=ip->daddr;
//            printf("ADD %s,%s\n",inet_ntoa(srcip),inet_ntoa(dstip));
            char cbuf[STR_SIZE];
            sprintf(cbuf,"ADD %d,%d\n",ip->saddr,ip->daddr);
            //send request to adbm for save record
            sendtoadbm(cbuf);

            
//    	      int srcp = ntohs(tcp->source);
// 	      int dstp = ntohs(tcp->dest);
//            printf("\nSource port %d Dest port %d\n",srcp,dstp);
        }
    }
    pcap_close(pcap);
        return TRUE;
}

//signal handler
void nssighandler(int iSigNo){
    switch(iSigNo){
        case SIGHUP:
            pcap_close(pcap);
            fNSNeedUpdate=TRUE;
            break;
        case SIGPIPE:
            break;
        case SIGSEGV:
        case SIGKILL:
        case SIGTERM:
        case SIGINT:
            pcap_close(pcap);
            exit(0);
//            kill(getppid(),SIGTERM);
//            fNSNeedTerm=TRUE;
            break;
        default:
            break;
    }
    return;
}
