diff options
Diffstat (limited to 'nis')
-rw-r--r-- | nis/Banner | 2 | ||||
-rw-r--r-- | nis/Makefile | 6 | ||||
-rw-r--r-- | nis/Versions | 7 | ||||
-rw-r--r-- | nis/nis_call.c | 216 | ||||
-rw-r--r-- | nis/nis_checkpoint.c | 2 | ||||
-rw-r--r-- | nis/nis_file.c | 32 | ||||
-rw-r--r-- | nis/nis_findserv.c | 22 | ||||
-rw-r--r-- | nis/nis_intern.h | 35 | ||||
-rw-r--r-- | nis/nis_lookup.c | 166 | ||||
-rw-r--r-- | nis/nis_mkdir.c | 2 | ||||
-rw-r--r-- | nis/nis_ping.c | 2 | ||||
-rw-r--r-- | nis/nis_rmdir.c | 2 | ||||
-rw-r--r-- | nis/nis_server.c | 4 | ||||
-rw-r--r-- | nis/nis_table.c | 399 | ||||
-rw-r--r-- | nis/nis_util.c | 2 | ||||
-rw-r--r-- | nis/rpcsvc/nislib.h | 31 |
16 files changed, 573 insertions, 357 deletions
@@ -1 +1 @@ -NIS(YP)/NIS+ NSS modules 0.17 by Thorsten Kukuk +NIS(YP)/NIS+ NSS modules 0.18 by Thorsten Kukuk diff --git a/nis/Makefile b/nis/Makefile index c736b5a..78fdd07 100644 --- a/nis/Makefile +++ b/nis/Makefile @@ -23,7 +23,7 @@ subdir := nis headers := $(wildcard rpcsvc/*.[hx]) distribute := nss-nis.h nss-nisplus.h nis_intern.h Banner \ - nisplus-parser.h nis_cache2.h nis_xdr.h + nisplus-parser.h nis_xdr.h # These are the databases available for the nis (and perhaps later nisplus) # service. This must be a superset of the services in nss. @@ -44,8 +44,8 @@ vpath %.c $(subdir-dirs) libnsl-routines = yp_xdr ypclnt ypupdate_xdr \ nis_subr nis_local_names nis_free nis_file \ - nis_print nis_error nis_call nis_lookup nis_cache\ - nis_table nis_xdr nis_server nis_ping nis_cache2_xdr\ + nis_print nis_error nis_call nis_lookup\ + nis_table nis_xdr nis_server nis_ping \ nis_checkpoint nis_mkdir nis_rmdir nis_getservlist\ nis_verifygroup nis_ismember nis_addmember nis_util\ nis_removemember nis_creategroup nis_destroygroup\ diff --git a/nis/Versions b/nis/Versions index aa2df3a..d26cba7 100644 --- a/nis/Versions +++ b/nis/Versions @@ -48,9 +48,10 @@ libnsl { # This functions are needed by the NIS+ tools and rpc.nisd, # they should never be used in a normal user program ! - __do_niscall2; __free_fdresult; __nis_default_access; - __nis_default_group; __nis_default_owner; __nis_default_ttl; - __nis_finddirectory; __nis_hash; + __free_fdresult; __nis_default_access; __nis_default_group; + __nis_default_owner; __nis_default_ttl; __nis_finddirectory; + __nis_hash; __nisbind_connect; __nisbind_create; + __nisbind_destroy; __nisbind_next; readColdStartFile; writeColdStartFile; } } diff --git a/nis/nis_call.c b/nis/nis_call.c index 94144d5..ce7607f 100644 --- a/nis/nis_call.c +++ b/nis/nis_call.c @@ -60,8 +60,8 @@ inetstr2int (const char *str) return inet_addr (buffer); } -static void -__bind_destroy (dir_binding *bind) +void +__nisbind_destroy (dir_binding *bind) { if (bind->clnt != NULL) { @@ -71,8 +71,8 @@ __bind_destroy (dir_binding *bind) } } -static nis_error -__bind_next (dir_binding *bind) +nis_error +__nisbind_next (dir_binding *bind) { u_int j; @@ -91,8 +91,7 @@ __bind_next (dir_binding *bind) j < bind->server_val[bind->server_used].ep.ep_len; ++j) if (strcmp (bind->server_val[bind->server_used].ep.ep_val[j].family, "inet") == 0) - if (strcmp (bind->server_val[bind->server_used].ep.ep_val[j].proto, - "-") == 0) + if (bind->server_val[bind->server_used].ep.ep_val[j].proto[0] == '-') { bind->current_ep = j; return NIS_SUCCESS; @@ -115,8 +114,8 @@ __bind_next (dir_binding *bind) return NIS_FAIL; } -static nis_error -__bind_connect (dir_binding *dbp) +nis_error +__nisbind_connect (dir_binding *dbp) { nis_server *serv; @@ -157,7 +156,7 @@ __bind_connect (dir_binding *dbp) if (dbp->use_auth) { - if (serv->key_type == NIS_PK_DH && key_secretkey_is_set ()) + if (serv->key_type == NIS_PK_DH) { char netname[MAXNETNAMELEN+1]; char *p; @@ -180,9 +179,9 @@ __bind_connect (dir_binding *dbp) return NIS_SUCCESS; } -static nis_error -__bind_create (dir_binding *dbp, const nis_server *serv_val, u_int serv_len, - u_long flags, cache2_info *cinfo) +nis_error +__nisbind_create (dir_binding *dbp, const nis_server *serv_val, u_int serv_len, + u_long flags) { dbp->clnt = NULL; @@ -208,54 +207,34 @@ __bind_create (dir_binding *dbp, const nis_server *serv_val, u_int serv_len, dbp->trys = 1; dbp->class = -1; - if (cinfo != NULL && cinfo->server_used >= 0) - { - dbp->server_used = cinfo->server_used; - dbp->current_ep = cinfo->current_ep; - dbp->class = cinfo->class; - } - else if (__nis_findfastest (dbp) < 1) + if (__nis_findfastest (dbp) < 1) { - __bind_destroy (dbp); + __nisbind_destroy (dbp); return NIS_NAMEUNREACHABLE; } return NIS_SUCCESS; } +/* __nisbind_connect (dbp) must be run before calling this function ! + So we could use the same binding twice */ nis_error -__do_niscall2 (const nis_server *server, u_int server_len, u_long prog, - xdrproc_t xargs, caddr_t req, xdrproc_t xres, caddr_t resp, - u_long flags, nis_cb *cb, cache2_info *cinfo) +__do_niscall3 (dir_binding *dbp, u_long prog, xdrproc_t xargs, caddr_t req, + xdrproc_t xres, caddr_t resp, u_long flags, nis_cb *cb) { enum clnt_stat result; nis_error retcode; - dir_binding dbp; - if (flags & MASTER_ONLY) - server_len = 1; - - if (__bind_create (&dbp, server, server_len, flags, cinfo) != NIS_SUCCESS) + if (dbp == NULL) return NIS_NAMEUNREACHABLE; - while (__bind_connect (&dbp) != NIS_SUCCESS) - { - if (__bind_next (&dbp) != NIS_SUCCESS) - { - __bind_destroy (&dbp); - return NIS_NAMEUNREACHABLE; - } - } do { again: - result = clnt_call (dbp.clnt, prog, xargs, req, xres, resp, RPCTIMEOUT); + result = clnt_call (dbp->clnt, prog, xargs, req, xres, resp, RPCTIMEOUT); if (result != RPC_SUCCESS) - { - __bind_destroy (&dbp); - retcode = NIS_RPCERROR; - } + retcode = NIS_RPCERROR; else { switch (prog) @@ -264,11 +243,11 @@ __do_niscall2 (const nis_server *server, u_int server_len, u_long prog, if ((((nis_result *)resp)->status == NIS_CBRESULTS) && (cb != NULL)) { - __nis_do_callback(&dbp, &((nis_result *)resp)->cookie, cb); + __nis_do_callback(dbp, &((nis_result *)resp)->cookie, cb); break; } - /* Yes, this is correct. If we doesn't have to start - a callback, look if we have to search another server */ + /* Yes, the missing break is correct. If we doesn't have to + start a callback, look if we have to search another server */ case NIS_LOOKUP: case NIS_ADD: case NIS_MODIFY: @@ -278,19 +257,16 @@ __do_niscall2 (const nis_server *server, u_int server_len, u_long prog, case NIS_IBREMOVE: case NIS_IBFIRST: case NIS_IBNEXT: - if ((((nis_result *)resp)->status == NIS_NOTFOUND) || + if ((((nis_result *)resp)->status == NIS_SYSTEMERROR) || (((nis_result *)resp)->status == NIS_NOSUCHNAME) || (((nis_result *)resp)->status == NIS_NOT_ME)) { - if (__bind_next (&dbp) == NIS_SUCCESS) + if (__nisbind_next (dbp) == NIS_SUCCESS) { - while (__bind_connect (&dbp) != NIS_SUCCESS) + while (__nisbind_connect (dbp) != NIS_SUCCESS) { - if (__bind_next (&dbp) != NIS_SUCCESS) - { - __bind_destroy (&dbp); + if (__nisbind_next (dbp) != NIS_SUCCESS) return NIS_SUCCESS; - } } } else @@ -299,19 +275,16 @@ __do_niscall2 (const nis_server *server, u_int server_len, u_long prog, } break; case NIS_FINDDIRECTORY: - if ((((fd_result *)resp)->status == NIS_NOTFOUND) || + if ((((fd_result *)resp)->status == NIS_SYSTEMERROR) || (((fd_result *)resp)->status == NIS_NOSUCHNAME) || (((fd_result *)resp)->status == NIS_NOT_ME)) { - if (__bind_next (&dbp) == NIS_SUCCESS) + if (__nisbind_next (dbp) == NIS_SUCCESS) { - while (__bind_connect (&dbp) != NIS_SUCCESS) + while (__nisbind_connect (dbp) != NIS_SUCCESS) { - if (__bind_next (&dbp) != NIS_SUCCESS) - { - __bind_destroy (&dbp); - return NIS_SUCCESS; - } + if (__nisbind_next (dbp) != NIS_SUCCESS) + return NIS_SUCCESS; } } else @@ -321,19 +294,16 @@ __do_niscall2 (const nis_server *server, u_int server_len, u_long prog, break; case NIS_DUMPLOG: /* log_result */ case NIS_DUMP: - if ((((log_result *)resp)->lr_status == NIS_NOTFOUND) || + if ((((log_result *)resp)->lr_status == NIS_SYSTEMERROR) || (((log_result *)resp)->lr_status == NIS_NOSUCHNAME) || (((log_result *)resp)->lr_status == NIS_NOT_ME)) { - if (__bind_next (&dbp) == NIS_SUCCESS) + if (__nisbind_next (dbp) == NIS_SUCCESS) { - while (__bind_connect (&dbp) != NIS_SUCCESS) + while (__nisbind_connect (dbp) != NIS_SUCCESS) { - if (__bind_next (&dbp) != NIS_SUCCESS) - { - __bind_destroy (&dbp); - return NIS_SUCCESS; - } + if (__nisbind_next (dbp) != NIS_SUCCESS) + return NIS_SUCCESS; } } else @@ -344,7 +314,6 @@ __do_niscall2 (const nis_server *server, u_int server_len, u_long prog, default: break; } - __bind_destroy (&dbp); retcode = NIS_SUCCESS; } } @@ -353,9 +322,37 @@ __do_niscall2 (const nis_server *server, u_int server_len, u_long prog, return retcode; } +nis_error +__do_niscall2 (const nis_server *server, u_int server_len, u_long prog, + xdrproc_t xargs, caddr_t req, xdrproc_t xres, caddr_t resp, + u_long flags, nis_cb *cb) +{ + dir_binding dbp; + nis_error status; + + if (flags & MASTER_ONLY) + server_len = 1; + + status = __nisbind_create (&dbp, server, server_len, flags); + if (status != NIS_SUCCESS) + return status; + + while (__nisbind_connect (&dbp) != NIS_SUCCESS) + { + if (__nisbind_next (&dbp) != NIS_SUCCESS) + return NIS_NAMEUNREACHABLE; + } + + status = __do_niscall3 (&dbp, prog, xargs, req, xres, resp, flags, cb); + + __nisbind_destroy (&dbp); + + return status; + +} + static directory_obj * -rec_dirsearch (const_nis_name name, directory_obj *dir, u_long flags, - nis_error *status) +rec_dirsearch (const_nis_name name, directory_obj *dir, nis_error *status) { fd_result *fd_res; XDR xdrs; @@ -396,7 +393,7 @@ rec_dirsearch (const_nis_name name, directory_obj *dir, u_long flags, /* We have found a NIS+ server serving ndomain, now let us search for "name" */ nis_free_directory (dir); - return rec_dirsearch (name, obj, flags, status); + return rec_dirsearch (name, obj, status); } else { @@ -461,7 +458,7 @@ rec_dirsearch (const_nis_name name, directory_obj *dir, u_long flags, /* We have found a NIS+ server serving ndomain, now let us search for "name" */ nis_free_directory (dir); - return rec_dirsearch (name, obj, flags, status); + return rec_dirsearch (name, obj, status); } } break; @@ -478,7 +475,7 @@ rec_dirsearch (const_nis_name name, directory_obj *dir, u_long flags, /* We try to query the current server for the searched object, maybe he know about it ? */ static directory_obj * -first_shoot (const_nis_name name, directory_obj *dir, u_long flags) +first_shoot (const_nis_name name, directory_obj *dir) { directory_obj *obj; fd_result *fd_res; @@ -516,51 +513,57 @@ first_shoot (const_nis_name name, directory_obj *dir, u_long flags) } nis_error -__do_niscall (const_nis_name name, u_long prog, xdrproc_t xargs, - caddr_t req, xdrproc_t xres, caddr_t resp, u_long flags, - nis_cb *cb) +__nisfind_server (const_nis_name name, directory_obj **dir) { - nis_error retcode; - directory_obj *dir = NULL; - nis_server *server; - u_int server_len; - cache2_info cinfo = {-1, -1, -1}; - int saved_errno = errno; - if (name == NULL) return NIS_BADNAME; +#if 0 /* Search in local cache. In the moment, we ignore the fastest server */ if (!(flags & NO_CACHE)) dir = __nis_cache_search (name, flags, &cinfo); +#endif - if (dir == NULL) + if (*dir == NULL) { nis_error status; directory_obj *obj; - dir = readColdStartFile (); - if (dir == NULL) /* No /var/nis/NIS_COLD_START->no NIS+ installed */ - { - __set_errno (saved_errno); - return NIS_UNAVAIL; - } + *dir = readColdStartFile (); + if (*dir == NULL) /* No /var/nis/NIS_COLD_START->no NIS+ installed */ + return NIS_UNAVAIL; /* Try at first, if servers in "dir" know our object */ - obj = first_shoot (name, dir, flags); + obj = first_shoot (name, *dir); if (obj == NULL) { - dir = rec_dirsearch (name, dir, flags, &status); - if (dir == NULL) - { - __set_errno (saved_errno); - return status; - } + *dir = rec_dirsearch (name, *dir, &status); + if (*dir == NULL) + return status; } else - dir = obj; + *dir = obj; } + return NIS_SUCCESS; +} + +nis_error +__do_niscall (const_nis_name name, u_long prog, xdrproc_t xargs, + caddr_t req, xdrproc_t xres, caddr_t resp, u_long flags, + nis_cb *cb) +{ + nis_error retcode; + dir_binding bptr; + directory_obj *dir = NULL; + nis_server *server; + u_int server_len; + int saved_errno = errno; + + retcode = __nisfind_server (name, &dir); + if (retcode != NIS_SUCCESS) + return retcode; + if (flags & MASTER_ONLY) { server = dir->do_servers.do_servers_val; @@ -572,9 +575,22 @@ __do_niscall (const_nis_name name, u_long prog, xdrproc_t xargs, server_len = dir->do_servers.do_servers_len; } + retcode = __nisbind_create (&bptr, server, server_len, flags); + if (retcode == NIS_SUCCESS) + { + while (__nisbind_connect (&bptr) != NIS_SUCCESS) + { + if (__nisbind_next (&bptr) != NIS_SUCCESS) + { + nis_free_directory (dir); + __nisbind_destroy (&bptr); + return NIS_NAMEUNREACHABLE; + } + } + retcode = __do_niscall3 (&bptr, prog, xargs, req, xres, resp, flags, cb); - retcode = __do_niscall2 (server, server_len, prog, xargs, req, xres, resp, - flags, cb, &cinfo); + __nisbind_destroy (&bptr); + } nis_free_directory (dir); diff --git a/nis/nis_checkpoint.c b/nis/nis_checkpoint.c index f1e860f..15bae8b 100644 --- a/nis/nis_checkpoint.c +++ b/nis/nis_checkpoint.c @@ -58,7 +58,7 @@ nis_checkpoint(const_nis_name dirname) if (__do_niscall2 (&NIS_RES_OBJECT(res2)->DI_data.do_servers.do_servers_val[i], 1, NIS_CHECKPOINT, (xdrproc_t) _xdr_nis_name, (caddr_t) &dirname, (xdrproc_t) _xdr_cp_result, - (caddr_t) &cpres, 0, NULL, NULL) != NIS_SUCCESS) + (caddr_t) &cpres, 0, NULL) != NIS_SUCCESS) NIS_RES_STATUS (res) = NIS_RPCERROR; else { diff --git a/nis/nis_file.c b/nis/nis_file.c index 94fa4eb..0ffac68 100644 --- a/nis/nis_file.c +++ b/nis/nis_file.c @@ -31,18 +31,26 @@ readColdStartFile (void) XDR xdrs; FILE *in; bool_t status; - directory_obj obj; + directory_obj *obj = calloc (1, sizeof (directory_obj)); + + if (obj == NULL) + return NULL; in = fopen (cold_start_file, "rb"); if (in == NULL) return NULL; - memset (&obj, '\0', sizeof (obj)); xdrstdio_create (&xdrs, in, XDR_DECODE); - status = _xdr_directory_obj (&xdrs, &obj); + status = _xdr_directory_obj (&xdrs, obj); xdr_destroy (&xdrs); fclose (in); - return status ? nis_clone_directory (&obj, NULL) : NULL; + if (status) + return obj; + else + { + nis_free_directory (obj); + return NULL; + } } bool_t @@ -70,19 +78,27 @@ nis_read_obj (const char *name) XDR xdrs; FILE *in; bool_t status; - nis_object obj; + nis_object *obj = calloc (1, sizeof (nis_object)); + + if (obj == NULL) + return NULL; in = fopen (name, "rb"); if (in == NULL) return NULL; - memset (&obj, '\0', sizeof (obj)); xdrstdio_create (&xdrs, in, XDR_DECODE); - status =_xdr_nis_object (&xdrs, &obj); + status =_xdr_nis_object (&xdrs, obj); xdr_destroy (&xdrs); fclose (in); - return status ? nis_clone_object (&obj, NULL) : NULL; + if (status) + return obj; + else + { + nis_free_object (obj); + return NULL; + } } bool_t diff --git a/nis/nis_findserv.c b/nis/nis_findserv.c index 832b6a5..5b6a749 100644 --- a/nis/nis_findserv.c +++ b/nis/nis_findserv.c @@ -110,8 +110,25 @@ struct findserv_req }; long -__nis_findfastest (dir_binding * bind) +__nis_findfastest (dir_binding *bind) { +#if 0 + unsigned long i, j; + + for (i = 0; i < bind->server_len; i++) + for (j = 0; j < bind->server_val[i].ep.ep_len; ++j) + if (strcmp (bind->server_val[i].ep.ep_val[j].family, "inet") == 0) + if ((bind->server_val[i].ep.ep_val[j].proto == NULL) || + (bind->server_val[i].ep.ep_val[j].proto[0] == '-') || + (bind->server_val[i].ep.ep_val[j].proto[0] == '\0')) + { + bind->server_used = i; + bind->current_ep = j; + return 1; + } + + return 0; +#else const struct timeval TIMEOUT50 = {5, 0}; const struct timeval TIMEOUT00 = {0, 0}; struct findserv_req **pings; @@ -137,7 +154,7 @@ __nis_findfastest (dir_binding * bind) for (j = 0; j < bind->server_val[i].ep.ep_len; ++j) if (strcmp (bind->server_val[i].ep.ep_val[j].family, "inet") == 0) if ((bind->server_val[i].ep.ep_val[j].proto == NULL) || - (strcmp (bind->server_val[i].ep.ep_val[j].proto, "-") == 0) || + (bind->server_val[i].ep.ep_val[j].proto[0] == '-') || (bind->server_val[i].ep.ep_val[j].proto[0] == '\0')) { sin.sin_addr.s_addr = @@ -228,4 +245,5 @@ __nis_findfastest (dir_binding * bind) free (pings); return found; +#endif } diff --git a/nis/nis_intern.h b/nis/nis_intern.h index bea4e272..9f515bb 100644 --- a/nis/nis_intern.h +++ b/nis/nis_intern.h @@ -24,31 +24,6 @@ __BEGIN_DECLS -struct dir_binding -{ - CLIENT *clnt; /* RPC CLIENT handle */ - nis_server *server_val; /* List of servers */ - u_int server_len; /* # of servers */ - u_int server_used; /* Which server we are bind in the moment ? */ - u_int current_ep; /* Which endpoint of the server are in use? */ - u_int trys; /* How many server have we tried ? */ - u_int class; /* From which class is server_val ? */ - bool_t master_only; /* Is only binded to the master */ - bool_t use_auth; /* Do we use AUTH ? */ - bool_t use_udp; /* Do we use UDP ? */ - struct sockaddr_in addr; /* Server's IP address */ - int socket; /* Server's local socket */ -}; -typedef struct dir_binding dir_binding; - -struct cache2_info -{ - long server_used; - long current_ep; - long class; -}; -typedef struct cache2_info cache2_info; - struct nis_cb { nis_server *serv; @@ -66,8 +41,7 @@ extern long __nis_findfastest __P ((dir_binding *bind)); extern nis_error __do_niscall2 __P ((const nis_server *serv, u_int serv_len, u_long prog, xdrproc_t xargs, caddr_t req, xdrproc_t xres, caddr_t resp, - u_long flags, nis_cb *cb, - cache2_info *cinfo)); + u_long flags, nis_cb *cb)); extern nis_error __do_niscall __P ((const_nis_name name, u_long prog, xdrproc_t xargs, caddr_t req, xdrproc_t xres, caddr_t resp, @@ -81,13 +55,6 @@ extern struct nis_cb *__nis_create_callback const void *userdata, u_long flags)); extern nis_error __nis_destroy_callback __P ((struct nis_cb *cb)); -#ifdef _LIBC -/* NIS+ Cache functions */ -extern directory_obj *__nis_cache_search __P ((const_nis_name name, - u_long flags, - cache2_info *cinfo)); -#endif - __END_DECLS #endif diff --git a/nis/nis_lookup.c b/nis/nis_lookup.c index 6a2198a..df16cce 100644 --- a/nis/nis_lookup.c +++ b/nis/nis_lookup.c @@ -25,20 +25,20 @@ nis_result * nis_lookup (const_nis_name name, const u_long flags) { - nis_result *res; + nis_result *res = calloc (1, sizeof (nis_result)); struct ns_request req; nis_name *names; nis_error status; + int link_first_try = 0; int count_links = 0; /* We will follow only 16 links in the deep */ int done = 0; int name_nr = 0; nis_name namebuf[2] = {NULL, NULL}; - res = calloc (1, sizeof (nis_result)); if (res == NULL) return NULL; - if (flags & EXPAND_NAME) + if ((flags & EXPAND_NAME) && (name[strlen (name) - 1] != '.')) { names = nis_getnames (name); if (names == NULL) @@ -56,51 +56,141 @@ nis_lookup (const_nis_name name, const u_long flags) req.ns_name = names[0]; while (!done) { + dir_binding bptr; + directory_obj *dir = NULL; req.ns_object.ns_object_len = 0; req.ns_object.ns_object_val = NULL; - memset (res, '\0', sizeof (nis_result)); - status = __do_niscall (req.ns_name, NIS_LOOKUP, - (xdrproc_t) _xdr_ns_request, - (caddr_t) & req, - (xdrproc_t) _xdr_nis_result, - (caddr_t) res, flags, NULL); + status = __nisfind_server (req.ns_name, &dir); if (status != NIS_SUCCESS) - NIS_RES_STATUS (res) = status; + { + NIS_RES_STATUS (res) = status; + return res; + } - switch (NIS_RES_STATUS (res)) + status = __nisbind_create (&bptr, dir->do_servers.do_servers_val, + dir->do_servers.do_servers_len, flags); + if (status != NIS_SUCCESS) { - case NIS_PARTIAL: - case NIS_SUCCESS: - case NIS_S_SUCCESS: - if (__type_of(NIS_RES_OBJECT (res)) == NIS_LINK_OBJ && - flags & FOLLOW_LINKS) /* We are following links */ + NIS_RES_STATUS (res) = status; + nis_free_directory (dir); + return res; + } + + while (__nisbind_connect (&bptr) != NIS_SUCCESS) + { + if (__nisbind_next (&bptr) != NIS_SUCCESS) + { + __nisbind_destroy (&bptr); + nis_free_directory (dir); + NIS_RES_STATUS (res) = NIS_NAMEUNREACHABLE; + return res; + } + } + + do + { + static struct timeval RPCTIMEOUT = {10, 0}; + enum clnt_stat result; + + again: + result = clnt_call (bptr.clnt, NIS_LOOKUP, + (xdrproc_t) _xdr_ns_request, + (caddr_t) &req, (xdrproc_t) _xdr_nis_result, + (caddr_t) res, RPCTIMEOUT); + + if (result != RPC_SUCCESS) + status = NIS_RPCERROR; + else { - /* if we hit the link limit, bail */ - if (count_links > NIS_MAXLINKS) + if (NIS_RES_STATUS (res) == NIS_SUCCESS) { - NIS_RES_STATUS (res) = NIS_LINKNAMEERROR; - ++done; - break; + if (__type_of(NIS_RES_OBJECT (res)) == NIS_LINK_OBJ && + flags & FOLLOW_LINKS) /* We are following links */ + { + if (count_links) + free (req.ns_name); + /* if we hit the link limit, bail */ + if (count_links > NIS_MAXLINKS) + { + NIS_RES_STATUS (res) = NIS_LINKNAMEERROR; + break; + } + ++count_links; + req.ns_name = + strdup (NIS_RES_OBJECT (res)->LI_data.li_name); + nis_freeresult (res); + res = calloc (1, sizeof (nis_result)); + if (res == NULL) + { + __nisbind_destroy (&bptr); + nis_free_directory (dir); + return NULL; + } + link_first_try = 1; /* Try at first the old binding */ + goto again; + } } - if (count_links) - free (req.ns_name); - ++count_links; - req.ns_name = strdup (NIS_RES_OBJECT (res)->LI_data.li_name); - nis_freeresult (res); - res = calloc (1, sizeof (nis_result)); - if (res == NULL) - return NULL; + else + if ((NIS_RES_STATUS (res) == NIS_SYSTEMERROR) || + (NIS_RES_STATUS (res) == NIS_NOSUCHNAME) || + (NIS_RES_STATUS (res) == NIS_NOT_ME)) + { + if (link_first_try) + { + __nisbind_destroy (&bptr); + nis_free_directory (dir); + + if (__nisfind_server (req.ns_name, &dir) != NIS_SUCCESS) + return res; + + if (__nisbind_create (&bptr, + dir->do_servers.do_servers_val, + dir->do_servers.do_servers_len, + flags) != NIS_SUCCESS) + { + nis_free_directory (dir); + return res; + } + } + else + if (__nisbind_next (&bptr) != NIS_SUCCESS) + break; /* No more servers to search */ + + while (__nisbind_connect (&bptr) != NIS_SUCCESS) + { + if (__nisbind_next (&bptr) != NIS_SUCCESS) + { + __nisbind_destroy (&bptr); + nis_free_directory (dir); + return res; + } + } + goto again; + } + break; } - else - ++done; - break; - case NIS_CBRESULTS: - /* The callback is handled in __do_niscall2 */ - ++done; - break; - case NIS_UNAVAIL: - /* NIS+ is not installed, or all servers are down */ + link_first_try = 0; /* Set it back */ + status= NIS_SUCCESS; + } + while ((flags & HARD_LOOKUP) && status == NIS_RPCERROR); + + __nisbind_destroy (&bptr); + nis_free_directory (dir); + + if (status != NIS_SUCCESS) + { + NIS_RES_STATUS (res) = status; + return res; + } + + switch (NIS_RES_STATUS (res)) + { + case NIS_PARTIAL: + case NIS_SUCCESS: + case NIS_S_SUCCESS: + case NIS_LINKNAMEERROR: /* We follow to max links */ + case NIS_UNAVAIL: /* NIS+ is not installed, or all servers are down */ ++done; break; default: diff --git a/nis/nis_mkdir.c b/nis/nis_mkdir.c index 71fc4ba..5d40dae 100644 --- a/nis/nis_mkdir.c +++ b/nis/nis_mkdir.c @@ -35,7 +35,7 @@ nis_mkdir (const_nis_name dir, const nis_server *server) res2 = __do_niscall2 (server, 1, NIS_MKDIR, (xdrproc_t) _xdr_nis_name, (caddr_t) &dir, (xdrproc_t) _xdr_nis_error, - (caddr_t) &res, 0, NULL, NULL); + (caddr_t) &res, 0, NULL); if (res2 != NIS_SUCCESS) return res2; diff --git a/nis/nis_ping.c b/nis/nis_ping.c index 1becd4b..3fc8755 100644 --- a/nis/nis_ping.c +++ b/nis/nis_ping.c @@ -62,7 +62,7 @@ nis_ping (const_nis_name dirname, u_long utime, const nis_object *dirobj) __do_niscall2 (&obj->DI_data.do_servers.do_servers_val[i], 1, NIS_PING, (xdrproc_t) _xdr_ping_args, (caddr_t) &args, (xdrproc_t) xdr_void, - (caddr_t) NULL, 0, NULL, NULL); + (caddr_t) NULL, 0, NULL); if (res) nis_freeresult (res); } diff --git a/nis/nis_rmdir.c b/nis/nis_rmdir.c index 1f3e918..0cd4458 100644 --- a/nis/nis_rmdir.c +++ b/nis/nis_rmdir.c @@ -33,7 +33,7 @@ nis_rmdir (const_nis_name dir, const nis_server *server) res2 = __do_niscall2 (server, 1, NIS_RMDIR, (xdrproc_t) _xdr_nis_name, (caddr_t) &dir, (xdrproc_t) _xdr_nis_error, - (caddr_t) &res, 0, NULL, NULL); + (caddr_t) &res, 0, NULL); if (res2 != NIS_SUCCESS) return res2; diff --git a/nis/nis_server.c b/nis/nis_server.c index aa0f05e..84cd5fb 100644 --- a/nis/nis_server.c +++ b/nis/nis_server.c @@ -41,7 +41,7 @@ nis_servstate (const nis_server *serv, const nis_tag *tags, if (__do_niscall2 (serv, 1, NIS_SERVSTATE, (xdrproc_t) _xdr_nis_taglist, (caddr_t) &taglist, (xdrproc_t) _xdr_nis_taglist, - (caddr_t) &tagres, 0, NULL, NULL) != RPC_SUCCESS) + (caddr_t) &tagres, 0, NULL) != RPC_SUCCESS) return NIS_RPCERROR; *result = tagres.tags.tags_val; @@ -67,7 +67,7 @@ nis_stats (const nis_server *serv, const nis_tag *tags, if (__do_niscall2 (serv, 1, NIS_STATUS, (xdrproc_t) _xdr_nis_taglist, (caddr_t) &taglist, (xdrproc_t) _xdr_nis_taglist, - (caddr_t) &tagres, 0, NULL, NULL) != RPC_SUCCESS) + (caddr_t) &tagres, 0, NULL) != RPC_SUCCESS) return NIS_RPCERROR; *result = tagres.tags.tags_val; diff --git a/nis/nis_table.c b/nis/nis_table.c index ed4b374..e0885ca 100644 --- a/nis/nis_table.c +++ b/nis/nis_table.c @@ -110,6 +110,40 @@ __create_ib_request (const_nis_name name, u_long flags) return ibreq; } +static struct timeval RPCTIMEOUT = {10, 0}; + +static char * +__get_tablepath (char *name, dir_binding *bptr) +{ + enum clnt_stat result; + nis_result *res = calloc (1, sizeof (nis_result)); + struct ns_request req; + + if (res == NULL) + return NULL; + + req.ns_name = name; + req.ns_object.ns_object_len = 0; + req.ns_object.ns_object_val = NULL; + + result = clnt_call (bptr->clnt, NIS_LOOKUP, (xdrproc_t) _xdr_ns_request, + (caddr_t) &req, (xdrproc_t) _xdr_nis_result, + (caddr_t) res, RPCTIMEOUT); + + if (result == RPC_SUCCESS && NIS_RES_STATUS (res) == NIS_SUCCESS && + __type_of (NIS_RES_OBJECT (res)) == NIS_TABLE_OBJ) + { + char *cptr = strdup (NIS_RES_OBJECT (res)->TA_data.ta_path); + nis_freeresult (res); + return cptr; + } + else + { + nis_freeresult (res); + return strdup (""); + } +} + nis_result * nis_list (const_nis_name name, u_long flags, int (*callback) (const_nis_name name, @@ -120,12 +154,16 @@ nis_list (const_nis_name name, u_long flags, nis_result *res = NULL; ib_request *ibreq; int status; + enum clnt_stat clnt_status; int count_links = 0; /* We will only follow NIS_MAXLINKS links! */ int done = 0; nis_name *names; nis_name namebuf[2] = {NULL, NULL}; int name_nr = 0; nis_cb *cb = NULL; + char *tableptr, *tablepath = NULL; + int have_tablepath = 0; + int first_try = 0; /* Do we try the old binding at first ? */ res = calloc (1, sizeof (nis_result)); if (res == NULL) @@ -164,189 +202,230 @@ nis_list (const_nis_name name, u_long flags, cb = NULL; - if (flags & FOLLOW_PATH || flags & ALL_RESULTS) + while (!done) { - nis_result *lres; - u_long newflags = flags & ~FOLLOW_PATH & ~ALL_RESULTS; - char table_path[NIS_MAXPATH + 3]; - char *ntable, *p; - u_long done = 0, failures = 0; - - while (names[name_nr] != NULL && !done) - { - lres = nis_lookup (names[name_nr], newflags | NO_AUTHINFO); - if (lres == NULL || NIS_RES_STATUS (lres) != NIS_SUCCESS) - { - NIS_RES_STATUS (res) = NIS_RES_STATUS (lres); - nis_freeresult (lres); - ++name_nr; - continue; - } - - /* nis_lookup handles FOLLOW_LINKS, - so we must have a table object.*/ - if (__type_of (NIS_RES_OBJECT (lres)) != NIS_TABLE_OBJ) - { - nis_freeresult (lres); - NIS_RES_STATUS (res) = NIS_INVALIDOBJ; - break; - } + dir_binding bptr; + directory_obj *dir = NULL; - /* Save the path, discard everything else. */ - p = __stpncpy (table_path, names[name_nr], NIS_MAXPATH); - *p++ = ':'; - p = __stpncpy (p, NIS_RES_OBJECT (lres)->TA_data.ta_path, - NIS_MAXPATH - (p - table_path)); - *p = '\0'; - nis_freeresult (lres); - free (res); - res = NULL; + memset (res, '\0', sizeof (nis_result)); - p = table_path; + status = __nisfind_server (ibreq->ibr_name, &dir); + if (status != NIS_SUCCESS) + { + NIS_RES_STATUS (res) = status; + return res; + } - while (((ntable = strsep (&p, ":")) != NULL) && !done) - { - char *c; + status = __nisbind_create (&bptr, dir->do_servers.do_servers_val, + dir->do_servers.do_servers_len, flags); + if (status != NIS_SUCCESS) + { + NIS_RES_STATUS (res) = status; + nis_free_directory (dir); + return res; + } - if (res != NULL) - nis_freeresult (res); + while (__nisbind_connect (&bptr) != NIS_SUCCESS) + if (__nisbind_next (&bptr) != NIS_SUCCESS) + { + __nisbind_destroy (&bptr); + nis_free_directory (dir); + NIS_RES_STATUS (res) = NIS_NAMEUNREACHABLE; + return res; + } - /* Do the job recursive here! */ - if ((c = strchr(name, ']')) != NULL) - { - /* Have indexed name ! */ - int index_len = c - name + 2; - char buf[index_len + strlen (ntable) + 1]; - - c = __stpncpy (buf, name, index_len); - strcpy (c, ntable); - res = nis_list (buf, newflags, callback,userdata); - } - else - res = nis_list (ntable, newflags, callback, userdata); - if (res == NULL) - return NULL; - switch (NIS_RES_STATUS (res)) - { - case NIS_SUCCESS: - case NIS_CBRESULTS: - if (!(flags & ALL_RESULTS)) - done = 1; - break; - case NIS_PARTIAL: /* The table is correct, we doesn't found - the entry */ - break; - default: - if (flags & ALL_RESULTS) - ++failures; - else - done = 1; - break; - } - } - if (NIS_RES_STATUS (res) == NIS_SUCCESS && failures) - NIS_RES_STATUS (res) = NIS_S_SUCCESS; - if (NIS_RES_STATUS (res) == NIS_NOTFOUND && failures) - NIS_RES_STATUS (res) = NIS_S_NOTFOUND; - break; - } - } - else - { if (callback != NULL) { cb = __nis_create_callback (callback, userdata, flags); ibreq->ibr_cbhost.ibr_cbhost_len = 1; ibreq->ibr_cbhost.ibr_cbhost_val = cb->serv; - } - - while (!done) - { - memset (res, '\0', sizeof (nis_result)); - - status = __do_niscall (ibreq->ibr_name, NIS_IBLIST, - (xdrproc_t) _xdr_ib_request, - (caddr_t) ibreq, (xdrproc_t) _xdr_nis_result, - (caddr_t) res, flags, cb); - if (status != NIS_SUCCESS) - NIS_RES_STATUS (res) = status; + } - switch (NIS_RES_STATUS (res)) - { - case NIS_PARTIAL: - case NIS_SUCCESS: - case NIS_S_SUCCESS: - if (__type_of (NIS_RES_OBJECT (res)) == NIS_LINK_OBJ && - flags & FOLLOW_LINKS) /* We are following links. */ - { - /* If we hit the link limit, bail. */ - if (count_links > NIS_MAXLINKS) + again: + clnt_status = clnt_call (bptr.clnt, NIS_IBLIST, + (xdrproc_t) _xdr_ib_request, (caddr_t) ibreq, + (xdrproc_t) _xdr_nis_result, + (caddr_t) res, RPCTIMEOUT); + + if (clnt_status != RPC_SUCCESS) + NIS_RES_STATUS (res) = NIS_RPCERROR; + else + switch (NIS_RES_STATUS (res)) + { /* start switch */ + case NIS_PARTIAL: + case NIS_SUCCESS: + case NIS_S_SUCCESS: + if (__type_of (NIS_RES_OBJECT (res)) == NIS_LINK_OBJ && + flags & FOLLOW_LINKS) /* We are following links. */ + { + free (ibreq->ibr_name); + /* If we hit the link limit, bail. */ + if (count_links > NIS_MAXLINKS) + { + NIS_RES_STATUS (res) = NIS_LINKNAMEERROR; + ++done; + break; + } + ++count_links; + ibreq->ibr_name = + strdup (NIS_RES_OBJECT (res)->LI_data.li_name); + if (NIS_RES_OBJECT (res)->LI_data.li_attrs.li_attrs_len) + if (ibreq->ibr_srch.ibr_srch_len == 0) { - NIS_RES_STATUS (res) = NIS_LINKNAMEERROR; - ++done; - break; + ibreq->ibr_srch.ibr_srch_len = + NIS_RES_OBJECT (res)->LI_data.li_attrs.li_attrs_len; + ibreq->ibr_srch.ibr_srch_val = + NIS_RES_OBJECT (res)->LI_data.li_attrs.li_attrs_val; } - if (count_links) - free (ibreq->ibr_name); - ++count_links; - free (ibreq->ibr_name); - ibreq->ibr_name = - strdup (NIS_RES_OBJECT (res)->LI_data.li_name); - if (NIS_RES_OBJECT (res)->LI_data.li_attrs.li_attrs_len) - if (ibreq->ibr_srch.ibr_srch_len == 0) + nis_freeresult (res); + res = calloc (1, sizeof (nis_result)); + if (res == NULL) + { + if (have_tablepath) + free (tablepath); + __nisbind_destroy (&bptr); + nis_free_directory (dir); + return NULL; + } + first_try = 1; /* Try at first the old binding */ + goto again; + } + else if ((flags & FOLLOW_PATH) && + NIS_RES_STATUS (res) == NIS_PARTIAL) + { + if (!have_tablepath) + { + tablepath = __get_tablepath (ibreq->ibr_name, &bptr); + tableptr = tablepath; + have_tablepath = 1; + } + if (tableptr == NULL) + { + ++done; + break; + } + free (ibreq->ibr_name); + ibreq->ibr_name = strsep (&tableptr, ":"); + if (ibreq->ibr_name == NULL || ibreq->ibr_name[0] == '\0') + { + ibreq->ibr_name = strdup (""); + ++done; + } + else + { + ibreq->ibr_name = strdup (ibreq->ibr_name); + nis_freeresult (res); + res = calloc (1, sizeof (nis_result)); + if (res == NULL) { - ibreq->ibr_srch.ibr_srch_len = - NIS_RES_OBJECT (res)->LI_data.li_attrs.li_attrs_len; - ibreq->ibr_srch.ibr_srch_val = - NIS_RES_OBJECT (res)->LI_data.li_attrs.li_attrs_val; + if (have_tablepath) + free (tablepath); + __nisbind_destroy (&bptr); + nis_free_directory (dir); + return NULL; } - nis_freeresult (res); - res = calloc (1, sizeof (nis_result)); - } - else - ++done; - break; - case NIS_CBRESULTS: - /* Calback is handled in nis_call.c (__do_niscall2), - but we have to change the error code */ - NIS_RES_STATUS (res) = cb->result; + first_try = 1; + goto again; + } + } + else ++done; - break; - case NIS_UNAVAIL: - /* NIS+ is not installed, or all servers are down. */ - ++done; - break; - default: - /* Try the next domainname if we don't follow a link. */ - if (count_links) - { - free (ibreq->ibr_name); - NIS_RES_STATUS (res) = NIS_LINKNAMEERROR; - ++done; - break; - } - ++name_nr; - if (names[name_nr] == NULL) - { + break; + case NIS_CBRESULTS: + if (cb != NULL) + { + __nis_do_callback (&bptr, &res->cookie, cb); + NIS_RES_STATUS (res) = cb->result; + + if (!(flags & ALL_RESULTS)) ++done; - break; - } - ibreq->ibr_name = names[name_nr]; - break; - } + else + { + if (!have_tablepath) + { + tablepath = __get_tablepath (ibreq->ibr_name, &bptr); + tableptr = tablepath; + have_tablepath = 1; + } + if (tableptr == NULL) + { + ++done; + break; + } + free (ibreq->ibr_name); + ibreq->ibr_name = strsep (&tableptr, ":"); + if (ibreq->ibr_name == NULL || ibreq->ibr_name[0] == '\0') + { + ibreq->ibr_name = strdup (""); + ++done; + } + else + ibreq->ibr_name = strdup (ibreq->ibr_name); + } + } + break; + case NIS_SYSTEMERROR: + case NIS_NOSUCHNAME: + case NIS_NOT_ME: + /* If we had first tried the old binding, do nothing, but + get a new binding */ + if (!first_try) + { + if (__nisbind_next (&bptr) != NIS_SUCCESS) + { + ++done; + break; /* No more servers to search */ + } + while (__nisbind_connect (&bptr) != NIS_SUCCESS) + { + if (__nisbind_next (&bptr) != NIS_SUCCESS) + { + ++done; + break; /* No more servers to search */ + } + } + goto again; + } + break; + default: + if (!first_try) + { + /* Try the next domainname if we don't follow a link. */ + if (count_links) + { + free (ibreq->ibr_name); + NIS_RES_STATUS (res) = NIS_LINKNAMEERROR; + ++done; + break; + } + ++name_nr; + if (names[name_nr] == NULL) + { + ++done; + break; + } + ibreq->ibr_name = names[name_nr]; + first_try = 1; /* Try old binding at first */ + goto again; + } + break; + } + first_try = 0; + + if (cb) + { + __nis_destroy_callback (cb); + ibreq->ibr_cbhost.ibr_cbhost_len = 0; + ibreq->ibr_cbhost.ibr_cbhost_val = NULL; } - } /* End of not FOLLOW_PATH. */ + + __nisbind_destroy (&bptr); + nis_free_directory (dir); + } if (names != namebuf) nis_freenames (names); - if (cb) - { - __nis_destroy_callback (cb); - ibreq->ibr_cbhost.ibr_cbhost_len = 0; - ibreq->ibr_cbhost.ibr_cbhost_val = NULL; - } - nis_free_request (ibreq); return res; diff --git a/nis/nis_util.c b/nis/nis_util.c index 656b1a4..2b351e7 100644 --- a/nis/nis_util.c +++ b/nis/nis_util.c @@ -38,7 +38,7 @@ __nis_finddirectory (directory_obj *dir, const_nis_name name) dir->do_servers.do_servers_len, NIS_FINDDIRECTORY, (xdrproc_t) _xdr_fd_args, (caddr_t) &fd_args, (xdrproc_t) _xdr_fd_result, - (caddr_t) fd_res, NO_AUTHINFO|USE_DGRAM, NULL, NULL); + (caddr_t) fd_res, NO_AUTHINFO|USE_DGRAM, NULL); if (status != NIS_SUCCESS) fd_res->status = status; diff --git a/nis/rpcsvc/nislib.h b/nis/rpcsvc/nislib.h index 016bedc..60bf892 100644 --- a/nis/rpcsvc/nislib.h +++ b/nis/rpcsvc/nislib.h @@ -1,4 +1,4 @@ -/* Copyright (C) 1997 Free Software Foundation, Inc. +/* Copyright (C) 1997, 1998 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1997. @@ -247,6 +247,35 @@ extern u_long __nis_hash __P ((const void *keyarg, register size_t len)); extern int __nis_lock_cache __P ((void)); extern int __nis_unlock_cache __P ((void)); +/* (XXX INTERNAL FUNCTIONS, ONLY FOR rpc.nisd AND glibc !!) */ +#if defined (NIS_INTERNAL) || defined (_LIBC) + +struct dir_binding +{ + CLIENT *clnt; /* RPC CLIENT handle */ + nis_server *server_val; /* List of servers */ + u_int server_len; /* # of servers */ + u_int server_used; /* Which server we are bind in the moment ? */ + u_int current_ep; /* Which endpoint of the server are in use? */ + u_int trys; /* How many server have we tried ? */ + u_int class; /* From which class is server_val ? */ + bool_t master_only; /* Is only binded to the master */ + bool_t use_auth; /* Do we use AUTH ? */ + bool_t use_udp; /* Do we use UDP ? */ + struct sockaddr_in addr; /* Server's IP address */ + int socket; /* Server's local socket */ +}; +typedef struct dir_binding dir_binding; + +extern nis_error __nisbind_create __P ((dir_binding *, const nis_server *, + u_int, u_long)); +extern nis_error __nisbind_connect __P ((dir_binding *)); +extern nis_error __nisbind_next __P ((dir_binding *)); +extern void __nisbind_destroy __P ((dir_binding *)); +extern nis_error __nisfind_server __P ((const_nis_name, directory_obj **)); + +#endif + __END_DECLS #endif /* __RPCSVC_NISLIB_H__ */ |