From 7088c18535199a90f0c06a55bbed4622f6cdb521 Mon Sep 17 00:00:00 2001 From: bAndie91 Date: Tue, 4 Oct 2016 15:20:03 +0200 Subject: [PATCH] implement _nss_resolver_gethostbyaddr_r() for reverse resolving --- SConstruct | 4 +-- src/nssrs.c | 69 ++++++++++++++++++++++++++++++++++++++------------ src/resolver.c | 65 ++++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 114 insertions(+), 24 deletions(-) diff --git a/SConstruct b/SConstruct index 69dc818..6c4752a 100644 --- a/SConstruct +++ b/SConstruct @@ -76,7 +76,7 @@ so = env.SharedLibrary("%s/libnss_resolver" % build_dir, Glob("src/*c"), install_dirs = { 'pack' : ARGUMENTS.get('pack_prefix', '%s/libnss/usr/lib' % build_dir), 'local': ARGUMENTS.get('prefix', '/usr/lib'), - 'azk' : '/azk/lib' + 'azk' : './azk/lib' } for k,v in install_dirs.items(): @@ -109,5 +109,5 @@ env.Alias('cares' , cares) env.Alias('cmocka' , cmocka) env.Alias('test' , cares + cmocka + test_app) env.Alias('pack' , cares + so_pack) -env.Alias('install', cares + ['/azk/lib']) +env.Alias('install', cares + ['./azk/lib']) env.Alias('local-install', cares + [install_dirs['local']]) diff --git a/src/nssrs.c b/src/nssrs.c index 966aebd..922d59e 100644 --- a/src/nssrs.c +++ b/src/nssrs.c @@ -17,15 +17,16 @@ #define ALIGN(a) (((a+sizeof(void*)-1)/sizeof(void*))*sizeof(void*)) -static void +static int pack_hostent(struct hostent *result, char *buffer, size_t buflen, - const char *name, - const void *addr) + const struct hostent *hent) { - char *aliases, *r_addr, *addrlist; - size_t l, idx; + const char *name = hent->h_name; + const void *addr = hent->h_addr_list[0]; + char **aliases, *r_addr, *addrlist; + size_t l, idx, aidx; /* we can't allocate any memory, the buffer is where we need to * return things we want to use @@ -38,12 +39,23 @@ pack_hostent(struct hostent *result, idx = ALIGN (l+1); - /* 2nd, the empty aliases array */ - aliases = buffer + idx; - *(char **) aliases = NULL; - idx += sizeof (char*); + /* 2nd, the aliases array */ + aliases = (char **)buffer + idx; + int alias_cnt = 0; + for(char** alias = hent->h_aliases; hent->h_aliases != NULL && *alias != NULL; alias++) alias_cnt++; + idx += (alias_cnt+1) * sizeof(void*); + for(alias_cnt = 0; hent->h_aliases != NULL && hent->h_aliases[alias_cnt] != NULL; alias_cnt++) + { + if(idx >= buflen) + return NSS_STATUS_TRYAGAIN; + aliases[alias_cnt] = buffer + idx; + l = strlen(hent->h_aliases[alias_cnt]) + 1; + memcpy(aliases[alias_cnt], hent->h_aliases[alias_cnt], l); + idx += l; + } + aliases[alias_cnt] = NULL; + result->h_aliases = aliases; - result->h_aliases = (char **) aliases; result->h_addrtype = AF_INET; result->h_length = sizeof (struct in_addr); @@ -55,10 +67,12 @@ pack_hostent(struct hostent *result, /* 4th, the addresses ptr array */ addrlist = buffer + idx; + //FIXME ((char **) addrlist)[0] = r_addr; ((char **) addrlist)[1] = NULL; result->h_addr_list = (char **) addrlist; + return NSS_STATUS_SUCCESS; } enum nss_status @@ -89,10 +103,10 @@ _nss_resolver_gethostbyname2_r (const char *name, return NSS_STATUS_NOTFOUND; } - pack_hostent(result, buffer, buflen, name, hosts->h_addr_list[0]); + int ok = pack_hostent(result, buffer, buflen, hosts); ares_free_hostent(hosts); - return NSS_STATUS_SUCCESS; + return ok; } enum nss_status @@ -122,7 +136,6 @@ _nss_resolver_gethostbyaddr_r (const void *addr, int *errnop, int *h_errnop) { - if (af != AF_INET) { *errnop = EAFNOSUPPORT; *h_errnop = NO_DATA; @@ -135,7 +148,31 @@ _nss_resolver_gethostbyaddr_r (const void *addr, return NSS_STATUS_UNAVAIL; } - *errnop = EAFNOSUPPORT; - *h_errnop = NO_DATA; - return NSS_STATUS_UNAVAIL; + const struct in_addr *address = addr; + char addrstr[INET6_ADDRSTRLEN]; + + sprintf(addrstr, "%s", inet_ntoa(*address)); + debug("Query libnss-resolver: %s - %s", NSSRS_DEFAULT_FOLDER, addrstr); + + struct hostent *hosts = nssrs_resolve(NSSRS_DEFAULT_FOLDER, addrstr); + + if (!hosts || hosts->h_name == NULL) { + *errnop = ENOENT; + *h_errnop = HOST_NOT_FOUND; + if (hosts) { + ares_free_hostent(hosts); + } + debug("Host not found"); + return NSS_STATUS_NOTFOUND; + } + + int ok = pack_hostent(result, buffer, buflen, hosts); + ares_free_hostent(hosts); + + if(ok == NSS_STATUS_TRYAGAIN) + { + *errnop = ERANGE; + *h_errnop = TRY_AGAIN; + } + return ok; } diff --git a/src/resolver.c b/src/resolver.c index 0b16ac2..3b6e772 100644 --- a/src/resolver.c +++ b/src/resolver.c @@ -39,7 +39,7 @@ static char **copy_list(char **list) { count++; } - debug("list size: %d\n", count); + debug("list size: %d", count); new_list = malloc((count+1) * sizeof(char *)); for (p = list; *p; p++) { new_list[index] = malloc(sizeof(struct in_addr)); @@ -53,12 +53,24 @@ static char **copy_list(char **list) { return new_list; } +static char ** copy_string_list(char ** list) +{ + char ** new_list = NULL; + int count = 0; + for(char** s = list; list != NULL && *s != NULL; s++) count++; + new_list = malloc((count+1) * sizeof(char*)); + for(count = 0; list != NULL && list[count] != NULL; count++) + new_list[count] = strdup(list[count]); + new_list[count] = NULL; + return new_list; +} + void nssrs_copy_hostent(struct hostent *from, struct hostent *to) { if (from->h_name != NULL) { to->h_name = strdup(from->h_name); to->h_addrtype = from->h_addrtype; to->h_length = from->h_length; - to->h_aliases = copy_list(from->h_aliases); + to->h_aliases = copy_string_list(from->h_aliases); to->h_addr_list = copy_list(from->h_addr_list); } } @@ -88,6 +100,7 @@ struct hostent *nssrs_resolver_by_servers(char *name, char *nameserver) { int status, optmask = 0; struct ares_options options; struct hostent *results; + struct in_addr inet_address; status = ares_library_init(ARES_LIB_INIT_ALL); if (status != ARES_SUCCESS) { @@ -95,9 +108,12 @@ struct hostent *nssrs_resolver_by_servers(char *name, char *nameserver) { return NULL; } - optmask = ARES_OPT_SERVERS | ARES_OPT_UDP_PORT; + optmask = ARES_OPT_SERVERS | ARES_OPT_UDP_PORT | ARES_OPT_TCP_PORT; + memset(&options, 0, sizeof(options)); options.servers = NULL; options.nservers = 0; + options.tcp_port = 53; + options.udp_port = 53; options.flags = ARES_FLAG_NOCHECKRESP; status = ares_init_options(&channel, &options, optmask); @@ -117,11 +133,22 @@ struct hostent *nssrs_resolver_by_servers(char *name, char *nameserver) { // Wait resolver results = malloc(sizeof(struct hostent)); nssrs_init_hostent(results); - ares_gethostbyname(channel, name, AF_INET, &callback, results); + if(inet_aton(name, &inet_address) != 0) + { + ares_gethostbyaddr(channel, &inet_address, sizeof(inet_address), AF_INET, &callback, results); + } + else + { + ares_gethostbyname(channel, name, AF_INET, &callback, results); + } wait_ares(channel); ares_destroy(channel); ares_library_cleanup(); + debug("h_name: %s", results->h_name); + for(char** alias = results->h_aliases; results->h_aliases != NULL && *alias != NULL; alias++) + debug("h_alias: %s", *alias); + if (results->h_name != NULL) { return results; } @@ -132,7 +159,33 @@ struct hostent *nssrs_resolver_by_servers(char *name, char *nameserver) { struct hostent *nssrs_resolve(char *folder, char *domain) { struct hostent *results = NULL; - char *file = nssrs_getfile_by_sufix(folder, domain); + char *file; + struct in_addr inet_address; + + if(inet_aton(domain, &inet_address)) + { + /* Make PTR address from IPv4 */ + char ptraddr[29]; + memset(ptraddr, 0, sizeof(ptraddr)); + char *dot = domain + strlen(domain); + while(dot >= domain) + { + if(dot[0] == '.' || dot == domain) + { + char *octet = dot + 1; + if(dot == domain) octet = domain; + int len = (char*)strchrnul(octet, '.') - octet + 2; + snprintf(ptraddr + strlen(ptraddr), len, "%s.", octet); + } + dot--; + } + strcat(ptraddr, "in-addr.arpa"); + file = nssrs_getfile_by_sufix(folder, ptraddr); + } + else + { + file = nssrs_getfile_by_sufix(folder, domain); + } if (file) { debug("resolver file: %s", file); @@ -150,7 +203,7 @@ struct hostent *nssrs_resolve(char *folder, char *domain) { for (i = 0; results->h_addr_list[i]; ++i) { inet_ntop(results->h_addrtype, results->h_addr_list[i], ip, sizeof(ip)); - debug("ip: %s\n", ip); + debug("ip: %s", ip); } } #endif