Line data Source code
1 : /* $OpenBSD: uipc_syscalls.c,v 1.178 2018/07/30 12:22:14 mpi Exp $ */
2 : /* $NetBSD: uipc_syscalls.c,v 1.19 1996/02/09 19:00:48 christos Exp $ */
3 :
4 : /*
5 : * Copyright (c) 1982, 1986, 1989, 1990, 1993
6 : * The Regents of the University of California. All rights reserved.
7 : *
8 : * Redistribution and use in source and binary forms, with or without
9 : * modification, are permitted provided that the following conditions
10 : * are met:
11 : * 1. Redistributions of source code must retain the above copyright
12 : * notice, this list of conditions and the following disclaimer.
13 : * 2. Redistributions in binary form must reproduce the above copyright
14 : * notice, this list of conditions and the following disclaimer in the
15 : * documentation and/or other materials provided with the distribution.
16 : * 3. Neither the name of the University nor the names of its contributors
17 : * may be used to endorse or promote products derived from this software
18 : * without specific prior written permission.
19 : *
20 : * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 : * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 : * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 : * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 : * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 : * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 : * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 : * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 : * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 : * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 : * SUCH DAMAGE.
31 : *
32 : * @(#)uipc_syscalls.c 8.4 (Berkeley) 2/21/94
33 : */
34 :
35 : #include <sys/param.h>
36 : #include <sys/systm.h>
37 : #include <sys/filedesc.h>
38 : #include <sys/proc.h>
39 : #include <sys/fcntl.h>
40 : #include <sys/file.h>
41 : #include <sys/ioctl.h>
42 : #include <sys/malloc.h>
43 : #include <sys/event.h>
44 : #include <sys/mbuf.h>
45 : #include <sys/protosw.h>
46 : #include <sys/socket.h>
47 : #include <sys/socketvar.h>
48 : #include <sys/signalvar.h>
49 : #include <sys/pledge.h>
50 : #include <sys/unpcb.h>
51 : #include <sys/un.h>
52 : #ifdef KTRACE
53 : #include <sys/ktrace.h>
54 : #endif
55 :
56 : #include <sys/mount.h>
57 : #include <sys/syscallargs.h>
58 :
59 : #include <sys/domain.h>
60 : #include <netinet/in.h>
61 : #include <net/route.h>
62 :
63 : /*
64 : * System call interface to the socket abstraction.
65 : */
66 : extern struct fileops socketops;
67 :
68 : int copyaddrout(struct proc *, struct mbuf *, struct sockaddr *, socklen_t,
69 : socklen_t *);
70 :
71 : uint16_t dnsjackport;
72 :
73 : int
74 0 : sys_socket(struct proc *p, void *v, register_t *retval)
75 : {
76 : struct sys_socket_args /* {
77 : syscallarg(int) domain;
78 : syscallarg(int) type;
79 : syscallarg(int) protocol;
80 0 : } */ *uap = v;
81 0 : struct filedesc *fdp = p->p_fd;
82 0 : struct socket *so;
83 0 : struct file *fp;
84 0 : int type = SCARG(uap, type);
85 0 : int domain = SCARG(uap, domain);
86 0 : int fd, cloexec, nonblock, fflag, error;
87 : unsigned int ss = 0;
88 :
89 0 : if ((type & SOCK_DNS) && !(domain == AF_INET || domain == AF_INET6))
90 0 : return (EINVAL);
91 :
92 0 : if (ISSET(type, SOCK_DNS))
93 0 : ss |= SS_DNS;
94 0 : error = pledge_socket(p, domain, ss);
95 0 : if (error)
96 0 : return (error);
97 :
98 0 : type &= ~(SOCK_CLOEXEC | SOCK_NONBLOCK | SOCK_DNS);
99 0 : cloexec = (SCARG(uap, type) & SOCK_CLOEXEC) ? UF_EXCLOSE : 0;
100 0 : nonblock = SCARG(uap, type) & SOCK_NONBLOCK;
101 0 : fflag = FREAD | FWRITE | (nonblock ? FNONBLOCK : 0);
102 :
103 0 : error = socreate(SCARG(uap, domain), &so, type, SCARG(uap, protocol));
104 0 : if (error)
105 0 : return (error);
106 :
107 0 : KERNEL_LOCK();
108 0 : fdplock(fdp);
109 0 : error = falloc(p, &fp, &fd);
110 0 : if (error) {
111 0 : fdpunlock(fdp);
112 0 : soclose(so, MSG_DONTWAIT);
113 0 : } else {
114 0 : fp->f_flag = fflag;
115 0 : fp->f_type = DTYPE_SOCKET;
116 0 : fp->f_ops = &socketops;
117 0 : so->so_state |= ss;
118 0 : fp->f_data = so;
119 0 : fdinsert(fdp, fd, cloexec, fp);
120 0 : fdpunlock(fdp);
121 0 : FRELE(fp, p);
122 0 : *retval = fd;
123 : }
124 0 : KERNEL_UNLOCK();
125 0 : return (error);
126 0 : }
127 :
128 : static inline int
129 0 : isdnssocket(struct socket *so)
130 : {
131 0 : return (so->so_state & SS_DNS);
132 : }
133 :
134 : /* For SS_DNS sockets, only allow port DNS (port 53) */
135 : static int
136 0 : dns_portcheck(struct proc *p, struct socket *so, void *nam, u_int *namelen)
137 : {
138 : int error = EINVAL;
139 :
140 0 : switch (so->so_proto->pr_domain->dom_family) {
141 : case AF_INET:
142 0 : if (*namelen < sizeof(struct sockaddr_in))
143 : break;
144 0 : if (((struct sockaddr_in *)nam)->sin_port == htons(53))
145 0 : error = 0;
146 0 : if (dnsjackport) {
147 : struct sockaddr_in sin;
148 : memset(&sin, 0, sizeof(sin));
149 : sin.sin_len = sizeof(sin);
150 : sin.sin_family = AF_INET;
151 0 : sin.sin_port = htons(dnsjackport);
152 : sin.sin_addr.s_addr = INADDR_LOOPBACK;
153 0 : memcpy(nam, &sin, sizeof(sin));
154 0 : *namelen = sizeof(sin);
155 0 : }
156 : break;
157 : #ifdef INET6
158 : case AF_INET6:
159 0 : if (*namelen < sizeof(struct sockaddr_in6))
160 : break;
161 0 : if (((struct sockaddr_in6 *)nam)->sin6_port == htons(53))
162 0 : error = 0;
163 0 : if (dnsjackport) {
164 0 : struct sockaddr_in6 sin6;
165 0 : memset(&sin6, 0, sizeof(sin6));
166 : sin6.sin6_len = sizeof(sin6);
167 : sin6.sin6_family = AF_INET6;
168 0 : sin6.sin6_port = htons(dnsjackport);
169 0 : sin6.sin6_addr = in6addr_loopback;
170 0 : memcpy(nam, &sin6, sizeof(sin6));
171 0 : *namelen = sizeof(sin6);
172 0 : }
173 : #endif
174 : }
175 0 : if (error && p->p_p->ps_flags & PS_PLEDGE)
176 0 : return (pledge_fail(p, EPERM, PLEDGE_DNS));
177 0 : return error;
178 0 : }
179 :
180 : int
181 0 : sys_bind(struct proc *p, void *v, register_t *retval)
182 : {
183 : struct sys_bind_args /* {
184 : syscallarg(int) s;
185 : syscallarg(const struct sockaddr *) name;
186 : syscallarg(socklen_t) namelen;
187 0 : } */ *uap = v;
188 0 : struct file *fp;
189 0 : struct mbuf *nam;
190 : struct socket *so;
191 : int s, error;
192 :
193 0 : if ((error = getsock(p, SCARG(uap, s), &fp)) != 0)
194 0 : return (error);
195 0 : so = fp->f_data;
196 0 : error = pledge_socket(p, so->so_proto->pr_domain->dom_family,
197 0 : so->so_state);
198 0 : if (error)
199 : goto out;
200 0 : error = sockargs(&nam, SCARG(uap, name), SCARG(uap, namelen),
201 : MT_SONAME);
202 0 : if (error)
203 : goto out;
204 : #ifdef KTRACE
205 0 : if (KTRPOINT(p, KTR_STRUCT))
206 0 : ktrsockaddr(p, mtod(nam, caddr_t), SCARG(uap, namelen));
207 : #endif
208 0 : s = solock(so);
209 0 : error = sobind(so, nam, p);
210 0 : sounlock(so, s);
211 0 : m_freem(nam);
212 : out:
213 0 : FRELE(fp, p);
214 0 : return (error);
215 0 : }
216 :
217 : int
218 0 : sys_listen(struct proc *p, void *v, register_t *retval)
219 : {
220 : struct sys_listen_args /* {
221 : syscallarg(int) s;
222 : syscallarg(int) backlog;
223 0 : } */ *uap = v;
224 0 : struct file *fp;
225 : struct socket *so;
226 : int error;
227 :
228 0 : if ((error = getsock(p, SCARG(uap, s), &fp)) != 0)
229 0 : return (error);
230 0 : so = fp->f_data;
231 0 : error = solisten(so, SCARG(uap, backlog));
232 0 : FRELE(fp, p);
233 0 : return (error);
234 0 : }
235 :
236 : int
237 0 : sys_accept(struct proc *p, void *v, register_t *retval)
238 : {
239 : struct sys_accept_args /* {
240 : syscallarg(int) s;
241 : syscallarg(struct sockaddr *) name;
242 : syscallarg(socklen_t *) anamelen;
243 0 : } */ *uap = v;
244 :
245 0 : return (doaccept(p, SCARG(uap, s), SCARG(uap, name),
246 0 : SCARG(uap, anamelen), SOCK_NONBLOCK_INHERIT, retval));
247 : }
248 :
249 : int
250 0 : sys_accept4(struct proc *p, void *v, register_t *retval)
251 : {
252 : struct sys_accept4_args /* {
253 : syscallarg(int) s;
254 : syscallarg(struct sockaddr *) name;
255 : syscallarg(socklen_t *) anamelen;
256 : syscallarg(socklen_t *) int flags;
257 0 : } */ *uap = v;
258 :
259 0 : if (SCARG(uap, flags) & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
260 0 : return (EINVAL);
261 :
262 0 : return (doaccept(p, SCARG(uap, s), SCARG(uap, name),
263 0 : SCARG(uap, anamelen), SCARG(uap, flags), retval));
264 0 : }
265 :
266 : int
267 0 : doaccept(struct proc *p, int sock, struct sockaddr *name, socklen_t *anamelen,
268 : int flags, register_t *retval)
269 : {
270 0 : struct filedesc *fdp = p->p_fd;
271 0 : struct file *fp, *headfp;
272 : struct mbuf *nam;
273 0 : socklen_t namelen;
274 0 : int error, s, tmpfd;
275 : struct socket *head, *so;
276 : int cloexec, nflag;
277 :
278 0 : cloexec = (flags & SOCK_CLOEXEC) ? UF_EXCLOSE : 0;
279 :
280 0 : if (name && (error = copyin(anamelen, &namelen, sizeof (namelen))))
281 0 : return (error);
282 0 : if ((error = getsock(p, sock, &fp)) != 0)
283 0 : return (error);
284 :
285 0 : headfp = fp;
286 :
287 0 : fdplock(fdp);
288 0 : error = falloc(p, &fp, &tmpfd);
289 0 : fdpunlock(fdp);
290 0 : if (error) {
291 0 : FRELE(headfp, p);
292 0 : return (error);
293 : }
294 :
295 0 : nam = m_get(M_WAIT, MT_SONAME);
296 :
297 0 : head = headfp->f_data;
298 0 : s = solock(head);
299 0 : if (isdnssocket(head) || (head->so_options & SO_ACCEPTCONN) == 0) {
300 : error = EINVAL;
301 0 : goto out;
302 : }
303 0 : if ((headfp->f_flag & FNONBLOCK) && head->so_qlen == 0) {
304 0 : if (head->so_state & SS_CANTRCVMORE)
305 0 : error = ECONNABORTED;
306 : else
307 : error = EWOULDBLOCK;
308 : goto out;
309 : }
310 0 : while (head->so_qlen == 0 && head->so_error == 0) {
311 0 : if (head->so_state & SS_CANTRCVMORE) {
312 0 : head->so_error = ECONNABORTED;
313 0 : break;
314 : }
315 0 : error = sosleep(head, &head->so_timeo, PSOCK | PCATCH, "netcon",
316 : 0);
317 0 : if (error)
318 : goto out;
319 : }
320 0 : if (head->so_error) {
321 : error = head->so_error;
322 0 : head->so_error = 0;
323 0 : goto out;
324 : }
325 :
326 : /*
327 : * Do not sleep after we have taken the socket out of the queue.
328 : */
329 0 : so = TAILQ_FIRST(&head->so_q);
330 0 : if (soqremque(so, 1) == 0)
331 0 : panic("accept");
332 :
333 : /* Figure out whether the new socket should be non-blocking. */
334 0 : nflag = flags & SOCK_NONBLOCK_INHERIT ? (headfp->f_flag & FNONBLOCK)
335 0 : : (flags & SOCK_NONBLOCK ? FNONBLOCK : 0);
336 :
337 : /* connection has been removed from the listen queue */
338 0 : KNOTE(&head->so_rcv.sb_sel.si_note, NOTE_SUBMIT);
339 :
340 0 : fp->f_type = DTYPE_SOCKET;
341 0 : fp->f_flag = FREAD | FWRITE | nflag;
342 0 : fp->f_ops = &socketops;
343 0 : error = soaccept(so, nam);
344 0 : if (!error && name != NULL)
345 0 : error = copyaddrout(p, nam, name, namelen, anamelen);
346 : out:
347 0 : if (!error) {
348 : sounlock(head, s);
349 0 : fdplock(fdp);
350 0 : fp->f_data = so;
351 0 : fdinsert(fdp, tmpfd, cloexec, fp);
352 0 : fdpunlock(fdp);
353 0 : FRELE(fp, p);
354 0 : *retval = tmpfd;
355 0 : } else {
356 : sounlock(head, s);
357 0 : fdplock(fdp);
358 0 : fdremove(fdp, tmpfd);
359 0 : closef(fp, p);
360 0 : fdpunlock(fdp);
361 : }
362 :
363 0 : m_freem(nam);
364 0 : FRELE(headfp, p);
365 0 : return (error);
366 0 : }
367 :
368 : int
369 0 : sys_connect(struct proc *p, void *v, register_t *retval)
370 : {
371 : struct sys_connect_args /* {
372 : syscallarg(int) s;
373 : syscallarg(const struct sockaddr *) name;
374 : syscallarg(socklen_t) namelen;
375 0 : } */ *uap = v;
376 0 : struct file *fp;
377 : struct socket *so;
378 0 : struct mbuf *nam = NULL;
379 : int error, s, interrupted = 0;
380 :
381 0 : if ((error = getsock(p, SCARG(uap, s), &fp)) != 0)
382 0 : return (error);
383 0 : so = fp->f_data;
384 0 : s = solock(so);
385 0 : if (so->so_state & SS_ISCONNECTING) {
386 : error = EALREADY;
387 0 : goto out;
388 : }
389 0 : error = sockargs(&nam, SCARG(uap, name), SCARG(uap, namelen),
390 : MT_SONAME);
391 0 : if (error)
392 : goto out;
393 0 : error = pledge_socket(p, so->so_proto->pr_domain->dom_family,
394 0 : so->so_state);
395 0 : if (error)
396 : goto out;
397 : #ifdef KTRACE
398 0 : if (KTRPOINT(p, KTR_STRUCT))
399 0 : ktrsockaddr(p, mtod(nam, caddr_t), SCARG(uap, namelen));
400 : #endif
401 :
402 0 : if (isdnssocket(so)) {
403 0 : u_int namelen = nam->m_len;
404 0 : error = dns_portcheck(p, so, mtod(nam, void *), &namelen);
405 0 : if (error)
406 0 : goto out;
407 0 : nam->m_len = namelen;
408 0 : }
409 :
410 0 : error = soconnect(so, nam);
411 0 : if (error)
412 : goto bad;
413 0 : if ((fp->f_flag & FNONBLOCK) && (so->so_state & SS_ISCONNECTING)) {
414 : error = EINPROGRESS;
415 0 : goto out;
416 : }
417 0 : while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) {
418 0 : error = sosleep(so, &so->so_timeo, PSOCK | PCATCH,
419 : "netcon2", 0);
420 0 : if (error) {
421 0 : if (error == EINTR || error == ERESTART)
422 0 : interrupted = 1;
423 : break;
424 : }
425 : }
426 0 : if (error == 0) {
427 0 : error = so->so_error;
428 0 : so->so_error = 0;
429 0 : }
430 : bad:
431 0 : if (!interrupted)
432 0 : so->so_state &= ~SS_ISCONNECTING;
433 : out:
434 0 : sounlock(so, s);
435 0 : FRELE(fp, p);
436 0 : m_freem(nam);
437 0 : if (error == ERESTART)
438 0 : error = EINTR;
439 0 : return (error);
440 0 : }
441 :
442 : int
443 0 : sys_socketpair(struct proc *p, void *v, register_t *retval)
444 : {
445 : struct sys_socketpair_args /* {
446 : syscallarg(int) domain;
447 : syscallarg(int) type;
448 : syscallarg(int) protocol;
449 : syscallarg(int *) rsv;
450 0 : } */ *uap = v;
451 0 : struct filedesc *fdp = p->p_fd;
452 0 : struct file *fp1, *fp2;
453 0 : struct socket *so1, *so2;
454 0 : int type, cloexec, nonblock, fflag, error, sv[2];
455 :
456 0 : type = SCARG(uap, type) & ~(SOCK_CLOEXEC | SOCK_NONBLOCK);
457 0 : cloexec = (SCARG(uap, type) & SOCK_CLOEXEC) ? UF_EXCLOSE : 0;
458 0 : nonblock = SCARG(uap, type) & SOCK_NONBLOCK;
459 0 : fflag = FREAD | FWRITE | (nonblock ? FNONBLOCK : 0);
460 :
461 0 : error = socreate(SCARG(uap, domain), &so1, type, SCARG(uap, protocol));
462 0 : if (error)
463 0 : return (error);
464 0 : error = socreate(SCARG(uap, domain), &so2, type, SCARG(uap, protocol));
465 0 : if (error)
466 : goto free1;
467 :
468 0 : error = soconnect2(so1, so2);
469 0 : if (error != 0)
470 : goto free2;
471 :
472 0 : if ((SCARG(uap, type) & SOCK_TYPE_MASK) == SOCK_DGRAM) {
473 : /*
474 : * Datagram socket connection is asymmetric.
475 : */
476 0 : error = soconnect2(so2, so1);
477 0 : if (error != 0)
478 : goto free2;
479 : }
480 0 : KERNEL_LOCK();
481 0 : fdplock(fdp);
482 0 : if ((error = falloc(p, &fp1, &sv[0])) != 0)
483 : goto free3;
484 0 : fp1->f_flag = fflag;
485 0 : fp1->f_type = DTYPE_SOCKET;
486 0 : fp1->f_ops = &socketops;
487 0 : fp1->f_data = so1;
488 0 : if ((error = falloc(p, &fp2, &sv[1])) != 0)
489 : goto free4;
490 0 : fp2->f_flag = fflag;
491 0 : fp2->f_type = DTYPE_SOCKET;
492 0 : fp2->f_ops = &socketops;
493 0 : fp2->f_data = so2;
494 0 : error = copyout(sv, SCARG(uap, rsv), 2 * sizeof (int));
495 0 : if (error == 0) {
496 : #ifdef KTRACE
497 0 : if (KTRPOINT(p, KTR_STRUCT))
498 0 : ktrfds(p, sv, 2);
499 : #endif
500 0 : fdinsert(fdp, sv[0], cloexec, fp1);
501 0 : fdinsert(fdp, sv[1], cloexec, fp2);
502 0 : fdpunlock(fdp);
503 0 : FRELE(fp1, p);
504 0 : FRELE(fp2, p);
505 0 : KERNEL_UNLOCK();
506 0 : return (0);
507 : }
508 0 : fdremove(fdp, sv[1]);
509 0 : closef(fp2, p);
510 0 : so2 = NULL;
511 : free4:
512 0 : fdremove(fdp, sv[0]);
513 0 : closef(fp1, p);
514 0 : so1 = NULL;
515 : free3:
516 0 : fdpunlock(fdp);
517 0 : KERNEL_UNLOCK();
518 : free2:
519 0 : if (so2 != NULL)
520 0 : (void)soclose(so2, 0);
521 : free1:
522 0 : if (so1 != NULL)
523 0 : (void)soclose(so1, 0);
524 0 : return (error);
525 0 : }
526 :
527 : int
528 0 : sys_sendto(struct proc *p, void *v, register_t *retval)
529 : {
530 : struct sys_sendto_args /* {
531 : syscallarg(int) s;
532 : syscallarg(const void *) buf;
533 : syscallarg(size_t) len;
534 : syscallarg(int) flags;
535 : syscallarg(const struct sockaddr *) to;
536 : syscallarg(socklen_t) tolen;
537 0 : } */ *uap = v;
538 0 : struct msghdr msg;
539 0 : struct iovec aiov;
540 :
541 0 : msg.msg_name = (caddr_t)SCARG(uap, to);
542 0 : msg.msg_namelen = SCARG(uap, tolen);
543 0 : msg.msg_iov = &aiov;
544 0 : msg.msg_iovlen = 1;
545 0 : msg.msg_control = 0;
546 0 : msg.msg_flags = 0;
547 0 : aiov.iov_base = (char *)SCARG(uap, buf);
548 0 : aiov.iov_len = SCARG(uap, len);
549 0 : return (sendit(p, SCARG(uap, s), &msg, SCARG(uap, flags), retval));
550 0 : }
551 :
552 : int
553 0 : sys_sendmsg(struct proc *p, void *v, register_t *retval)
554 : {
555 : struct sys_sendmsg_args /* {
556 : syscallarg(int) s;
557 : syscallarg(const struct msghdr *) msg;
558 : syscallarg(int) flags;
559 0 : } */ *uap = v;
560 0 : struct msghdr msg;
561 0 : struct iovec aiov[UIO_SMALLIOV], *iov;
562 : int error;
563 :
564 0 : error = copyin(SCARG(uap, msg), &msg, sizeof (msg));
565 0 : if (error)
566 0 : return (error);
567 : #ifdef KTRACE
568 0 : if (KTRPOINT(p, KTR_STRUCT))
569 0 : ktrmsghdr(p, &msg);
570 : #endif
571 :
572 0 : if (msg.msg_iovlen > IOV_MAX)
573 0 : return (EMSGSIZE);
574 0 : if (msg.msg_iovlen > UIO_SMALLIOV)
575 0 : iov = mallocarray(msg.msg_iovlen, sizeof(struct iovec),
576 : M_IOV, M_WAITOK);
577 : else
578 0 : iov = aiov;
579 0 : if (msg.msg_iovlen &&
580 0 : (error = copyin(msg.msg_iov, iov,
581 0 : (unsigned)(msg.msg_iovlen * sizeof (struct iovec)))))
582 : goto done;
583 : #ifdef KTRACE
584 0 : if (msg.msg_iovlen && KTRPOINT(p, KTR_STRUCT))
585 0 : ktriovec(p, iov, msg.msg_iovlen);
586 : #endif
587 0 : msg.msg_iov = iov;
588 0 : msg.msg_flags = 0;
589 0 : error = sendit(p, SCARG(uap, s), &msg, SCARG(uap, flags), retval);
590 : done:
591 0 : if (iov != aiov)
592 0 : free(iov, M_IOV, sizeof(struct iovec) * msg.msg_iovlen);
593 0 : return (error);
594 0 : }
595 :
596 : int
597 0 : sendit(struct proc *p, int s, struct msghdr *mp, int flags, register_t *retsize)
598 : {
599 0 : struct file *fp;
600 0 : struct uio auio;
601 : struct iovec *iov;
602 : int i;
603 0 : struct mbuf *to, *control;
604 : struct socket *so;
605 : size_t len;
606 : int error;
607 : #ifdef KTRACE
608 : struct iovec *ktriov = NULL;
609 : int iovlen = 0;
610 : #endif
611 :
612 0 : to = NULL;
613 :
614 0 : if ((error = getsock(p, s, &fp)) != 0)
615 0 : return (error);
616 0 : so = fp->f_data;
617 0 : if (fp->f_flag & FNONBLOCK)
618 0 : flags |= MSG_DONTWAIT;
619 :
620 0 : error = pledge_sendit(p, mp->msg_name);
621 0 : if (error)
622 : goto bad;
623 :
624 0 : auio.uio_iov = mp->msg_iov;
625 0 : auio.uio_iovcnt = mp->msg_iovlen;
626 0 : auio.uio_segflg = UIO_USERSPACE;
627 0 : auio.uio_rw = UIO_WRITE;
628 0 : auio.uio_procp = p;
629 0 : auio.uio_offset = 0; /* XXX */
630 0 : auio.uio_resid = 0;
631 0 : iov = mp->msg_iov;
632 0 : for (i = 0; i < mp->msg_iovlen; i++, iov++) {
633 : /* Don't allow sum > SSIZE_MAX */
634 0 : if (iov->iov_len > SSIZE_MAX ||
635 0 : (auio.uio_resid += iov->iov_len) > SSIZE_MAX) {
636 : error = EINVAL;
637 0 : goto bad;
638 : }
639 : }
640 0 : if (mp->msg_name) {
641 0 : error = sockargs(&to, mp->msg_name, mp->msg_namelen,
642 : MT_SONAME);
643 0 : if (error)
644 : goto bad;
645 0 : if (isdnssocket(so)) {
646 0 : u_int namelen = mp->msg_namelen;
647 0 : error = dns_portcheck(p, so, mtod(to, caddr_t),
648 : &namelen);
649 0 : if (error)
650 0 : goto bad;
651 0 : mp->msg_namelen = namelen;
652 0 : }
653 : #ifdef KTRACE
654 0 : if (KTRPOINT(p, KTR_STRUCT))
655 0 : ktrsockaddr(p, mtod(to, caddr_t), mp->msg_namelen);
656 : #endif
657 : }
658 0 : if (mp->msg_control) {
659 0 : if (mp->msg_controllen < CMSG_ALIGN(sizeof(struct cmsghdr))) {
660 : error = EINVAL;
661 0 : goto bad;
662 : }
663 0 : error = sockargs(&control, mp->msg_control,
664 : mp->msg_controllen, MT_CONTROL);
665 0 : if (error)
666 : goto bad;
667 : #ifdef KTRACE
668 0 : if (KTRPOINT(p, KTR_STRUCT) && mp->msg_controllen)
669 0 : ktrcmsghdr(p, mtod(control, char *),
670 : mp->msg_controllen);
671 : #endif
672 : } else
673 0 : control = 0;
674 : #ifdef KTRACE
675 0 : if (KTRPOINT(p, KTR_GENIO)) {
676 0 : ktriov = mallocarray(auio.uio_iovcnt, sizeof(struct iovec),
677 : M_TEMP, M_WAITOK);
678 0 : iovlen = auio.uio_iovcnt * sizeof (struct iovec);
679 :
680 0 : memcpy(ktriov, auio.uio_iov, iovlen);
681 0 : }
682 : #endif
683 0 : len = auio.uio_resid;
684 0 : error = sosend(so, to, &auio, NULL, control, flags);
685 0 : if (error) {
686 0 : if (auio.uio_resid != len && (error == ERESTART ||
687 0 : error == EINTR || error == EWOULDBLOCK))
688 0 : error = 0;
689 0 : if (error == EPIPE && (flags & MSG_NOSIGNAL) == 0) {
690 0 : KERNEL_LOCK();
691 0 : ptsignal(p, SIGPIPE, STHREAD);
692 0 : KERNEL_UNLOCK();
693 0 : }
694 : }
695 0 : if (error == 0) {
696 0 : *retsize = len - auio.uio_resid;
697 0 : mtx_enter(&fp->f_mtx);
698 0 : fp->f_wxfer++;
699 0 : fp->f_wbytes += *retsize;
700 0 : mtx_leave(&fp->f_mtx);
701 0 : }
702 : #ifdef KTRACE
703 0 : if (ktriov != NULL) {
704 0 : if (error == 0)
705 0 : ktrgenio(p, s, UIO_WRITE, ktriov, *retsize);
706 0 : free(ktriov, M_TEMP, iovlen);
707 0 : }
708 : #endif
709 : bad:
710 0 : FRELE(fp, p);
711 0 : m_freem(to);
712 0 : return (error);
713 0 : }
714 :
715 : int
716 0 : sys_recvfrom(struct proc *p, void *v, register_t *retval)
717 : {
718 : struct sys_recvfrom_args /* {
719 : syscallarg(int) s;
720 : syscallarg(void *) buf;
721 : syscallarg(size_t) len;
722 : syscallarg(int) flags;
723 : syscallarg(struct sockaddr *) from;
724 : syscallarg(socklen_t *) fromlenaddr;
725 0 : } */ *uap = v;
726 0 : struct msghdr msg;
727 0 : struct iovec aiov;
728 : int error;
729 :
730 0 : if (SCARG(uap, fromlenaddr)) {
731 0 : error = copyin(SCARG(uap, fromlenaddr),
732 0 : &msg.msg_namelen, sizeof (msg.msg_namelen));
733 0 : if (error)
734 0 : return (error);
735 : } else
736 0 : msg.msg_namelen = 0;
737 0 : msg.msg_name = (caddr_t)SCARG(uap, from);
738 0 : msg.msg_iov = &aiov;
739 0 : msg.msg_iovlen = 1;
740 0 : aiov.iov_base = SCARG(uap, buf);
741 0 : aiov.iov_len = SCARG(uap, len);
742 0 : msg.msg_control = 0;
743 0 : msg.msg_flags = SCARG(uap, flags);
744 0 : return (recvit(p, SCARG(uap, s), &msg,
745 0 : (caddr_t)SCARG(uap, fromlenaddr), retval));
746 0 : }
747 :
748 : int
749 0 : sys_recvmsg(struct proc *p, void *v, register_t *retval)
750 : {
751 : struct sys_recvmsg_args /* {
752 : syscallarg(int) s;
753 : syscallarg(struct msghdr *) msg;
754 : syscallarg(int) flags;
755 0 : } */ *uap = v;
756 0 : struct msghdr msg;
757 0 : struct iovec aiov[UIO_SMALLIOV], *uiov, *iov;
758 : int error;
759 :
760 0 : error = copyin(SCARG(uap, msg), &msg, sizeof (msg));
761 0 : if (error)
762 0 : return (error);
763 :
764 0 : if (msg.msg_iovlen > IOV_MAX)
765 0 : return (EMSGSIZE);
766 0 : if (msg.msg_iovlen > UIO_SMALLIOV)
767 0 : iov = mallocarray(msg.msg_iovlen, sizeof(struct iovec),
768 : M_IOV, M_WAITOK);
769 : else
770 0 : iov = aiov;
771 0 : msg.msg_flags = SCARG(uap, flags);
772 0 : if (msg.msg_iovlen > 0) {
773 0 : error = copyin(msg.msg_iov, iov,
774 0 : msg.msg_iovlen * sizeof(struct iovec));
775 0 : if (error)
776 : goto done;
777 : }
778 0 : uiov = msg.msg_iov;
779 0 : msg.msg_iov = iov;
780 0 : if ((error = recvit(p, SCARG(uap, s), &msg, NULL, retval)) == 0) {
781 0 : msg.msg_iov = uiov;
782 : #ifdef KTRACE
783 0 : if (KTRPOINT(p, KTR_STRUCT)) {
784 0 : ktrmsghdr(p, &msg);
785 0 : if (msg.msg_iovlen)
786 0 : ktriovec(p, iov, msg.msg_iovlen);
787 : }
788 : #endif
789 0 : error = copyout(&msg, SCARG(uap, msg), sizeof(msg));
790 0 : }
791 : done:
792 0 : if (iov != aiov)
793 0 : free(iov, M_IOV, sizeof(struct iovec) * msg.msg_iovlen);
794 0 : return (error);
795 0 : }
796 :
797 : int
798 0 : recvit(struct proc *p, int s, struct msghdr *mp, caddr_t namelenp,
799 : register_t *retsize)
800 : {
801 0 : struct file *fp;
802 0 : struct uio auio;
803 : struct iovec *iov;
804 : int i;
805 : size_t len;
806 : int error;
807 0 : struct mbuf *from = NULL, *control = NULL;
808 : #ifdef KTRACE
809 : struct iovec *ktriov = NULL;
810 : int iovlen = 0;
811 : #endif
812 :
813 0 : if ((error = getsock(p, s, &fp)) != 0)
814 0 : return (error);
815 :
816 0 : auio.uio_iov = mp->msg_iov;
817 0 : auio.uio_iovcnt = mp->msg_iovlen;
818 0 : auio.uio_segflg = UIO_USERSPACE;
819 0 : auio.uio_rw = UIO_READ;
820 0 : auio.uio_procp = p;
821 0 : auio.uio_offset = 0; /* XXX */
822 0 : auio.uio_resid = 0;
823 0 : iov = mp->msg_iov;
824 0 : for (i = 0; i < mp->msg_iovlen; i++, iov++) {
825 : /* Don't allow sum > SSIZE_MAX */
826 0 : if (iov->iov_len > SSIZE_MAX ||
827 0 : (auio.uio_resid += iov->iov_len) > SSIZE_MAX) {
828 : error = EINVAL;
829 0 : goto out;
830 : }
831 : }
832 : #ifdef KTRACE
833 0 : if (KTRPOINT(p, KTR_GENIO)) {
834 0 : ktriov = mallocarray(auio.uio_iovcnt, sizeof(struct iovec),
835 : M_TEMP, M_WAITOK);
836 0 : iovlen = auio.uio_iovcnt * sizeof (struct iovec);
837 :
838 0 : memcpy(ktriov, auio.uio_iov, iovlen);
839 0 : }
840 : #endif
841 0 : len = auio.uio_resid;
842 0 : if (fp->f_flag & FNONBLOCK)
843 0 : mp->msg_flags |= MSG_DONTWAIT;
844 0 : error = soreceive(fp->f_data, &from, &auio, NULL,
845 0 : mp->msg_control ? &control : NULL,
846 0 : &mp->msg_flags,
847 0 : mp->msg_control ? mp->msg_controllen : 0);
848 0 : if (error) {
849 0 : if (auio.uio_resid != len && (error == ERESTART ||
850 0 : error == EINTR || error == EWOULDBLOCK))
851 0 : error = 0;
852 : }
853 : #ifdef KTRACE
854 0 : if (ktriov != NULL) {
855 0 : if (error == 0)
856 0 : ktrgenio(p, s, UIO_READ, ktriov, len - auio.uio_resid);
857 0 : free(ktriov, M_TEMP, iovlen);
858 0 : }
859 : #endif
860 0 : if (error)
861 : goto out;
862 0 : *retsize = len - auio.uio_resid;
863 0 : if (mp->msg_name) {
864 0 : socklen_t alen;
865 :
866 0 : if (from == NULL)
867 0 : alen = 0;
868 : else {
869 0 : alen = from->m_len;
870 0 : error = copyout(mtod(from, caddr_t), mp->msg_name,
871 0 : MIN(alen, mp->msg_namelen));
872 0 : if (error)
873 0 : goto out;
874 : #ifdef KTRACE
875 0 : if (KTRPOINT(p, KTR_STRUCT))
876 0 : ktrsockaddr(p, mtod(from, caddr_t), alen);
877 : #endif
878 : }
879 0 : mp->msg_namelen = alen;
880 0 : if (namelenp &&
881 0 : (error = copyout(&alen, namelenp, sizeof(alen)))) {
882 0 : goto out;
883 : }
884 0 : }
885 0 : if (mp->msg_control) {
886 0 : len = mp->msg_controllen;
887 0 : if (len <= 0 || control == NULL)
888 0 : len = 0;
889 : else {
890 : struct mbuf *m = control;
891 : caddr_t cp = mp->msg_control;
892 :
893 0 : do {
894 0 : i = m->m_len;
895 0 : if (len < i) {
896 0 : mp->msg_flags |= MSG_CTRUNC;
897 0 : i = len;
898 0 : }
899 0 : error = copyout(mtod(m, caddr_t), cp, i);
900 : #ifdef KTRACE
901 0 : if (KTRPOINT(p, KTR_STRUCT) && error == 0 && i)
902 0 : ktrcmsghdr(p, mtod(m, char *), i);
903 : #endif
904 0 : if (m->m_next)
905 0 : i = ALIGN(i);
906 0 : cp += i;
907 0 : len -= i;
908 0 : if (error != 0 || len <= 0)
909 : break;
910 0 : } while ((m = m->m_next) != NULL);
911 0 : len = cp - (caddr_t)mp->msg_control;
912 : }
913 0 : mp->msg_controllen = len;
914 0 : }
915 0 : if (!error) {
916 0 : mtx_enter(&fp->f_mtx);
917 0 : fp->f_rxfer++;
918 0 : fp->f_rbytes += *retsize;
919 0 : mtx_leave(&fp->f_mtx);
920 0 : }
921 : out:
922 0 : FRELE(fp, p);
923 0 : m_freem(from);
924 0 : m_freem(control);
925 0 : return (error);
926 0 : }
927 :
928 : int
929 0 : sys_shutdown(struct proc *p, void *v, register_t *retval)
930 : {
931 : struct sys_shutdown_args /* {
932 : syscallarg(int) s;
933 : syscallarg(int) how;
934 0 : } */ *uap = v;
935 0 : struct file *fp;
936 : int error;
937 :
938 0 : if ((error = getsock(p, SCARG(uap, s), &fp)) != 0)
939 0 : return (error);
940 0 : error = soshutdown(fp->f_data, SCARG(uap, how));
941 0 : FRELE(fp, p);
942 0 : return (error);
943 0 : }
944 :
945 : int
946 0 : sys_setsockopt(struct proc *p, void *v, register_t *retval)
947 : {
948 : struct sys_setsockopt_args /* {
949 : syscallarg(int) s;
950 : syscallarg(int) level;
951 : syscallarg(int) name;
952 : syscallarg(const void *) val;
953 : syscallarg(socklen_t) valsize;
954 0 : } */ *uap = v;
955 0 : struct file *fp;
956 : struct mbuf *m = NULL;
957 : struct socket *so;
958 : int s, error;
959 :
960 :
961 0 : if ((error = getsock(p, SCARG(uap, s), &fp)) != 0)
962 0 : return (error);
963 0 : error = pledge_sockopt(p, 1, SCARG(uap, level), SCARG(uap, name));
964 0 : if (error)
965 : goto bad;
966 0 : if (SCARG(uap, valsize) > MCLBYTES) {
967 : error = EINVAL;
968 0 : goto bad;
969 : }
970 0 : if (SCARG(uap, val)) {
971 0 : m = m_get(M_WAIT, MT_SOOPTS);
972 0 : if (SCARG(uap, valsize) > MLEN) {
973 0 : MCLGET(m, M_DONTWAIT);
974 0 : if ((m->m_flags & M_EXT) == 0) {
975 : error = ENOBUFS;
976 0 : goto bad;
977 : }
978 : }
979 0 : if (m == NULL) {
980 : error = ENOBUFS;
981 0 : goto bad;
982 : }
983 0 : error = copyin(SCARG(uap, val), mtod(m, caddr_t),
984 0 : SCARG(uap, valsize));
985 0 : if (error) {
986 : goto bad;
987 : }
988 0 : m->m_len = SCARG(uap, valsize);
989 0 : }
990 0 : so = fp->f_data;
991 0 : s = solock(so);
992 0 : error = sosetopt(so, SCARG(uap, level), SCARG(uap, name), m);
993 0 : sounlock(so, s);
994 : bad:
995 0 : m_freem(m);
996 0 : FRELE(fp, p);
997 0 : return (error);
998 0 : }
999 :
1000 : int
1001 0 : sys_getsockopt(struct proc *p, void *v, register_t *retval)
1002 : {
1003 : struct sys_getsockopt_args /* {
1004 : syscallarg(int) s;
1005 : syscallarg(int) level;
1006 : syscallarg(int) name;
1007 : syscallarg(void *) val;
1008 : syscallarg(socklen_t *) avalsize;
1009 0 : } */ *uap = v;
1010 0 : struct file *fp;
1011 : struct mbuf *m = NULL;
1012 0 : socklen_t valsize;
1013 : struct socket *so;
1014 : int s, error;
1015 :
1016 0 : if ((error = getsock(p, SCARG(uap, s), &fp)) != 0)
1017 0 : return (error);
1018 0 : error = pledge_sockopt(p, 0, SCARG(uap, level), SCARG(uap, name));
1019 0 : if (error)
1020 : goto out;
1021 0 : if (SCARG(uap, val)) {
1022 0 : error = copyin(SCARG(uap, avalsize),
1023 : &valsize, sizeof (valsize));
1024 0 : if (error)
1025 : goto out;
1026 : } else
1027 0 : valsize = 0;
1028 0 : m = m_get(M_WAIT, MT_SOOPTS);
1029 0 : so = fp->f_data;
1030 0 : s = solock(so);
1031 0 : error = sogetopt(so, SCARG(uap, level), SCARG(uap, name), m);
1032 0 : sounlock(so, s);
1033 0 : if (error == 0 && SCARG(uap, val) && valsize && m != NULL) {
1034 0 : if (valsize > m->m_len)
1035 0 : valsize = m->m_len;
1036 0 : error = copyout(mtod(m, caddr_t), SCARG(uap, val), valsize);
1037 0 : if (error == 0)
1038 0 : error = copyout(&valsize,
1039 0 : SCARG(uap, avalsize), sizeof (valsize));
1040 : }
1041 0 : m_free(m);
1042 : out:
1043 0 : FRELE(fp, p);
1044 0 : return (error);
1045 0 : }
1046 :
1047 : /*
1048 : * Get socket name.
1049 : */
1050 : int
1051 0 : sys_getsockname(struct proc *p, void *v, register_t *retval)
1052 : {
1053 : struct sys_getsockname_args /* {
1054 : syscallarg(int) fdes;
1055 : syscallarg(struct sockaddr *) asa;
1056 : syscallarg(socklen_t *) alen;
1057 0 : } */ *uap = v;
1058 0 : struct file *fp;
1059 : struct socket *so;
1060 : struct mbuf *m = NULL;
1061 0 : socklen_t len;
1062 : int error, s;
1063 :
1064 0 : if ((error = getsock(p, SCARG(uap, fdes), &fp)) != 0)
1065 0 : return (error);
1066 0 : error = copyin(SCARG(uap, alen), &len, sizeof (len));
1067 0 : if (error)
1068 : goto bad;
1069 0 : so = fp->f_data;
1070 0 : error = pledge_socket(p, -1, so->so_state);
1071 0 : if (error)
1072 : goto bad;
1073 0 : m = m_getclr(M_WAIT, MT_SONAME);
1074 0 : s = solock(so);
1075 0 : error = (*so->so_proto->pr_usrreq)(so, PRU_SOCKADDR, 0, m, 0, p);
1076 0 : sounlock(so, s);
1077 0 : if (error)
1078 : goto bad;
1079 0 : error = copyaddrout(p, m, SCARG(uap, asa), len, SCARG(uap, alen));
1080 : bad:
1081 0 : FRELE(fp, p);
1082 0 : m_freem(m);
1083 0 : return (error);
1084 0 : }
1085 :
1086 : /*
1087 : * Get name of peer for connected socket.
1088 : */
1089 : int
1090 0 : sys_getpeername(struct proc *p, void *v, register_t *retval)
1091 : {
1092 : struct sys_getpeername_args /* {
1093 : syscallarg(int) fdes;
1094 : syscallarg(struct sockaddr *) asa;
1095 : syscallarg(socklen_t *) alen;
1096 0 : } */ *uap = v;
1097 0 : struct file *fp;
1098 : struct socket *so;
1099 : struct mbuf *m = NULL;
1100 0 : socklen_t len;
1101 : int error, s;
1102 :
1103 0 : if ((error = getsock(p, SCARG(uap, fdes), &fp)) != 0)
1104 0 : return (error);
1105 0 : so = fp->f_data;
1106 0 : error = pledge_socket(p, -1, so->so_state);
1107 0 : if (error)
1108 : goto bad;
1109 0 : if ((so->so_state & SS_ISCONNECTED) == 0) {
1110 : error = ENOTCONN;
1111 0 : goto bad;
1112 : }
1113 0 : error = copyin(SCARG(uap, alen), &len, sizeof (len));
1114 0 : if (error)
1115 : goto bad;
1116 0 : m = m_getclr(M_WAIT, MT_SONAME);
1117 0 : s = solock(so);
1118 0 : error = (*so->so_proto->pr_usrreq)(so, PRU_PEERADDR, 0, m, 0, p);
1119 0 : sounlock(so, s);
1120 0 : if (error)
1121 : goto bad;
1122 0 : error = copyaddrout(p, m, SCARG(uap, asa), len, SCARG(uap, alen));
1123 : bad:
1124 0 : FRELE(fp, p);
1125 0 : m_freem(m);
1126 0 : return (error);
1127 0 : }
1128 :
1129 : int
1130 0 : sockargs(struct mbuf **mp, const void *buf, size_t buflen, int type)
1131 : {
1132 : struct sockaddr *sa;
1133 : struct mbuf *m;
1134 : int error;
1135 :
1136 : /*
1137 : * We can't allow socket names > UCHAR_MAX in length, since that
1138 : * will overflow sa_len. Also, control data more than MCLBYTES in
1139 : * length is just too much.
1140 : * Memory for sa_len and sa_family must exist.
1141 : */
1142 0 : if ((buflen > (type == MT_SONAME ? UCHAR_MAX : MCLBYTES)) ||
1143 0 : (type == MT_SONAME && buflen < offsetof(struct sockaddr, sa_data)))
1144 0 : return (EINVAL);
1145 :
1146 : /* Allocate an mbuf to hold the arguments. */
1147 0 : m = m_get(M_WAIT, type);
1148 0 : if (buflen > MLEN) {
1149 0 : MCLGET(m, M_WAITOK);
1150 0 : if ((m->m_flags & M_EXT) == 0) {
1151 0 : m_free(m);
1152 0 : return ENOBUFS;
1153 : }
1154 : }
1155 0 : m->m_len = buflen;
1156 0 : error = copyin(buf, mtod(m, caddr_t), buflen);
1157 0 : if (error) {
1158 0 : (void) m_free(m);
1159 0 : return (error);
1160 : }
1161 0 : *mp = m;
1162 0 : if (type == MT_SONAME) {
1163 0 : sa = mtod(m, struct sockaddr *);
1164 0 : sa->sa_len = buflen;
1165 0 : }
1166 0 : return (0);
1167 0 : }
1168 :
1169 : int
1170 0 : getsock(struct proc *p, int fdes, struct file **fpp)
1171 : {
1172 : struct file *fp;
1173 :
1174 0 : fp = fd_getfile(p->p_fd, fdes);
1175 0 : if (fp == NULL)
1176 0 : return (EBADF);
1177 0 : if (fp->f_type != DTYPE_SOCKET) {
1178 0 : FRELE(fp, p);
1179 0 : return (ENOTSOCK);
1180 : }
1181 0 : *fpp = fp;
1182 :
1183 0 : return (0);
1184 0 : }
1185 :
1186 : int
1187 0 : sys_setrtable(struct proc *p, void *v, register_t *retval)
1188 : {
1189 : struct sys_setrtable_args /* {
1190 : syscallarg(int) rtableid;
1191 0 : } */ *uap = v;
1192 : int rtableid, error;
1193 :
1194 0 : rtableid = SCARG(uap, rtableid);
1195 :
1196 0 : if (p->p_p->ps_rtableid == (u_int)rtableid)
1197 0 : return (0);
1198 0 : if (p->p_p->ps_rtableid != 0 && (error = suser(p)) != 0)
1199 0 : return (error);
1200 0 : if (rtableid < 0 || !rtable_exists((u_int)rtableid))
1201 0 : return (EINVAL);
1202 :
1203 0 : p->p_p->ps_rtableid = (u_int)rtableid;
1204 0 : return (0);
1205 0 : }
1206 :
1207 : int
1208 0 : sys_getrtable(struct proc *p, void *v, register_t *retval)
1209 : {
1210 0 : *retval = (int)p->p_p->ps_rtableid;
1211 0 : return (0);
1212 : }
1213 :
1214 : int
1215 0 : copyaddrout(struct proc *p, struct mbuf *name, struct sockaddr *sa,
1216 : socklen_t buflen, socklen_t *outlen)
1217 : {
1218 : int error;
1219 0 : socklen_t namelen = name->m_len;
1220 :
1221 : /* SHOULD COPY OUT A CHAIN HERE */
1222 0 : error = copyout(mtod(name, caddr_t), sa, MIN(buflen, namelen));
1223 0 : if (error == 0) {
1224 : #ifdef KTRACE
1225 0 : if (KTRPOINT(p, KTR_STRUCT))
1226 0 : ktrsockaddr(p, mtod(name, caddr_t), namelen);
1227 : #endif
1228 0 : error = copyout(&namelen, outlen, sizeof(*outlen));
1229 0 : }
1230 :
1231 0 : return (error);
1232 0 : }
|