+int lstgetremotename2(struct lport *lp, struct socket *sk2, struct sockaddr **namebuf, socklen_t *lenbuf)
+{
+ struct sockaddr *name1, *name2;
+ socklen_t len1, len2;
+ struct ufd *ufd1, *ufd2;
+
+ ufd1 = lp->ufd;
+ ufd2 = getskufd(sk2);
+ if(ufd2->type != UFD_SOCK) {
+ errno = EOPNOTSUPP;
+ return(-1);
+ }
+ if(ufd1->d.l.family != ufd2->d.s.family)
+ {
+ flog(LOG_ERR, "using lstgetremotename2 with sockets of differing family: %i %i", ufd1->d.l.family, ufd2->d.s.family);
+ return(-1);
+ }
+ if(getremotename(ufd1->fd, &name1, &len1))
+ return(-1);
+ if(getremotename(ufd2->fd, &name2, &len2)) {
+ free(name1);
+ return(-1);
+ }
+ sethostaddr(name1, name2);
+ free(name2);
+ *namebuf = name1;
+ *lenbuf = len1;
+ return(0);
+}
+
+int getucred(struct socket *sk, uid_t *uid, gid_t *gid)
+{
+ struct ufd *ufd;
+
+ ufd = getskufd(sk);
+ if(ufd->type != UFD_SOCK) {
+ errno = EOPNOTSUPP;
+ return(-1);
+ }
+ if(ufd->d.s.family != AF_UNIX) {
+ errno = EOPNOTSUPP;
+ return(-1);
+ }
+ *uid = ufd->d.s.ucred.uid;
+ *gid = ufd->d.s.ucred.gid;
+ return(0);
+}
+
+/* void sockblock(struct socket *sk, int block) */
+/* { */
+/* struct ufd *ufd; */
+
+/* ufd = getskufd(sk); */
+/* ufd->ignread = block; */
+/* } */
+
+int sockfamily(struct socket *sk)
+{
+ struct ufd *ufd;
+
+ ufd = getskufd(sk);
+ if(ufd->type != UFD_SOCK) {
+ errno = EOPNOTSUPP;
+ return(-1);
+ }
+ return(ufd->d.s.family);
+}
+
+int sockpeeraddr(struct socket *sk, struct sockaddr **namebuf, socklen_t *lenbuf)
+{
+ struct ufd *ufd;
+
+ ufd = getskufd(sk);
+ if(ufd->type != UFD_SOCK) {
+ errno = EOPNOTSUPP;
+ return(-1);
+ }
+ if(ufd->d.s.remote == NULL)
+ return(-1);
+ *namebuf = memcpy(smalloc(ufd->d.s.remotelen), ufd->d.s.remote, ufd->d.s.remotelen);
+ if(lenbuf != NULL)
+ *lenbuf = ufd->d.s.remotelen;
+ return(0);
+}
+
+char *formatsockpeer(struct socket *sk)
+{
+ struct sockaddr *name;
+ socklen_t nlen;
+ char *ret;
+
+ if(sockpeeraddr(sk, &name, &nlen))
+ return(NULL);
+ ret = formataddress(name, nlen);
+ free(name);
+ return(ret);
+}
+