nis_lookup.c revision 61961e0f20c7637a3846bb39786bb9dffa91dfb9
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
*
* This module contains just the core lookup functions.
*/
#include <stdlib.h>
#include <unistd.h>
#include <syslog.h>
#include <string.h>
#include "nis_clnt.h"
#include "nis_local.h"
int (*)(), void *, nis_call_state *);
nis_call_state *);
unsigned __nis_max_hard_lookup_time = 300;
extern int __nis_debug_rpc;
/*
* NOTE : Binding bug : due to the implementation of the
* NIS+ service, when you want to list a directory you
* need to bind not to a server that serves the directory
* object, but to a server that serves the directory itself.
* This will often be different machines.
*
* However, we can mitigate the impact of always trying to
* bind to the table if we're searching a table by checking
* for search criteria. (listing directories can't have a
* search criteria). So if we're a list, and we don't have
* a search criteria, bind to the "name" passed first. Otherwise
* attempt to bind to domain_of(name) first.
*/
int list_op, /* list semantics */
void *cbdata, /* Callback data */
int (*cback)()) /* Callback (for list calls) */
{
int times_thru;
int sec;
int linknum = 0;
nis_result *link_res = 0;
/*
* Allocate a result structure. We also make a local
* copy of the request so that we can reuse it while
* following links (without clobbering the callers copy).
*/
return (NULL);
/*
* Loop until we can't make any more progress on getting
* a good server (or indefinitely if HARDLOOKUP is set).
*/
times_thru = 0;
for (;;) {
/* set state for this lookup */
state.parent_first = 0;
else
/*
* Loop until we get a response from a server or
* until we can no longer get a client handle.
*/
for (;;) {
if ((flags & HARD_LOOKUP) == 0 ||
goto call_done;
}
break;
} else {
/*
* If there is an error in do_list() or
* do_lookup(), they will set res->status.
*/
if (list_op)
else
&state);
/*
* If we get NIS_NOT_ME or NIS_NOTMASTER,
* then we are talking to a server that
* is not up-to-date and we need to try
* a different server. In essence,
* it is equivalent to getting no
* response at all, so we treat it
* as such. __nis_release_server()
* will believe that we got an RPC
* error and will avoid using the
* server.
*/
if (st == RPC_SUCCESS &&
st = RPC_TIMEDOUT;
}
if (st == RPC_SUCCESS)
goto call_done;
}
}
/*
* We did not have any luck with the current
* binding, we we need to try to get a different
* one.
*
* We have to practice an exponential backoff
* to keep this code from abusing the network
* when we run with HARD_LOOKUP enabled.
* __nis_max_hard_lookup_time is max time to
* wait (currently 5 minutes)
*
* Yes this code could be better but it should
* not be called very often either. If it is
* efficiency is the least of your problems.
*/
"NIS+ server for %s not responding, still trying",
times_thru++;
if (sec > __nis_max_hard_lookup_time) {
--times_thru;
}
}
/* accumulate ticks */
/*
* We have a response from a server. If we got a link,
* then follow it (if the FOLLOW_LINKS flag is set).
*/
linknum++;
if (linknum > NIS_MAXLINKS) {
} else {
if (link_res) {
}
return (NULL);
}
}
list_op = 1;
goto follow_link;
}
}
/*
* If we failed following a link, return the link result (but
* set the status to the actual failure.
*/
if (link_res) {
}
} else if (link_res != 0) {
}
return (res);
}
/*
* The rpc.nisd program has a local copy of this function.
* The server tries to resolve lookups in its own data base.
* If it can't, then it goes ahead and calls __nis_remote_lookup().
*/
int list_op, /* list semantics */
void *cbdata, /* Callback data */
int (*cback)()) /* Callback (for list calls) */
{
}
{
return (NULL);
for (;;) {
break;
}
if (__nis_debug_rpc)
if (__nis_debug_rpc >= 2)
xdr_fd_args, (char *)&req,
if (__nis_debug_rpc)
if (status == RPC_SUCCESS)
break;
}
return (res);
}
{
}
{
if (err != NIS_SUCCESS)
return (NULL);
return (res);
}
static
enum clnt_stat
{
int err;
if (cback) {
return (RPC_SUCCESS);
}
}
if (__nis_debug_rpc)
if (__nis_debug_rpc >= 2)
xdr_ib_request, (char *)req,
if (__nis_debug_rpc)
if (__nis_debug_rpc >= 2)
if (stat == RPC_SUCCESS) {
NIS_CALLBACK, 0, clnt);
if (err < 0)
}
/*
* XXX need to check for and handle NIS_NOCALLBACK
* XXX and refresh callback address.
*/
}
return (stat);
}
static
enum clnt_stat
{
if (__nis_debug_rpc)
if (__nis_debug_rpc >= 2)
xdr_ns_request, (char *)&nsr,
if (__nis_debug_rpc)
if (__nis_debug_rpc >= 2)
return (stat);
}