Update.
[glibc.git] / nis / nis_call.c
blob12b3ab265ecb5807399f1e2fd020c2deb7f3f410
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. */
20 #include <string.h>
21 #include <rpc/rpc.h>
22 #include <rpc/auth.h>
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;
32 static unsigned long
33 inetstr2int (const char *str)
35 char buffer[strlen (str) + 3];
36 size_t buflen;
37 size_t i, j;
39 buflen = stpcpy (buffer, str) - buffer;
41 j = 0;
42 for (i = 0; i < buflen; ++i)
43 if (buffer[i] == '.')
45 ++j;
46 if (j == 4)
48 buffer[i] = '\0';
49 break;
53 return inet_addr (buffer);
56 static CLIENT *
57 __nis_dobind (const nis_server *server, u_long flags)
59 struct sockaddr_in clnt_saddr;
60 int clnt_sock;
61 size_t i;
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);
72 else
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);
77 else
78 continue;
80 else
81 if (strcmp (server->ep.ep_val[i].proto,"tcp") == 0)
83 if ((flags & USE_DGRAM) == USE_DGRAM)
84 continue;
85 else
86 clnt_saddr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
89 else
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);
95 else
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);
101 else
102 continue;
104 else
105 if (strcmp (server->ep.ep_val[i].proto,"tcp") == 0)
107 if ((flags & USE_DGRAM) == USE_DGRAM)
108 continue;
109 else
110 clnt_saddr.sin_addr.s_addr =
111 inetstr2int (server->ep.ep_val[i].uaddr);
114 else
115 continue;
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);
121 else
122 client = clnttcp_create (&clnt_saddr, NIS_PROG, NIS_VERSION,
123 &clnt_sock, 0, 0);
125 if (client == NULL)
126 continue;
127 if (clnt_call (client, 0, (xdrproc_t) xdr_void, NULL,
128 (xdrproc_t) xdr_void, NULL, TIMEOUT) != RPC_SUCCESS)
130 clnt_destroy (client);
131 continue;
134 if ((flags & NO_AUTHINFO) != NO_AUTHINFO)
136 #if defined(HAVE_SECURE_RPC)
137 if (server->key_type == NIS_PK_DH)
139 char netname[MAXNETNAMELEN+1];
140 char *p;
142 p = stpcpy (netname, "unix.");
143 strncpy (p, server->name,MAXNETNAMELEN-5);
144 netname[MAXNETNAMELEN] = '\0';
145 p = strchr (netname, '.');
146 *p = '@';
147 client->cl_auth =
148 authdes_pk_create (netname, &server->pkey, 300, NULL, NULL);
149 if (!client->cl_auth)
150 client->cl_auth = authunix_create_default ();
152 else
153 #endif
154 client->cl_auth = authunix_create_default ();
156 return client;
159 return NULL;
162 nis_error
163 __do_niscall (const nis_server *serv, int serv_len, u_long prog,
164 xdrproc_t xargs, caddr_t req, xdrproc_t xres, caddr_t resp,
165 u_long flags)
167 CLIENT *clnt;
168 directory_obj *dir = NULL;
169 const nis_server *server;
170 int try, result;
171 unsigned int server_len;
173 if (serv == NULL || serv_len == 0)
175 dir = readColdStartFile ();
176 if (dir == NULL)
178 fputs (_("Error: could not find a NIS_COLD_START file\n"), stderr);
179 return NIS_UNAVAIL;
181 server = dir->do_servers.do_servers_val;
182 server_len = dir->do_servers.do_servers_len;
184 else
186 server = serv;
187 server_len = serv_len;
190 if (((flags & MASTER_ONLY) == MASTER_ONLY) && server_len > 1)
191 server_len = 1; /* The first entry is the master */
193 try = 0;
194 result = NIS_NAMEUNREACHABLE;
196 while (try < MAXTRIES && result != RPC_SUCCESS)
198 unsigned int i;
200 if ((flags & HARD_LOOKUP) == 0)
201 ++try;
203 for (i = 0; i < server_len; i++)
205 if ((clnt = __nis_dobind (&server[i], flags)) == NULL)
206 continue;
208 result = clnt_call (clnt, prog, xargs, req, xres, resp, TIMEOUT);
210 if (result != RPC_SUCCESS)
212 clnt_perror (clnt, "do_niscall: clnt_call");
213 clnt_destroy (clnt);
214 result = NIS_RPCERROR;
216 else
217 clnt_destroy (clnt);
221 if (dir != NULL)
222 nis_free_directory (dir);
223 return result;