simple-socket library 1.1.5

SocketUtils.cpp

Go to the documentation of this file.
00001 #include "SocketUtils.h"
00002 #include "SimpleSocket.h"
00003 
00004 #include <sys/socket.h>
00005 #include <sys/ioctl.h>
00006 #include <arpa/inet.h>
00007 #include <net/if.h>
00008 #include <net/if_arp.h>
00009 #include <netdb.h>
00010 
00011 #include <cstring>
00012 #include <cstdlib>
00013 #include <sstream>
00014 #include <iomanip>
00015 
00016 using namespace NET;
00017 
00018 namespace
00019 {
00020     class sockaddr_ptr
00021     {
00022     public:
00023         sockaddr_ptr( const sockaddr* sa) : msa(*sa) {}
00024         const sockaddr_in& operator*() const { return msi; }
00025         const sockaddr_in* operator->() const { return &msi; }
00026 
00027     private:
00028         union { sockaddr msa; sockaddr_in msi; };
00029     };
00030 }
00031 
00032 std::string NET::resolveHostname( const std::string& hostname)
00033 {
00034     hostent* host = gethostbyname( hostname.c_str());
00035     if( host == 0)
00036     {
00037         // strerror() will not work for gethostbyname()
00038         throw SocketException("Failed to resolve address (gethostbyname)", false);
00039     }
00040     return std::string(host->h_addr);
00041 }
00042 
00043 unsigned short NET::resolveService( const std::string& service, const std::string& protocol)
00044 {
00045     struct servent* serv = getservbyname( service.c_str(), protocol.c_str());
00046 
00047     if(!serv)
00048         // Service is port number
00049         return std::atoi( service.c_str());
00050     else
00051         // Found port (network byte order) by name
00052         return ntohs( serv->s_port);
00053 }
00054 
00055 std::vector<std::string> NET::getNetworkInterfaces()
00056 {
00057     std::vector<std::string> ret;
00058     struct if_nameindex* index = if_nameindex();
00059 
00060     for( int i = 0; index[i].if_index != 0; ++i)
00061         ret.push_back( std::string( index[i].if_name));
00062 
00063     if_freenameindex(index);
00064     return ret;
00065 }
00066 
00067 std::string NET::getInterfaceAddress( const std::string& interface)
00068 {
00069     struct ifreq ifr;
00070 
00071     ifr.ifr_addr.sa_family = AF_INET;
00072     std::strncpy( ifr.ifr_name, interface.c_str(), sizeof(ifr.ifr_name));
00073 
00074     int sock = ::socket( AF_INET, SOCK_DGRAM, IPPROTO_IP);
00075     if( sock < 0)
00076         throw SocketException("Couldn't create socket (getInterfaceAddress)");
00077 
00078     if( ioctl( sock, SIOCGIFADDR, &ifr) < 0)
00079         throw SocketException("ioctl failed (getInterfaceAddress)");
00080 
00081     ::close(sock);
00082 
00083     return inet_ntoa( sockaddr_ptr( &ifr.ifr_addr)->sin_addr);
00084 }
00085 
00086 void NET::setInterfaceAddress( const std::string& interface, const std::string& address)
00087 {
00088     struct ifreq ifr;
00089 
00090     ifr.ifr_addr.sa_family = AF_INET;
00091     std::strncpy( ifr.ifr_name, interface.c_str(), sizeof(ifr.ifr_name));
00092 
00093     int sock = ::socket( AF_INET, SOCK_DGRAM, IPPROTO_IP);
00094     if( sock < 0)
00095         throw SocketException("Couldn't create socket (setInterfaceAddress)");
00096 
00097     inet_aton( address.c_str(), &(reinterpret_cast<sockaddr_in*>(&ifr.ifr_addr)->sin_addr));
00098 
00099     if( ioctl( sock, SIOCSIFADDR, &ifr) < 0)
00100         throw SocketException("ioctl failed (setInterfaceAddress)");
00101 
00102     ::close(sock);
00103 }
00104 
00105 std::string NET::getBroadcastAddress( const std::string& interface)
00106 {
00107     struct ifreq ifr;
00108 
00109     ifr.ifr_addr.sa_family = AF_INET;
00110     std::strncpy( ifr.ifr_name, interface.c_str(), sizeof(ifr.ifr_name));
00111 
00112     int sock = ::socket( AF_INET, SOCK_DGRAM, IPPROTO_IP);
00113     if( sock < 0)
00114         throw SocketException("Couldn't create socket (getBroadcastAddress)");
00115 
00116     if( ioctl( sock, SIOCGIFBRDADDR, &ifr) < 0)
00117         throw SocketException("ioctl failed (getInterfaceAddress)");
00118 
00119     ::close(sock);
00120 
00121     return inet_ntoa( sockaddr_ptr( &ifr.ifr_broadaddr)->sin_addr);
00122 }
00123 
00124 void NET::setBroadcastAddress( const std::string& interface, const std::string& address)
00125 {
00126     struct ifreq ifr;
00127 
00128     ifr.ifr_addr.sa_family = AF_INET;
00129     std::strncpy( ifr.ifr_name, interface.c_str(), sizeof(ifr.ifr_name));
00130 
00131     int sock = ::socket( AF_INET, SOCK_DGRAM, IPPROTO_IP);
00132     if( sock < 0)
00133         throw SocketException("Couldn't create socket (setBroadcastAddress)");
00134 
00135     inet_aton( address.c_str(), &(reinterpret_cast<sockaddr_in*>(&ifr.ifr_broadaddr)->sin_addr));
00136 
00137     if( ioctl( sock, SIOCSIFBRDADDR, &ifr) < 0)
00138         throw SocketException("ioctl failed (setBroadcastAddress)");
00139 
00140     ::close(sock);
00141 }
00142 
00143 std::string NET::getNetmask( const std::string& interface)
00144 {
00145     struct ifreq ifr;
00146 
00147     ifr.ifr_addr.sa_family = AF_INET;
00148     std::strncpy( ifr.ifr_name, interface.c_str(), sizeof(ifr.ifr_name));
00149 
00150     int sock = ::socket( AF_INET, SOCK_DGRAM, IPPROTO_IP);
00151     if( sock < 0)
00152         throw SocketException("Couldn't create socket (getBroadcastAddress)");
00153 
00154     if( ioctl( sock, SIOCGIFNETMASK, &ifr) < 0)
00155         throw SocketException("ioctl failed (getNetmask)");
00156 
00157     ::close(sock);
00158 
00159     return inet_ntoa( sockaddr_ptr( &ifr.ifr_netmask)->sin_addr);
00160 }
00161 
00162 void NET::setNetmask( const std::string& interface, const std::string& address)
00163 {
00164     struct ifreq ifr;
00165 
00166     ifr.ifr_addr.sa_family = AF_INET;
00167     std::strncpy( ifr.ifr_name, interface.c_str(), sizeof(ifr.ifr_name));
00168 
00169     int sock = ::socket( AF_INET, SOCK_DGRAM, IPPROTO_IP);
00170     if( sock < 0)
00171         throw SocketException("Couldn't create socket (setNetmask)");
00172 
00173     inet_aton( address.c_str(), &(reinterpret_cast<sockaddr_in*>(&ifr.ifr_netmask)->sin_addr));
00174 
00175     if( ioctl( sock, SIOCSIFNETMASK, &ifr) < 0)
00176         throw SocketException("ioctl failed (setNetmask)");
00177 
00178     ::close(sock);
00179 }
00180 
00181 std::string NET::getDestinationAddress( const std::string& interface)
00182 {
00183     struct ifreq ifr;
00184 
00185     ifr.ifr_addr.sa_family = AF_INET;
00186     std::strncpy( ifr.ifr_name, interface.c_str(), sizeof(ifr.ifr_name));
00187 
00188     int sock = ::socket( AF_INET, SOCK_DGRAM, IPPROTO_IP);
00189     if( sock < 0)
00190         throw SocketException("Couldn't create socket (getBroadcastAddress)");
00191 
00192     if( ioctl( sock, SIOCGIFDSTADDR, &ifr) < 0)
00193         throw SocketException("ioctl failed (getDestinationAddress)");
00194 
00195     ::close(sock);
00196 
00197     return inet_ntoa( sockaddr_ptr( &ifr.ifr_dstaddr)->sin_addr);
00198 }
00199 
00200 void NET::setDestinationAddress( const std::string& interface, const std::string& address)
00201 {
00202     struct ifreq ifr;
00203 
00204     ifr.ifr_addr.sa_family = AF_INET;
00205     std::strncpy( ifr.ifr_name, interface.c_str(), sizeof(ifr.ifr_name));
00206 
00207     int sock = ::socket( AF_INET, SOCK_DGRAM, IPPROTO_IP);
00208     if( sock < 0)
00209         throw SocketException("Couldn't create socket (setDestinationAddress)");
00210 
00211     inet_aton( address.c_str(), &(reinterpret_cast<sockaddr_in*>(&ifr.ifr_dstaddr)->sin_addr));
00212 
00213     if( ioctl( sock, SIOCSIFDSTADDR, &ifr) < 0)
00214         throw SocketException("ioctl failed (setDestinationAddress)");
00215 
00216     ::close(sock);
00217 }
00218 
00219 int NET::getMTU( const std::string& interface)
00220 {
00221     struct ifreq ifr;
00222 
00223     ifr.ifr_addr.sa_family = AF_INET;
00224     std::strncpy( ifr.ifr_name, interface.c_str(), sizeof(ifr.ifr_name));
00225 
00226     int sock = ::socket( AF_INET, SOCK_DGRAM, IPPROTO_IP);
00227     if( sock < 0)
00228         throw SocketException("Couldn't create socket (getMTU)");
00229 
00230     if( ioctl( sock, SIOCGIFMTU, &ifr) < 0)
00231         throw SocketException("ioctl failed (getInterfaceAddress)");
00232 
00233     ::close(sock);
00234 
00235     return ifr.ifr_mtu;
00236 }
00237 
00238 void NET::setMTU( const std::string& interface, int mtu)
00239 {
00240     struct ifreq ifr;
00241 
00242     ifr.ifr_addr.sa_family = AF_INET;
00243     std::strncpy( ifr.ifr_name, interface.c_str(), sizeof(ifr.ifr_name));
00244 
00245     int sock = ::socket( AF_INET, SOCK_DGRAM, IPPROTO_IP);
00246     if( sock < 0)
00247         throw SocketException("Couldn't create socket (setMTU)");
00248 
00249     ifr.ifr_mtu = mtu;
00250 
00251     if( ioctl( sock, SIOCSIFDSTADDR, &ifr) < 0)
00252         throw SocketException("ioctl failed (setMTU)");
00253 
00254     ::close(sock);
00255 }
00256 
00257 std::string NET::getHardwareAddress( const std::string& interface, char separationChar)
00258 {
00259     struct ifreq ifr;
00260 
00261     ifr.ifr_addr.sa_family = AF_INET;
00262     std::strncpy( ifr.ifr_name, interface.c_str(), sizeof(ifr.ifr_name));
00263 
00264     int sock = ::socket( AF_INET, SOCK_DGRAM, IPPROTO_IP);
00265     if( sock < 0)
00266         throw SocketException("Couldn't create socket (getMTU)");
00267 
00268     if( ioctl( sock, SIOCGIFHWADDR, &ifr) < 0)
00269         throw SocketException("ioctl failed (getInterfaceAddress)");
00270 
00271     ::close(sock);
00272 
00273     switch( ifr.ifr_hwaddr.sa_family) {
00274         default:
00275             throw SocketException("Invalid Hardware type (getHardwareAddress)");
00276             break;
00277         case ARPHRD_NETROM:
00278         case ARPHRD_ETHER:
00279         case ARPHRD_PPP:
00280         case ARPHRD_EETHER:
00281         case ARPHRD_IEEE802:
00282             break;
00283     }
00284 
00285     std::ostringstream str;
00286     str << std::hex << std::setw(2) << std::setfill('0');
00287 
00288     for( int i = 0; i <= 4; ++i)
00289     {
00290         str << std::uppercase
00291             << static_cast<int>( reinterpret_cast<unsigned char*>( ifr.ifr_addr.sa_data)[i])
00292             << separationChar;
00293     }
00294 
00295     str << std::uppercase
00296         << static_cast<int>( reinterpret_cast<unsigned char*>( ifr.ifr_addr.sa_data)[5]);
00297     return str.str();
00298 }