Fix typo.
[kopensolaris-gnu/glibc.git] / nis / nis_call.c
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.
4
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.
9
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.
14
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.  */
19
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"
28
29 static struct timeval TIMEOUT = {25, 0};
30 static int const MAXTRIES = 3;
31
32 static unsigned long
33 inetstr2int (const char *str)
34 {
35   char buffer[strlen (str) + 3];
36   size_t buflen;
37   size_t i, j;
38
39   buflen = stpcpy (buffer, str) - buffer;
40
41   j = 0;
42   for (i = 0; i < buflen; ++i)
43     if (buffer[i] == '.')
44       {
45         ++j;
46         if (j == 4)
47           {
48             buffer[i] = '\0';
49             break;
50           }
51       }
52
53   return inet_addr (buffer);
54 }
55
56 static CLIENT *
57 __nis_dobind (const nis_server *server, u_long flags)
58 {
59   struct sockaddr_in clnt_saddr;
60   int clnt_sock;
61   size_t i;
62   CLIENT *client = NULL;
63   /* XXX What is this variable for?  */
64   void *out = NULL;
65
66   for (i = 0; i < server->ep.ep_len; i++)
67     {
68       memset (&clnt_saddr, '\0', sizeof clnt_saddr);
69       clnt_saddr.sin_family = AF_INET;
70       if (strcmp (server->ep.ep_val[i].family,"loopback") == 0)
71         {
72           if (server->ep.ep_val[i].uaddr[i] == '-')
73             clnt_saddr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
74           else
75             if (strcmp (server->ep.ep_val[i].proto,"udp") == 0)
76               {
77                 if ((flags & USE_DGRAM) == USE_DGRAM)
78                   clnt_saddr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
79                 else
80                   continue;
81               }
82           else
83             if (strcmp (server->ep.ep_val[i].proto,"tcp") == 0)
84               {
85                 if ((flags & USE_DGRAM) == USE_DGRAM)
86                   continue;
87                 else
88                   clnt_saddr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
89               }
90         }
91       else
92         if (strcmp (server->ep.ep_val[i].family,"inet") == 0)
93           {
94             if (server->ep.ep_val[i].uaddr[i] == '-')
95               clnt_saddr.sin_addr.s_addr =
96                 inetstr2int (server->ep.ep_val[i].uaddr);
97             else
98               if (strcmp (server->ep.ep_val[i].proto,"udp") == 0)
99                 {
100                   if ((flags & USE_DGRAM) == USE_DGRAM)
101                     clnt_saddr.sin_addr.s_addr =
102                       inetstr2int (server->ep.ep_val[i].uaddr);
103                   else
104                     continue;
105                 }
106               else
107                 if (strcmp (server->ep.ep_val[i].proto,"tcp") == 0)
108                   {
109                     if ((flags & USE_DGRAM) == USE_DGRAM)
110                       continue;
111                     else
112                       clnt_saddr.sin_addr.s_addr =
113                         inetstr2int (server->ep.ep_val[i].uaddr);
114                   }
115           }
116         else
117           continue;
118
119       clnt_sock = RPC_ANYSOCK;
120       if ((flags & USE_DGRAM) == USE_DGRAM)
121         client = clntudp_create (&clnt_saddr, NIS_PROG, NIS_VERSION,
122                                  TIMEOUT, &clnt_sock);
123       else
124         client = clnttcp_create (&clnt_saddr, NIS_PROG, NIS_VERSION,
125                                  &clnt_sock, 0, 0);
126
127       if (client == NULL)
128         continue;
129 #if 1
130       if (clnt_call (client, 0, (xdrproc_t) xdr_void, NULL,
131                      (xdrproc_t) xdr_void, out, TIMEOUT) != RPC_SUCCESS)
132         {
133           clnt_destroy (client);
134           continue;
135         }
136 #endif
137       if ((flags & NO_AUTHINFO) != NO_AUTHINFO)
138           {
139 #if !defined(NO_DES_RPC)
140             if (server->key_type == NIS_PK_DH)
141               {
142                 char netname[MAXNETNAMELEN+1];
143                 char *p;
144
145                 strcpy (netname, "unix.");
146                 strncat (netname, server->name,MAXNETNAMELEN-5);
147                 netname[MAXNETNAMELEN-5] = '\0';
148                 p = strchr (netname, '.');
149                 *p = '@';
150                 client->cl_auth =
151                   authdes_pk_create (netname, &server->pkey, 300, NULL, NULL);
152                 if (!client->cl_auth)
153                   client->cl_auth = authunix_create_default ();
154               }
155             else
156 #endif
157               client->cl_auth = authunix_create_default ();
158           }
159       return client;
160     }
161
162   return NULL;
163 }
164
165 nis_error
166 __do_niscall (const nis_server *serv, int serv_len, u_long prog,
167               xdrproc_t xargs, caddr_t req, xdrproc_t xres, caddr_t resp,
168               u_long flags)
169 {
170   CLIENT *clnt;
171   directory_obj *dir = NULL;
172   const nis_server *server;
173   int try, result, server_len;
174
175   if (serv == NULL || serv_len == 0)
176     {
177       dir = readColdStartFile ();
178       if (dir == NULL)
179         return NIS_UNAVAIL;
180       server = dir->do_servers.do_servers_val;
181       server_len = dir->do_servers.do_servers_len;
182     }
183   else
184     {
185       server = serv;
186       server_len = serv_len;
187     }
188
189   try = 0;
190   result = NIS_NAMEUNREACHABLE;
191
192   while (try < MAXTRIES && result != RPC_SUCCESS)
193     {
194       unsigned int i;
195
196       ++try;
197       for (i = 0; i < server_len; i++)
198         {
199           if ((clnt = __nis_dobind (&server[i], flags)) == NULL)
200             continue;
201
202           result = clnt_call (clnt, prog, xargs, req, xres, resp, TIMEOUT);
203
204           if (result != RPC_SUCCESS)
205             {
206               /* XXX Grrr.  The cast is needed for now since Sun code does
207                  note know about `const'.  */
208               clnt_perror (clnt, (char *) "do_niscall: clnt_call");
209               clnt_destroy (clnt);
210               result = NIS_RPCERROR;
211             }
212           else
213             clnt_destroy (clnt);
214         }
215     }
216
217   if (dir != NULL)
218     nis_free_directory (dir);
219   return result;
220 }