|
INET Framework for OMNeT++/OMNEST
|
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