blocxx
|
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