uipc_syscalls_40.c revision 1.1 1 /* $NetBSD: uipc_syscalls_40.c,v 1.1 2007/05/29 21:32:27 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.1 2007/05/29 21:32:27 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 #include <compat/sys/sockio.h>
39 #endif
40 /*
41 * Return interface configuration
42 * of system. List may be used
43 * in later ioctl's (above) to get
44 * other information.
45 */
46 /*ARGSUSED*/
47 int
48 compat_ifconf(u_long cmd, void *data)
49 {
50 struct oifconf *ifc = data;
51 struct ifnet *ifp;
52 struct ifaddr *ifa;
53 struct oifreq ifr, *ifrp;
54 int space = ifc->ifc_len, error = 0;
55 const int sz = (int)sizeof(ifr);
56 int sign;
57
58 if ((ifrp = ifc->ifc_req) == NULL) {
59 space = 0;
60 sign = -1;
61 } else {
62 sign = 1;
63 }
64 IFNET_FOREACH(ifp) {
65 (void)strncpy(ifr.ifr_name, ifp->if_xname,
66 sizeof(ifr.ifr_name));
67 if (ifr.ifr_name[sizeof(ifr.ifr_name) - 1] != '\0')
68 return ENAMETOOLONG;
69 if (TAILQ_EMPTY(&ifp->if_addrlist)) {
70 memset(&ifr.ifr_addr, 0, sizeof(ifr.ifr_addr));
71 if (ifrp != NULL && space >= sz) {
72 error = copyout(&ifr, ifrp, sz);
73 if (error != 0)
74 break;
75 ifrp++;
76 }
77 space -= sizeof(ifr) * sign;
78 continue;
79 }
80
81 TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
82 struct sockaddr *sa = ifa->ifa_addr;
83 #ifdef COMPAT_OSOCK
84 if (cmd == OOSIOCGIFCONF) {
85 struct osockaddr *osa =
86 (struct osockaddr *)&ifr.ifr_addr;
87 /*
88 * If it does not fit, we don't bother with it
89 */
90 if (sa->sa_len > sizeof(*osa))
91 continue;
92 memcpy(&ifr.ifr_addr, sa, sa->sa_len);
93 osa->sa_family = sa->sa_family;
94 if (ifrp != NULL && space >= sz) {
95 error = copyout(&ifr, ifrp, sz);
96 ifrp++;
97 }
98 } else
99 #endif
100 if (sa->sa_len <= sizeof(*sa)) {
101 memcpy(&ifr.ifr_addr, sa, sa->sa_len);
102 if (ifrp != NULL && space >= sz) {
103 error = copyout(&ifr, ifrp, sz);
104 ifrp++;
105 }
106 } else {
107 space -= (sa->sa_len - sizeof(*sa)) * sign;
108 if (ifrp != NULL && space >= sz) {
109 error = copyout(&ifr, ifrp,
110 sizeof(ifr.ifr_name));
111 if (error == 0) {
112 error = copyout(sa,
113 &ifrp->ifr_addr,
114 sa->sa_len);
115 }
116 ifrp = (struct oifreq *)
117 (sa->sa_len +
118 (char *)&ifrp->ifr_addr);
119 }
120 }
121 if (error != 0)
122 break;
123 space -= sz * sign;
124 }
125 }
126 if (ifrp != NULL)
127 ifc->ifc_len -= space;
128 else
129 ifc->ifc_len = space;
130 return error;
131 }
132