blocxx
NwIface.cpp
Go to the documentation of this file.
1 /*******************************************************************************
2 * Copyright (C) 2005, Vintela, Inc. All rights reserved.
3 * Copyright (C) 2006, Novell, Inc. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * * Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * * Neither the name of
14 * Vintela, Inc.,
15 * nor Novell, Inc.,
16 * nor the names of its contributors or employees may be used to
17 * endorse or promote products derived from this software without
18 * specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
31 *******************************************************************************/
32 
33 
39 #include "blocxx/BLOCXX_config.h"
40 
41 #if !defined(BLOCXX_WIN32) && !defined(BLOCXX_NETWARE)
42 
43 extern "C"
44 {
45 #ifdef BLOCXX_HAVE_UNISTD_H
46  #include <unistd.h>
47 #endif
48 
49 #include <stdlib.h>
50 #include <stdio.h>
51 #include <sys/types.h>
52 
53 #ifdef BLOCXX_HAVE_SYS_SOCKET_H
54  #include <sys/socket.h>
55 #endif
56 
57 #include <arpa/inet.h>
58 #include <errno.h>
59 
60 #ifdef BLOCXX_GNU_LINUX
61  #include <sys/ioctl.h>
62  #include <linux/if.h>
63  #include <string.h>
64 
65 #elif defined (BLOCXX_OPENSERVER)
66  #include <string.h>
67  #include <stropts.h>
68  #include <net/if.h>
69  #include <netinet/in.h>
70  #include <strings.h>
71  #include <arpa/inet.h>
72  #include <fcntl.h>
73  #include <paths.h>
74  #include <sys/mdi.h>
75 
76 #elif defined (BLOCXX_DARWIN)
77  #include <net/if.h>
78  #include <sys/ioctl.h>
79 #else
80 
81  #ifdef BLOCXX_HAVE_STROPTS_H
82  #include <stropts.h>
83  #endif
84 
85  #include <net/if.h>
86  #include <netinet/in.h>
87 
88  #if defined (BLOCXX_HAVE_SYS_SOCKIO_H)
89  #include <sys/sockio.h>
90  #endif
91 
92  #include <strings.h>
93  #include <fcntl.h>
94 #endif
95 
96 #include <string.h>
97 } // extern "C"
98 // These need to be after the system includes because of some weird openserver
99 // include order problem
100 #include "blocxx/NwIface.hpp"
101 #include "blocxx/String.hpp"
102 #include "blocxx/Exception.hpp"
103 #include "blocxx/SocketUtils.hpp"
104 
105 namespace BLOCXX_NAMESPACE
106 {
107 
110 {
111  int s, lerrno;
112  struct ifreq ifr;
113  struct sockaddr_in *sin(0);
114  if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
115  {
116  BLOCXX_THROW(SocketException, "socket");
117  }
118  getInterfaceName(s);
119  bzero(&ifr, sizeof(ifr));
120  strncpy(ifr.ifr_name, m_name.c_str(), sizeof(ifr.ifr_name));
122  // Get IP address
123  if (ioctl(s, SIOCGIFADDR, &ifr) < 0)
124  {
125  lerrno = errno;
126  close(s);
127  BLOCXX_THROW(SocketException, "ioctl:SIOCGIFADDR");
128  }
129  sin = reinterpret_cast<struct sockaddr_in *>(&ifr.ifr_addr);
130  m_addr = sin->sin_addr.s_addr;
132  // Get the broadcast address
133  // Testing
134  if (ioctl(s, SIOCGIFBRDADDR, &ifr) < 0)
135  {
136  lerrno = errno;
137  close(s);
138  BLOCXX_THROW(SocketException, "ioctl:SIOCGIFBRDADDR");
139  }
140  sin = reinterpret_cast<struct sockaddr_in*>(&ifr.ifr_broadaddr);
141  m_bcastAddr = sin->sin_addr.s_addr;
143  // Get net mask
144  if (ioctl(s, SIOCGIFNETMASK, &ifr) < 0)
145  {
146  lerrno = errno;
147  close(s);
148  BLOCXX_THROW(SocketException, "ioctl:SIOCGIFNETMASK");
149  }
150 #ifdef BLOCXX_GNU_LINUX
151  sin = reinterpret_cast<struct sockaddr_in *>(&ifr.ifr_netmask);
152 #else
153  sin = reinterpret_cast<struct sockaddr_in *>(&ifr.ifr_broadaddr);
154 #endif
155  m_netmask = sin->sin_addr.s_addr;
156  close(s);
157 }
159 String
161 {
162  return m_name;
163 }
165 unsigned long
167 {
168  return m_addr;
169 }
171 String
173 {
175 }
177 unsigned long
179 {
180  return m_bcastAddr;
181 }
183 String
185 {
187 }
189 /*
190 String
191 NwIface::getMACAddressString()
192 {
193  return m_macAddress;
194 }
195 */
197 unsigned long
199 {
200  return m_netmask;
201 }
203 String
205 {
207 }
209 bool
210 NwIface::sameNetwork(unsigned long addr)
211 {
212  return ((addr & m_netmask) == (m_addr & m_netmask));
213 }
215 bool
217 {
218  return sameNetwork(stringToAddress(straddr));
219 }
221 unsigned long
223 {
224  return inet_addr(straddr.c_str());
225 }
227 void
229 {
230  char *p(0);
231  int numreqs = 30;
232  struct ifconf ifc;
233  struct ifreq *ifr(0);
234  struct ifreq ifrcopy;
235  int n;
236  int oldlen = -1;
237  int lerrno = 0;
238  const char* appliesTo(0);
239  ifc.ifc_buf = NULL;
240  for (;;)
241  {
242  ifc.ifc_len = sizeof(struct ifreq) * numreqs;
243  if (ifc.ifc_buf == NULL)
244  {
245  ifc.ifc_buf = new char[ifc.ifc_len];
246  }
247  else
248  {
249  p = new char[ifc.ifc_len];
250  memmove(p, ifc.ifc_buf, oldlen);
251  delete [] ifc.ifc_buf;
252  ifc.ifc_buf = p;
253  }
254  oldlen = ifc.ifc_len;
255  if (ioctl(sockfd, SIOCGIFCONF, &ifc) < 0)
256  {
257  lerrno = errno;
258  appliesTo = "ioctl:SIOCGIFCONF";
259  break;
260  }
261  if (ifc.ifc_len == static_cast<int>(sizeof(struct ifreq) * numreqs))
262  {
263  /* assume it overflowed and try again */
264  numreqs += 10;
265  continue;
266  }
267  break;
268  }
269  if (lerrno == 0)
270  {
271  lerrno = ENODEV;
272  appliesTo = "No interfaces found";
273  ifr = ifc.ifc_req;
274  for (n = 0; n < ifc.ifc_len; n += sizeof(struct ifreq))
275  {
276  ifrcopy = *ifr;
277  if (ioctl(sockfd, SIOCGIFFLAGS, &ifrcopy) < 0)
278  {
279  lerrno = errno;
280  appliesTo = "ioctl:SIOCGIFFLAGS";
281  break;
282  }
283 #ifdef BLOCXX_GNU_LINUX
284  if ((ifrcopy.ifr_flags & IFF_UP) && !(ifrcopy.ifr_flags & (IFF_LOOPBACK | IFF_DYNAMIC)))
285 #else
286  if ((ifrcopy.ifr_flags & IFF_UP))
287 #endif
288  {
289  m_name = ifr->ifr_name;
290  lerrno = 0;
291  break;
292  }
293  ifr++;
294  }
295  }
296  if (ifc.ifc_buf != NULL)
297  {
298  delete [] ifc.ifc_buf;
299  }
300  if (lerrno != 0)
301  {
302  BLOCXX_THROW(SocketException, "NwIface::getInterfaceName");
303  }
304 }
305 
306 } // end namespace BLOCXX_NAMESPACE
307 
308 #endif // #if !defined(BLOCXX_WIN32) && !defined(BLOCXX_NETWARE)
309