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*/
33 int
34 compat_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