diff options
Diffstat (limited to 'nis')
-rw-r--r-- | nis/nss_compat/compat-grp.c | 12 | ||||
-rw-r--r-- | nis/nss_compat/compat-initgroups.c | 6 | ||||
-rw-r--r-- | nis/nss_compat/compat-spwd.c | 23 | ||||
-rw-r--r-- | nis/nss_nis/nis-alias.c | 5 | ||||
-rw-r--r-- | nis/nss_nis/nis-ethers.c | 9 | ||||
-rw-r--r-- | nis/nss_nis/nis-grp.c | 6 | ||||
-rw-r--r-- | nis/nss_nis/nis-hosts.c | 6 | ||||
-rw-r--r-- | nis/nss_nis/nis-netgrp.c | 9 | ||||
-rw-r--r-- | nis/nss_nis/nis-publickey.c | 33 | ||||
-rw-r--r-- | nis/nss_nis/nis-service.c | 115 | ||||
-rw-r--r-- | nis/ypclnt.c | 358 |
11 files changed, 373 insertions, 209 deletions
diff --git a/nis/nss_compat/compat-grp.c b/nis/nss_compat/compat-grp.c index ac56f6f..2de4608 100644 --- a/nis/nss_compat/compat-grp.c +++ b/nis/nss_compat/compat-grp.c @@ -1,6 +1,6 @@ /* Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc. This file is part of the GNU C Library. - Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1996. + Contributed by Thorsten Kukuk <kukuk@suse.de>, 1996. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as @@ -730,7 +730,10 @@ _nss_compat_getgrnam_r (const char *name, struct group *grp, enum nss_status status; if (name[0] == '-' || name[0] == '+') - return NSS_STATUS_NOTFOUND; + { + *errnop = ENOENT; + return NSS_STATUS_NOTFOUND; + } __libc_lock_lock (lock); @@ -915,7 +918,10 @@ internal_getgrgid_r (gid_t gid, struct group *result, ent_t *ent, status = getgrgid_plusgroup (gid, result, buffer, buflen, errnop); if (status == NSS_STATUS_RETURN) /* We couldn't parse the entry */ - return NSS_STATUS_NOTFOUND; + { + *errnop = ENOENT; + return NSS_STATUS_NOTFOUND; + } else return status; } diff --git a/nis/nss_compat/compat-initgroups.c b/nis/nss_compat/compat-initgroups.c index 47b395e..d4c3422 100644 --- a/nis/nss_compat/compat-initgroups.c +++ b/nis/nss_compat/compat-initgroups.c @@ -263,6 +263,7 @@ getgrent_next_nis (struct group *result, ent_t *ent, char *buffer, if (yp_get_default_domain (&domain) != YPERR_SUCCESS) { ent->nis = 0; + *errnop = ENOENT; return NSS_STATUS_NOTFOUND; } @@ -445,7 +446,10 @@ getgrnam_plusgroup (const char *name, struct group *result, char *buffer, ++p; parse_res = _nss_files_parse_grent (p, result, data, buflen, errnop); if (parse_res == -1) - return NSS_STATUS_TRYAGAIN; + { + *errnop = ERANGE; + return NSS_STATUS_TRYAGAIN; + } } if (parse_res) diff --git a/nis/nss_compat/compat-spwd.c b/nis/nss_compat/compat-spwd.c index 1290346..f254fad 100644 --- a/nis/nss_compat/compat-spwd.c +++ b/nis/nss_compat/compat-spwd.c @@ -383,6 +383,7 @@ getspent_next_nis_netgr (const char *name, struct spwd *result, ent_t *ent, if (parse_res == -1) { ent->netgrdata.cursor = saved_cursor; + *errnop = ERANGE; return NSS_STATUS_TRYAGAIN; } @@ -1112,7 +1113,10 @@ internal_getspnam_r (const char *name, struct spwd *result, ent_t *ent, && result->sp_namp[1] != '@') { if (strcmp (&result->sp_namp[1], name) == 0) - return NSS_STATUS_NOTFOUND; + { + *errnop = ENOENT; + return NSS_STATUS_NOTFOUND; + } else continue; } @@ -1128,8 +1132,11 @@ internal_getspnam_r (const char *name, struct spwd *result, ent_t *ent, status = getspnam_plususer (name, result, buffer, buflen, errnop); if (status == NSS_STATUS_RETURN) - /* We couldn't parse the entry */ - return NSS_STATUS_NOTFOUND; + { + /* We couldn't parse the entry */ + *errnop = ENOENT; + return NSS_STATUS_NOTFOUND; + } else return status; } @@ -1142,7 +1149,10 @@ internal_getspnam_r (const char *name, struct spwd *result, ent_t *ent, status = getspnam_plususer (name, result, buffer, buflen, errnop); if (status == NSS_STATUS_RETURN) /* We couldn't parse the entry */ - return NSS_STATUS_NOTFOUND; + { + *errnop = ENOENT; + return NSS_STATUS_NOTFOUND; + } else return status; } @@ -1159,7 +1169,10 @@ _nss_compat_getspnam_r (const char *name, struct spwd *pwd, enum nss_status status; if (name[0] == '-' || name[0] == '+') - return NSS_STATUS_NOTFOUND; + { + *errnop = ENOENT; + return NSS_STATUS_NOTFOUND; + } if (ni == NULL) { diff --git a/nis/nss_nis/nis-alias.c b/nis/nss_nis/nis-alias.c index 64d0bf8..e6e2386 100644 --- a/nis/nss_nis/nis-alias.c +++ b/nis/nss_nis/nis-alias.c @@ -278,7 +278,10 @@ _nss_nis_getaliasbyname_r (const char *name, struct aliasent *alias, if (parse_res == -1) return NSS_STATUS_TRYAGAIN; else - return NSS_STATUS_NOTFOUND; + { + *errnop = ENOENT; + return NSS_STATUS_NOTFOUND; + } } return NSS_STATUS_SUCCESS; diff --git a/nis/nss_nis/nis-ethers.c b/nis/nss_nis/nis-ethers.c index c95f766..c1ea32a 100644 --- a/nis/nss_nis/nis-ethers.c +++ b/nis/nss_nis/nis-ethers.c @@ -1,6 +1,6 @@ -/* Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc. +/* Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc. This file is part of the GNU C Library. - Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1996. + Contributed by Thorsten Kukuk <kukuk@suse.de>, 1996. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as @@ -241,7 +241,10 @@ _nss_nis_gethostton_r (const char *name, struct ether *eth, if (parse_res == -1) return NSS_STATUS_TRYAGAIN; else - return NSS_STATUS_NOTFOUND; + { + *errnop = ENOENT; + return NSS_STATUS_NOTFOUND; + } } return NSS_STATUS_SUCCESS; } diff --git a/nis/nss_nis/nis-grp.c b/nis/nss_nis/nis-grp.c index 6dca66e..62e6b47 100644 --- a/nis/nss_nis/nis-grp.c +++ b/nis/nss_nis/nis-grp.c @@ -1,6 +1,6 @@ -/* Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc. +/* Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc. This file is part of the GNU C Library. - Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1996. + Contributed by Thorsten Kukuk <kukuk@suse.de>, 1996. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as @@ -207,7 +207,7 @@ _nss_nis_getgrnam_r (const char *name, struct group *grp, return NSS_STATUS_TRYAGAIN; else { - *errnop = EAGAIN; + *errnop = ENOENT; return NSS_STATUS_NOTFOUND; } } diff --git a/nis/nss_nis/nis-hosts.c b/nis/nss_nis/nis-hosts.c index 0ddc930..15aff25 100644 --- a/nis/nss_nis/nis-hosts.c +++ b/nis/nss_nis/nis-hosts.c @@ -321,6 +321,7 @@ internal_gethostbyname2_r (const char *name, int af, struct hostent *host, else { *h_errnop = HOST_NOT_FOUND; + *errnop = ENOENT; return NSS_STATUS_NOTFOUND; } } @@ -392,7 +393,10 @@ _nss_nis_gethostbyaddr_r (char *addr, size_t addrlen, int af, *errnop = errno; } if (retval == NSS_STATUS_NOTFOUND) - *h_errnop = HOST_NOT_FOUND; + { + *h_errnop = HOST_NOT_FOUND; + *errnop = ENOENT; + } return retval; } diff --git a/nis/nss_nis/nis-netgrp.c b/nis/nss_nis/nis-netgrp.c index d170b56..0d3ed44 100644 --- a/nis/nss_nis/nis-netgrp.c +++ b/nis/nss_nis/nis-netgrp.c @@ -1,6 +1,6 @@ -/* Copyright (C) 1996, 1997 Free Software Foundation, Inc. +/* Copyright (C) 1996, 1997, 1999 Free Software Foundation, Inc. This file is part of the GNU C Library. - Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1996. + Contributed by Thorsten Kukuk <kukuk@suse.de>, 1996. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as @@ -117,7 +117,10 @@ _nss_nis_getnetgrent_r (struct __netgrent *result, char *buffer, size_t buflen, enum nss_status status; if (cursor == NULL) - return NSS_STATUS_NOTFOUND; + { + *errnop = ENOENT; + return NSS_STATUS_NOTFOUND; + } __libc_lock_lock (lock); diff --git a/nis/nss_nis/nis-publickey.c b/nis/nss_nis/nis-publickey.c index 73afd44..821accf 100644 --- a/nis/nss_nis/nis-publickey.c +++ b/nis/nss_nis/nis-publickey.c @@ -1,6 +1,6 @@ -/* Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc. +/* Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc. This file is part of the GNU C Library. - Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1996. + Contributed by Thorsten Kukuk <kukuk@suse.de>, 1996. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as @@ -50,8 +50,11 @@ _nss_nis_getpublickey (const char *netname, char *pkey, int *errnop) domain = strchr (netname, '@'); if (!domain) - return NSS_STATUS_UNAVAIL; - domain++; + { + *errnop = EINVAL; + return NSS_STATUS_UNAVAIL; + } + ++domain; retval = yperr2nss (yp_match (domain, "publickey.byname", netname, strlen (netname), &result, &len)); @@ -95,8 +98,11 @@ _nss_nis_getsecretkey (const char *netname, char *skey, char *passwd, domain = strchr (netname, '@'); if (!domain) - return NSS_STATUS_UNAVAIL; - domain++; + { + *errnop = EINVAL; + return NSS_STATUS_UNAVAIL; + } + ++domain; retval = yperr2nss (yp_match (domain, "publickey.byname", netname, strlen (netname), &result, &len)); @@ -196,10 +202,13 @@ _nss_nis_netname2user (char netname[MAXNETNAMELEN + 1], uid_t *uidp, domain = strchr (netname, '@'); if (!domain) - return NSS_STATUS_UNAVAIL; + { + *errnop = EINVAL; + return NSS_STATUS_UNAVAIL; + } /* Point past the '@' character */ - domain++; + ++domain; lookup = NULL; yperr = yp_match (domain, "netid.byname", netname, strlen (netname), &lookup, &len); @@ -209,11 +218,13 @@ _nss_nis_netname2user (char netname[MAXNETNAMELEN + 1], uid_t *uidp, break; /* the successful case */ case YPERR_DOMAIN: case YPERR_KEY: + *errnop = ENOENT; return NSS_STATUS_NOTFOUND; case YPERR_MAP: default: return NSS_STATUS_UNAVAIL; } + if (lookup) { enum nss_status err; @@ -224,7 +235,9 @@ _nss_nis_netname2user (char netname[MAXNETNAMELEN + 1], uid_t *uidp, return err; } else - return NSS_STATUS_NOTFOUND; - + { + *errnop = ENOENT; + return NSS_STATUS_NOTFOUND; + } return NSS_STATUS_SUCCESS; } diff --git a/nis/nss_nis/nis-service.c b/nis/nss_nis/nis-service.c index 103b1e4..cece55c 100644 --- a/nis/nss_nis/nis-service.c +++ b/nis/nss_nis/nis-service.c @@ -172,7 +172,7 @@ internal_nis_getservent_r (struct servent *serv, char *buffer, return NSS_STATUS_NOTFOUND; } p = strncpy (buffer, data->next->val, buflen); - while (isspace (*p)) + while (isspace (*p)) ++p; parse_res = _nss_files_parse_servent (p, serv, pdata, buflen, errnop); @@ -215,6 +215,63 @@ _nss_nis_getservbyname_r (const char *name, char *protocol, 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; + size_t keylen, 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++ = '/'; + stpcpy (cp, protocol); + keylen = strlen (key); + status = yperr2nss (yp_match (domain, "services.byservicename", key, + keylen, &result, &len)); + + /* If we found the key, it's ok and parse the result. If not, + fall through and parse the complete table. */ + if (status == NSS_STATUS_SUCCESS) + { + struct parser_data *pdata = (void *) buffer; + int parse_res; + char *p; + + if ((size_t) (len + 1) > buflen) + { + free (result); + *errnop = ERANGE; + return NSS_STATUS_TRYAGAIN; + } + + p = strncpy (buffer, result, len); + buffer[len] = '\0'; + while (isspace (*p)) + ++p; + free (result); + parse_res = _nss_files_parse_servent (p, serv, pdata, + buflen, errnop); + if (parse_res < 0) + { + if (parse_res == -1) + return NSS_STATUS_TRYAGAIN; + else + { + *errnop = ENOENT; + return NSS_STATUS_NOTFOUND; + } + } + else + return NSS_STATUS_SUCCESS; + } + } + status = internal_nis_setservent (&data); if (status != NSS_STATUS_SUCCESS) return status; @@ -256,10 +313,57 @@ _nss_nis_getservbyport_r (int port, char *protocol, struct servent *serv, enum nss_status status; int found; - if (protocol == NULL) + /* If the protocol is given, we only need one query */ + if (protocol != NULL) { - *errnop = EINVAL; - return NSS_STATUS_UNAVAIL; + char key[100 + strlen (protocol) + 2]; + char *domain, *result; + size_t keylen, 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, + keylen, &result, &len)); + + /* If we found the key, it's ok and parse the result. If not, + fall through and parse the complete table. */ + if (status == NSS_STATUS_SUCCESS) + { + struct parser_data *pdata = (void *) buffer; + int parse_res; + char *p; + + if ((size_t) (len + 1) > buflen) + { + free (result); + *errnop = ERANGE; + return NSS_STATUS_TRYAGAIN; + } + + p = strncpy (buffer, result, len); + buffer[len] = '\0'; + while (isspace (*p)) + ++p; + free (result); + parse_res = _nss_files_parse_servent (p, serv, pdata, + buflen, errnop); + if (parse_res < 0) + { + if (parse_res == -1) + return NSS_STATUS_TRYAGAIN; + else + { + *errnop = ENOENT; + return NSS_STATUS_NOTFOUND; + } + } + else + return NSS_STATUS_SUCCESS; + } } status = internal_nis_setservent (&data); @@ -270,7 +374,8 @@ _nss_nis_getservbyport_r (int port, char *protocol, struct servent *serv, while (!found && ((status = internal_nis_getservent_r (serv, buffer, buflen, errnop, &data)) == NSS_STATUS_SUCCESS)) - if (serv->s_port == port && strcmp (serv->s_proto, protocol) == 0) + if (serv->s_port == port && + (protocol == NULL || strcmp (serv->s_proto, protocol) == 0)) found = 1; internal_nis_endservent (&data); diff --git a/nis/ypclnt.c b/nis/ypclnt.c index 1dc9ca3..00d0f8b 100644 --- a/nis/ypclnt.c +++ b/nis/ypclnt.c @@ -1,6 +1,6 @@ /* Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc. This file is part of the GNU C Library. - Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1996. + Contributed by Thorsten Kukuk <kukuk@suse.de>, 1996. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as @@ -42,7 +42,6 @@ struct dom_binding struct sockaddr_in dom_server_addr; int dom_socket; CLIENT *dom_client; - long int dom_vers; }; typedef struct dom_binding dom_binding; @@ -63,7 +62,6 @@ __yp_bind (const char *domain, dom_binding **ypdb) int clnt_sock; CLIENT *client; int is_new = 0; - int try; if (domain == NULL || domain[0] == '\0') return YPERR_BADARGS; @@ -83,137 +81,127 @@ __yp_bind (const char *domain, dom_binding **ypdb) { is_new = 1; ysd = (dom_binding *) calloc (1, sizeof *ysd); - ysd->dom_socket = -1; - ysd->dom_vers = -1; } - try = 0; - - do - { - ++try; - if (try > MAXTRIES) - { - if (is_new) - free (ysd); - return YPERR_YPBIND; - } - #if USE_BINDINGDIR - if (ysd->dom_vers < 1 && try == 1) /* Try binding dir only first time */ + if (ysd->dom_client == NULL) + { + /* Try binding dir at first if we have no binding */ + char path[sizeof (BINDINGDIR) + strlen (domain) + 10]; + struct iovec vec[2]; + unsigned short port; + int fd; + + sprintf (path, "%s/%s.%d", BINDINGDIR, domain, YPBINDVERS); + fd = open (path, O_RDONLY); + if (fd >= 0) { - char path[sizeof (BINDINGDIR) - 1 + strlen (domain) + 10]; - struct iovec vec[2]; - unsigned short port; - int fd; - - sprintf (path, "%s/%s.%d", BINDINGDIR, domain, YPBINDVERS); - fd = open (path, O_RDONLY); - if (fd >= 0) + /* We have a binding file and could save a RPC call */ + vec[0].iov_base = &port; + vec[0].iov_len = sizeof (port); + vec[1].iov_base = &ypbr; + vec[1].iov_len = sizeof (ypbr); + + if (readv (fd, vec, 2) == sizeof (port) + sizeof (ypbr)) { - /* We have a binding file and could save a RPC call */ - vec[0].iov_base = &port; - vec[0].iov_len = sizeof (port); - vec[1].iov_base = &ypbr; - vec[1].iov_len = sizeof (ypbr); - - if (readv (fd, vec, 2) == sizeof (port) + sizeof (ypbr)) - { - ysd->dom_server_addr.sin_family = AF_INET; - memcpy (&ysd->dom_server_addr.sin_port, - ypbr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_port, - sizeof (ysd->dom_server_addr.sin_port)); - memcpy (&ysd->dom_server_addr.sin_addr.s_addr, - ypbr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_addr, - sizeof (ysd->dom_server_addr.sin_addr.s_addr)); - ysd->dom_vers = YPVERS; - strncpy (ysd->dom_domain, domain, YPMAXDOMAIN); - ysd->dom_domain[YPMAXDOMAIN] = '\0'; - } - close (fd); + ysd->dom_server_addr.sin_family = AF_INET; + memcpy (&ysd->dom_server_addr.sin_port, + ypbr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_port, + sizeof (ysd->dom_server_addr.sin_port)); + memcpy (&ysd->dom_server_addr.sin_addr.s_addr, + ypbr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_addr, + sizeof (ysd->dom_server_addr.sin_addr.s_addr)); + strncpy (ysd->dom_domain, domain, YPMAXDOMAIN); + ysd->dom_domain[YPMAXDOMAIN] = '\0'; + + ysd->dom_socket = RPC_ANYSOCK; + ysd->dom_client = clntudp_create (&ysd->dom_server_addr, YPPROG, + YPVERS, UDPTIMEOUT, + &ysd->dom_socket); + + if (ysd->dom_client != NULL) + /* If the program exits, close the socket */ + if (fcntl (ysd->dom_socket, F_SETFD, 1) == -1) + perror ("fcntl: F_SETFD"); } + close (fd); } + } #endif /* USE_BINDINGDIR */ - if (ysd->dom_vers == -1) + if (ysd->dom_client == NULL) + { + memset (&clnt_saddr, '\0', sizeof clnt_saddr); + clnt_saddr.sin_family = AF_INET; + clnt_saddr.sin_addr.s_addr = htonl (INADDR_LOOPBACK); + clnt_sock = RPC_ANYSOCK; + client = clnttcp_create (&clnt_saddr, YPBINDPROG, YPBINDVERS, + &clnt_sock, 0, 0); + if (client == NULL) { - if (ysd->dom_client) - { - clnt_destroy (ysd->dom_client); - ysd->dom_client = NULL; - ysd->dom_socket = -1; - } - memset (&clnt_saddr, '\0', sizeof clnt_saddr); - clnt_saddr.sin_family = AF_INET; - clnt_saddr.sin_addr.s_addr = htonl (INADDR_LOOPBACK); - clnt_sock = RPC_ANYSOCK; - client = clnttcp_create (&clnt_saddr, YPBINDPROG, YPBINDVERS, - &clnt_sock, 0, 0); - if (client == NULL) - { - if (is_new) - free (ysd); - return YPERR_YPBIND; - } - /* - ** Check the port number -- should be < IPPORT_RESERVED. - ** If not, it's possible someone has registered a bogus - ** ypbind with the portmapper and is trying to trick us. - */ - if (ntohs (clnt_saddr.sin_port) >= IPPORT_RESERVED) - { - clnt_destroy (client); - if (is_new) - free (ysd); - return YPERR_YPBIND; - } - - if (clnt_call (client, YPBINDPROC_DOMAIN, - (xdrproc_t) xdr_domainname, (caddr_t) &domain, - (xdrproc_t) xdr_ypbind_resp, - (caddr_t) &ypbr, RPCTIMEOUT) != RPC_SUCCESS) - { - clnt_destroy (client); - if (is_new) - free (ysd); - return YPERR_YPBIND; - } - - clnt_destroy (client); - - if (ypbr.ypbind_status != YPBIND_SUCC_VAL) - { - fprintf (stderr, _("YPBINDPROC_DOMAIN: %s\n"), - ypbinderr_string (ypbr.ypbind_resp_u.ypbind_error)); - if (is_new) - free (ysd); - return YPERR_DOMAIN; - } - memset (&ysd->dom_server_addr, '\0', sizeof ysd->dom_server_addr); - ysd->dom_server_addr.sin_family = AF_INET; - memcpy (&ysd->dom_server_addr.sin_port, - ypbr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_port, - sizeof (ysd->dom_server_addr.sin_port)); - memcpy (&ysd->dom_server_addr.sin_addr.s_addr, - ypbr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_addr, - sizeof (ysd->dom_server_addr.sin_addr.s_addr)); - ysd->dom_vers = YPVERS; - strncpy (ysd->dom_domain, domain, YPMAXDOMAIN); - ysd->dom_domain[YPMAXDOMAIN] = '\0'; - } + if (is_new) + free (ysd); + return YPERR_YPBIND; + } + /* Check the port number -- should be < IPPORT_RESERVED. + If not, it's possible someone has registered a bogus + ypbind with the portmapper and is trying to trick us. */ + if (ntohs (clnt_saddr.sin_port) >= IPPORT_RESERVED) + { + clnt_destroy (client); + if (is_new) + free (ysd); + return YPERR_YPBIND; + } + + if (clnt_call (client, YPBINDPROC_DOMAIN, + (xdrproc_t) xdr_domainname, (caddr_t) &domain, + (xdrproc_t) xdr_ypbind_resp, + (caddr_t) &ypbr, RPCTIMEOUT) != RPC_SUCCESS) + { + clnt_destroy (client); + if (is_new) + free (ysd); + return YPERR_YPBIND; + } + + clnt_destroy (client); + + if (ypbr.ypbind_status != YPBIND_SUCC_VAL) + { + fprintf (stderr, _("YPBINDPROC_DOMAIN: %s\n"), + ypbinderr_string (ypbr.ypbind_resp_u.ypbind_error)); + if (is_new) + free (ysd); + return YPERR_DOMAIN; + } + memset (&ysd->dom_server_addr, '\0', sizeof ysd->dom_server_addr); + ysd->dom_server_addr.sin_family = AF_INET; + memcpy (&ysd->dom_server_addr.sin_port, + ypbr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_port, + sizeof (ysd->dom_server_addr.sin_port)); + memcpy (&ysd->dom_server_addr.sin_addr.s_addr, + ypbr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_addr, + sizeof (ysd->dom_server_addr.sin_addr.s_addr)); + strncpy (ysd->dom_domain, domain, YPMAXDOMAIN); + ysd->dom_domain[YPMAXDOMAIN] = '\0'; ysd->dom_socket = RPC_ANYSOCK; ysd->dom_client = clntudp_create (&ysd->dom_server_addr, YPPROG, YPVERS, UDPTIMEOUT, &ysd->dom_socket); - if (ysd->dom_client == NULL) - ysd->dom_vers = -1; + if (ysd->dom_client != NULL) + /* If the program exits, close the socket */ + if (fcntl (ysd->dom_socket, F_SETFD, 1) == -1) + perror ("fcntl: F_SETFD"); } - while (ysd->dom_client == NULL); - /* If the program exists, close the socket */ - if (fcntl (ysd->dom_socket, F_SETFD, 1) == -1) - perror ("fcntl: F_SETFD"); + if (ysd->dom_client == NULL) + { + if (is_new) + free (ysd); + return YPERR_YPSERV; + } if (is_new && ypdb != NULL) { @@ -229,7 +217,60 @@ __yp_unbind (dom_binding *ydb) { clnt_destroy (ydb->dom_client); ydb->dom_client = NULL; - ydb->dom_socket = -1; +} + +int +yp_bind (const char *indomain) +{ + int status; + + __libc_lock_lock (ypbindlist_lock); + + status = __yp_bind (indomain, &__ypbindlist); + + __libc_lock_unlock (ypbindlist_lock); + + return status; +} + +static void +yp_unbind_locked (const char *indomain) +{ + dom_binding *ydbptr, *ydbptr2; + + ydbptr2 = NULL; + ydbptr = __ypbindlist; + + while (ydbptr != NULL) + { + if (strcmp (ydbptr->dom_domain, indomain) == 0) + { + dom_binding *work; + + work = ydbptr; + if (ydbptr2 == NULL) + __ypbindlist = __ypbindlist->dom_pnext; + else + ydbptr2 = ydbptr->dom_pnext; + __yp_unbind (work); + free (work); + break; + } + ydbptr2 = ydbptr; + ydbptr = ydbptr->dom_pnext; + } +} + +void +yp_unbind (const char *indomain) +{ + __libc_lock_lock (ypbindlist_lock); + + yp_unbind_locked (indomain); + + __libc_lock_unlock (ypbindlist_lock); + + return; } static int @@ -278,14 +319,26 @@ do_ypcall (const char *domain, u_long prog, xdrproc_t xargs, if (result != RPC_SUCCESS) { - clnt_perror (ydb->dom_client, "do_ypcall: clnt_call"); - ydb->dom_vers = -1; - if (!use_ypbindlist) + /* Don't print the error message on the first try. It + could be that we use cached data which is now invalid. */ + if (try != 0) + clnt_perror (ydb->dom_client, "do_ypcall: clnt_call"); + + if (use_ypbindlist) + { + /* We use ypbindlist, and the old cached data is + invalid. unbind now and create a new binding */ + yp_unbind_locked (domain); + __libc_lock_unlock (ypbindlist_lock); + use_ypbindlist = FALSE; + } + else { __yp_unbind (ydb); free (ydb); - ydb = NULL; } + + ydb = NULL; status = YPERR_RPC; } else @@ -311,52 +364,6 @@ do_ypcall (const char *domain, u_long prog, xdrproc_t xargs, return status; } -int -yp_bind (const char *indomain) -{ - int status; - - __libc_lock_lock (ypbindlist_lock); - - status = __yp_bind (indomain, &__ypbindlist); - - __libc_lock_unlock (ypbindlist_lock); - - return status; -} - -void -yp_unbind (const char *indomain) -{ - dom_binding *ydbptr, *ydbptr2; - - __libc_lock_lock (ypbindlist_lock); - - ydbptr2 = NULL; - ydbptr = __ypbindlist; - while (ydbptr != NULL) - { - if (strcmp (ydbptr->dom_domain, indomain) == 0) - { - dom_binding *work; - - work = ydbptr; - if (ydbptr2 == NULL) - __ypbindlist = __ypbindlist->dom_pnext; - else - ydbptr2 = ydbptr->dom_pnext; - __yp_unbind (work); - free (work); - break; - } - ydbptr2 = ydbptr; - ydbptr = ydbptr->dom_pnext; - } - - __libc_lock_unlock (ypbindlist_lock); - - return; -} __libc_lock_define_initialized (static, domainname_lock) @@ -374,7 +381,7 @@ yp_get_default_domain (char **outdomain) result = YPERR_NODOM; else if (strcmp (__ypdomainname, "(none)") == 0) { - /* If domainname is not set, some Systems will return "(none)" */ + /* If domainname is not set, some systems will return "(none)" */ __ypdomainname[0] = '\0'; result = YPERR_NODOM; } @@ -629,6 +636,10 @@ __xdr_ypresp_all (XDR *xdrs, u_long *objp) int keylen = resp.ypresp_all_u.val.key.keydat_len; int vallen = resp.ypresp_all_u.val.val.valdat_len; + /* We are not allowed to modify the key and val data. + But we are allowed to add data behind the buffer, + if we don't modify the length. So add an extra NUL + character to avoid trouble with broken code. */ *objp = YP_TRUE; memcpy (key, resp.ypresp_all_u.val.key.keydat_val, keylen); key[keylen] = '\0'; @@ -640,14 +651,13 @@ __xdr_ypresp_all (XDR *xdrs, u_long *objp) return TRUE; } break; - case YP_NOMORE: - *objp = YP_NOMORE; - xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp); - return TRUE; - break; default: *objp = resp.ypresp_all_u.val.stat; xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp); + /* Sun says we don't need to make this call, but must return + immediatly. Since Solaris makes this call, we will call + the callback function, too. */ + (*ypall_foreach) (*objp, NULL, 0, NULL, 0, ypall_data); return TRUE; } } |