uipc_syscalls_40.c revision 1.3
1/*	$NetBSD: uipc_syscalls_40.c,v 1.3 2007/05/30 21:02:02 christos Exp $	*/
2
3/* written by Pavel Cahyna, 2006. Public domain. */
4
5#include <sys/cdefs.h>
6__KERNEL_RCSID(0, "$NetBSD: uipc_syscalls_40.c,v 1.3 2007/05/30 21:02:02 christos Exp $");
7
8/*
9 * System call interface to the socket abstraction.
10 */
11
12#include <sys/param.h>
13#include <sys/kernel.h>
14#include <sys/msg.h>
15#include <sys/sysctl.h>
16#include <sys/mount.h>
17#include <sys/syscallargs.h>
18#include <sys/errno.h>
19
20#include <net/if.h>
21
22#include <compat/sys/socket.h>
23#include <compat/sys/sockio.h>
24
25#ifdef COMPAT_OIFREQ
26/*
27 * Return interface configuration
28 * of system.  List may be used
29 * in later ioctl's (above) to get
30 * other information.
31 */
32/*ARGSUSED*/
33int
34compat_ifconf(u_long cmd, void *data)
35{
36	struct oifconf *ifc = data;
37	struct ifnet *ifp;
38	struct ifaddr *ifa;
39	struct oifreq ifr, *ifrp;
40	int space = ifc->ifc_len, error = 0;
41	const int sz = (int)sizeof(ifr);
42	int sign;
43
44	if ((ifrp = ifc->ifc_req) == NULL) {
45		space = 0;
46		sign = -1;
47	} else {
48		sign = 1;
49	}
50	IFNET_FOREACH(ifp) {
51		(void)strncpy(ifr.ifr_name, ifp->if_xname,
52		    sizeof(ifr.ifr_name));
53		if (ifr.ifr_name[sizeof(ifr.ifr_name) - 1] != '\0')
54			return ENAMETOOLONG;
55		if (TAILQ_EMPTY(&ifp->if_addrlist)) {
56			memset(&ifr.ifr_addr, 0, sizeof(ifr.ifr_addr));
57			if (ifrp != NULL && space >= sz) {
58				error = copyout(&ifr, ifrp, sz);
59				if (error != 0)
60					break;
61				ifrp++;
62			}
63			space -= sizeof(ifr) * sign;
64			continue;
65		}
66
67		TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
68			struct sockaddr *sa = ifa->ifa_addr;
69#ifdef COMPAT_OSOCK
70			if (cmd == OOSIOCGIFCONF) {
71				struct osockaddr *osa =
72					 (struct osockaddr *)&ifr.ifr_addr;
73				/*
74				 * If it does not fit, we don't bother with it
75				 */
76				if (sa->sa_len > sizeof(*osa))
77					continue;
78				memcpy(&ifr.ifr_addr, sa, sa->sa_len);
79				osa->sa_family = sa->sa_family;
80				if (ifrp != NULL && space >= sz) {
81					error = copyout(&ifr, ifrp, sz);
82					ifrp++;
83				}
84			} else
85#endif
86			if (sa->sa_len <= sizeof(*sa)) {
87				memcpy(&ifr.ifr_addr, sa, sa->sa_len);
88				if (ifrp != NULL && space >= sz) {
89					error = copyout(&ifr, ifrp, sz);
90					ifrp++;
91				}
92			} else {
93				space -= (sa->sa_len - sizeof(*sa)) * sign;
94				if (ifrp != NULL && space >= sz) {
95					error = copyout(&ifr, ifrp,
96					    sizeof(ifr.ifr_name));
97					if (error == 0) {
98						error = copyout(sa,
99						    &ifrp->ifr_addr,
100						    sa->sa_len);
101					}
102					ifrp = (struct oifreq *)
103						(sa->sa_len +
104						 (char *)&ifrp->ifr_addr);
105				}
106			}
107			if (error != 0)
108				break;
109			space -= sz * sign;
110		}
111	}
112	if (ifrp != NULL)
113		ifc->ifc_len -= space;
114	else
115		ifc->ifc_len = space;
116	return error;
117}
118#endif
119