diff options
author | Michal Privoznik <mprivozn@redhat.com> | 2016-02-14 08:13:54 +0100 |
---|---|---|
committer | Michal Privoznik <mprivozn@redhat.com> | 2016-03-18 17:29:53 +0100 |
commit | 917038c110b67648c112f588d2a130ba33ed0bf9 (patch) | |
tree | f3a79a347b1e1c33f384ef306e9bce6cac28716c /tools/nss | |
parent | 7dbcb26f7f67b9ff2bee47e6144763a3d729717e (diff) | |
download | libvirt-917038c110b67648c112f588d2a130ba33ed0bf9.tar.gz |
Implement _nss_libvirt_gethostbyname4_r
This function is a different beast compared to previous ones.
But yet again, nothing surprising is happening here.
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Diffstat (limited to 'tools/nss')
-rw-r--r-- | tools/nss/libvirt_nss.c | 95 | ||||
-rw-r--r-- | tools/nss/libvirt_nss.h | 4 | ||||
-rw-r--r-- | tools/nss/libvirt_nss.syms | 1 |
3 files changed, 100 insertions, 0 deletions
diff --git a/tools/nss/libvirt_nss.c b/tools/nss/libvirt_nss.c index 1b9ccba607..ba3bb31b35 100644 --- a/tools/nss/libvirt_nss.c +++ b/tools/nss/libvirt_nss.c @@ -364,3 +364,98 @@ _nss_libvirt_gethostbyname3_r(const char *name, int af, struct hostent *result, VIR_FREE(addr); return ret; } + +enum nss_status +_nss_libvirt_gethostbyname4_r(const char *name, struct gaih_addrtuple **pat, + char *buffer, size_t buflen, int *errnop, + int *herrnop, int32_t *ttlp) +{ + enum nss_status ret = NSS_STATUS_UNAVAIL; + leaseAddress *addr = NULL; + size_t naddr, i; + bool found = false; + int r; + size_t nameLen, need, idx; + struct gaih_addrtuple *r_tuple, *r_tuple_first = NULL; + char *r_name; + + if ((r = findLease(name, AF_UNSPEC, &addr, &naddr, &found, errnop)) < 0) { + /* Error occurred. Return immediately. */ + if (*errnop == EAGAIN) { + *herrnop = TRY_AGAIN; + return NSS_STATUS_TRYAGAIN; + } else { + *herrnop = NO_RECOVERY; + return NSS_STATUS_UNAVAIL; + } + } + + if (!found) { + /* NOT found */ + *errnop = ESRCH; + *herrnop = HOST_NOT_FOUND; + return NSS_STATUS_NOTFOUND; + } else if (!naddr) { + /* Found, but no data */ + *errnop = ENXIO; + *herrnop = NO_DATA; + return NSS_STATUS_UNAVAIL; + } + + /* Found and have data */ + + nameLen = strlen(name); + /* We need space for: + * a) name + * b) addresses */ + need = ALIGN(nameLen + 1) + naddr * ALIGN(sizeof(struct gaih_addrtuple)); + + if (buflen < need) { + *errnop = ENOMEM; + *herrnop = TRY_AGAIN; + ret = NSS_STATUS_TRYAGAIN; + goto cleanup; + } + + /* First, append name */ + r_name = buffer; + memcpy(r_name, name, nameLen + 1); + idx = ALIGN(nameLen + 1); + + + /* Second, append addresses */ + r_tuple_first = (struct gaih_addrtuple*) (buffer + idx); + for (i = 0; i < naddr; i++) { + int family = addr[i].af; + + r_tuple = (struct gaih_addrtuple*) (buffer + idx); + if (i == naddr - 1) + r_tuple->next = NULL; + else + r_tuple->next = (struct gaih_addrtuple*) ((char*) r_tuple + ALIGN(sizeof(struct gaih_addrtuple))); + r_tuple->name = r_name; + r_tuple->family = family; + r_tuple->scopeid = 0; + memcpy(r_tuple->addr, addr[i].addr, FAMILY_ADDRESS_SIZE(family)); + + idx += ALIGN(sizeof(struct gaih_addrtuple)); + } + + /* At this point, idx == need */ + DEBUG("Done idx:%zd need:%zd", idx, need); + + if (*pat) + **pat = *r_tuple_first; + else + *pat = r_tuple_first; + + if (ttlp) + *ttlp = 0; + + /* Explicitly reset all error variables */ + *errnop = 0; + *herrnop = NETDB_SUCCESS; + ret = NSS_STATUS_SUCCESS; + cleanup: + return ret; +} diff --git a/tools/nss/libvirt_nss.h b/tools/nss/libvirt_nss.h index dd037f555c..589c1e6e09 100644 --- a/tools/nss/libvirt_nss.h +++ b/tools/nss/libvirt_nss.h @@ -45,4 +45,8 @@ enum nss_status _nss_libvirt_gethostbyname3_r(const char *name, int af, struct hostent *result, char *buffer, size_t buflen, int *errnop, int *herrnop, int32_t *ttlp, char **canonp); +enum nss_status +_nss_libvirt_gethostbyname4_r(const char *name, struct gaih_addrtuple **pat, + char *buffer, size_t buflen, int *errnop, + int *herrnop, int32_t *ttlp); #endif /* __LIBVIRT_NSS_H__ */ diff --git a/tools/nss/libvirt_nss.syms b/tools/nss/libvirt_nss.syms index b88b8be3a0..5a793e47e6 100644 --- a/tools/nss/libvirt_nss.syms +++ b/tools/nss/libvirt_nss.syms @@ -7,5 +7,6 @@ global: _nss_libvirt_gethostbyname_r; _nss_libvirt_gethostbyname2_r; _nss_libvirt_gethostbyname3_r; + _nss_libvirt_gethostbyname4_r; local: *; }; |