6 #include <sys/socket.h>
7 #include <netinet/in.h>
11 #include <sys/types.h>
14 enum nss_status _nss_icmp_gethostbyaddr_r(const void *addr, socklen_t len, int af, struct hostent *result, char *buffer, size_t buflen, int *errnop, int *h_errnop)
30 retbuf = (struct retstruct *)buffer;
31 if((buflen < sizeof(*retbuf)) || (len > sizeof(retbuf->retaddr))) {
33 *h_errnop = NETDB_INTERNAL;
34 return(NSS_STATUS_UNAVAIL);
37 ap = (u_int8_t *)addr;
38 if(inet_ntop(af, addr, addrbuf, sizeof(addrbuf)) == NULL) {
40 *h_errnop = NETDB_INTERNAL;
41 return(NSS_STATUS_UNAVAIL);
46 *h_errnop = NETDB_INTERNAL;
47 return(NSS_STATUS_UNAVAIL);
49 /* I honestly don't know if it is considered OK to fork in other
50 * people's programs. We need a SUID worker, though, so there's
51 * little choice that I can see. */
52 if((child = fork()) < 0) {
54 *h_errnop = NETDB_INTERNAL;
55 return(NSS_STATUS_UNAVAIL);
61 if((fd = open("/dev/null", O_WRONLY)) < 0)
66 for(i = 3; i < FD_SETSIZE; i++)
69 execlp("idnlookup", "idnlookup", addrbuf, NULL);
77 ret = read(pfd[0], addrbuf + rl, sizeof(addrbuf) - rl);
80 *h_errnop = NETDB_INTERNAL;
82 return(NSS_STATUS_UNAVAIL);
85 if(rl >= sizeof(addrbuf) - 1) {
87 *h_errnop = NETDB_INTERNAL;
89 return(NSS_STATUS_UNAVAIL);
97 p3 = buffer + sizeof(*retbuf);
98 while((p2 = strchr(p, '\n')) != NULL) {
100 if((p3 - buffer) + (p2 - p) + 1 > buflen) {
102 *h_errnop = NETDB_INTERNAL;
103 return(NSS_STATUS_UNAVAIL);
105 memcpy(p3, p, (p2 - p) + 1);
106 retbuf->aliaslist[an] = p3;
111 *h_errnop = NETDB_INTERNAL;
112 return(NSS_STATUS_UNAVAIL);
116 *h_errnop = TRY_AGAIN; /* Is this correct? */
117 return(NSS_STATUS_NOTFOUND);
119 retbuf->aliaslist[an] = NULL;
121 memcpy(retbuf->retaddr, addr, len);
122 retbuf->addrlist[0] = retbuf->retaddr;
123 retbuf->addrlist[1] = NULL;
124 result->h_name = retbuf->aliaslist[0];
125 result->h_aliases = retbuf->aliaslist;
126 result->h_addr_list = retbuf->addrlist;
127 result->h_addrtype = af;
128 result->h_length = len;
130 *h_errnop = NETDB_SUCCESS;
131 return(NSS_STATUS_SUCCESS);