summaryrefslogtreecommitdiff
path: root/tools/nss
diff options
context:
space:
mode:
authorMichal Privoznik <mprivozn@redhat.com>2016-02-14 08:13:54 +0100
committerMichal Privoznik <mprivozn@redhat.com>2016-03-18 17:29:53 +0100
commit917038c110b67648c112f588d2a130ba33ed0bf9 (patch)
treef3a79a347b1e1c33f384ef306e9bce6cac28716c /tools/nss
parent7dbcb26f7f67b9ff2bee47e6144763a3d729717e (diff)
downloadlibvirt-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.c95
-rw-r--r--tools/nss/libvirt_nss.h4
-rw-r--r--tools/nss/libvirt_nss.syms1
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: *;
};