Net-Connection-Sniffer

 view release on metacpan or  search on metacpan

Sniffer.xs  view on Meta::CPAN

    dusr	= newHV();
    init_hv(dusr,len);
    hv_store(stats,(char *)trgt.s,4,newRV_noinc((SV *)dusr),0);
  }
  if ((fetch_uv(dusr,"T")) < now) {
    dnsRflag = 1;
    av_push(dnsrequest,newSVpv((char *)trgt.s,4));
  }
}

MODULE = Net::Connection::Sniffer	PACKAGE = Net::Connection::Sniffer

PROTOTYPES: DISABLE

 # run, now, next, start 		I32
 # rate, bw				NV

 #	SVt_NULL,       /* 0 */
 #	SVt_IV,         /* 1 */
 #	SVt_NV,         /* 2 */
 #	SVt_RV,         /* 3 */
 #	SVt_PV,         /* 4 */
 #	SVt_PVIV,       /* 5 */
 #	SVt_PVNV,       /* 6 */
 #	SVt_PVMG,       /* 7 */
 #	SVt_PVBM,       /* 8 */
 #	SVt_PVLV,       /* 9 */
 #	SVt_PVAV,       /* 10 */
 #	SVt_PVHV,       /* 11 */
 #	SVt_PVCV,       /* 12 */
 #	SVt_PVGV,       /* 13 */
 #	SVt_PVFM,       /* 14 */
 #	SVt_PVIO        /* 15 */

void
p2xs_gvars(pnow, pstart, prate, pbw)
	SV	* pnow
	SV	* pstart
	SV	* prate
	SV	* pbw
  INIT:
	if (items != 4)
	  croak("Usage: Net::Connection::Sniffer::p2xs_gvars(pnow, pstart, prate, pbw)");

  CODE:
	now	= SvUV(pnow);
	nextp	= now;
	nextrate= 300;
	next	= now + nextrate;	/*	first increment is 5 minutes, following are different	*/
	start	= SvUV(pstart);
	rate	= SvNV(prate);
	bw	= SvNV(pbw);
	hup	= 0;
	ra	= 0;
	ba	= 0;

PROTOTYPES: ENABLE

void
xs2p_gvars()
  PPCODE:
	EXTEND(SP,4);
	PUSHs(sv_2mortal(newSVuv(now)));
	PUSHs(sv_2mortal(newSVuv(start)));
	PUSHs(sv_2mortal(newSVnv(rate)));
	PUSHs(sv_2mortal(newSVnv(bw)));
	XSRETURN(4);

void
xs_daemon_init(sniffer,hpref,dnsref,nhost,dnshost,port,listenon,bpfstr,dev,snaplen,promisc,to)
	SV	* sniffer
	SV	* hpref
	SV	* dnsref
	SV	* nhost
	SV	* dnshost
	int	port
	SV	* listenon
	char	* bpfstr
	char	* dev
	int	snaplen
	int	promisc
	int	to
    PREINIT:
	unsigned char * ip, * lip, * sniffp;
	STRLEN	len;
	char	errorbuf[PCAP_ERRBUF_SIZE+1];
	struct bpf_program real_fp;
    CODE:
	pktlen = snaplen;
	if (SvPOK(sniffer) == 0)
	  croak("sniffer is not a 'path' or 'STDERR'");

	if (! SvROK(hpref))
	  croak("stats is not a REF");
	if (SvTYPE(SvRV(hpref)) != SVt_PVHV)
	  croak("stats is not a hash REF");

	if (! SvROK(dnsref))
	  croak("dnslookup is not REF");
	if (SvTYPE(SvRV(dnsref)) != SVt_PVAV)
	  croak("dnslookup is not an array REF");

	if (SvPOK(nhost) == 0)
	  croak("nhost is not a netaddr");
	ip = (u_char *)SvPV(nhost,len);
	if (len != 4)
	  croak("nhost length of netaddr length is %d, should be 4", len);
	strncpy((char *)me.s,(char *)ip,4);

	if (SvPOK(dnshost) == 0)
	  croak("dnshost is not a netaddr");
	ip = (u_char *)SvPV(dnshost,len);
	if (len != 4)
	  croak("dnshost length of netaddr length is %d, should be 4", len);
	bzero(&dnsaddr.sa,socklen);
	dnsaddr.si.sin_family = PF_INET;
	dnsaddr.si.sin_addr.s_addr = *((unsigned long *)ip);
	dnsaddr.si.sin_port = htons(53);

	if ((dnsFD = socket(PF_INET,SOCK_DGRAM,0)) < 0)
	  croak("could not open name server socket");

Sniffer.xs  view on Meta::CPAN

#define PRINT_dumptxt	5
#define CLOSE_wFD	6
#define WAS_PURGE	7
#define TERMINATE	8

int
_enter_constants(...)
    ALIAS:
	Net::Connection::Sniffer::INITIALIZE	= 0
	Net::Connection::Sniffer::SEND_dns	= 1
	Net::Connection::Sniffer::SEND_listen	= 2
	Net::Connection::Sniffer::INIT_wFD	= 3
	Net::Connection::Sniffer::RECV_dns	= 4
	Net::Connection::Sniffer::PRINT_dumptxt	= 5
	Net::Connection::Sniffer::CLOSE_wFD	= 6
	Net::Connection::Sniffer::WAS_PURGE	= 7
	Net::Connection::Sniffer::TERMINATE	= 8
    CODE:
	RETVAL = ix;
    OUTPUT:
	RETVAL

 #
 #	first return value indicates 		args
 #	the requested perl run operation
 #	0	end, run is zero
 #	1	listen interrupt		now, sender.naddr, message received
 #	2	dnslookup
 #	3	dump request			hup, init
 #	4	dns receive			len, buffer
 #	5	purge interrupt -- dns alarm is checked here in Perl
 #
#define END_RUN		0
#define LISTEN_MSG	1
#define DNS_NEEDED	2
#define DUMP_REQUEST	3
#define DNS_RECEIVE	4
#define PURGE		5

int
_exit_constants()
    ALIAS:
	Net::Connection::Sniffer::END_RUN	= 0
	Net::Connection::Sniffer::LISTEN_MSG	= 1
	Net::Connection::Sniffer::DNS_NEEDED	= 2
	Net::Connection::Sniffer::DUMP_REQUEST	= 3
	Net::Connection::Sniffer::DNS_RECEIVE	= 4
	Net::Connection::Sniffer::PURGE		= 5
    CODE:
	RETVAL = ix;
    OUTPUT:
	RETVAL

void
xs_while(vector,...)
	int	vector
    PREINIT:
	unsigned char * buf;
	STRLEN	len;
	int	dnslen, listenlen;
    PPCODE:
	switch(vector)
	{
	case SEND_dns	:	
		if (av_len(dnsrequest) < 0) {
		  dnsRflag = 0;
		  av_undef(dnsrequest);
		}
		buf = (unsigned char *)SvPV(ST(1),len);
		sendto(dnsFD,buf,len,0,&dnsaddr.sa,socklen);
		break;
	case WAS_PURGE	:
		break;
	case PRINT_dumptxt :
		buf = (unsigned char *)SvPV(ST(1),len);
		my_dump((char *)buf,len);
		break;
	case SEND_listen :
		if (SvPOK(ST(1)) == 0)
		  break;
		buf = (unsigned char *)SvPV(ST(1),len);
		sendto(lFD,buf,len,0,&sender.sa,socklen);
	case INIT_wFD	:
		signal_dump = 0;
		if (SvIOK(ST(2)) == 0)
		  croak("arg2 is not a boolean 0/1");
		if (SvIV(ST(2)) != 0) {
		  if (dumptofile) {
		    WFD = fopen(tmp,"w");
		  }
		  wFD = fileno(WFD);
		  dump_head = 1;
		  nleft = 0;
		}
		break;
	case CLOSE_wFD	:
		if (dumptofile != 0) {
 #		  fsync(wFD);
		  while(1) {
		    if (close(wFD) < 0) {
		      if (errno == EINTR)
			continue;		/*	try again	*/
		      break;			/*	else fatal	*/
		    } else
		      rename(tmp,filepath);
		    break;
		  }
		}
		wFD = 0;
		break;
	case INITIALIZE	:
		run = SvIV(ST(1));
		ra = 0;
		ba = 0;
		maxfd = dnsFD + 1;
		if (lFD != 0 && lFD >= maxfd)
		  maxfd = lFD +1;
		if (pFD >= maxfd)
		  maxfd = pFD +1;
		max = maxfd;
		FD_ZERO(&rset);

Sniffer.xs  view on Meta::CPAN

	  }

	DNSCHECK:
	  if (FD_ISSET(dnsFD,&rset)) {
	    dnslen = recv(dnsFD,out.s,512,0);
	    if (dnslen > 0) {
	      EXTEND(SP,3);
	      PUSHs(sv_2mortal(newSViv(DNS_RECEIVE)));
	      PUSHs(sv_2mortal(newSViv(dnslen)));
	      PUSHs(sv_2mortal(newSVpv((char *)out.s,dnslen)));
	      XSRETURN(3);
	    }
	  }

	WFDCHECK:
	  if (wFD != 0 && FD_ISSET(wFD,&wset) && dumpmore() == 0) {
	    EXTEND(SP,3);
	    PUSHs(sv_2mortal(newSViv(DUMP_REQUEST)));
	    PUSHs(sv_2mortal(newSViv(hup)));
	    PUSHs(sv_2mortal(newSViv(dump_head)));
	    dump_head = 0;
	    XSRETURN(3);
	  }

	TIMECHECK:
	  if (now > nextp) {		/* purge once a second			*/
	TIMEFORCE:
	    nextp = now;
	    if (run > 0)
	      run--;
	    if (wFD != 0)
	      signal_dump = 0;
	    EXTEND(SP,3);
	    PUSHs(sv_2mortal(newSViv(PURGE)));
	    PUSHs(sv_2mortal(newSViv(now)));
	    PUSHs(sv_2mortal(newSViv(signal_dump)));
	    XSRETURN(3);
	  }
	}
	closeMOST();
	if (wFD != 0 && dumptofile != 0)
	  close(wFD);
	pcap_close(pcap);
	XPUSHs(sv_2mortal(newSViv(END_RUN)));
	XSRETURN(1);

 # ############## THIS STUFF IS FOR TESTING ONLY!

void
inc_sv(hpp,key)
	SV	* hpp
	char	* key
  ALIAS:
	Net::Connection::Sniffer::fetch_uv = 1
  PREINIT:
	HV	* hp;
  INIT:
	if (SvTYPE(SvRV(hpp)) != SVt_PVHV)
	  croak("hp is not a hash REF");
	hp = (HV *)SvRV(hpp);
  PPCODE:
	if (ix == 1) {
	  XPUSHs(sv_2mortal(newSVuv(fetch_uv(hp,key))));
	  XSRETURN(1);
	} else
	  inc_sv(hp,key);

void
set_uv(hpp,key,vp)
	SV	* hpp
	char	* key
	SV	* vp
  ALIAS:
	Net::Connection::Sniffer::set_nv = 2
	Net::Connection::Sniffer::add_nv = 1
  PREINIT:
	HV	* hp;
	u_int32_t	val32;
	double	valnv;
  INIT:
	if (SvTYPE(SvRV(hpp)) != SVt_PVHV)
	  croak("hp is not a hash REF");
	hp = (HV *)SvRV(hpp);
  CODE:
	if (ix == 2) {
	  valnv = SvNV(vp);
	  set_nv(hp,key,valnv);
	} else {
	  val32 = SvUV(vp);
	  if (ix == 1)
	    add_nv(hp,key,val32);
	  else
	    set_uv(hp,key,val32);
	}

void
aEQaPLUSbXm(hpp,key1,key2,multi)
	SV	* hpp
	char	* key1
	char	* key2
	NV	multi
  PREINIT:
	HV	* hp;
  INIT:
	if (SvTYPE(SvRV(hpp)) != SVt_PVHV)
	  croak("hp is not a hash REF");
	hp = (HV *)SvRV(hpp);
  CODE:
	aEQaPLUSbXm(hp,key1,key2,multi);

void
init_hv(hpp,len)
	SV	* hpp
	I32	len
  PREINIT:
	HV	* hp;
  INIT:
	if (SvTYPE(SvRV(hpp)) != SVt_PVHV)
	  croak("hp is not a hash REF");
	hp = (HV *)SvRV(hpp);
  CODE:



( run in 0.831 second using v1.01-cache-2.11-cpan-5511b514fd6 )