X-Git-Url: http://git.dolda2000.com/gitweb/?a=blobdiff_plain;f=nss-icmp.c;fp=nss-icmp.c;h=0000000000000000000000000000000000000000;hb=21c92d5d484277cf22f62ecc8e60db1608e062ad;hp=5bc5ec7db9cbfe7dbf529da8200a04651b9a3289;hpb=bbb05b86699cdb941ecbd93e38654e4199d0a150;p=icmp-dn.git diff --git a/nss-icmp.c b/nss-icmp.c deleted file mode 100644 index 5bc5ec7..0000000 --- a/nss-icmp.c +++ /dev/null @@ -1,400 +0,0 @@ -/* - * nss-icmp or libnss_icmp - GNU C Library NSS module to query host - * names by ICMP. - * Copyright (C) 2005 Fredrik Tolf - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define CONFIGFILE "/etc/nss-icmp.conf" -#if 0 -#define DEBUGP(format...) fprintf(stderr, "nss-icmp: " format); -#else -#define DEBUGP(format...) -#endif - -struct cache { - struct cache *next, *prev; - char *addr; - socklen_t addrlen; - int af; - int notfound; - char **names; - time_t at, ttl; -}; - -static int inited = 0; -static int timeout = -1; -static int usecache = 1; -static time_t nfttl = 300; -static struct cache *cache = NULL; - -static void readconfig(void) -{ - FILE *f; - char linebuf[1024]; - char *p, *p2; - - if((f = fopen(CONFIGFILE, "r")) == NULL) - return; - - while(fgets(linebuf, sizeof(linebuf), f) != NULL) { - if(linebuf[0] == '#') - continue; - if((p = strchr(linebuf, '\n')) != NULL) - *p = 0; - if((p = strchr(linebuf, ' ')) != NULL) { - p2 = p + 1; - *p = 0; - } - if(!strcmp(linebuf, "timeout")) { - if(p2 == NULL) - continue; - timeout = atoi(p2); - } - if(!strcmp(linebuf, "ttlnotfound")) { - if(p2 == NULL) - continue; - nfttl = atoi(p2); - } - if(!strcmp(linebuf, "nocache")) { - usecache = 0; - } - } - - fclose(f); -} - -static void freecache(struct cache *cc) -{ - int i; - - if(cc->next != NULL) - cc->next->prev = cc->prev; - if(cc->prev != NULL) - cc->prev->next = cc->next; - if(cc == cache) - cache = cc->next; - if(cc->addr != NULL) - free(cc->addr); - if(cc->names != NULL) { - for(i = 0; cc->names[i] != NULL; i++) - free(cc->names[i]); - free(cc->names); - } - free(cc); -} - -static void cachenotfound(const void *addr, socklen_t len, int af, time_t ttl) -{ - struct cache *cc; - - for(cc = cache; cc != NULL; cc = cc->next) { - if((cc->af == af) && (cc->addrlen == len) && !memcmp(cc->addr, addr, len)) - break; - } - if(cc == NULL) { - if((cc = malloc(sizeof(*cc))) == NULL) - return; - memset(cc, 0, sizeof(*cc)); - if((cc->addr = malloc(len)) == NULL) { - freecache(cc); - return; - } - memcpy(cc->addr, addr, len); - cc->addrlen = len; - cc->af = af; - cc->at = time(NULL); - cc->ttl = ttl; - - cc->notfound = 1; - - cc->next = cache; - if(cache != NULL) - cache->prev = cc; - cache = cc; - } -} - -static void updatecache(const void *addr, socklen_t len, int af, char **names, time_t ttl) -{ - int i; - struct cache *cc; - - for(cc = cache; cc != NULL; cc = cc->next) { - if((cc->af == af) && (cc->addrlen == len) && !memcmp(cc->addr, addr, len)) - break; - } - if(cc == NULL) { - if((cc = malloc(sizeof(*cc))) == NULL) - return; - memset(cc, 0, sizeof(*cc)); - if((cc->addr = malloc(len)) == NULL) { - freecache(cc); - return; - } - memcpy(cc->addr, addr, len); - cc->addrlen = len; - cc->af = af; - cc->at = time(NULL); - cc->ttl = ttl; - - for(i = 0; names[i] != NULL; i++); - if((cc->names = malloc(sizeof(*(cc->names)) * (i + 1))) == NULL) { - freecache(cc); - return; - } - memset(cc->names, 0, sizeof(*(cc->names)) * (i + 1)); - for(i = 0; names[i] != NULL; i++) { - if((cc->names[i] = malloc(strlen(names[i]) + 1)) == NULL) { - freecache(cc); - return; - } - strcpy(cc->names[i], names[i]); - } - - cc->next = cache; - if(cache != NULL) - cache->prev = cc; - cache = cc; - } -} - -static void expirecache(void) -{ - struct cache *cc, *next; - time_t now; - - now = time(NULL); - for(cc = cache; cc != NULL; cc = next) { - next = cc->next; - if(now - cc->at > cc->ttl) { - freecache(cc); - continue; - } - } -} - -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) -{ - int i, ret; - struct retstruct { - char *aliaslist[16]; - char *addrlist[2]; - char retaddr[16]; - } *retbuf; - char addrbuf[1024]; - int an, thislen, ttl; - char *p, *p2, *p3; - u_int8_t *ap; - pid_t child; - int pfd[2]; - int rl; - int status; - struct cache *cc; - - if(!inited) { - readconfig(); - inited = 1; - } - - retbuf = (struct retstruct *)buffer; - if((buflen < sizeof(*retbuf)) || (len > sizeof(retbuf->retaddr))) { - *errnop = ENOMEM; - *h_errnop = NETDB_INTERNAL; - return(NSS_STATUS_UNAVAIL); - } - - DEBUGP("starting lookup\n"); - - if(usecache) { - expirecache(); - for(cc = cache; cc != NULL; cc = cc->next) { - if((cc->af == af) && (cc->addrlen == len) && !memcmp(cc->addr, addr, len)) - break; - } - } else { - cc = NULL; - } - - if(cc == NULL) { - DEBUGP("address not in cache, looking up for real\n"); - ap = (u_int8_t *)addr; - if(inet_ntop(af, addr, addrbuf, sizeof(addrbuf)) == NULL) { - *errnop = errno; - *h_errnop = NETDB_INTERNAL; - return(NSS_STATUS_UNAVAIL); - } - DEBUGP("address is %s\n", addrbuf); - - if(pipe(pfd)) { - *errnop = errno; - *h_errnop = NETDB_INTERNAL; - return(NSS_STATUS_UNAVAIL); - } - /* I honestly don't know if it is considered OK to fork in other - * people's programs. We need a SUID worker, though, so there's - * little choice that I can see. */ - if((child = fork()) < 0) { - *errnop = errno; - *h_errnop = NETDB_INTERNAL; - return(NSS_STATUS_UNAVAIL); - } - - if(child == 0) { - int i, fd; - char timeoutbuf[128]; - - if((fd = open("/dev/null", O_WRONLY)) < 0) - exit(127); - close(pfd[0]); - dup2(pfd[1], 1); - dup2(fd, 2); - for(i = 3; i < FD_SETSIZE; i++) - close(i); - - if(timeout != -1) { - snprintf(timeoutbuf, sizeof(timeoutbuf), "%i", timeout); - execlp("idnlookup", "idnlookup", "-Tt", timeoutbuf, addrbuf, NULL); - } else { - execlp("idnlookup", "idnlookup", "-T", addrbuf, NULL); - } - exit(127); - } - - close(pfd[1]); - - rl = 0; - do { - ret = read(pfd[0], addrbuf + rl, sizeof(addrbuf) - rl); - if(ret < 0) { - *errnop = errno; - *h_errnop = NETDB_INTERNAL; - close(pfd[0]); - return(NSS_STATUS_UNAVAIL); - } - rl += ret; - if(rl >= sizeof(addrbuf) - 1) { - *errnop = ENOMEM; - *h_errnop = NETDB_INTERNAL; - close(pfd[0]); - return(NSS_STATUS_UNAVAIL); - } - } while(ret != 0); - addrbuf[rl] = 0; - close(pfd[0]); - - waitpid(child, &status, 0); - - if((p = strchr(addrbuf, '\n')) == NULL) { - if(usecache) - cachenotfound(addr, len, af, nfttl); - *h_errnop = TRY_AGAIN; /* XXX: Is this correct? */ - return(NSS_STATUS_NOTFOUND); - } - *(p++) = 0; - ttl = atoi(addrbuf); - - an = 0; - p3 = buffer + sizeof(*retbuf); - while((p2 = strchr(p, '\n')) != NULL) { - *p2 = 0; - thislen = p2 - p; - if(thislen == 0) - continue; - if((p3 - buffer) + thislen + 1 > buflen) { - *errnop = ENOMEM; - *h_errnop = NETDB_INTERNAL; - return(NSS_STATUS_UNAVAIL); - } - memcpy(p3, p, thislen + 1); - retbuf->aliaslist[an] = p3; - p3 += thislen + 1; - p = p2 + 1; - if(++an == 16) { - *errnop = ENOMEM; - *h_errnop = NETDB_INTERNAL; - return(NSS_STATUS_UNAVAIL); - } - } - if(an == 0) { - if(usecache) - cachenotfound(addr, len, af, nfttl); - *h_errnop = TRY_AGAIN; /* XXX: Is this correct? */ - return(NSS_STATUS_NOTFOUND); - } - retbuf->aliaslist[an] = NULL; - - if(usecache) - updatecache(addr, len, af, retbuf->aliaslist, ttl); - } else { - DEBUGP("address found in cache\n"); - if(cc->notfound) { - *h_errnop = TRY_AGAIN; /* XXX: Is this correct? */ - return(NSS_STATUS_NOTFOUND); - } - - p3 = buffer + sizeof(*retbuf); - for(i = 0; cc->names[i] != NULL; i++) { - thislen = strlen(cc->names[i]); - DEBUGP("filling in address %s, length %i\n", cc->names[i], thislen); - if((p3 - buffer) + thislen + 1 > buflen) { - *errnop = ENOMEM; - *h_errnop = NETDB_INTERNAL; - return(NSS_STATUS_UNAVAIL); - } - memcpy(p3, cc->names[i], thislen + 1); - retbuf->aliaslist[i] = p3; - p3 += thislen + 1; - } - retbuf->aliaslist[i] = NULL; - } - - DEBUGP("returning hostent\n"); - memcpy(retbuf->retaddr, addr, len); - retbuf->addrlist[0] = retbuf->retaddr; - retbuf->addrlist[1] = NULL; - result->h_name = retbuf->aliaslist[0]; - result->h_aliases = retbuf->aliaslist; - result->h_addr_list = retbuf->addrlist; - result->h_addrtype = af; - result->h_length = len; - - *h_errnop = NETDB_SUCCESS; - DEBUGP("returning\n"); - return(NSS_STATUS_SUCCESS); -} - -/* - * Local Variables: - * compile-command: "gcc -shared -Wall -g -o libnss_icmp.so.2 nss-icmp.c" - * End: - */