+static char *sk_tcp_peer_info(Socket sock)
+{
+ Actual_Socket s = (Actual_Socket) sock;
+ struct sockaddr_storage addr;
+ socklen_t addrlen = sizeof(addr);
+ char buf[INET6_ADDRSTRLEN];
+
+ if (getpeername(s->s, (struct sockaddr *)&addr, &addrlen) < 0)
+ return NULL;
+ if (addr.ss_family == AF_INET) {
+ return dupprintf
+ ("%s:%d",
+ inet_ntoa(((struct sockaddr_in *)&addr)->sin_addr),
+ (int)ntohs(((struct sockaddr_in *)&addr)->sin_port));
+#ifndef NO_IPV6
+ } else if (addr.ss_family == AF_INET6) {
+ return dupprintf
+ ("[%s]:%d",
+ inet_ntop(AF_INET6, &((struct sockaddr_in6 *)&addr)->sin6_addr,
+ buf, sizeof(buf)),
+ (int)ntohs(((struct sockaddr_in6 *)&addr)->sin6_port));
+#endif
+ } else if (addr.ss_family == AF_UNIX) {
+ /*
+ * For Unix sockets, the source address is unlikely to be
+ * helpful. Instead, we try SO_PEERCRED and try to get the
+ * source pid.
+ */
+ int pid, uid, gid;
+ if (so_peercred(s->s, &pid, &uid, &gid)) {
+ char uidbuf[64], gidbuf[64];
+ sprintf(uidbuf, "%d", uid);
+ sprintf(gidbuf, "%d", gid);
+ struct passwd *pw = getpwuid(uid);
+ struct group *gr = getgrgid(gid);
+ return dupprintf("pid %d (%s:%s)", pid,
+ pw ? pw->pw_name : uidbuf,
+ gr ? gr->gr_name : gidbuf);
+ }
+ return NULL;
+ } else {
+ return NULL;
+ }
+}
+