kernel: Save some indent here and there and some small cleanup.
[dragonfly.git] / sys / emulation / 43bsd / 43bsd_socket.c
1 /*
2  * 43BSD_SOCKET.C       - 4.3BSD compatibility socket syscalls
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. Neither the name of the University nor the names of its contributors
16  *    may be used to endorse or promote products derived from this software
17  *    without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29  * SUCH DAMAGE.
30  *
31  * The original versions of these syscalls used to live in
32  * kern/uipc_syscalls.c.  These are heavily modified to use the
33  * new split syscalls.
34  */
35
36 #include "opt_compat.h"
37
38 #include <sys/param.h>
39 #include <sys/systm.h>
40 #include <sys/kernel.h>
41 #include <sys/sysproto.h>
42 #include <sys/kern_syscall.h>
43 #include <sys/malloc.h>
44 #include <sys/mbuf.h>
45 #include <sys/proc.h>
46 #include <sys/socket.h>
47 #include <sys/socketvar.h>
48 #include <sys/uio.h>
49
50 #include <sys/mplock2.h>
51
52 #include "43bsd_socket.h"
53
54 /*
55  * System call interface to the socket abstraction.
56  */
57
58 static int
59 compat_43_getsockaddr(struct sockaddr **namp, caddr_t uaddr, size_t len)
60 {
61         struct sockaddr *sa;
62         int error;
63
64         *namp = NULL;
65         if (len > SOCK_MAXADDRLEN)
66                 return ENAMETOOLONG;
67         if (len < offsetof(struct sockaddr, sa_data[0]))
68                 return EDOM;
69         sa = kmalloc(len, M_SONAME, M_WAITOK);
70         error = copyin(uaddr, sa, len);
71         if (error) {
72                 kfree(sa, M_SONAME);
73         } else {
74                 /*
75                  * Convert to the 4.4BSD sockaddr structure.
76                  */
77                 sa->sa_family = sa->sa_len;
78                 sa->sa_len = len;
79                 *namp = sa;
80         }
81         return error;
82 }
83
84 static int
85 compat_43_copyout_sockaddr(struct sockaddr *sa, caddr_t uaddr, int sa_len)
86 {
87         int error;
88
89         ((struct osockaddr *)sa)->sa_family = sa->sa_family;
90         error = copyout(sa, uaddr, sa_len);
91
92         return (error);
93 }
94
95 /*
96  * MPALMOSTSAFE
97  */
98 int
99 sys_oaccept(struct accept_args *uap)
100 {
101         struct sockaddr *sa = NULL;
102         int sa_len;
103         int error;
104
105         if (uap->name) {
106                 error = copyin(uap->anamelen, &sa_len, sizeof(sa_len));
107                 if (error)
108                         return (error);
109
110                 get_mplock();
111                 error = kern_accept(uap->s, 0, &sa, &sa_len,
112                                     &uap->sysmsg_iresult, 0);
113                 rel_mplock();
114
115                 if (error) {
116                         /*
117                          * return a namelen of zero for older code which
118                          * might ignore the return value from accept.
119                          */
120                         sa_len = 0;
121                         copyout(&sa_len, uap->anamelen, sizeof(*uap->anamelen));
122                 } else {
123                         compat_43_copyout_sockaddr(sa, uap->name, sa_len);
124                         if (error == 0) {
125                                 error = copyout(&sa_len, uap->anamelen,
126                                     sizeof(*uap->anamelen));
127                         }
128                 }
129                 if (sa)
130                         kfree(sa, M_SONAME);
131         } else {
132                 get_mplock();
133                 error = kern_accept(uap->s, 0, NULL, 0, &uap->sysmsg_iresult, 0);
134                 rel_mplock();
135         }
136         return (error);
137 }
138
139 /*
140  * MPALMOSTSAFE
141  */
142 int
143 sys_ogetsockname(struct getsockname_args *uap)
144 {
145         struct sockaddr *sa = NULL;
146         int error, sa_len;
147
148         error = copyin(uap->alen, &sa_len, sizeof(sa_len));
149         if (error)
150                 return (error);
151
152         get_mplock();
153         error = kern_getsockname(uap->fdes, &sa, &sa_len);
154         rel_mplock();
155
156         if (error == 0)
157                 error = compat_43_copyout_sockaddr(sa, uap->asa, sa_len);
158         if (error == 0) {
159                 error = copyout(&sa_len, uap->alen, sizeof(*uap->alen));
160         }
161         if (sa)
162                 kfree(sa, M_SONAME);
163         return (error);
164 }
165
166 /*
167  * MPALMOSTSAFE
168  */
169 int
170 sys_ogetpeername(struct ogetpeername_args *uap)
171 {
172         struct sockaddr *sa = NULL;
173         int error, sa_len;
174
175         error = copyin(uap->alen, &sa_len, sizeof(sa_len));
176         if (error)
177                 return (error);
178
179         get_mplock();
180         error = kern_getpeername(uap->fdes, &sa, &sa_len);
181         rel_mplock();
182
183         if (error == 0) {
184                 error = compat_43_copyout_sockaddr(sa, uap->asa, sa_len);
185         }
186         if (error == 0)
187                 error = copyout(&sa_len, uap->alen, sizeof(*uap->alen));
188         if (sa)
189                 kfree(sa, M_SONAME);
190         return (error);
191 }
192
193 /*
194  * MPALMOSTSAFE
195  */
196 int
197 sys_osend(struct osend_args *uap)
198 {
199         struct thread *td = curthread;
200         struct uio auio;
201         struct iovec aiov;
202         int error;
203
204         aiov.iov_base = uap->buf;
205         aiov.iov_len = uap->len;
206         auio.uio_iov = &aiov;
207         auio.uio_iovcnt = 1;
208         auio.uio_offset = 0;
209         auio.uio_resid = uap->len;
210         auio.uio_segflg = UIO_USERSPACE;
211         auio.uio_rw = UIO_WRITE;
212         auio.uio_td = td;
213
214         get_mplock();
215         error = kern_sendmsg(uap->s, NULL, &auio, NULL, uap->flags,
216                              &uap->sysmsg_szresult);
217         rel_mplock();
218
219         return (error);
220 }
221
222 /*
223  * MPALMOSTSAFE
224  */
225 int
226 sys_osendmsg(struct osendmsg_args *uap)
227 {
228         struct thread *td = curthread;
229         struct msghdr msg;
230         struct uio auio;
231         struct iovec aiov[UIO_SMALLIOV], *iov = NULL;
232         struct sockaddr *sa = NULL;
233         struct mbuf *control = NULL;
234         struct cmsghdr *cm;
235         int error;
236
237         error = copyin(uap->msg, (caddr_t)&msg, sizeof (msg));
238         if (error)
239                 return (error);
240
241         /*
242          * Conditionally copyin msg.msg_name.
243          */
244         if (msg.msg_name) {
245                 error = compat_43_getsockaddr(&sa, msg.msg_name,
246                     msg.msg_namelen);
247                 if (error)
248                         return (error);
249         }
250
251         /*
252          * Populate auio.
253          */
254         error = iovec_copyin(msg.msg_iov, &iov, aiov, msg.msg_iovlen,
255                              &auio.uio_resid);
256         if (error)
257                 goto cleanup2;
258         auio.uio_iov = iov;
259         auio.uio_iovcnt = msg.msg_iovlen;
260         auio.uio_offset = 0;
261         auio.uio_segflg = UIO_USERSPACE;
262         auio.uio_rw = UIO_WRITE;
263         auio.uio_td = td;
264
265         /*
266          * Conditionally copyin msg.msg_control.
267          */
268         if (msg.msg_control) {
269                 if (msg.msg_controllen < 0 || msg.msg_controllen > MLEN) {
270                         error = EINVAL;
271                         goto cleanup;
272                 }
273                 control = m_get(M_WAITOK, MT_CONTROL);
274                 if (control == NULL) {
275                         error = ENOBUFS;
276                         goto cleanup;
277                 }
278                 control->m_len = msg.msg_controllen;
279                 error = copyin(msg.msg_control, mtod(control, caddr_t),
280                     msg.msg_controllen);
281                 if (error) {
282                         m_free(control);
283                         goto cleanup;
284                 }
285                 /*
286                  * In 4.3BSD, the only type of ancillary data was
287                  * access rights and this data did not use a header
288                  * to identify it's type.  Thus, we must prepend the
289                  * control data with the proper cmsghdr structure
290                  * so that the kernel recognizes it as access rights.
291                  */
292                 M_PREPEND(control, sizeof(*cm), M_WAITOK);
293                 if (control == NULL) {
294                         error = ENOBUFS;
295                         goto cleanup;
296                 }
297                 cm = mtod(control, struct cmsghdr *);
298                 cm->cmsg_len = control->m_len;
299                 cm->cmsg_level = SOL_SOCKET;
300                 cm->cmsg_type = SCM_RIGHTS;
301         }
302
303         get_mplock();
304         error = kern_sendmsg(uap->s, sa, &auio, control, uap->flags,
305                              &uap->sysmsg_szresult);
306         rel_mplock();
307
308 cleanup:
309         iovec_free(&iov, aiov);
310 cleanup2:
311         if (sa)
312                 kfree(sa, M_SONAME);
313         return (error);
314 }
315
316 /*
317  * MPALMOSTSAFE
318  */
319 int
320 sys_orecv(struct orecv_args *uap)
321 {
322         struct thread *td = curthread;
323         struct uio auio;
324         struct iovec aiov;
325         int error;
326
327         aiov.iov_base = uap->buf;
328         aiov.iov_len = uap->len;
329         auio.uio_iov = &aiov;
330         auio.uio_iovcnt = 1;
331         auio.uio_offset = 0;
332         auio.uio_resid = uap->len;
333         auio.uio_segflg = UIO_USERSPACE;
334         auio.uio_rw = UIO_READ;
335         auio.uio_td = td;
336
337         get_mplock();
338         error = kern_recvmsg(uap->s, NULL, &auio, NULL, &uap->flags,
339                              &uap->sysmsg_szresult);
340         rel_mplock();
341
342         return (error);
343 }
344
345 /*
346  * MPALMOSTSAFE
347  */
348 int
349 sys_orecvfrom(struct recvfrom_args *uap)
350 {
351         struct thread *td = curthread;
352         struct uio auio;
353         struct iovec aiov;
354         struct sockaddr *sa = NULL;
355         int error, fromlen;
356
357         if (uap->from && uap->fromlenaddr) {
358                 error = copyin(uap->fromlenaddr, &fromlen, sizeof(fromlen));
359                 if (error)
360                         return (error);
361                 if (fromlen < 0)
362                         return (EINVAL);
363         } else {
364                 fromlen = 0;
365         }
366         aiov.iov_base = uap->buf;
367         aiov.iov_len = uap->len;
368         auio.uio_iov = &aiov;
369         auio.uio_iovcnt = 1;
370         auio.uio_offset = 0;
371         auio.uio_resid = uap->len;
372         auio.uio_segflg = UIO_USERSPACE;
373         auio.uio_rw = UIO_READ;
374         auio.uio_td = td;
375
376         get_mplock();
377         error = kern_recvmsg(uap->s, uap->from ? &sa : NULL, &auio, NULL,
378                              &uap->flags, &uap->sysmsg_szresult);
379         rel_mplock();
380
381         if (error == 0 && uap->from) {
382                 if (sa != NULL) {
383                         fromlen = MIN(fromlen, sa->sa_len);
384                         error = compat_43_copyout_sockaddr(sa, uap->from,
385                                                            fromlen);
386                 } else
387                         fromlen = 0;
388                 if (error == 0)
389                         /*
390                          * Old recvfrom didn't signal an error if this
391                          * next copyout failed.
392                          */
393                         copyout(&fromlen, uap->fromlenaddr, sizeof(fromlen));
394         }
395         if (sa)
396                 kfree(sa, M_SONAME);
397
398         return (error);
399 }
400
401 /*
402  * MPALMOSTSAFE
403  */
404 int
405 sys_orecvmsg(struct orecvmsg_args *uap)
406 {
407         struct thread *td = curthread;
408         struct msghdr msg;
409         struct uio auio;
410         struct iovec aiov[UIO_SMALLIOV], *iov = NULL;
411         struct mbuf *m, *control = NULL;
412         struct sockaddr *sa = NULL;
413         caddr_t ctlbuf;
414         socklen_t *ufromlenp, *ucontrollenp;
415         int error, fromlen, controllen, len, flags, *uflagsp;
416
417         /*
418          * This copyin handles everything except the iovec.
419          */
420         error = copyin(uap->msg, &msg, sizeof(struct omsghdr));
421         if (error)
422                 return (error);
423
424         if (msg.msg_name && msg.msg_namelen < 0)
425                 return (EINVAL);
426         if (msg.msg_control && msg.msg_controllen < 0)
427                 return (EINVAL);
428
429         ufromlenp = (socklen_t *)((caddr_t)uap->msg + offsetof(struct msghdr,
430             msg_namelen));
431         ucontrollenp = (socklen_t *)((caddr_t)uap->msg + offsetof(struct msghdr,
432             msg_controllen));
433         uflagsp = (int *)((caddr_t)uap->msg + offsetof(struct msghdr,
434             msg_flags));
435
436         /*
437          * Populate auio.
438          */
439         error = iovec_copyin(msg.msg_iov, &iov, aiov, msg.msg_iovlen,
440                              &auio.uio_resid);
441         if (error)
442                 return (error);
443         auio.uio_iov = iov;
444         auio.uio_iovcnt = msg.msg_iovlen;
445         auio.uio_offset = 0;
446         auio.uio_segflg = UIO_USERSPACE;
447         auio.uio_rw = UIO_READ;
448         auio.uio_td = td;
449
450         flags = msg.msg_flags;
451
452         get_mplock();
453         error = kern_recvmsg(uap->s, (msg.msg_name ? &sa : NULL), &auio,
454                              (msg.msg_control ? &control : NULL), &flags,
455                              &uap->sysmsg_szresult);
456         rel_mplock();
457
458         /*
459          * Copyout msg.msg_name and msg.msg_namelen.
460          */
461         if (error == 0 && msg.msg_name) {
462                 if (sa != NULL) {
463                         fromlen = MIN(msg.msg_namelen, sa->sa_len);
464                         error = compat_43_copyout_sockaddr(sa, msg.msg_name,
465                                                            fromlen);
466                 } else
467                         fromlen = 0;
468                 if (error == 0)
469                         /*
470                          * Old recvfrom didn't signal an error if this
471                          * next copyout failed.
472                          */
473                         copyout(&fromlen, ufromlenp, sizeof(*ufromlenp));
474         }
475
476         /*
477          * Copyout msg.msg_control and msg.msg_controllen.
478          */
479         if (error == 0 && msg.msg_control) {
480                 /*
481                  * If we receive access rights, trim the cmsghdr; anything
482                  * else is tossed.
483                  */
484                 if (mtod((struct mbuf *)msg.msg_control,
485                     struct cmsghdr *)->cmsg_level != SOL_SOCKET ||
486                     mtod((struct mbuf *)msg.msg_control,
487                     struct cmsghdr *)->cmsg_type != SCM_RIGHTS) {
488                         int temp = 0;
489                         error = copyout(&temp, ucontrollenp,
490                             sizeof(*ucontrollenp));
491                         goto cleanup;
492                 }
493                 ((struct mbuf *)msg.msg_control)->m_len -=
494                     sizeof(struct cmsghdr);
495                 ((struct mbuf *)msg.msg_control)->m_data +=
496                     sizeof(struct cmsghdr);
497
498                 len = msg.msg_controllen;
499                 m = control;
500                 ctlbuf = (caddr_t)msg.msg_control;
501
502                 while(m && len > 0) {
503                         unsigned int tocopy;
504
505                         if (len >= m->m_len) {
506                                 tocopy = m->m_len;
507                         } else {
508                                 msg.msg_flags |= MSG_CTRUNC;
509                                 tocopy = len;
510                         }
511
512                         error = copyout(mtod(m, caddr_t), ctlbuf,
513                             tocopy);
514                         if (error)
515                                 goto cleanup;
516
517                         ctlbuf += tocopy;
518                         len -= tocopy;
519                         m = m->m_next;
520                 }
521                 controllen = ctlbuf - (caddr_t)msg.msg_control;
522                 error = copyout(&controllen, ucontrollenp,
523                     sizeof(*ucontrollenp));
524         }
525
526         if (error == 0)
527                 error = copyout(&flags, uflagsp, sizeof(*uflagsp));
528
529 cleanup:
530         if (sa)
531                 kfree(sa, M_SONAME);
532         iovec_free(&iov, aiov);
533         if (control)
534                 m_freem(control);
535         return (error);
536 }
537