IPv6Address.cc

Go to the documentation of this file.
00001 //
00002 // Copyright (C) 2005 Wei Yang, Ng
00003 // Copyright (C) 2005 Andras Varga
00004 //
00005 // This program is free software; you can redistribute it and/or
00006 // modify it under the terms of the GNU Lesser General Public
00007 // License as published by the Free Software Foundation; either
00008 // version 2.1 of the License, or (at your option) any later version.
00009 //
00010 // This program is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 // GNU Lesser General Public License for more details.
00014 //
00015 // You should have received a copy of the GNU Lesser General Public
00016 // License along with this program; if not, see <http://www.gnu.org/licenses/>.
00017 //
00018 
00019 #include <iostream>
00020 #include <sstream>
00021 #include "IPv6Address.h"
00022 #include "InterfaceToken.h"
00023 
00024 const uint32 LINK_LOCAL_PREFIX = 0xFE800000;
00025 const uint32 SITE_LOCAL_PREFIX = 0xFEC00000;
00026 const uint32 MULTICAST_PREFIX = 0xFF000000;
00027 
00028 //Link and Site local masks should only preserve 10 bits as prefix length is 10.
00029 const uint32 LINK_LOCAL_MASK = 0xFFC00000;
00030 const uint32 SITE_LOCAL_MASK = 0xFFC00000;
00031 const uint32 MULTICAST_MASK = 0xFF000000;
00032 
00033 // RFC 3513: IPv6 Addressing Architecture
00034 // Section 2.7.1: Pre-defined Multicast Addresses
00035 const IPv6Address IPv6Address::UNSPECIFIED_ADDRESS("::0");
00036 const IPv6Address IPv6Address::LOOPBACK_ADDRESS("::1");
00037 const IPv6Address IPv6Address::ALL_NODES_1("FF01::1");
00038 const IPv6Address IPv6Address::ALL_NODES_2("FF02::1");
00039 const IPv6Address IPv6Address::ALL_ROUTERS_1("FF01::2");
00040 const IPv6Address IPv6Address::ALL_ROUTERS_2("FF02::2");
00041 const IPv6Address IPv6Address::ALL_ROUTERS_5("FF05::2");
00042 const IPv6Address IPv6Address::SOLICITED_NODE_PREFIX("FF02:0:0:0:0:1:FF00:0");
00043 const IPv6Address IPv6Address::LINKLOCAL_PREFIX("FE80::");
00044 
00045 
00046 // returns numOctals; advances s just over the last hex digit converted
00047 // FIXME "octal" appears to be a bad name
00048 static int parseOctals(const char *&s, int *octals)
00049 {
00050     int k = 0;
00051     while (1)
00052     {
00053         char *e;
00054         octals[k] = strtoul(s,&e,16);
00055         if (s==e) { // no hex digit converted
00056             if (k!=0) s--;  // "unskip" preceding ':'
00057             return k;
00058         }
00059         // if negative or too big, return (s will point to beginning of large number)
00060         if (octals[k]<0 || octals[k]>0xffff)
00061             return k;
00062         k++;  // octals[k] successfully stored
00063         s = e;  // skip converted hex number
00064         if (*s!=':' || k==8)
00065             return k;
00066         s++;  // skip ':'
00067     }
00068 }
00069 
00070 bool IPv6Address::doTryParse(const char *&addr)
00071 {
00072     if (!strcmp(addr,"<unspec>"))
00073     {
00074         addr += 8;
00075         d[0] = d[1] = d[2] = d[3] = 0;
00076         return true;
00077     }
00078 
00079     // parse and store 16-bit units
00080     int octals[8];
00081     int numOctals = parseOctals(addr, octals);
00082 
00083     // if address string contains "::", parse and store second half too
00084     if (*addr==':' && *(addr+1)==':')
00085     {
00086         addr += 2;
00087         int suffixOctals[8];
00088         int numSuffixOctals = parseOctals(addr, suffixOctals);
00089 
00090         // merge suffixOctals[] into octals[]
00091         if (numOctals+numSuffixOctals>8)
00092             return false; // too many
00093         for (int i=numOctals; i<8; i++) {
00094             int j = i-8+numSuffixOctals;
00095             octals[i] = j<0 ? 0 : suffixOctals[j];
00096         }
00097         numOctals = 8;
00098     }
00099 
00100     if (numOctals!=8)
00101         return false; // too few
00102 
00103     // copy octets to d[]
00104     for (unsigned int i=0; i<4; i++)
00105         d[i] = (octals[i*2]<<16) + octals[2*i + 1];
00106 
00107     return true;
00108 }
00109 
00110 bool IPv6Address::tryParse(const char *addr)
00111 {
00112     if (!addr)
00113         return false;
00114     if (!doTryParse(addr))
00115         return false;
00116     if (*addr!=0)
00117         return false; // illegal trailing character
00118     return true;
00119 }
00120 
00121 bool IPv6Address::tryParseAddrWithPrefix(const char *addr, int& prefixLen)
00122 {
00123     if (!addr)
00124         return false;
00125     if (!doTryParse(addr))
00126         return false;
00127     if (*addr!='/')
00128         return false; // no '/' after address
00129     addr++;
00130 
00131     // parse prefix
00132     char *e;
00133     prefixLen = strtoul(addr,&e,10);
00134     if (addr==e)
00135         return false; // no number after '/'
00136     if (*e!=0)
00137         return false; // garbage after number
00138     if (prefixLen<0 || prefixLen>128)
00139         return false; // wrong len value
00140     return true;
00141 }
00142 
00143 void IPv6Address::set(const char *addr)
00144 {
00145     if (!tryParse(addr))
00146         throw cRuntimeError("IPv6Address: cannot interpret address string `%s'", addr);
00147 }
00148 
00149 // find longest sequence of zeros in address (at least with len=2)
00150 static void findGap(int *octals, int& start, int& end)
00151 {
00152     start = end = 0;
00153     int beg = -1;
00154     for (int i=0; i<8; i++)
00155     {
00156         if (beg==-1 && octals[i]==0)
00157         {
00158             // begin counting
00159             beg = i;
00160         }
00161         else if (beg!=-1 && octals[i]!=0)
00162         {
00163             // end counting
00164             if (i-beg>=2 && i-beg>end-start) {
00165                 start = beg; end = i;
00166             }
00167             beg = -1;
00168         }
00169     }
00170 
00171     // check last zero-seq
00172     if (beg!=-1 && beg<=6 && 8-beg>end-start) {
00173         start = beg; end = 8;
00174     }
00175 }
00176 
00177 std::string IPv6Address::str() const
00178 {
00179     if (isUnspecified())
00180         return std::string("<unspec>");
00181 
00182     // convert to 16-bit octals
00183     int octals[8] = {
00184         (d[0]>>16), (d[0]&0xffff), (d[1]>>16), (d[1]&0xffff),
00185         (d[2]>>16), (d[2]&0xffff), (d[3]>>16), (d[3]&0xffff)
00186     };
00187 
00188     // find longest sequence of zeros in octals[]
00189     int start, end;
00190     findGap(octals, start, end);
00191     if (start==0 && end==8)
00192         return "::0";  // the unspecified address is a special case
00193 
00194     // print octals, replacing gap with "::"
00195     std::stringstream os;
00196     os << std::hex;
00197     for (int i=0; i<start; i++)
00198         os << (i==0?"":":") << octals[i];
00199     if (start!=end)
00200         os << "::";
00201     for (int j=end; j<8; j++)
00202         os << (j==end?"":":") << octals[j];
00203     return os.str();
00204 }
00205 
00206 IPv6Address::Scope IPv6Address::getScope() const
00207 {
00208     //Mask the given IPv6 address with the different mask types
00209     //to get only the IPv6 address scope. Compare the masked
00210     //address with the different prefixes.
00211 
00212     if ((d[0] & LINK_LOCAL_MASK) == LINK_LOCAL_PREFIX )
00213     {
00214         return LINK;
00215     }
00216     else if ((d[0] & SITE_LOCAL_MASK) == SITE_LOCAL_PREFIX )
00217     {
00218         return SITE;
00219     }
00220     else if ((d[0] & MULTICAST_MASK) == MULTICAST_PREFIX )
00221     {
00222         return MULTICAST;
00223     }
00224     else if (d[0] == 0x00000000 && d[1] == 0x00000000 && d[2] == 0x00000000)
00225     {
00226         if (d[3] == 0x00000000)
00227         {
00228             return UNSPECIFIED;
00229         }
00230         else if (d[3] == 0x00000001)
00231         {
00232             return LOOPBACK;
00233         }
00234         else
00235         {
00236             return GLOBAL; // actually an "IPv4-compatible IPv6 address"
00237         }
00238     }
00239     else
00240     {
00241         return GLOBAL;
00242     }
00243 }
00244 
00245 const char *IPv6Address::scopeName(Scope scope)
00246 {
00247     switch (scope)
00248     {
00249         case UNSPECIFIED:        return "unspec";
00250         case LOOPBACK:           return "loopback";
00251         case MULTICAST:          return "mcast";
00252         case LINK:               return "link";
00253         case SITE:               return "site";
00254         case GLOBAL:             return "global";
00255         default:                 return "???";
00256     }
00257 }
00258 
00259 void IPv6Address::constructMask(int prefixLength, uint32 *mask)
00260 {
00261     ASSERT(prefixLength>=0 && prefixLength<=128 && mask!=NULL);
00262 
00263     // create a mask based on the prefix length.
00264     if (prefixLength==0)
00265     {
00266         mask[0] = mask[1] = mask[2] = mask[3] = 0x00000000;
00267     }
00268     else if (prefixLength<=32)
00269     {
00270         int num_of_shifts = 32 - prefixLength;
00271         mask[0] = 0xFFFFFFFFU << num_of_shifts;
00272         mask[1] = 0x00000000;
00273         mask[2] = 0x00000000;
00274         mask[3] = 0x00000000;
00275     }
00276     else if (prefixLength<=64)
00277     {
00278         int num_of_shifts = 64 - prefixLength;
00279         mask[0] = 0xFFFFFFFFU;
00280         mask[1] = 0xFFFFFFFFU << num_of_shifts;
00281         mask[2] = 0x00000000;
00282         mask[3] = 0x00000000;
00283     }
00284     else if (prefixLength<=96)
00285     {
00286         int num_of_shifts = 96 - prefixLength;
00287         mask[0] = 0xFFFFFFFFU;
00288         mask[1] = 0xFFFFFFFFU;
00289         mask[2] = 0xFFFFFFFFU << num_of_shifts;
00290         mask[3] = 0x00000000;
00291     }
00292     else
00293     {
00294         int num_of_shifts = 128 - prefixLength;
00295         mask[0] = 0xFFFFFFFFU;
00296         mask[1] = 0xFFFFFFFFU;
00297         mask[2] = 0xFFFFFFFFU;
00298         mask[3] = 0xFFFFFFFFU << num_of_shifts;
00299     }
00300 }
00301 
00302 IPv6Address IPv6Address::getPrefix(int prefixLength) const
00303 {
00304     // First we construct a mask.
00305     uint32 mask[4];
00306     constructMask(prefixLength, mask);
00307 
00308     // Now we mask each IPv6 address segment and create a new IPv6 Address!
00309     return IPv6Address(d[0]&mask[0],d[1]&mask[1],d[2]&mask[2],d[3]&mask[3] );
00310 }
00311 
00312 IPv6Address IPv6Address::getSuffix(int prefixLength) const
00313 {
00314     // First we construct a mask.
00315     uint32 mask[4];
00316     constructMask(prefixLength, mask);
00317 
00318     // Now we mask each IPv6 address segment, inverse it
00319     // and create a new IPv6 Address!
00320     return IPv6Address(d[0]&~mask[0],d[1]&~mask[1],d[2]&~mask[2],d[3]&~mask[3] );
00321 }
00322 
00323 const IPv6Address& IPv6Address::setPrefix(const IPv6Address& fromAddr, int prefixLength)
00324 {
00325     // first we construct a mask.
00326     uint32 mask[4];
00327     constructMask(prefixLength, mask);
00328 
00329     // combine the addresses
00330     d[0] = (d[0]&~mask[0]) | (fromAddr.d[0]&mask[0]);
00331     d[1] = (d[1]&~mask[1]) | (fromAddr.d[1]&mask[1]);
00332     d[2] = (d[2]&~mask[2]) | (fromAddr.d[2]&mask[2]);
00333     d[3] = (d[3]&~mask[3]) | (fromAddr.d[3]&mask[3]);
00334     return *this;
00335 }
00336 
00337 
00338 const IPv6Address& IPv6Address::setSuffix(const IPv6Address& fromAddr, int prefixLength)
00339 {
00340     // first we construct a mask.
00341     uint32 mask[4];
00342     constructMask(prefixLength, mask);
00343 
00344     // combine the addresses
00345     d[0] = (d[0]&mask[0]) | (fromAddr.d[0]&~mask[0]);
00346     d[1] = (d[1]&mask[1]) | (fromAddr.d[1]&~mask[1]);
00347     d[2] = (d[2]&mask[2]) | (fromAddr.d[2]&~mask[2]);
00348     d[3] = (d[3]&mask[3]) | (fromAddr.d[3]&~mask[3]);
00349     return *this;
00350 }
00351 
00352 IPv6Address IPv6Address::formLinkLocalAddress(const InterfaceToken& ident)
00353 {
00354     IPv6Address suffix(0, 0, ident.normal(), ident.low());
00355     IPv6Address linkLocalAddr = IPv6Address::LINKLOCAL_PREFIX;
00356     linkLocalAddr.setSuffix(suffix, 128-ident.length());
00357     return linkLocalAddr;
00358 }
00359 
00360 bool IPv6Address::matches(const IPv6Address& prefix, int prefixLength) const
00361 {
00362     // first we construct a mask.
00363     uint32 mask[4];
00364     constructMask(prefixLength, mask);
00365 
00366     // xor the bits of the 2 addresses, and the result should be zero wherever
00367     // the mask has 1 bits
00368     return (((d[0]^prefix.d[0])&mask[0]) | ((d[1]^prefix.d[1])&mask[1]) |
00369             ((d[2]^prefix.d[2])&mask[2]) | ((d[3]^prefix.d[3])&mask[3]))==0;
00370 }
00371 
00372 int IPv6Address::getMulticastScope() const
00373 {
00374     if ((d[0] & MULTICAST_MASK)!=MULTICAST_PREFIX)
00375         throw cRuntimeError("IPv6Address::getMulticastScope(): %s is not a multicast address", str().c_str());
00376     return (d[0] >> 16) & 0x0F;
00377 }
00378 
00379