4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
24 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
25 * Use is subject to license terms.
35 #include <sys/param.h>
36 #include <sys/types.h>
37 #include <sys/systeminfo.h>
39 #include <rpcsvc/nfs_prot.h>
40 #include <rpcsvc/ypclnt.h>
41 #include <rpcsvc/yp_prot.h>
42 #include <sys/errno.h>
43 #include "automount.h"
48 static int replace_undscr_by_dot(char *);
49 static int nis_err(int);
51 static char nis_mydomain
[YPMAXDOMAIN
];
54 struct dir_entry
**list
;
55 struct dir_entry
*last
;
59 static int readdir_callback(int, char *, int, const char *,
60 int, struct dir_cbdata
*);
63 init_nis(char **stack
, char ***stkptr
)
70 (void) sysinfo(SI_SRPC_DOMAIN
, nis_mydomain
, sizeof (nis_mydomain
));
75 getmapent_nis(key
, map
, ml
, stack
, stkptr
, iswildcard
, isrestricted
)
91 nserr
= yp_match(nis_mydomain
, map
, key
, strlen(key
),
93 if (nserr
== YPERR_MAP
) {
97 "getmapent_nis: memory alloc failed: %m");
98 return (__NSW_UNAVAIL
);
100 if (replace_undscr_by_dot(my_map
))
101 nserr
= yp_match(nis_mydomain
, my_map
, key
,
102 strlen(key
), &nisline
, &nislen
);
106 if (nserr
== YPERR_KEY
) {
108 * Try the default entry "*"
111 nserr
= yp_match(nis_mydomain
, map
, "*", 1,
114 nserr
= yp_match(nis_mydomain
, my_map
, "*", 1,
116 if (!nserr
&& iswildcard
)
120 syslog(LOG_ERR
, "%s: %s",
121 map
, yperr_string(nserr
));
128 nserr
= nis_err(nserr
);
133 * at this point we are sure that yp_match succeeded
134 * so massage the entry by
135 * 1. ignoring # and beyond
136 * 2. trim the trailing whitespace
138 if (lp
= strchr(nisline
, '#'))
140 len
= strlen(nisline
);
142 nserr
= __NSW_NOTFOUND
;
145 lp
= &nisline
[len
- 1];
146 while (lp
> nisline
&& isspace(*lp
))
149 nserr
= __NSW_NOTFOUND
;
152 (void) strcpy(ml
->linebuf
, nisline
);
156 /* now we have the correct line */
158 nserr
= __NSW_SUCCESS
;
161 free((char *)nisline
);
167 loadmaster_nis(mapname
, defopts
, stack
, stkptr
)
168 char *mapname
, *defopts
;
173 char *key
, *nkey
, *val
;
175 char dir
[256], map
[256], qbuff
[256];
176 char *pmap
, *opts
, *my_mapname
;
181 nkey
= NULL
; nkl
= 0;
185 * need a private copy of mapname, because we may change
186 * the underscores by dots. We however do not want the
187 * orignal to be changed, as we may want to use the
188 * original name in some other name service
190 my_mapname
= strdup(mapname
);
191 if (my_mapname
== NULL
) {
192 syslog(LOG_ERR
, "loadmaster_yp: memory alloc failed: %m");
193 /* not the name svc's fault but ... */
194 return (__NSW_UNAVAIL
);
199 err
= yp_first(nis_mydomain
, my_mapname
,
200 &nkey
, &nkl
, &val
, &vl
);
202 if ((err
== YPERR_MAP
) &&
203 (replace_undscr_by_dot(my_mapname
)))
204 err
= yp_first(nis_mydomain
, my_mapname
,
205 &nkey
, &nkl
, &val
, &vl
);
207 if ((err
== YPERR_DOMAIN
) || (err
== YPERR_YPBIND
)) {
209 "can't read nis map %s: %s - retrying",
210 my_mapname
, yperr_string(err
));
211 while ((err
== YPERR_DOMAIN
) ||
212 (err
== YPERR_YPBIND
)) {
214 err
= yp_first(nis_mydomain
, my_mapname
,
215 &nkey
, &nkl
, &val
, &vl
);
218 "nis map %s: read OK.", my_mapname
);
221 err
= yp_next(nis_mydomain
, my_mapname
, key
, kl
,
222 &nkey
, &nkl
, &val
, &vl
);
225 if (err
!= YPERR_NOMORE
&& err
!= YPERR_MAP
)
227 syslog(LOG_ERR
, "%s: %s",
228 my_mapname
, yperr_string(err
));
237 if (kl
>= 256 || vl
>= 256)
239 if (kl
< 2 || vl
< 1)
241 if (isspace(*key
) || *key
== '#')
243 (void) strncpy(dir
, key
, kl
);
245 if (macro_expand("", dir
, qbuff
, sizeof (dir
))) {
247 "%s in NIS map %s: entry too long (max %d chars)",
248 dir
, my_mapname
, sizeof (dir
) - 1);
251 (void) strncpy(map
, val
, vl
);
253 if (macro_expand(dir
, map
, qbuff
, sizeof (map
))) {
255 "%s in NIS map %s: entry too long (max %d chars)",
256 map
, my_mapname
, sizeof (map
) - 1);
260 while (*pmap
&& isspace(*pmap
))
261 pmap
++; /* skip blanks in front of map */
263 while (*opts
&& !isspace(*opts
))
267 while (*opts
&& isspace(*opts
))
277 * Check for no embedded blanks.
279 if (strcspn(opts
, " ") == strlen(opts
)) {
280 dirinit(dir
, pmap
, opts
, 0, stack
, stkptr
);
283 pr_msg("Warning: invalid entry for %s in NIS map %s ignored.\n", dir
, mapname
);
291 * In the context of a master map, if no entry is
292 * found, it is like NOTFOUND
294 if (count
> 0 && err
== YPERR_NOMORE
)
295 return (__NSW_SUCCESS
);
298 return (nis_err(err
));
301 * This case will happen if map is empty
302 * or none of the entries is valid
304 return (__NSW_NOTFOUND
);
309 loaddirect_nis(nismap
, localmap
, opts
, stack
, stkptr
)
310 char *nismap
, *localmap
, *opts
;
314 int first
, err
, count
;
315 char *key
, *nkey
, *val
, *my_nismap
;
321 nkey
= NULL
; nkl
= 0;
326 my_nismap
= strdup(nismap
);
327 if (my_nismap
== NULL
) {
328 syslog(LOG_ERR
, "loadmaster_yp: memory alloc failed: %m");
329 return (__NSW_UNAVAIL
);
334 err
= yp_first(nis_mydomain
, my_nismap
, &nkey
, &nkl
,
337 if ((err
== YPERR_MAP
) &&
338 (replace_undscr_by_dot(my_nismap
)))
339 err
= yp_first(nis_mydomain
, my_nismap
,
340 &nkey
, &nkl
, &val
, &vl
);
342 if ((err
== YPERR_DOMAIN
) || (err
== YPERR_YPBIND
)) {
344 "can't read nis map %s: %s - retrying",
345 my_nismap
, yperr_string(err
));
346 while ((err
== YPERR_DOMAIN
) ||
347 (err
== YPERR_YPBIND
)) {
349 err
= yp_first(nis_mydomain
, my_nismap
,
350 &nkey
, &nkl
, &val
, &vl
);
353 "nis map %s: read OK.", my_nismap
);
356 err
= yp_next(nis_mydomain
, my_nismap
, key
, kl
,
357 &nkey
, &nkl
, &val
, &vl
);
360 if (err
!= YPERR_NOMORE
&& err
!= YPERR_MAP
)
361 syslog(LOG_ERR
, "%s: %s",
362 my_nismap
, yperr_string(err
));
370 if (kl
< 2 || kl
>= 100)
372 if (isspace(*key
) || *key
== '#')
374 (void) strncpy(dir
, key
, kl
);
377 dirinit(dir
, localmap
, opts
, 1, stack
, stkptr
);
385 if (count
> 0 && err
== YPERR_NOMORE
)
386 return (__NSW_SUCCESS
);
388 return (nis_err(err
));
393 replace_undscr_by_dot(map
)
414 return (__NSW_SUCCESS
);
416 return (__NSW_NOTFOUND
);
418 return (__NSW_UNAVAIL
);
420 return (__NSW_UNAVAIL
);
425 getmapkeys_nis(nsmap
, list
, error
, cache_time
, stack
, stkptr
)
427 struct dir_entry
**list
;
434 struct dir_cbdata readdir_cbdata
;
435 struct ypall_callback cback
;
438 char *key
= NULL
, *val
= NULL
;
446 *cache_time
= RDDIR_CACHE_TIME
;
449 * XXX Hack to determine if we need to replace '_' with '.'
450 * Have to use yp_first() since yp_all() simply fails if
451 * the map is not present
453 my_map
= strdup(nsmap
);
454 if (my_map
== NULL
) {
456 "getmapkeys_nis: memory alloc failed: %m");
458 return (__NSW_UNAVAIL
);
460 nserr
= yp_first(nis_mydomain
, my_map
, &key
, &nkl
, &val
, &vl
);
461 if (nserr
== YPERR_MAP
) {
462 if (replace_undscr_by_dot(my_map
)) {
463 nserr
= yp_first(nis_mydomain
, my_map
,
464 &key
, &nkl
, &val
, &vl
);
466 if (nserr
== YPERR_MAP
) {
470 *error
= 0; /* return an empty list */
472 syslog(LOG_ERR
, "%s: %s",
473 nsmap
, yperr_string(nserr
));
476 return (nis_err(nserr
));
484 readdir_cbdata
.list
= list
;
485 readdir_cbdata
.last
= NULL
;
486 readdir_cbdata
.error
= 0;
488 cback
.foreach
= readdir_callback
;
489 cback
.data
= (char *)&readdir_cbdata
;
492 * after all this song and dance we finally
493 * ask for the list of entries
495 nserr
= yp_all(nis_mydomain
, my_map
, &cback
);
498 *error
= readdir_cbdata
.error
;
501 syslog(LOG_ERR
, "%s: %s", nsmap
, yperr_string(nserr
));
506 return (nis_err(nserr
));
509 return (__NSW_SUCCESS
);
513 readdir_callback(instatus
, inkey
, inkeylen
, inval
, invallen
, indata
)
519 struct dir_cbdata
*indata
;
521 struct dir_entry
**list
= indata
->list
;
522 struct dir_entry
*last
= indata
->last
;
523 char key
[MAXPATHLEN
];
530 if (instatus
!= YP_TRUE
)
531 return (0); /* next entry. yp_all may decide otherwise... */
533 if (inkeylen
== 0 || isspace(*inkey
) || *inkey
== '#')
537 * yp_all allocates inkey with two extra bytes which contain
538 * NEWLINE and null but these two bytes are not reflected in
541 strncpy(key
, inkey
, inkeylen
);
542 key
[inkeylen
] = '\0';
545 * Wildcard entry should be ignored - following entries should continue
546 * to be read to corroborate with the way we search for entries in yp,
547 * i.e., first for an exact key match and then a wildcard, if there's
548 * no exact key match.
550 if (key
[0] == '*' && key
[1] == '\0')
553 if (add_dir_entry(key
, list
, &last
)) {
554 indata
->error
= ENOMEM
;
555 return (1); /* get no more entries */