Net-DNS-ToolKit

 view release on metacpan or  search on metacpan

ToolKit.xs  view on Meta::CPAN

#ifdef USELOOPBACK
	mysa.sin_addr = inet_makeaddr(IN_LOOPBACKNET, 1);
#else
	mysa.sin_addr.s_addr = INADDR_ANY;
#endif
}

int
lchance()
{
#ifndef NO_RESOLV_CONF
  return 0;
#else
#ifdef lastchanceTEST
  my_res_state.options = RES_INIT;
  if (res_ninit(&my_res_state) != 0)		/* punt if we can not initialize resolver interface */
    return 0;
  return my_res_state.nscount;
#else
  memset(&my_res_state,0,sizeof(my_res_state));
  return get_nameservers(&my_res_state);
#endif
#endif
}

MODULE = Net::DNS::ToolKit	PACKAGE = Net::DNS::ToolKit

PROTOTYPES: DISABLE

 # include functions for inet_aton, inet_ntoa, dn_expand

INCLUDE: xs_include/dn_expand.inc

 # int dn_comp(unsigned char *exp_dn, unsigned char *comp_dn, 
 #	int length, unsigned char **dnptrs, unsigned char **lastdnptr);
 #
 # dn_comp
 #	dn_comp() compresses the domain name exp_dn and stores it in 
 #	the buffer comp_dn of length 'length'. The  compression  uses  
 #	an  array of pointers dnptrs to previously compressed names 
 #	in the current message.  The first pointer points to the 
 #	beginning of the message and the list ends with NULL.  The 
 #	limit  of  the  array  is specified  by  lastdnptr.  if dnptr 
 #	is NULL, domain names are not compressed.  If lastdnptr is 
 #	NULL, the list of labels is not updated.
 #

void
dn_comp(buffer, offset, name,...)
	SV * buffer
	int offset
	SV * name
    PROTOTYPE: $$$;@ 
    PREINIT:
	AV * dptr;
	SV **aptrs;
	STRLEN len, size, bsize;
	u_char **lastdnptr, **aoff;
	u_char * exp_dn, * msg, * comp_dn;
	int i, v, dnsize;
    PPCODE:
	if (! SvROK(buffer) || ! SvROK(name))
	    XSRETURN_EMPTY;

 # see: perlapi on 'svtype' and /usr/lib/perl5/i386-linux/CORE/sv.h

	name = SvRV(name);

	if (SvTYPE(name) == SVt_PVGV)		/* debugging, skip dn_comp	*/
	    exp_dn = (u_char *)SvPV(GvSV(name), len);
        if (SvPOK(name))                        /* normal	*/
	    exp_dn = (u_char *)SvPV(name, len);
	else					/* punt, not scalar or glob	*/
	    XSRETURN_EMPTY;

	buffer = SvRV(buffer);
	if (! SvPOK(buffer))
	    XSRETURN_EMPTY;

		# get the size of the buffer
	(void)SvPV(buffer,size);

	if (size != offset)			/* punt if it does not match offset	*/
	    XSRETURN_EMPTY;

		# add some space at the end of the string, get pointer
	msg = (u_char *)SvGROW(buffer, (STRLEN)(size + MAXDNAME));
	comp_dn = msg + offset;

		# setup dnptrs from outside or init them to zero
	dnsize = sizeof dnptrs/sizeof dnptrs[0];
	lastdnptr = dnptrs + dnsize;

	if (items > 3 && SvTRUE(ST(3)) && SvROK(ST(3))) {	/* defined, should be \@dnptrs	*/

	    dptr = (AV *)SvRV(ST(3));	/* array pointer	*/

		# external array must be exactly the same size as internal one
	    i = av_len(dptr);
	    if ( i != dnsize -1)
		XSRETURN_EMPTY;

	    for(i=0;i<dnsize;i++) {
		aptrs = av_fetch(dptr,i,0);
		if (aptrs == NULL)	/* should never happen	*/
		    XSRETURN_EMPTY;

		v = SvIV(*aptrs);
		if (i == 0 || v)
		    dnptrs[i] = msg + v;
		else
		    dnptrs[i] = NULL;
	    }
	} else {
	    memset(dnptrs,0,sizeof(dnptrs));
	    dnptrs[0] = msg;
	}

	if (SvTYPE(name) == SVt_PVGV)
	    dnptrs[0] = NULL;			/* do not compress	*/
	len = dn_comp((char *)exp_dn,comp_dn,MAXDNAME,dnptrs,lastdnptr);

		# set the string length to the new real length	
	SvCUR_set(buffer, (I32)(size + len));

	EXTEND(SP, dnsize + 1);
	PUSHs(sv_2mortal(newSViv(size + len )));
	for(i=0;i<dnsize;i++) {
	    if (dnptrs[i] == NULL)
		PUSHs(sv_2mortal(newSViv(0)));
	    else
		PUSHs(sv_2mortal(newSViv(dnptrs[i] - msg)));
	}
	XSRETURN(dnsize + 1);

 # return the header values
 # ID, QR, Opcode, AA, TC, RD, RA, MBZ, AD, CD, RCODE, QDCOUNT, ANCOUNT, NSCOUNT, ARCOUNT

void
gethead(header)
	SV * header
    PROTOTYPE: $
    PREINIT:
	STRLEN len;
	MY_HEADER * hp;
    PPCODE:
	if (! SvROK(header))
	    XSRETURN_EMPTY;

	hp = (MY_HEADER *)SvPV(SvRV(header),len);
	EXTEND(SP, 16);
	PUSHs(sv_2mortal(newSViv(NS_HFIXEDSZ)));
	PUSHs(sv_2mortal(newSViv(ntohs(hp->id))));
	PUSHs(sv_2mortal(newSViv(hp->qr)));
	PUSHs(sv_2mortal(newSViv(hp->opcode)));
	PUSHs(sv_2mortal(newSViv(hp->aa)));
	PUSHs(sv_2mortal(newSViv(hp->tc)));
	PUSHs(sv_2mortal(newSViv(hp->rd)));
	PUSHs(sv_2mortal(newSViv(hp->ra)));
	PUSHs(sv_2mortal(newSViv(hp->z)));
	PUSHs(sv_2mortal(newSViv(hp->ad)));
	PUSHs(sv_2mortal(newSViv(hp->cd)));
	PUSHs(sv_2mortal(newSViv(hp->rcode)));
	PUSHs(sv_2mortal(newSViv(ntohs(hp->qdcount))));
	PUSHs(sv_2mortal(newSViv(ntohs(hp->ancount))));
	PUSHs(sv_2mortal(newSViv(ntohs(hp->nscount))));
	PUSHs(sv_2mortal(newSViv(ntohs(hp->arcount))));
	XSRETURN(16);

void
parse_char(ch)
	unsigned char ch
    PROTOTYPE: $
    PREINIT:
	u_char bmask[] = {128,64,32,16,8,4,2,1};
	unsigned int i, hi, lo, tens[] = {1000,100,10,1, 1000,100,10,1};
	char out[15];
    PPCODE:
	hi = lo = 0;
	for(i=0;i<4;i++) {
	  if (ch & bmask[i])
		hi += tens[i];
	}
	for(i=4;i<8;i++) {
	  if (ch & bmask[i])
		lo += tens[i];
	}
	EXTEND(SP,4);
	sprintf(out,"%04d_%04d",hi,lo);
	PUSHs(sv_2mortal(newSVpv(out,0)));
	i = (int)ch;
	sprintf(out,"0x%02X",i);
	PUSHs(sv_2mortal( newSVpv(out,0)));
	sprintf(out,"%3d",i);
	PUSHs(sv_2mortal(newSVpv(out,0)));
	if (i < 0x20 || i > 0x7E) {
	    sprintf(out,"%s","");
	    PUSHs(sv_2mortal(newSVpv(out,0)));
	} else {
	    sprintf(out,"%c",ch);
	    PUSHs(sv_2mortal(newSVpv(out,0)));
	}
	XSRETURN(4);

unsigned char
get1char(buffer,off)
	SV * buffer
	unsigned int off
    PROTOTYPE: $$
    PREINIT:
	STRLEN size;
	unsigned char * cp;
    CODE:
	if (!SvROK(buffer))	/* not a pointer	*/
	    XSRETURN_UNDEF;

	cp = (u_char *)(SvPV(SvRV(buffer),size) + off);

	if (size <= off)	/* offset beyond end	*/
	    XSRETURN_UNDEF;

	RETVAL = *cp;
    OUTPUT:
	RETVAL

void
getstring(buffer,off,len)
	SV * buffer
	unsigned int off
	unsigned int len
    PROTOTYPE: $$$
    PREINIT:
	STRLEN size;
	unsigned char * cp;
	SV * out;
    PPCODE:
	if (!SvROK(buffer))	/* not a pointer	*/
	    XSRETURN_EMPTY;

	cp = (u_char *)(SvPV(SvRV(buffer),size) + off);

	if (off + len > size)	/* offset beyond end	*/
	    XSRETURN_EMPTY;

	out = sv_newmortal();
	sv_setpvn(out, (char *)cp, len );
	XPUSHs(out);
	if (GIMME_V == G_ARRAY) {
	    XPUSHs(sv_2mortal(newSViv(off + len)));
	    XSRETURN(2);
	}
	    XSRETURN(1);

unsigned int
putstring(buffer,off,string)
	SV * buffer
	unsigned int off
	SV * string
    PROTOTYPE: $$$
    PREINIT:
	SV * buf;
	STRLEN size, len;
	unsigned char * cp, * bp;
    CODE:
	if (!SvROK(buffer))	/* not a pointer	*/
	    XSRETURN_UNDEF;

	if (!SvROK(string))	/* not a pointer	*/
	    XSRETURN_UNDEF;

	buf = SvRV(buffer);

	(void)SvPV(buf,size);

	if (off > size)		/* not a valid offset	*/
	    XSRETURN_UNDEF;

	cp = (u_char *)SvPV(SvRV(string),len);

	if (off + len > MAXDNAME)	/* too big to add	*/
	    XSRETURN_UNDEF;

	if (off < size)
	    SvCUR_set(buf,off);

	sv_catpvn(buf, (char *)cp, len);

	SvCUR_set(buf, (I32)(off + len));
	RETVAL = off + len;
    OUTPUT:
	RETVAL

 # void
 # get32
void
get16(buffer,off)
	SV * buffer
	unsigned int off
    ALIAS:
	Net::DNS::ToolKit::get32 = 1
    PREINIT:
	SV * out;
	STRLEN size;
	u_char * cp;
    PPCODE:
	if (GIMME_V == G_VOID)
	    XSRETURN_UNDEF;		/* punt, nothing to return	*/

	if (!SvROK(buffer)) {
	bail:
	    if (GIMME_V != G_ARRAY)
		XSRETURN_UNDEF;
	    else
		XSRETURN_EMPTY;
	}
	cp = (u_char *)(SvPV(SvRV(buffer),size) + off);

	if (ix) {
	    off += NS_INT32SZ;
	    if (off > size)			/* punt if pointing beyond end of buff	*/
		goto bail;
	    XPUSHs(sv_2mortal(newSViv(gint32(cp))));
	} else {
	    off += NS_INT16SZ;
	    if (off > size)			/* punt if pointing beyond end of buff	*/
		goto bail;
	    XPUSHs(sv_2mortal(newSViv(gint16(cp))));
	}
	if (GIMME_V == G_ARRAY) {
	    XPUSHs(sv_2mortal(newSViv(off)));
	    XSRETURN(2);
	}
	    XSRETURN(1);

 # void
 # put1char, put32
unsigned int
put16(buffer,off,val_long)
	SV * buffer
	unsigned int off
	SV * val_long
    ALIAS:
	Net::DNS::ToolKit::put32 = 1
	Net::DNS::ToolKit::put1char = 2
    PREINIT:
	STRLEN size;
	U32 val;
	unsigned int i, ns_size = NS_INT16SZ;
	u_char c, * cp, blank[NS_INT32SZ];
    CODE:
	if (!SvROK(buffer))
	    XSRETURN_UNDEF;

	buffer = SvRV(buffer);
 	(void)SvPV(buffer,size);			/* get size of buffer	*/

	if (off > size)					/* punt if pointing beyond end of buff	*/
	    XSRETURN_UNDEF;

	val = SvUV(val_long);

	if (ix == 1)
	    ns_size = NS_INT32SZ;
	else if (ix == 2) {
	    if (val > 255)
		XSRETURN_UNDEF;
		ns_size = 1;
		c = (u_char)val;
	}
	else {
	    if (val > 65535)
		XSRETURN_UNDEF;
	    i = (unsigned int)val;
	}

	if (off + ns_size > size)			/* add space at end if needed	*/
	    sv_catpvn(buffer,(char *)blank,ns_size);

	cp = (u_char *)(SvPV(buffer,size) + off);

	if (ix == 1)
	    gput32(cp,val);
	else if (ix == 2)
	    *cp = c;
	else
	    gput16(cp,i);

	RETVAL = off + ns_size;
    OUTPUT:
	RETVAL

void
getIPv4(buffer,off)
	SV * buffer
	unsigned int off
    PREINIT:
	SV * netaddr;
	STRLEN size;
	u_char * cp, out[NS_INADDRSZ];
    PPCODE:
	if (GIMME_V == G_VOID)
	    XSRETURN_UNDEF;		/* punt, nothing to return	*/

	if (!SvROK(buffer)) {
	bail:
	    if (GIMME_V != G_ARRAY)
		XSRETURN_UNDEF;
	    else
		XSRETURN_EMPTY;
	}
	cp = (u_char *)(SvPV(SvRV(buffer),size) + off);

	off += NS_INADDRSZ;
	if (off > size)			/* punt if pointing beyond end of buff	*/
	    goto bail;
	
	netaddr = sv_newmortal();
	sv_setpvn(netaddr, (char *)cp, NS_INADDRSZ );
	XPUSHs(netaddr);
	if (GIMME_V == G_ARRAY) {
	    XPUSHs(sv_2mortal(newSViv( off)));
	    XSRETURN(2);
	}
	    XSRETURN(1);

unsigned int
putIPv4(buffer,off,netaddr)
	SV * buffer
	unsigned int off
	unsigned char * netaddr
    PREINIT:
	STRLEN size, discard;
	u_char * cp, blank[NS_INADDRSZ];
    CODE:
	if (!SvROK(buffer))
	    XSRETURN_UNDEF;

	buffer = SvRV(buffer);
 	(void)SvPV(buffer,size);			/* get size of buffer	*/

	if (off > size)					/* punt if pointing beyond end of buff	*/
	    XSRETURN_UNDEF;

	if (off + NS_INADDRSZ > size)
	    sv_catpvn(buffer,(char *)blank,NS_INADDRSZ);	/* extend buffer if needed	*/

	cp = (u_char *)(SvPV(buffer, discard) + size);

	memcpy(cp,netaddr,NS_INADDRSZ);

	RETVAL = (int)(size + NS_INADDRSZ);
    OUTPUT:
	RETVAL

void
getIPv6(buffer,off)
	SV * buffer
	unsigned int off
    PREINIT:
	SV * ipv6addr;
	STRLEN size;
	u_char * cp, out[NS_IN6ADDRSZ];
    PPCODE:
	if (GIMME_V == G_VOID)
	    XSRETURN_UNDEF;		/* punt, nothing to return	*/

	if (!SvROK(buffer)) {
	bail:
	    if (GIMME_V != G_ARRAY)
		XSRETURN_UNDEF;
	    else
		XSRETURN_EMPTY;
	}
	cp = (u_char *)(SvPV(SvRV(buffer),size) + off);

	off += NS_IN6ADDRSZ;
	if (off > size)			/* punt if pointing beyond end of buff	*/
	    goto bail;
	
	ipv6addr = sv_newmortal();
	sv_setpvn(ipv6addr, (char *)cp, NS_IN6ADDRSZ );
	XPUSHs(ipv6addr);
	if (GIMME_V == G_ARRAY) {
	    XPUSHs(sv_2mortal(newSViv( off)));
	    XSRETURN(2);
	}
	    XSRETURN(1);

unsigned int
putIPv6(buffer,off,ipv6addr)
	SV * buffer
	unsigned int off
	unsigned char * ipv6addr
    PREINIT:
	STRLEN size, discard;
	u_char * cp, blank[NS_IN6ADDRSZ];
    CODE:
	if (!SvROK(buffer))
	    XSRETURN_UNDEF;

	buffer = SvRV(buffer);
	(void)SvPV(buffer,size);			/* get size of buffer	*/

	if (off > size)					/* punt if pointing beyond end of buff	*/
	    XSRETURN_UNDEF;

	if (off + NS_IN6ADDRSZ > size)
	    sv_catpvn(buffer,(char *)blank,NS_IN6ADDRSZ);	/* extend buffer if needed	*/

	cp = (u_char *)(SvPV(buffer, discard) + size);

	memcpy(cp,ipv6addr,NS_IN6ADDRSZ);

	RETVAL = (int)(size + NS_IN6ADDRSZ);
    OUTPUT:
	RETVAL

void
gettimeofday()
    PREINIT:
	SV * tmp;				/* older perl does not know about newSVuv */
    PPCODE:
	if (gettimeofday(&tv,NULL)) {		/* any error	*/
	    if (GIMME_V == G_ARRAY)
		XSRETURN_EMPTY;
	    else
		XSRETURN_UNDEF;
	}
	tmp = newSViv(tv.tv_sec);
	sv_setuv(tmp,tv.tv_sec);
	XPUSHs(sv_2mortal(tmp));
	if (GIMME_V == G_ARRAY) {
	    tmp = newSViv(tv.tv_usec);
	    sv_setuv(tmp,tv.tv_usec);
	    XPUSHs(sv_2mortal(tmp));
	    XSRETURN(2);
	}
	XSRETURN(1);

void
get_default()
    PPCODE:
	mysin();
	XPUSHs(sv_2mortal(newSVpvn((char *)&mysa.sin_addr, NS_INADDRSZ)));
	XSRETURN(1);

void
get_path()
    PREINIT:
	SV * out;
    PPCODE:
	if (path == NULL)
	    XSRETURN_UNDEF;
	out = sv_newmortal();
	sv_setpvn(out, path, (STRLEN)pathz);    
	XPUSHs(out);
	XSRETURN(1);

void
lastchance()
    PREINIT:
	int i, nscount;
	u_char * netptr;
    PPCODE:
	if ((nscount = lchance()) < 1) {
	    if (GIMME_V != G_ARRAY)
		XSRETURN_UNDEF;
	    else
		XSRETURN_EMPTY;
	}
	if (GIMME_V != G_ARRAY)
	    nscount = 1;

	for(i=0;i<nscount;i++) {
	    netptr = ns_ptr(i); 
	    XPUSHs(sv_2mortal(newSVpvn((char *)netptr, NS_INADDRSZ)));
	}
	XSRETURN(nscount);



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