Prepare for new dir hier by Oron Peled.
[icmp-dn.git] / nss-icmp.c
diff --git a/nss-icmp.c b/nss-icmp.c
deleted file mode 100644 (file)
index 5bc5ec7..0000000
+++ /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 <fredrik@dolda2000.com>
- *
- *  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 <stdlib.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <string.h>
-#include <errno.h>
-#include <time.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <netdb.h>
-#include <arpa/inet.h>
-#include <nss.h>
-#include <sys/types.h>
-#include <fcntl.h>
-#include <sys/wait.h>
-
-#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:
- */