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 )