uipc_syscalls_43.c revision 1.15 1 /* $NetBSD: uipc_syscalls_43.c,v 1.15 2001/07/17 11:49:40 jdolecek Exp $ */
2
3 /*
4 * Copyright (c) 1982, 1986, 1989, 1990, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by the University of
18 * California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 *
35 * @(#)uipc_syscalls.c 8.4 (Berkeley) 2/21/94
36 */
37
38 #include <sys/param.h>
39 #include <sys/systm.h>
40 #include <sys/filedesc.h>
41 #include <sys/kernel.h>
42 #include <sys/proc.h>
43 #include <sys/file.h>
44 #include <sys/socket.h>
45 #include <sys/socketvar.h>
46 #include <sys/stat.h>
47 #include <sys/ioctl.h>
48 #include <sys/fcntl.h>
49 #include <sys/malloc.h>
50 #include <sys/syslog.h>
51 #include <sys/unistd.h>
52 #include <sys/resourcevar.h>
53 #include <sys/mbuf.h> /* for MLEN */
54
55 #include <sys/mount.h>
56 #include <sys/syscallargs.h>
57
58 #include <compat/common/compat_util.h>
59
60 #include <uvm/uvm_extern.h>
61
62 /*
63 * Following 4.3 syscalls were not versioned, even through they should
64 * have been:
65 * connect(2), bind(2), sendto(2)
66 */
67
68 static int compat_43_sa_put(caddr_t);
69
70 int
71 compat_43_sys_accept(p, v, retval)
72 struct proc *p;
73 void *v;
74 register_t *retval;
75 {
76 struct compat_43_sys_accept_args /* {
77 syscallarg(int) s;
78 syscallarg(caddr_t) name;
79 syscallarg(int *) anamelen;
80 } */ *uap = v;
81 int error;
82
83 if ((error = sys_accept(p, v, retval)) != 0)
84 return error;
85
86 if (SCARG(uap, name)
87 && (error = compat_43_sa_put(SCARG(uap, name))))
88 return (error);
89
90 return 0;
91 }
92
93 int
94 compat_43_sys_getpeername(p, v, retval)
95 struct proc *p;
96 void *v;
97 register_t *retval;
98 {
99 struct compat_43_sys_getpeername_args /* {
100 syscallarg(int) fdes;
101 syscallarg(caddr_t) asa;
102 syscallarg(int *) alen;
103 } */ *uap = v;
104
105 int error;
106
107 if ((error = sys_getpeername(p, v, retval)) != 0)
108 return error;
109
110 if ((error = compat_43_sa_put(SCARG(uap, asa))))
111 return (error);
112
113 return 0;
114 }
115
116 int
117 compat_43_sys_getsockname(p, v, retval)
118 struct proc *p;
119 void *v;
120 register_t *retval;
121 {
122 struct compat_43_sys_getsockname_args /* {
123 syscallarg(int) fdes;
124 syscallarg(caddr_t) asa;
125 syscallarg(int *) alen;
126 } */ *uap = v;
127 int error;
128
129 if ((error = sys_getsockname(p, v, retval)) != 0)
130 return error;
131
132 if ((error = compat_43_sa_put(SCARG(uap, asa))))
133 return (error);
134
135 return 0;
136 }
137
138 int
139 compat_43_sys_recv(p, v, retval)
140 struct proc *p;
141 void *v;
142 register_t *retval;
143 {
144 struct compat_43_sys_recv_args /* {
145 syscallarg(int) s;
146 syscallarg(caddr_t) buf;
147 syscallarg(int) len;
148 syscallarg(int) flags;
149 } */ *uap = v;
150 struct sys_recvfrom_args bra;
151
152 SCARG(&bra, s) = SCARG(uap, s);
153 SCARG(&bra, buf) = SCARG(uap, buf);
154 SCARG(&bra, len) = (size_t) SCARG(uap, len);
155 SCARG(&bra, flags) = SCARG(uap, flags);
156 SCARG(&bra, from) = NULL;
157 SCARG(&bra, fromlenaddr) = NULL;
158
159 return (sys_recvfrom(p, &bra, retval));
160 }
161
162 int
163 compat_43_sys_recvfrom(p, v, retval)
164 struct proc *p;
165 void *v;
166 register_t *retval;
167 {
168 struct compat_43_sys_recvfrom_args /* {
169 syscallarg(int) s;
170 syscallarg(caddr_t) buf;
171 syscallarg(size_t) len;
172 syscallarg(int) flags;
173 syscallarg(caddr_t) from;
174 syscallarg(int *) fromlenaddr;
175 } */ *uap = v;
176 int error;
177
178 if ((error = sys_recvfrom(p, v, retval)))
179 return (error);
180
181 if (SCARG(uap, from) && (error = compat_43_sa_put(SCARG(uap, from))))
182 return (error);
183
184 return (0);
185 }
186
187 /*
188 * Old recvmsg. Arrange necessary structures, calls generic code and
189 * adjusts results accordingly.
190 */
191 int
192 compat_43_sys_recvmsg(p, v, retval)
193 struct proc *p;
194 void *v;
195 register_t *retval;
196 {
197 struct compat_43_sys_recvmsg_args /* {
198 syscallarg(int) s;
199 syscallarg(struct omsghdr *) msg;
200 syscallarg(int) flags;
201 } */ *uap = v;
202 struct omsghdr omsg;
203 struct msghdr msg;
204 struct iovec aiov[UIO_SMALLIOV], *iov;
205 int error;
206
207 error = copyin((caddr_t)SCARG(uap, msg), (caddr_t)&omsg,
208 sizeof (struct omsghdr));
209 if (error)
210 return (error);
211 if ((u_int)omsg.msg_iovlen > UIO_SMALLIOV) {
212 if ((u_int)omsg.msg_iovlen > IOV_MAX)
213 return (EMSGSIZE);
214 iov = malloc(sizeof(struct iovec) * omsg.msg_iovlen,
215 M_IOV, M_WAITOK);
216 } else
217 iov = aiov;
218
219 error = copyin((caddr_t)omsg.msg_iov, (caddr_t)iov,
220 (unsigned)(omsg.msg_iovlen * sizeof (struct iovec)));
221 if (error)
222 goto done;
223
224 msg.msg_name = omsg.msg_name;
225 msg.msg_namelen = omsg.msg_namelen;
226 msg.msg_iovlen = omsg.msg_iovlen;
227 msg.msg_iov = iov;
228 msg.msg_flags = SCARG(uap, flags);
229
230 /*
231 * If caller passes accrights, arrange things for generic code to
232 * DTRT.
233 */
234 if (omsg.msg_accrights && omsg.msg_accrightslen) {
235 caddr_t sg = stackgap_init(p->p_emul);
236 struct cmsg *ucmsg;
237
238 /* it was this way in 4.4BSD */
239 if ((u_int) omsg.msg_accrightslen > MLEN)
240 return (EINVAL);
241
242 ucmsg = stackgap_alloc(&sg, CMSG_SPACE(omsg.msg_accrightslen));
243 if (ucmsg == NULL)
244 return (ENOMEM);
245
246 msg.msg_control = ucmsg;
247 msg.msg_controllen = CMSG_SPACE(omsg.msg_accrightslen);
248 } else {
249 msg.msg_control = NULL;
250 msg.msg_controllen = 0;
251 }
252
253 error = recvit(p, SCARG(uap, s), &msg,
254 (caddr_t)&SCARG(uap, msg)->msg_namelen, retval);
255
256 /*
257 * If there is any control information and it's SCM_RIGHTS,
258 * pass it back to the program.
259 */
260 if (!error && omsg.msg_accrights && msg.msg_controllen > 0) {
261 struct cmsghdr *cmsg;
262
263 cmsg = (struct cmsghdr *) malloc(msg.msg_controllen,
264 M_TEMP, M_WAITOK);
265
266 error = copyin(msg.msg_control, cmsg, msg.msg_controllen);
267 if (error) {
268 free(cmsg, M_TEMP);
269 return (error);
270 }
271
272 if (cmsg->cmsg_level != SOL_SOCKET
273 || cmsg->cmsg_type != SCM_RIGHTS
274 || copyout(CMSG_DATA(cmsg), omsg.msg_accrights,
275 cmsg->cmsg_len)) {
276 omsg.msg_accrightslen = 0;
277 }
278
279 free(cmsg, M_TEMP);
280
281 if (!error) {
282 error = copyout(&cmsg->cmsg_len,
283 &SCARG(uap, msg)->msg_accrightslen, sizeof(int));
284 }
285 }
286
287 if (!error && omsg.msg_name) {
288 int namelen;
289
290 if ((error = copyin(&SCARG(uap, msg)->msg_namelen, &namelen, sizeof(int)) == 0)
291 && namelen > 0)
292 error = compat_43_sa_put(omsg.msg_name);
293 }
294
295 done:
296 if (iov != aiov)
297 free(iov, M_IOV);
298 return (error);
299 }
300
301 int
302 compat_43_sys_send(p, v, retval)
303 struct proc *p;
304 void *v;
305 register_t *retval;
306 {
307 struct compat_43_sys_send_args /* {
308 syscallarg(int) s;
309 syscallarg(caddr_t) buf;
310 syscallarg(int) len;
311 syscallarg(int) flags;
312 } */ *uap = v;
313 struct sys_sendto_args bsa;
314
315 SCARG(&bsa, s) = SCARG(uap, s);
316 SCARG(&bsa, buf) = SCARG(uap, buf);
317 SCARG(&bsa, len) = SCARG(uap, len);
318 SCARG(&bsa, flags) = SCARG(uap, flags);
319 SCARG(&bsa, to) = NULL;
320 SCARG(&bsa, tolen) = 0;
321
322 return (sys_sendto(p, &bsa, retval));
323 }
324
325 /*
326 * Old sendmsg. Arrange necessary structures, call generic code and
327 * adjust the results accordingly for old code.
328 */
329 int
330 compat_43_sys_sendmsg(p, v, retval)
331 struct proc *p;
332 void *v;
333 register_t *retval;
334 {
335 struct compat_43_sys_sendmsg_args /* {
336 syscallarg(int) s;
337 syscallarg(caddr_t) msg;
338 syscallarg(int) flags;
339 } */ *uap = v;
340 struct omsghdr omsg;
341 struct msghdr msg;
342 struct iovec aiov[UIO_SMALLIOV], *iov;
343 int error;
344 caddr_t sg = stackgap_init(p->p_emul);
345
346 error = copyin(SCARG(uap, msg), (caddr_t)&omsg,
347 sizeof (struct omsghdr));
348 if (error)
349 return (error);
350 if ((u_int)omsg.msg_iovlen > UIO_SMALLIOV) {
351 if ((u_int)omsg.msg_iovlen > IOV_MAX)
352 return (EMSGSIZE);
353 iov = malloc(sizeof(struct iovec) * omsg.msg_iovlen,
354 M_IOV, M_WAITOK);
355 } else
356 iov = aiov;
357 error = copyin((caddr_t)omsg.msg_iov, (caddr_t)iov,
358 (unsigned)(omsg.msg_iovlen * sizeof (struct iovec)));
359 if (error)
360 goto done;
361
362 if (omsg.msg_name) {
363 struct osockaddr *osa;
364 struct sockaddr *sa, *usa;
365
366 if ((u_int) omsg.msg_namelen > UCHAR_MAX)
367 return (EINVAL);
368
369 osa = malloc(omsg.msg_namelen, M_TEMP, M_WAITOK);
370
371 if ((error = copyin(omsg.msg_name, osa, omsg.msg_namelen))) {
372 free(osa, M_TEMP);
373 return (error);
374 }
375
376 sa = (struct sockaddr *) osa;
377 sa->sa_family = osa->sa_family;
378 sa->sa_len = omsg.msg_namelen;
379
380 usa = stackgap_alloc(&sg, omsg.msg_namelen);
381 if (!usa) {
382 free(osa, M_TEMP);
383 return (ENOMEM);
384 }
385
386 (void) copyout(sa, usa, omsg.msg_namelen);
387 free(osa, M_TEMP);
388
389 msg.msg_name = usa;
390 msg.msg_namelen = omsg.msg_namelen;
391 } else {
392 msg.msg_name = NULL;
393 msg.msg_namelen = 0;
394 }
395 msg.msg_iovlen = omsg.msg_iovlen;
396 msg.msg_iov = iov;
397 msg.msg_flags = 0;
398
399 if (omsg.msg_accrights && omsg.msg_accrightslen != 0) {
400 struct cmsghdr *cmsg, *ucmsg;
401
402 /* it was this way in 4.4BSD */
403 if ((u_int) omsg.msg_accrightslen > MLEN)
404 return (EINVAL);
405
406 cmsg = malloc(CMSG_SPACE(omsg.msg_accrightslen), M_TEMP,
407 M_WAITOK);
408 cmsg->cmsg_len = CMSG_SPACE(omsg.msg_accrightslen);
409 cmsg->cmsg_level = SOL_SOCKET;
410 cmsg->cmsg_type = SCM_RIGHTS;
411
412 error = copyin(omsg.msg_accrights, CMSG_DATA(cmsg),
413 omsg.msg_accrightslen);
414 if (error) {
415 free(cmsg, M_TEMP);
416 return (error);
417 }
418
419 ucmsg = stackgap_alloc(&sg, CMSG_SPACE(omsg.msg_accrightslen));
420 if (!ucmsg) {
421 free(cmsg, M_TEMP);
422 return (ENOMEM);
423 }
424
425 (void) copyout(cmsg, ucmsg, CMSG_SPACE(omsg.msg_accrightslen));
426 free(cmsg, M_TEMP);
427
428 msg.msg_control = ucmsg;
429 msg.msg_controllen = CMSG_SPACE(omsg.msg_accrightslen);
430 } else {
431 msg.msg_control = NULL;
432 msg.msg_controllen = 0;
433 }
434
435 error = sendit(p, SCARG(uap, s), &msg, SCARG(uap, flags), retval);
436 done:
437 if (iov != aiov)
438 FREE(iov, M_IOV);
439 return (error);
440 }
441
442 static int
443 compat_43_sa_put(from)
444 caddr_t from;
445 {
446 struct osockaddr *osa = (struct osockaddr *) from;
447 struct sockaddr sa;
448 struct osockaddr *kosa;
449 int error, len;
450
451 /*
452 * Only read/write the sockaddr family and length, the rest is
453 * not changed.
454 */
455 len = sizeof(sa.sa_len) + sizeof(sa.sa_family);
456
457 error = copyin((caddr_t) osa, (caddr_t) &sa, len);
458 if (error)
459 return (error);
460
461 /* Note: we convert from sockaddr sa_family to osockaddr one here */
462 kosa = (struct osockaddr *) &sa;
463 kosa->sa_family = sa.sa_family;
464 error = copyout(kosa, osa, len);
465 if (error)
466 return (error);
467
468 return (0);
469 }
470