Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
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
00029 const uint32 LINK_LOCAL_MASK = 0xFFC00000;
00030 const uint32 SITE_LOCAL_MASK = 0xFFC00000;
00031 const uint32 MULTICAST_MASK = 0xFF000000;
00032
00033
00034
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
00047
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) {
00056 if (k!=0) s--;
00057 return k;
00058 }
00059
00060 if (octals[k]<0 || octals[k]>0xffff)
00061 return k;
00062 k++;
00063 s = e;
00064 if (*s!=':' || k==8)
00065 return k;
00066 s++;
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
00080 int octals[8];
00081 int numOctals = parseOctals(addr, octals);
00082
00083
00084 if (*addr==':' && *(addr+1)==':')
00085 {
00086 addr += 2;
00087 int suffixOctals[8];
00088 int numSuffixOctals = parseOctals(addr, suffixOctals);
00089
00090
00091 if (numOctals+numSuffixOctals>8)
00092 return false;
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;
00102
00103
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;
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;
00129 addr++;
00130
00131
00132 char *e;
00133 prefixLen = strtoul(addr,&e,10);
00134 if (addr==e)
00135 return false;
00136 if (*e!=0)
00137 return false;
00138 if (prefixLen<0 || prefixLen>128)
00139 return false;
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
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
00159 beg = i;
00160 }
00161 else if (beg!=-1 && octals[i]!=0)
00162 {
00163
00164 if (i-beg>=2 && i-beg>end-start) {
00165 start = beg; end = i;
00166 }
00167 beg = -1;
00168 }
00169 }
00170
00171
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
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
00189 int start, end;
00190 findGap(octals, start, end);
00191 if (start==0 && end==8)
00192 return "::0";
00193
00194
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
00209
00210
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;
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
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
00305 uint32 mask[4];
00306 constructMask(prefixLength, mask);
00307
00308
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
00315 uint32 mask[4];
00316 constructMask(prefixLength, mask);
00317
00318
00319
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
00326 uint32 mask[4];
00327 constructMask(prefixLength, mask);
00328
00329
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
00341 uint32 mask[4];
00342 constructMask(prefixLength, mask);
00343
00344
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
00363 uint32 mask[4];
00364 constructMask(prefixLength, mask);
00365
00366
00367
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