aboutsummaryrefslogtreecommitdiff
path: root/nis/nss_nis
diff options
context:
space:
mode:
Diffstat (limited to 'nis/nss_nis')
-rw-r--r--nis/nss_nis/nis-service.c174
1 files changed, 120 insertions, 54 deletions
diff --git a/nis/nss_nis/nis-service.c b/nis/nss_nis/nis-service.c
index 9af9fd2..b0a6236 100644
--- a/nis/nss_nis/nis-service.c
+++ b/nis/nss_nis/nis-service.c
@@ -51,6 +51,18 @@ typedef struct intern_t intern_t;
static intern_t intern = { NULL, NULL };
+struct search_t
+{
+ const char *name;
+ const char *proto;
+ int port;
+ enum nss_status status;
+ struct servent *serv;
+ char *buffer;
+ size_t buflen;
+ int *errnop;
+};
+
static int
saveit (int instatus, char *inkey, int inkeylen, char *inval,
int invallen, char *indata)
@@ -80,6 +92,68 @@ saveit (int instatus, char *inkey, int inkeylen, char *inval,
return 0;
}
+static int
+dosearch (int instatus, char *inkey, int inkeylen, char *inval,
+ int invallen, char *indata)
+{
+ struct search_t *req = (struct search_t *) indata;
+
+ if (instatus != YP_TRUE)
+ return 1;
+
+ if (inkey && inkeylen > 0 && inval && invallen > 0)
+ {
+ struct parser_data *pdata = (void *) req->buffer;
+ int parse_res;
+ char *p;
+
+ if ((size_t) (invallen + 1) > req->buflen)
+ {
+ *req->errnop = ERANGE;
+ req->status = NSS_STATUS_TRYAGAIN;
+ return 1;
+ }
+
+ p = strncpy (req->buffer, inval, invallen);
+ req->buffer[invallen] = '\0';
+ while (isspace (*p))
+ ++p;
+
+ parse_res = _nss_files_parse_servent (p, req->serv, pdata, req->buflen,
+ req->errnop);
+ if (parse_res == -1)
+ {
+ req->status = NSS_STATUS_TRYAGAIN;
+ return 1;
+ }
+
+ if (!parse_res)
+ return 0;
+
+ if (req->proto != NULL && strcmp (req->serv->s_proto, req->proto) != 0)
+ return 0;
+
+ if (req->port != -1 && req->serv->s_port != req->port)
+ return 0;
+
+ if (req->name != NULL && strcmp (req->serv->s_name, req->name) != 0)
+ {
+ char **cp;
+ for (cp = req->serv->s_aliases; *cp; cp++)
+ if (strcmp (req->name, *cp) == 0)
+ break;
+
+ if (*cp == NULL)
+ return 0;
+ }
+
+ req->status = NSS_STATUS_SUCCESS;
+ return 1;
+ }
+
+ return 0;
+}
+
static enum nss_status
internal_nis_endservent (intern_t * intern)
{
@@ -126,6 +200,7 @@ internal_nis_setservent (intern_t *intern)
return status;
}
+
enum nss_status
_nss_nis_setservent (int stayopen)
{
@@ -191,9 +266,8 @@ _nss_nis_getservbyname_r (const char *name, const char *protocol,
struct servent *serv, char *buffer, size_t buflen,
int *errnop)
{
- intern_t data = { NULL, NULL };
enum nss_status status;
- int found;
+ char *domain;
if (name == NULL)
{
@@ -201,19 +275,18 @@ _nss_nis_getservbyname_r (const char *name, const char *protocol,
return NSS_STATUS_UNAVAIL;
}
+ if (yp_get_default_domain (&domain))
+ return NSS_STATUS_UNAVAIL;
+
/* If the protocol is given, we could try if our NIS server knows
about services.byservicename map. If yes, we only need one query */
if (protocol != NULL)
{
char key[strlen (name) + strlen (protocol) + 2];
- char *cp, *domain, *result;
+ char *cp, *result;
size_t keylen, len;
int int_len;
- /* If this fails, the other solution will also fail. */
- if (yp_get_default_domain (&domain))
- return NSS_STATUS_UNAVAIL;
-
/* key is: "name/protocol" */
cp = stpcpy (key, name);
*cp++ = '/';
@@ -257,34 +330,25 @@ _nss_nis_getservbyname_r (const char *name, const char *protocol,
}
}
- status = internal_nis_setservent (&data);
+ struct ypall_callback ypcb;
+ struct search_t req;
+
+ ypcb.foreach = dosearch;
+ ypcb.data = (char *) &req;
+ req.name = name;
+ req.proto = protocol;
+ req.port = -1;
+ req.serv = serv;
+ req.buffer = buffer;
+ req.buflen = buflen;
+ req.errnop = errnop;
+ req.status = NSS_STATUS_NOTFOUND;
+ status = yperr2nss (yp_all (domain, "services.byservicename", &ypcb));
+
if (status != NSS_STATUS_SUCCESS)
return status;
- found = 0;
- while (!found &&
- ((status = internal_nis_getservent_r (serv, buffer, buflen, errnop,
- &data)) == NSS_STATUS_SUCCESS))
- {
- if (protocol == NULL || strcmp (serv->s_proto, protocol) == 0)
- {
- char **cp;
-
- if (strcmp (serv->s_name, name) == 0)
- found = 1;
- else
- for (cp = serv->s_aliases; *cp; cp++)
- if (strcmp (name, *cp) == 0)
- found = 1;
- }
- }
-
- internal_nis_endservent (&data);
-
- if (!found && status == NSS_STATUS_SUCCESS)
- return NSS_STATUS_NOTFOUND;
- else
- return status;
+ return req.status;
}
enum nss_status
@@ -292,22 +356,20 @@ _nss_nis_getservbyport_r (int port, const char *protocol,
struct servent *serv, char *buffer,
size_t buflen, int *errnop)
{
- intern_t data = { NULL, NULL };
enum nss_status status;
- int found;
+ char *domain;
+
+ if (yp_get_default_domain (&domain))
+ return NSS_STATUS_UNAVAIL;
/* If the protocol is given, we only need one query */
if (protocol != NULL)
{
char key[100 + strlen (protocol) + 2];
- char *domain, *result;
+ char *result;
size_t keylen, len;
int int_len;
- /* If this fails, the other solution will also fail. */
- if (yp_get_default_domain (&domain))
- return NSS_STATUS_UNAVAIL;
-
/* key is: "port/protocol" */
keylen = snprintf (key, sizeof (key), "%d/%s", port, protocol);
status = yperr2nss (yp_match (domain, "services.byname", key,
@@ -348,22 +410,26 @@ _nss_nis_getservbyport_r (int port, const char *protocol,
}
}
- status = internal_nis_setservent (&data);
- if (status != NSS_STATUS_SUCCESS)
- return status;
-
- found = 0;
- while (!found &&
- ((status = internal_nis_getservent_r (serv, buffer, buflen, errnop,
- &data)) == NSS_STATUS_SUCCESS))
- if (serv->s_port == port &&
- (protocol == NULL || strcmp (serv->s_proto, protocol) == 0))
- found = 1;
+ if (port == -1)
+ return NSS_STATUS_NOTFOUND;
- internal_nis_endservent (&data);
+ struct ypall_callback ypcb;
+ struct search_t req;
+
+ ypcb.foreach = dosearch;
+ ypcb.data = (char *) &req;
+ req.name = NULL;
+ req.proto = protocol;
+ req.port = port;
+ req.serv = serv;
+ req.buffer = buffer;
+ req.buflen = buflen;
+ req.errnop = errnop;
+ req.status = NSS_STATUS_NOTFOUND;
+ status = yperr2nss (yp_all (domain, "services.byname", &ypcb));
- if (!found && status == NSS_STATUS_SUCCESS)
- return NSS_STATUS_NOTFOUND;
- else
+ if (status != NSS_STATUS_SUCCESS)
return status;
+
+ return req.status;
}