X-Git-Url: http://dolda2000.com/gitweb/?a=blobdiff_plain;f=nss-icmp.c;h=014f2573a140cd590bfa1a57f78983609382f7ab;hb=c9d7532139d71ed4955b5da519643a64bd590089;hp=b9f10139ee04e00869ef52f91cf452bd1ebc140e;hpb=15a913c297d12c0a4b14c01437420ac0df8b6675;p=icmp-dn.git diff --git a/nss-icmp.c b/nss-icmp.c index b9f1013..014f257 100644 --- a/nss-icmp.c +++ b/nss-icmp.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -12,6 +13,11 @@ #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; @@ -20,11 +26,13 @@ struct cache { 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) @@ -50,6 +58,11 @@ static void readconfig(void) continue; timeout = atoi(p2); } + if(!strcmp(linebuf, "ttlnotfound")) { + if(p2 == NULL) + continue; + nfttl = atoi(p2); + } if(!strcmp(linebuf, "nocache")) { usecache = 0; } @@ -78,7 +91,7 @@ static void freecache(struct cache *cc) free(cc); } -static void cachenotfound(const void *addr, socklen_t len, int af) +static void cachenotfound(const void *addr, socklen_t len, int af, time_t ttl) { struct cache *cc; @@ -97,6 +110,8 @@ static void cachenotfound(const void *addr, socklen_t len, int af) memcpy(cc->addr, addr, len); cc->addrlen = len; cc->af = af; + cc->at = time(NULL); + cc->ttl = ttl; cc->notfound = 1; @@ -107,39 +122,41 @@ static void cachenotfound(const void *addr, socklen_t len, int af) } } -static void updatecache(struct hostent *he) +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 == he->h_addrtype) && (cc->addrlen == he->h_length) && !memcmp(cc->addr, he->h_addr_list[0], he->h_length)) + 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(he->h_length)) == NULL) { + if((cc->addr = malloc(len)) == NULL) { freecache(cc); return; } - memcpy(cc->addr, he->h_addr_list[0], he->h_length); - cc->addrlen = he->h_length; - cc->af = he->h_addrtype; + memcpy(cc->addr, addr, len); + cc->addrlen = len; + cc->af = af; + cc->at = time(NULL); + cc->ttl = ttl; - for(i = 0; he->h_aliases[i] != NULL; i++); + 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; he->h_aliases[i] != NULL; i++) { - if((cc->names[i] = malloc(strlen(he->h_aliases[i]) + 1)) == NULL) { + for(i = 0; names[i] != NULL; i++) { + if((cc->names[i] = malloc(strlen(names[i]) + 1)) == NULL) { freecache(cc); return; } - strcpy(cc->names[i], he->h_aliases[i]); + strcpy(cc->names[i], names[i]); } cc->next = cache; @@ -149,6 +166,21 @@ static void updatecache(struct hostent *he) } } +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; @@ -158,7 +190,7 @@ enum nss_status _nss_icmp_gethostbyaddr_r(const void *addr, socklen_t len, int a char retaddr[16]; } *retbuf; char addrbuf[1024]; - int an, thislen; + int an, thislen, ttl; char *p, *p2, *p3; u_int8_t *ap; pid_t child; @@ -178,18 +210,27 @@ enum nss_status _nss_icmp_gethostbyaddr_r(const void *addr, socklen_t len, int a return(NSS_STATUS_UNAVAIL); } - for(cc = cache; cc != NULL; cc = cc->next) { - if((cc->af == af) && (cc->addrlen == len) && !memcmp(cc->addr, addr, len)) - break; + 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; @@ -219,9 +260,9 @@ enum nss_status _nss_icmp_gethostbyaddr_r(const void *addr, socklen_t len, int a if(timeout != -1) { snprintf(timeoutbuf, sizeof(timeoutbuf), "%i", timeout); - execlp("idnlookup", "idnlookup", "-t", timeoutbuf, addrbuf, NULL); + execlp("idnlookup", "idnlookup", "-Tt", timeoutbuf, addrbuf, NULL); } else { - execlp("idnlookup", "idnlookup", addrbuf, NULL); + execlp("idnlookup", "idnlookup", "-T", addrbuf, NULL); } exit(127); } @@ -247,9 +288,17 @@ enum nss_status _nss_icmp_gethostbyaddr_r(const void *addr, socklen_t len, int a } while(ret != 0); addrbuf[rl] = 0; close(pfd[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; - p = addrbuf; p3 = buffer + sizeof(*retbuf); while((p2 = strchr(p, '\n')) != NULL) { *p2 = 0; @@ -272,12 +321,17 @@ enum nss_status _nss_icmp_gethostbyaddr_r(const void *addr, socklen_t len, int a } } if(an == 0) { - cachenotfound(addr, len, af); + 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); @@ -286,22 +340,20 @@ enum nss_status _nss_icmp_gethostbyaddr_r(const void *addr, socklen_t len, int a 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[an] = p3; + retbuf->aliaslist[i] = p3; p3 += thislen + 1; - if(++an == 16) { - *errnop = ENOMEM; - *h_errnop = NETDB_INTERNAL; - return(NSS_STATUS_UNAVAIL); - } } + retbuf->aliaslist[i] = NULL; } + DEBUGP("returning hostent\n"); memcpy(retbuf->retaddr, addr, len); retbuf->addrlist[0] = retbuf->retaddr; retbuf->addrlist[1] = NULL; @@ -311,9 +363,7 @@ enum nss_status _nss_icmp_gethostbyaddr_r(const void *addr, socklen_t len, int a result->h_addrtype = af; result->h_length = len; - if(cc == NULL) - updatecache(result); - *h_errnop = NETDB_SUCCESS; + DEBUGP("returning\n"); return(NSS_STATUS_SUCCESS); }