]>
Commit | Line | Data |
---|---|---|
880f421f | 1 | /* Copyright (C) 1997, 1998 Free Software Foundation, Inc. |
e61abf83 UD |
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 <nss.h> | |
21 | #include <errno.h> | |
22 | #include <ctype.h> | |
23 | #include <netdb.h> | |
24 | #include <string.h> | |
5107cf1d | 25 | #include <bits/libc-lock.h> |
e61abf83 | 26 | #include <rpcsvc/nis.h> |
e61abf83 UD |
27 | |
28 | #include "nss-nisplus.h" | |
29 | ||
30 | __libc_lock_define_initialized (static, lock); | |
31 | ||
32 | static nis_result *result = NULL; | |
2d7da676 UD |
33 | static nis_name tablename_val = NULL; |
34 | static u_long tablename_len = 0; | |
e61abf83 UD |
35 | |
36 | #define NISENTRYVAL(idx,col,res) \ | |
2d7da676 | 37 | ((res)->objects.objects_val[(idx)].EN_data.en_cols.en_cols_val[(col)].ec_value.ec_value_val) |
e61abf83 UD |
38 | |
39 | #define NISENTRYLEN(idx,col,res) \ | |
2d7da676 | 40 | ((res)->objects.objects_val[(idx)].EN_data.en_cols.en_cols_val[(col)].ec_value.ec_value_len) |
e61abf83 UD |
41 | |
42 | static int | |
43 | _nss_nisplus_parse_servent (nis_result *result, struct servent *serv, | |
d71b808a | 44 | char *buffer, size_t buflen, int *errnop) |
e61abf83 | 45 | { |
2d7da676 | 46 | char *first_unused = buffer; |
e61abf83 | 47 | size_t room_left = buflen; |
7799b7b3 | 48 | unsigned int i; |
2d7da676 | 49 | char *p, *line; |
e61abf83 UD |
50 | |
51 | if (result == NULL) | |
26dee9c4 | 52 | return 0; |
e61abf83 | 53 | |
d71b808a UD |
54 | if ((result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS) |
55 | || __type_of (result->objects.objects_val) != NIS_ENTRY_OBJ | |
56 | || strcmp (result->objects.objects_val->EN_data.en_type, | |
57 | "services_tbl") != 0 | |
58 | || result->objects.objects_val->EN_data.en_cols.en_cols_len < 4) | |
26dee9c4 | 59 | return 0; |
e61abf83 | 60 | |
2d7da676 | 61 | if (NISENTRYLEN (0, 0, result) >= room_left) |
e61abf83 | 62 | { |
2d7da676 | 63 | no_more_room: |
d71b808a | 64 | *errnop = ERANGE; |
60c96635 | 65 | return -1; |
e61abf83 | 66 | } |
2d7da676 UD |
67 | strncpy (first_unused, NISENTRYVAL (0, 0, result), |
68 | NISENTRYLEN (0, 0, result)); | |
69 | first_unused[NISENTRYLEN (0, 0, result)] = '\0'; | |
70 | serv->s_name = first_unused; | |
71 | room_left -= (strlen (first_unused) +1); | |
72 | first_unused += strlen (first_unused) +1; | |
73 | ||
74 | if (NISENTRYLEN (0, 2, result) >= room_left) | |
75 | goto no_more_room; | |
76 | strncpy (first_unused, NISENTRYVAL (0, 2, result), | |
77 | NISENTRYLEN (0, 2, result)); | |
78 | first_unused[NISENTRYLEN (0, 2, result)] = '\0'; | |
79 | serv->s_proto = first_unused; | |
d71b808a UD |
80 | room_left -= strlen (first_unused) + 1; |
81 | first_unused += strlen (first_unused) + 1; | |
2d7da676 | 82 | |
7ef90c15 | 83 | serv->s_port = htons (atoi (NISENTRYVAL (0, 3, result))); |
2d7da676 UD |
84 | p = first_unused; |
85 | ||
86 | line = p; | |
880f421f | 87 | for (i = 0; i < result->objects.objects_len; ++i) |
e61abf83 | 88 | { |
2d7da676 UD |
89 | if (strcmp (NISENTRYVAL (i, 1, result), serv->s_name) != 0) |
90 | { | |
91 | if (NISENTRYLEN (i, 1, result) + 2 > room_left) | |
92 | goto no_more_room; | |
cd6ede75 | 93 | *p++ = ' '; |
9a0a462c UD |
94 | p = __stpncpy (p, NISENTRYVAL (i, 1, result), |
95 | NISENTRYLEN (i, 1, result)); | |
2d7da676 UD |
96 | *p = '\0'; |
97 | room_left -= (NISENTRYLEN (i, 1, result) + 1); | |
98 | } | |
e61abf83 | 99 | } |
880f421f | 100 | *p++ = '\0'; |
2d7da676 UD |
101 | first_unused = p; |
102 | ||
103 | /* Adjust the pointer so it is aligned for | |
104 | storing pointers. */ | |
105 | first_unused += __alignof__ (char *) - 1; | |
106 | first_unused -= ((first_unused - (char *) 0) % __alignof__ (char *)); | |
107 | serv->s_aliases = (char **) first_unused; | |
108 | if (room_left < sizeof (char *)) | |
109 | goto no_more_room; | |
110 | room_left -= (sizeof (char *)); | |
111 | serv->s_aliases[0] = NULL; | |
112 | ||
113 | i = 0; | |
114 | while (*line != '\0') | |
e61abf83 | 115 | { |
2d7da676 UD |
116 | /* Skip leading blanks. */ |
117 | while (isspace (*line)) | |
ac9f45cf | 118 | ++line; |
e61abf83 | 119 | |
2d7da676 UD |
120 | if (*line == '\0') |
121 | break; | |
122 | ||
123 | if (room_left < sizeof (char *)) | |
124 | goto no_more_room; | |
125 | ||
126 | room_left -= sizeof (char *); | |
127 | serv->s_aliases[i] = line; | |
128 | ||
129 | while (*line != '\0' && *line != ' ') | |
130 | ++line; | |
131 | ||
132 | if (*line == ' ') | |
133 | { | |
134 | *line = '\0'; | |
135 | ++line; | |
136 | ++i; | |
e61abf83 | 137 | } |
2d7da676 UD |
138 | else |
139 | serv->s_aliases[i+1] = NULL; | |
e61abf83 UD |
140 | } |
141 | ||
2d7da676 UD |
142 | return 1; |
143 | } | |
144 | ||
145 | static enum nss_status | |
d71b808a | 146 | _nss_create_tablename (int *errnop) |
2d7da676 UD |
147 | { |
148 | if (tablename_val == NULL) | |
149 | { | |
150 | char buf [40 + strlen (nis_local_directory ())]; | |
151 | char *p; | |
152 | ||
9a0a462c UD |
153 | p = __stpcpy (buf, "services.org_dir."); |
154 | p = __stpcpy (p, nis_local_directory ()); | |
155 | tablename_val = __strdup (buf); | |
2d7da676 | 156 | if (tablename_val == NULL) |
d71b808a UD |
157 | { |
158 | *errnop = errno; | |
159 | return NSS_STATUS_TRYAGAIN; | |
160 | } | |
2d7da676 UD |
161 | tablename_len = strlen (tablename_val); |
162 | } | |
163 | return NSS_STATUS_SUCCESS; | |
e61abf83 UD |
164 | } |
165 | ||
2d7da676 | 166 | |
e61abf83 UD |
167 | enum nss_status |
168 | _nss_nisplus_setservent (void) | |
169 | { | |
2d7da676 | 170 | enum nss_status status = NSS_STATUS_SUCCESS; |
d71b808a | 171 | int err; |
2d7da676 | 172 | |
e61abf83 UD |
173 | __libc_lock_lock (lock); |
174 | ||
175 | if (result) | |
176 | nis_freeresult (result); | |
177 | result = NULL; | |
2d7da676 UD |
178 | |
179 | if (tablename_val == NULL) | |
d71b808a | 180 | status = _nss_create_tablename (&err); |
e61abf83 UD |
181 | |
182 | __libc_lock_unlock (lock); | |
183 | ||
2d7da676 | 184 | return status; |
e61abf83 UD |
185 | } |
186 | ||
187 | enum nss_status | |
188 | _nss_nisplus_endservent (void) | |
189 | { | |
190 | __libc_lock_lock (lock); | |
191 | ||
192 | if (result) | |
193 | nis_freeresult (result); | |
194 | result = NULL; | |
e61abf83 UD |
195 | |
196 | __libc_lock_unlock (lock); | |
197 | ||
198 | return NSS_STATUS_SUCCESS; | |
199 | } | |
200 | ||
201 | static enum nss_status | |
202 | internal_nisplus_getservent_r (struct servent *serv, char *buffer, | |
d71b808a | 203 | size_t buflen, int *errnop) |
e61abf83 UD |
204 | { |
205 | int parse_res; | |
206 | ||
207 | /* Get the next entry until we found a correct one. */ | |
208 | do | |
209 | { | |
60c96635 | 210 | nis_result *saved_res; |
8f2ece69 | 211 | |
e61abf83 UD |
212 | if (result == NULL) |
213 | { | |
60c96635 | 214 | saved_res = NULL; |
2d7da676 | 215 | if (tablename_val == NULL) |
d71b808a UD |
216 | { |
217 | enum nss_status status = _nss_create_tablename (errnop); | |
218 | ||
219 | if (status != NSS_STATUS_SUCCESS) | |
220 | return status; | |
221 | } | |
e61abf83 | 222 | |
2d7da676 | 223 | result = nis_first_entry (tablename_val); |
e61abf83 UD |
224 | if (niserr2nss (result->status) != NSS_STATUS_SUCCESS) |
225 | return niserr2nss (result->status); | |
226 | } | |
227 | else | |
228 | { | |
229 | nis_result *res; | |
230 | ||
60c96635 | 231 | saved_res = result; |
2d7da676 | 232 | res = nis_next_entry (tablename_val, &result->cookie); |
e61abf83 UD |
233 | result = res; |
234 | if (niserr2nss (result->status) != NSS_STATUS_SUCCESS) | |
60c96635 UD |
235 | { |
236 | nis_freeresult (saved_res); | |
237 | return niserr2nss (result->status); | |
238 | } | |
e61abf83 UD |
239 | } |
240 | ||
d71b808a UD |
241 | parse_res = _nss_nisplus_parse_servent (result, serv, buffer, |
242 | buflen, errnop); | |
243 | if (parse_res == -1) | |
60c96635 UD |
244 | { |
245 | nis_freeresult (result); | |
246 | result = saved_res; | |
d71b808a | 247 | *errnop = ERANGE; |
60c96635 UD |
248 | return NSS_STATUS_TRYAGAIN; |
249 | } | |
250 | else | |
251 | { | |
252 | if (saved_res) | |
253 | nis_freeresult (saved_res); | |
254 | } | |
e61abf83 UD |
255 | } |
256 | while (!parse_res); | |
257 | ||
258 | return NSS_STATUS_SUCCESS; | |
259 | } | |
260 | ||
261 | enum nss_status | |
262 | _nss_nisplus_getservent_r (struct servent *result, char *buffer, | |
d71b808a | 263 | size_t buflen, int *errnop) |
e61abf83 UD |
264 | { |
265 | int status; | |
266 | ||
267 | __libc_lock_lock (lock); | |
268 | ||
d71b808a | 269 | status = internal_nisplus_getservent_r (result, buffer, buflen, errnop); |
e61abf83 UD |
270 | |
271 | __libc_lock_unlock (lock); | |
272 | ||
273 | return status; | |
274 | } | |
275 | ||
276 | enum nss_status | |
277 | _nss_nisplus_getservbyname_r (const char *name, const char *protocol, | |
278 | struct servent *serv, | |
d71b808a | 279 | char *buffer, size_t buflen, int *errnop) |
e61abf83 UD |
280 | { |
281 | int parse_res; | |
282 | ||
2d7da676 | 283 | if (tablename_val == NULL) |
d71b808a UD |
284 | { |
285 | enum nss_status status = _nss_create_tablename (errnop); | |
286 | ||
287 | if (status != NSS_STATUS_SUCCESS) | |
288 | return status; | |
289 | } | |
2d7da676 | 290 | |
e61abf83 UD |
291 | if (name == NULL || protocol == NULL) |
292 | { | |
d71b808a | 293 | *errnop = EINVAL; |
e61abf83 UD |
294 | return NSS_STATUS_NOTFOUND; |
295 | } | |
296 | else | |
297 | { | |
298 | nis_result *result; | |
2d7da676 | 299 | char buf[strlen (name) + 255 + tablename_len]; |
e61abf83 UD |
300 | |
301 | /* Search at first in the alias list, and use the correct name | |
302 | for the next search */ | |
2d7da676 UD |
303 | sprintf (buf, "[name=%s,proto=%s],%s", name, protocol, |
304 | tablename_val); | |
305 | result = nis_list (buf, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL); | |
e61abf83 UD |
306 | |
307 | /* If we do not find it, try it as original name. But if the | |
308 | database is correct, we should find it in the first case, too */ | |
d71b808a UD |
309 | if ((result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS) |
310 | || __type_of (result->objects.objects_val) != NIS_ENTRY_OBJ | |
311 | || strcmp (result->objects.objects_val->EN_data.en_type, | |
312 | "services_tbl") != 0 | |
313 | || result->objects.objects_val->EN_data.en_cols.en_cols_len < 4) | |
2d7da676 UD |
314 | sprintf (buf, "[cname=%s,proto=%s],%s", name, protocol, |
315 | tablename_val); | |
e61abf83 | 316 | else |
2d7da676 UD |
317 | sprintf (buf, "[cname=%s,proto=%s],%s", |
318 | NISENTRYVAL (0, 0, result), protocol, tablename_val); | |
e61abf83 UD |
319 | |
320 | nis_freeresult (result); | |
2d7da676 | 321 | result = nis_list (buf, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL); |
e61abf83 UD |
322 | |
323 | if (niserr2nss (result->status) != NSS_STATUS_SUCCESS) | |
324 | { | |
325 | enum nss_status status = niserr2nss (result->status); | |
326 | ||
327 | nis_freeresult (result); | |
328 | return status; | |
329 | } | |
330 | ||
d71b808a UD |
331 | parse_res = _nss_nisplus_parse_servent (result, serv, buffer, buflen, |
332 | errnop); | |
e61abf83 UD |
333 | nis_freeresult (result); |
334 | ||
ac9f45cf | 335 | if (parse_res < 1) |
d71b808a | 336 | { |
ac9f45cf UD |
337 | if (parse_res == -1) |
338 | { | |
339 | *errnop = ERANGE; | |
340 | return NSS_STATUS_TRYAGAIN; | |
341 | } | |
342 | else | |
343 | return NSS_STATUS_NOTFOUND; | |
d71b808a | 344 | } |
ac9f45cf | 345 | return NSS_STATUS_SUCCESS; |
e61abf83 UD |
346 | } |
347 | } | |
348 | ||
349 | enum nss_status | |
350 | _nss_nisplus_getservbynumber_r (const int number, const char *protocol, | |
351 | struct servent *serv, | |
d71b808a | 352 | char *buffer, size_t buflen, int *errnop) |
e61abf83 | 353 | { |
2d7da676 | 354 | if (tablename_val == NULL) |
d71b808a UD |
355 | { |
356 | enum nss_status status = _nss_create_tablename (errnop); | |
357 | ||
358 | if (status != NSS_STATUS_SUCCESS) | |
359 | return status; | |
360 | } | |
e61abf83 UD |
361 | |
362 | if (protocol == NULL) | |
363 | { | |
d71b808a | 364 | *errnop = EINVAL; |
e61abf83 UD |
365 | return NSS_STATUS_NOTFOUND; |
366 | } | |
2d7da676 UD |
367 | else |
368 | { | |
369 | int parse_res; | |
370 | nis_result *result; | |
371 | char buf[60 + strlen (protocol) + tablename_len]; | |
e61abf83 | 372 | |
9a0a462c UD |
373 | sprintf (buf, "[number=%d,proto=%s],%s", |
374 | number, protocol, tablename_val); | |
e61abf83 | 375 | |
2d7da676 | 376 | result = nis_list (buf, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL); |
e61abf83 | 377 | |
2d7da676 UD |
378 | if (niserr2nss (result->status) != NSS_STATUS_SUCCESS) |
379 | { | |
380 | enum nss_status status = niserr2nss (result->status); | |
e61abf83 | 381 | |
2d7da676 UD |
382 | nis_freeresult (result); |
383 | return status; | |
384 | } | |
e61abf83 | 385 | |
d71b808a UD |
386 | parse_res = _nss_nisplus_parse_servent (result, serv, buffer, buflen, |
387 | errnop); | |
2d7da676 | 388 | nis_freeresult (result); |
e61abf83 | 389 | |
ac9f45cf | 390 | if (parse_res < 1) |
d71b808a | 391 | { |
ac9f45cf UD |
392 | if (parse_res == -1) |
393 | { | |
394 | *errnop = ERANGE; | |
395 | return NSS_STATUS_TRYAGAIN; | |
396 | } | |
397 | else | |
398 | return NSS_STATUS_NOTFOUND; | |
d71b808a | 399 | } |
ac9f45cf | 400 | return NSS_STATUS_SUCCESS; |
2d7da676 | 401 | } |
e61abf83 | 402 | } |