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