Use addr, not p for inet_pton call.
[kopensolaris-gnu/glibc.git] / nis / nss_nis / nis-ethers.c
1 /* Copyright (C) 1996, 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>, 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 <ctype.h>
22 #include <errno.h>
23 #include <string.h>
24 #include <libc-lock.h>
25 #include <rpcsvc/yp.h>
26 #include <rpcsvc/ypclnt.h>
27 #include <netinet/if_ether.h>
28
29 #include "nss-nis.h"
30
31 /* Protect global state against multiple changers */
32 __libc_lock_define_initialized (static, lock)
33
34 struct ether
35 {
36   const char *e_name;
37   struct ether_addr e_addr;
38 };
39
40 /* Get the declaration of the parser function.  */
41 #define ENTNAME etherent
42 #define STRUCTURE ether
43 #define EXTERN_PARSER
44 #include <nss/nss_files/files-parse.c>
45
46 struct response
47 {
48   char *val;
49   struct response *next;
50 };
51
52 static struct response *start = NULL;
53 static struct response *next = NULL;
54
55 static int
56 saveit (int instatus, char *inkey, int inkeylen, char *inval,
57         int invallen, char *indata)
58 {
59   if (instatus != YP_TRUE)
60     return instatus;
61
62   if (inkey && inkeylen > 0 && inval && invallen > 0)
63     {
64       if (start == NULL)
65         {
66           start = malloc (sizeof (struct response));
67           next = start;
68         }
69       else
70         {
71           next->next = malloc (sizeof (struct response));
72           next = next->next;
73         }
74       next->next = NULL;
75       next->val = malloc (invallen + 1);
76       strncpy (next->val, inval, invallen);
77       next->val[invallen] = '\0';
78     }
79
80   return 0;
81 }
82
83 enum nss_status
84 internal_nis_setetherent (void)
85 {
86   char *domainname;
87   struct ypall_callback ypcb;
88   enum nss_status status;
89
90   yp_get_default_domain (&domainname);
91
92   while (start != NULL)
93     {
94       if (start->val != NULL)
95         free (start->val);
96       next = start;
97       start = start->next;
98       free (next);
99     }
100   start = NULL;
101
102   ypcb.foreach = saveit;
103   ypcb.data = NULL;
104   status = yperr2nss (yp_all (domainname, "ethers.byname", &ypcb));
105   next = start;
106
107   return status;
108 }
109
110 enum nss_status
111 _nss_nis_setetherent (void)
112 {
113   enum nss_status result;
114
115   __libc_lock_lock (lock);
116
117   result = internal_nis_setetherent ();
118
119   __libc_lock_unlock (lock);
120
121   return result;
122 }
123
124 enum nss_status
125 _nss_nis_endetherent (void)
126 {
127   __libc_lock_lock (lock);
128
129   while (start != NULL)
130     {
131       if (start->val != NULL)
132         free (start->val);
133       next = start;
134       start = start->next;
135       free (next);
136     }
137   start = NULL;
138   next = NULL;
139
140   __libc_lock_unlock (lock);
141
142   return NSS_STATUS_SUCCESS;
143 }
144
145 static enum nss_status
146 internal_nis_getetherent_r (struct ether *eth, char *buffer, size_t buflen)
147 {
148   struct parser_data *data = (void *) buffer;
149   int parse_res;
150
151   if (start == NULL)
152     internal_nis_setetherent ();
153
154   /* Get the next entry until we found a correct one. */
155   do
156     {
157       char *p;
158
159       if (next == NULL)
160         return NSS_STATUS_NOTFOUND;
161       p = strcpy (buffer, next->val);
162       next = next->next;
163
164       while (isspace (*p))
165         ++p;
166
167       parse_res = _nss_files_parse_etherent (p, eth, data, buflen);
168       if (!parse_res && errno == ERANGE)
169         return NSS_STATUS_TRYAGAIN;
170     }
171   while (!parse_res);
172
173   return NSS_STATUS_SUCCESS;
174 }
175
176 enum nss_status
177 _nss_nis_getetherent_r (struct ether *result, char *buffer, size_t buflen)
178 {
179   int status;
180
181   __libc_lock_lock (lock);
182
183   status = internal_nis_getetherent_r (result, buffer, buflen);
184
185   __libc_lock_unlock (lock);
186
187   return status;
188 }
189
190 enum nss_status
191 _nss_nis_gethostton_r (const char *name, struct ether *eth,
192                        char *buffer, size_t buflen)
193 {
194   struct parser_data *data = (void *) buffer;
195   enum nss_status retval;
196   char *domain, *result, *p;
197   int len, parse_res;
198
199   if (name == NULL)
200     {
201       __set_errno (EINVAL);
202       return NSS_STATUS_UNAVAIL;
203     }
204
205   if (yp_get_default_domain (&domain))
206     return NSS_STATUS_UNAVAIL;
207
208   retval = yperr2nss (yp_match (domain, "ethers.byname", name,
209                                 strlen (name), &result, &len));
210
211   if (retval != NSS_STATUS_SUCCESS)
212     {
213       if (retval == NSS_STATUS_TRYAGAIN)
214         __set_errno (EAGAIN);
215       return retval;
216     }
217
218   if ((size_t) (len + 1) > buflen)
219     {
220       free (result);
221       __set_errno (ERANGE);
222       return NSS_STATUS_TRYAGAIN;
223     }
224
225   p = strncpy (buffer, result, len);
226   buffer[len] = '\0';
227   while (isspace (*p))
228     ++p;
229   free (result);
230
231   parse_res = _nss_files_parse_etherent (p, eth, data, buflen);
232
233   if (!parse_res)
234     {
235       if (errno == ERANGE)
236         return NSS_STATUS_TRYAGAIN;
237       else
238         return NSS_STATUS_NOTFOUND;
239     }
240   else
241     return NSS_STATUS_SUCCESS;
242 }
243
244 enum nss_status
245 _nss_nis_getntohost_r (struct ether_addr *addr, struct ether *eth,
246                        char *buffer, size_t buflen)
247 {
248   struct parser_data *data = (void *) buffer;
249   enum nss_status retval;
250   char *domain, *result, *p;
251   int len, nlen, parse_res;
252   char buf[33];
253
254   if (addr == NULL)
255     {
256       __set_errno (EINVAL);
257       return NSS_STATUS_UNAVAIL;
258     }
259
260   if (yp_get_default_domain (&domain))
261     return NSS_STATUS_UNAVAIL;
262
263   nlen = sprintf (buf, "%x:%x:%x:%x:%x:%x",
264                   (int) addr->ether_addr_octet[0],
265                   (int) addr->ether_addr_octet[1],
266                   (int) addr->ether_addr_octet[2],
267                   (int) addr->ether_addr_octet[3],
268                   (int) addr->ether_addr_octet[4],
269                   (int) addr->ether_addr_octet[5]);
270
271   retval = yperr2nss (yp_match (domain, "ethers.byaddr", buf,
272                                 nlen, &result, &len));
273
274   if (retval != NSS_STATUS_SUCCESS)
275     {
276       if (retval == NSS_STATUS_TRYAGAIN)
277         __set_errno (EAGAIN);
278       return retval;
279     }
280
281   if ((size_t) (len + 1) > buflen)
282     {
283       free (result);
284       __set_errno (ERANGE);
285       return NSS_STATUS_TRYAGAIN;
286     }
287
288   p = strncpy (buffer, result, len);
289   buffer[len] = '\0';
290   while (isspace (*p))
291     ++p;
292   free (result);
293
294   parse_res = _nss_files_parse_etherent (p, eth, data, buflen);
295
296   if (!parse_res)
297     {
298       if (errno == ERANGE)
299         return NSS_STATUS_TRYAGAIN;
300       else
301         return NSS_STATUS_NOTFOUND;
302     }
303   else
304     return NSS_STATUS_SUCCESS;
305 }