IPAddress.cc

Go to the documentation of this file.
00001 //
00002 // Copyright (C) 2001  Vincent Oberle (vincent@oberle.com)
00003 // Institute of Telematics, University of Karlsruhe, Germany.
00004 // University Comillas, Madrid, Spain.
00005 // Copyright (C) 2004, 2008 Andras Varga
00006 // Copyright (C) 2008  Ingmar Baumgart
00007 //
00008 // This program is free software; you can redistribute it and/or
00009 // modify it under the terms of the GNU Lesser General Public
00010 // License as published by the Free Software Foundation; either
00011 // version 2.1 of the License, or (at your option) any later version.
00012 //
00013 // This program is distributed in the hope that it will be useful,
00014 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00015 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016 // GNU Lesser General Public License for more details.
00017 //
00018 // You should have received a copy of the GNU Lesser General Public
00019 // License along with this program; if not, see <http://www.gnu.org/licenses/>.
00020 //
00021 
00022 
00023 //
00024 //  Author: Vincent Oberle
00025 //  Date: Jan-March 2001
00026 //  Cleanup and rewrite: Andras Varga, 2004
00027 //
00028 
00029 #include "IPAddress.h"
00030 
00034 static const int IPADDRESS_STRING_SIZE = 20;
00035 
00036 // predefined addresses
00037 const IPAddress IPAddress::UNSPECIFIED_ADDRESS;
00038 const IPAddress IPAddress::LOOPBACK_ADDRESS("127.0.0.1");
00039 const IPAddress IPAddress::LOOPBACK_NETMASK("255.0.0.0");
00040 const IPAddress IPAddress::ALLONES_ADDRESS("255.255.255.255");
00041 
00042 const IPAddress IPAddress::ALL_HOSTS_MCAST("224.0.0.1");
00043 const IPAddress IPAddress::ALL_ROUTERS_MCAST("224.0.0.2");
00044 const IPAddress IPAddress::ALL_DVMRP_ROUTERS_MCAST("224.0.0.4");
00045 const IPAddress IPAddress::ALL_OSPF_ROUTERS_MCAST("224.0.0.5");
00046 const IPAddress IPAddress::ALL_OSPF_DESIGNATED_ROUTERS_MCAST("224.0.0.6");
00047 
00048 
00049 void IPAddress::set(int i0, int i1, int i2, int i3)
00050 {
00051     addr = (i0 << 24) | (i1 << 16) | (i2 << 8) | i3;
00052 }
00053 
00054 bool IPAddress::parseIPAddress(const char *text, unsigned char tobytes[])
00055 {
00056     if (!text)
00057         return false;
00058 
00059     if (!strcmp(text,"<unspec>"))
00060     {
00061         tobytes[0] = tobytes[1] = tobytes[2] = tobytes[3] = 0;
00062         return true;
00063     }
00064 
00065     const char *s = text;
00066     int i=0;
00067     while(true)
00068     {
00069         if (*s<'0' || *s>'9')
00070             return false;  // missing number
00071 
00072         // read and store number
00073         int num = 0;
00074         while (*s>='0' && *s<='9')
00075             num = 10*num + (*s++ - '0');
00076         if (num>255)
00077             return false; // number too big
00078         tobytes[i++] = (unsigned char) num;
00079 
00080         if (!*s)
00081             break;  // end of string
00082         if (*s!='.')
00083             return false;  // invalid char after number
00084         if (i==4)
00085             return false;  // read 4th number and not yet EOS
00086 
00087         // skip '.'
00088         s++;
00089     }
00090     return i==4;  // must have all 4 numbers
00091 }
00092 
00093 void IPAddress::set(const char *text)
00094 {
00095     unsigned char buf[4];
00096     if (!text)
00097         opp_error("IP address string is NULL");
00098     bool ok = parseIPAddress(text, buf);
00099     if (!ok)
00100         opp_error("Invalid IP address string `%s'", text);
00101     set(buf[0], buf[1], buf[2], buf[3]);
00102 }
00103 
00104 std::string IPAddress::str() const
00105 {
00106     if (isUnspecified())
00107         return std::string("<unspec>");
00108 
00109     char buf[IPADDRESS_STRING_SIZE];
00110     sprintf(buf, "%u.%u.%u.%u", (addr>>24)&255, (addr>>16)&255, (addr>>8)&255, addr&255);
00111     return std::string(buf);
00112 }
00113 
00114 char IPAddress::getIPClass() const
00115 {
00116     unsigned char buf = getDByte(0);
00117     if ((buf & 0x80) == 0x00)       // 0xxxx
00118         return 'A';
00119     else if ((buf & 0xC0) == 0x80)  // 10xxx
00120         return 'B';
00121     else if ((buf & 0xE0) == 0xC0)  // 110xx
00122         return 'C';
00123     else if ((buf & 0xF0) == 0xE0)  // 1110x
00124         return 'D';
00125     else if ((buf & 0xF8) == 0xF0)  // 11110
00126         return 'E';
00127     else
00128         return '?';
00129 }
00130 
00131 IPAddress IPAddress::getNetwork() const
00132 {
00133     switch (getIPClass())
00134     {
00135     case 'A':
00136         // Class A: network = 7 bits
00137         return IPAddress(getDByte(0), 0, 0, 0);
00138     case 'B':
00139         // Class B: network = 14 bits
00140         return IPAddress(getDByte(0), getDByte(1), 0, 0);
00141     case 'C':
00142         // Class C: network = 21 bits
00143         return IPAddress(getDByte(0), getDByte(1), getDByte(2), 0);
00144     default:
00145         // Class D or E
00146         return IPAddress();
00147     }
00148 }
00149 
00150 IPAddress IPAddress::getNetworkMask() const
00151 {
00152     switch (getIPClass())
00153     {
00154     case 'A':
00155         // Class A: network = 7 bits
00156         return IPAddress(255, 0, 0, 0);
00157     case 'B':
00158         // Class B: network = 14 bits
00159         return IPAddress(255, 255, 0, 0);
00160     case 'C':
00161         // Class C: network = 21 bits
00162         return IPAddress(255, 255, 255, 0);
00163     default:
00164         // Class D or E: return null address
00165         return IPAddress();
00166     }
00167 }
00168 
00169 
00170 bool IPAddress::isNetwork(const IPAddress& toCmp) const
00171 {
00172     IPAddress netmask = getNetworkMask();
00173     if (netmask.isUnspecified()) return false; // Class is D or E
00174     return maskedAddrAreEqual(*this, toCmp, netmask);
00175 }
00176 
00177 
00178 bool IPAddress::prefixMatches(const IPAddress& to_cmp, int numbits) const
00179 {
00180     if (numbits<1)
00181         return true;
00182 
00183     uint32 addr2 = to_cmp.getInt();
00184 
00185     if (numbits > 31)
00186         return addr==addr2;
00187 
00188     // The right shift on an unsigned int produces 0 on the left
00189     uint32 mask = 0xFFFFFFFF;
00190     mask = ~(mask >> numbits);
00191 
00192     return (addr & mask) == (addr2 & mask);
00193 }
00194 
00195 int IPAddress::getNumMatchingPrefixBits(const IPAddress& to_cmp) const
00196 {
00197     uint32 addr2 = to_cmp.getInt();
00198 
00199     uint32 res = addr ^ addr2;
00200     // If the bits are equal, there is a 0, so counting
00201     // the zeros from the left
00202     for (int i = 31; i >= 0; i--) {
00203         if (res & (1 << i)) {
00204             // 1, means not equal, so stop
00205             return 31 - i;
00206         }
00207     }
00208     return 32;
00209 }
00210 
00211 int IPAddress::getNetmaskLength() const
00212 {
00213     int i;
00214     for (i=0; i<31; i++)
00215         if (addr & (1 << i))
00216             return 32-i;
00217     return 0;
00218 }
00219 
00220 void IPAddress::keepFirstBits(unsigned int n)
00221 {
00222     addr &= 0xFFFFFFFF << n;
00223 }
00224 
00225 bool IPAddress::maskedAddrAreEqual(const IPAddress& addr1,
00226                                    const IPAddress& addr2,
00227                                    const IPAddress& netmask)
00228 {
00229     // return addr1.doAnd(netmask).equals(addr2.doAnd(netmask));
00230     // Looks weird, but is the same and is faster
00231     return !(bool)((addr1.addr ^ addr2.addr) & netmask.addr);
00232 }
00233 
00234 bool IPAddress::isWellFormed(const char *text)
00235 {
00236     unsigned char dummy[4];
00237     return parseIPAddress(text, dummy);
00238 }
00239 
00240