+static int
+gai_trivial(struct in_addr *in4, struct in6_addr *in6, int16_t port, const struct addrinfo *hints, struct addrinfo **res)
+{
+ int32_t family, wantv4, wantv6, proto;
+ char *loopv4, *loopv6;
+ struct in_addr a4;
+ struct in6_addr a6;
+ struct addrinfo *a;
+
+ family = PF_UNSPEC;
+ if (hints != NULL) family = hints->ai_family;
+
+ wantv4 = 1;
+ wantv6 = 1;
+
+ if (family == PF_INET6) wantv4 = 0;
+ if (family == PF_INET) wantv6 = 0;
+
+ memset(&a4, 0, sizeof(struct in_addr));
+ memset(&a6, 0, sizeof(struct in6_addr));
+
+ if ((in4 == NULL) && (in6 == NULL))
+ {
+ loopv4 = "127.0.0.1";
+ loopv6 = "0:0:0:0:0:0:0:1";
+
+ if ((hints != NULL) && ((hints->ai_flags & AI_PASSIVE) == 1))
+ {
+ loopv4 = "0.0.0.0";
+ loopv6 = "0:0:0:0:0:0:0:0";
+ }
+
+ if ((family == PF_UNSPEC) || (family == PF_INET))
+ {
+ inet_pton(AF_INET, loopv4, &a4);
+ }
+
+ if ((family == PF_UNSPEC) || (family == PF_INET6))
+ {
+ inet_pton(AF_INET6, loopv6, &a6);
+ }
+ }
+ else if (in4 == NULL)
+ {
+ if (family == PF_INET) return EAI_BADHINTS;
+
+ wantv4 = 0;
+ memcpy(&a6, in6, sizeof(struct in6_addr));
+ }
+ else if (in6 == NULL)
+ {
+ if (family == PF_INET6) return EAI_BADHINTS;
+
+ wantv6 = 0;
+ memcpy(&a4, in4, sizeof(struct in_addr));
+ }
+ else
+ {
+ return EAI_NODATA;
+ }
+
+ proto = IPPROTO_UNSPEC;
+
+ if (hints != NULL)
+ {
+ proto = hints->ai_protocol;
+ if (proto == IPPROTO_UNSPEC)
+ {
+ if (hints->ai_socktype == SOCK_DGRAM) proto = IPPROTO_UDP;
+ else if (hints->ai_socktype == SOCK_STREAM) proto = IPPROTO_TCP;
+ }
+ }
+
+ if (wantv4 == 1)
+ {
+ if ((proto == IPPROTO_UNSPEC) || (proto == IPPROTO_UDP))
+ {
+ a = new_addrinfo_v4(0, SOCK_DGRAM, IPPROTO_UDP, port, a4, 0, NULL);
+ append_addrinfo(res, a);
+ }
+
+ if ((proto == IPPROTO_UNSPEC) || (proto == IPPROTO_TCP))
+ {
+ a = new_addrinfo_v4(0, SOCK_STREAM, IPPROTO_TCP, port, a4, 0, NULL);
+ append_addrinfo(res, a);
+ }
+
+ if (proto == IPPROTO_ICMP)
+ {
+ a = new_addrinfo_v4(0, SOCK_RAW, IPPROTO_ICMP, port, a4, 0, NULL);
+ append_addrinfo(res, a);
+ }
+ }
+
+ if (wantv6 == 1)
+ {
+ if ((proto == IPPROTO_UNSPEC) || (proto == IPPROTO_UDP))
+ {
+ a = new_addrinfo_v6(0, SOCK_DGRAM, IPPROTO_UDP, port, a6, 0, NULL);
+ append_addrinfo(res, a);
+ }
+
+ if ((proto == IPPROTO_UNSPEC) || (proto == IPPROTO_TCP))
+ {
+ a = new_addrinfo_v6(0, SOCK_STREAM, IPPROTO_TCP, port, a6, 0, NULL);
+ append_addrinfo(res, a);
+ }
+
+ if (proto == IPPROTO_ICMPV6)
+ {
+ a = new_addrinfo_v6(0, SOCK_RAW, IPPROTO_ICMPV6, port, a6, 0, NULL);
+ append_addrinfo(res, a);
+ }
+ }
+
+ return 0;
+}
+