uipc_syscalls_43.c revision 1.16 1 /* $NetBSD: uipc_syscalls_43.c,v 1.16 2001/07/22 13:46:51 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 (EMSGSIZE);
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 /* safe - msg.msg_controllen set by kernel */
264 cmsg = (struct cmsghdr *) malloc(msg.msg_controllen,
265 M_TEMP, M_WAITOK);
266
267 error = copyin(msg.msg_control, cmsg, msg.msg_controllen);
268 if (error) {
269 free(cmsg, M_TEMP);
270 return (error);
271 }
272
273 if (cmsg->cmsg_level != SOL_SOCKET
274 || cmsg->cmsg_type != SCM_RIGHTS
275 || copyout(CMSG_DATA(cmsg), omsg.msg_accrights,
276 cmsg->cmsg_len)) {
277 omsg.msg_accrightslen = 0;
278 }
279
280 free(cmsg, M_TEMP);
281
282 if (!error) {
283 error = copyout(&cmsg->cmsg_len,
284 &SCARG(uap, msg)->msg_accrightslen, sizeof(int));
285 }
286 }
287
288 if (!error && omsg.msg_name) {
289 int namelen;
290
291 if ((error = copyin(&SCARG(uap, msg)->msg_namelen, &namelen, sizeof(int)) == 0)
292 && namelen > 0)
293 error = compat_43_sa_put(omsg.msg_name);
294 }
295
296 done:
297 if (iov != aiov)
298 free(iov, M_IOV);
299 return (error);
300 }
301
302 int
303 compat_43_sys_send(p, v, retval)
304 struct proc *p;
305 void *v;
306 register_t *retval;
307 {
308 struct compat_43_sys_send_args /* {
309 syscallarg(int) s;
310 syscallarg(caddr_t) buf;
311 syscallarg(int) len;
312 syscallarg(int) flags;
313 } */ *uap = v;
314 struct sys_sendto_args bsa;
315
316 SCARG(&bsa, s) = SCARG(uap, s);
317 SCARG(&bsa, buf) = SCARG(uap, buf);
318 SCARG(&bsa, len) = SCARG(uap, len);
319 SCARG(&bsa, flags) = SCARG(uap, flags);
320 SCARG(&bsa, to) = NULL;
321 SCARG(&bsa, tolen) = 0;
322
323 return (sys_sendto(p, &bsa, retval));
324 }
325
326 /*
327 * Old sendmsg. Arrange necessary structures, call generic code and
328 * adjust the results accordingly for old code.
329 */
330 int
331 compat_43_sys_sendmsg(p, v, retval)
332 struct proc *p;
333 void *v;
334 register_t *retval;
335 {
336 struct compat_43_sys_sendmsg_args /* {
337 syscallarg(int) s;
338 syscallarg(caddr_t) msg;
339 syscallarg(int) flags;
340 } */ *uap = v;
341 struct omsghdr omsg;
342 struct msghdr msg;
343 struct iovec aiov[UIO_SMALLIOV], *iov;
344 int error;
345 caddr_t sg = stackgap_init(p->p_emul);
346
347 error = copyin(SCARG(uap, msg), (caddr_t)&omsg,
348 sizeof (struct omsghdr));
349 if (error)
350 return (error);
351 if ((u_int)omsg.msg_iovlen > UIO_SMALLIOV) {
352 if ((u_int)omsg.msg_iovlen > IOV_MAX)
353 return (EMSGSIZE);
354 iov = malloc(sizeof(struct iovec) * omsg.msg_iovlen,
355 M_IOV, M_WAITOK);
356 } else
357 iov = aiov;
358 error = copyin((caddr_t)omsg.msg_iov, (caddr_t)iov,
359 (unsigned)(omsg.msg_iovlen * sizeof (struct iovec)));
360 if (error)
361 goto done;
362
363 if (omsg.msg_name) {
364 struct osockaddr *osa;
365 struct sockaddr *sa, *usa;
366
367 if ((u_int) omsg.msg_namelen > UCHAR_MAX)
368 return (EINVAL);
369
370 osa = malloc(omsg.msg_namelen, M_TEMP, M_WAITOK);
371
372 if ((error = copyin(omsg.msg_name, osa, omsg.msg_namelen))) {
373 free(osa, M_TEMP);
374 return (error);
375 }
376
377 sa = (struct sockaddr *) osa;
378 sa->sa_family = osa->sa_family;
379 sa->sa_len = omsg.msg_namelen;
380
381 usa = stackgap_alloc(&sg, omsg.msg_namelen);
382 if (!usa) {
383 free(osa, M_TEMP);
384 return (ENOMEM);
385 }
386
387 (void) copyout(sa, usa, omsg.msg_namelen);
388 free(osa, M_TEMP);
389
390 msg.msg_name = usa;
391 msg.msg_namelen = omsg.msg_namelen;
392 } else {
393 msg.msg_name = NULL;
394 msg.msg_namelen = 0;
395 }
396 msg.msg_iovlen = omsg.msg_iovlen;
397 msg.msg_iov = iov;
398 msg.msg_flags = 0;
399
400 if (omsg.msg_accrights && omsg.msg_accrightslen != 0) {
401 struct cmsghdr *cmsg, *ucmsg;
402
403 /* it was this way in 4.4BSD */
404 if ((u_int) omsg.msg_accrightslen > MLEN)
405 return (EINVAL);
406
407 cmsg = malloc(CMSG_SPACE(omsg.msg_accrightslen), M_TEMP,
408 M_WAITOK);
409 cmsg->cmsg_len = CMSG_SPACE(omsg.msg_accrightslen);
410 cmsg->cmsg_level = SOL_SOCKET;
411 cmsg->cmsg_type = SCM_RIGHTS;
412
413 error = copyin(omsg.msg_accrights, CMSG_DATA(cmsg),
414 omsg.msg_accrightslen);
415 if (error) {
416 free(cmsg, M_TEMP);
417 return (error);
418 }
419
420 ucmsg = stackgap_alloc(&sg, CMSG_SPACE(omsg.msg_accrightslen));
421 if (!ucmsg) {
422 free(cmsg, M_TEMP);
423 return (EMSGSIZE);
424 }
425
426 (void) copyout(cmsg, ucmsg, CMSG_SPACE(omsg.msg_accrightslen));
427 free(cmsg, M_TEMP);
428
429 msg.msg_control = ucmsg;
430 msg.msg_controllen = CMSG_SPACE(omsg.msg_accrightslen);
431 } else {
432 msg.msg_control = NULL;
433 msg.msg_controllen = 0;
434 }
435
436 error = sendit(p, SCARG(uap, s), &msg, SCARG(uap, flags), retval);
437 done:
438 if (iov != aiov)
439 FREE(iov, M_IOV);
440 return (error);
441 }
442
443 static int
444 compat_43_sa_put(from)
445 caddr_t from;
446 {
447 struct osockaddr *osa = (struct osockaddr *) from;
448 struct sockaddr sa;
449 struct osockaddr *kosa;
450 int error, len;
451
452 /*
453 * Only read/write the sockaddr family and length, the rest is
454 * not changed.
455 */
456 len = sizeof(sa.sa_len) + sizeof(sa.sa_family);
457
458 error = copyin((caddr_t) osa, (caddr_t) &sa, len);
459 if (error)
460 return (error);
461
462 /* Note: we convert from sockaddr sa_family to osockaddr one here */
463 kosa = (struct osockaddr *) &sa;
464 kosa->sa_family = sa.sa_family;
465 error = copyout(kosa, osa, len);
466 if (error)
467 return (error);
468
469 return (0);
470 }
471