*
* \sa getnameinfo(3).
*/
-char *host_and_port(struct sockaddr *sa, socklen_t len)
+static char *host_and_port(struct sockaddr *sa, socklen_t len)
{
static char output[NI_MAXHOST + NI_MAXSERV + 2];
char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV];
ret = getnameinfo(sa, len, hbuf, sizeof(hbuf), sbuf, sizeof(sbuf),
NI_NUMERICHOST | NI_NUMERICSERV);
- if (ret) {
- PARA_WARNING_LOG("hostname lookup error (%s).\n", gai_strerror(ret));
+ if (ret) {
+ PARA_WARNING_LOG("hostname lookup error (%s).\n",
+ gai_strerror(ret));
sprintf(output, "(unknown)");
- } else {
+ } else
sprintf(output, "%s#%s", hbuf, sbuf);
- }
return output;
}
return host_and_port((struct sockaddr *)&ss, sslen);
}
-char *local_name(int sockfd)
+char *local_name(int sockfd)
{
return __get_sock_name(sockfd, getsockname);
}
return __get_sock_name(sockfd, getpeername);
}
+/**
+ * Extract IPv4 or IPv6-mapped-IPv4 address from sockaddr_storage.
+ * \param ss Container of IPv4/6 address
+ * \return Extracted IPv4 address (different from 0) or 0 if unsuccessful.
+ *
+ * \sa RFC 3493
+ */
+struct in_addr extract_v4_addr(const struct sockaddr_storage *ss)
+{
+ struct in_addr ia = { 0 };
+
+ if (ss->ss_family == AF_INET)
+ ia.s_addr = ((struct sockaddr_in *)ss)->sin_addr.s_addr;
+ if (ss->ss_family == AF_INET6) {
+ const struct in6_addr v6_addr = ((struct sockaddr_in6 *)ss)->sin6_addr;
+
+ if (IN6_IS_ADDR_V4MAPPED(&v6_addr))
+ memcpy(&ia.s_addr, &(v6_addr.s6_addr[12]), 4);
+ }
+ return ia;
+}
+
/*
* Send out a buffer, resend on short writes.
*