/* * 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 #include #include #include #include #if defined(__FreeBSD__) #include #include #include /* 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 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+hwencodeLAs(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_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<>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<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<>b; t=(d0&sm)<>b; uint16_t r=8-b; octet rm=m<>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<>s; sm=m>>s; rm=~sm; d0=(t&sm)|(d0&rm); octet& d1=dst[o+1]; // second destination s=8-s; t=nm<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<>s;} else { s=e-8; sm=m>>s; uint16_t r=8-s; octet rm=m<>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<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=llencodeOctets(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;s16)?tag:""; for(i=0;i16?0:"");} void PvOctets::log(uint32_t t) const { CmCString s("\nlog:"); for(uint32_t i=0;iether();} 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())); }