1 /* Copyright (c) 1997-2022 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3 
4    The GNU C Library is free software; you can redistribute it and/or
5    modify it under the terms of the GNU Lesser General Public
6    License as published by the Free Software Foundation; either
7    version 2.1 of the License, or (at your option) any later version.
8 
9    The GNU C Library is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12    Lesser General Public License for more details.
13 
14    You should have received a copy of the GNU Lesser General Public
15    License along with the GNU C Library; if not, see
16    <https://www.gnu.org/licenses/>.  */
17 
18 #include <assert.h>
19 #include <string.h>
20 #include <rpcsvc/nis.h>
21 #include <libc-diag.h>
22 #include <shlib-compat.h>
23 
24 #include "nis_xdr.h"
25 #include "nis_intern.h"
26 #include "libnsl.h"
27 
28 
29 struct ib_request *
__create_ib_request(const_nis_name name,unsigned int flags)30 __create_ib_request (const_nis_name name, unsigned int flags)
31 {
32   struct ib_request *ibreq = calloc (1, sizeof (struct ib_request));
33   nis_attr *search_val = NULL;
34   size_t search_len = 0;
35   size_t size = 0;
36 
37   if (ibreq == NULL)
38     return NULL;
39 
40   ibreq->ibr_flags = flags;
41 
42   char *cptr = strdupa (name);
43 
44   /* Not of "[key=value,key=value,...],foo.." format? */
45   if (cptr[0] != '[')
46     {
47       ibreq->ibr_name = strdup (cptr);
48       if (ibreq->ibr_name == NULL)
49 	{
50 	  free (ibreq);
51 	  return NULL;
52 	}
53       return ibreq;
54     }
55 
56   /* "[key=value,...],foo" format */
57   ibreq->ibr_name = strchr (cptr, ']');
58   if (ibreq->ibr_name == NULL || ibreq->ibr_name[1] != ',')
59     {
60       /* The object has not really been built yet so we use free.  */
61       free (ibreq);
62       return NULL;
63     }
64 
65   /* Check if we have an entry of "[key=value,],bar".  If, remove the "," */
66   if (ibreq->ibr_name[-1] == ',')
67     ibreq->ibr_name[-1] = '\0';
68   else
69     ibreq->ibr_name[0] = '\0';
70   ibreq->ibr_name += 2;
71   ibreq->ibr_name = strdup (ibreq->ibr_name);
72   if (ibreq->ibr_name == NULL)
73     {
74     free_null:
75       while (search_len-- > 0)
76 	{
77 	  free (search_val[search_len].zattr_ndx);
78 	  free (search_val[search_len].zattr_val.zattr_val_val);
79 	}
80       free (search_val);
81       nis_free_request (ibreq);
82       return NULL;
83     }
84 
85   ++cptr; /* Remove "[" */
86 
87   while (cptr != NULL && cptr[0] != '\0')
88     {
89       char *key = cptr;
90       char *val = strchr (cptr, '=');
91 
92       cptr = strchr (key, ',');
93       if (cptr != NULL)
94 	*cptr++ = '\0';
95 
96       if (__glibc_unlikely (val == NULL))
97 	{
98 	  nis_free_request (ibreq);
99 	  return NULL;
100 	}
101       *val++ = '\0';
102       if (search_len + 1 >= size)
103 	{
104 	  size += 1;
105 	  nis_attr *newp = realloc (search_val, size * sizeof (nis_attr));
106 	  if (newp == NULL)
107 	    goto free_null;
108 	  search_val = newp;
109 	}
110       search_val[search_len].zattr_ndx = strdup (key);
111       if (search_val[search_len].zattr_ndx == NULL)
112 	goto free_null;
113 
114       search_val[search_len].zattr_val.zattr_val_len = strlen (val) + 1;
115       search_val[search_len].zattr_val.zattr_val_val = strdup (val);
116       if (search_val[search_len].zattr_val.zattr_val_val == NULL)
117 	{
118 	  free (search_val[search_len].zattr_ndx);
119 	  goto free_null;
120 	}
121 
122       ++search_len;
123     }
124 
125   ibreq->ibr_srch.ibr_srch_val = search_val;
126   ibreq->ibr_srch.ibr_srch_len = search_len;
127 
128   return ibreq;
129 }
130 libnsl_hidden_nolink_def (__create_ib_request, GLIBC_PRIVATE)
131 
132 static const struct timeval RPCTIMEOUT = {10, 0};
133 
134 static char *
get_tablepath(char * name,dir_binding * bptr)135 get_tablepath (char *name, dir_binding *bptr)
136 {
137   enum clnt_stat result;
138   nis_result res;
139   struct ns_request req;
140 
141   memset (&res, '\0', sizeof (res));
142 
143   req.ns_name = name;
144   req.ns_object.ns_object_len = 0;
145   req.ns_object.ns_object_val = NULL;
146 
147   result = clnt_call (bptr->clnt, NIS_LOOKUP, (xdrproc_t) _xdr_ns_request,
148 		      (caddr_t) &req, (xdrproc_t) _xdr_nis_result,
149 		      (caddr_t) &res, RPCTIMEOUT);
150 
151   const char *cptr;
152   if (result == RPC_SUCCESS && NIS_RES_STATUS (&res) == NIS_SUCCESS
153       && __type_of (NIS_RES_OBJECT (&res)) == NIS_TABLE_OBJ)
154     cptr = NIS_RES_OBJECT (&res)->TA_data.ta_path;
155   else
156     cptr = "";
157 
158   char *str = strdup (cptr);
159 
160   if (result == RPC_SUCCESS)
161     xdr_free ((xdrproc_t) _xdr_nis_result, (char *) &res);
162 
163   return str;
164 }
165 
166 
167 nis_error
__follow_path(char ** tablepath,char ** tableptr,struct ib_request * ibreq,dir_binding * bptr)168 __follow_path (char **tablepath, char **tableptr, struct ib_request *ibreq,
169 	       dir_binding *bptr)
170 {
171   if (*tablepath == NULL)
172     {
173       *tablepath = get_tablepath (ibreq->ibr_name, bptr);
174       if (*tablepath == NULL)
175 	return NIS_NOMEMORY;
176 
177       *tableptr = *tablepath;
178     }
179 
180   /* Since tableptr is only set here, and it's set when tablepath is NULL,
181      which it is initially defined as, we know it will always be set here.  */
182   DIAG_PUSH_NEEDS_COMMENT;
183   DIAG_IGNORE_NEEDS_COMMENT (4.7, "-Wmaybe-uninitialized");
184 
185   if (*tableptr == NULL)
186     return NIS_NOTFOUND;
187 
188   char *newname = strsep (tableptr, ":");
189   if (newname[0] == '\0')
190     return NIS_NOTFOUND;
191 
192   DIAG_POP_NEEDS_COMMENT;
193 
194   newname = strdup (newname);
195   if (newname == NULL)
196     return NIS_NOMEMORY;
197 
198   free (ibreq->ibr_name);
199   ibreq->ibr_name = newname;
200 
201   return NIS_SUCCESS;
202 }
libnsl_hidden_nolink_def(__follow_path,GLIBC_PRIVATE)203 libnsl_hidden_nolink_def (__follow_path, GLIBC_PRIVATE)
204 
205 
206 nis_result *
207 nis_list (const_nis_name name, unsigned int flags,
208 	  int (*callback) (const_nis_name name,
209 			   const nis_object *object,
210 			   const void *userdata),
211 	  const void *userdata)
212 {
213   nis_result *res = malloc (sizeof (nis_result));
214   ib_request *ibreq;
215   int status;
216   enum clnt_stat clnt_status;
217   int count_links = 0;		/* We will only follow NIS_MAXLINKS links! */
218   int done = 0;
219   nis_name *names;
220   nis_name namebuf[2] = {NULL, NULL};
221   int name_nr = 0;
222   nis_cb *cb = NULL;
223   char *tableptr;
224   char *tablepath = NULL;
225   int first_try = 0; /* Do we try the old binding at first ? */
226   nis_result *allres = NULL;
227 
228   if (res == NULL)
229     return NULL;
230 
231   if (name == NULL)
232     {
233       status = NIS_BADNAME;
234     err_out:
235       nis_freeresult (allres);
236       memset (res, '\0', sizeof (nis_result));
237       NIS_RES_STATUS (res) = status;
238       return res;
239     }
240 
241   ibreq = __create_ib_request (name, flags);
242   if (ibreq == NULL)
243     {
244       status = NIS_BADNAME;
245       goto err_out;
246     }
247 
248   if ((flags & EXPAND_NAME)
249       && ibreq->ibr_name[strlen (ibreq->ibr_name) - 1] != '.')
250     {
251       names = nis_getnames (ibreq->ibr_name);
252       free (ibreq->ibr_name);
253       ibreq->ibr_name = NULL;
254       if (names == NULL)
255 	{
256 	  nis_free_request (ibreq);
257 	  status = NIS_BADNAME;
258 	  goto err_out;
259 	}
260       ibreq->ibr_name = strdup (names[name_nr]);
261       if (ibreq->ibr_name == NULL)
262 	{
263 	  nis_freenames (names);
264 	  nis_free_request (ibreq);
265 	  status = NIS_NOMEMORY;
266 	  goto err_out;
267 	}
268     }
269   else
270     {
271       names = namebuf;
272       names[name_nr] = ibreq->ibr_name;
273     }
274 
275   cb = NULL;
276 
277   while (!done)
278     {
279       dir_binding bptr;
280       directory_obj *dir = NULL;
281 
282       memset (res, '\0', sizeof (nis_result));
283 
284       status = __nisfind_server (ibreq->ibr_name,
285 				 ibreq->ibr_srch.ibr_srch_val != NULL,
286 				 &dir, &bptr, flags & ~MASTER_ONLY);
287       if (status != NIS_SUCCESS)
288 	{
289 	  NIS_RES_STATUS (res) = status;
290 	  goto fail3;
291 	}
292 
293       while (__nisbind_connect (&bptr) != NIS_SUCCESS)
294 	if (__glibc_unlikely (__nisbind_next (&bptr) != NIS_SUCCESS))
295 	  {
296 	    NIS_RES_STATUS (res) = NIS_NAMEUNREACHABLE;
297 	    goto fail;
298 	  }
299 
300       if (callback != NULL)
301 	{
302 	  assert (cb == NULL);
303 	  cb = __nis_create_callback (callback, userdata, flags);
304 	  ibreq->ibr_cbhost.ibr_cbhost_len = 1;
305 	  ibreq->ibr_cbhost.ibr_cbhost_val = cb->serv;
306 	}
307 
308     again:
309       clnt_status = clnt_call (bptr.clnt, NIS_IBLIST,
310 			       (xdrproc_t) _xdr_ib_request, (caddr_t) ibreq,
311 			       (xdrproc_t) _xdr_nis_result,
312 			       (caddr_t) res, RPCTIMEOUT);
313 
314       if (__glibc_unlikely (clnt_status != RPC_SUCCESS))
315 	NIS_RES_STATUS (res) = NIS_RPCERROR;
316       else
317 	switch (NIS_RES_STATUS (res))
318 	  { /* start switch */
319 	  case NIS_PARTIAL:
320 	  case NIS_SUCCESS:
321 	  case NIS_S_SUCCESS:
322 	    if (__type_of (NIS_RES_OBJECT (res)) == NIS_LINK_OBJ
323 		&& (flags & FOLLOW_LINKS))	/* We are following links.  */
324 	      {
325 		free (ibreq->ibr_name);
326 		ibreq->ibr_name = NULL;
327 		/* If we hit the link limit, bail.  */
328 		if (__glibc_unlikely (count_links > NIS_MAXLINKS))
329 		  {
330 		    NIS_RES_STATUS (res) = NIS_LINKNAMEERROR;
331 		    ++done;
332 		    break;
333 		  }
334 		++count_links;
335 		ibreq->ibr_name =
336 		  strdup (NIS_RES_OBJECT (res)->LI_data.li_name);
337 		if (ibreq->ibr_name == NULL)
338 		  {
339 		    NIS_RES_STATUS (res) = NIS_NOMEMORY;
340 		  fail:
341 		    __nisbind_destroy (&bptr);
342 		    nis_free_directory (dir);
343 		  fail3:
344 		    free (tablepath);
345 		    if (cb)
346 		      {
347 			__nis_destroy_callback (cb);
348 			ibreq->ibr_cbhost.ibr_cbhost_len = 0;
349 			ibreq->ibr_cbhost.ibr_cbhost_val = NULL;
350 		      }
351 		    if (names != namebuf)
352 		      nis_freenames (names);
353 		    nis_free_request (ibreq);
354 		    nis_freeresult (allres);
355 		    return res;
356 		  }
357 		if (NIS_RES_OBJECT (res)->LI_data.li_attrs.li_attrs_len)
358 		  if (ibreq->ibr_srch.ibr_srch_len == 0)
359 		    {
360 		      ibreq->ibr_srch.ibr_srch_len =
361 			NIS_RES_OBJECT (res)->LI_data.li_attrs.li_attrs_len;
362 		      ibreq->ibr_srch.ibr_srch_val =
363 			NIS_RES_OBJECT (res)->LI_data.li_attrs.li_attrs_val;
364 		    }
365 		/* The following is a non-obvious optimization.  A
366 		   nis_freeresult call would call xdr_free as the
367 		   following code.  But it also would unnecessarily
368 		   free the result structure.  We avoid this here
369 		   along with the necessary tests.  */
370 		xdr_free ((xdrproc_t) _xdr_nis_result, (char *)res);
371 		memset (res, '\0', sizeof (*res));
372 		first_try = 1; /* Try at first the old binding */
373 		goto again;
374 	      }
375 	    else if ((flags & FOLLOW_PATH)
376 		     && NIS_RES_STATUS (res) == NIS_PARTIAL)
377 	      {
378 		enum nis_error err = __follow_path (&tablepath, &tableptr,
379 						    ibreq, &bptr);
380 		if (err != NIS_SUCCESS)
381 		  {
382 		    if (err == NIS_NOMEMORY)
383 		      NIS_RES_STATUS (res) = err;
384 		    ++done;
385 		  }
386 		else
387 		  {
388 		    /* The following is a non-obvious optimization.  A
389 		       nis_freeresult call would call xdr_free as the
390 		       following code.  But it also would unnecessarily
391 		       free the result structure.  We avoid this here
392 		       along with the necessary tests.  */
393 		    xdr_free ((xdrproc_t) _xdr_nis_result, (char *) res);
394 		    memset (res, '\0', sizeof (*res));
395 		    first_try = 1;
396 		    goto again;
397 		  }
398 	      }
399 	    else if ((flags & (FOLLOW_PATH | ALL_RESULTS))
400 		     == (FOLLOW_PATH | ALL_RESULTS))
401 	      {
402 		if (allres == NULL)
403 		  {
404 		    allres = res;
405 		    res = malloc (sizeof (nis_result));
406 		    if (res == NULL)
407 		      {
408 			res = allres;
409 			allres = NULL;
410 			NIS_RES_STATUS (res) = NIS_NOMEMORY;
411 			goto fail;
412 		      }
413 		    NIS_RES_STATUS (res) = NIS_RES_STATUS (allres);
414 		  }
415 		else
416 		  {
417 		    nis_object *objects_val
418 		      = realloc (NIS_RES_OBJECT (allres),
419 				 (NIS_RES_NUMOBJ (allres)
420 				  + NIS_RES_NUMOBJ (res))
421 				 * sizeof (nis_object));
422 		    if (objects_val == NULL)
423 		      {
424 			NIS_RES_STATUS (res) = NIS_NOMEMORY;
425 			goto fail;
426 		      }
427 		    NIS_RES_OBJECT (allres) = objects_val;
428 		    memcpy (NIS_RES_OBJECT (allres) + NIS_RES_NUMOBJ (allres),
429 			    NIS_RES_OBJECT (res),
430 			    NIS_RES_NUMOBJ (res) * sizeof (nis_object));
431 		    NIS_RES_NUMOBJ (allres) += NIS_RES_NUMOBJ (res);
432 		    NIS_RES_NUMOBJ (res) = 0;
433 		    free (NIS_RES_OBJECT (res));
434 		    NIS_RES_OBJECT (res) = NULL;
435 		    NIS_RES_STATUS (allres) = NIS_RES_STATUS (res);
436 		    xdr_free ((xdrproc_t) _xdr_nis_result, (char *) res);
437 		  }
438 		enum nis_error err = __follow_path (&tablepath, &tableptr,
439 						    ibreq, &bptr);
440 		if (err != NIS_SUCCESS)
441 		  {
442 		    /* Prepare for the nis_freeresult call.  */
443 		    memset (res, '\0', sizeof (*res));
444 
445 		    if (err == NIS_NOMEMORY)
446 		      NIS_RES_STATUS (allres) = err;
447 		    ++done;
448 		  }
449 	      }
450 	    else
451 	      ++done;
452 	    break;
453 	  case NIS_CBRESULTS:
454 	    if (cb != NULL)
455 	      {
456 		__nis_do_callback (&bptr, &res->cookie, cb);
457 		NIS_RES_STATUS (res) = cb->result;
458 
459 		if (!(flags & ALL_RESULTS))
460 		  ++done;
461 		else
462 		  {
463 		    enum nis_error err
464 		      = __follow_path (&tablepath, &tableptr, ibreq, &bptr);
465 		    if (err != NIS_SUCCESS)
466 		      {
467 			if (err == NIS_NOMEMORY)
468 			  NIS_RES_STATUS (res) = err;
469 			++done;
470 		      }
471 		  }
472 	      }
473 	    break;
474 	  case NIS_SYSTEMERROR:
475 	  case NIS_NOSUCHNAME:
476 	  case NIS_NOT_ME:
477 	    /* If we had first tried the old binding, do nothing, but
478 	       get a new binding */
479 	    if (!first_try)
480 	      {
481 		if (__nisbind_next (&bptr) != NIS_SUCCESS)
482 		  {
483 		    ++done;
484 		    break; /* No more servers to search */
485 		  }
486 		while (__nisbind_connect (&bptr) != NIS_SUCCESS)
487 		  {
488 		    if (__nisbind_next (&bptr) != NIS_SUCCESS)
489 		      {
490 			++done;
491 			break; /* No more servers to search */
492 		      }
493 		  }
494 		goto again;
495 	      }
496 	    break;
497 	  default:
498 	    if (!first_try)
499 	      {
500 		/* Try the next domainname if we don't follow a link.  */
501 		free (ibreq->ibr_name);
502 		ibreq->ibr_name = NULL;
503 		if (__glibc_unlikely (count_links))
504 		  {
505 		    NIS_RES_STATUS (res) = NIS_LINKNAMEERROR;
506 		    ++done;
507 		    break;
508 		  }
509 		++name_nr;
510 		if (names[name_nr] == NULL)
511 		  {
512 		    ++done;
513 		    break;
514 		  }
515 		ibreq->ibr_name = strdup (names[name_nr]);
516 		if (ibreq->ibr_name == NULL)
517 		  {
518 		    NIS_RES_STATUS (res) = NIS_NOMEMORY;
519 		    goto fail;
520 		  }
521 		first_try = 1; /* Try old binding at first */
522 		goto again;
523 	      }
524 	    break;
525 	  }
526       first_try = 0;
527 
528       if (cb)
529 	{
530 	  __nis_destroy_callback (cb);
531 	  ibreq->ibr_cbhost.ibr_cbhost_len = 0;
532 	  ibreq->ibr_cbhost.ibr_cbhost_val = NULL;
533 	  cb = NULL;
534 	}
535 
536       __nisbind_destroy (&bptr);
537       nis_free_directory (dir);
538     }
539 
540   free (tablepath);
541 
542   if (names != namebuf)
543     nis_freenames (names);
544 
545   nis_free_request (ibreq);
546 
547   if (allres)
548     {
549       nis_freeresult (res);
550       return allres;
551     }
552 
553   return res;
554 }
libnsl_hidden_nolink_def(nis_list,GLIBC_2_1)555 libnsl_hidden_nolink_def (nis_list, GLIBC_2_1)
556 
557 nis_result *
558 nis_add_entry (const_nis_name name, const nis_object *obj2, unsigned int flags)
559 {
560   nis_result *res = calloc (1, sizeof (nis_result));
561   if (res == NULL)
562     return NULL;
563 
564   if (name == NULL)
565     {
566       NIS_RES_STATUS (res) = NIS_BADNAME;
567       return res;
568     }
569 
570   ib_request *ibreq = __create_ib_request (name, flags);
571   if (ibreq == NULL)
572     {
573       NIS_RES_STATUS (res) = NIS_BADNAME;
574       return res;
575     }
576 
577   nis_object obj;
578   memcpy (&obj, obj2, sizeof (nis_object));
579 
580   size_t namelen = strlen (name);
581   char buf1[namelen + 20];
582   char buf4[namelen + 20];
583 
584   if (obj.zo_name == NULL || strlen (obj.zo_name) == 0)
585     obj.zo_name = nis_leaf_of_r (name, buf1, sizeof (buf1));
586 
587   if (obj.zo_owner == NULL || strlen (obj.zo_owner) == 0)
588     obj.zo_owner = nis_local_principal ();
589 
590   if (obj.zo_group == NULL || strlen (obj.zo_group) == 0)
591     obj.zo_group = nis_local_group ();
592 
593   obj.zo_domain = nis_domain_of_r (name, buf4, sizeof (buf4));
594 
595   ibreq->ibr_obj.ibr_obj_val = nis_clone_object (&obj, NULL);
596   if (ibreq->ibr_obj.ibr_obj_val == NULL)
597     {
598       nis_free_request (ibreq);
599       NIS_RES_STATUS (res) = NIS_NOMEMORY;
600       return res;
601     }
602   ibreq->ibr_obj.ibr_obj_len = 1;
603 
604   nis_error status = __do_niscall (ibreq->ibr_name, NIS_IBADD,
605 				   (xdrproc_t) _xdr_ib_request,
606 				   (caddr_t) ibreq,
607 				   (xdrproc_t) _xdr_nis_result,
608 				   (caddr_t) res, 0, NULL);
609   if (__glibc_unlikely (status != NIS_SUCCESS))
610     NIS_RES_STATUS (res) = status;
611 
612   nis_free_request (ibreq);
613 
614   return res;
615 }
libnsl_hidden_nolink_def(nis_add_entry,GLIBC_2_1)616 libnsl_hidden_nolink_def (nis_add_entry, GLIBC_2_1)
617 
618 nis_result *
619 nis_modify_entry (const_nis_name name, const nis_object *obj2,
620 		  unsigned int flags)
621 {
622   nis_object obj;
623   nis_result *res;
624   nis_error status;
625   ib_request *ibreq;
626   size_t namelen = strlen (name);
627   char buf1[namelen + 20];
628   char buf4[namelen + 20];
629 
630   res = calloc (1, sizeof (nis_result));
631   if (res == NULL)
632     return NULL;
633 
634   ibreq = __create_ib_request (name, flags);
635   if (ibreq == NULL)
636     {
637       NIS_RES_STATUS (res) = NIS_BADNAME;
638       return res;
639     }
640 
641   memcpy (&obj, obj2, sizeof (nis_object));
642 
643   if (obj.zo_name == NULL || strlen (obj.zo_name) == 0)
644     obj.zo_name = nis_leaf_of_r (name, buf1, sizeof (buf1));
645 
646   if (obj.zo_owner == NULL || strlen (obj.zo_owner) == 0)
647     obj.zo_owner = nis_local_principal ();
648 
649   if (obj.zo_group == NULL || strlen (obj.zo_group) == 0)
650     obj.zo_group = nis_local_group ();
651 
652   obj.zo_domain = nis_domain_of_r (name, buf4, sizeof (buf4));
653 
654   ibreq->ibr_obj.ibr_obj_val = nis_clone_object (&obj, NULL);
655   if (ibreq->ibr_obj.ibr_obj_val == NULL)
656     {
657       nis_free_request (ibreq);
658       NIS_RES_STATUS (res) = NIS_NOMEMORY;
659       return res;
660     }
661   ibreq->ibr_obj.ibr_obj_len = 1;
662 
663   status = __do_niscall (ibreq->ibr_name, NIS_IBMODIFY,
664 			 (xdrproc_t) _xdr_ib_request,
665 			 (caddr_t) ibreq, (xdrproc_t) _xdr_nis_result,
666 			 (caddr_t) res, 0, NULL);
667   if (__glibc_unlikely (status != NIS_SUCCESS))
668     NIS_RES_STATUS (res) = status;
669 
670   nis_free_request (ibreq);
671 
672   return res;
673 }
libnsl_hidden_nolink_def(nis_modify_entry,GLIBC_2_1)674 libnsl_hidden_nolink_def (nis_modify_entry, GLIBC_2_1)
675 
676 nis_result *
677 nis_remove_entry (const_nis_name name, const nis_object *obj,
678 		  unsigned int flags)
679 {
680   nis_result *res;
681   ib_request *ibreq;
682   nis_error status;
683 
684   res = calloc (1, sizeof (nis_result));
685   if (res == NULL)
686     return NULL;
687 
688   if (name == NULL)
689     {
690       NIS_RES_STATUS (res) = NIS_BADNAME;
691       return res;
692     }
693 
694   ibreq = __create_ib_request (name, flags);
695   if (ibreq == NULL)
696     {
697       NIS_RES_STATUS (res) = NIS_BADNAME;
698       return res;
699     }
700 
701   if (obj != NULL)
702     {
703       ibreq->ibr_obj.ibr_obj_val = nis_clone_object (obj, NULL);
704       if (ibreq->ibr_obj.ibr_obj_val == NULL)
705 	{
706 	  nis_free_request (ibreq);
707 	  NIS_RES_STATUS (res) = NIS_NOMEMORY;
708 	  return res;
709 	}
710       ibreq->ibr_obj.ibr_obj_len = 1;
711     }
712 
713   if ((status = __do_niscall (ibreq->ibr_name, NIS_IBREMOVE,
714 			      (xdrproc_t) _xdr_ib_request,
715 			      (caddr_t) ibreq, (xdrproc_t) _xdr_nis_result,
716 			      (caddr_t) res, 0, NULL)) != NIS_SUCCESS)
717     NIS_RES_STATUS (res) = status;
718 
719   nis_free_request (ibreq);
720 
721   return res;
722 }
libnsl_hidden_nolink_def(nis_remove_entry,GLIBC_2_1)723 libnsl_hidden_nolink_def (nis_remove_entry, GLIBC_2_1)
724 
725 nis_result *
726 nis_first_entry (const_nis_name name)
727 {
728   nis_result *res;
729   ib_request *ibreq;
730   nis_error status;
731 
732   res = calloc (1, sizeof (nis_result));
733   if (res == NULL)
734     return NULL;
735 
736   if (name == NULL)
737     {
738       NIS_RES_STATUS (res) = NIS_BADNAME;
739       return res;
740     }
741 
742   ibreq = __create_ib_request (name, 0);
743   if (ibreq == NULL)
744     {
745       NIS_RES_STATUS (res) = NIS_BADNAME;
746       return res;
747     }
748 
749   status = __do_niscall (ibreq->ibr_name, NIS_IBFIRST,
750 			 (xdrproc_t) _xdr_ib_request,
751 			 (caddr_t) ibreq, (xdrproc_t) _xdr_nis_result,
752 			 (caddr_t) res, 0, NULL);
753 
754   if (__glibc_unlikely (status != NIS_SUCCESS))
755     NIS_RES_STATUS (res) = status;
756 
757   nis_free_request (ibreq);
758 
759   return res;
760 }
libnsl_hidden_nolink_def(nis_first_entry,GLIBC_2_1)761 libnsl_hidden_nolink_def (nis_first_entry, GLIBC_2_1)
762 
763 nis_result *
764 nis_next_entry (const_nis_name name, const netobj *cookie)
765 {
766   nis_result *res;
767   ib_request *ibreq;
768   nis_error status;
769 
770   res = calloc (1, sizeof (nis_result));
771   if (res == NULL)
772     return NULL;
773 
774   if (name == NULL)
775     {
776       NIS_RES_STATUS (res) = NIS_BADNAME;
777       return res;
778     }
779 
780   ibreq = __create_ib_request (name, 0);
781   if (ibreq == NULL)
782     {
783       NIS_RES_STATUS (res) = NIS_BADNAME;
784       return res;
785     }
786 
787   if (cookie != NULL)
788     {
789       ibreq->ibr_cookie.n_bytes = cookie->n_bytes;
790       ibreq->ibr_cookie.n_len = cookie->n_len;
791     }
792 
793   status = __do_niscall (ibreq->ibr_name, NIS_IBNEXT,
794 			 (xdrproc_t) _xdr_ib_request,
795 			 (caddr_t) ibreq, (xdrproc_t) _xdr_nis_result,
796 			 (caddr_t) res, 0, NULL);
797 
798   if (__glibc_unlikely (status != NIS_SUCCESS))
799     NIS_RES_STATUS (res) = status;
800 
801   if (cookie != NULL)
802     {
803       /* Don't give cookie free, it is not from us */
804       ibreq->ibr_cookie.n_bytes = NULL;
805       ibreq->ibr_cookie.n_len = 0;
806     }
807 
808   nis_free_request (ibreq);
809 
810   return res;
811 }
812 libnsl_hidden_nolink_def (nis_next_entry, GLIBC_2_1)
813