2 Unix SMB/CIFS implementation.
3 Samba utility functions
4 Copyright (C) Andrew Tridgell 1998
5 Copyright (C) Jeremy Allison 2007
6 Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2007
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "system/network.h"
27 #include <sys/types.h>
29 #ifdef HAVE_SYS_TIME_H
34 #ifdef HAVE_SYS_SOCKIO_H
35 #include <sys/sockio.h>
39 #ifdef HAVE_IFACE_GETIFADDRS
40 #define _FOUND_IFACE_ANY
43 void rep_freeifaddrs(struct ifaddrs *ifp)
47 free(ifp->ifa_netmask);
48 free(ifp->ifa_dstaddr);
49 if (ifp->ifa_next != NULL)
50 freeifaddrs(ifp->ifa_next);
54 static struct sockaddr *sockaddr_dup(struct sockaddr *sa)
58 #ifdef HAVE_SOCKADDR_SA_LEN
61 socklen = sizeof(struct sockaddr_storage);
63 ret = calloc(1, socklen);
66 memcpy(ret, sa, socklen);
73 /* this works for Linux 2.2, Solaris 2.5, SunOS4, HPUX 10.20, OSF1
74 V4.0, Ultrix 4.4, SCO Unix 3.2, IRIX 6.4 and FreeBSD 3.2.
76 It probably also works on any BSD style system. */
78 int rep_getifaddrs(struct ifaddrs **ifap)
83 struct ifreq *ifr=NULL;
85 struct in_addr ipaddr;
88 struct ifaddrs *curif, *lastif;
92 if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
96 ifc.ifc_len = sizeof(buff);
99 if (ioctl(fd, SIOCGIFCONF, &ifc) != 0) {
106 n = ifc.ifc_len / sizeof(struct ifreq);
108 /* Loop through interfaces, looking for given IP address */
109 for (i=n-1;i>=0 && total < max_interfaces;i--) {
110 if (ioctl(fd, SIOCGIFADDR, &ifr[i]) != 0) {
114 curif = calloc(1, sizeof(struct ifaddrs));
115 if (lastif == NULL) {
118 lastif->ifa_next = (*ifap);
121 curif->ifa_name = strdup(ifr[i].ifr_name);
122 curif->ifa_addr = sockaddr_dup(&ifr[i].ifr_addr);
123 curif->ifa_dstaddr = NULL;
124 curif->ifa_data = NULL;
125 curif->ifa_next = NULL;
126 curif->ifa_netmask = NULL;
128 if (ioctl(fd, SIOCGIFFLAGS, &ifr[i]) != 0) {
133 curif->ifa_flags = ifr[i].ifr_flags;
135 if (ioctl(fd, SIOCGIFNETMASK, &ifr[i]) != 0) {
140 curif->ifa_netmask = sockaddr_dup(&ifr[i].ifr_addr);
150 #define _FOUND_IFACE_ANY
151 #endif /* HAVE_IFACE_IFCONF */
152 #ifdef HAVE_IFACE_IFREQ
155 #include <sys/stropts.h>
158 /****************************************************************************
159 this should cover most of the streams based systems
160 Thanks to Andrej.Borsenkow@mow.siemens.ru for several ideas in this code
161 ****************************************************************************/
162 int rep_getifaddrs(struct ifaddrs **ifap)
165 struct strioctl strioctl;
168 struct ifreq *ifr=NULL;
170 struct in_addr ipaddr;
171 struct in_addr nmask;
173 struct ifaddrs *curif;
177 if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
181 strioctl.ic_cmd = SIOCGIFCONF;
182 strioctl.ic_dp = buff;
183 strioctl.ic_len = sizeof(buff);
184 if (ioctl(fd, I_STR, &strioctl) < 0) {
189 /* we can ignore the possible sizeof(int) here as the resulting
190 number of interface structures won't change */
191 n = strioctl.ic_len / sizeof(struct ifreq);
193 /* we will assume that the kernel returns the length as an int
194 at the start of the buffer if the offered size is a
195 multiple of the structure size plus an int */
196 if (n*sizeof(struct ifreq) + sizeof(int) == strioctl.ic_len) {
197 ifr = (struct ifreq *)(buff + sizeof(int));
199 ifr = (struct ifreq *)buff;
202 /* Loop through interfaces */
204 for (i = 0; i<n && total < max_interfaces; i++) {
207 curif = calloc(1, sizeof(struct ifaddrs));
208 if (lastif == NULL) {
211 lastif->ifa_next = (*ifap);
214 strioctl.ic_cmd = SIOCGIFFLAGS;
215 strioctl.ic_dp = (char *)&ifreq;
216 strioctl.ic_len = sizeof(struct ifreq);
217 if (ioctl(fd, I_STR, &strioctl) != 0) {
222 curif->ifa_flags = ifreq.ifr_flags;
224 strioctl.ic_cmd = SIOCGIFADDR;
225 strioctl.ic_dp = (char *)&ifreq;
226 strioctl.ic_len = sizeof(struct ifreq);
227 if (ioctl(fd, I_STR, &strioctl) != 0) {
232 curif->ifa_name = strdup(ifreq.ifr_name);
233 curif->ifa_addr = sockaddr_dup(&ifreq.ifr_addr);
234 curif->ifa_dstaddr = NULL;
235 curif->ifa_data = NULL;
236 curif->ifa_next = NULL;
237 curif->ifa_netmask = NULL;
239 strioctl.ic_cmd = SIOCGIFNETMASK;
240 strioctl.ic_dp = (char *)&ifreq;
241 strioctl.ic_len = sizeof(struct ifreq);
242 if (ioctl(fd, I_STR, &strioctl) != 0) {
247 curif->ifa_netmask = sockaddr_dup(&ifreq.ifr_addr);
257 #define _FOUND_IFACE_ANY
258 #endif /* HAVE_IFACE_IFREQ */
259 #ifdef HAVE_IFACE_AIX
261 /****************************************************************************
262 this one is for AIX (tested on 4.2)
263 ****************************************************************************/
264 int rep_getifaddrs(struct ifaddrs **ifap)
269 struct ifreq *ifr=NULL;
270 struct in_addr ipaddr;
271 struct in_addr nmask;
274 struct ifaddrs *curif, *lastif;
278 if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
282 ifc.ifc_len = sizeof(buff);
285 if (ioctl(fd, SIOCGIFCONF, &ifc) != 0) {
292 /* Loop through interfaces */
298 inc = ifr->ifr_addr.sa_len;
300 if (ioctl(fd, SIOCGIFADDR, ifr) != 0) {
305 curif = calloc(1, sizeof(struct ifaddrs));
306 if (lastif == NULL) {
309 lastif->ifa_next = (*ifap);
312 curif->ifa_name = strdup(ifr->ifr_name);
313 curif->ifa_addr = sockaddr_dup(&ifr->ifr_addr);
314 curif->ifa_dstaddr = NULL;
315 curif->ifa_data = NULL;
316 curif->ifa_netmask = NULL;
317 curif->ifa_next = NULL;
319 if (ioctl(fd, SIOCGIFFLAGS, ifr) != 0) {
324 curif->ifa_flags = ifr->ifr_flags;
326 if (ioctl(fd, SIOCGIFNETMASK, ifr) != 0) {
331 curif->ifa_netmask = sockaddr_dup(&ifr->ifr_addr);
337 * Patch from Archie Cobbs (archie@whistle.com). The
338 * addresses in the SIOCGIFCONF interface list have a
339 * minimum size. Usually this doesn't matter, but if
340 * your machine has tunnel interfaces, etc. that have
341 * a zero length "link address", this does matter. */
343 if (inc < sizeof(ifr->ifr_addr))
344 inc = sizeof(ifr->ifr_addr);
347 ifr = (struct ifreq*) (((char*) ifr) + inc);
355 #define _FOUND_IFACE_ANY
356 #endif /* HAVE_IFACE_AIX */
357 #ifndef _FOUND_IFACE_ANY
358 int rep_getifaddrs(struct ifaddrs **ifap)
366 /* this is the autoconf driver to test get_interfaces() */
370 struct ifaddrs *ifs = NULL;
373 ret = getifaddrs(&ifs);
375 perror("getifaddrs() failed");
380 printf("%-10s ", ifs->ifa_name);
381 if (ifs->ifa_addr != NULL &&
382 ifs->ifa_addr->sa_family == AF_INET) {
383 printf("IP=%s ", inet_ntoa(((struct sockaddr_in *)ifs->ifa_addr)->sin_addr));
384 if (ifs->ifa_netmask != NULL)
385 printf("NETMASK=%s", inet_ntoa(((struct sockaddr_in *)ifs->ifa_netmask)->sin_addr));