#define _SUSV2_SOURCE #define _C99_SNPRINTF_EXTENSION #include #include #include #include #include #include #include #include #include #include #include #define nil ((void*)0) static int getport(char *trans, int port, char *srv, int srvlen) { char buf[128], match[5], *p, *q; int fd, r, n; r = EAI_FAIL; fd = open("/net/cs", O_RDWR); if(fd < 0) return r; snprintf(buf, sizeof buf, "!port=%d %s=*", port, trans); snprintf(match, sizeof match, "%s=", trans); if(write(fd, buf, strlen(buf)) == -1){ close(fd); return r; } lseek(fd, 0, 0); n = read(fd, buf, sizeof buf - 1); if(n > 0){ buf[n] = 0; for(p = buf; p != nil; p = q){ q = strchr(buf, ' '); if(q != nil) *q++ = 0; if(strncmp(p, match, 4) == 0){ r = snprintf(srv, srvlen, "%s", p+4); break; } } } close(fd); return r; } static int getname(int af, void *addr, char *host, long hostlen, int flags) { char ipbuf[128], buf[128], *p, *q; int fd, r, n; r = EAI_FAIL; if(inet_ntop(af, addr, ipbuf, sizeof ipbuf) == nil) return EAI_SYSTEM; fd = open("/net/cs", O_RDWR); if(fd < 0) return r; snprintf(buf, sizeof buf, "!ip=%s dom=*", ipbuf); if(write(fd, buf, strlen(buf)) == -1){ close(fd); return r; } lseek(fd, 0, 0); n = read(fd, buf, sizeof buf - 1); if(n > 0){ buf[n] = 0; for(p = buf; p != nil; p = q){ q = strchr(buf, ' '); if(q != nil) *q++ = 0; if(strncmp(p, "dom=", 4) == 0){ r = snprintf(ipbuf, sizeof ipbuf, "%s", p+4); break; } } } close(fd); if(r >= 0){ if(flags & NI_NOFQDN){ p = strchr(ipbuf, '.'); if(p != nil) *p = 0; } r = EAI_OVERFLOW; if(snprintf(host, hostlen, "%s", ipbuf) >= 0) r = 0; } return r; } static int afhinfo(int af, void *addr, int port, char *host, long hostlen, char *srv, long srvlen, int flags) { char *trans; int r; trans = "tcp"; if(flags & NI_DGRAM) trans = "udp"; if(flags & NI_NUMERICSERV || getport(trans, port, srv, srvlen) < 0) snprintf(srv, srvlen, "%d", port); /* require name even if not returning it */ if(flags & NI_NAMEREQD){ r = getname(af, addr, host, hostlen, flags); if(r < 0) return r; } if(flags & NI_NUMERICHOST){ if(inet_ntop(af, addr, host, hostlen) == nil) return EAI_SYSTEM; return 0; } if(getname(af, addr, host, hostlen, flags) == 0) return 0; return 0; } int getnameinfo(const struct sockaddr *sa, int len, char *host, long hostlen, char *srv, long srvlen, int flags) { char fakehost[64], fakesrv[16]; struct sockaddr_in *in; struct sockaddr_in6 *in6; if(host != nil && hostlen != 0) *host = 0; else{ host = fakehost; hostlen = sizeof fakehost; } if(srv != nil && hostlen != 0) *srv = 0; else{ srv = fakesrv; srvlen = sizeof fakesrv; } switch(sa->sa_family){ default: return EAI_SOCKTYPE; case AF_INET: if(len < sizeof *in) return EAI_OVERFLOW; in = (struct sockaddr_in*)sa; return afhinfo(AF_INET, &in->sin_addr, ntohs(in->sin_port), host, hostlen, srv, srvlen, flags); case AF_INET6: if(len < sizeof *in6) return EAI_OVERFLOW; in6 = (struct sockaddr_in6*)sa; return afhinfo(AF_INET6, &in6->sin6_addr, ntohs(in6->sin6_port), host, hostlen, srv, srvlen, flags); } }