blocxx

NwIface.cpp

Go to the documentation of this file.
00001 /*******************************************************************************
00002 * Copyright (C) 2005, Vintela, Inc. All rights reserved.
00003 * Copyright (C) 2006, Novell, Inc. All rights reserved.
00004 * 
00005 * Redistribution and use in source and binary forms, with or without
00006 * modification, are permitted provided that the following conditions are met:
00007 * 
00008 *     * Redistributions of source code must retain the above copyright notice,
00009 *       this list of conditions and the following disclaimer.
00010 *     * Redistributions in binary form must reproduce the above copyright
00011 *       notice, this list of conditions and the following disclaimer in the
00012 *       documentation and/or other materials provided with the distribution.
00013 *     * Neither the name of 
00014 *       Vintela, Inc., 
00015 *       nor Novell, Inc., 
00016 *       nor the names of its contributors or employees may be used to 
00017 *       endorse or promote products derived from this software without 
00018 *       specific prior written permission.
00019 * 
00020 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00021 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00022 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00023 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00024 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00025 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00026 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00027 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00028 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00029 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00030 * POSSIBILITY OF SUCH DAMAGE.
00031 *******************************************************************************/
00032 
00033 
00039 #include "blocxx/BLOCXX_config.h"
00040 
00041 #if !defined(BLOCXX_WIN32) && !defined(BLOCXX_NETWARE)
00042 
00043 extern "C"
00044 {
00045 #ifdef BLOCXX_HAVE_UNISTD_H
00046   #include <unistd.h>
00047 #endif
00048 
00049 #include <stdlib.h>
00050 #include <stdio.h>
00051 #include <sys/types.h>
00052 
00053 #ifdef BLOCXX_HAVE_SYS_SOCKET_H
00054   #include <sys/socket.h>
00055 #endif
00056 
00057 #include <arpa/inet.h>
00058 #include <errno.h>
00059 
00060 #ifdef BLOCXX_GNU_LINUX
00061   #include <sys/ioctl.h>
00062   #include <linux/if.h>
00063   #include <string.h>
00064 
00065 #elif defined (BLOCXX_OPENSERVER)
00066   #include <string.h>
00067   #include <stropts.h>
00068   #include <net/if.h>
00069   #include <netinet/in.h>
00070   #include <strings.h>
00071   #include <arpa/inet.h>
00072   #include <fcntl.h>
00073   #include <paths.h>
00074   #include <sys/mdi.h>
00075 
00076 #elif defined (BLOCXX_DARWIN)
00077   #include <net/if.h>
00078   #include <sys/ioctl.h>
00079 #else
00080 
00081   #ifdef BLOCXX_HAVE_STROPTS_H
00082     #include <stropts.h>
00083   #endif
00084 
00085   #include <net/if.h>
00086   #include <netinet/in.h>
00087 
00088   #if defined (BLOCXX_HAVE_SYS_SOCKIO_H)
00089     #include <sys/sockio.h>
00090   #endif
00091 
00092   #include <strings.h>
00093   #include <fcntl.h>
00094 #endif
00095 
00096 #include <string.h>
00097 } // extern "C"
00098 // These need to be after the system includes because of some weird openserver
00099 // include order problem
00100 #include "blocxx/NwIface.hpp"
00101 #include "blocxx/String.hpp"
00102 #include "blocxx/Exception.hpp"
00103 #include "blocxx/SocketUtils.hpp"
00104 
00105 namespace BLOCXX_NAMESPACE
00106 {
00107 
00109 NwIface::NwIface()
00110 {
00111    int s, lerrno;
00112    struct ifreq ifr;
00113    struct sockaddr_in *sin(0);
00114    if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
00115    {
00116       BLOCXX_THROW(SocketException, "socket");
00117    }
00118    getInterfaceName(s);
00119    bzero(&ifr, sizeof(ifr));
00120    strncpy(ifr.ifr_name, m_name.c_str(), sizeof(ifr.ifr_name));
00122    // Get IP address
00123    if (ioctl(s, SIOCGIFADDR, &ifr) < 0)
00124    {
00125       lerrno = errno;
00126       close(s);
00127       BLOCXX_THROW(SocketException, "ioctl:SIOCGIFADDR");
00128    }
00129    sin = reinterpret_cast<struct sockaddr_in *>(&ifr.ifr_addr);
00130    m_addr = sin->sin_addr.s_addr;
00132    // Get the broadcast address
00133    // Testing
00134    if (ioctl(s, SIOCGIFBRDADDR, &ifr) < 0)
00135    {
00136       lerrno = errno;
00137       close(s);
00138       BLOCXX_THROW(SocketException, "ioctl:SIOCGIFBRDADDR");
00139    }
00140    sin = reinterpret_cast<struct sockaddr_in*>(&ifr.ifr_broadaddr);
00141    m_bcastAddr = sin->sin_addr.s_addr;
00143    // Get net mask
00144    if (ioctl(s, SIOCGIFNETMASK, &ifr) < 0)
00145    {
00146       lerrno = errno;
00147       close(s);
00148       BLOCXX_THROW(SocketException, "ioctl:SIOCGIFNETMASK");
00149    }
00150 #ifdef BLOCXX_GNU_LINUX
00151    sin = reinterpret_cast<struct sockaddr_in *>(&ifr.ifr_netmask);
00152 #else
00153    sin = reinterpret_cast<struct sockaddr_in *>(&ifr.ifr_broadaddr);
00154 #endif
00155    m_netmask = sin->sin_addr.s_addr;
00156    close(s);
00157 }
00159 String
00160 NwIface::getName()
00161 {
00162    return m_name;
00163 }
00165 unsigned long
00166 NwIface::getIPAddress()
00167 {
00168    return m_addr;
00169 }
00171 String
00172 NwIface::getIPAddressString()
00173 {
00174    return SocketUtils::inetAddrToString(m_addr);
00175 }
00177 unsigned long
00178 NwIface::getBroadcastAddress()
00179 {
00180    return m_bcastAddr;
00181 }
00183 String
00184 NwIface::getBroadcastAddressString()
00185 {
00186    return SocketUtils::inetAddrToString(m_bcastAddr);
00187 }
00189 /*
00190 String
00191 NwIface::getMACAddressString()
00192 {
00193    return m_macAddress;
00194 }
00195 */
00197 unsigned long
00198 NwIface::getNetmask()
00199 {
00200    return m_netmask;
00201 }
00203 String
00204 NwIface::getNetmaskString()
00205 {
00206    return SocketUtils::inetAddrToString(m_netmask);
00207 }
00209 bool
00210 NwIface::sameNetwork(unsigned long addr)
00211 {
00212    return ((addr & m_netmask) == (m_addr & m_netmask));
00213 }
00215 bool
00216 NwIface::sameNetwork(const String& straddr)
00217 {
00218    return sameNetwork(stringToAddress(straddr));
00219 }
00221 unsigned long
00222 NwIface::stringToAddress(const String& straddr)
00223 {
00224    return inet_addr(straddr.c_str());
00225 }
00227 void
00228 NwIface::getInterfaceName(SocketHandle_t sockfd)
00229 {
00230    char *p(0);
00231    int numreqs = 30;
00232    struct ifconf ifc;
00233    struct ifreq *ifr(0);
00234    struct ifreq ifrcopy;
00235    int n;
00236    int oldlen = -1;
00237    int lerrno = 0;
00238    const char* appliesTo(0);
00239    ifc.ifc_buf = NULL;
00240    for (;;)
00241    {
00242       ifc.ifc_len = sizeof(struct ifreq) * numreqs;
00243       if (ifc.ifc_buf == NULL)
00244       {
00245          ifc.ifc_buf = new char[ifc.ifc_len];
00246       }
00247       else
00248       {
00249          p = new char[ifc.ifc_len];
00250          memmove(p, ifc.ifc_buf, oldlen);
00251          delete [] ifc.ifc_buf;
00252          ifc.ifc_buf = p;
00253       }
00254       oldlen = ifc.ifc_len;
00255       if (ioctl(sockfd, SIOCGIFCONF, &ifc) < 0)
00256       {
00257          lerrno = errno;
00258          appliesTo = "ioctl:SIOCGIFCONF";
00259          break;
00260       }
00261       if (ifc.ifc_len == static_cast<int>(sizeof(struct ifreq) * numreqs))
00262       {
00263          /* assume it overflowed and try again */
00264          numreqs += 10;
00265          continue;
00266       }
00267       break;
00268    }
00269    if (lerrno == 0)
00270    {
00271       lerrno = ENODEV;
00272       appliesTo = "No interfaces found";
00273       ifr = ifc.ifc_req;
00274       for (n = 0; n < ifc.ifc_len; n += sizeof(struct ifreq))
00275       {
00276          ifrcopy = *ifr;
00277          if (ioctl(sockfd, SIOCGIFFLAGS, &ifrcopy) < 0)
00278          {
00279             lerrno = errno;
00280             appliesTo = "ioctl:SIOCGIFFLAGS";
00281             break;
00282          }
00283 #ifdef BLOCXX_GNU_LINUX
00284          if ((ifrcopy.ifr_flags & IFF_UP) && !(ifrcopy.ifr_flags & (IFF_LOOPBACK | IFF_DYNAMIC)))
00285 #else
00286          if ((ifrcopy.ifr_flags & IFF_UP))
00287 #endif
00288          {
00289             m_name = ifr->ifr_name;
00290             lerrno = 0;
00291             break;
00292          }
00293          ifr++;
00294       }
00295    }
00296    if (ifc.ifc_buf != NULL)
00297    {
00298       delete [] ifc.ifc_buf;
00299    }
00300    if (lerrno != 0)
00301    {
00302       BLOCXX_THROW(SocketException, "NwIface::getInterfaceName");
00303    }
00304 }
00305 
00306 } // end namespace BLOCXX_NAMESPACE
00307 
00308 #endif   // #if !defined(BLOCXX_WIN32) && !defined(BLOCXX_NETWARE)
00309