mirror of
https://sourceware.org/git/glibc.git
synced 2024-11-09 23:00:07 +00:00
* nis/ypclnt.c (__yp_bind_client_create): New, small chunk
of duplicated code from __yp_bind. (__yp_bind_file): New, binding dir code from __yp_bind. (__yp_bind_client_create): New, ypbind code from __yp_bind. (__ypclnt_call): New, make NIS query. (do_ypcall): At first use cached data, then try data from binding directory, after this ask ypbind for a working ypserv. Based on a patch from Jeff Bastian <jmbastia@ti.com> and Chris Barrera <cbarrera@ti.com>
This commit is contained in:
parent
fe54a69c1c
commit
57be8a82ed
12
ChangeLog
12
ChangeLog
@ -1,3 +1,15 @@
|
|||||||
|
2004-02-03 Thorsten Kukuk <kukuk@suse.de>
|
||||||
|
|
||||||
|
* nis/ypclnt.c (__yp_bind_client_create): New, small chunk
|
||||||
|
of duplicated code from __yp_bind.
|
||||||
|
(__yp_bind_file): New, binding dir code from __yp_bind.
|
||||||
|
(__yp_bind_client_create): New, ypbind code from __yp_bind.
|
||||||
|
(__ypclnt_call): New, make NIS query.
|
||||||
|
(do_ypcall): At first use cached data, then try data from
|
||||||
|
binding directory, after this ask ypbind for a working ypserv.
|
||||||
|
Based on a patch from Jeff Bastian <jmbastia@ti.com> and
|
||||||
|
Chris Barrera <cbarrera@ti.com>
|
||||||
|
|
||||||
2004-01-19 Roland McGrath <roland@redhat.com>
|
2004-01-19 Roland McGrath <roland@redhat.com>
|
||||||
|
|
||||||
* configure.in: Don't set CCVERSION.
|
* configure.in: Don't set CCVERSION.
|
||||||
|
324
nis/ypclnt.c
324
nis/ypclnt.c
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 1996-2001, 2002, 2003 Free Software Foundation, Inc.
|
/* Copyright (C) 1996-2001, 2002, 2003, 2004 Free Software Foundation, Inc.
|
||||||
This file is part of the GNU C Library.
|
This file is part of the GNU C Library.
|
||||||
Contributed by Thorsten Kukuk <kukuk@suse.de>, 1996.
|
Contributed by Thorsten Kukuk <kukuk@suse.de>, 1996.
|
||||||
|
|
||||||
@ -53,14 +53,112 @@ __libc_lock_define_initialized (static, ypbindlist_lock)
|
|||||||
static dom_binding *__ypbindlist = NULL;
|
static dom_binding *__ypbindlist = NULL;
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
__yp_bind_client_create (const char *domain, dom_binding *ysd,
|
||||||
|
struct ypbind_resp *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));
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
__yp_bind_file (const char *domain, dom_binding *ysd)
|
||||||
|
{
|
||||||
|
struct ypbind_resp ypbr;
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
/* 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))
|
||||||
|
__yp_bind_client_create (domain, ysd, &ypbr);
|
||||||
|
|
||||||
|
close (fd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
__yp_bind (const char *domain, dom_binding **ypdb)
|
__yp_bind_ypbindprog (const char *domain, dom_binding *ysd)
|
||||||
{
|
{
|
||||||
struct sockaddr_in clnt_saddr;
|
struct sockaddr_in clnt_saddr;
|
||||||
struct ypbind_resp ypbr;
|
struct ypbind_resp ypbr;
|
||||||
dom_binding *ysd = NULL;
|
|
||||||
int clnt_sock;
|
int clnt_sock;
|
||||||
CLIENT *client;
|
CLIENT *client;
|
||||||
|
|
||||||
|
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)
|
||||||
|
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);
|
||||||
|
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);
|
||||||
|
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));
|
||||||
|
return YPERR_DOMAIN;
|
||||||
|
}
|
||||||
|
memset (&ysd->dom_server_addr, '\0', sizeof ysd->dom_server_addr);
|
||||||
|
|
||||||
|
__yp_bind_client_create (domain, ysd, &ypbr);
|
||||||
|
|
||||||
|
return YPERR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
__yp_bind (const char *domain, dom_binding **ypdb)
|
||||||
|
{
|
||||||
|
dom_binding *ysd = NULL;
|
||||||
int is_new = 0;
|
int is_new = 0;
|
||||||
|
|
||||||
if (domain == NULL || domain[0] == '\0')
|
if (domain == NULL || domain[0] == '\0')
|
||||||
@ -83,116 +181,20 @@ __yp_bind (const char *domain, dom_binding **ypdb)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if USE_BINDINGDIR
|
#if USE_BINDINGDIR
|
||||||
if (ysd->dom_client == NULL)
|
|
||||||
{
|
|
||||||
/* Try binding dir at first if we have no binding */
|
/* Try binding dir at first if we have no binding */
|
||||||
char path[sizeof (BINDINGDIR) + strlen (domain) + 10];
|
if (ysd->dom_client == NULL)
|
||||||
struct iovec vec[2];
|
__yp_bind_file (domain, ysd);
|
||||||
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))
|
|
||||||
{
|
|
||||||
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 */
|
#endif /* USE_BINDINGDIR */
|
||||||
|
|
||||||
if (ysd->dom_client == NULL)
|
if (ysd->dom_client == NULL)
|
||||||
{
|
{
|
||||||
memset (&clnt_saddr, '\0', sizeof clnt_saddr);
|
int retval = __yp_bind_ypbindprog (domain, ysd);
|
||||||
clnt_saddr.sin_family = AF_INET;
|
if (retval != YPERR_SUCCESS)
|
||||||
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)
|
if (is_new)
|
||||||
free (ysd);
|
free (ysd);
|
||||||
return YPERR_YPBIND;
|
return retval;
|
||||||
}
|
}
|
||||||
/* 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)
|
|
||||||
/* If the program exits, close the socket */
|
|
||||||
if (fcntl (ysd->dom_socket, F_SETFD, 1) == -1)
|
|
||||||
perror ("fcntl: F_SETFD");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ysd->dom_client == NULL)
|
if (ysd->dom_client == NULL)
|
||||||
@ -215,7 +217,6 @@ static void
|
|||||||
__yp_unbind (dom_binding *ydb)
|
__yp_unbind (dom_binding *ydb)
|
||||||
{
|
{
|
||||||
clnt_destroy (ydb->dom_client);
|
clnt_destroy (ydb->dom_client);
|
||||||
ydb->dom_client = NULL;
|
|
||||||
free (ydb);
|
free (ydb);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -272,17 +273,37 @@ yp_unbind (const char *indomain)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
__ypclnt_call (const char *domain, u_long prog, xdrproc_t xargs,
|
||||||
|
caddr_t req, xdrproc_t xres, caddr_t resp, dom_binding **ydb,
|
||||||
|
int print_error)
|
||||||
|
{
|
||||||
|
enum clnt_stat result;
|
||||||
|
|
||||||
|
result = clnt_call ((*ydb)->dom_client, prog,
|
||||||
|
xargs, req, xres, resp, RPCTIMEOUT);
|
||||||
|
|
||||||
|
if (result != RPC_SUCCESS)
|
||||||
|
{
|
||||||
|
/* We don't print an error message, if we try our old,
|
||||||
|
cached data. Only print this for data, which should work. */
|
||||||
|
if (print_error)
|
||||||
|
clnt_perror ((*ydb)->dom_client, "do_ypcall: clnt_call");
|
||||||
|
|
||||||
|
return YPERR_RPC;
|
||||||
|
}
|
||||||
|
|
||||||
|
return YPERR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
do_ypcall (const char *domain, u_long prog, xdrproc_t xargs,
|
do_ypcall (const char *domain, u_long prog, xdrproc_t xargs,
|
||||||
caddr_t req, xdrproc_t xres, caddr_t resp)
|
caddr_t req, xdrproc_t xres, caddr_t resp)
|
||||||
{
|
{
|
||||||
dom_binding *ydb = NULL;
|
dom_binding *ydb;
|
||||||
bool_t use_ypbindlist = FALSE;
|
int status;
|
||||||
int try, status;
|
|
||||||
enum clnt_stat result;
|
|
||||||
int saved_errno = errno;
|
int saved_errno = errno;
|
||||||
|
|
||||||
try = 0;
|
|
||||||
status = YPERR_YPERR;
|
status = YPERR_YPERR;
|
||||||
|
|
||||||
__libc_lock_lock (ypbindlist_lock);
|
__libc_lock_lock (ypbindlist_lock);
|
||||||
@ -296,60 +317,53 @@ do_ypcall (const char *domain, u_long prog, xdrproc_t xargs,
|
|||||||
ydb = ydb->dom_pnext;
|
ydb = ydb->dom_pnext;
|
||||||
}
|
}
|
||||||
if (ydb != NULL)
|
if (ydb != NULL)
|
||||||
use_ypbindlist = TRUE;
|
{
|
||||||
else
|
if (__yp_bind (domain, &ydb) == 0)
|
||||||
__libc_lock_unlock (ypbindlist_lock);
|
{
|
||||||
|
/* Call server, print no error message, do not unbind. */
|
||||||
|
status = __ypclnt_call (domain, prog, xargs, req, xres,
|
||||||
|
resp, &ydb, 0);
|
||||||
|
if (status == YPERR_SUCCESS)
|
||||||
|
{
|
||||||
|
__set_errno (saved_errno);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* 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);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
__libc_lock_unlock (ypbindlist_lock);
|
__libc_lock_unlock (ypbindlist_lock);
|
||||||
|
|
||||||
while (try < MAXTRIES && status != YPERR_SUCCESS)
|
/* First try with cached data failed. Now try to get
|
||||||
|
current data from the system. */
|
||||||
|
ydb = NULL;
|
||||||
|
if (__yp_bind (domain, &ydb) == 0)
|
||||||
{
|
{
|
||||||
if (__yp_bind (domain, &ydb) != 0)
|
status = __ypclnt_call (domain, prog, xargs, req, xres,
|
||||||
|
resp, &ydb, 1);
|
||||||
|
__yp_unbind (ydb);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if USE_BINDINGDIR
|
||||||
|
/* If we support binding dir data, we have a third chance:
|
||||||
|
Ask ypbind. */
|
||||||
|
if (status != YPERR_SUCCESS)
|
||||||
|
{
|
||||||
|
ydb = calloc (1, sizeof (dom_binding));
|
||||||
|
if (__yp_bind_ypbindprog (domain, ydb) == YPERR_SUCCESS)
|
||||||
{
|
{
|
||||||
if (use_ypbindlist)
|
status = __ypclnt_call (domain, prog, xargs, req, xres,
|
||||||
__libc_lock_unlock (ypbindlist_lock);
|
resp, &ydb, 1);
|
||||||
__set_errno (saved_errno);
|
__yp_unbind (ydb);
|
||||||
return YPERR_DOMAIN;
|
|
||||||
}
|
|
||||||
|
|
||||||
result = clnt_call (ydb->dom_client, prog,
|
|
||||||
xargs, req, xres, resp, RPCTIMEOUT);
|
|
||||||
|
|
||||||
if (result != RPC_SUCCESS)
|
|
||||||
{
|
|
||||||
/* 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);
|
|
||||||
|
|
||||||
ydb = NULL;
|
|
||||||
status = YPERR_RPC;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
status = YPERR_SUCCESS;
|
free (ydb);
|
||||||
|
|
||||||
try++;
|
|
||||||
}
|
}
|
||||||
if (use_ypbindlist)
|
#endif
|
||||||
{
|
|
||||||
__libc_lock_unlock (ypbindlist_lock);
|
|
||||||
use_ypbindlist = FALSE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
if (ydb != NULL)
|
|
||||||
__yp_unbind (ydb);
|
|
||||||
|
|
||||||
__set_errno (saved_errno);
|
__set_errno (saved_errno);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user