Update.
[platform/upstream/glibc.git] / nis / nss_nis / nis-network.c
1 /* Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3    Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1996.
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 <nss.h>
21 #include <netdb.h>
22 #include <ctype.h>
23 #include <errno.h>
24 #include <string.h>
25 #include <netinet/in.h>
26 #include <arpa/inet.h>
27 #include <bits/libc-lock.h>
28 #include <rpcsvc/yp.h>
29 #include <rpcsvc/ypclnt.h>
30
31 #include "nss-nis.h"
32
33 /* Get the declaration of the parser function.  */
34 #define ENTNAME netent
35 #define EXTERN_PARSER
36 #include <nss/nss_files/files-parse.c>
37
38 __libc_lock_define_initialized (static, lock)
39
40 static bool_t new_start = 1;
41 static char *oldkey = NULL;
42 static int oldkeylen = 0;
43
44 enum nss_status
45 _nss_nis_setnetent (void)
46 {
47   __libc_lock_lock (lock);
48
49   new_start = 1;
50   if (oldkey != NULL)
51     {
52       free (oldkey);
53       oldkey = NULL;
54       oldkeylen = 0;
55     }
56
57   __libc_lock_unlock (lock);
58
59   return NSS_STATUS_SUCCESS;
60 }
61
62 enum nss_status
63 _nss_nis_endnetent (void)
64 {
65   __libc_lock_lock (lock);
66
67   new_start = 1;
68   if (oldkey != NULL)
69     {
70       free (oldkey);
71       oldkey = NULL;
72       oldkeylen = 0;
73     }
74
75   __libc_lock_unlock (lock);
76
77   return NSS_STATUS_SUCCESS;
78 }
79
80 static enum nss_status
81 internal_nis_getnetent_r (struct netent *net, char *buffer, size_t buflen,
82                           int *errnop, int *herrnop)
83 {
84   struct parser_data *data = (void *) buffer;
85   char *domain, *result, *outkey;
86   int len, keylen, parse_res;
87
88   if (yp_get_default_domain (&domain))
89     return NSS_STATUS_UNAVAIL;
90
91   /* Get the next entry until we found a correct one. */
92   do
93     {
94       enum nss_status retval;
95       char *p;
96
97       if (new_start)
98         retval = yperr2nss (yp_first (domain, "networks.byname",
99                                       &outkey, &keylen, &result, &len));
100       else
101         retval = yperr2nss ( yp_next (domain, "networks.byname",
102                                       oldkey, oldkeylen,
103                                       &outkey, &keylen, &result, &len));
104
105       if (retval != NSS_STATUS_SUCCESS)
106         {
107           if (retval == NSS_STATUS_NOTFOUND)
108             *errnop = ENOENT;
109           else if (retval == NSS_STATUS_TRYAGAIN)
110             {
111               *herrnop = NETDB_INTERNAL;
112               *errnop = errno;
113             }
114           return retval;
115         }
116
117       if ((size_t) (len + 1) > buflen)
118         {
119           free (result);
120           *errnop = ERANGE;
121           *herrnop = NETDB_INTERNAL;
122           return NSS_STATUS_TRYAGAIN;
123         }
124
125       p = strncpy (buffer, result, len);
126       buffer[len] = '\0';
127       while (isspace (*p))
128         ++p;
129       free (result);
130
131       parse_res = _nss_files_parse_netent (p, net, data, buflen, errnop);
132       if (parse_res == -1)
133         {
134           free (outkey);
135           *herrnop = NETDB_INTERNAL;
136           *errnop = ERANGE;
137           return NSS_STATUS_TRYAGAIN;
138         }
139
140       free (oldkey);
141       oldkey = outkey;
142       oldkeylen = keylen;
143       new_start = 0;
144     }
145   while (!parse_res);
146
147   return NSS_STATUS_SUCCESS;
148 }
149
150 enum nss_status
151 _nss_nis_getnetent_r (struct netent *net, char *buffer, size_t buflen,
152                       int *errnop, int *herrnop)
153 {
154   enum nss_status status;
155
156   __libc_lock_lock (lock);
157
158   status = internal_nis_getnetent_r (net, buffer, buflen, errnop, herrnop);
159
160   __libc_lock_unlock (lock);
161
162   return status;
163 }
164
165 enum nss_status
166 _nss_nis_getnetbyname_r (const char *name, struct netent *net, char *buffer,
167                          size_t buflen, int *errnop, int *herrnop)
168 {
169   enum nss_status retval;
170   struct parser_data *data = (void *) buffer;
171   char *domain, *result, *p;
172   int len, parse_res;
173
174   if (name == NULL)
175     {
176       *errnop = EINVAL;
177       *herrnop = NETDB_INTERNAL;
178       return NSS_STATUS_UNAVAIL;
179     }
180
181   if (yp_get_default_domain (&domain))
182     return NSS_STATUS_UNAVAIL;
183
184   if (buflen < sizeof *data + 1)
185     {
186       *herrnop = NETDB_INTERNAL;
187       *errnop = ERANGE;
188       return NSS_STATUS_TRYAGAIN;
189     }
190   else
191     {
192       /* Convert name to lowercase.  */
193       size_t namlen = strlen (name);
194       char name2[namlen + 1];
195       int i;
196
197       for (i = 0; i < namlen; ++i)
198         name2[i] = tolower (name[i]);
199       name2[i] = '\0';
200
201       retval = yperr2nss (yp_match (domain, "networks.byname", name2,
202                                     namlen, &result, &len));
203     }
204
205
206   if (retval != NSS_STATUS_SUCCESS)
207     {
208       if (retval == NSS_STATUS_NOTFOUND)
209         *errnop = ENOENT;
210       else if (retval == NSS_STATUS_TRYAGAIN)
211         {
212           *errnop = errno;
213           *herrnop = NETDB_INTERNAL;
214         }
215       return retval;
216     }
217
218   if ((size_t) (len + 1) > buflen)
219     {
220       free (result);
221       *errnop = ERANGE;
222       *herrnop = NETDB_INTERNAL;
223       return NSS_STATUS_TRYAGAIN;
224     }
225
226   p = strncpy (buffer, result, len);
227   buffer[len] = '\0';
228   while (isspace (*p))
229     ++p;
230   free (result);
231
232   parse_res = _nss_files_parse_netent (p, net, data, buflen, errnop);
233
234   if (parse_res < 1)
235     {
236       *herrnop = NETDB_INTERNAL;
237       if (parse_res == -1)
238         return NSS_STATUS_TRYAGAIN;
239       else
240         {
241           *errnop = ENOENT;
242           return NSS_STATUS_NOTFOUND;
243         }
244     }
245   else
246     return NSS_STATUS_SUCCESS;
247 }
248
249 enum nss_status
250 _nss_nis_getnetbyaddr_r (unsigned long addr, int type, struct netent *net,
251                          char *buffer, size_t buflen, int *errnop,
252                          int *herrnop)
253 {
254   struct parser_data *data = (void *) buffer;
255   char *domain;
256   char *result;
257   int len;
258   char buf[256];
259   int blen;
260   struct in_addr in;
261   char *p;
262
263   if (yp_get_default_domain (&domain))
264     return NSS_STATUS_UNAVAIL;
265
266   in = inet_makeaddr (addr, 0);
267   strcpy (buf, inet_ntoa (in));
268   blen = strlen (buf);
269
270   while (1)
271     {
272       enum nss_status retval;
273       int parse_res;
274
275       retval = yperr2nss (yp_match (domain, "networks.byaddr", buf,
276                                     strlen (buf), &result, &len));
277
278         if (retval != NSS_STATUS_SUCCESS)
279           {
280             if (retval == NSS_STATUS_NOTFOUND)
281               {
282                 if (buf[blen - 2] == '.' && buf[blen - 1] == '0')
283                   {
284                     /* Try again, but with trailing dot(s)
285                        removed (one by one) */
286                     buf[blen - 2] = '\0';
287                     blen -= 2;
288                     continue;
289                   }
290                 else
291                   {
292                     *errnop = ENOENT;
293                     return NSS_STATUS_NOTFOUND;
294                   }
295               }
296             else
297               {
298                 if (retval == NSS_STATUS_TRYAGAIN)
299                   *errnop = errno;
300                 return retval;
301               }
302           }
303
304       if ((size_t) (len + 1) > buflen)
305         {
306           free (result);
307           *errnop = ERANGE;
308           *herrnop = NETDB_INTERNAL;
309           return NSS_STATUS_TRYAGAIN;
310         }
311
312         p = strncpy (buffer, result, len);
313         buffer[len] = '\0';
314         while (isspace (*p))
315           ++p;
316         free (result);
317
318         parse_res = _nss_files_parse_netent (p, net, data, buflen, errnop);
319
320         if (parse_res < 1)
321           {
322             *herrnop = NETDB_INTERNAL;
323             if (parse_res == -1)
324               return NSS_STATUS_TRYAGAIN;
325             else
326               {
327                 *errnop = ENOENT;
328                 return NSS_STATUS_NOTFOUND;
329               }
330           }
331         else
332           return NSS_STATUS_SUCCESS;
333     }
334 }