This source file includes following definitions.
- sys_socket
- sys_bind
- sys_listen
- sys_accept
- sys_connect
- sys_socketpair
- sys_sendto
- sys_sendmsg
- sendit
- sys_recvfrom
- sys_recvmsg
- recvit
- sys_shutdown
- sys_setsockopt
- sys_getsockopt
- sys_pipe
- sys_getsockname
- sys_getpeername
- sys_getpeereid
- sockargs
- getsock
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
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/file.h>
40 #include <sys/buf.h>
41 #include <sys/malloc.h>
42 #include <sys/event.h>
43 #include <sys/mbuf.h>
44 #include <sys/protosw.h>
45 #include <sys/socket.h>
46 #include <sys/socketvar.h>
47 #include <sys/signalvar.h>
48 #include <sys/unpcb.h>
49 #include <sys/un.h>
50 #ifdef KTRACE
51 #include <sys/ktrace.h>
52 #endif
53
54 #include <sys/mount.h>
55 #include <sys/syscallargs.h>
56
57
58
59
60 extern struct fileops socketops;
61
62 int
63 sys_socket(struct proc *p, void *v, register_t *retval)
64 {
65 struct sys_socket_args
66
67
68
69 *uap = v;
70 struct filedesc *fdp = p->p_fd;
71 struct socket *so;
72 struct file *fp;
73 int fd, error;
74
75 fdplock(fdp);
76
77 if ((error = falloc(p, &fp, &fd)) != 0)
78 goto out;
79 fp->f_flag = FREAD|FWRITE;
80 fp->f_type = DTYPE_SOCKET;
81 fp->f_ops = &socketops;
82 error = socreate(SCARG(uap, domain), &so, SCARG(uap, type),
83 SCARG(uap, protocol));
84 if (error) {
85 fdremove(fdp, fd);
86 closef(fp, p);
87 } else {
88 fp->f_data = so;
89 FILE_SET_MATURE(fp);
90 *retval = fd;
91 }
92 out:
93 fdpunlock(fdp);
94 return (error);
95 }
96
97
98 int
99 sys_bind(struct proc *p, void *v, register_t *retval)
100 {
101 struct sys_bind_args
102
103
104
105 *uap = v;
106 struct file *fp;
107 struct mbuf *nam;
108 int error;
109
110 if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0)
111 return (error);
112 error = sockargs(&nam, SCARG(uap, name), SCARG(uap, namelen),
113 MT_SONAME);
114 if (error == 0) {
115 error = sobind(fp->f_data, nam);
116 m_freem(nam);
117 }
118 FRELE(fp);
119 return (error);
120 }
121
122
123 int
124 sys_listen(struct proc *p, void *v, register_t *retval)
125 {
126 struct sys_listen_args
127
128
129 *uap = v;
130 struct file *fp;
131 int error;
132
133 if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0)
134 return (error);
135 error = solisten(fp->f_data, SCARG(uap, backlog));
136 FRELE(fp);
137 return (error);
138 }
139
140 int
141 sys_accept(struct proc *p, void *v, register_t *retval)
142 {
143 struct sys_accept_args
144
145
146
147 *uap = v;
148 struct file *fp, *headfp;
149 struct mbuf *nam;
150 socklen_t namelen;
151 int error, s, tmpfd;
152 struct socket *head, *so;
153 int nflag;
154
155 if (SCARG(uap, name) && (error = copyin(SCARG(uap, anamelen),
156 &namelen, sizeof (namelen))))
157 return (error);
158 if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0)
159 return (error);
160 headfp = fp;
161 s = splsoftnet();
162 head = fp->f_data;
163 if ((head->so_options & SO_ACCEPTCONN) == 0) {
164 error = EINVAL;
165 goto bad;
166 }
167 if ((head->so_state & SS_NBIO) && head->so_qlen == 0) {
168 if (head->so_state & SS_CANTRCVMORE)
169 error = ECONNABORTED;
170 else
171 error = EWOULDBLOCK;
172 goto bad;
173 }
174 while (head->so_qlen == 0 && head->so_error == 0) {
175 if (head->so_state & SS_CANTRCVMORE) {
176 head->so_error = ECONNABORTED;
177 break;
178 }
179 error = tsleep(&head->so_timeo, PSOCK | PCATCH, netcon, 0);
180 if (error) {
181 goto bad;
182 }
183 }
184 if (head->so_error) {
185 error = head->so_error;
186 head->so_error = 0;
187 goto bad;
188 }
189
190
191
192
193
194
195
196
197 so = TAILQ_FIRST(&head->so_q);
198 if (soqremque(so, 1) == 0)
199 panic("accept");
200
201
202 nflag = (fp->f_flag & FNONBLOCK);
203
204 fdplock(p->p_fd);
205 if ((error = falloc(p, &fp, &tmpfd)) != 0) {
206
207
208
209
210
211
212 so->so_head = head;
213 head->so_qlen++;
214 so->so_onq = &head->so_q;
215 TAILQ_INSERT_HEAD(so->so_onq, so, so_qe);
216 wakeup_one(&head->so_timeo);
217 goto bad;
218 }
219 *retval = tmpfd;
220
221
222 KNOTE(&head->so_rcv.sb_sel.si_note, 0);
223
224 fp->f_type = DTYPE_SOCKET;
225 fp->f_flag = FREAD | FWRITE | nflag;
226 fp->f_ops = &socketops;
227 fp->f_data = so;
228 nam = m_get(M_WAIT, MT_SONAME);
229 error = soaccept(so, nam);
230 if (!error && SCARG(uap, name)) {
231 if (namelen > nam->m_len)
232 namelen = nam->m_len;
233
234 if ((error = copyout(mtod(nam, caddr_t),
235 SCARG(uap, name), namelen)) == 0)
236 error = copyout(&namelen, SCARG(uap, anamelen),
237 sizeof (*SCARG(uap, anamelen)));
238 }
239
240 if (error) {
241 fdremove(p->p_fd, tmpfd);
242 closef(fp, p);
243 } else {
244 FILE_SET_MATURE(fp);
245 }
246 m_freem(nam);
247 bad:
248 fdpunlock(p->p_fd);
249 splx(s);
250 FRELE(headfp);
251 return (error);
252 }
253
254
255 int
256 sys_connect(struct proc *p, void *v, register_t *retval)
257 {
258 struct sys_connect_args
259
260
261
262 *uap = v;
263 struct file *fp;
264 struct socket *so;
265 struct mbuf *nam = NULL;
266 int error, s;
267
268 if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0)
269 return (error);
270 so = fp->f_data;
271 if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) {
272 FRELE(fp);
273 return (EALREADY);
274 }
275 error = sockargs(&nam, SCARG(uap, name), SCARG(uap, namelen),
276 MT_SONAME);
277 if (error)
278 goto bad;
279 error = soconnect(so, nam);
280 if (error)
281 goto bad;
282 if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) {
283 FRELE(fp);
284 m_freem(nam);
285 return (EINPROGRESS);
286 }
287 s = splsoftnet();
288 while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) {
289 error = tsleep(&so->so_timeo, PSOCK | PCATCH,
290 netcon, 0);
291 if (error)
292 break;
293 }
294 if (error == 0) {
295 error = so->so_error;
296 so->so_error = 0;
297 }
298 splx(s);
299 bad:
300 so->so_state &= ~SS_ISCONNECTING;
301 FRELE(fp);
302 if (nam)
303 m_freem(nam);
304 if (error == ERESTART)
305 error = EINTR;
306 return (error);
307 }
308
309 int
310 sys_socketpair(struct proc *p, void *v, register_t *retval)
311 {
312 struct sys_socketpair_args
313
314
315
316
317 *uap = v;
318 struct filedesc *fdp = p->p_fd;
319 struct file *fp1, *fp2;
320 struct socket *so1, *so2;
321 int fd, error, sv[2];
322
323 error = socreate(SCARG(uap, domain), &so1, SCARG(uap, type),
324 SCARG(uap, protocol));
325 if (error)
326 return (error);
327 error = socreate(SCARG(uap, domain), &so2, SCARG(uap, type),
328 SCARG(uap, protocol));
329 if (error)
330 goto free1;
331
332 fdplock(fdp);
333 if ((error = falloc(p, &fp1, &fd)) != 0)
334 goto free2;
335 sv[0] = fd;
336 fp1->f_flag = FREAD|FWRITE;
337 fp1->f_type = DTYPE_SOCKET;
338 fp1->f_ops = &socketops;
339 fp1->f_data = so1;
340 if ((error = falloc(p, &fp2, &fd)) != 0)
341 goto free3;
342 fp2->f_flag = FREAD|FWRITE;
343 fp2->f_type = DTYPE_SOCKET;
344 fp2->f_ops = &socketops;
345 fp2->f_data = so2;
346 sv[1] = fd;
347 if ((error = soconnect2(so1, so2)) != 0)
348 goto free4;
349 if (SCARG(uap, type) == SOCK_DGRAM) {
350
351
352
353 if ((error = soconnect2(so2, so1)) != 0)
354 goto free4;
355 }
356 error = copyout(sv, SCARG(uap, rsv), 2 * sizeof (int));
357 if (error == 0) {
358 FILE_SET_MATURE(fp1);
359 FILE_SET_MATURE(fp2);
360 fdpunlock(fdp);
361 return (0);
362 }
363 free4:
364 fdremove(fdp, sv[1]);
365 closef(fp2, p);
366 so2 = NULL;
367 free3:
368 fdremove(fdp, sv[0]);
369 closef(fp1, p);
370 so1 = NULL;
371 free2:
372 if (so2 != NULL)
373 (void)soclose(so2);
374 fdpunlock(fdp);
375 free1:
376 if (so1 != NULL)
377 (void)soclose(so1);
378 return (error);
379 }
380
381 int
382 sys_sendto(struct proc *p, void *v, register_t *retval)
383 {
384 struct sys_sendto_args
385
386
387
388
389
390
391 *uap = v;
392 struct msghdr msg;
393 struct iovec aiov;
394
395 msg.msg_name = (caddr_t)SCARG(uap, to);
396 msg.msg_namelen = SCARG(uap, tolen);
397 msg.msg_iov = &aiov;
398 msg.msg_iovlen = 1;
399 msg.msg_control = 0;
400 #ifdef COMPAT_OLDSOCK
401 msg.msg_flags = 0;
402 #endif
403 aiov.iov_base = (char *)SCARG(uap, buf);
404 aiov.iov_len = SCARG(uap, len);
405 return (sendit(p, SCARG(uap, s), &msg, SCARG(uap, flags), retval));
406 }
407
408 int
409 sys_sendmsg(struct proc *p, void *v, register_t *retval)
410 {
411 struct sys_sendmsg_args
412
413
414
415 *uap = v;
416 struct msghdr msg;
417 struct iovec aiov[UIO_SMALLIOV], *iov;
418 int error;
419
420 error = copyin(SCARG(uap, msg), &msg, sizeof (msg));
421 if (error)
422 return (error);
423 if (msg.msg_iovlen > IOV_MAX)
424 return (EMSGSIZE);
425 if (msg.msg_iovlen > UIO_SMALLIOV)
426 iov = malloc(sizeof(struct iovec) * msg.msg_iovlen,
427 M_IOV, M_WAITOK);
428 else
429 iov = aiov;
430 if (msg.msg_iovlen &&
431 (error = copyin(msg.msg_iov, iov,
432 (unsigned)(msg.msg_iovlen * sizeof (struct iovec)))))
433 goto done;
434 msg.msg_iov = iov;
435 #ifdef COMPAT_OLDSOCK
436 msg.msg_flags = 0;
437 #endif
438 error = sendit(p, SCARG(uap, s), &msg, SCARG(uap, flags), retval);
439 done:
440 if (iov != aiov)
441 free(iov, M_IOV);
442 return (error);
443 }
444
445 int
446 sendit(struct proc *p, int s, struct msghdr *mp, int flags, register_t *retsize)
447 {
448 struct file *fp;
449 struct uio auio;
450 struct iovec *iov;
451 int i;
452 struct mbuf *to, *control;
453 int len, error;
454 #ifdef KTRACE
455 struct iovec *ktriov = NULL;
456 #endif
457
458 to = NULL;
459
460 if ((error = getsock(p->p_fd, s, &fp)) != 0)
461 return (error);
462 auio.uio_iov = mp->msg_iov;
463 auio.uio_iovcnt = mp->msg_iovlen;
464 auio.uio_segflg = UIO_USERSPACE;
465 auio.uio_rw = UIO_WRITE;
466 auio.uio_procp = p;
467 auio.uio_offset = 0;
468 auio.uio_resid = 0;
469 iov = mp->msg_iov;
470 for (i = 0; i < mp->msg_iovlen; i++, iov++) {
471
472 if (iov->iov_len > SSIZE_MAX ||
473 (auio.uio_resid += iov->iov_len) > SSIZE_MAX) {
474 error = EINVAL;
475 goto bad;
476 }
477 }
478 if (mp->msg_name) {
479 error = sockargs(&to, mp->msg_name, mp->msg_namelen,
480 MT_SONAME);
481 if (error)
482 goto bad;
483 }
484 if (mp->msg_control) {
485 if (mp->msg_controllen < CMSG_ALIGN(sizeof(struct cmsghdr))
486 #ifdef COMPAT_OLDSOCK
487 && mp->msg_flags != MSG_COMPAT
488 #endif
489 ) {
490 error = EINVAL;
491 goto bad;
492 }
493 error = sockargs(&control, mp->msg_control,
494 mp->msg_controllen, MT_CONTROL);
495 if (error)
496 goto bad;
497 #ifdef COMPAT_OLDSOCK
498 if (mp->msg_flags == MSG_COMPAT) {
499 struct cmsghdr *cm;
500
501 M_PREPEND(control, sizeof(*cm), M_WAIT);
502 cm = mtod(control, struct cmsghdr *);
503 cm->cmsg_len = control->m_len;
504 cm->cmsg_level = SOL_SOCKET;
505 cm->cmsg_type = SCM_RIGHTS;
506 }
507 #endif
508 } else
509 control = 0;
510 #ifdef KTRACE
511 if (KTRPOINT(p, KTR_GENIO)) {
512 int iovlen = auio.uio_iovcnt * sizeof (struct iovec);
513
514 ktriov = malloc(iovlen, M_TEMP, M_WAITOK);
515 bcopy(auio.uio_iov, ktriov, iovlen);
516 }
517 #endif
518 len = auio.uio_resid;
519 error = sosend(fp->f_data, to, &auio, NULL, control, flags);
520 if (error) {
521 if (auio.uio_resid != len && (error == ERESTART ||
522 error == EINTR || error == EWOULDBLOCK))
523 error = 0;
524 if (error == EPIPE)
525 psignal(p, SIGPIPE);
526 }
527 if (error == 0) {
528 *retsize = len - auio.uio_resid;
529 fp->f_wxfer++;
530 fp->f_wbytes += *retsize;
531 }
532 #ifdef KTRACE
533 if (ktriov != NULL) {
534 if (error == 0)
535 ktrgenio(p, s, UIO_WRITE, ktriov, *retsize, error);
536 free(ktriov, M_TEMP);
537 }
538 #endif
539 bad:
540 FRELE(fp);
541 if (to)
542 m_freem(to);
543 return (error);
544 }
545
546 int
547 sys_recvfrom(struct proc *p, void *v, register_t *retval)
548 {
549 struct sys_recvfrom_args
550
551
552
553
554
555
556 *uap = v;
557 struct msghdr msg;
558 struct iovec aiov;
559 int error;
560
561 if (SCARG(uap, fromlenaddr)) {
562 error = copyin(SCARG(uap, fromlenaddr),
563 &msg.msg_namelen, sizeof (msg.msg_namelen));
564 if (error)
565 return (error);
566 } else
567 msg.msg_namelen = 0;
568 msg.msg_name = (caddr_t)SCARG(uap, from);
569 msg.msg_iov = &aiov;
570 msg.msg_iovlen = 1;
571 aiov.iov_base = SCARG(uap, buf);
572 aiov.iov_len = SCARG(uap, len);
573 msg.msg_control = 0;
574 msg.msg_flags = SCARG(uap, flags);
575 return (recvit(p, SCARG(uap, s), &msg,
576 (caddr_t)SCARG(uap, fromlenaddr), retval));
577 }
578
579 int
580 sys_recvmsg(struct proc *p, void *v, register_t *retval)
581 {
582 struct sys_recvmsg_args
583
584
585
586 *uap = v;
587 struct msghdr msg;
588 struct iovec aiov[UIO_SMALLIOV], *uiov, *iov;
589 int error;
590
591 error = copyin(SCARG(uap, msg), &msg, sizeof (msg));
592 if (error)
593 return (error);
594 if (msg.msg_iovlen > IOV_MAX)
595 return (EMSGSIZE);
596 if (msg.msg_iovlen > UIO_SMALLIOV)
597 iov = malloc(sizeof(struct iovec) * msg.msg_iovlen,
598 M_IOV, M_WAITOK);
599 else
600 iov = aiov;
601 #ifdef COMPAT_OLDSOCK
602 msg.msg_flags = SCARG(uap, flags) &~ MSG_COMPAT;
603 #else
604 msg.msg_flags = SCARG(uap, flags);
605 #endif
606 if (msg.msg_iovlen > 0) {
607 error = copyin(msg.msg_iov, iov,
608 (unsigned)(msg.msg_iovlen * sizeof (struct iovec)));
609 if (error)
610 goto done;
611 }
612 uiov = msg.msg_iov;
613 msg.msg_iov = iov;
614 if ((error = recvit(p, SCARG(uap, s), &msg, NULL, retval)) == 0) {
615 msg.msg_iov = uiov;
616 error = copyout(&msg, SCARG(uap, msg), sizeof(msg));
617 }
618 done:
619 if (iov != aiov)
620 free(iov, M_IOV);
621 return (error);
622 }
623
624 int
625 recvit(struct proc *p, int s, struct msghdr *mp, caddr_t namelenp,
626 register_t *retsize)
627 {
628 struct file *fp;
629 struct uio auio;
630 struct iovec *iov;
631 int i;
632 size_t len;
633 int error;
634 struct mbuf *from = NULL, *control = NULL;
635 #ifdef KTRACE
636 struct iovec *ktriov = NULL;
637 #endif
638
639 if ((error = getsock(p->p_fd, s, &fp)) != 0)
640 return (error);
641 auio.uio_iov = mp->msg_iov;
642 auio.uio_iovcnt = mp->msg_iovlen;
643 auio.uio_segflg = UIO_USERSPACE;
644 auio.uio_rw = UIO_READ;
645 auio.uio_procp = p;
646 auio.uio_offset = 0;
647 auio.uio_resid = 0;
648 iov = mp->msg_iov;
649 for (i = 0; i < mp->msg_iovlen; i++, iov++) {
650
651 if (iov->iov_len > SSIZE_MAX ||
652 (auio.uio_resid += iov->iov_len) > SSIZE_MAX) {
653 error = EINVAL;
654 goto out;
655 }
656 }
657 #ifdef KTRACE
658 if (KTRPOINT(p, KTR_GENIO)) {
659 int iovlen = auio.uio_iovcnt * sizeof (struct iovec);
660
661 ktriov = malloc(iovlen, M_TEMP, M_WAITOK);
662 bcopy(auio.uio_iov, ktriov, iovlen);
663 }
664 #endif
665 len = auio.uio_resid;
666 error = soreceive(fp->f_data, &from, &auio, NULL,
667 mp->msg_control ? &control : NULL,
668 &mp->msg_flags);
669 if (error) {
670 if (auio.uio_resid != len && (error == ERESTART ||
671 error == EINTR || error == EWOULDBLOCK))
672 error = 0;
673 }
674 #ifdef KTRACE
675 if (ktriov != NULL) {
676 if (error == 0)
677 ktrgenio(p, s, UIO_READ,
678 ktriov, len - auio.uio_resid, error);
679 free(ktriov, M_TEMP);
680 }
681 #endif
682 if (error)
683 goto out;
684 *retsize = len - auio.uio_resid;
685 if (mp->msg_name) {
686 socklen_t alen;
687
688 if (from == NULL)
689 alen = 0;
690 else {
691
692 alen = mp->msg_namelen;
693 if (alen > from->m_len)
694 alen = from->m_len;
695
696 #ifdef COMPAT_OLDSOCK
697 if (mp->msg_flags & MSG_COMPAT)
698 mtod(from, struct osockaddr *)->sa_family =
699 mtod(from, struct sockaddr *)->sa_family;
700 #endif
701 error = copyout(mtod(from, caddr_t), mp->msg_name, alen);
702 if (error)
703 goto out;
704 }
705 mp->msg_namelen = alen;
706 if (namelenp &&
707 (error = copyout(&alen, namelenp, sizeof(alen)))) {
708 #ifdef COMPAT_OLDSOCK
709 if (mp->msg_flags & MSG_COMPAT)
710 error = 0;
711 else
712 #endif
713 goto out;
714 }
715 }
716 if (mp->msg_control) {
717 #ifdef COMPAT_OLDSOCK
718
719
720
721
722
723
724
725 if (control && mp->msg_flags & MSG_COMPAT) {
726 if (mtod(control, struct cmsghdr *)->cmsg_level !=
727 SOL_SOCKET ||
728 mtod(control, struct cmsghdr *)->cmsg_type !=
729 SCM_RIGHTS) {
730 mp->msg_controllen = 0;
731 goto out;
732 }
733 control->m_len -= sizeof (struct cmsghdr);
734 control->m_data += sizeof (struct cmsghdr);
735 }
736 #endif
737 len = mp->msg_controllen;
738 if (len <= 0 || control == NULL)
739 len = 0;
740 else {
741 struct mbuf *m = control;
742 caddr_t p = mp->msg_control;
743
744 do {
745 i = m->m_len;
746 if (len < i) {
747 mp->msg_flags |= MSG_CTRUNC;
748 i = len;
749 }
750 error = copyout(mtod(m, caddr_t), p,
751 (unsigned)i);
752 if (m->m_next)
753 i = ALIGN(i);
754 p += i;
755 len -= i;
756 if (error != 0 || len <= 0)
757 break;
758 } while ((m = m->m_next) != NULL);
759 len = p - (caddr_t)mp->msg_control;
760 }
761 mp->msg_controllen = len;
762 }
763 if (!error) {
764 fp->f_rxfer++;
765 fp->f_rbytes += *retsize;
766 }
767 out:
768 FRELE(fp);
769 if (from)
770 m_freem(from);
771 if (control)
772 m_freem(control);
773 return (error);
774 }
775
776
777 int
778 sys_shutdown(struct proc *p, void *v, register_t *retval)
779 {
780 struct sys_shutdown_args
781
782
783 *uap = v;
784 struct file *fp;
785 int error;
786
787 if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0)
788 return (error);
789 error = soshutdown(fp->f_data, SCARG(uap, how));
790 FRELE(fp);
791 return (error);
792 }
793
794
795 int
796 sys_setsockopt(struct proc *p, void *v, register_t *retval)
797 {
798 struct sys_setsockopt_args
799
800
801
802
803
804 *uap = v;
805 struct file *fp;
806 struct mbuf *m = NULL;
807 int error;
808
809 if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0)
810 return (error);
811 if (SCARG(uap, valsize) > MCLBYTES) {
812 error = EINVAL;
813 goto bad;
814 }
815 if (SCARG(uap, val)) {
816 m = m_get(M_WAIT, MT_SOOPTS);
817 if (SCARG(uap, valsize) > MLEN) {
818 MCLGET(m, M_DONTWAIT);
819 if ((m->m_flags & M_EXT) == 0) {
820 error = ENOBUFS;
821 goto bad;
822 }
823 }
824 if (m == NULL) {
825 error = ENOBUFS;
826 goto bad;
827 }
828 error = copyin(SCARG(uap, val), mtod(m, caddr_t),
829 SCARG(uap, valsize));
830 if (error) {
831 goto bad;
832 }
833 m->m_len = SCARG(uap, valsize);
834 }
835 error = sosetopt(fp->f_data, SCARG(uap, level),
836 SCARG(uap, name), m);
837 m = NULL;
838 bad:
839 if (m)
840 m_freem(m);
841 FRELE(fp);
842 return (error);
843 }
844
845
846 int
847 sys_getsockopt(struct proc *p, void *v, register_t *retval)
848 {
849 struct sys_getsockopt_args
850
851
852
853
854
855 *uap = v;
856 struct file *fp;
857 struct mbuf *m = NULL;
858 socklen_t valsize;
859 int error;
860
861 if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0)
862 return (error);
863 if (SCARG(uap, val)) {
864 error = copyin(SCARG(uap, avalsize),
865 &valsize, sizeof (valsize));
866 if (error)
867 goto out;
868 } else
869 valsize = 0;
870 if ((error = sogetopt(fp->f_data, SCARG(uap, level),
871 SCARG(uap, name), &m)) == 0 && SCARG(uap, val) && valsize &&
872 m != NULL) {
873 if (valsize > m->m_len)
874 valsize = m->m_len;
875 error = copyout(mtod(m, caddr_t), SCARG(uap, val), valsize);
876 if (error == 0)
877 error = copyout(&valsize,
878 SCARG(uap, avalsize), sizeof (valsize));
879 }
880 out:
881 FRELE(fp);
882 if (m != NULL)
883 (void)m_free(m);
884 return (error);
885 }
886
887 int
888 sys_pipe(struct proc *p, void *v, register_t *retval)
889 {
890 struct sys_pipe_args
891
892 *uap = v;
893 int error, fds[2];
894 register_t rval[2];
895
896 if ((error = sys_opipe(p, v, rval)) != 0)
897 return (error);
898
899 fds[0] = rval[0];
900 fds[1] = rval[1];
901 error = copyout(fds, SCARG(uap, fdp), 2 * sizeof (int));
902 if (error) {
903 fdplock(p->p_fd);
904 fdrelease(p, fds[0]);
905 fdrelease(p, fds[1]);
906 fdpunlock(p->p_fd);
907 }
908 return (error);
909 }
910
911
912
913
914
915 int
916 sys_getsockname(struct proc *p, void *v, register_t *retval)
917 {
918 struct sys_getsockname_args
919
920
921
922 *uap = v;
923 struct file *fp;
924 struct socket *so;
925 struct mbuf *m = NULL;
926 socklen_t len;
927 int error;
928
929 if ((error = getsock(p->p_fd, SCARG(uap, fdes), &fp)) != 0)
930 return (error);
931 error = copyin(SCARG(uap, alen), &len, sizeof (len));
932 if (error)
933 goto bad;
934 so = fp->f_data;
935 m = m_getclr(M_WAIT, MT_SONAME);
936 error = (*so->so_proto->pr_usrreq)(so, PRU_SOCKADDR, 0, m, 0);
937 if (error)
938 goto bad;
939 if (len > m->m_len)
940 len = m->m_len;
941 error = copyout(mtod(m, caddr_t), SCARG(uap, asa), len);
942 if (error == 0)
943 error = copyout(&len, SCARG(uap, alen), sizeof (len));
944 bad:
945 FRELE(fp);
946 if (m)
947 m_freem(m);
948 return (error);
949 }
950
951
952
953
954
955 int
956 sys_getpeername(struct proc *p, void *v, register_t *retval)
957 {
958 struct sys_getpeername_args
959
960
961
962 *uap = v;
963 struct file *fp;
964 struct socket *so;
965 struct mbuf *m = NULL;
966 socklen_t len;
967 int error;
968
969 if ((error = getsock(p->p_fd, SCARG(uap, fdes), &fp)) != 0)
970 return (error);
971 so = fp->f_data;
972 if ((so->so_state & (SS_ISCONNECTED|SS_ISCONFIRMING)) == 0) {
973 FRELE(fp);
974 return (ENOTCONN);
975 }
976 error = copyin(SCARG(uap, alen), &len, sizeof (len));
977 if (error)
978 goto bad;
979 m = m_getclr(M_WAIT, MT_SONAME);
980 error = (*so->so_proto->pr_usrreq)(so, PRU_PEERADDR, 0, m, 0);
981 if (error)
982 goto bad;
983 if (len > m->m_len)
984 len = m->m_len;
985 error = copyout(mtod(m, caddr_t), SCARG(uap, asa), len);
986 if (error == 0)
987 error = copyout(&len, SCARG(uap, alen), sizeof (len));
988 bad:
989 FRELE(fp);
990 m_freem(m);
991 return (error);
992 }
993
994
995
996
997
998 int
999 sys_getpeereid(struct proc *p, void *v, register_t *retval)
1000 {
1001 struct sys_getpeereid_args
1002
1003
1004
1005 *uap = v;
1006 struct file *fp;
1007 struct socket *so;
1008 struct mbuf *m = NULL;
1009 struct unpcbid *id;
1010 int error;
1011
1012 if ((error = getsock(p->p_fd, SCARG(uap, fdes), &fp)) != 0)
1013 return (error);
1014 so = fp->f_data;
1015 if (so->so_proto != pffindtype(AF_LOCAL, SOCK_STREAM)) {
1016 FRELE(fp);
1017 return (EOPNOTSUPP);
1018 }
1019 m = m_getclr(M_WAIT, MT_SONAME);
1020 if (m == NULL) {
1021 error = ENOBUFS;
1022 goto bad;
1023 }
1024 error = (*so->so_proto->pr_usrreq)(so, PRU_PEEREID, 0, m, 0);
1025 if (!error && m->m_len != sizeof(struct unpcbid))
1026 error = EOPNOTSUPP;
1027 if (error)
1028 goto bad;
1029 id = mtod(m, struct unpcbid *);
1030 error = copyout(&(id->unp_euid), SCARG(uap, euid), sizeof(uid_t));
1031 if (error == 0)
1032 error = copyout(&(id->unp_egid), SCARG(uap, egid), sizeof(gid_t));
1033 bad:
1034 FRELE(fp);
1035 m_freem(m);
1036 return (error);
1037 }
1038
1039 int
1040 sockargs(struct mbuf **mp, const void *buf, size_t buflen, int type)
1041 {
1042 struct sockaddr *sa;
1043 struct mbuf *m;
1044 int error;
1045
1046
1047
1048
1049
1050
1051 if (buflen > (type == MT_SONAME ? UCHAR_MAX : MCLBYTES))
1052 return (EINVAL);
1053
1054
1055 m = m_get(M_WAIT, type);
1056 if ((u_int)buflen > MLEN) {
1057 MCLGET(m, M_WAITOK);
1058 if ((m->m_flags & M_EXT) == 0) {
1059 m_free(m);
1060 return ENOBUFS;
1061 }
1062 }
1063 m->m_len = buflen;
1064 error = copyin(buf, mtod(m, caddr_t), buflen);
1065 if (error) {
1066 (void) m_free(m);
1067 return (error);
1068 }
1069 *mp = m;
1070 if (type == MT_SONAME) {
1071 sa = mtod(m, struct sockaddr *);
1072 #if defined(COMPAT_OLDSOCK) && BYTE_ORDER != BIG_ENDIAN
1073 if (sa->sa_family == 0 && sa->sa_len < AF_MAX)
1074 sa->sa_family = sa->sa_len;
1075 #endif
1076 sa->sa_len = buflen;
1077 }
1078 return (0);
1079 }
1080
1081 int
1082 getsock(struct filedesc *fdp, int fdes, struct file **fpp)
1083 {
1084 struct file *fp;
1085
1086 if ((fp = fd_getfile(fdp, fdes)) == NULL)
1087 return (EBADF);
1088 if (fp->f_type != DTYPE_SOCKET)
1089 return (ENOTSOCK);
1090 *fpp = fp;
1091 FREF(fp);
1092
1093 return (0);
1094 }