Writing a custom nss hosts module

622 views Asked by At

I'm seeking to implement a custom nss module for the getent hosts lookup. Based on glibc's resolv/nss-dns/dns-host.c and gnunet's src/gns/nss/nss_gns.c I wrote the following minimal implementation that I hoped at least should write something to syslog - which it sadly doesn't.

#include <netdb.h>
#include <nss.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <syslog.h>

#define _nss_lash_gethostbyname2_r _nss_lash_gethostbyname_r
#define _nss_lash_gethostbyname3_r _nss_lash_gethostbyname_r
#define _nss_lash_gethostbyname4_r _nss_lash_gethostbyname_r
#define _nss_lash_getcanonname_r _nss_lash_gethostbyaddr_r
#define _nss_lash_gethostbyaddr2_r _nss_lash_gethostbyaddr_r
#define _nss_lash_getnetbyname_r _nss_lash_gethostbyaddr_r
#define _nss_lash_getnetbyaddr_r _nss_lash_gethostbyaddr_r

typedef char addr[1]; 
const addr default_addrs[2] = {0x01, 0x00};

enum nss_status
_nss_lash_gethostbyname_r (const char *name, struct hostent *result,
              char *buffer, size_t buflen, int *errnop,
              int *h_errnop)
{
    syslog(LOG_WARNING, name);
    if (!strcmp(name, "lash")) {
        return NSS_STATUS_UNAVAIL;
    }
    *(result->h_aliases) = 0x0;
    result->h_addrtype = AF_INET;
    result->h_length = 1;
    *(result->h_addr_list) = (char *)default_addrs;
    *errnop = 0;
    *h_errnop = NETDB_SUCCESS; 
    return NSS_STATUS_SUCCESS;      
}

enum nss_status
_nss_lash_gethostbyaddr_r (const char *name, struct hostent *result,
              char *buffer, size_t buflen, int *errnop,
              int *h_errnop)
{
    syslog(LOG_ERR, name);
    if (!strcmp(name, "lash")) {
        return NSS_STATUS_UNAVAIL;
    }
    *(result->h_aliases) = 0x0;
    result->h_addrtype = AF_INET;
    result->h_length = 1;
    *(result->h_addr_list) = (char *)default_addrs;
    *errnop = 0;
    *h_errnop = NETDB_SUCCESS; 
    return NSS_STATUS_SUCCESS;      

}

I've added lash to /etc/nsswitch.conf. strace shows that the /lib/libnss_lash.so.2 file is being successfully opened. However the return value from the nss lookup is NSS_UNAVAIL / ENOENT. If I add [unavail=return] to /etc/nsswitch.conf after the lash entry, I get the same result.

Anyone have any clues to what I'm missing?

(the #define lines attempt to catch all symbols found in objdump -T /lib/libnss_dns.so, which seems to be the simpler implementation)

Using:

  • glibc 2.30
  • gnunet 0.11.6-ish
  • nss 3.49.2
1

There are 1 answers

0
i6f70 On

In order to write to syslog from the NSS module, you need to open the syslog first of all. Here is an example:

openlog(NSS_MODULE_NAME, LOG_PID | LOG_CONS, LOG_AUTHPRIV);

syslog(LOG_ERR, "Something wrong here. ERROR: %s", error_str);

syslog(LOG_INFO, "Some info: %s", info_str);

closelog();

And don't forget to close it at the end. Good luck! =)