+ if ((ip = (char *) calloc(IPSIZE, sizeof(char))) == NULL) {
+ if (result) {
+ freeaddrinfo(result);
+ }
+ return (NULL);
+ }
+
+ hai = result;
+ satop(hai->ai_addr, ip, IPSIZE);
+
+ freeaddrinfo(result);
+ return (ip);
+ }
+
+ return (NULL);
+}
+
+/* satop(struct sockaddr *sa, char *dst, socklen_t size)
+ * Convert a sockaddr to a printable address.
+ */
+int satop(struct sockaddr *sa, char *dst, socklen_t size)
+{
+ sa_family_t af;
+ struct sockaddr_in *sa4;
+ struct sockaddr_in6 *sa6;
+#ifdef WIN32
+ int newlength;
+#endif
+
+ af = sa->sa_family;
+
+ switch (af)
+ {
+ case AF_INET:
+ sa4 = (struct sockaddr_in *) sa;
+#ifdef WIN32
+ newlength = size;
+ WSAAddressToString((LPSOCKADDR) sa4, sizeof(struct sockaddr_in),
+ NULL, dst, (LPDWORD) &newlength);
+#else
+ inet_ntop(af, (const void *) &(sa4->sin_addr), dst, size);
+#endif
+ return(0);
+ case AF_INET6:
+ sa6 = (struct sockaddr_in6 *) sa;
+#ifdef WIN32
+ newlength = size;
+ WSAAddressToString((LPSOCKADDR) sa6, sizeof(struct sockaddr_in6),
+ NULL, dst, (LPDWORD) &newlength);
+#else
+ inet_ntop(af, (const void *) &(sa6->sin6_addr), dst, size);
+#endif
+ if (IN6_IS_ADDR_V4MAPPED(&(sa6->sin6_addr)))
+ { /* extract the embedded IPv4 address */
+ memmove(dst, dst+7, size-7);
+ }
+ return(0);
+ default:
+ *dst = '\0';
+ return(-1);
+ }
+}
+
+int OS_CloseSocket(int socket)
+{
+#ifdef WIN32
+ return (closesocket(socket));
+#else
+ return (close(socket));
+#endif /* WIN32 */
+}
+
+
+/*
+ * OS_DecodeAddrinfo() will decode the contents of an addrinfo structure and
+ * log the IP version, address, and port number for each item in the
+ * linked list of addrinfo structs.
+ */
+
+int OS_DecodeAddrinfo (struct addrinfo *res) {
+ struct addrinfo *p; /* pointer to addrinfo structs */
+
+ for (p = res; p != NULL; p = p->ai_next)
+ verbose ("%s",OS_DecodeSockaddr (p->ai_addr));
+ return 0;
+}
+
+
+/*
+ * OS_DecodeSockaddr() will decode a socket address and return a string with
+ * the IP version, address, and port number.
+ */
+
+char *OS_DecodeSockaddr (struct sockaddr *sa) {
+ int rc; /* return code */
+ char ipaddr[INET6_ADDRSTRLEN]; /* printed address */
+ char ipport[NI_MAXSERV]; /* printed port */
+ static char buf[256]; /* message buffer */
+
+#if defined(__linux__) || defined (WIN32)
+ /* most Linux systems do not have sa_len in the sockaddr struct */
+ socklen_t slen = 0;
+ switch(sa->sa_family) {
+ case AF_INET:
+ slen = sizeof(struct sockaddr_in);
+ break;
+ case AF_INET6:
+ slen = sizeof(struct sockaddr_in6);
+ break;
+ default:
+ // XXX WTF
+ break;
+ }
+ rc = getnameinfo ((struct sockaddr *) sa, slen, ipaddr,
+ sizeof (ipaddr), ipport, sizeof (ipport),
+ NI_NUMERICHOST | NI_NUMERICSERV);
+#else
+ /* BSD systems require the value in sa->sa_len or error 4 occurs */
+ rc = getnameinfo ((struct sockaddr *) sa, sa->sa_len, ipaddr,
+ sizeof (ipaddr), ipport, sizeof (ipport),
+ NI_NUMERICHOST | NI_NUMERICSERV);
+#endif
+
+ if (rc) {
+ sprintf (buf, "Error %d on getnameinfo: %s", rc, gai_strerror (rc));
+ return (buf);
+ }
+
+ sprintf (buf, "%s: %s on port %s",
+ DecodeFamily (sa->sa_family), ipaddr, ipport);
+ return buf;
+}
+
+
+/*
+ * DecodeFamily() is used to convert the IP family into a string for info
+ * and debugging purposes.
+ */
+
+char *DecodeFamily (int val) {
+ static char buf[32]; /* response */
+
+ switch (val) {
+ case AF_INET:
+ strcpy (buf,"IPv4");
+ break;
+ case AF_INET6:
+ strcpy (buf,"IPv6");
+ break;
+ default:
+ sprintf (buf, "Unknown Family %d", val);
+ break;
+ }
+
+ return (buf);
+}
+
+
+/*
+ * DecodeSocktype() is used to convert the IP socket type into a string for
+ * info and debugging purposes.
+ */
+
+char *DecodeSocktype (int val) {
+ static char buf[32]; /* response */
+
+ switch (val) {
+ case SOCK_STREAM:
+ strcpy (buf,"STREAM");
+ break;
+ case SOCK_DGRAM:
+ strcpy (buf,"DGRAM");
+ break;
+ case SOCK_RAW:
+ strcpy (buf,"RAW");
+ break;
+ default:
+ sprintf (buf, "Unknown Sock Type %d", val);
+ break;
+ }