uipc_syscalls_40.c revision 1.11 1 /* $NetBSD: uipc_syscalls_40.c,v 1.11 2016/07/07 09:32:02 ozaki-r 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.11 2016/07/07 09:32:02 ozaki-r 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/syscallargs.h>
17 #include <sys/errno.h>
18
19 #include <net/if.h>
20
21 #include <compat/sys/socket.h>
22 #include <compat/sys/sockio.h>
23
24 #ifdef COMPAT_OIFREQ
25 /*
26 * Return interface configuration
27 * of system. List may be used
28 * in later ioctl's (above) to get
29 * other information.
30 */
31 /*ARGSUSED*/
32 int
33 compat_ifconf(u_long cmd, void *data)
34 {
35 struct oifconf *ifc = data;
36 struct ifnet *ifp;
37 struct ifaddr *ifa;
38 struct oifreq ifr, *ifrp = NULL;
39 int space = 0, error = 0;
40 const int sz = (int)sizeof(ifr);
41 const bool docopy = ifc->ifc_req != NULL;
42 int s;
43 int bound;
44 struct psref psref;
45
46 if (docopy) {
47 space = ifc->ifc_len;
48 ifrp = ifc->ifc_req;
49 }
50
51 bound = curlwp_bind();
52 s = pserialize_read_enter();
53 IFNET_READER_FOREACH(ifp) {
54 psref_acquire(&psref, &ifp->if_psref, ifnet_psref_class);
55 pserialize_read_exit(s);
56
57 (void)strncpy(ifr.ifr_name, ifp->if_xname,
58 sizeof(ifr.ifr_name));
59 if (ifr.ifr_name[sizeof(ifr.ifr_name) - 1] != '\0') {
60 error = ENAMETOOLONG;
61 goto release_exit;
62 }
63 if (IFADDR_READER_EMPTY(ifp)) {
64 memset(&ifr.ifr_addr, 0, sizeof(ifr.ifr_addr));
65 if (space >= sz) {
66 error = copyout(&ifr, ifrp, sz);
67 if (error != 0)
68 goto release_exit;
69 ifrp++;
70 }
71 space -= sizeof(ifr);
72 continue;
73 }
74
75 IFADDR_READER_FOREACH(ifa, ifp) {
76 struct sockaddr *sa = ifa->ifa_addr;
77 #ifdef COMPAT_OSOCK
78 if (cmd == OOSIOCGIFCONF) {
79 struct osockaddr *osa =
80 (struct osockaddr *)&ifr.ifr_addr;
81 /*
82 * If it does not fit, we don't bother with it
83 */
84 if (sa->sa_len > sizeof(*osa))
85 continue;
86 memcpy(&ifr.ifr_addr, sa, sa->sa_len);
87 osa->sa_family = sa->sa_family;
88 if (space >= sz) {
89 error = copyout(&ifr, ifrp, sz);
90 ifrp++;
91 }
92 } else
93 #endif
94 if (sa->sa_len <= sizeof(*sa)) {
95 memcpy(&ifr.ifr_addr, sa, sa->sa_len);
96 if (space >= sz) {
97 error = copyout(&ifr, ifrp, sz);
98 ifrp++;
99 }
100 } else {
101 space -= sa->sa_len - sizeof(*sa);
102 if (space >= sz) {
103 error = copyout(&ifr, ifrp,
104 sizeof(ifr.ifr_name));
105 if (error == 0) {
106 error = copyout(sa,
107 &ifrp->ifr_addr,
108 sa->sa_len);
109 }
110 ifrp = (struct oifreq *)
111 (sa->sa_len +
112 (char *)&ifrp->ifr_addr);
113 }
114 }
115 if (error != 0)
116 goto release_exit;
117 space -= sz;
118 }
119
120 s = pserialize_read_enter();
121 psref_release(&psref, &ifp->if_psref, ifnet_psref_class);
122 }
123 pserialize_read_exit(s);
124 curlwp_bindx(bound);
125
126 if (docopy)
127 ifc->ifc_len -= space;
128 else
129 ifc->ifc_len = -space;
130 return (0);
131
132 release_exit:
133 psref_release(&psref, &ifp->if_psref, ifnet_psref_class);
134 curlwp_bindx(bound);
135 return error;
136 }
137 #endif
138