66#include <sys/capsicum.h>
67#include <sys/domain.h>
68#include <sys/eventhandler.h>
71#include <sys/filedesc.h>
72#include <sys/kernel.h>
74#include <sys/malloc.h>
80#include <sys/protosw.h>
82#include <sys/resourcevar.h>
83#include <sys/rwlock.h>
84#include <sys/socket.h>
85#include <sys/socketvar.h>
86#include <sys/signalvar.h>
89#include <sys/sysctl.h>
91#include <sys/taskqueue.h>
102#include <security/mac/mac_framework.h>
126static int unp_defers_count;
128static const struct sockaddr sun_noname = {
sizeof(sun_noname), AF_LOCAL };
164static SYSCTL_NODE(_net, PF_LOCAL, local, CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
167 CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
170 CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
173 CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
189 "File descriptors in flight.");
191 &unp_defers_count, 0,
192 "File descriptors deferred to taskqueue for close.");
254#define UNP_LINK_LOCK_INIT() rw_init(&unp_link_rwlock, \
257#define UNP_LINK_LOCK_ASSERT() rw_assert(&unp_link_rwlock, \
259#define UNP_LINK_UNLOCK_ASSERT() rw_assert(&unp_link_rwlock, \
262#define UNP_LINK_RLOCK() rw_rlock(&unp_link_rwlock)
263#define UNP_LINK_RUNLOCK() rw_runlock(&unp_link_rwlock)
264#define UNP_LINK_WLOCK() rw_wlock(&unp_link_rwlock)
265#define UNP_LINK_WUNLOCK() rw_wunlock(&unp_link_rwlock)
266#define UNP_LINK_WLOCK_ASSERT() rw_assert(&unp_link_rwlock, \
268#define UNP_LINK_WOWNED() rw_wowned(&unp_link_rwlock)
270#define UNP_DEFERRED_LOCK_INIT() mtx_init(&unp_defers_lock, \
271 "unp_defer", NULL, MTX_DEF)
272#define UNP_DEFERRED_LOCK() mtx_lock(&unp_defers_lock)
273#define UNP_DEFERRED_UNLOCK() mtx_unlock(&unp_defers_lock)
275#define UNP_REF_LIST_LOCK() UNP_DEFERRED_LOCK();
276#define UNP_REF_LIST_UNLOCK() UNP_DEFERRED_UNLOCK();
278#define UNP_PCB_LOCK_INIT(unp) mtx_init(&(unp)->unp_mtx, \
281#define UNP_PCB_LOCK_DESTROY(unp) mtx_destroy(&(unp)->unp_mtx)
282#define UNP_PCB_LOCKPTR(unp) (&(unp)->unp_mtx)
283#define UNP_PCB_LOCK(unp) mtx_lock(&(unp)->unp_mtx)
284#define UNP_PCB_TRYLOCK(unp) mtx_trylock(&(unp)->unp_mtx)
285#define UNP_PCB_UNLOCK(unp) mtx_unlock(&(unp)->unp_mtx)
286#define UNP_PCB_OWNED(unp) mtx_owned(&(unp)->unp_mtx)
287#define UNP_PCB_LOCK_ASSERT(unp) mtx_assert(&(unp)->unp_mtx, MA_OWNED)
288#define UNP_PCB_UNLOCK_ASSERT(unp) mtx_assert(&(unp)->unp_mtx, MA_NOTOWNED)
292static int unp_connect(
struct socket *,
struct sockaddr *,
294static int unp_connectat(
int,
struct socket *,
struct sockaddr *,
296static int unp_connect2(
struct socket *so,
struct socket *so2,
int);
301static void unp_drop(
struct unpcb *);
302static void unp_gc(__unused
void *,
int);
303static void unp_scan(
struct mbuf *,
void (*)(
struct filedescent **,
int));
310static struct mbuf *
unp_addsockcred(
struct thread *,
struct mbuf *,
int);
318 old = refcount_acquire(&unp->unp_refcount);
319 KASSERT(old > 0, (
"%s: unpcb %p has no references", __func__, unp));
322static __result_use_check
bool
329 if ((ret = refcount_release(&unp->unp_refcount))) {
342 ret = refcount_release(&unp->unp_refcount);
343 KASSERT(!ret, (
"%s: unpcb %p has no references", __func__, unp));
354 }
else if ((uintptr_t)unp2 > (uintptr_t)unp) {
383 unp2 = unp->unp_conn;
386 if (__predict_false(unp == unp2))
393 if ((uintptr_t)unp2 > (uintptr_t)unp) {
403 KASSERT(unp->unp_conn == unp2 || unp->unp_conn == NULL,
404 (
"%s: socket %p was reconnected", __func__, unp));
405 if (--unp->unp_pairbusy == 0 && (unp->unp_flags & UNP_WAITING) != 0) {
406 unp->unp_flags &= ~UNP_WAITING;
413 if (unp->unp_conn == NULL) {
428 .pr_type = SOCK_STREAM,
430 .pr_flags = PR_CONNREQUIRED|PR_WANTRCVD|PR_RIGHTS|
436 .pr_type = SOCK_DGRAM,
438 .pr_flags = PR_ATOMIC|PR_ADDR|PR_RIGHTS|PR_CAPATTACH,
443 .pr_type = SOCK_SEQPACKET,
451 .pr_flags = PR_ADDR|PR_ATOMIC|PR_CONNREQUIRED|
452 PR_WANTRCVD|PR_RIGHTS|PR_CAPATTACH,
459 .dom_family = AF_LOCAL,
471 struct unpcb *unp, *unp2;
474 KASSERT(unp != NULL, (
"uipc_abort: unp == NULL"));
478 unp2 = unp->unp_conn;
490 struct unpcb *unp, *unp2;
491 const struct sockaddr *sa;
498 KASSERT(unp != NULL, (
"uipc_accept: unp == NULL"));
500 *nam =
malloc(
sizeof(
struct sockaddr_un), M_SONAME, M_WAITOK);
503 if (unp2 != NULL && unp2->unp_addr != NULL)
504 sa = (
struct sockaddr *)unp2->unp_addr;
507 bcopy(sa, *nam, sa->sa_len);
518 u_long sendspace, recvspace;
523 KASSERT(so->so_pcb == NULL, (
"uipc_attach: so_pcb != NULL"));
524 if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
525 switch (so->so_type) {
542 panic(
"uipc_attach");
544 error =
soreserve(so, sendspace, recvspace);
548 unp = uma_zalloc(
unp_zone, M_NOWAIT | M_ZERO);
551 LIST_INIT(&unp->unp_refs);
553 unp->unp_socket = so;
555 refcount_init(&unp->unp_refcount, 1);
563 switch (so->so_type) {
565 LIST_INSERT_HEAD(&
unp_shead, unp, unp_link);
569 LIST_INSERT_HEAD(&
unp_dhead, unp, unp_link);
577 panic(
"uipc_attach");
587uipc_bindat(
int fd,
struct socket *so,
struct sockaddr *nam,
struct thread *td)
589 struct sockaddr_un *soun = (
struct sockaddr_un *)nam;
599 if (nam->sa_family != AF_UNIX)
600 return (EAFNOSUPPORT);
603 KASSERT(unp != NULL, (
"uipc_bind: unp == NULL"));
605 if (soun->sun_len >
sizeof(
struct sockaddr_un))
607 namelen = soun->sun_len - offsetof(
struct sockaddr_un, sun_path);
621 if (unp->unp_vnode != NULL) {
625 if (unp->unp_flags & UNP_BINDING) {
629 unp->unp_flags |= UNP_BINDING;
632 buf =
malloc(namelen + 1, M_TEMP, M_WAITOK);
633 bcopy(soun->sun_path,
buf, namelen);
637 NDINIT_ATRIGHTS(&nd, CREATE, NOFOLLOW | LOCKPARENT | SAVENAME | NOCACHE,
638 UIO_SYSSPACE,
buf,
fd, cap_rights_init_one(&rights, CAP_BINDAT));
644 if (vp != NULL ||
vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
645 NDFREE(&nd, NDF_ONLY_PNBUF);
661 vattr.va_type = VSOCK;
662 vattr.va_mode = (ACCESSPERMS & ~td->td_proc->p_pd->pd_cmask);
664 error = mac_vnode_check_create(td->td_ucred, nd.ni_dvp, &nd.ni_cnd,
668 error = VOP_CREATE(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
669 NDFREE(&nd, NDF_ONLY_PNBUF);
671 VOP_VPUT_PAIR(nd.ni_dvp, NULL,
true);
673 if (error == ERELOOKUP)
678 ASSERT_VOP_ELOCKED(vp,
"uipc_bind");
682 VOP_UNP_BIND(vp, unp);
684 unp->unp_addr = soun;
685 unp->unp_flags &= ~UNP_BINDING;
688 VOP_VPUT_PAIR(nd.ni_dvp, &vp,
true);
695 unp->unp_flags &= ~UNP_BINDING;
702uipc_bind(
struct socket *so,
struct sockaddr *nam,
struct thread *td)
709uipc_connect(
struct socket *so,
struct sockaddr *nam,
struct thread *td)
713 KASSERT(td == curthread, (
"uipc_connect: td != curthread"));
724 KASSERT(td == curthread, (
"uipc_connectat: td != curthread"));
732 struct unpcb *unp, *unp2;
733 struct vnode *vp = NULL;
737 KASSERT(unp != NULL, (
"uipc_close: unp == NULL"));
740 if ((vp = unp->unp_vnode) != NULL) {
745 if (vp && unp->unp_vnode == NULL) {
751 unp->unp_vnode = NULL;
766 struct unpcb *unp, *unp2;
770 KASSERT(unp != NULL, (
"uipc_connect2: unp == NULL"));
772 KASSERT(unp2 != NULL, (
"uipc_connect2: unp2 == NULL"));
782 struct unpcb *unp, *unp2;
785 int local_unp_rights;
788 KASSERT(unp != NULL, (
"uipc_detach: unp == NULL"));
794 if (!SOLISTENING(so)) {
806 LIST_REMOVE(unp, unp_link);
807 if (unp->unp_gcflag & UNPGC_DEAD)
808 LIST_REMOVE(unp, unp_dead);
815 if ((vp = unp->unp_vnode) != NULL) {
820 if (unp->unp_vnode != vp && unp->unp_vnode != NULL) {
826 if ((vp = unp->unp_vnode) != NULL) {
828 unp->unp_vnode = NULL;
836 while (!LIST_EMPTY(&unp->unp_refs)) {
837 struct unpcb *ref = LIST_FIRST(&unp->unp_refs);
851 unp->unp_socket->so_pcb = NULL;
852 unp->unp_socket = NULL;
853 free(unp->unp_addr, M_SONAME);
854 unp->unp_addr = NULL;
861 if (local_unp_rights)
868 struct unpcb *unp, *unp2;
871 KASSERT(unp != NULL, (
"uipc_disconnect: unp == NULL"));
887 if (so->so_type != SOCK_STREAM && so->so_type != SOCK_SEQPACKET)
896 if (unp->unp_conn != NULL || (unp->unp_flags & UNP_CONNECTING) != 0)
898 else if (unp->unp_vnode == NULL)
899 error = EDESTADDRREQ;
908 cru2xt(td, &unp->unp_peercred);
919 struct unpcb *unp, *unp2;
920 const struct sockaddr *sa;
923 KASSERT(unp != NULL, (
"uipc_peeraddr: unp == NULL"));
925 *nam =
malloc(
sizeof(
struct sockaddr_un), M_SONAME, M_WAITOK);
932 unp2 = unp->unp_conn;
935 if (unp2->unp_addr != NULL)
936 sa = (
struct sockaddr *) unp2->unp_addr;
939 bcopy(sa, *nam, sa->sa_len);
943 bcopy(sa, *nam, sa->sa_len);
952 struct unpcb *unp, *unp2;
957 KASSERT(unp != NULL, (
"%s: unp == NULL", __func__));
958 KASSERT(so->so_type == SOCK_STREAM || so->so_type == SOCK_SEQPACKET,
959 (
"%s: socktype %d", __func__, so->so_type));
971 SOCKBUF_LOCK(&so->so_rcv);
972 mbcnt = so->so_rcv.sb_mbcnt;
973 sbcc = sbavail(&so->so_rcv);
974 SOCKBUF_UNLOCK(&so->so_rcv);
985 unp2 = unp->unp_conn;
990 so2 = unp2->unp_socket;
991 SOCKBUF_LOCK(&so2->so_snd);
992 if (sbcc < so2->so_snd.sb_hiwat && mbcnt < so2->so_snd.sb_mbmax)
993 so2->so_snd.sb_flags &= ~SB_STOP;
994 sowwakeup_locked(so2);
1001 struct mbuf *control,
struct thread *td)
1003 struct unpcb *unp, *unp2;
1008 unp = sotounpcb(so);
1009 KASSERT(unp != NULL, (
"%s: unp == NULL", __func__));
1010 KASSERT(so->so_type == SOCK_STREAM || so->so_type == SOCK_DGRAM ||
1011 so->so_type == SOCK_SEQPACKET,
1012 (
"%s: socktype %d", __func__, so->so_type));
1015 if (
flags & PRUS_OOB) {
1023 switch (so->so_type) {
1026 const struct sockaddr *from;
1049 if (unp2->unp_flags & UNP_WANTCRED_MASK)
1052 if (unp->unp_addr != NULL)
1053 from = (
struct sockaddr *)unp->unp_addr;
1056 so2 = unp2->unp_socket;
1057 SOCKBUF_LOCK(&so2->so_rcv);
1060 sorwakeup_locked(so2);
1065 error = (so->so_state & SS_NBIO) ? EAGAIN : ENOBUFS;
1074 case SOCK_SEQPACKET:
1076 if ((so->so_state & SS_ISCONNECTED) == 0) {
1092 }
else if (so->so_snd.sb_state & SBS_CANTSENDMORE) {
1098 if ((so2 = unp2->unp_socket) == NULL) {
1103 SOCKBUF_LOCK(&so2->so_rcv);
1104 if (unp2->unp_flags & UNP_WANTCRED_MASK) {
1111 unp2->unp_flags &= ~UNP_WANTCRED_ONESHOT;
1123 switch (so->so_type) {
1125 if (control != NULL) {
1133 case SOCK_SEQPACKET:
1135 &sun_noname, m, control))
1140 mbcnt = so2->so_rcv.sb_mbcnt;
1141 sbcc = sbavail(&so2->so_rcv);
1143 sorwakeup_locked(so2);
1145 SOCKBUF_UNLOCK(&so2->so_rcv);
1154 SOCKBUF_LOCK(&so->so_snd);
1155 if (sbcc >= so->so_snd.sb_hiwat || mbcnt >= so->so_snd.sb_mbmax)
1156 so->so_snd.sb_flags |= SB_STOP;
1157 SOCKBUF_UNLOCK(&so->so_snd);
1166 if (
flags & PRUS_EOF) {
1172 if (control != NULL && error != 0)
1176 if (control != NULL)
1182 if (m != NULL && (
flags & PRUS_NOTREADY) == 0)
1190 struct mbuf *mb, *n;
1194 if (SOLISTENING(so)) {
1201 if (sb->sb_fnrdy != NULL) {
1202 for (mb = sb->sb_mb, n = mb->m_nextpkt; mb != NULL;) {
1217 return (mb != NULL);
1223 struct unpcb *unp, *unp2;
1227 unp = sotounpcb(so);
1229 KASSERT(so->so_type == SOCK_STREAM,
1230 (
"%s: unexpected socket type for %p", __func__, so));
1235 so2 = unp2->unp_socket;
1236 SOCKBUF_LOCK(&so2->so_rcv);
1238 sorwakeup_locked(so2);
1240 SOCKBUF_UNLOCK(&so2->so_rcv);
1253 LIST_FOREACH(unp, &
unp_shead, unp_link) {
1260 for (i = 0; i <
count; i++)
1272 unp = sotounpcb(so);
1273 KASSERT(unp != NULL, (
"uipc_sense: unp == NULL"));
1275 sb->st_blksize = so->so_snd.sb_hiwat;
1277 sb->st_ino = unp->unp_ino;
1286 unp = sotounpcb(so);
1287 KASSERT(unp != NULL, (
"uipc_shutdown: unp == NULL"));
1300 const struct sockaddr *sa;
1302 unp = sotounpcb(so);
1303 KASSERT(unp != NULL, (
"uipc_sockaddr: unp == NULL"));
1305 *nam =
malloc(
sizeof(
struct sockaddr_un), M_SONAME, M_WAITOK);
1307 if (unp->unp_addr != NULL)
1308 sa = (
struct sockaddr *) unp->unp_addr;
1311 bcopy(sa, *nam, sa->sa_len);
1390 if (sopt->sopt_level != SOL_LOCAL)
1393 unp = sotounpcb(so);
1394 KASSERT(unp != NULL, (
"uipc_ctloutput: unp == NULL"));
1396 switch (sopt->sopt_dir) {
1398 switch (sopt->sopt_name) {
1399 case LOCAL_PEERCRED:
1401 if (unp->unp_flags & UNP_HAVEPC)
1402 xu = unp->unp_peercred;
1404 if (so->so_type == SOCK_STREAM)
1416 optval = unp->unp_flags & UNP_WANTCRED_ONESHOT ? 1 : 0;
1420 case LOCAL_CREDS_PERSISTENT:
1422 optval = unp->unp_flags & UNP_WANTCRED_ALWAYS ? 1 : 0;
1426 case LOCAL_CONNWAIT:
1428 optval = unp->unp_flags & UNP_CONNWAIT ? 1 : 0;
1439 switch (sopt->sopt_name) {
1441 case LOCAL_CREDS_PERSISTENT:
1442 case LOCAL_CONNWAIT:
1443 error =
sooptcopyin(sopt, &optval,
sizeof(optval),
1448#define OPTSET(bit, exclusive) do { \
1449 UNP_PCB_LOCK(unp); \
1451 if ((unp->unp_flags & (exclusive)) != 0) { \
1452 UNP_PCB_UNLOCK(unp); \
1456 unp->unp_flags |= (bit); \
1458 unp->unp_flags &= ~(bit); \
1459 UNP_PCB_UNLOCK(unp); \
1462 switch (sopt->sopt_name) {
1464 OPTSET(UNP_WANTCRED_ONESHOT, UNP_WANTCRED_ALWAYS);
1467 case LOCAL_CREDS_PERSISTENT:
1468 OPTSET(UNP_WANTCRED_ALWAYS, UNP_WANTCRED_ONESHOT);
1471 case LOCAL_CONNWAIT:
1481 error = ENOPROTOOPT;
1494unp_connect(
struct socket *so,
struct sockaddr *nam,
struct thread *td)
1505 struct sockaddr_un *soun;
1508 struct unpcb *unp, *unp2, *unp3;
1509 struct nameidata nd;
1510 char buf[SOCK_MAXADDRLEN];
1511 struct sockaddr *sa;
1512 cap_rights_t rights;
1516 if (nam->sa_family != AF_UNIX)
1517 return (EAFNOSUPPORT);
1518 if (nam->sa_len >
sizeof(
struct sockaddr_un))
1520 len = nam->sa_len - offsetof(
struct sockaddr_un, sun_path);
1523 soun = (
struct sockaddr_un *)nam;
1524 bcopy(soun->sun_path,
buf, len);
1528 unp = sotounpcb(so);
1543 if (SOLISTENING(so))
1545 else if (unp->unp_conn != NULL)
1547 else if ((unp->unp_flags & UNP_CONNECTING) != 0) {
1554 if (unp->unp_pairbusy > 0) {
1555 unp->unp_flags |= UNP_WAITING;
1561 unp->unp_flags |= UNP_CONNECTING;
1564 connreq = (so->so_proto->pr_flags & PR_CONNREQUIRED) != 0;
1566 sa =
malloc(
sizeof(
struct sockaddr_un), M_SONAME, M_WAITOK);
1569 NDINIT_ATRIGHTS(&nd, LOOKUP, FOLLOW | LOCKSHARED | LOCKLEAF,
1570 UIO_SYSSPACE,
buf,
fd, cap_rights_init_one(&rights, CAP_CONNECTAT));
1576 ASSERT_VOP_LOCKED(vp,
"unp_connect");
1577 NDFREE_NOTHING(&nd);
1581 if (vp->v_type != VSOCK) {
1586 error = mac_vnode_check_open(td->td_ucred, vp, VWRITE | VREAD);
1590 error = VOP_ACCESS(vp, VWRITE, td->td_ucred, td);
1594 unp = sotounpcb(so);
1595 KASSERT(unp != NULL, (
"unp_connect: unp == NULL"));
1599 VOP_UNP_CONNECT(vp, &unp2);
1601 error = ECONNREFUSED;
1604 so2 = unp2->unp_socket;
1605 if (so->so_type != so2->so_type) {
1610 if (SOLISTENING(so2)) {
1611 CURVNET_SET(so2->so_vnet);
1617 error = ECONNREFUSED;
1620 unp3 = sotounpcb(so2);
1622 if (unp2->unp_addr != NULL) {
1623 bcopy(unp2->unp_addr, sa, unp2->unp_addr->sun_len);
1624 unp3->unp_addr = (
struct sockaddr_un *) sa;
1639 mac_socketpeer_set_from_socket(so, so2);
1640 mac_socketpeer_set_from_socket(so2, so);
1645 KASSERT(unp2 != NULL && so2 != NULL && unp2->unp_socket == so2 &&
1646 sotounpcb(so2) == unp2,
1647 (
"%s: unp2 %p so2 %p", __func__, unp2, so2));
1658 KASSERT((unp->unp_flags & UNP_CONNECTING) != 0,
1659 (
"%s: unp %p has UNP_CONNECTING clear", __func__, unp));
1660 unp->unp_flags &= ~UNP_CONNECTING;
1674 struct unpcb *server_unp,
struct unpcb *listen_unp)
1676 cru2xt(td, &client_unp->unp_peercred);
1677 client_unp->unp_flags |= UNP_HAVEPC;
1679 memcpy(&server_unp->unp_peercred, &listen_unp->unp_peercred,
1680 sizeof(server_unp->unp_peercred));
1681 server_unp->unp_flags |= UNP_HAVEPC;
1682 client_unp->unp_flags |= (listen_unp->unp_flags & UNP_WANTCRED_MASK);
1691 unp = sotounpcb(so);
1692 KASSERT(unp != NULL, (
"unp_connect2: unp == NULL"));
1693 unp2 = sotounpcb(so2);
1694 KASSERT(unp2 != NULL, (
"unp_connect2: unp2 == NULL"));
1698 KASSERT(unp->unp_conn == NULL,
1699 (
"%s: socket %p is already connected", __func__, unp));
1701 if (so2->so_type != so->so_type)
1702 return (EPROTOTYPE);
1703 unp->unp_conn = unp2;
1706 switch (so->so_type) {
1709 LIST_INSERT_HEAD(&unp2->unp_refs, unp, unp_reflink);
1715 case SOCK_SEQPACKET:
1716 KASSERT(unp2->unp_conn == NULL,
1717 (
"%s: socket %p is already connected", __func__, unp2));
1718 unp2->unp_conn = unp;
1719 if (req == PRU_CONNECT &&
1720 ((unp->unp_flags | unp2->unp_flags) & UNP_CONNWAIT))
1728 panic(
"unp_connect2");
1736 struct socket *so, *so2;
1738 struct unpcb *unptmp;
1743 KASSERT(unp->unp_conn == unp2,
1744 (
"%s: unpcb %p is not connected to %p", __func__, unp, unp2));
1746 unp->unp_conn = NULL;
1747 so = unp->unp_socket;
1748 so2 = unp2->unp_socket;
1749 switch (unp->unp_socket->so_type) {
1753 LIST_FOREACH(unptmp, &unp2->unp_refs, unp_reflink) {
1757 KASSERT(unptmp != NULL,
1758 (
"%s: %p not found in reflist of %p", __func__, unp, unp2));
1760 LIST_REMOVE(unp, unp_reflink);
1764 so->so_state &= ~SS_ISCONNECTED;
1770 case SOCK_SEQPACKET:
1773 MPASS(unp2->unp_conn == unp);
1774 unp2->unp_conn = NULL;
1802 struct unpcb *unp, **unp_list;
1804 struct xunpgen *xug;
1805 struct unp_head *head;
1810 switch ((intptr_t)arg1) {
1819 case SOCK_SEQPACKET:
1824 panic(
"unp_pcblist: arg1 %d", (
int)(intptr_t)arg1);
1831 if (req->oldptr == NULL) {
1833 req->oldidx = 2 * (
sizeof *xug)
1834 + (n + n/8) *
sizeof(
struct xunpcb);
1838 if (req->newptr != NULL)
1844 xug =
malloc(
sizeof(*xug), M_TEMP, M_WAITOK | M_ZERO);
1850 xug->xug_len =
sizeof *xug;
1852 xug->xug_gen = gencnt;
1854 error = SYSCTL_OUT(req, xug,
sizeof *xug);
1860 unp_list =
malloc(n *
sizeof *unp_list, M_TEMP, M_WAITOK);
1863 for (unp = LIST_FIRST(head), i = 0; unp && i < n;
1864 unp = LIST_NEXT(unp, unp_link)) {
1866 if (unp->unp_gencnt <= gencnt) {
1868 unp->unp_socket->so_cred)) {
1872 unp_list[i++] = unp;
1881 xu =
malloc(
sizeof(*xu), M_TEMP, M_WAITOK | M_ZERO);
1882 for (i = 0; i < n; i++) {
1888 if (unp->unp_gencnt <= gencnt) {
1889 xu->xu_len =
sizeof *xu;
1890 xu->xu_unpp = (uintptr_t)unp;
1895 if (unp->unp_addr != NULL)
1896 bcopy(unp->unp_addr, &xu->xu_addr,
1897 unp->unp_addr->sun_len);
1899 bzero(&xu->xu_addr,
sizeof(xu->xu_addr));
1900 if (unp->unp_conn != NULL &&
1901 unp->unp_conn->unp_addr != NULL)
1902 bcopy(unp->unp_conn->unp_addr,
1904 unp->unp_conn->unp_addr->sun_len);
1906 bzero(&xu->xu_caddr,
sizeof(xu->xu_caddr));
1907 xu->unp_vnode = (uintptr_t)unp->unp_vnode;
1908 xu->unp_conn = (uintptr_t)unp->unp_conn;
1909 xu->xu_firstref = (uintptr_t)LIST_FIRST(&unp->unp_refs);
1910 xu->xu_nextref = (uintptr_t)LIST_NEXT(unp, unp_reflink);
1911 xu->unp_gencnt = unp->unp_gencnt;
1914 error = SYSCTL_OUT(req, xu,
sizeof *xu);
1930 error = SYSCTL_OUT(req, xug,
sizeof *xug);
1932 free(unp_list, M_TEMP);
1938 CTLTYPE_OPAQUE | CTLFLAG_RD | CTLFLAG_MPSAFE,
1939 (
void *)(intptr_t)SOCK_DGRAM, 0,
unp_pcblist,
"S,xunpcb",
1940 "List of active local datagram sockets");
1942 CTLTYPE_OPAQUE | CTLFLAG_RD | CTLFLAG_MPSAFE,
1943 (
void *)(intptr_t)SOCK_STREAM, 0,
unp_pcblist,
"S,xunpcb",
1944 "List of active local stream sockets");
1946 CTLTYPE_OPAQUE | CTLFLAG_RD | CTLFLAG_MPSAFE,
1947 (
void *)(intptr_t)SOCK_SEQPACKET, 0,
unp_pcblist,
"S,xunpcb",
1948 "List of active local seqpacket sockets");
1958 unp2 = unp->unp_conn;
1959 if ((unp->unp_socket->so_type == SOCK_STREAM ||
1960 (unp->unp_socket->so_type == SOCK_SEQPACKET)) && unp2 != NULL) {
1961 so = unp2->unp_socket;
1980 so = unp->unp_socket;
1982 so->so_error = ECONNRESET;
1998 KASSERT(fdcount > 0, (
"%s: fdcount %d", __func__, fdcount));
2000 for (i = 0; i < fdcount; i++) {
2001 fp = fdep[i]->fde_file;
2005 free(fdep[0], M_FILECAPS);
2011 struct thread *td = curthread;
2012 struct cmsghdr *cm = mtod(control,
struct cmsghdr *);
2015 struct filedesc *fdesc = td->td_proc->p_fd;
2016 struct filedescent **fdep;
2018 socklen_t clen = control->m_len, datalen;
2025 if (controlp != NULL)
2027 while (cm != NULL) {
2028 if (
sizeof(*cm) > clen || cm->cmsg_len > clen) {
2032 data = CMSG_DATA(cm);
2033 datalen = (caddr_t)cm + cm->cmsg_len - (caddr_t)
data;
2034 if (cm->cmsg_level == SOL_SOCKET
2035 && cm->cmsg_type == SCM_RIGHTS) {
2036 newfds = datalen /
sizeof(*fdep);
2042 if (error || controlp == NULL) {
2046 FILEDESC_XLOCK(fdesc);
2054 newlen = newfds *
sizeof(int);
2056 SCM_RIGHTS, SOL_SOCKET);
2057 if (*controlp == NULL) {
2058 FILEDESC_XUNLOCK(fdesc);
2065 CMSG_DATA(mtod(*controlp,
struct cmsghdr *));
2066 if (
fdallocn(td, 0, fdp, newfds) != 0) {
2067 FILEDESC_XUNLOCK(fdesc);
2074 for (i = 0; i < newfds; i++, fdp++) {
2075 _finstall(fdesc, fdep[i]->fde_file, *fdp,
2076 (
flags & MSG_CMSG_CLOEXEC) != 0 ? O_CLOEXEC : 0,
2077 &fdep[i]->fde_caps);
2086 m_chtype(*controlp, MT_EXTCONTROL);
2087 FILEDESC_XUNLOCK(fdesc);
2088 free(fdep[0], M_FILECAPS);
2091 if (error || controlp == NULL)
2094 cm->cmsg_type, cm->cmsg_level);
2095 if (*controlp == NULL) {
2100 CMSG_DATA(mtod(*controlp,
struct cmsghdr *)),
2103 controlp = &(*controlp)->m_next;
2106 if (CMSG_SPACE(datalen) < clen) {
2107 clen -= CMSG_SPACE(datalen);
2108 cm = (
struct cmsghdr *)
2109 ((caddr_t)cm + CMSG_SPACE(datalen));
2129unp_zdtor(
void *mem,
int size __unused,
void *arg __unused)
2135 KASSERT(LIST_EMPTY(&unp->unp_refs),
2136 (
"%s: unpcb %p has lingering refs", __func__, unp));
2137 KASSERT(unp->unp_socket == NULL,
2138 (
"%s: unpcb %p has socket backpointer", __func__, unp));
2139 KASSERT(unp->unp_vnode == NULL,
2140 (
"%s: unpcb %p has vnode references", __func__, unp));
2141 KASSERT(unp->unp_conn == NULL,
2142 (
"%s: unpcb %p is still connected", __func__, unp));
2143 KASSERT(unp->unp_addr == NULL,
2144 (
"%s: unpcb %p has leaked addr", __func__, unp));
2158 unp_zone = uma_zcreate(
"unpcb",
sizeof(
struct unpcb), NULL, dtor,
2159 NULL, NULL, UMA_ALIGN_CACHE, 0);
2161 uma_zone_set_warning(
unp_zone,
"kern.ipc.maxsockets limit reached");
2163 NULL, EVENTHANDLER_PRI_ANY);
2167 SLIST_INIT(&unp_defers);
2183 for (m = control; m != NULL; m = m->m_next) {
2184 cp = mtod(m,
struct cmsghdr *);
2185 if (cp->cmsg_level != SOL_SOCKET ||
2186 cp->cmsg_type != SCM_RIGHTS)
2188 data = CMSG_DATA(cp);
2189 datalen = (caddr_t)cp + cp->cmsg_len - (caddr_t)
data;
2197 struct mbuf *control, **initial_controlp;
2199 struct filedesc *fdesc;
2202 struct cmsgcred *cmcred;
2203 struct filedescent *fde, **fdep, *fdev;
2206 struct timespec *
ts;
2208 socklen_t clen, datalen;
2209 int i, j, error, *fdp, oldfds;
2217 control = *controlp;
2218 clen = control->m_len;
2220 initial_controlp = controlp;
2221 for (cm = mtod(control,
struct cmsghdr *); cm != NULL;) {
2222 if (
sizeof(*cm) > clen || cm->cmsg_level != SOL_SOCKET
2223 || cm->cmsg_len > clen || cm->cmsg_len <
sizeof(*cm)) {
2227 data = CMSG_DATA(cm);
2228 datalen = (caddr_t)cm + cm->cmsg_len - (caddr_t)
data;
2230 switch (cm->cmsg_type) {
2236 SCM_CREDS, SOL_SOCKET);
2237 if (*controlp == NULL) {
2241 cmcred = (
struct cmsgcred *)
2242 CMSG_DATA(mtod(*controlp,
struct cmsghdr *));
2243 cmcred->cmcred_pid = p->p_pid;
2244 cmcred->cmcred_uid = td->td_ucred->cr_ruid;
2245 cmcred->cmcred_gid = td->td_ucred->cr_rgid;
2246 cmcred->cmcred_euid = td->td_ucred->cr_uid;
2247 cmcred->cmcred_ngroups = MIN(td->td_ucred->cr_ngroups,
2249 for (i = 0; i < cmcred->cmcred_ngroups; i++)
2250 cmcred->cmcred_groups[i] =
2251 td->td_ucred->cr_groups[i];
2255 oldfds = datalen / sizeof (
int);
2263 FILEDESC_SLOCK(fdesc);
2264 for (i = 0; i < oldfds; i++, fdp++) {
2265 fp = fget_noref(fdesc, *fdp);
2267 FILEDESC_SUNLOCK(fdesc);
2271 if (!(fp->f_ops->fo_flags & DFLAG_PASSABLE)) {
2272 FILEDESC_SUNLOCK(fdesc);
2282 newlen = oldfds *
sizeof(fdep[0]);
2284 SCM_RIGHTS, SOL_SOCKET);
2285 if (*controlp == NULL) {
2286 FILEDESC_SUNLOCK(fdesc);
2291 for (i = 0; i < oldfds; i++, fdp++) {
2292 if (!fhold(fdesc->fd_ofiles[*fdp].fde_file)) {
2294 for (j = 0; j < i; j++, fdp++) {
2295 fdrop(fdesc->fd_ofiles[*fdp].
2298 FILEDESC_SUNLOCK(fdesc);
2304 fdep = (
struct filedescent **)
2305 CMSG_DATA(mtod(*controlp,
struct cmsghdr *));
2306 fdev =
malloc(
sizeof(*fdev) * oldfds, M_FILECAPS,
2308 for (i = 0; i < oldfds; i++, fdev++, fdp++) {
2309 fde = &fdesc->fd_ofiles[*fdp];
2311 fdep[i]->fde_file = fde->fde_file;
2313 &fdep[i]->fde_caps,
true);
2316 FILEDESC_SUNLOCK(fdesc);
2321 SCM_TIMESTAMP, SOL_SOCKET);
2322 if (*controlp == NULL) {
2326 tv = (
struct timeval *)
2327 CMSG_DATA(mtod(*controlp,
struct cmsghdr *));
2333 SCM_BINTIME, SOL_SOCKET);
2334 if (*controlp == NULL) {
2339 CMSG_DATA(mtod(*controlp,
struct cmsghdr *));
2345 SCM_REALTIME, SOL_SOCKET);
2346 if (*controlp == NULL) {
2350 ts = (
struct timespec *)
2351 CMSG_DATA(mtod(*controlp,
struct cmsghdr *));
2357 SCM_MONOTONIC, SOL_SOCKET);
2358 if (*controlp == NULL) {
2362 ts = (
struct timespec *)
2363 CMSG_DATA(mtod(*controlp,
struct cmsghdr *));
2372 if (*controlp != NULL)
2373 controlp = &(*controlp)->m_next;
2374 if (CMSG_SPACE(datalen) < clen) {
2375 clen -= CMSG_SPACE(datalen);
2376 cm = (
struct cmsghdr *)
2377 ((caddr_t)cm + CMSG_SPACE(datalen));
2385 if (error != 0 && initial_controlp != NULL)
2394 struct mbuf *m, *n, *n_prev;
2395 const struct cmsghdr *cm;
2396 int ngroups, i, cmsgtype;
2399 ngroups = MIN(td->td_ucred->cr_ngroups, CMGROUP_MAX);
2400 if (
mode & UNP_WANTCRED_ALWAYS) {
2401 ctrlsz = SOCKCRED2SIZE(ngroups);
2402 cmsgtype = SCM_CREDS2;
2404 ctrlsz = SOCKCREDSIZE(ngroups);
2405 cmsgtype = SCM_CREDS;
2412 if (
mode & UNP_WANTCRED_ALWAYS) {
2413 struct sockcred2 *sc;
2415 sc = (
void *)CMSG_DATA(mtod(m,
struct cmsghdr *));
2417 sc->sc_pid = td->td_proc->p_pid;
2418 sc->sc_uid = td->td_ucred->cr_ruid;
2419 sc->sc_euid = td->td_ucred->cr_uid;
2420 sc->sc_gid = td->td_ucred->cr_rgid;
2421 sc->sc_egid = td->td_ucred->cr_gid;
2422 sc->sc_ngroups = ngroups;
2423 for (i = 0; i < sc->sc_ngroups; i++)
2424 sc->sc_groups[i] = td->td_ucred->cr_groups[i];
2426 struct sockcred *sc;
2428 sc = (
void *)CMSG_DATA(mtod(m,
struct cmsghdr *));
2429 sc->sc_uid = td->td_ucred->cr_ruid;
2430 sc->sc_euid = td->td_ucred->cr_uid;
2431 sc->sc_gid = td->td_ucred->cr_rgid;
2432 sc->sc_egid = td->td_ucred->cr_gid;
2433 sc->sc_ngroups = ngroups;
2434 for (i = 0; i < sc->sc_ngroups; i++)
2435 sc->sc_groups[i] = td->td_ucred->cr_groups[i];
2443 if (control != NULL && cmsgtype == SCM_CREDS)
2444 for (n = control, n_prev = NULL; n != NULL;) {
2445 cm = mtod(n,
struct cmsghdr *);
2446 if (cm->cmsg_level == SOL_SOCKET &&
2447 cm->cmsg_type == SCM_CREDS) {
2449 control = n->m_next;
2451 n_prev->m_next = n->m_next;
2460 m->m_next = control;
2464static struct unpcb *
2469 if (fp->f_type != DTYPE_SOCKET)
2471 if ((so = fp->f_data) == NULL)
2475 return sotounpcb(so);
2484 dr =
malloc(
sizeof(*dr), M_TEMP, M_WAITOK);
2487 SLIST_INSERT_HEAD(&unp_defers, dr, ud_link);
2489 atomic_add_int(&unp_defers_count, 1);
2505 if (SLIST_FIRST(&unp_defers) == NULL) {
2509 SLIST_SWAP(&unp_defers, &drl,
unp_defer);
2512 while ((dr = SLIST_FIRST(&drl)) != NULL) {
2513 SLIST_REMOVE_HEAD(&drl, ud_link);
2518 atomic_add_int(&unp_defers_count, -
count);
2528 if ((unp =
fptounp(fp)) != NULL) {
2530 unp->unp_msgcount++;
2543 if ((unp =
fptounp(fp)) != NULL) {
2544 unp->unp_msgcount--;
2571 (
"%s: not on gc callout", __func__));
2574 for (i = 0; i < fdcount; i++) {
2575 fp = fdep[i]->fde_file;
2576 if ((unp =
fptounp(fp)) == NULL)
2578 if ((unp->unp_gcflag & UNPGC_DEAD) == 0)
2595 (
"%s: not on gc callout", __func__));
2598 for (i = 0; i < fdcount; i++) {
2599 fp = fdep[i]->fde_file;
2600 if ((unp =
fptounp(fp)) == NULL)
2602 if ((unp->unp_gcflag & UNPGC_DEAD) == 0)
2612 struct socket *so, *soa;
2614 so = unp->unp_socket;
2616 if (SOLISTENING(so)) {
2620 TAILQ_FOREACH(soa, &so->sol_comp, so_list) {
2621 if (sotounpcb(soa)->unp_gcflag & UNPGC_IGNORE_RIGHTS)
2623 SOCKBUF_LOCK(&soa->so_rcv);
2625 SOCKBUF_UNLOCK(&soa->so_rcv);
2631 if ((unp->unp_gcflag & UNPGC_IGNORE_RIGHTS) == 0) {
2632 SOCKBUF_LOCK(&so->so_rcv);
2634 SOCKBUF_UNLOCK(&so->so_rcv);
2642 "Number of unreachable sockets claimed by the garbage collector.");
2646 "Number of times the garbage collector has run.");
2649 "Number of active local sockets.");
2656 struct unp_head **head;
2657 struct unp_head unp_deadhead;
2658 struct file *f, **unref;
2659 struct unpcb *unp, *unptmp;
2660 int i, total, unp_unreachable;
2662 LIST_INIT(&unp_deadhead);
2668 unp_unreachable = 0;
2670 for (head = heads; *head != NULL; head++)
2671 LIST_FOREACH(unp, *head, unp_link) {
2672 KASSERT((unp->unp_gcflag & ~UNPGC_IGNORE_RIGHTS) == 0,
2673 (
"%s: unp %p has unexpected gc flags 0x%x",
2674 __func__, unp, (
unsigned int)unp->unp_gcflag));
2685 if (f != NULL && unp->unp_msgcount != 0 &&
2686 refcount_load(&f->f_count) == unp->unp_msgcount) {
2687 LIST_INSERT_HEAD(&unp_deadhead, unp, unp_dead);
2688 unp->unp_gcflag |= UNPGC_DEAD;
2689 unp->unp_gcrefs = unp->unp_msgcount;
2700 LIST_FOREACH(unp, &unp_deadhead, unp_dead)
2711 LIST_FOREACH_SAFE(unp, &unp_deadhead, unp_dead, unptmp)
2712 if (unp->unp_gcrefs > 0) {
2713 unp->unp_gcflag &= ~UNPGC_DEAD;
2714 LIST_REMOVE(unp, unp_dead);
2715 KASSERT(unp_unreachable > 0,
2716 (
"%s: unp_unreachable underflow.",
2725 if (unp_unreachable == 0)
2734 unref =
malloc(unp_unreachable *
sizeof(
struct file *),
2743 LIST_FOREACH(unp, &unp_deadhead, unp_dead) {
2744 KASSERT((unp->unp_gcflag & UNPGC_DEAD) != 0,
2745 (
"%s: unp %p not marked UNPGC_DEAD", __func__, unp));
2746 unp->unp_gcflag &= ~UNPGC_DEAD;
2748 if (unp->unp_msgcount == 0 || f == NULL ||
2749 refcount_load(&f->f_count) != unp->unp_msgcount ||
2753 KASSERT(total <= unp_unreachable,
2754 (
"%s: incorrect unreachable count.", __func__));
2763 for (i = 0; i < total; i++) {
2766 so = unref[i]->f_data;
2767 CURVNET_SET(so->so_vnet);
2775 for (i = 0; i < total; i++)
2776 fdrop(unref[i], NULL);
2778 free(unref, M_TEMP);
2797 unp = sotounpcb(so);
2799 unp->unp_gcflag |= UNPGC_IGNORE_RIGHTS;
2801 if (!SOLISTENING(so))
2806unp_scan(
struct mbuf *m0,
void (*op)(
struct filedescent **,
int))
2811 socklen_t clen, datalen;
2813 while (m0 != NULL) {
2814 for (m = m0; m; m = m->m_next) {
2815 if (m->m_type != MT_CONTROL)
2818 cm = mtod(m,
struct cmsghdr *);
2821 while (cm != NULL) {
2822 if (
sizeof(*cm) > clen || cm->cmsg_len > clen)
2825 data = CMSG_DATA(cm);
2826 datalen = (caddr_t)cm + cm->cmsg_len
2829 if (cm->cmsg_level == SOL_SOCKET &&
2830 cm->cmsg_type == SCM_RIGHTS) {
2831 (*op)(
data, datalen /
2832 sizeof(
struct filedescent *));
2835 if (CMSG_SPACE(datalen) < clen) {
2836 clen -= CMSG_SPACE(datalen);
2837 cm = (
struct cmsghdr *)
2838 ((caddr_t)cm + CMSG_SPACE(datalen));
2861 ASSERT_VOP_ELOCKED(vp,
"vfs_unp_reclaim");
2862 KASSERT(vp->v_type == VSOCK,
2863 (
"vfs_unp_reclaim: vp->v_type != VSOCK"));
2868 VOP_UNP_CONNECT(vp, &unp);
2872 if (unp->unp_vnode == vp) {
2874 unp->unp_vnode = NULL;
2886db_print_indent(
int indent)
2890 for (i = 0; i < indent; i++)
2895db_print_unpflags(
int unp_flags)
2900 if (unp_flags & UNP_HAVEPC) {
2901 db_printf(
"%sUNP_HAVEPC", comma ?
", " :
"");
2904 if (unp_flags & UNP_WANTCRED_ALWAYS) {
2905 db_printf(
"%sUNP_WANTCRED_ALWAYS", comma ?
", " :
"");
2908 if (unp_flags & UNP_WANTCRED_ONESHOT) {
2909 db_printf(
"%sUNP_WANTCRED_ONESHOT", comma ?
", " :
"");
2912 if (unp_flags & UNP_CONNWAIT) {
2913 db_printf(
"%sUNP_CONNWAIT", comma ?
", " :
"");
2916 if (unp_flags & UNP_CONNECTING) {
2917 db_printf(
"%sUNP_CONNECTING", comma ?
", " :
"");
2920 if (unp_flags & UNP_BINDING) {
2921 db_printf(
"%sUNP_BINDING", comma ?
", " :
"");
2927db_print_xucred(
int indent,
struct xucred *xu)
2931 db_print_indent(indent);
2932 db_printf(
"cr_version: %u cr_uid: %u cr_pid: %d cr_ngroups: %d\n",
2933 xu->cr_version, xu->cr_uid, xu->cr_pid, xu->cr_ngroups);
2934 db_print_indent(indent);
2935 db_printf(
"cr_groups: ");
2937 for (i = 0; i < xu->cr_ngroups; i++) {
2938 db_printf(
"%s%u", comma ?
", " :
"", xu->cr_groups[i]);
2945db_print_unprefs(
int indent,
struct unp_head *uh)
2951 LIST_FOREACH(unp, uh, unp_reflink) {
2952 if (counter % 4 == 0)
2953 db_print_indent(indent);
2954 db_printf(
"%p ", unp);
2955 if (counter % 4 == 3)
2959 if (counter != 0 && counter % 4 != 0)
2963DB_SHOW_COMMAND(unpcb, db_show_unpcb)
2968 db_printf(
"usage: show unpcb <addr>\n");
2971 unp = (
struct unpcb *)
addr;
2973 db_printf(
"unp_socket: %p unp_vnode: %p\n", unp->unp_socket,
2976 db_printf(
"unp_ino: %ju unp_conn: %p\n", (uintmax_t)unp->unp_ino,
2979 db_printf(
"unp_refs:\n");
2980 db_print_unprefs(2, &unp->unp_refs);
2983 db_printf(
"unp_addr: %p\n", unp->unp_addr);
2985 db_printf(
"unp_gencnt: %llu\n",
2986 (
unsigned long long)unp->unp_gencnt);
2988 db_printf(
"unp_flags: %x (", unp->unp_flags);
2989 db_print_unpflags(unp->unp_flags);
2992 db_printf(
"unp_peercred:\n");
2993 db_print_xucred(2, &unp->unp_peercred);
2995 db_printf(
"unp_refcount: %u\n", unp->unp_refcount);
static struct bt_table bt
void _finstall(struct filedesc *fdp, struct file *fp, int fd, int flags, struct filecaps *fcaps)
bool filecaps_copy(const struct filecaps *src, struct filecaps *dst, bool locked)
void closef_nothread(struct file *fp)
int fdallocn(struct thread *td, int minfd, int *fds, int n)
void filecaps_free(struct filecaps *fcaps)
void *() malloc(size_t size, struct malloc_type *mtp, int flags)
void free(void *addr, struct malloc_type *mtp)
void m_freem(struct mbuf *mb)
struct mtx_pool __read_mostly * mtxpool_sleep
struct mtx * mtx_pool_find(struct mtx_pool *pool, void *ptr)
void cru2xt(struct thread *td, struct xucred *xcr)
int cr_cansee(struct ucred *u1, struct ucred *u2)
void panic(const char *fmt,...)
void wakeup(const void *ident)
void nanouptime(struct timespec *tsp)
void bintime(struct bintime *bt)
void microtime(struct timeval *tvp)
void nanotime(struct timespec *tsp)
struct iommu_domain ** domain
int taskqueue_enqueue(struct taskqueue *queue, struct task *task)
int taskqueue_member(struct taskqueue *queue, struct thread *td)
int taskqueue_enqueue_timeout(struct taskqueue *queue, struct timeout_task *ttask, int ticks)
void soroverflow_locked(struct socket *so)
void sbrelease(struct sockbuf *sb, struct socket *so)
void sbappendcontrol_locked(struct sockbuf *sb, struct mbuf *m0, struct mbuf *control, int flags)
void socantsendmore(struct socket *so)
int soreserve(struct socket *so, u_long sndcc, u_long rcvcc)
int sbappendaddr_nospacecheck_locked(struct sockbuf *sb, const struct sockaddr *asa, struct mbuf *m0, struct mbuf *control)
int sbready(struct sockbuf *sb, struct mbuf *m0, int count)
void sbappend_locked(struct sockbuf *sb, struct mbuf *m, int flags)
struct mbuf * sbcreatecontrol(caddr_t p, int size, int type, int level)
void socantrcvmore(struct socket *so)
int sbappendaddr_locked(struct sockbuf *sb, const struct sockaddr *asa, struct mbuf *m0, struct mbuf *control)
int solisten_proto_check(struct socket *so)
void sorflush(struct socket *so)
struct socket * sonewconn(struct socket *head, int connstatus)
void soisdisconnected(struct socket *so)
void soisconnected(struct socket *so)
void sotoxsocket(struct socket *so, struct xsocket *xso)
int sooptcopyin(struct sockopt *sopt, void *buf, size_t len, size_t minlen)
int soreceive_generic(struct socket *so, struct sockaddr **psa, struct uio *uio, struct mbuf **mp0, struct mbuf **controlp, int *flagsp)
void soisconnecting(struct socket *so)
struct sockaddr * sodupsockaddr(const struct sockaddr *sa, int mflags)
void solisten_proto(struct socket *so, int backlog)
int soreceive_dgram(struct socket *so, struct sockaddr **psa, struct uio *uio, struct mbuf **mp0, struct mbuf **controlp, int *flagsp)
int sooptcopyout(struct sockopt *sopt, const void *buf, size_t len)
static SLIST_HEAD(unp_defer)
SYSINIT(unp_init, SI_SUB_PROTO_DOMAIN, SI_ORDER_SECOND, unp_init, NULL)
static u_long unpsp_recvspace
static void unp_remove_dead_ref(struct filedescent **fdep, int fdcount)
static struct unp_head unp_sphead
static int uipc_bind(struct socket *so, struct sockaddr *nam, struct thread *td)
static struct pr_usrreqs uipc_usrreqs_dgram
static int uipc_connect2(struct socket *, struct socket *)
static int uipc_shutdown(struct socket *so)
static void unp_disconnect(struct unpcb *unp, struct unpcb *unp2)
void vfs_unp_reclaim(struct vnode *vp)
static struct unpcb * unp_pcb_lock_peer(struct unpcb *unp)
#define UNP_REF_LIST_LOCK()
SYSCTL_INT(_net_local, OID_AUTO, inflight, CTLFLAG_RD, &unp_rights, 0, "File descriptors in flight.")
static void uipc_abort(struct socket *so)
static int uipc_sockaddr(struct socket *so, struct sockaddr **nam)
#define UNP_PCB_UNLOCK_ASSERT(unp)
#define UNP_PCB_LOCK_INIT(unp)
#define UNP_LINK_WUNLOCK()
static u_long unpsp_sendspace
static void unp_init(void *arg __unused)
static int uipc_listen(struct socket *so, int backlog, struct thread *td)
#define UNP_PCB_LOCK(unp)
static int uipc_sense(struct socket *so, struct stat *sb)
static void unp_gc_scan(struct unpcb *unp, void(*op)(struct filedescent **, int))
static struct unpcb * fptounp(struct file *fp)
static struct protosw localsw[]
static void unp_restore_undead_ref(struct filedescent **fdep, int fdcount)
SYSCTL_PROC(_net_local_dgram, OID_AUTO, pcblist, CTLTYPE_OPAQUE|CTLFLAG_RD|CTLFLAG_MPSAFE,(void *)(intptr_t) SOCK_DGRAM, 0, unp_pcblist, "S,xunpcb", "List of active local datagram sockets")
static void unp_dispose(struct socket *so)
static int uipc_disconnect(struct socket *so)
MALLOC_DECLARE(M_FILECAPS)
SYSCTL_UINT(_net_local, OID_AUTO, sockcount, CTLFLAG_RD, &unp_count, 0, "Number of active local sockets.")
static int uipc_accept(struct socket *so, struct sockaddr **nam)
static void unp_gc(__unused void *, int)
static void unp_freerights(struct filedescent **, int)
static void uipc_close(struct socket *so)
#define UNP_PCB_LOCKPTR(unp)
static struct rwlock unp_link_rwlock
static void unp_pcb_rele_notlast(struct unpcb *unp)
static u_long unpdg_sendspace
#define UNP_PCB_UNLOCK(unp)
static int uipc_rcvd(struct socket *so, int flags)
static void unp_discard(struct file *)
static void unp_internalize_cleanup_rights(struct mbuf *control)
#define UNP_REF_LIST_UNLOCK()
static int unp_connect2(struct socket *so, struct socket *so2, int)
void unp_copy_peercred(struct thread *td, struct unpcb *client_unp, struct unpcb *server_unp, struct unpcb *listen_unp)
static SYSCTL_NODE(_net, PF_LOCAL, local, CTLFLAG_RW|CTLFLAG_MPSAFE, 0, "Local domain")
static void unp_internalize_fp(struct file *)
static int uipc_peeraddr(struct socket *so, struct sockaddr **nam)
static int uipc_ready(struct socket *so, struct mbuf *m, int count)
#define UNP_LINK_LOCK_INIT()
static struct unp_head unp_dhead
#define UNP_LINK_WOWNED()
static bool uipc_ready_scan(struct socket *so, struct mbuf *m, int count, int *errorp)
static int unp_externalize(struct mbuf *, struct mbuf **, int)
static struct task unp_defer_task
static u_long unpst_recvspace
static int uipc_bindat(int fd, struct socket *so, struct sockaddr *nam, struct thread *td)
static void unp_dispose_mbuf(struct mbuf *)
static void unp_process_defers(void *__unused, int)
static int unp_connect(struct socket *, struct sockaddr *, struct thread *)
static struct pr_usrreqs uipc_usrreqs_dgram uipc_usrreqs_stream
#define UNP_PCB_LOCK_ASSERT(unp)
static int uipc_ctloutput(struct socket *, struct sockopt *)
static void unp_shutdown(struct unpcb *)
static int unp_externalize_fp(struct file *)
static struct timeout_task unp_gc_task
#define UNP_LINK_RUNLOCK()
static unp_gen_t unp_gencnt
static struct pr_usrreqs uipc_usrreqs_seqpacket
#define UNP_DEFERRED_UNLOCK()
static int uipc_attach(struct socket *so, int proto, struct thread *td)
static void unp_pcb_unlock_pair(struct unpcb *unp, struct unpcb *unp2)
#define UNP_LINK_UNLOCK_ASSERT()
#define OPTSET(bit, exclusive)
static void unp_drop(struct unpcb *)
static void unp_scan(struct mbuf *, void(*)(struct filedescent **, int))
static struct mtx unp_defers_lock
static struct unp_head unp_shead
SYSCTL_ULONG(_net_local_stream, OID_AUTO, sendspace, CTLFLAG_RW, &unpst_sendspace, 0, "Default stream send space.")
static int uipc_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
static void uipc_detach(struct socket *so)
static void unp_pcb_hold(struct unpcb *unp)
static __result_use_check bool unp_pcb_rele(struct unpcb *unp)
#define UNP_DEFERRED_LOCK_INIT()
static void unp_zone_change(void *tag)
#define UNP_PCB_LOCK_DESTROY(unp)
#define UNP_LINK_LOCK_ASSERT()
#define UNP_DEFERRED_LOCK()
static int unp_connectat(int, struct socket *, struct sockaddr *, struct thread *)
static void unp_pcb_lock_pair(struct unpcb *unp, struct unpcb *unp2)
static int uipc_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam, struct mbuf *control, struct thread *td)
#define UNP_PCB_TRYLOCK(unp)
static struct mbuf * unp_addsockcred(struct thread *, struct mbuf *, int)
static u_long unpst_sendspace
static u_long unpdg_recvspace
static uma_zone_t unp_zone
static struct domain localdomain
static int unp_internalize(struct mbuf **, struct thread *)
static int unp_pcblist(SYSCTL_HANDLER_ARGS)
static int uipc_connectat(int fd, struct socket *so, struct sockaddr *nam, struct thread *td)
void() NDFREE(struct nameidata *ndp, const u_int flags)
int namei(struct nameidata *ndp)
void vref(struct vnode *vp)
void vrele(struct vnode *vp)
void vput(struct vnode *vp)
void vunref(struct vnode *vp)
int vn_start_write(struct vnode *vp, struct mount **mpp, int flags)
void vn_finished_write(struct mount *mp)