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*/
49 int
50 compat_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