- if (ss2->ss_family == AF_INET6 &&
- IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)ss2)->sin6_addr)) {
- memset(&ss2_v4, 0, sizeof(struct sockaddr_in));
- memcpy(&ss2_v4.sin_addr.s_addr,
- &(((struct sockaddr_in6 *)ss2)->sin6_addr.s6_addr[12]),
+ return mystr_sockaddr;
+}
+
+int
+str_to_sockaddr(
+ const char *src,
+ sockaddr_union *dst)
+{
+ int result;
+
+ g_debug("parsing %s", src);
+ /* try AF_INET first */
+ SU_INIT(dst, AF_INET);
+ if ((result = inet_pton(AF_INET, src, &dst->sin.sin_addr)) == 1)
+ return result;
+
+ /* otherwise try AF_INET6, if supported */
+#ifdef WORKING_IPV6
+ SU_INIT(dst, AF_INET6);
+ return inet_pton(AF_INET6, src, &dst->sin6.sin6_addr);
+#else
+ return result;
+#endif
+}
+
+/* Unmap a V4MAPPED IPv6 address into its equivalent IPv4 address. The location
+ * TMP is used to store the rewritten address, if necessary. Returns a pointer
+ * to the unmapped address.
+ */
+#if defined(WORKING_IPV6) && defined(IN6_IS_ADDR_V4MAPPED)
+static sockaddr_union *
+unmap_v4mapped(
+ sockaddr_union *sa,
+ sockaddr_union *tmp)
+{
+ if (SU_GET_FAMILY(sa) == AF_INET6 && IN6_IS_ADDR_V4MAPPED(&sa->sin6.sin6_addr)) {
+ SU_INIT(tmp, AF_INET);
+ SU_SET_PORT(tmp, SU_GET_PORT(sa));
+ /* extract the v4 address from byte 12 of the v6 address */
+ memcpy(&tmp->sin.sin_addr.s_addr,
+ &sa->sin6.sin6_addr.s6_addr[12],