NetAddr-IP

 view release on metacpan or  search on metacpan

Lite/Util/Util.xs  view on Meta::CPAN

	}
	tmp = bcd8 & 0x80000000;	/*	propagated carry	*/
	bcd8 <<= 1;			/*	x 2			*/
	if (carry)
	  bcd8 += 1;
	n->bcd[i] = bcd8;
	carry = tmp;
      }
    }
  }
  netswap(n->bcd,5);
  return 20;
}

/*	convert a bcd number string to a bcd text string
	returns the number of digits
 */
int
_bcd2txt(unsigned char * bcd2p, BCD * n)
{
  register unsigned char bcd, dchar;
  int	i, j = 0;

  for (i=0;i<20;i++) {
    dchar = *(bcd2p + i);
    bcd = dchar >> 4;
    if (j || bcd) {
      n->txt[j] = bcd + zero;
      j++;
    }
    bcd = dchar & 0xF;
    if (j || bcd || i == 19) {		/* must be at least one digit	*/
      n->txt[j] = bcd + zero;
      j++;
    }
  }
  n->txt[j] = 0;				/* string terminator	*/
  return j;
}

/*	INCLUDE: xs_include/miniSocket.inc	removed 10-12-11	*/



MODULE = NetAddr::IP::Util    PACKAGE = NetAddr::IP::Util

PROTOTYPES: ENABLE

void
comp128(s,...)
	SV * s
ALIAS:
	NetAddr::IP::Util::ipv6to4 = 2
	NetAddr::IP::Util::shiftleft = 1
PREINIT:
	unsigned char * ap;
	char * subname;
	u_int32_t wa[4];
	STRLEN len;
	int i;
PPCODE:
	ap = (unsigned char *) SvPV(s,len);
	if (len != 16) {
	  if (ix == 2)
	    subname = is_ipv6to4;
	  else if (ix == 1)
	    subname = is_shiftleft;
	  else
	    subname = is_comp128;
	  croak("Bad arg length for %s%s, length is %d, should be %d",
		"NetAddr::IP::Util::",subname,len *8,128);
	}
	if (ix == 2) {
	  XPUSHs(sv_2mortal(newSVpvn((char *)(ap +12),4)));
	  XSRETURN(1);
	}
	else if (ix == 1) {
	  if (items < 2) {
	    memcpy(wa,ap,16);
	  }
	  else if ((i = SvIV(ST(1))) == 0) {
	    memcpy(wa,ap,16);
	  }
	  else if (i < 0 || i > 128) {
	    croak("Bad arg value for %s, is %d, should be 0 thru 128",
		"NetAddr::IP::Util::shiftleft",i);
	  }
	  else {
	    netswap_copy(wa,ap,4);
	    do {
		_128x2(wa);
		i--;
	    } while (i > 0);
	    netswap(wa,4);
	  }
	}
	else {
	  memcpy(wa,ap,16);
	  fastcomp128(wa);
	}
	XPUSHs(sv_2mortal(newSVpvn((char *)wa,16)));
	XSRETURN(1);

void
add128(as,bs)
	SV * as
	SV * bs
ALIAS:
	NetAddr::IP::Util::sub128 = 1
PREINIT:
	unsigned char * ap, *bp;
	char * subname;
	u_int32_t wa[4], wb[4];
	n128 a128;
	STRLEN len;
PPCODE:
	ap = (unsigned char *) SvPV(as,len);
	if (len != 16) {
    Bail:
	  if (ix == 1)
	    subname = is_sub128;
	  else
	    subname = is_add128;
	  croak("Bad arg length for %s%s, length is %d, should be %d",
		"NetAddr::IP::Util::",subname,len *8,128);
	}

	bp = (unsigned char *) SvPV(bs,len);
	if (len != 16) {
	  goto Bail;
	}
	netswap_copy(wa,ap,4);
	netswap_copy(wb,bp,4);
	if (ix == 1) {
	  fastcomp128(wb);
	  XPUSHs(sv_2mortal(newSViv((I32)adder128(wa,wb,&a128,1))));
	}
	else {
	  XPUSHs(sv_2mortal(newSViv((I32)adder128(wa,wb,&a128,0))));
	}
	if (GIMME_V == G_ARRAY) {
	  netswap(a128.u,4);
	  XPUSHs(sv_2mortal(newSVpvn((char *)a128.c,16)));
	  XSRETURN(2);
	}
	XSRETURN(1);

void
addconst(s,cnst)
	SV * s
	I32 cnst
PREINIT:
	n128 a128;
	unsigned char * ap;
	u_int32_t wa[4], wb[4];
	STRLEN len;
PPCODE:
	ap = (unsigned char *) SvPV(s,len);
	if (len != 16) {
	  croak("Bad arg length for %s, length is %d, should be %d",
		"NetAddr::IP::Util::addconst",len *8,128);
	}
	netswap_copy(wa,ap,4);
	XPUSHs(sv_2mortal(newSViv((I32)addercon(wa,wb,&a128,cnst))));
	if (GIMME_V == G_ARRAY) {
	  netswap(a128.u,4);
	  XPUSHs(sv_2mortal(newSVpvn((char *)a128.c,16)));
	  XSRETURN(2);
	}
	XSRETURN(1);


int
hasbits(s)
	SV * s
PREINIT:
	unsigned char * bp;
	char * subname;
	STRLEN len;
CODE:
	bp = (unsigned char *) SvPV(s,len);
	if (len != 16) {
	  subname = is_hasbits;
	  croak("Bad arg length for %s%s, length is %d, should be %d",
		"NetAddr::IP::Util::",subname,len *8,128);
	}
	RETVAL = have128(bp);
OUTPUT:
	RETVAL

void
bin2bcd(s)
	SV * s
ALIAS:
	NetAddr::IP::Util::bcdn2txt = 2
	NetAddr::IP::Util::bin2bcdn = 1
PREINIT:
	BCD n;
	unsigned char * cp;
	STRLEN	len;
PPCODE:
	cp = (unsigned char *) SvPV(s,len);
	if (ix == 0) {
	  if (len != 16) {
	    croak("Bad arg length for %s, length is %d, should be %d",
		"NetAddr::IP::Util::bin2bcd",len *8,128);
	  }
	  (void) _bin2bcd(cp,&n);
	  XPUSHs(sv_2mortal(newSVpvn((char *)n.txt,_bcd2txt((unsigned char *)n.bcd,&n))));
	}
	else if (ix == 1) {
	  if (len != 16) {
	    croak("Bad arg length for %s, length is %d, should be %d",
		"NetAddr::IP::Util::bin2bcdn",len *8,128);
	  }
	  XPUSHs(sv_2mortal(newSVpvn((char *)n.bcd,_bin2bcd(cp,&n))));
	}
	else {
	  if (len > 20) {
	    croak("Bad arg length for %s, length is %d, should %d digits or less",
		"NetAddr::IP::Util::bcdn2txt",len *2,40);
	  }
	  XPUSHs(sv_2mortal(newSVpvn((char *)n.txt,_bcd2txt(cp,&n))));
	}
	XSRETURN(1);

#*
#* the second argument 'len' is the number of bcd digits for
#* the bcdn2bin conversion. Pack looses track of the number
#* digits so this is needed to do the "right thing".
#* NOTE: that simple_pack always returns 40 digits
#*
void
bcd2bin(s,...)
	SV * s
ALIAS:
	NetAddr::IP::Util::bcdn2bin = 2
	NetAddr::IP::Util::simple_pack = 1
PREINIT:
	BCD n;
	n128 c128, a128;
	unsigned char * cp, badc;
	char * subname;
	STRLEN len;
PPCODE:
	cp = (unsigned char *) SvPV(s,len);
	if (len > 40) {
	  if (ix == 0)
	    subname = is_bcd2bin;
	  else if (ix ==1)
	    subname = is_simple_pack;
    Badigits:
	  croak("Bad arg length for %s%s, length is %d, should be %d digits or less",
		"NetAddr::IP::Util::",subname,len,40);
	}
	if (ix == 2) {
	  if (len > 20) {
	    len <<= 1;		/*	times 2	*/
	    subname = is_bcdn2bin;
	    goto Badigits;
	  }
	  if (items < 2) {
	    croak("Bad usage, should have %s('packedbcd,length)",
		"NetAddr::IP::Util::bcdn2bin");
	  }
	  len = SvIV(ST(1));
	  _bcdn2bin(cp,&a128,&c128,(int)len);
	  netswap(a128.u,4);
	  XPUSHs(sv_2mortal(newSVpvn((char *)a128.c,16)));
	  XSRETURN(1);
	}
	badc = _simple_pack(cp,(int)len, &n);
	if (badc) {
	  if (ix == 1)
	    subname = is_simple_pack;
	  else
	    subname = is_bcd2bin;
	  croak("Bad char in string for %s%s, character is '%c', allowed are 0-9",
		"NetAddr::IP::Util::",subname,badc);
	}
	if (ix == 0) {
	  _bcdn2bin((void *)n.bcd,&a128,&c128,40);
	  netswap(a128.u,4);
	  XPUSHs(sv_2mortal(newSVpvn((char *)a128.c,16)));
	}
	else {	/*	ix == 1	*/
	  XPUSHs(sv_2mortal(newSVpvn((char *)n.bcd,20)));
	}
	XSRETURN(1);

void
notcontiguous(s)
	SV * s
PREINIT:
	unsigned char * ap, count;
	u_int32_t wa[4];
	STRLEN len;
PPCODE:
	ap = (unsigned char *) SvPV(s,len);
	if (len != 16) {
	  croak("Bad arg length for %s, length is %d, should be %d",
		"NetAddr::IP::Util::countbits",len *8,128);
	}
	netswap_copy(wa,ap,4);
	count = _countbits(wa);
	XPUSHs(sv_2mortal(newSViv((I32)have128(wa))));
	if (GIMME_V == G_ARRAY) {
	  XPUSHs(sv_2mortal(newSViv((I32)count)));
	  XSRETURN(2);
	}
	XSRETURN(1);

void
ipv4to6(s)
	SV * s
ALIAS:
	NetAddr::IP::Util::mask4to6 = 1
PREINIT:
	unsigned char * ip;
	char * subname;
	u_int32_t wa[4];
	STRLEN len;
PPCODE:
	ip = (unsigned char *) SvPV(s,len);
	if (len != 4) {
	  if (ix == 1)
	    subname = is_mask4to6;
	  else
	    subname = is_ipv4to6;
	  croak("Bad arg length for %s%s, length is %d, should be 32",
		"NetAddr::IP::Util::",subname,len *8);
	}
	if (ix == 0)
	  extendipv4(ip, wa);
	else
	  extendmask4(ip, wa);
	XPUSHs(sv_2mortal(newSVpvn((char *)wa,16)));
	XSRETURN(1);

void
ipanyto6(s)
	SV * s
ALIAS:
	NetAddr::IP::Util::maskanyto6 = 1
PREINIT:
	unsigned char * ip;
	char * subname;
	u_int32_t wa[4];
	STRLEN len;
PPCODE:
	ip = (unsigned char *) SvPV(s,len);
	if (len == 16)		/* if already 128 bits, return input	*/
	  XPUSHs(sv_2mortal(newSVpvn((char *)ip,16)));
	else if (len == 4) {
	  if (ix == 0)
	    extendipv4(ip, wa);
	  else
	    extendmask4(ip, wa);
	  XPUSHs(sv_2mortal(newSVpvn((char *)wa,16)));
	}
	else {
	  if (ix == 1)
	    subname = is_maskanyto6;
	  else
	    subname = is_ipanyto6;
	  croak("Bad arg length for %s%s, length is %d, should be 32 or 128",
		"NetAddr::IP::Util::",subname,len *8);
	}
	XSRETURN(1);



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