/*
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005 Yokogawa Electric Corporation,
* YDC Corporation, IPA (Information-technology Promotion Agency, Japan).
* All rights reserved.
*
* Redistribution and use of this software in source and binary forms, with
* or without modification, are permitted provided that the following
* conditions and disclaimer are agreed and accepted by the user:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the names of the copyrighters, the name of the project which
* is related to this software (hereinafter referred to as "project") nor
* the names of the contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* 4. No merchantable use may be permitted without prior written
* notification to the copyrighters. However, using this software for the
* purpose of testing or evaluating any products including merchantable
* products may be permitted without any notification to the copyrighters.
*
*
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHTERS, THE PROJECT AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING
* BUT NOT LIMITED THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHTERS, THE PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT,STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*
* $TAHI: v6eval/lib/Pz/PvOctets.cc,v 1.46 2005/05/09 09:35:24 akisada Exp $
*/
#include "PvOctets.h"
#include "RObject.h"
#include "WObject.h"
#include "ItPosition.h"
#include "PvIfName.h"
#include "PControl.h"
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#if defined(__FreeBSD__)
#include <net/if.h>
#include <netinet/if_ether.h>
#include <net/ethernet.h>
/*
extern "C" {
char *ether_ntoa __P((const struct ether_addr *));
struct ether_addr *ether_aton __P((const char *));
int ether_ntohost __P((char *, const struct ether_addr *));
int ether_hostton __P((const char *, struct ether_addr *));
int ether_line __P((const char *, struct ether_addr *, char *));
}
*/
#endif
#include <string.h>
PvOctets::~PvOctets() {
if(allocated_!=0) {
delete [] buffer_; allocated_=0;}
buffer_=0;}
PvOctets::PvOctets():PvObject(),allocated_(0),length_(0),buffer_(0) {}
PvOctets::PvOctets(const PvOctets& o):PvObject(o),allocated_(0),length_(0),buffer_(0) {
uint32_t l=o.length();
length_=l;
OCTSTR s=(OCTSTR)o.string();
if(o.allocated_==0) {buffer_=s;}
else {
buffer_=new octet[allocated_=l];
memcpy(buffer_,s,l);}}
PvOctets::PvOctets(uint32_t l,OCTSTR o,bool b):allocated_(0),length_(l),buffer_(o) {
if(b||(buffer_==0&&l>0)) {buffer_=new octet[allocated_=l];}
if(o!=0&&o!=buffer_) {memcpy(buffer_,o,l);}}
PvObject* PvOctets::shallowCopy() const {
return new PvOctets(length(),(OCTSTR)string());}
OCTSTR PvOctets::buffer(uint32_t n) {
uint32_t l=length();
if(n>l) {abort();}
if(buffer_==0&&l>0) {buffer_=new octet[allocated_=l];}
return buffer_+n;}
bool PvOctets::isEqual(const PvOctets* o) const {
uint32_t ml=length();
uint32_t ol=o->length();
return (ml==ol && memcmp(string(),o->string(),ml)==0);}
COCTSTR PvOctets::octetsValue(bool& b) const {
b=true;
return string();}
PvOctets* PvOctets::octetString() const {return (PvOctets*)this;}
PvV4Addr::~PvV4Addr() {}
PvV4Addr::PvV4Addr(OCTSTR o,bool b):PvOctets(sizeof(v4addr),o,b) {}
PvObject* PvV4Addr::shallowCopy() const {
return new PvV4Addr((OCTSTR)string());}
PvV4Addr::PvV4Addr(CSTR p,bool& c,OCTSTR o):PvOctets(sizeof(v4addr),o) {
c=pton(p);}
bool PvV4Addr::pton(CSTR p) {
if(p==0) {return false;}
return inet_pton(AF_INET,p,buffer())==1;}
PvEther::~PvEther() {}
PvEther::PvEther(OCTSTR o,bool b):PvOctets(sizeof(etheraddr),o,b) {}
PvEther::PvEther(CSTR p,bool& c,OCTSTR o):PvOctets(sizeof(etheraddr),o) {
c=pton(p);}
PvObject* PvEther::shallowCopy() const {
return new PvEther((OCTSTR)string());}
bool PvEther::pton(CSTR p) {
if(p==0) {return false;}
struct ether_addr *n=ether_aton((char*)p);
if(n!=0) {set(length(),n->octet);}
return (n!=0);}
PvEther::PvEther(const PvV6Addr& v6,OCTSTR o):PvOctets(sizeof(etheraddr),o) {
multicast(v6);}
void PvEther::multicast(const PvV6Addr& v6) {
COCTSTR src=v6.string();
OCTSTR buf=buffer();
buf[0]=0x33; buf[1]=0x33;
buf[2]=src[12]; buf[3]=src[13]; buf[4]=src[14]; buf[5]=src[15];}
PvEUI64::~PvEUI64() {}
PvEUI64::PvEUI64(OCTSTR o,bool b):PvOctets(sizeof(eui64addr),o,b) {}
PvEUI64::PvEUI64(const PvEther& et,OCTSTR o):PvOctets(sizeof(eui64addr),o) {
create(et);}
void PvEUI64::create(const PvEther& et) {
COCTSTR src=et.string();
OCTSTR buf=buffer();
buf[0]=src[0]^0x02; buf[1]=src[1]; buf[2]=src[2];
buf[3]=0xff; buf[4]=0xfe;
buf[5]=src[3]; buf[6]=src[4]; buf[7]=src[5];}
PvV6Addr::~PvV6Addr() {}
PvV6Addr::PvV6Addr(OCTSTR o,bool b):PvOctets(sizeof(v6addr),o,b) {}
PvV6Addr::PvV6Addr(CSTR p,bool& c,OCTSTR o):PvOctets(sizeof(v6addr),o) {
c=pton(p);}
PvObject* PvV6Addr::shallowCopy() const {
return new PvV6Addr((OCTSTR)string());}
bool PvV6Addr::pton(CSTR p) {
if(p==0) {return false;}
return inet_pton(AF_INET6,p,buffer())==1;}
PvV6Addr* PvV6Addr::merge(uint16_t w,const PvOctets& h,PvV6Addr* o) const {
uint32_t tw=length()*8; // v6addr*8
if(o==0) {o=new PvV6Addr;}
if(o!=this) {o->zero();}
uint32_t hw=h.length()*8; // host width
if(hw>tw) {abort();}
uint16_t pw=(w+hw<tw)?tw-hw:w; // prefix width
uint32_t rw=tw-pw;
ItPosition it;
o->encodeLAs(string(),it,w);
it.addBytes(pw/8); it.addBits(pw%8);
uint32_t ho=(hw-rw)/8; // host offset;
// printf("it(%d,%d) ho=%d rw=%d\n",it.bytes(),it.bits(),ho,rw);
o->encodeRAs(h.string(ho),it,rw);
return o;}
bool PvV6Addr::isV6Addr() const {return true;}
PvOctets* PvOctets::set(uint32_t l,OCTSTR s) {
length_=l;
if(allocated_==0) {
if(s!=0) {buffer_=s;}
return this;}
if(allocated_<l) {
OCTSTR old=buffer_;
buffer_=new octet[allocated_=l];
if(s==0&&old!=0) {memcpy(buffer_,old,l);}
delete [] old;}
if(s!=0) {memcpy(buffer_,s,l);}
return this;}
PvOctets& PvOctets::operator=(const PvOctets& o) {
if(this!=&o) {
set(o.length(),(OCTSTR)o.string());}
return *this;}
PvOctets* PvOctets::substr(uint32_t n,uint32_t l,PvOctets* o) {
OCTSTR s=buffer(n);
if(o==0) {return new PvOctets(l,s);}
return o->set(l,s);}
//======================================================================
// at: position
// bytes
// | bits
// | |
// | | w:indicate width
// | <-(w)->
// | | |
// (o)(b) (e)
// v v v
// +--//---0-(d0)--8-(d1)--+-------+-------+
// first second
//
//----------------------------------------------------------------------
// Left Adjusted value(Octets)
// n:
// <(w)->
// +-------
// mask 11111100 = (2^w-1)<<(8-w)
//
void PvOctets::encodeLA(octet n,const ItPosition& at,uint16_t w) {
if(w>8) {abort();}
OCTSTR dst=buffer();
uint32_t o=at.bytes(); // octet offset
uint16_t b=at.bits(); // bits offset
uint16_t e=b+w; // bits end offset
octet& d0=dst[o]; // first destination
octet m=((1<<w)-1)<<(8-w); // mask for efficent width
octet nm=(n&m); // masked network value
octet t=0, sm=0, rm=0;
t=nm>>b; sm=m>>b; rm=~sm;
d0=(t&sm)|(d0&rm);
if(e<8) {return;} // It's fit in one octet !!
octet& d1=dst[o+1]; // second destination
uint16_t s=8-b;
t=nm<<s; sm=m<<s; rm=~sm;
d1=(t&sm)|(d1&rm);}
octet PvOctets::decodeLA(const ItPosition& at,uint16_t w) const {
if(w>8) {abort();}
COCTSTR src=string();
uint32_t o=at.bytes(); // octet offset
uint16_t b=at.bits(); // bits offset
uint16_t e=b+w; // bits end offset
const octet& d0=src[o]; // first source
octet m=((1<<w)-1)<<(8-w); // mask for efficent width
octet t=0; // target octet
octet sm=0; // shifted mask
if(e<8) { // It's fit in one octet !!
sm=m>>b;
t=(d0&sm)<<b;}
else {
sm=m>>b;
uint16_t r=8-b;
octet rm=m<<r;
const octet& d1=src[o+1]; // second source
t=((d0&sm)<<b)|((d1&rm)>>r);}
return t;}
//----------------------------------------------------------------------
// Right Adjusted value(Numbers)
// n:
// <-(w)>
// +-------
// mask 00111111 = (2^w-1)
//
void PvOctets::encodeRA(octet n,const ItPosition& at,uint16_t w) {
if(w>8) {abort();}
OCTSTR dst=buffer();
uint32_t o=at.bytes(); // octet offset
uint16_t e=at.bits()+w; // bits end offset
octet& d0=dst[o]; // first destination
octet m=(1<<w)-1; // mask for efficent width
octet nm=(n&m); // masked network value
uint16_t s=0; // shift width
octet t=0, sm=0, rm=0;
if(e<8) { // It's fit in one octet !!
s=8-e; t=nm<<s; sm=m<<s; rm=~sm;
d0=(t&sm)|(d0&rm);}
else {
s=e-8; t=nm>>s; sm=m>>s; rm=~sm;
d0=(t&sm)|(d0&rm);
octet& d1=dst[o+1]; // second destination
s=8-s; t=nm<<s; sm=m<<s; rm=~sm;
d1=(t&sm)|(d1&rm);}}
octet PvOctets::decodeRA(const ItPosition& at,uint16_t w) const {
if(w>8) {abort();}
COCTSTR src=string();
uint32_t o=at.bytes(); // octet offset
uint16_t e=at.bits()+w; // bits end offset
const octet& d0=src[o]; // first source
octet m=(1<<w)-1; // mask for efficent width
uint16_t s=0; // shift width
octet t=0; // target octet
octet sm=0; // shifted mask
if(e<8) { // It's fit in one octet !!
s=8-e; sm=m<<s;
t=(d0&sm)>>s;}
else {
s=e-8; sm=m>>s;
uint16_t r=8-s;
octet rm=m<<r;
const octet& d1=src[o+1]; // second source
t=((d0&sm)<<s)|((d1&rm)>>r);}
return t;}
//----------------------------------------------------------------------
void PvOctets::encodeLAs(COCTSTR np,const ItPosition& at,uint16_t w) {
OCTSTR dst=buffer();
uint16_t cw=0; // current bit width
ItPosition it(at);
for(;w>0;w-=cw,np++) {
cw=w>8?8:w;
if(cw==8&&it.bits()==0) {
dst[it.bytes()]=*np;}
else {
encodeLA(*np,it,cw);}
it.addBits(cw);}}
void PvOctets::decodeLAs(OCTSTR np,const ItPosition& at,uint16_t w) const {
COCTSTR src=string();
uint16_t cw=0; // current bit width
ItPosition it(at);
for(;w>0;w-=cw,np++) {
cw=w>8?8:w;
if(cw==8&&it.bits()==0) {
*np=src[it.bytes()];}
else {
*np=decodeLA(it,cw);}
it.addBits(cw);}}
//----------------------------------------------------------------------
void PvOctets::encodeRAs(COCTSTR np,const ItPosition& at,uint16_t w) {
OCTSTR dst=buffer();
uint16_t cw=0; // current bit width
ItPosition it(at);
for(;w>0;w-=cw,np++) {
cw=(w-1)%8+1;
if(cw==8&&it.bits()==0) {
dst[it.bytes()]=*np;}
else {
encodeRA(*np,it,cw);}
it.addBits(cw);}}
void PvOctets::decodeRAs(OCTSTR np,const ItPosition& at,uint16_t w) const {
COCTSTR src=string();
uint16_t cw=0; // current bit width
ItPosition it(at);
for(;w>0;w-=cw,np++) {
cw=(w-1)%8+1;
if(cw==8&&it.bits()==0) {
*np=src[it.bytes()];}
else {
*np=decodeRA(it,cw);}
it.addBits(cw);}}
//----------------------------------------------------------------------
// Right Adjusted value(Numbers)
// n:
// <-----(w)--------->
// +-------+-------+-------+-------
// mask 00000000000001111111111111111111 = (2^w-1)
//
void PvOctets::encodeNUint(uint32_t n,const ItPosition& at,uint16_t w) {
uint16_t uo=(32-w)/8; // offset in n(uint32_t)
COCTSTR np=((OCTSTR)&n)+uo;
encodeRAs(np,at,w);}
void PvOctets::encodeUint(uint32_t h,const ItPosition& at,uint16_t w) {
encodeNUint(htonl(h),at,w);}
uint32_t PvOctets::decodeNUint(const ItPosition& at,uint16_t w) const {
uint32_t n=0;
uint16_t uo=(32-w)/8; // offset in n(uint32_t)
OCTSTR np=((OCTSTR)&n)+uo;
decodeRAs(np,at,w);
return n;}
uint32_t PvOctets::decodeUint(const ItPosition& at,uint16_t w) const {
return ntohl(decodeNUint(at,w));}
//----------------------------------------------------------------------
void PvOctets::encode(const ItPosition& at,const PvOctets& o) {
COCTSTR s=o.string();
uint32_t l=o.length();
if(at.bits()>0) {encodeLAs(s,at,l*8);}
else {memcpy(buffer(at.bytes()),s,l);}}
void PvOctets::encodeZero(const ItPosition& at,const ItPosition& size) {
ItPosition offset = at;
uint32_t len = size.bytes();
if(len>0){//bytes zero
PvOctets zerobuf(len); zerobuf.zero();
encode(offset,zerobuf);
offset.addBytes(len);}
uint16_t bitlen = size.bits();
if(bitlen>0){//remain bits zero
uint32_t zerobits = 0;
encodeUint(zerobits,offset,bitlen);}
}
int32_t PvOctets::compareWidth(const PvOctets& r,uint32_t w) const {
int32_t ow=w/8;
int32_t bw=w%8;
octet m=((1<<bw)-1)<<(8-bw); // mask for efficent width
COCTSTR ls=string();
COCTSTR rs=r.string();
int x=memcmp(ls,rs,ow);
if(x==0&&bw>0) {x=(ls[ow]&m)-(rs[ow]&m);}
return x;}
int32_t PvOctets::compareOctets(const PvOctets& r) const {
int32_t ll=length();
int32_t rl=r.length();
int32_t ml=ll<rl?ll:rl;
COCTSTR ls=string();
COCTSTR rs=r.string();
int32_t x=memcmp(ls,rs,ml);
// printf("%d=memecmp(",x); print(); printf(","); r.print(); printf(",%d);\n",ml);
return x!=0?x:ll-rl;}
int32_t PvOctets::compareObject(const PObject& r) const {
return -(r.compareOctets(*this));}
bool PvOctets::generate(WControl& c,WObject* w,OCTBUF& v) const {
w->encodeOctets(c,v,*this);
return c;}
uint32_t PvOctets::sum1Octet() const {
uint32_t t=0;
uint32_t l=length();
COCTSTR s=string(), e;
for(e=s+l;s<e;s++) {
t+=*s;}
return t;}
uint32_t PvOctets::sum2Octets() const {
uint32_t t=0, n=0;
uint32_t i,l=length();
COCTSTR s=string();
for(i=0;i+1<l;i+=2,s+=2) {
n=s[0]<<8|s[1];
t+=n;}
if(l!=i) {
n=s[0]<<8;
t+=n;}
return t;}
uint32_t PvOctets::sum4Octets() const {
uint32_t t=0, n=0;
uint32_t i,l=length();
COCTSTR s=string();
for(i=0;i+3<l;i+=4,s+=4) {
n=s[0]<<24|s[1]<<16|s[2]<<8|s[3];
t+=n;}
n=0;
switch(l-i) {
case 3: n=s[0]<<24|s[1]<<16|s[2]<<8; break;
case 2: n=s[0]<<24|s[1]<<16; break;
case 1: n=s[0]<<24; break;}
t+=n;
return t;}
void PvOctets::zero() {
memset(buffer(),0x00,length());}
void PvOctets::fill() {
memset(buffer(),0xff,length());}
void PvOctets::dump(CSTR tag) const {
int i, i9=length();
COCTSTR s=string();
CSTR nl=tag!=0?tag:"\n";
CSTR pad=(tag!=0&&length()>16)?tag:"";
for(i=0;i<i9;i++) {
printf("%s%02x",pad,s[i]&0xff);
switch((i%32)+1) {
case 4: case 12: case 20: case 28: pad=" "; break;
case 8: case 16: case 24: pad=" "; break;
case 32: pad=nl; break;
default: pad=""; break;}}}
void PvOctets::print() const {dump(length()>16?0:"");}
void PvOctets::log(uint32_t t) const {
CmCString s("\nlog:");
for(uint32_t i=0;i<t;i++) {s += "| ";}
s += " ";
dump(s.string());}
void PvV4Addr::log(uint32_t t) const {print();}
void PvV6Addr::log(uint32_t t) const {print();}
void PvEther::log(uint32_t t) const {print();}
void PvV4Addr::print() const {
char tmp[sizeof "255.255.255.255"];
inet_ntop(AF_INET,string(),tmp,sizeof(tmp));
printf("%s",tmp);}
void PvEther::print() const {
printf("%s",ether_ntoa((ether_addr*)string()));}
void PvV6Addr::print() const {
char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"];
inet_ntop(AF_INET6,string(),tmp,sizeof(tmp));
printf("%s",tmp);}
const PvEther* PvEther::TN() {
PvIfName* tn=defaultTN();
return tn->ether();}
const PvEther* PvEther::NUT() {
PvIfName* tn=defaultNUT();
return tn->ether();}
const PvV6Addr* PvV6Addr::TN() {
PvIfName* tn=defaultTN();
return tn->v6addr();}
const PvV6Addr* PvV6Addr::NUT() {
PvIfName* tn=defaultNUT();
return tn->v6addr();}
const PvV6Addr& PvV6Addr::linkLocal() {
if(linkLocal_==0) {
bool ok=false;
linkLocal_=new PvV6Addr(linkLocalPrefixPresentation_,ok);}
return *linkLocal_;}
bool PvV6Addr::netMerge(CSTR net,int len,const PvV6Addr& hostAddr) {
bool ok=true;
PvV6Addr netAddr(net,ok); if(!ok) {return false;}
if(len<0||len>128) {return false;}
netAddr.merge(len,hostAddr,this);
return true;}
PvIfName* PvOctets::defaultTN() {
if(defaultTN_==0) {defaultTN_=PvIfName::findTn();}
return defaultTN_;}
PvIfName* PvOctets::defaultNUT() {
if(defaultNUT_==0) {defaultNUT_=PvIfName::findNut();}
return defaultNUT_;}
void PvOctets::defaultNotUsed() {
PvIfName* p=new PvIfName("local");
defaultTN_=p;
defaultNUT_=p;}
bool PvOctets::isOctets() const {return true;}
int32_t PvOctets::addressFamily() const {return AF_UNSPEC;}
int32_t PvV4Addr::addressFamily() const {return AF_INET;}
int32_t PvV6Addr::addressFamily() const {return AF_INET6;}
PvIfName* PvOctets::defaultTN_=0;
PvIfName* PvOctets::defaultNUT_=0;
PvV6Addr* PvV6Addr::linkLocal_=0;
implementCmList(PvOctetsList,PvOctets);
const CSTR PvOctets::linkLocalPrefixPresentation_="fe80::";
////////////////////////////////////////////////////////////////
PvCookie64::PvCookie64(OCTSTR o, bool b):PvOctets(8, o, b) {}
PvCookie64::~PvCookie64() {}
void PvCookie64::log(uint32_t t) const {
print();
}
void PvCookie64::print() const {
COCTSTR buf = string();
uint32_t buflen = length(), d = 0;
for(d = 0; d < buflen; d ++) {
printf("%02x", buf[d]);
}
}
const PvCookie64 *PvCookie64::zerocookie() {
char tmp[8];
memset(tmp, 0, 8);
return(new PvCookie64((OCTSTR)tmp, true));
}
PvObject *PvCookie64::shallowCopy() const {
return(new PvCookie64((OCTSTR)string()));
}
////////////////////////////////////////////////////////////////
PvBSA96::PvBSA96(OCTSTR o, bool b):PvOctets(12, o, b) {}
PvBSA96::~PvBSA96() {}
void PvBSA96::log(uint32_t t) const {
print();
}
void PvBSA96::print() const {
COCTSTR buf = 0;
uint32_t buflen = 0, d = 0;
buf = string();
buflen = length();
for(d = 0; d < buflen; d ++) {
printf("%02x", buf[d]);
}
}
const PvBSA96 *PvBSA96::zerobsa() {
char tmp[12];
memset(tmp, 0, 12);
return(new PvBSA96((OCTSTR)tmp, true));
}
PvObject *PvBSA96::shallowCopy() const {
return(new PvBSA96((OCTSTR)string()));
}
syntax highlighted by Code2HTML, v. 0.9.1