2 * SPDX-License-Identifier: BSD-3-Clause
4 * Copyright (c) 1983, 1993
5 * The Regents of the University of California. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 #include <sys/param.h>
33 #include <sys/socket.h>
34 #include <arpa/inet.h>
47 #include <rpcsvc/yp_prot.h>
48 #include <rpcsvc/ypclnt.h>
50 #include "namespace.h"
51 #include "reentrant.h"
52 #include "un-namespace.h"
53 #include "netdb_private.h"
63 SERVENT_STORAGE_INITIAL = 1 << 10, /* 1 KByte */
64 SERVENT_STORAGE_MAX = 1 << 20, /* 1 MByte */
69 enum nss_lookup_type how;
73 static const ns_src defaultsrc[] = {
74 { NSSRC_COMPAT, NS_SUCCESS },
78 static int servent_unpack(char *, struct servent *, char **, size_t, int *);
80 /* files backend declarations */
86 int compat_mode_active;
88 static void files_endstate(void *);
89 NSS_TLS_HANDLING(files);
91 static int files_servent(void *, void *, va_list);
92 static int files_setservent(void *, void *, va_list);
94 /* db backend declarations */
101 static void db_endstate(void *);
102 NSS_TLS_HANDLING(db);
104 static int db_servent(void *, void *, va_list);
105 static int db_setservent(void *, void *, va_list);
108 /* nis backend declarations */
109 static int nis_servent(void *, void *, va_list);
110 static int nis_setservent(void *, void *, va_list);
115 char yp_domain[MAXHOSTNAMELEN];
119 static void nis_endstate(void *);
120 NSS_TLS_HANDLING(nis);
122 static int nis_servent(void *, void *, va_list);
123 static int nis_setservent(void *, void *, va_list);
126 /* compat backend declarations */
127 static int compat_setservent(void *, void *, va_list);
129 /* get** wrappers for get**_r functions declarations */
130 struct servent_state {
135 static void servent_endstate(void *);
136 NSS_TLS_HANDLING(servent);
146 static int wrap_getservbyname_r(struct key, struct servent *, char *, size_t,
148 static int wrap_getservbyport_r(struct key, struct servent *, char *, size_t,
150 static int wrap_getservent_r(struct key, struct servent *, char *, size_t,
152 static struct servent *getserv(int (*fn)(struct key, struct servent *, char *,
153 size_t, struct servent **), struct key);
156 static int serv_id_func(char *, size_t *, va_list, void *);
157 static int serv_marshal_func(char *, size_t *, void *, va_list, void *);
158 static int serv_unmarshal_func(char *, size_t, void *, va_list, void *);
162 servent_unpack(char *p, struct servent *serv, char **aliases,
163 size_t aliases_size, int *errnop)
165 char *cp, **q, *endp;
171 memset(serv, 0, sizeof(struct servent));
173 cp = strpbrk(p, "#\n");
178 p = strpbrk(p, " \t");
182 while (*p == ' ' || *p == '\t')
184 cp = strpbrk(p, ",/");
189 l = strtol(p, &endp, 10);
190 if (endp == p || *endp != '\0' || l < 0 || l > USHRT_MAX)
192 serv->s_port = htons((in_port_t)l);
195 q = serv->s_aliases = aliases;
196 cp = strpbrk(cp, " \t");
200 if (*cp == ' ' || *cp == '\t') {
204 if (q < &aliases[aliases_size - 1]) {
211 cp = strpbrk(cp, " \t");
221 parse_result(struct servent *serv, char *buffer, size_t bufsize,
222 char *resultbuf, size_t resultbuflen, int *errnop)
227 if (bufsize <= resultbuflen + _ALIGNBYTES + sizeof(char *)) {
231 aliases = (char **)_ALIGN(&buffer[resultbuflen + 1]);
232 aliases_size = (buffer + bufsize - (char *)aliases) / sizeof(char *);
233 if (aliases_size < 1) {
238 memcpy(buffer, resultbuf, resultbuflen);
239 buffer[resultbuflen] = '\0';
241 if (servent_unpack(buffer, serv, aliases, aliases_size, errnop) != 0)
242 return ((*errnop == 0) ? NS_NOTFOUND : NS_RETURN);
246 /* files backend implementation */
248 files_endstate(void *p)
255 f = ((struct files_state *)p)->fp;
263 * compat structures. compat and files sources functionalities are almost
264 * equal, so they all are managed by files_servent function
267 files_servent(void *retval, void *mdata, va_list ap)
269 static const ns_src compat_src[] = {
271 { NSSRC_NIS, NS_SUCCESS },
275 ns_dtab compat_dtab[] = {
276 { NSSRC_DB, db_servent,
277 (void *)((struct servent_mdata *)mdata)->how },
279 { NSSRC_NIS, nis_servent,
280 (void *)((struct servent_mdata *)mdata)->how },
285 struct files_state *st;
289 struct servent_mdata *serv_mdata;
294 struct servent *serv;
305 serv_mdata = (struct servent_mdata *)mdata;
306 switch (serv_mdata->how) {
308 name = va_arg(ap, char *);
309 proto = va_arg(ap, char *);
312 port = va_arg(ap, int);
313 proto = va_arg(ap, char *);
321 serv = va_arg(ap, struct servent *);
322 buffer = va_arg(ap, char *);
323 bufsize = va_arg(ap, size_t);
324 errnop = va_arg(ap,int *);
326 *errnop = files_getstate(&st);
331 st->compat_mode_active = 0;
333 if (st->fp == NULL && (st->fp = fopen(_PATH_SERVICES, "re")) == NULL) {
338 if (serv_mdata->how == nss_lt_all)
342 stayopen = st->stayopen;
347 if (!st->compat_mode_active) {
348 if ((line = fgetln(st->fp, &linesize)) == NULL) {
354 if (*line=='+' && serv_mdata->compat_mode != 0)
355 st->compat_mode_active = 1;
358 if (st->compat_mode_active != 0) {
359 switch (serv_mdata->how) {
361 rv = nsdispatch(retval, compat_dtab,
362 NSDB_SERVICES_COMPAT, "getservbyname_r",
363 compat_src, name, proto, serv, buffer,
367 rv = nsdispatch(retval, compat_dtab,
368 NSDB_SERVICES_COMPAT, "getservbyport_r",
369 compat_src, port, proto, serv, buffer,
373 rv = nsdispatch(retval, compat_dtab,
374 NSDB_SERVICES_COMPAT, "getservent_r",
375 compat_src, serv, buffer, bufsize, errnop);
379 if (!(rv & NS_TERMINATE) ||
380 serv_mdata->how != nss_lt_all)
381 st->compat_mode_active = 0;
386 rv = parse_result(serv, buffer, bufsize, line, linesize,
388 if (rv == NS_NOTFOUND)
394 switch (serv_mdata->how) {
396 if (strcmp(name, serv->s_name) == 0)
398 for (cp = serv->s_aliases; *cp; cp++)
399 if (strcmp(name, *cp) == 0)
404 if (proto == NULL || strcmp(serv->s_proto, proto) == 0)
408 if (port != serv->s_port)
411 if (proto == NULL || strcmp(serv->s_proto, proto) == 0)
419 } while (!(rv & NS_TERMINATE));
421 if (!stayopen && st->fp != NULL) {
426 if ((rv == NS_SUCCESS) && (retval != NULL))
427 *(struct servent **)retval=serv;
433 files_setservent(void *retval, void *mdata, va_list ap)
435 struct files_state *st;
439 rv = files_getstate(&st);
443 switch ((enum constants)(uintptr_t)mdata) {
447 st->fp = fopen(_PATH_SERVICES, "re");
453 if (st->fp != NULL) {
463 st->compat_mode_active = 0;
467 /* db backend implementation */
476 db = ((struct db_state *)p)->db;
484 db_servent(void *retval, void *mdata, va_list ap)
487 DBT key, data, *result;
494 enum nss_lookup_type how;
499 struct servent *serv;
506 how = (enum nss_lookup_type)(uintptr_t)mdata;
509 name = va_arg(ap, char *);
510 proto = va_arg(ap, char *);
513 port = va_arg(ap, int);
514 proto = va_arg(ap, char *);
522 serv = va_arg(ap, struct servent *);
523 buffer = va_arg(ap, char *);
524 bufsize = va_arg(ap, size_t);
525 errnop = va_arg(ap,int *);
527 *errnop = db_getstate(&st);
531 if (how == nss_lt_all && st->keynum < 0)
532 return (NS_NOTFOUND);
534 if (st->db == NULL) {
535 st->db = dbopen(_PATH_SERVICES_DB, O_RDONLY, 0, DB_HASH, NULL);
536 if (st->db == NULL) {
542 stayopen = (how == nss_lt_all) ? 1 : st->stayopen;
550 key.size = snprintf(buf, sizeof(buf),
553 key.size = snprintf(buf, sizeof(buf),
554 "\376%s/%s", name, proto);
556 if (db->get(db, &key, &data, 0) != 0 ||
557 db->get(db, &data, &key, 0) != 0) {
567 key.size = snprintf(buf, sizeof(buf),
570 key.size = snprintf(buf, sizeof(buf),
571 "\377%d/%s", port, proto);
573 if (db->get(db, &key, &data, 0) != 0 ||
574 db->get(db, &data, &key, 0) != 0) {
582 key.size = snprintf(buf, sizeof(buf), "%d",
585 if (db->get(db, &key, &data, 0) != 0) {
594 rv = parse_result(serv, buffer, bufsize, result->data,
595 result->size - 1, errnop);
597 } while (!(rv & NS_TERMINATE) && how == nss_lt_all);
600 if (!stayopen && st->db != NULL) {
605 if (rv == NS_SUCCESS && retval != NULL)
606 *(struct servent **)retval = serv;
612 db_setservent(void *retval, void *mdata, va_list ap)
619 rv = db_getstate(&st);
623 switch ((enum constants)(uintptr_t)mdata) {
644 /* nis backend implementation */
647 nis_endstate(void *p)
652 free(((struct nis_state *)p)->yp_key);
657 nis_servent(void *retval, void *mdata, va_list ap)
659 char *resultbuf, *lastkey;
663 struct nis_state *st;
666 enum nss_lookup_type how;
671 struct servent *serv;
679 how = (enum nss_lookup_type)(uintptr_t)mdata;
682 name = va_arg(ap, char *);
683 proto = va_arg(ap, char *);
686 port = va_arg(ap, int);
687 proto = va_arg(ap, char *);
695 serv = va_arg(ap, struct servent *);
696 buffer = va_arg(ap, char *);
697 bufsize = va_arg(ap, size_t);
698 errnop = va_arg(ap, int *);
700 *errnop = nis_getstate(&st);
704 if (st->yp_domain[0] == '\0') {
705 if (getdomainname(st->yp_domain, sizeof st->yp_domain)) {
715 asprintf(&buf, "%s/%s", name, proto);
717 return (NS_TRYAGAIN);
718 if (yp_match(st->yp_domain, "services.byname", buf,
719 strlen(buf), &resultbuf, &resultbuflen)) {
726 asprintf(&buf, "%d/%s", ntohs(port), proto);
728 return (NS_TRYAGAIN);
731 * We have to be a little flexible
732 * here. Ideally you're supposed to have both
733 * a services.byname and a services.byport
734 * map, but some systems have only
735 * services.byname. FreeBSD cheats a little by
736 * putting the services.byport information in
737 * the same map as services.byname so that
738 * either case will work. We allow for both
739 * possibilities here: if there is no
740 * services.byport map, we try services.byname
743 rv = yp_match(st->yp_domain, "services.byport", buf,
744 strlen(buf), &resultbuf, &resultbuflen);
746 if (rv == YPERR_MAP) {
747 if (yp_match(st->yp_domain,
748 "services.byname", buf,
749 strlen(buf), &resultbuf,
762 if (!st->yp_stepping) {
764 rv = yp_first(st->yp_domain, "services.byname",
765 &st->yp_key, &st->yp_keylen, &resultbuf,
773 lastkey = st->yp_key;
774 rv = yp_next(st->yp_domain, "services.byname",
775 st->yp_key, st->yp_keylen, &st->yp_key,
776 &st->yp_keylen, &resultbuf, &resultbuflen);
787 rv = parse_result(serv, buffer, bufsize, resultbuf,
788 resultbuflen, errnop);
791 } while (!(rv & NS_TERMINATE) && how == nss_lt_all);
795 if (rv == NS_SUCCESS && retval != NULL)
796 *(struct servent **)retval = serv;
802 nis_setservent(void *result, void *mdata, va_list ap)
804 struct nis_state *st;
807 rv = nis_getstate(&st);
811 switch ((enum constants)(uintptr_t)mdata) {
826 /* compat backend implementation */
828 compat_setservent(void *retval, void *mdata, va_list ap)
830 static const ns_src compat_src[] = {
832 { NSSRC_NIS, NS_SUCCESS },
836 ns_dtab compat_dtab[] = {
837 { NSSRC_DB, db_setservent, mdata },
839 { NSSRC_NIS, nis_setservent, mdata },
845 (void)files_setservent(retval, mdata, ap);
847 switch ((enum constants)(uintptr_t)mdata) {
850 (void)nsdispatch(retval, compat_dtab, NSDB_SERVICES_COMPAT,
851 "setservent", compat_src, f);
854 (void)nsdispatch(retval, compat_dtab, NSDB_SERVICES_COMPAT,
855 "endservent", compat_src);
866 serv_id_func(char *buffer, size_t *buffer_size, va_list ap, void *cache_mdata)
872 size_t desired_size, size, size2;
873 enum nss_lookup_type lookup_type;
874 int res = NS_UNAVAIL;
876 lookup_type = (enum nss_lookup_type)(uintptr_t)cache_mdata;
877 switch (lookup_type) {
879 name = va_arg(ap, char *);
880 proto = va_arg(ap, char *);
883 desired_size = sizeof(enum nss_lookup_type) + size + 1;
885 size2 = strlen(proto);
886 desired_size += size2 + 1;
890 if (desired_size > *buffer_size) {
895 memcpy(buffer, &lookup_type, sizeof(enum nss_lookup_type));
896 memcpy(buffer + sizeof(enum nss_lookup_type), name, size + 1);
899 memcpy(buffer + sizeof(enum nss_lookup_type) + size + 1,
905 port = va_arg(ap, int);
906 proto = va_arg(ap, char *);
908 desired_size = sizeof(enum nss_lookup_type) + sizeof(int);
910 size = strlen(proto);
911 desired_size += size + 1;
915 if (desired_size > *buffer_size) {
920 memcpy(buffer, &lookup_type, sizeof(enum nss_lookup_type));
921 memcpy(buffer + sizeof(enum nss_lookup_type), &port,
925 memcpy(buffer + sizeof(enum nss_lookup_type) +
926 sizeof(int), proto, size + 1);
931 /* should be unreachable */
936 *buffer_size = desired_size;
941 serv_marshal_func(char *buffer, size_t *buffer_size, void *retval, va_list ap,
945 char *proto __unused;
947 struct servent *serv;
948 char *orig_buf __unused;
949 size_t orig_buf_size __unused;
951 struct servent new_serv;
958 switch ((enum nss_lookup_type)(uintptr_t)cache_mdata) {
960 name = va_arg(ap, char *);
961 proto = va_arg(ap, char *);
964 port = va_arg(ap, int);
965 proto = va_arg(ap, char *);
970 /* should be unreachable */
974 serv = va_arg(ap, struct servent *);
975 orig_buf = va_arg(ap, char *);
976 orig_buf_size = va_arg(ap, size_t);
978 desired_size = _ALIGNBYTES + sizeof(struct servent) + sizeof(char *);
979 if (serv->s_name != NULL)
980 desired_size += strlen(serv->s_name) + 1;
981 if (serv->s_proto != NULL)
982 desired_size += strlen(serv->s_proto) + 1;
985 if (serv->s_aliases != NULL) {
986 for (alias = serv->s_aliases; *alias; ++alias) {
987 desired_size += strlen(*alias) + 1;
991 desired_size += _ALIGNBYTES +
992 sizeof(char *) * (aliases_size + 1);
995 if (*buffer_size < desired_size) {
996 /* this assignment is here for future use */
997 *buffer_size = desired_size;
1001 memcpy(&new_serv, serv, sizeof(struct servent));
1002 memset(buffer, 0, desired_size);
1004 *buffer_size = desired_size;
1005 p = buffer + sizeof(struct servent) + sizeof(char *);
1006 memcpy(buffer + sizeof(struct servent), &p, sizeof(char *));
1007 p = (char *)_ALIGN(p);
1009 if (new_serv.s_name != NULL) {
1010 size = strlen(new_serv.s_name);
1011 memcpy(p, new_serv.s_name, size);
1012 new_serv.s_name = p;
1016 if (new_serv.s_proto != NULL) {
1017 size = strlen(new_serv.s_proto);
1018 memcpy(p, new_serv.s_proto, size);
1019 new_serv.s_proto = p;
1023 if (new_serv.s_aliases != NULL) {
1024 p = (char *)_ALIGN(p);
1025 memcpy(p, new_serv.s_aliases, sizeof(char *) * aliases_size);
1026 new_serv.s_aliases = (char **)p;
1027 p += sizeof(char *) * (aliases_size + 1);
1029 for (alias = new_serv.s_aliases; *alias; ++alias) {
1030 size = strlen(*alias);
1031 memcpy(p, *alias, size);
1037 memcpy(buffer, &new_serv, sizeof(struct servent));
1038 return (NS_SUCCESS);
1042 serv_unmarshal_func(char *buffer, size_t buffer_size, void *retval, va_list ap,
1045 char *name __unused;
1046 char *proto __unused;
1048 struct servent *serv;
1052 size_t orig_buf_size;
1055 switch ((enum nss_lookup_type)(uintptr_t)cache_mdata) {
1057 name = va_arg(ap, char *);
1058 proto = va_arg(ap, char *);
1061 port = va_arg(ap, int);
1062 proto = va_arg(ap, char *);
1067 /* should be unreachable */
1068 return (NS_UNAVAIL);
1071 serv = va_arg(ap, struct servent *);
1072 orig_buf = va_arg(ap, char *);
1073 orig_buf_size = va_arg(ap, size_t);
1074 ret_errno = va_arg(ap, int *);
1077 buffer_size - sizeof(struct servent) - sizeof(char *)) {
1078 *ret_errno = ERANGE;
1082 memcpy(serv, buffer, sizeof(struct servent));
1083 memcpy(&p, buffer + sizeof(struct servent), sizeof(char *));
1085 orig_buf = (char *)_ALIGN(orig_buf);
1086 memcpy(orig_buf, buffer + sizeof(struct servent) + sizeof(char *) +
1087 (_ALIGN(p) - (size_t)p),
1088 buffer_size - sizeof(struct servent) - sizeof(char *) -
1089 (_ALIGN(p) - (size_t)p));
1090 p = (char *)_ALIGN(p);
1092 NS_APPLY_OFFSET(serv->s_name, orig_buf, p, char *);
1093 NS_APPLY_OFFSET(serv->s_proto, orig_buf, p, char *);
1094 if (serv->s_aliases != NULL) {
1095 NS_APPLY_OFFSET(serv->s_aliases, orig_buf, p, char **);
1097 for (alias = serv->s_aliases; *alias; ++alias)
1098 NS_APPLY_OFFSET(*alias, orig_buf, p, char *);
1102 *((struct servent **)retval) = serv;
1103 return (NS_SUCCESS);
1106 NSS_MP_CACHE_HANDLING(services);
1107 #endif /* NS_CACHING */
1109 /* get**_r functions implementation */
1111 getservbyname_r(const char *name, const char *proto, struct servent *serv,
1112 char *buffer, size_t bufsize, struct servent **result)
1114 static const struct servent_mdata mdata = { nss_lt_name, 0 };
1115 static const struct servent_mdata compat_mdata = { nss_lt_name, 1 };
1117 static const nss_cache_info cache_info =
1118 NS_COMMON_CACHE_INFO_INITIALIZER(
1119 services, (void *)nss_lt_name,
1120 serv_id_func, serv_marshal_func, serv_unmarshal_func);
1121 #endif /* NS_CACHING */
1122 static const ns_dtab dtab[] = {
1123 { NSSRC_FILES, files_servent, (void *)&mdata },
1124 { NSSRC_DB, db_servent, (void *)nss_lt_name },
1126 { NSSRC_NIS, nis_servent, (void *)nss_lt_name },
1128 { NSSRC_COMPAT, files_servent, (void *)&compat_mdata },
1130 NS_CACHE_CB(&cache_info)
1132 { NULL, NULL, NULL }
1138 rv = nsdispatch(result, dtab, NSDB_SERVICES, "getservbyname_r",
1139 defaultsrc, name, proto, serv, buffer, bufsize, &ret_errno);
1141 if (rv == NS_SUCCESS)
1148 getservbyport_r(int port, const char *proto, struct servent *serv,
1149 char *buffer, size_t bufsize, struct servent **result)
1151 static const struct servent_mdata mdata = { nss_lt_id, 0 };
1152 static const struct servent_mdata compat_mdata = { nss_lt_id, 1 };
1154 static const nss_cache_info cache_info =
1155 NS_COMMON_CACHE_INFO_INITIALIZER(
1156 services, (void *)nss_lt_id,
1157 serv_id_func, serv_marshal_func, serv_unmarshal_func);
1159 static const ns_dtab dtab[] = {
1160 { NSSRC_FILES, files_servent, (void *)&mdata },
1161 { NSSRC_DB, db_servent, (void *)nss_lt_id },
1163 { NSSRC_NIS, nis_servent, (void *)nss_lt_id },
1165 { NSSRC_COMPAT, files_servent, (void *)&compat_mdata },
1167 NS_CACHE_CB(&cache_info)
1169 { NULL, NULL, NULL }
1175 rv = nsdispatch(result, dtab, NSDB_SERVICES, "getservbyport_r",
1176 defaultsrc, port, proto, serv, buffer, bufsize, &ret_errno);
1178 if (rv == NS_SUCCESS)
1185 getservent_r(struct servent *serv, char *buffer, size_t bufsize,
1186 struct servent **result)
1188 static const struct servent_mdata mdata = { nss_lt_all, 0 };
1189 static const struct servent_mdata compat_mdata = { nss_lt_all, 1 };
1191 static const nss_cache_info cache_info = NS_MP_CACHE_INFO_INITIALIZER(
1192 services, (void *)nss_lt_all,
1193 serv_marshal_func, serv_unmarshal_func);
1195 static const ns_dtab dtab[] = {
1196 { NSSRC_FILES, files_servent, (void *)&mdata },
1197 { NSSRC_DB, db_servent, (void *)nss_lt_all },
1199 { NSSRC_NIS, nis_servent, (void *)nss_lt_all },
1201 { NSSRC_COMPAT, files_servent, (void *)&compat_mdata },
1203 NS_CACHE_CB(&cache_info)
1205 { NULL, NULL, NULL }
1211 rv = nsdispatch(result, dtab, NSDB_SERVICES, "getservent_r",
1212 defaultsrc, serv, buffer, bufsize, &ret_errno);
1214 if (rv == NS_SUCCESS)
1221 setservent(int stayopen)
1224 static const nss_cache_info cache_info = NS_MP_CACHE_INFO_INITIALIZER(
1225 services, (void *)nss_lt_all,
1228 static const ns_dtab dtab[] = {
1229 { NSSRC_FILES, files_setservent, (void *)SETSERVENT },
1230 { NSSRC_DB, db_setservent, (void *)SETSERVENT },
1232 { NSSRC_NIS, nis_setservent, (void *)SETSERVENT },
1234 { NSSRC_COMPAT, compat_setservent, (void *)SETSERVENT },
1236 NS_CACHE_CB(&cache_info)
1238 { NULL, NULL, NULL }
1241 (void)nsdispatch(NULL, dtab, NSDB_SERVICES, "setservent", defaultsrc,
1249 static const nss_cache_info cache_info = NS_MP_CACHE_INFO_INITIALIZER(
1250 services, (void *)nss_lt_all,
1253 static const ns_dtab dtab[] = {
1254 { NSSRC_FILES, files_setservent, (void *)ENDSERVENT },
1255 { NSSRC_DB, db_setservent, (void *)ENDSERVENT },
1257 { NSSRC_NIS, nis_setservent, (void *)ENDSERVENT },
1259 { NSSRC_COMPAT, compat_setservent, (void *)ENDSERVENT },
1261 NS_CACHE_CB(&cache_info)
1263 { NULL, NULL, NULL }
1266 (void)nsdispatch(NULL, dtab, NSDB_SERVICES, "endservent", defaultsrc);
1269 /* get** wrappers for get**_r functions implementation */
1271 servent_endstate(void *p)
1276 free(((struct servent_state *)p)->buffer);
1281 wrap_getservbyname_r(struct key key, struct servent *serv, char *buffer,
1282 size_t bufsize, struct servent **res)
1284 return (getservbyname_r(key.name, key.proto, serv, buffer, bufsize,
1289 wrap_getservbyport_r(struct key key, struct servent *serv, char *buffer,
1290 size_t bufsize, struct servent **res)
1292 return (getservbyport_r(key.port, key.proto, serv, buffer, bufsize,
1297 wrap_getservent_r(struct key key, struct servent *serv, char *buffer,
1298 size_t bufsize, struct servent **res)
1300 return (getservent_r(serv, buffer, bufsize, res));
1303 static struct servent *
1304 getserv(int (*fn)(struct key, struct servent *, char *, size_t,
1305 struct servent **), struct key key)
1308 struct servent *res;
1309 struct servent_state * st;
1311 rv = servent_getstate(&st);
1317 if (st->buffer == NULL) {
1318 st->buffer = malloc(SERVENT_STORAGE_INITIAL);
1319 if (st->buffer == NULL)
1321 st->bufsize = SERVENT_STORAGE_INITIAL;
1324 rv = fn(key, &st->serv, st->buffer, st->bufsize, &res);
1325 if (res == NULL && rv == ERANGE) {
1327 if ((st->bufsize << 1) > SERVENT_STORAGE_MAX) {
1333 st->buffer = malloc(st->bufsize);
1334 if (st->buffer == NULL)
1337 } while (res == NULL && rv == ERANGE);
1345 getservbyname(const char *name, const char *proto)
1352 return (getserv(wrap_getservbyname_r, key));
1356 getservbyport(int port, const char *proto)
1363 return (getserv(wrap_getservbyport_r, key));
1374 return (getserv(wrap_getservent_r, key));