+
+static int
+mp_getaddr_v4(struct socket *mp_so, struct sockaddr **nam, boolean_t peer)
+{
+ struct mptses *mpte = mpsotompte(mp_so);
+ struct sockaddr_in *sin;
+
+ /*
+ * Do the malloc first in case it blocks.
+ */
+ MALLOC(sin, struct sockaddr_in *, sizeof(*sin), M_SONAME, M_WAITOK);
+ if (sin == NULL) {
+ return ENOBUFS;
+ }
+ bzero(sin, sizeof(*sin));
+ sin->sin_family = AF_INET;
+ sin->sin_len = sizeof(*sin);
+
+ if (!peer) {
+ sin->sin_port = mpte->__mpte_src_v4.sin_port;
+ sin->sin_addr = mpte->__mpte_src_v4.sin_addr;
+ } else {
+ sin->sin_port = mpte->__mpte_dst_v4.sin_port;
+ sin->sin_addr = mpte->__mpte_dst_v4.sin_addr;
+ }
+
+ *nam = (struct sockaddr *)sin;
+ return 0;
+}
+
+static int
+mp_getaddr_v6(struct socket *mp_so, struct sockaddr **nam, boolean_t peer)
+{
+ struct mptses *mpte = mpsotompte(mp_so);
+ struct in6_addr addr;
+ in_port_t port;
+
+ if (!peer) {
+ port = mpte->__mpte_src_v6.sin6_port;
+ addr = mpte->__mpte_src_v6.sin6_addr;
+ } else {
+ port = mpte->__mpte_dst_v6.sin6_port;
+ addr = mpte->__mpte_dst_v6.sin6_addr;
+ }
+
+ *nam = in6_sockaddr(port, &addr);
+ if (*nam == NULL) {
+ return ENOBUFS;
+ }
+
+ return 0;
+}
+
+int
+mp_getsockaddr(struct socket *mp_so, struct sockaddr **nam)
+{
+ struct mptses *mpte = mpsotompte(mp_so);
+
+ if (mpte->mpte_src.sa_family == AF_INET || mpte->mpte_src.sa_family == 0) {
+ return mp_getaddr_v4(mp_so, nam, false);
+ } else if (mpte->mpte_src.sa_family == AF_INET6) {
+ return mp_getaddr_v6(mp_so, nam, false);
+ } else {
+ return EINVAL;
+ }
+}
+
+int
+mp_getpeeraddr(struct socket *mp_so, struct sockaddr **nam)
+{
+ struct mptses *mpte = mpsotompte(mp_so);
+
+ if (mpte->mpte_src.sa_family == AF_INET || mpte->mpte_src.sa_family == 0) {
+ return mp_getaddr_v4(mp_so, nam, true);
+ } else if (mpte->mpte_src.sa_family == AF_INET6) {
+ return mp_getaddr_v6(mp_so, nam, true);
+ } else {
+ return EINVAL;
+ }
+}