uipc_syscalls_40.c revision 1.6
1/*	$NetBSD: uipc_syscalls_40.c,v 1.6 2007/12/05 22:51:28 dyoung 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.6 2007/12/05 22:51:28 dyoung 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, error = 0;
41	const int sz = (int)sizeof(ifr);
42
43	if ((ifrp = ifc->ifc_req) == NULL)
44		space = 0;
45	else
46		space = ifc->ifc_len;
47	IFNET_FOREACH(ifp) {
48		(void)strncpy(ifr.ifr_name, ifp->if_xname,
49		    sizeof(ifr.ifr_name));
50		if (ifr.ifr_name[sizeof(ifr.ifr_name) - 1] != '\0')
51			return ENAMETOOLONG;
52		if (IFADDR_EMPTY(ifp)) {
53			memset(&ifr.ifr_addr, 0, sizeof(ifr.ifr_addr));
54			if (space >= sz) {
55				error = copyout(&ifr, ifrp, sz);
56				if (error != 0)
57					return (error);
58				ifrp++;
59			}
60			space -= sizeof(ifr);
61			continue;
62		}
63
64		IFADDR_FOREACH(ifa, ifp) {
65			struct sockaddr *sa = ifa->ifa_addr;
66#ifdef COMPAT_OSOCK
67			if (cmd == OOSIOCGIFCONF) {
68				struct osockaddr *osa =
69				    (struct osockaddr *)&ifr.ifr_addr;
70				/*
71				 * If it does not fit, we don't bother with it
72				 */
73				if (sa->sa_len > sizeof(*osa))
74					continue;
75				memcpy(&ifr.ifr_addr, sa, sa->sa_len);
76				osa->sa_family = sa->sa_family;
77				if (space >= sz) {
78					error = copyout(&ifr, ifrp, sz);
79					ifrp++;
80				}
81			} else
82#endif
83			if (sa->sa_len <= sizeof(*sa)) {
84				memcpy(&ifr.ifr_addr, sa, sa->sa_len);
85				if (space >= sz) {
86					error = copyout(&ifr, ifrp, sz);
87					ifrp++;
88				}
89			} else {
90				space -= sa->sa_len - sizeof(*sa);
91				if (space >= sz) {
92					error = copyout(&ifr, ifrp,
93					    sizeof(ifr.ifr_name));
94					if (error == 0) {
95						error = copyout(sa,
96						    &ifrp->ifr_addr,
97						    sa->sa_len);
98					}
99					ifrp = (struct oifreq *)
100						(sa->sa_len +
101						 (char *)&ifrp->ifr_addr);
102				}
103			}
104			if (error != 0)
105				return (error);
106			space -= sz;
107		}
108	}
109	if (ifrp != NULL)
110		ifc->ifc_len -= space;
111	else
112		ifc->ifc_len = -space;
113	return (0);
114}
115#endif
116