Move non-deprecated RPC-related functions from sunrpc to inet
[platform/upstream/glibc.git] / nis / nss_nis / nis-ethers.c
1 /* Copyright (C) 1996-2020 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3    Contributed by Thorsten Kukuk <kukuk@suse.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 Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the 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    Lesser General Public License for more details.
14
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, see
17    <https://www.gnu.org/licenses/>.  */
18
19 #include <nss.h>
20 #include <ctype.h>
21 #include <errno.h>
22 #include <string.h>
23 #include <libc-lock.h>
24 #include <rpcsvc/yp.h>
25 #include <rpcsvc/ypclnt.h>
26 #include <netinet/ether.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 /* Get the declaration of the parser function.  */
35 #define ENTNAME etherent
36 #define STRUCTURE etherent
37 #define EXTERN_PARSER
38 #include <nss/nss_files/files-parse.c>
39
40 struct response
41 {
42   struct response *next;
43   char val[0];
44 };
45
46 static struct response *start;
47 static struct response *next;
48
49 static int
50 saveit (int instatus, char *inkey, int inkeylen, char *inval,
51         int invallen, char *indata)
52 {
53   if (instatus != YP_TRUE)
54     return 1;
55
56   if (inkey && inkeylen > 0 && inval && invallen > 0)
57     {
58       struct response *newp = malloc (sizeof (struct response) + invallen + 1);
59       if (newp == NULL)
60         return 1; /* We have no error code for out of memory */
61
62       if (start == NULL)
63         start = newp;
64       else
65         next->next = newp;
66       next = newp;
67
68       newp->next = NULL;
69       *((char *) mempcpy (newp->val, inval, invallen)) = '\0';
70     }
71
72   return 0;
73 }
74
75 static void
76 internal_nis_endetherent (void)
77 {
78   while (start != NULL)
79     {
80       next = start;
81       start = start->next;
82       free (next);
83     }
84 }
85
86 enum nss_status
87 _nss_nis_endetherent (void)
88 {
89   __libc_lock_lock (lock);
90
91   internal_nis_endetherent ();
92   next = NULL;
93
94   __libc_lock_unlock (lock);
95
96   return NSS_STATUS_SUCCESS;
97 }
98
99 static enum nss_status
100 internal_nis_setetherent (void)
101 {
102   char *domainname;
103   struct ypall_callback ypcb;
104   enum nss_status status;
105
106   yp_get_default_domain (&domainname);
107
108   internal_nis_endetherent ();
109
110   ypcb.foreach = saveit;
111   ypcb.data = NULL;
112   status = yperr2nss (yp_all (domainname, "ethers.byname", &ypcb));
113   next = start;
114
115   return status;
116 }
117
118 enum nss_status
119 _nss_nis_setetherent (int stayopen)
120 {
121   enum nss_status result;
122
123   __libc_lock_lock (lock);
124
125   result = internal_nis_setetherent ();
126
127   __libc_lock_unlock (lock);
128
129   return result;
130 }
131
132 static enum nss_status
133 internal_nis_getetherent_r (struct etherent *eth, char *buffer, size_t buflen,
134                             int *errnop)
135 {
136   struct parser_data *data = (void *) buffer;
137   int parse_res;
138
139   if (start == NULL)
140     internal_nis_setetherent ();
141
142   /* Get the next entry until we found a correct one. */
143   do
144     {
145       char *p;
146
147       if (next == NULL)
148         return NSS_STATUS_NOTFOUND;
149
150       p = strncpy (buffer, next->val, buflen);
151
152       while (isspace (*p))
153         ++p;
154
155       parse_res = _nss_files_parse_etherent (p, eth, data, buflen, errnop);
156       if (parse_res == -1)
157         return NSS_STATUS_TRYAGAIN;
158       next = next->next;
159     }
160   while (!parse_res);
161
162   return NSS_STATUS_SUCCESS;
163 }
164
165 enum nss_status
166 _nss_nis_getetherent_r (struct etherent *result, char *buffer, size_t buflen,
167                         int *errnop)
168 {
169   int status;
170
171   __libc_lock_lock (lock);
172
173   status = internal_nis_getetherent_r (result, buffer, buflen, errnop);
174
175   __libc_lock_unlock (lock);
176
177   return status;
178 }
179
180 enum nss_status
181 _nss_nis_gethostton_r (const char *name, struct etherent *eth,
182                        char *buffer, size_t buflen, int *errnop)
183 {
184   if (name == NULL)
185     {
186       *errnop = EINVAL;
187       return NSS_STATUS_UNAVAIL;
188     }
189
190   char *domain;
191   if (__glibc_unlikely (yp_get_default_domain (&domain)))
192     return NSS_STATUS_UNAVAIL;
193
194   char *result;
195   int len;
196   int yperr = yp_match (domain, "ethers.byname", name, strlen (name), &result,
197                         &len);
198
199   if (__glibc_unlikely (yperr != YPERR_SUCCESS))
200     {
201       enum nss_status retval = yperr2nss (yperr);
202
203       if (retval == NSS_STATUS_TRYAGAIN)
204         *errnop = errno;
205       return retval;
206     }
207
208   if (__glibc_unlikely ((size_t) (len + 1) > buflen))
209     {
210       free (result);
211       *errnop = ERANGE;
212       return NSS_STATUS_TRYAGAIN;
213     }
214
215   char *p = strncpy (buffer, result, len);
216   buffer[len] = '\0';
217   while (isspace (*p))
218     ++p;
219   free (result);
220
221   int parse_res = _nss_files_parse_etherent (p, eth, (void *) buffer, buflen,
222                                              errnop);
223   if (__glibc_unlikely (parse_res < 1))
224     {
225       if (parse_res == -1)
226         return NSS_STATUS_TRYAGAIN;
227       else
228         return NSS_STATUS_NOTFOUND;
229     }
230   return NSS_STATUS_SUCCESS;
231 }
232
233 enum nss_status
234 _nss_nis_getntohost_r (const struct ether_addr *addr, struct etherent *eth,
235                        char *buffer, size_t buflen, int *errnop)
236 {
237   if (addr == NULL)
238     {
239       *errnop = EINVAL;
240       return NSS_STATUS_UNAVAIL;
241     }
242
243   char *domain;
244   if (__glibc_unlikely (yp_get_default_domain (&domain)))
245     return NSS_STATUS_UNAVAIL;
246
247   char buf[33];
248   int nlen = snprintf (buf, sizeof (buf), "%x:%x:%x:%x:%x:%x",
249                       (int) addr->ether_addr_octet[0],
250                       (int) addr->ether_addr_octet[1],
251                       (int) addr->ether_addr_octet[2],
252                       (int) addr->ether_addr_octet[3],
253                       (int) addr->ether_addr_octet[4],
254                       (int) addr->ether_addr_octet[5]);
255
256   char *result;
257   int len;
258   int yperr = yp_match (domain, "ethers.byaddr", buf, nlen, &result, &len);
259
260   if (__glibc_unlikely (yperr != YPERR_SUCCESS))
261     {
262       enum nss_status retval = yperr2nss (yperr);
263
264       if (retval == NSS_STATUS_TRYAGAIN)
265         *errnop = errno;
266       return retval;
267     }
268
269   if (__glibc_unlikely ((size_t) (len + 1) > buflen))
270     {
271       free (result);
272       *errnop = ERANGE;
273       return NSS_STATUS_TRYAGAIN;
274     }
275
276   char *p = strncpy (buffer, result, len);
277   buffer[len] = '\0';
278   while (isspace (*p))
279     ++p;
280   free (result);
281
282   int parse_res = _nss_files_parse_etherent (p, eth, (void *) buffer, buflen,
283                                              errnop);
284   if (__glibc_unlikely (parse_res < 1))
285     {
286       if (parse_res == -1)
287         return NSS_STATUS_TRYAGAIN;
288       else
289         return NSS_STATUS_NOTFOUND;
290     }
291   return NSS_STATUS_SUCCESS;
292 }