• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/router/samba-3.5.8/lib/replace/
1/*
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
7
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.
12
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.
17
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/>.
20*/
21
22#define SOCKET_WRAPPER_NOT_REPLACE
23
24#include "replace.h"
25#include "system/network.h"
26
27#include <unistd.h>
28#include <stdio.h>
29#include <sys/types.h>
30
31#ifdef HAVE_SYS_TIME_H
32#include <sys/time.h>
33#endif
34
35#ifndef SIOCGIFCONF
36#ifdef HAVE_SYS_SOCKIO_H
37#include <sys/sockio.h>
38#endif
39#endif
40
41#ifdef HAVE_IFACE_GETIFADDRS
42#define _FOUND_IFACE_ANY
43#else
44
45void rep_freeifaddrs(struct ifaddrs *ifp)
46{
47	if (ifp != NULL) {
48		free(ifp->ifa_name);
49		free(ifp->ifa_addr);
50		free(ifp->ifa_netmask);
51		free(ifp->ifa_dstaddr);
52		freeifaddrs(ifp->ifa_next);
53		free(ifp);
54	}
55}
56
57static struct sockaddr *sockaddr_dup(struct sockaddr *sa)
58{
59	struct sockaddr *ret;
60	socklen_t socklen;
61#ifdef HAVE_SOCKADDR_SA_LEN
62	socklen = sa->sa_len;
63#else
64	socklen = sizeof(struct sockaddr_storage);
65#endif
66	ret = calloc(1, socklen);
67	if (ret == NULL)
68		return NULL;
69	memcpy(ret, sa, socklen);
70	return ret;
71}
72#endif
73
74#if HAVE_IFACE_IFCONF
75
76/* this works for Linux 2.2, Solaris 2.5, SunOS4, HPUX 10.20, OSF1
77   V4.0, Ultrix 4.4, SCO Unix 3.2, IRIX 6.4 and FreeBSD 3.2.
78
79   It probably also works on any BSD style system.  */
80
81int rep_getifaddrs(struct ifaddrs **ifap)
82{
83	struct ifconf ifc;
84	char buff[8192];
85	int fd, i, n;
86	struct ifreq *ifr=NULL;
87	struct ifaddrs *curif;
88	struct ifaddrs *lastif = NULL;
89
90	*ifap = NULL;
91
92	if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
93		return -1;
94	}
95
96	ifc.ifc_len = sizeof(buff);
97	ifc.ifc_buf = buff;
98
99	if (ioctl(fd, SIOCGIFCONF, &ifc) != 0) {
100		close(fd);
101		return -1;
102	}
103
104	ifr = ifc.ifc_req;
105
106	n = ifc.ifc_len / sizeof(struct ifreq);
107
108	/* Loop through interfaces, looking for given IP address */
109	for (i=n-1; i>=0; i--) {
110		if (ioctl(fd, SIOCGIFFLAGS, &ifr[i]) == -1) {
111			freeifaddrs(*ifap);
112			return -1;
113		}
114
115		curif = calloc(1, sizeof(struct ifaddrs));
116		curif->ifa_name = strdup(ifr[i].ifr_name);
117		curif->ifa_flags = ifr[i].ifr_flags;
118		curif->ifa_dstaddr = NULL;
119		curif->ifa_data = NULL;
120		curif->ifa_next = NULL;
121
122		curif->ifa_addr = NULL;
123		if (ioctl(fd, SIOCGIFADDR, &ifr[i]) != -1) {
124			curif->ifa_addr = sockaddr_dup(&ifr[i].ifr_addr);
125		}
126
127		curif->ifa_netmask = NULL;
128		if (ioctl(fd, SIOCGIFNETMASK, &ifr[i]) != -1) {
129			curif->ifa_netmask = sockaddr_dup(&ifr[i].ifr_addr);
130		}
131
132		if (lastif == NULL) {
133			*ifap = curif;
134		} else {
135			lastif->ifa_next = curif;
136		}
137		lastif = curif;
138	}
139
140	close(fd);
141
142	return 0;
143}
144
145#define _FOUND_IFACE_ANY
146#endif /* HAVE_IFACE_IFCONF */
147#ifdef HAVE_IFACE_IFREQ
148
149#ifndef I_STR
150#include <sys/stropts.h>
151#endif
152
153/****************************************************************************
154this should cover most of the streams based systems
155Thanks to Andrej.Borsenkow@mow.siemens.ru for several ideas in this code
156****************************************************************************/
157int rep_getifaddrs(struct ifaddrs **ifap)
158{
159	struct ifreq ifreq;
160	struct strioctl strioctl;
161	char buff[8192];
162	int fd, i, n;
163	struct ifreq *ifr=NULL;
164	struct ifaddrs *curif;
165	struct ifaddrs *lastif = NULL;
166
167	*ifap = NULL;
168
169	if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
170		return -1;
171	}
172
173	strioctl.ic_cmd = SIOCGIFCONF;
174	strioctl.ic_dp  = buff;
175	strioctl.ic_len = sizeof(buff);
176	if (ioctl(fd, I_STR, &strioctl) < 0) {
177		close(fd);
178		return -1;
179	}
180
181	/* we can ignore the possible sizeof(int) here as the resulting
182	   number of interface structures won't change */
183	n = strioctl.ic_len / sizeof(struct ifreq);
184
185	/* we will assume that the kernel returns the length as an int
186           at the start of the buffer if the offered size is a
187           multiple of the structure size plus an int */
188	if (n*sizeof(struct ifreq) + sizeof(int) == strioctl.ic_len) {
189		ifr = (struct ifreq *)(buff + sizeof(int));
190	} else {
191		ifr = (struct ifreq *)buff;
192	}
193
194	/* Loop through interfaces */
195
196	for (i = 0; i<n; i++) {
197		ifreq = ifr[i];
198
199		curif = calloc(1, sizeof(struct ifaddrs));
200		if (lastif == NULL) {
201			*ifap = curif;
202		} else {
203			lastif->ifa_next = curif;
204		}
205
206		strioctl.ic_cmd = SIOCGIFFLAGS;
207		strioctl.ic_dp  = (char *)&ifreq;
208		strioctl.ic_len = sizeof(struct ifreq);
209		if (ioctl(fd, I_STR, &strioctl) != 0) {
210			freeifaddrs(*ifap);
211			return -1;
212		}
213
214		curif->ifa_flags = ifreq.ifr_flags;
215
216		strioctl.ic_cmd = SIOCGIFADDR;
217		strioctl.ic_dp  = (char *)&ifreq;
218		strioctl.ic_len = sizeof(struct ifreq);
219		if (ioctl(fd, I_STR, &strioctl) != 0) {
220			freeifaddrs(*ifap);
221			return -1;
222		}
223
224		curif->ifa_name = strdup(ifreq.ifr_name);
225		curif->ifa_addr = sockaddr_dup(&ifreq.ifr_addr);
226		curif->ifa_dstaddr = NULL;
227		curif->ifa_data = NULL;
228		curif->ifa_next = NULL;
229		curif->ifa_netmask = NULL;
230
231		strioctl.ic_cmd = SIOCGIFNETMASK;
232		strioctl.ic_dp  = (char *)&ifreq;
233		strioctl.ic_len = sizeof(struct ifreq);
234		if (ioctl(fd, I_STR, &strioctl) != 0) {
235			freeifaddrs(*ifap);
236			return -1;
237		}
238
239		curif->ifa_netmask = sockaddr_dup(&ifreq.ifr_addr);
240
241		lastif = curif;
242	}
243
244	close(fd);
245
246	return 0;
247}
248
249#define _FOUND_IFACE_ANY
250#endif /* HAVE_IFACE_IFREQ */
251#ifdef HAVE_IFACE_AIX
252
253/****************************************************************************
254this one is for AIX (tested on 4.2)
255****************************************************************************/
256int rep_getifaddrs(struct ifaddrs **ifap)
257{
258	char buff[8192];
259	int fd, i;
260	struct ifconf ifc;
261	struct ifreq *ifr=NULL;
262	struct ifaddrs *curif;
263	struct ifaddrs *lastif = NULL;
264
265	*ifap = NULL;
266
267	if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
268		return -1;
269	}
270
271	ifc.ifc_len = sizeof(buff);
272	ifc.ifc_buf = buff;
273
274	if (ioctl(fd, SIOCGIFCONF, &ifc) != 0) {
275		close(fd);
276		return -1;
277	}
278
279	ifr = ifc.ifc_req;
280
281	/* Loop through interfaces */
282	i = ifc.ifc_len;
283
284	while (i > 0) {
285		uint_t inc;
286
287		inc = ifr->ifr_addr.sa_len;
288
289		if (ioctl(fd, SIOCGIFADDR, ifr) != 0) {
290			freeaddrinfo(*ifap);
291			return -1;
292		}
293
294		curif = calloc(1, sizeof(struct ifaddrs));
295		if (lastif == NULL) {
296			*ifap = curif;
297		} else {
298			lastif->ifa_next = curif;
299		}
300
301		curif->ifa_name = strdup(ifr->ifr_name);
302		curif->ifa_addr = sockaddr_dup(&ifr->ifr_addr);
303		curif->ifa_dstaddr = NULL;
304		curif->ifa_data = NULL;
305		curif->ifa_netmask = NULL;
306		curif->ifa_next = NULL;
307
308		if (ioctl(fd, SIOCGIFFLAGS, ifr) != 0) {
309			freeaddrinfo(*ifap);
310			return -1;
311		}
312
313		curif->ifa_flags = ifr->ifr_flags;
314
315		if (ioctl(fd, SIOCGIFNETMASK, ifr) != 0) {
316			freeaddrinfo(*ifap);
317			return -1;
318		}
319
320		curif->ifa_netmask = sockaddr_dup(&ifr->ifr_addr);
321
322		lastif = curif;
323
324	next:
325		/*
326		 * Patch from Archie Cobbs (archie@whistle.com).  The
327		 * addresses in the SIOCGIFCONF interface list have a
328		 * minimum size. Usually this doesn't matter, but if
329		 * your machine has tunnel interfaces, etc. that have
330		 * a zero length "link address", this does matter.  */
331
332		if (inc < sizeof(ifr->ifr_addr))
333			inc = sizeof(ifr->ifr_addr);
334		inc += IFNAMSIZ;
335
336		ifr = (struct ifreq*) (((char*) ifr) + inc);
337		i -= inc;
338	}
339
340	close(fd);
341	return 0;
342}
343
344#define _FOUND_IFACE_ANY
345#endif /* HAVE_IFACE_AIX */
346#ifndef _FOUND_IFACE_ANY
347int rep_getifaddrs(struct ifaddrs **ifap)
348{
349	errno = ENOSYS;
350	return -1;
351}
352#endif
353