1 /* Copyright (C) 1997 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3 Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1997.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public License as
7 published by the Free Software Foundation; either version 2 of the
8 License, or (at your option) any later version.
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
15 You should have received a copy of the GNU Library General Public
16 License along with the GNU C Library; see the file COPYING.LIB. If not,
17 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA. */
23 #include <rpcsvc/nis.h>
24 #include <sys/socket.h>
25 #include <netinet/in.h>
26 #include <arpa/inet.h>
27 #include "nis_intern.h"
29 static struct timeval TIMEOUT
= {25, 0};
30 static int const MAXTRIES
= 3;
33 inetstr2int (const char *str
)
35 char buffer
[strlen (str
) + 3];
39 buflen
= stpcpy (buffer
, str
) - buffer
;
42 for (i
= 0; i
< buflen
; ++i
)
53 return inet_addr (buffer
);
57 __nis_dobind (const nis_server
*server
, u_long flags
)
59 struct sockaddr_in clnt_saddr
;
62 CLIENT
*client
= NULL
;
64 memset (&clnt_saddr
, '\0', sizeof clnt_saddr
);
65 clnt_saddr
.sin_family
= AF_INET
;
66 for (i
= 0; i
< server
->ep
.ep_len
; i
++)
68 if (strcmp (server
->ep
.ep_val
[i
].family
,"loopback") == 0)
70 if (server
->ep
.ep_val
[i
].uaddr
[i
] == '-')
71 clnt_saddr
.sin_addr
.s_addr
= htonl (INADDR_LOOPBACK
);
73 if (strcmp (server
->ep
.ep_val
[i
].proto
,"udp") == 0)
75 if ((flags
& USE_DGRAM
) == USE_DGRAM
)
76 clnt_saddr
.sin_addr
.s_addr
= htonl (INADDR_LOOPBACK
);
81 if (strcmp (server
->ep
.ep_val
[i
].proto
,"tcp") == 0)
83 if ((flags
& USE_DGRAM
) == USE_DGRAM
)
86 clnt_saddr
.sin_addr
.s_addr
= htonl (INADDR_LOOPBACK
);
90 if (strcmp (server
->ep
.ep_val
[i
].family
,"inet") == 0)
92 if (server
->ep
.ep_val
[i
].uaddr
[i
] == '-')
93 clnt_saddr
.sin_addr
.s_addr
=
94 inetstr2int (server
->ep
.ep_val
[i
].uaddr
);
96 if (strcmp (server
->ep
.ep_val
[i
].proto
,"udp") == 0)
98 if ((flags
& USE_DGRAM
) == USE_DGRAM
)
99 clnt_saddr
.sin_addr
.s_addr
=
100 inetstr2int (server
->ep
.ep_val
[i
].uaddr
);
105 if (strcmp (server
->ep
.ep_val
[i
].proto
,"tcp") == 0)
107 if ((flags
& USE_DGRAM
) == USE_DGRAM
)
110 clnt_saddr
.sin_addr
.s_addr
=
111 inetstr2int (server
->ep
.ep_val
[i
].uaddr
);
117 clnt_sock
= RPC_ANYSOCK
;
118 if ((flags
& USE_DGRAM
) == USE_DGRAM
)
119 client
= clntudp_create (&clnt_saddr
, NIS_PROG
, NIS_VERSION
,
120 TIMEOUT
, &clnt_sock
);
122 client
= clnttcp_create (&clnt_saddr
, NIS_PROG
, NIS_VERSION
,
127 if (clnt_call (client
, 0, (xdrproc_t
) xdr_void
, NULL
,
128 (xdrproc_t
) xdr_void
, NULL
, TIMEOUT
) != RPC_SUCCESS
)
130 clnt_destroy (client
);
134 if ((flags
& NO_AUTHINFO
) != NO_AUTHINFO
)
136 #if defined(HAVE_SECURE_RPC)
137 if (server
->key_type
== NIS_PK_DH
&& getenv ("NO_SECURE_RPC") == NULL
)
139 char netname
[MAXNETNAMELEN
+1];
142 p
= stpcpy (netname
, "unix.");
143 strncpy (p
, server
->name
,MAXNETNAMELEN
-5);
144 netname
[MAXNETNAMELEN
] = '\0';
145 p
= strchr (netname
, '.');
148 authdes_pk_create (netname
, &server
->pkey
, 300, NULL
, NULL
);
149 if (!client
->cl_auth
)
150 client
->cl_auth
= authunix_create_default ();
154 client
->cl_auth
= authunix_create_default ();
163 __do_niscall2 (const nis_server
*server
, u_int server_len
, u_long prog
,
164 xdrproc_t xargs
, caddr_t req
, xdrproc_t xres
, caddr_t resp
,
171 result
= NIS_NAMEUNREACHABLE
;
173 if (((flags
& MASTER_ONLY
) == MASTER_ONLY
) && server_len
> 1)
174 server_len
= 1; /* The first entry is the master */
176 while (try < MAXTRIES
&& result
!= RPC_SUCCESS
)
180 if ((flags
& HARD_LOOKUP
) == 0)
183 for (i
= 0; i
< server_len
; i
++)
185 if ((clnt
= __nis_dobind (&server
[i
], flags
)) == NULL
)
188 result
= clnt_call (clnt
, prog
, xargs
, req
, xres
, resp
, TIMEOUT
);
190 if (result
!= RPC_SUCCESS
)
192 clnt_perror (clnt
, "do_niscall: clnt_call");
194 result
= NIS_RPCERROR
;
204 static directory_obj
*
205 dir_lookup (const_nis_name name
, nis_server
*serv
, u_long flags
)
210 struct ns_request req
;
213 res
= calloc (1, sizeof (nis_result
));
214 req
.ns_name
= (char *)name
;
215 req
.ns_object
.ns_object_len
= 0;
216 req
.ns_object
.ns_object_val
= NULL
;
218 result
= NIS_NAMEUNREACHABLE
;
220 while (try < MAXTRIES
&& result
!= RPC_SUCCESS
)
222 if ((clnt
= __nis_dobind (serv
, flags
)) == NULL
)
225 result
= clnt_call (clnt
, NIS_LOOKUP
, (xdrproc_t
) xdr_ns_request
,
226 (caddr_t
) &req
, (xdrproc_t
) xdr_nis_result
,
227 (caddr_t
) res
, TIMEOUT
);
229 if (result
!= RPC_SUCCESS
)
231 clnt_perror (clnt
, "do_niscall: clnt_call");
233 result
= NIS_RPCERROR
;
238 if (result
!= RPC_SUCCESS
|| res
->status
!= NIS_SUCCESS
)
241 dir
= nis_clone_directory (&res
->objects
.objects_val
->DI_data
, NULL
);
242 nis_freeresult (res
);
247 static directory_obj
*
248 rec_dirsearch (const_nis_name name
, directory_obj
*dir
, u_long flags
)
250 char domain
[strlen (name
) + 3];
252 nis_domain_of_r (name
, domain
, sizeof (domain
));
253 if (strncmp (domain
, "org_dir.", 8) == 0)
255 char tmp
[strlen (name
) + 3];
257 nis_domain_of_r (domain
, tmp
, sizeof (tmp
));
258 strcpy (domain
, tmp
);
261 if (strncmp (domain
, "groups_dir.", 11) == 0)
263 char tmp
[strlen (name
) + 3];
265 nis_domain_of_r (domain
, tmp
, sizeof (tmp
));
266 strcpy (domain
, tmp
);
270 /* We have no grous_dir or org_dir, so try the complete name */
271 strcpy (domain
, name
);
274 switch (nis_dir_cmp (domain
, dir
->do_name
))
279 /* NOT_SEQUENTIAL means, go one up and try it there ! */
281 { /* We need data from a parent domain */
283 char ndomain
[strlen (name
) + 3];
285 nis_domain_of_r (dir
->do_name
, ndomain
, sizeof (ndomain
));
287 /* The root server of our domain is a replica of the parent
288 domain ! (Now I understand why a root server must be a
289 replica of the parent domain) */
290 obj
= dir_lookup (ndomain
, dir
->do_servers
.do_servers_val
,
294 /* We have found a NIS+ server serving ndomain, now
295 let us search for "name" */
296 nis_free_directory (dir
);
297 return rec_dirsearch (name
, obj
, flags
);
301 /* Ups, very bad. Are we already the root server ? */
302 nis_free_directory (dir
);
310 char leaf
[strlen (name
) + 3];
311 char ndomain
[strlen (name
) + 3];
316 if (strlen (domain
) == 0)
318 nis_free_directory (dir
);
321 nis_leaf_of_r (domain
, leaf
, sizeof (leaf
));
322 nis_domain_of_r (domain
, ndomain
, sizeof (ndomain
));
323 strcpy (domain
, ndomain
);
325 while (nis_dir_cmp (domain
, dir
->do_name
) != SAME_NAME
);
327 strcat (leaf
, domain
);
329 for (i
= 0; i
< dir
->do_servers
.do_servers_len
; ++i
)
331 obj
= dir_lookup (leaf
, &dir
->do_servers
.do_servers_val
[i
],
335 /* We have found a NIS+ server serving ndomain, now
336 let us search for "name" */
337 nis_free_directory (dir
);
338 return rec_dirsearch (name
, obj
, flags
);
344 nis_free_directory (dir
);
347 nis_free_directory (dir
);
352 __do_niscall (const_nis_name name
, u_long prog
, xdrproc_t xargs
,
353 caddr_t req
, xdrproc_t xres
, caddr_t resp
, u_long flags
)
356 directory_obj
*dir
= NULL
;
357 const nis_server
*server
;
361 dir
= readColdStartFile ();
362 if (dir
== NULL
) /* No /var/nis/NIS_COLD_START -> no NIS+ installed */
367 dir
= rec_dirsearch (name
, dir
, flags
);
370 if (nis_dir_cmp (nis_local_directory(), name
) == NOT_SEQUENTIAL
)
371 return NIS_NAMEUNREACHABLE
;
376 server
= dir
->do_servers
.do_servers_val
;
377 server_len
= dir
->do_servers
.do_servers_len
;
379 if (((flags
& MASTER_ONLY
) == MASTER_ONLY
) && server_len
> 1)
380 server_len
= 1; /* The first entry is the master */
382 result
= __do_niscall2 (server
, server_len
, prog
, xargs
, req
, xres
,
385 nis_free_directory (dir
);