uipc_syscalls_40.c revision 1.24 1 1.24 riastrad /* $NetBSD: uipc_syscalls_40.c,v 1.24 2022/07/07 18:17:33 riastradh Exp $ */
2 1.1 christos
3 1.1 christos /* written by Pavel Cahyna, 2006. Public domain. */
4 1.1 christos
5 1.1 christos #include <sys/cdefs.h>
6 1.24 riastrad __KERNEL_RCSID(0, "$NetBSD: uipc_syscalls_40.c,v 1.24 2022/07/07 18:17:33 riastradh Exp $");
7 1.17 pgoyette
8 1.17 pgoyette #if defined(_KERNEL_OPT)
9 1.17 pgoyette #include "opt_compat_netbsd.h"
10 1.17 pgoyette #endif
11 1.1 christos
12 1.1 christos /*
13 1.1 christos * System call interface to the socket abstraction.
14 1.1 christos */
15 1.1 christos
16 1.1 christos #include <sys/param.h>
17 1.1 christos #include <sys/kernel.h>
18 1.1 christos #include <sys/msg.h>
19 1.1 christos #include <sys/sysctl.h>
20 1.1 christos #include <sys/syscallargs.h>
21 1.1 christos #include <sys/errno.h>
22 1.17 pgoyette #include <sys/compat_stub.h>
23 1.1 christos
24 1.1 christos #include <net/if.h>
25 1.1 christos
26 1.1 christos #include <compat/sys/socket.h>
27 1.3 christos #include <compat/sys/sockio.h>
28 1.1 christos
29 1.17 pgoyette #include <compat/common/compat_mod.h>
30 1.17 pgoyette
31 1.1 christos /*
32 1.20 msaitoh * Return interface configuration of system. List may be used in later
33 1.20 msaitoh * ioctl's (above) to get other information.
34 1.1 christos */
35 1.1 christos /*ARGSUSED*/
36 1.16 christos static int
37 1.17 pgoyette compat_ifconf(u_long cmd, void *data)
38 1.1 christos {
39 1.1 christos struct oifconf *ifc = data;
40 1.1 christos struct ifnet *ifp;
41 1.8 ozaki struct oifreq ifr, *ifrp = NULL;
42 1.8 ozaki int space = 0, error = 0;
43 1.1 christos const int sz = (int)sizeof(ifr);
44 1.9 ozaki int s;
45 1.10 ozaki int bound;
46 1.9 ozaki struct psref psref;
47 1.1 christos
48 1.16 christos switch (cmd) {
49 1.16 christos case OSIOCGIFCONF:
50 1.16 christos case OOSIOCGIFCONF:
51 1.16 christos break;
52 1.16 christos default:
53 1.16 christos return ENOSYS;
54 1.16 christos }
55 1.16 christos
56 1.24 riastrad const bool docopy = ifc->ifc_req != NULL;
57 1.8 ozaki if (docopy) {
58 1.23 msaitoh if (ifc->ifc_len < 0)
59 1.23 msaitoh return EINVAL;
60 1.23 msaitoh
61 1.4 enami space = ifc->ifc_len;
62 1.8 ozaki ifrp = ifc->ifc_req;
63 1.8 ozaki }
64 1.23 msaitoh memset(&ifr, 0, sizeof(ifr));
65 1.8 ozaki
66 1.10 ozaki bound = curlwp_bind();
67 1.9 ozaki s = pserialize_read_enter();
68 1.9 ozaki IFNET_READER_FOREACH(ifp) {
69 1.12 ozaki struct ifaddr *ifa;
70 1.12 ozaki
71 1.13 ozaki if_acquire(ifp, &psref);
72 1.14 ozaki pserialize_read_exit(s);
73 1.9 ozaki
74 1.1 christos (void)strncpy(ifr.ifr_name, ifp->if_xname,
75 1.1 christos sizeof(ifr.ifr_name));
76 1.9 ozaki if (ifr.ifr_name[sizeof(ifr.ifr_name) - 1] != '\0') {
77 1.9 ozaki error = ENAMETOOLONG;
78 1.9 ozaki goto release_exit;
79 1.9 ozaki }
80 1.11 ozaki if (IFADDR_READER_EMPTY(ifp)) {
81 1.1 christos memset(&ifr.ifr_addr, 0, sizeof(ifr.ifr_addr));
82 1.4 enami if (space >= sz) {
83 1.1 christos error = copyout(&ifr, ifrp, sz);
84 1.1 christos if (error != 0)
85 1.9 ozaki goto release_exit;
86 1.1 christos ifrp++;
87 1.1 christos }
88 1.4 enami space -= sizeof(ifr);
89 1.14 ozaki goto next;
90 1.1 christos }
91 1.1 christos
92 1.14 ozaki s = pserialize_read_enter();
93 1.11 ozaki IFADDR_READER_FOREACH(ifa, ifp) {
94 1.1 christos struct sockaddr *sa = ifa->ifa_addr;
95 1.12 ozaki struct psref psref_ifa;
96 1.12 ozaki
97 1.12 ozaki ifa_acquire(ifa, &psref_ifa);
98 1.12 ozaki pserialize_read_exit(s);
99 1.1 christos #ifdef COMPAT_OSOCK
100 1.1 christos if (cmd == OOSIOCGIFCONF) {
101 1.1 christos struct osockaddr *osa =
102 1.4 enami (struct osockaddr *)&ifr.ifr_addr;
103 1.1 christos /*
104 1.1 christos * If it does not fit, we don't bother with it
105 1.1 christos */
106 1.14 ozaki if (sa->sa_len > sizeof(*osa))
107 1.14 ozaki goto next_ifa;
108 1.1 christos memcpy(&ifr.ifr_addr, sa, sa->sa_len);
109 1.1 christos osa->sa_family = sa->sa_family;
110 1.4 enami if (space >= sz) {
111 1.1 christos error = copyout(&ifr, ifrp, sz);
112 1.1 christos ifrp++;
113 1.1 christos }
114 1.1 christos } else
115 1.1 christos #endif
116 1.1 christos if (sa->sa_len <= sizeof(*sa)) {
117 1.1 christos memcpy(&ifr.ifr_addr, sa, sa->sa_len);
118 1.4 enami if (space >= sz) {
119 1.1 christos error = copyout(&ifr, ifrp, sz);
120 1.1 christos ifrp++;
121 1.1 christos }
122 1.1 christos } else {
123 1.4 enami space -= sa->sa_len - sizeof(*sa);
124 1.4 enami if (space >= sz) {
125 1.22 maxv error = copyout(&ifr.ifr_name, ifrp,
126 1.1 christos sizeof(ifr.ifr_name));
127 1.1 christos if (error == 0) {
128 1.1 christos error = copyout(sa,
129 1.1 christos &ifrp->ifr_addr,
130 1.1 christos sa->sa_len);
131 1.1 christos }
132 1.1 christos ifrp = (struct oifreq *)
133 1.1 christos (sa->sa_len +
134 1.1 christos (char *)&ifrp->ifr_addr);
135 1.1 christos }
136 1.1 christos }
137 1.14 ozaki if (error != 0) {
138 1.14 ozaki ifa_release(ifa, &psref_ifa);
139 1.14 ozaki goto release_exit;
140 1.14 ozaki }
141 1.14 ozaki space -= sz;
142 1.14 ozaki
143 1.15 martin #ifdef COMPAT_OSOCK
144 1.14 ozaki next_ifa:
145 1.15 martin #endif
146 1.12 ozaki s = pserialize_read_enter();
147 1.12 ozaki ifa_release(ifa, &psref_ifa);
148 1.1 christos }
149 1.14 ozaki pserialize_read_exit(s);
150 1.9 ozaki
151 1.14 ozaki next:
152 1.14 ozaki s = pserialize_read_enter();
153 1.13 ozaki if_release(ifp, &psref);
154 1.1 christos }
155 1.9 ozaki pserialize_read_exit(s);
156 1.10 ozaki curlwp_bindx(bound);
157 1.9 ozaki
158 1.8 ozaki if (docopy)
159 1.1 christos ifc->ifc_len -= space;
160 1.1 christos else
161 1.4 enami ifc->ifc_len = -space;
162 1.20 msaitoh return 0;
163 1.9 ozaki
164 1.9 ozaki release_exit:
165 1.13 ozaki if_release(ifp, &psref);
166 1.10 ozaki curlwp_bindx(bound);
167 1.9 ozaki return error;
168 1.1 christos }
169 1.16 christos
170 1.17 pgoyette void
171 1.16 christos uipc_syscalls_40_init(void)
172 1.16 christos {
173 1.17 pgoyette
174 1.21 pgoyette MODULE_HOOK_SET(uipc_syscalls_40_hook, compat_ifconf);
175 1.16 christos }
176 1.17 pgoyette
177 1.16 christos void
178 1.16 christos uipc_syscalls_40_fini(void)
179 1.16 christos {
180 1.17 pgoyette
181 1.18 pgoyette MODULE_HOOK_UNSET(uipc_syscalls_40_hook);
182 1.16 christos }
183