+#ifdef HAVE_IPV6
+#define SIZEOF_SOCKADDR(so) ((so).sa.sa_family == AF_INET6 ? \
+ sizeof(so.sin6) : sizeof(so.sin))
+#else
+#define SIZEOF_SOCKADDR(so) (sizeof(so.sin))
+#endif
+
+typedef union {
+ struct sockaddr sa;
+ struct sockaddr_in sin;
+#ifdef HAVE_IPV6
+ struct sockaddr_in6 sin6;
+#endif
+} SilcSockaddr;
+
+static bool silc_net_set_sockaddr(SilcSockaddr *addr, const char *ip_addr,
+ int port)
+{
+ int len;
+
+ memset(addr, 0, sizeof(*addr));
+
+ /* Check for IPv4 and IPv6 addresses */
+ if (ip_addr) {
+ if (!silc_net_is_ip(ip_addr)) {
+ SILC_LOG_ERROR(("%s is not IP address", ip_addr));
+ return FALSE;
+ }
+
+ if (silc_net_is_ip4(ip_addr)) {
+ /* IPv4 address */
+ len = sizeof(addr->sin.sin_addr);
+ silc_net_addr2bin(ip_addr,
+ (unsigned char *)&addr->sin.sin_addr.s_addr, len);
+ addr->sin.sin_family = AF_INET;
+ addr->sin.sin_port = port ? htons(port) : 0;
+ } else {
+#ifdef HAVE_IPV6
+ /* IPv6 address */
+ len = sizeof(addr->sin6.sin6_addr);
+ silc_net_addr2bin(ip_addr,
+ (unsigned char *)&addr->sin6.sin6_addr, len);
+ addr->sin6.sin6_family = AF_INET6;
+ addr->sin6.sin6_port = port ? htons(port) : 0;
+#else
+ SILC_LOG_ERROR(("IPv6 support is not compiled in"));
+ return FALSE;
+#endif
+ }
+ } else {
+ /* Any address */
+ addr->sin.sin_family = AF_INET;
+ addr->sin.sin_addr.s_addr = INADDR_ANY;
+ if (port)
+ addr->sin.sin_port = htons(port);
+ }
+
+ return TRUE;
+}
+