MACAddress.cc

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2003 Andras Varga; CTIE, Monash University, Australia
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU Lesser General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU Lesser General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU Lesser General Public License
00015  * along with this program; if not, see <http://www.gnu.org/licenses/>.
00016 */
00017 
00018 #include <ctype.h>
00019 #include "MACAddress.h"
00020 #include "InterfaceToken.h"
00021 
00022 
00023 unsigned int MACAddress::autoAddressCtr;
00024 
00025 //
00026 // Converts hex string into a byte array 'destbuf'. Destbuf is 'size'
00027 // chars long -- if hext string is shorter, destbuf is filled with zeros;
00028 // if destbuf is longer, it is truncated. Non-hex characters are
00029 // discarded before conversion. Returns number of bytes converted from hex.
00030 //
00031 static int hextobin(const char *hexstr, unsigned char *destbuf, int size)
00032 {
00033     int k=0;
00034     const char *s = hexstr;
00035     for (int pos=0; pos<size; pos++)
00036     {
00037         if (!s || !*s)
00038         {
00039             destbuf[pos] = 0;
00040         }
00041         else
00042         {
00043             while (*s && !isxdigit(*s)) s++;
00044             if (!*s) {destbuf[pos]=0; continue;}
00045             unsigned char d = isdigit(*s) ? (*s-'0') : islower(*s) ? (*s-'a'+10) : (*s-'A'+10);
00046             d = d<<4;
00047             s++;
00048 
00049             while (*s && !isxdigit(*s)) s++;
00050             if (!*s) {destbuf[pos]=0; continue;}
00051             d += isdigit(*s) ? (*s-'0') : islower(*s) ? (*s-'a'+10) : (*s-'A'+10);
00052             s++;
00053 
00054             destbuf[pos] = d;
00055             k++;
00056         }
00057     }
00058     return k;
00059 }
00060 
00061 const MACAddress MACAddress::UNSPECIFIED_ADDRESS;
00062 const MACAddress MACAddress::BROADCAST_ADDRESS("ff:ff:ff:ff:ff:ff");
00063 
00064 MACAddress::MACAddress()
00065 {
00066     address[0]=address[1]=address[2]=address[3]=address[4]=address[5]=0;
00067 }
00068 
00069 MACAddress::MACAddress(const char *hexstr)
00070 {
00071     setAddress(hexstr);
00072 }
00073 
00074 MACAddress& MACAddress::operator=(const MACAddress& other)
00075 {
00076     memcpy(address, other.address, MAC_ADDRESS_BYTES);
00077     return *this;
00078 }
00079 
00080 unsigned int MACAddress::getAddressSize() const
00081 {
00082     return 6;
00083 }
00084 
00085 unsigned char MACAddress::getAddressByte(unsigned int k) const
00086 {
00087     if (k>=6) throw cRuntimeError("Array of size 6 indexed with %d", k);
00088     return address[k];
00089 }
00090 
00091 void MACAddress::setAddressByte(unsigned int k, unsigned char addrbyte)
00092 {
00093     if (k>=6) throw cRuntimeError("Array of size 6 indexed with %d", k);
00094     address[k] = addrbyte;
00095 }
00096 
00097 bool MACAddress::tryParse(const char *hexstr)
00098 {
00099     if (!hexstr)
00100         return false;
00101 
00102     // check syntax
00103     int numHexDigits = 0;
00104     for (const char *s = hexstr; *s; s++) {
00105         if (isxdigit(*s))
00106             numHexDigits++;
00107         else if (*s!=' ' && *s!=':' && *s!='-')
00108             return false; // wrong syntax
00109     }
00110     if (numHexDigits != 2*MAC_ADDRESS_BYTES)
00111         return false;
00112 
00113     // convert
00114     hextobin(hexstr, address, MAC_ADDRESS_BYTES);
00115     return true;
00116 }
00117 
00118 void MACAddress::setAddress(const char *hexstr)
00119 {
00120     if (!tryParse(hexstr))
00121         throw cRuntimeError("MACAddress: wrong address syntax '%s': 12 hex digits expected, with optional embedded spaces, hyphens or colons", hexstr);
00122 }
00123 
00124 void MACAddress::setAddressBytes(unsigned char *addrbytes)
00125 {
00126     memcpy(address, addrbytes, MAC_ADDRESS_BYTES);
00127 }
00128 
00129 void MACAddress::setBroadcast()
00130 {
00131     address[0]=address[1]=address[2]=address[3]=address[4]=address[5]=0xff;
00132 }
00133 
00134 bool MACAddress::isBroadcast() const
00135 {
00136     return (address[0]&address[1]&address[2]&address[3]&address[4]&address[5])==0xff;
00137 }
00138 
00139 bool MACAddress::isUnspecified() const
00140 {
00141     return !(address[0] || address[1] || address[2] || address[3] || address[4] || address[5]);
00142 }
00143 
00144 std::string MACAddress::str() const
00145 {
00146     char buf[20];
00147     char *s = buf;
00148     for (int i=0; i<MAC_ADDRESS_BYTES; i++, s+=3)
00149         sprintf(s,"%2.2X-",address[i]);
00150     *(s-1)='\0';
00151     return std::string(buf);
00152 }
00153 
00154 bool MACAddress::equals(const MACAddress& other) const
00155 {
00156     return memcmp(address, other.address, MAC_ADDRESS_BYTES)==0;
00157 }
00158 
00159 int MACAddress::compareTo(const MACAddress& other) const
00160 {
00161     return memcmp(address, other.address, MAC_ADDRESS_BYTES);
00162 }
00163 
00164 InterfaceToken MACAddress::formInterfaceIdentifier() const
00165 {
00166     const unsigned char *b = address;
00167     uint32 high = (b[0]<<24) | (b[1]<<16) | (b[2]<<8) | 0xff;
00168     uint32 low =  (0xfe<<24) | (b[3]<<16) | (b[4]<<8) | b[5];
00169     return InterfaceToken(low, high, 64);
00170 }
00171 
00172 MACAddress MACAddress::generateAutoAddress()
00173 {
00174     ++autoAddressCtr;
00175 
00176     unsigned char addrbytes[6];
00177     addrbytes[0] = 0x0A;
00178     addrbytes[1] = 0xAA;
00179     addrbytes[2] = (autoAddressCtr>>24)&0xff;
00180     addrbytes[3] = (autoAddressCtr>>16)&0xff;
00181     addrbytes[4] = (autoAddressCtr>>8)&0xff;
00182     addrbytes[5] = (autoAddressCtr)&0xff;
00183 
00184     MACAddress addr;
00185     addr.setAddressBytes(addrbytes);
00186     return addr;
00187 }
00188