+SockAddr sk_nonamelookup(const char *host)
+{
+ SockAddr ret = smalloc(sizeof(struct SockAddr_tag));
+ ret->error = NULL;
+ ret->family = AF_UNSPEC;
+ strncpy(ret->hostname, host, lenof(ret->hostname));
+ ret->hostname[lenof(ret->hostname)-1] = '\0';
+ return ret;
+}
+
+void sk_getaddr(SockAddr addr, char *buf, int buflen)
+{
+#ifdef IPV6
+ if (addr->family == AF_INET6) {
+ FIXME; /* I don't know how to get a text form of an IPv6 address. */
+ } else
+#endif
+ if (addr->family == AF_INET) {
+ struct in_addr a;
+ a.s_addr = htonl(addr->address);
+ strncpy(buf, inet_ntoa(a), buflen);
+ buf[buflen-1] = '\0';
+ } else {
+ assert(addr->family == AF_UNSPEC);
+ strncpy(buf, addr->hostname, buflen);
+ buf[buflen-1] = '\0';
+ }
+}
+
+int sk_hostname_is_local(char *name)
+{
+ return !strcmp(name, "localhost");
+}
+
+int sk_address_is_local(SockAddr addr)
+{
+#ifdef IPV6
+ if (addr->family == AF_INET6) {
+ FIXME; /* someone who can compile for IPV6 had better do this bit */
+ } else
+#endif
+ if (addr->family == AF_INET) {
+ struct in_addr a;
+ a.s_addr = htonl(addr->address);
+ return ipv4_is_loopback(a);
+ } else {
+ assert(addr->family == AF_UNSPEC);
+ return 0; /* we don't know; assume not */
+ }
+}
+
+int sk_addrtype(SockAddr addr)
+{
+ return (addr->family == AF_INET ? ADDRTYPE_IPV4 :
+#ifdef IPV6
+ addr->family == AF_INET6 ? ADDRTYPE_IPV6 :
+#endif
+ ADDRTYPE_NAME);
+}
+
+void sk_addrcopy(SockAddr addr, char *buf)
+{
+ assert(addr->family != AF_UNSPEC);
+#ifdef IPV6
+ if (addr->family == AF_INET6) {
+ memcpy(buf, (char*) addr->ai, 16);
+ } else
+#endif
+ if (addr->family == AF_INET) {
+ struct in_addr a;
+ a.s_addr = htonl(addr->address);
+ memcpy(buf, (char*) &a.s_addr, 4);
+ }
+}
+