aa985019d2a7b047c426a61a6a14fcf5bc26d8d5
[kopensolaris-gnu/glibc.git] / nis / nis_call.c
1 /* Copyright (C) 1997 Free Software Foundation, Inc.
2
3    This file is part of the GNU C Library.
4    Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1997.
5    
6    The GNU C Library is free software; you can redistribute it and/or
7    modify it under the terms of the GNU Library General Public License as
8    published by the Free Software Foundation; either version 2 of the
9    License, or (at your option) any later version.
10    
11    The GNU C Library is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    Library General Public License for more details.
15    
16    You should have received a copy of the GNU Library General Public
17    License along with the GNU C Library; see the file COPYING.LIB.  If not,
18    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19    Boston, MA 02111-1307, USA.  */
20
21 #include <string.h>
22 #include <rpc/rpc.h>
23 #include <rpc/auth.h>
24 #include <rpcsvc/nis.h>
25 #include <sys/socket.h>
26 #include <netinet/in.h>
27 #include <arpa/inet.h>
28 #include "nis_intern.h"
29
30 static struct timeval TIMEOUT = {25, 0};
31 static int const MAXTRIES = 3;
32
33 static unsigned long
34 inetstr2int (const char *str)
35 {
36   char buffer[strlen(str)+3];
37   int i, j;
38
39   strcpy (buffer, str);
40
41   j = 0;
42   for (i = 0; i < strlen (buffer); ++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, i;
61   CLIENT *client = NULL;
62   void *out;
63
64   for (i = 0; i < server->ep.ep_len; i++)
65     {
66       memset (&clnt_saddr, '\0', sizeof clnt_saddr);
67       clnt_saddr.sin_family = AF_INET;
68       if (strcmp (server->ep.ep_val[i].family,"loopback") == 0)
69         {
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)
74               {
75                 if ((flags & USE_DGRAM) == USE_DGRAM)
76                   clnt_saddr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
77                 else
78                   continue;
79               }
80           else
81             if (strcmp (server->ep.ep_val[i].proto,"tcp") == 0)
82               {
83                 if ((flags & USE_DGRAM) == USE_DGRAM)
84                   continue;
85                 else
86                   clnt_saddr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
87               }
88         }
89       else
90         if (strcmp (server->ep.ep_val[i].family,"inet") == 0)
91           {
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)
97                 {
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;
103                 }
104               else
105                 if (strcmp (server->ep.ep_val[i].proto,"tcp") == 0)
106                   {
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);
112                   }
113           }
114         else
115           continue;
116
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);
124       
125       if (client == NULL)
126         continue;
127 #if 1
128       if (clnt_call (client, 0, (xdrproc_t) xdr_void, NULL,
129                      (xdrproc_t) xdr_void, out, TIMEOUT) != RPC_SUCCESS)
130         {
131           clnt_destroy (client);
132           continue;
133         }
134 #endif
135       if ((flags & NO_AUTHINFO) != NO_AUTHINFO)
136           {
137 #if !defined(NO_DES_RPC)
138             if (server->key_type == NIS_PK_DH)
139               {
140                 char netname[MAXNETNAMELEN+1];
141                 char *p;
142                 
143                 strcpy(netname,"unix.");
144                 strncat(netname,server->name,MAXNETNAMELEN-5);
145                 netname[MAXNETNAMELEN-5] = '\0';
146                 p = strchr(netname,'.');
147                 *p = '@';
148                 if(!(client->cl_auth = 
149                      authdes_pk_create(netname, &server->pkey, 300, NULL, NULL)))
150                   client->cl_auth = authunix_create_default();
151               }
152             else
153 #endif
154               client->cl_auth = authunix_create_default();
155           }
156       return client;
157     }
158   
159   return NULL;
160 }
161
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)
166 {
167   CLIENT *clnt;
168   directory_obj *dir = NULL;
169   nis_server *server;
170   int try, result, server_len;
171   
172   if (serv == NULL || serv_len == 0)
173     {
174       dir = readColdStartFile ();
175       if (dir == NULL)
176         return NIS_UNAVAIL;
177       server = dir->do_servers.do_servers_val;
178       server_len = dir->do_servers.do_servers_len;
179     }
180   else
181     {
182       server = serv;
183       server_len = serv_len;
184     }
185
186   try = 0;
187   result = NIS_NAMEUNREACHABLE;
188   
189   while (try < MAXTRIES && result != RPC_SUCCESS)
190     {
191       unsigned int i;
192
193       ++try;
194       for (i = 0; i < server_len; i++)
195         {
196           if ((clnt = __nis_dobind (&server[i], flags)) == NULL)
197             continue;
198           
199           result = clnt_call (clnt, prog, xargs, req, xres, resp, TIMEOUT);
200          
201           if (result != RPC_SUCCESS)
202             {
203               clnt_perror (clnt, "do_niscall: clnt_call");
204               clnt_destroy (clnt);
205               result = NIS_RPCERROR;
206             }
207           else
208             clnt_destroy (clnt);
209         }
210     }
211   
212   if (dir != NULL)
213     nis_free_directory (dir);
214   return result;
215 }