diff options
author | Stephen Gallagher <sgallagh@redhat.com> | 2012-01-23 09:01:25 -0500 |
---|---|---|
committer | Stephen Gallagher <sgallagh@redhat.com> | 2012-01-27 09:02:02 -0500 |
commit | cff6bb5f8ee424b0e3aff74247e103e44075b16a (patch) | |
tree | 1e403045250015d194c652ce9fc36e1111e7bb3f | |
parent | 990b7ebaf67b6d4cc982c805a8ec1126111bd4b4 (diff) | |
download | sssd-cff6bb5f8ee424b0e3aff74247e103e44075b16a.tar.gz sssd-cff6bb5f8ee424b0e3aff74247e103e44075b16a.tar.bz2 sssd-cff6bb5f8ee424b0e3aff74247e103e44075b16a.zip |
NSS: Add client support for [set|get|end]servent()
-rw-r--r-- | src/sss_client/nss_services.c | 129 |
1 files changed, 125 insertions, 4 deletions
diff --git a/src/sss_client/nss_services.c b/src/sss_client/nss_services.c index e6aea58b..3f042b4a 100644 --- a/src/sss_client/nss_services.c +++ b/src/sss_client/nss_services.c @@ -31,6 +31,21 @@ #include <string.h> #include "sss_cli.h" +static struct sss_nss_getservent_data { + size_t len; + size_t ptr; + uint8_t *data; +} sss_nss_getservent_data; + +static void sss_nss_getservent_data_clean(void) { + + if (sss_nss_getservent_data.data != NULL) { + free(sss_nss_getservent_data.data); + sss_nss_getservent_data.data = NULL; + } + sss_nss_getservent_data.len = 0; + sss_nss_getservent_data.ptr = 0; +} /* GETSERVBYNAME Request * @@ -340,22 +355,128 @@ out: enum nss_status _nss_sss_setservent(void) { - return NSS_STATUS_UNAVAIL; + enum nss_status nret; + int errnop; + sss_nss_lock(); + + /* make sure we do not have leftovers, and release memory */ + sss_nss_getservent_data_clean(); + + nret = sss_nss_make_request(SSS_NSS_SETSERVENT, + NULL, NULL, NULL, &errnop); + if (nret != NSS_STATUS_SUCCESS) { + errno = errnop; + } + + sss_nss_unlock(); + return nret; } +static enum nss_status internal_getservent_r(struct servent *result, + char *buffer, size_t buflen, + int *errnop); enum nss_status _nss_sss_getservent_r(struct servent *result, char *buffer, size_t buflen, int *errnop) { - fprintf(stderr, "getservent [%s]\n", buffer); - return NSS_STATUS_UNAVAIL; + enum nss_status nret; + + sss_nss_lock(); + nret = internal_getservent_r(result, buffer, buflen, errnop); + sss_nss_unlock(); + + return nret; +} + +static enum nss_status internal_getservent_r(struct servent *result, + char *buffer, size_t buflen, + int *errnop) +{ + struct sss_cli_req_data rd; + struct sss_nss_svc_rep pwrep; + uint8_t *repbuf; + size_t replen; + enum nss_status nret; + uint32_t num_entries; + int ret; + + /* Caught once glibc passing in buffer == 0x0 */ + if (!buffer || !buflen) return ERANGE; + + /* if there are leftovers return the next one */ + if (sss_nss_getservent_data.data != NULL && + sss_nss_getservent_data.ptr < sss_nss_getservent_data.len) { + + repbuf = sss_nss_getservent_data.data + sss_nss_getservent_data.ptr; + replen = sss_nss_getservent_data.len - sss_nss_getservent_data.ptr; + + pwrep.result = result; + pwrep.buffer = buffer; + pwrep.buflen = buflen; + + ret = sss_nss_getsvc_readrep(&pwrep, repbuf, &replen); + if (ret) { + *errnop = ret; + return NSS_STATUS_TRYAGAIN; + } + + /* advance buffer pointer */ + sss_nss_getservent_data.ptr = sss_nss_getservent_data.len - replen; + + return NSS_STATUS_SUCCESS; + } + + /* release memory if any */ + sss_nss_getservent_data_clean(); + + /* retrieve no more than SSS_NSS_MAX_ENTRIES at a time */ + num_entries = SSS_NSS_MAX_ENTRIES; + rd.len = sizeof(uint32_t); + rd.data = &num_entries; + + nret = sss_nss_make_request(SSS_NSS_GETSERVENT, &rd, + &repbuf, &replen, errnop); + if (nret != NSS_STATUS_SUCCESS) { + return nret; + } + + /* no results if not found */ + if ((((uint32_t *)repbuf)[0] == 0) + || (replen - SVC_METADATA_COUNT == 0)) { + free(repbuf); + return NSS_STATUS_NOTFOUND; + } + + sss_nss_getservent_data.data = repbuf; + sss_nss_getservent_data.len = replen; + + /* skip metadata fields */ + sss_nss_getservent_data.ptr = SVC_METADATA_COUNT; + + /* call again ourselves, this will return the first result */ + return internal_getservent_r(result, buffer, buflen, errnop); } enum nss_status _nss_sss_endservent(void) { - return NSS_STATUS_UNAVAIL; + enum nss_status nret; + int errnop; + + sss_nss_lock(); + + /* make sure we do not have leftovers, and release memory */ + sss_nss_getservent_data_clean(); + + nret = sss_nss_make_request(SSS_NSS_ENDSERVENT, + NULL, NULL, NULL, &errnop); + if (nret != NSS_STATUS_SUCCESS) { + errno = errnop; + } + + sss_nss_unlock(); + return nret; } |