INet4Address.cc

Go to the documentation of this file.
00001 // $Id: INet4Address.cc 1772 2011-03-10 12:45:21Z tho $
00002 //
00003 // Copyright (C) 2007
00004 // Fraunhofer (FOKUS)
00005 // Competence Center NETwork research (NET), St. Augustin, GERMANY
00006 //     Stefan Bund <g0dil@berlios.de>
00007 //
00008 // This program is free software; you can redistribute it and/or modify
00009 // it under the terms of the GNU General Public License as published by
00010 // the Free Software Foundation; either version 2 of the License, or
00011 // (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 General Public License for more details.
00017 //
00018 // You should have received a copy of the GNU General Public License
00019 // along with this program; if not, write to the
00020 // Free Software Foundation, Inc.,
00021 // 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00022 
00026 #include "INet4Address.hh"
00027 //#include "INet4Address.ih"
00028 
00029 // Custom includes
00030 #include <arpa/inet.h>
00031 #include <netdb.h>
00032 #include <sys/socket.h>
00033 #include <boost/lexical_cast.hpp>
00034 #if defined(_REENTRANT) && !defined(__GLIBC__)
00035 #include <boost/thread/mutex.hpp>
00036 #endif
00037 #include <senf/Socket/Protocols/AddressExceptions.hh>
00038 
00039 //#include "INet4Address.mpp"
00040 #define prefix_
00041 //-/////////////////////////////////////////////////////////////////////////////////////////////////
00042 
00043 //-/////////////////////////////////////////////////////////////////////////////////////////////////
00044 // senf::INet4Address::INet4Address
00045 
00046 prefix_ senf::INet4Address::INet4Address(address_type value)
00047 {
00048     iref() = htonl(value);
00049 }
00050 
00051 prefix_ senf::INet4Address senf::INet4Address::from_string(std::string const & s)
00052 {
00053     struct in_addr ina;
00054     if (::inet_pton(AF_INET,s.c_str(),&ina) > 0)
00055         return INet4Address::from_inaddr(ina.s_addr);
00056 
00057     if  (s.empty())
00058         throw AddressSyntaxException() << ": empty string";
00059 
00060     int herr (0);
00061 
00062     // If available, we use the reentrant GNU variant. This has the additional advantage, that we
00063     // can explicitly ask for IPv4 addresses
00064 
00065 #   ifdef __GLIBC__
00066 
00067     struct hostent entbuf;
00068     char buffer[4096];
00069     struct hostent * ent (0);
00070     ::gethostbyname2_r(s.c_str(), AF_INET, &entbuf, buffer, sizeof(buffer), &ent, &herr);
00071 
00072 #   else // ! __GLIBC__
00073 
00074 #   ifdef _REENTRANT
00075     static boost::mutex mutex;
00076     boost::mutex::scoped_lock lock(mutex);
00077 #   endif
00078     struct hostent * ent (::gethostbyname(s.c_str()));
00079     herr = h_errno;
00080 
00081 #   endif // __GLIBC__
00082 
00083     if (!ent)
00084         throw UnknownHostnameException(s);
00085     if (ent->h_addrtype != AF_INET)
00086         throw UnknownHostnameException(s);
00087 
00088     // We are only interested in the first address ...
00089     return INet4Address::from_inaddr(
00090         reinterpret_cast<in_addr*>(*(ent->h_addr_list))->s_addr);
00091 }
00092 
00093 prefix_ bool senf::INet4Address::local()
00094     const
00095 {
00096     address_type l (address());
00097     return
00098         (l & 0xFF000000u) == 0x0A000000u ||
00099         (l & 0xFFF00000u) == 0xAC100000u ||
00100         (l & 0xFFFF0000u) == 0xA9FE0000u ||
00101         (l & 0xFFFF0000u) == 0xC0A80000u;
00102 }
00103 
00104 prefix_ bool senf::INet4Address::loopback()
00105     const
00106 {
00107     return (address() & 0xFF000000u) == 0x7F000000u;
00108 }
00109 
00110 prefix_ bool senf::INet4Address::multicast()
00111     const
00112 {
00113     return (address() & 0xF0000000u) == 0xE0000000u;
00114 }
00115 
00116 prefix_ senf::INet4Address::address_type senf::INet4Address::address()
00117     const
00118 {
00119     return ntohl(iref());
00120 }
00121 
00122 senf::INet4Address const senf::INet4Address::None;
00123 senf::INet4Address const senf::INet4Address::Loopback (0x7F000001u);
00124 senf::INet4Address const senf::INet4Address::Broadcast (0xFFFFFFFFu);
00125 
00126 //-/////////////////////////////////////////////////////////////////////////////////////////////////
00127 // senf::INet4Network
00128 
00129 prefix_ senf::INet4Network::INet4Network(std::string const & s)
00130 {
00131     std::string::size_type i (s.find('/'));
00132     if (i == std::string::npos)
00133         throw AddressSyntaxException(s);
00134     try {
00135         prefix_len_ = boost::lexical_cast<unsigned>(std::string(s,i+1));
00136     } catch (boost::bad_lexical_cast const &) {
00137         throw AddressSyntaxException(s);
00138     }
00139     address_ = INet4Address(INet4Address::from_string(std::string(s, 0, i)).address() & mask());
00140 }
00141 
00142 //-/////////////////////////////////////////////////////////////////////////////////////////////////
00143 // namespace members
00144 
00145 prefix_ std::ostream & senf::operator<<(std::ostream & os, INet4Address const & addr)
00146 {
00147     ::in_addr ina;
00148     char buffer[16];
00149     ina.s_addr = addr.inaddr();
00150     ::inet_ntop(AF_INET,&ina,buffer,16);
00151     buffer[15] = 0;
00152     os << buffer;
00153     return os;
00154 }
00155 
00156 prefix_ std::istream & senf::operator>>(std::istream & is, INet4Address & addr)
00157 {
00158     std::string s;
00159     if (!(is >> s))
00160         return is;
00161     try {
00162         addr = INet4Address::from_string(s);
00163     }
00164     catch (AddressException &) {
00165         is.setstate(std::ios::failbit);
00166     }
00167     return is;
00168 }
00169 
00170 prefix_ std::istream & senf::operator>>(std::istream & is, INet4Network & addr)
00171 {
00172     std::string s;
00173     if (!(is >> s))
00174         return is;
00175     try {
00176         addr = INet4Network(s);
00177     }
00178     catch (AddressException &) {
00179         is.setstate(std::ios::failbit);
00180     }
00181     return is;
00182 }
00183 
00184 //-/////////////////////////////////////////////////////////////////////////////////////////////////
00185 #undef prefix_
00186 //#include "INet4Address.mpp"
00187 
00188 
00189 // Local Variables:
00190 // mode: c++
00191 // fill-column: 100
00192 // comment-column: 40
00193 // c-file-style: "senf"
00194 // indent-tabs-mode: nil
00195 // ispell-local-dictionary: "american"
00196 // compile-command: "scons -u test"
00197 // End: