+/**
+ * wget_sockaddr_set_address
+ *
+ * This function takes an wget_sockaddr and fill in the protocol type,
+ * the port number and the address, there NULL in address means wildcard.
+ * Unsuported adress family will abort the whole programm.
+ *
+ * Input:
+ * wget_sockaddr* The space to be filled
+ * int The wished protocol
+ * unsigned short The port
+ * const ip_address The Binary IP adress
+ *
+ * Return:
+ * - Only modify 1. param
+ */
+void
+wget_sockaddr_set_address (wget_sockaddr *sa,
+ int ip_family, unsigned short port, ip_address *addr)
+{
+ if (ip_family == AF_INET)
+ {
+ sa->sin.sin_family = ip_family;
+ sa->sin.sin_port = htons (port);
+ if (addr == NULL)
+ memset (&sa->sin.sin_addr, 0, sizeof(ip4_address));
+ else
+ {
+ ip4_address addr4;
+ if (!map_ip_to_ipv4 (addr, &addr4))
+ /* should the callers have prevented this? */
+ abort ();
+ memcpy (&sa->sin.sin_addr, &addr4, sizeof(ip4_address));
+ }
+ return;
+ }
+#ifdef INET6
+ if (ip_family == AF_INET6)
+ {
+ sa->sin6.sin6_family = ip_family;
+ sa->sin6.sin6_port = htons (port);
+ if (addr == NULL)
+ memset (&sa->sin6.sin6_addr, 0 , 16);
+ else
+ memcpy (&sa->sin6.sin6_addr, addr, 16);
+ return;
+ }
+#endif
+ abort();
+}
+
+/**
+ * wget_sockaddr_set_port
+ *
+ * This funtion only fill the port of the socket information.
+ * If the protocol is not supported nothing is done.
+ * Unsuported adress family will abort the whole programm.
+ *
+ * Require:
+ * that the IP-Protocol already is set.
+ *
+ * Input:
+ * wget_sockaddr* The space there port should be entered
+ * unsigned int The port that should be entered in host order
+ *
+ * Return:
+ * - Only modify 1. param
+ */
+void
+wget_sockaddr_set_port (wget_sockaddr *sa, unsigned short port)
+{
+ if (sa->sa.sa_family == AF_INET)
+ {
+ sa->sin.sin_port = htons (port);
+ return;
+ }
+#ifdef INET6
+ if (sa->sa.sa_family == AF_INET6)
+ {
+ sa->sin6.sin6_port = htons (port);
+ return;
+ }
+#endif
+ abort();
+}
+
+/**
+ * wget_sockaddr_get_addr
+ *
+ * This function return the adress from an sockaddr as byte string.
+ * Unsuported adress family will abort the whole programm.
+ *
+ * Require:
+ * that the IP-Protocol already is set.
+ *
+ * Input:
+ * wget_sockaddr* Socket Information
+ *
+ * Output:
+ * unsigned char * IP address as byte string.
+ */
+void *
+wget_sockaddr_get_addr (wget_sockaddr *sa)
+{
+ if (sa->sa.sa_family == AF_INET)
+ return &sa->sin.sin_addr;
+#ifdef INET6
+ if (sa->sa.sa_family == AF_INET6)
+ return &sa->sin6.sin6_addr;
+#endif
+ abort();
+ /* unreached */
+ return NULL;
+}
+
+/**
+ * wget_sockaddr_get_port
+ *
+ * This function only return the port from the input structure
+ * Unsuported adress family will abort the whole programm.
+ *
+ * Require:
+ * that the IP-Protocol already is set.
+ *
+ * Input:
+ * wget_sockaddr* Information where to get the port
+ *
+ * Output:
+ * unsigned short Port Number in host order.
+ */
+unsigned short
+wget_sockaddr_get_port (const wget_sockaddr *sa)
+{
+ if (sa->sa.sa_family == AF_INET)
+ return htons (sa->sin.sin_port);
+#ifdef INET6
+ if (sa->sa.sa_family == AF_INET6)
+ return htons (sa->sin6.sin6_port);
+#endif
+ abort();
+ /* do not complain about return nothing */
+ return -1;
+}
+
+/**
+ * sockaddr_len
+ *
+ * This function return the length of the sockaddr corresponding to
+ * the acutall prefered protocol for (bind, connect etc...)
+ * Unsuported adress family will abort the whole programm.
+ *
+ * Require:
+ * that the IP-Protocol already is set.
+ *
+ * Input:
+ * - Public IP-Family Information
+ *
+ * Output:
+ * int structure length for socket options
+ */
+int
+sockaddr_len ()
+{
+ if (ip_default_family == AF_INET)
+ return sizeof (struct sockaddr_in);
+#ifdef INET6
+ if (ip_default_family == AF_INET6)
+ return sizeof (struct sockaddr_in6);
+#endif
+ abort();
+ /* do not complain about return nothing */
+ return 0;
+}
+
+/**
+ * Map an IPv4 adress to the internal adress format.
+ */
+void
+map_ipv4_to_ip (ip4_address *ipv4, ip_address *ip)
+{
+#ifdef INET6
+ static unsigned char ipv64[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff};
+ memcpy ((char *)ip + 12, ipv4 , 4);
+ memcpy ((char *)ip + 0, ipv64, 12);
+#else
+ if ((char *)ip != (char *)ipv4)
+ memcpy (ip, ipv4, 4);
+#endif
+}
+
+/* Detect whether an IP adress represents an IPv4 address and, if so,
+ copy it to IPV4. 0 is returned on failure.
+ This operation always succeeds when Wget is compiled without IPv6.
+ If IPV4 is NULL, don't copy, just detect. */
+
+int
+map_ip_to_ipv4 (ip_address *ip, ip4_address *ipv4)
+{
+#ifdef INET6
+ static unsigned char ipv64[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff};
+ if (0 != memcmp (ip, ipv64, 12))
+ return 0;
+ if (ipv4)
+ memcpy (ipv4, (char *)ip + 12, 4);
+#else
+ if (ipv4)
+ memcpy (ipv4, (char *)ip, 4);
+#endif
+ return 1;
+}
+\f
+/* Pretty-print ADDR. When compiled without IPv6, this is the same as
+ inet_ntoa. With IPv6, it either prints an IPv6 address or an IPv4
+ address. */