+#define CONFIGFILE "/etc/nss-icmp.conf"
+
+struct cache {
+ struct cache *next, *prev;
+ char *addr;
+ socklen_t addrlen;
+ int af;
+ int notfound;
+ char **names;
+};
+
+static int inited = 0;
+static int timeout = -1;
+static int usecache = 1;
+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, "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)
+{
+ 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->notfound = 1;
+
+ cc->next = cache;
+ if(cache != NULL)
+ cache->prev = cc;
+ cache = cc;
+ }
+}
+
+static void updatecache(struct hostent *he)
+{
+ 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))
+ break;
+ }
+ if(cc == NULL) {
+ if((cc = malloc(sizeof(*cc))) == NULL)
+ return;
+ memset(cc, 0, sizeof(*cc));
+ if((cc->addr = malloc(he->h_length)) == 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;
+
+ for(i = 0; he->h_aliases[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) {
+ freecache(cc);
+ return;
+ }
+ strcpy(cc->names[i], he->h_aliases[i]);
+ }
+
+ cc->next = cache;
+ if(cache != NULL)
+ cache->prev = cc;
+ cache = cc;
+ }
+}
+