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 #if defined(LIBC_SCCS) && !defined(lint)
33 static char sccsid[] = "@(#)getservent.c 8.1 (Berkeley) 6/4/93";
34 #endif /* LIBC_SCCS and not lint */
35 #include <sys/cdefs.h>
36 __FBSDID("$FreeBSD$");
38 #include <sys/param.h>
39 #include <sys/socket.h>
40 #include <arpa/inet.h>
53 #include <rpcsvc/yp_prot.h>
54 #include <rpcsvc/ypclnt.h>
56 #include "namespace.h"
57 #include "reentrant.h"
58 #include "un-namespace.h"
59 #include "netdb_private.h"
69 SERVENT_STORAGE_INITIAL = 1 << 10, /* 1 KByte */
70 SERVENT_STORAGE_MAX = 1 << 20, /* 1 MByte */
75 enum nss_lookup_type how;
79 static const ns_src defaultsrc[] = {
80 { NSSRC_COMPAT, NS_SUCCESS },
84 static int servent_unpack(char *, struct servent *, char **, size_t, int *);
86 /* files backend declarations */
92 int compat_mode_active;
94 static void files_endstate(void *);
95 NSS_TLS_HANDLING(files);
97 static int files_servent(void *, void *, va_list);
98 static int files_setservent(void *, void *, va_list);
100 /* db backend declarations */
107 static void db_endstate(void *);
108 NSS_TLS_HANDLING(db);
110 static int db_servent(void *, void *, va_list);
111 static int db_setservent(void *, void *, va_list);
114 /* nis backend declarations */
115 static int nis_servent(void *, void *, va_list);
116 static int nis_setservent(void *, void *, va_list);
121 char yp_domain[MAXHOSTNAMELEN];
125 static void nis_endstate(void *);
126 NSS_TLS_HANDLING(nis);
128 static int nis_servent(void *, void *, va_list);
129 static int nis_setservent(void *, void *, va_list);
132 /* compat backend declarations */
133 static int compat_setservent(void *, void *, va_list);
135 /* get** wrappers for get**_r functions declarations */
136 struct servent_state {
141 static void servent_endstate(void *);
142 NSS_TLS_HANDLING(servent);
152 static int wrap_getservbyname_r(struct key, struct servent *, char *, size_t,
154 static int wrap_getservbyport_r(struct key, struct servent *, char *, size_t,
156 static int wrap_getservent_r(struct key, struct servent *, char *, size_t,
158 static struct servent *getserv(int (*fn)(struct key, struct servent *, char *,
159 size_t, struct servent **), struct key);
162 static int serv_id_func(char *, size_t *, va_list, void *);
163 static int serv_marshal_func(char *, size_t *, void *, va_list, void *);
164 static int serv_unmarshal_func(char *, size_t, void *, va_list, void *);
168 servent_unpack(char *p, struct servent *serv, char **aliases,
169 size_t aliases_size, int *errnop)
171 char *cp, **q, *endp;
177 memset(serv, 0, sizeof(struct servent));
179 cp = strpbrk(p, "#\n");
184 p = strpbrk(p, " \t");
188 while (*p == ' ' || *p == '\t')
190 cp = strpbrk(p, ",/");
195 l = strtol(p, &endp, 10);
196 if (endp == p || *endp != '\0' || l < 0 || l > USHRT_MAX)
198 serv->s_port = htons((in_port_t)l);
201 q = serv->s_aliases = aliases;
202 cp = strpbrk(cp, " \t");
206 if (*cp == ' ' || *cp == '\t') {
210 if (q < &aliases[aliases_size - 1]) {
217 cp = strpbrk(cp, " \t");
227 parse_result(struct servent *serv, char *buffer, size_t bufsize,
228 char *resultbuf, size_t resultbuflen, int *errnop)
233 if (bufsize <= resultbuflen + _ALIGNBYTES + sizeof(char *)) {
237 aliases = (char **)_ALIGN(&buffer[resultbuflen + 1]);
238 aliases_size = (buffer + bufsize - (char *)aliases) / sizeof(char *);
239 if (aliases_size < 1) {
244 memcpy(buffer, resultbuf, resultbuflen);
245 buffer[resultbuflen] = '\0';
247 if (servent_unpack(buffer, serv, aliases, aliases_size, errnop) != 0)
248 return ((*errnop == 0) ? NS_NOTFOUND : NS_RETURN);
252 /* files backend implementation */
254 files_endstate(void *p)
261 f = ((struct files_state *)p)->fp;
269 * compat structures. compat and files sources functionalities are almost
270 * equal, so they all are managed by files_servent function
273 files_servent(void *retval, void *mdata, va_list ap)
275 static const ns_src compat_src[] = {
277 { NSSRC_NIS, NS_SUCCESS },
281 ns_dtab compat_dtab[] = {
282 { NSSRC_DB, db_servent,
283 (void *)((struct servent_mdata *)mdata)->how },
285 { NSSRC_NIS, nis_servent,
286 (void *)((struct servent_mdata *)mdata)->how },
291 struct files_state *st;
295 struct servent_mdata *serv_mdata;
300 struct servent *serv;
311 serv_mdata = (struct servent_mdata *)mdata;
312 switch (serv_mdata->how) {
314 name = va_arg(ap, char *);
315 proto = va_arg(ap, char *);
318 port = va_arg(ap, int);
319 proto = va_arg(ap, char *);
327 serv = va_arg(ap, struct servent *);
328 buffer = va_arg(ap, char *);
329 bufsize = va_arg(ap, size_t);
330 errnop = va_arg(ap,int *);
332 *errnop = files_getstate(&st);
337 st->compat_mode_active = 0;
339 if (st->fp == NULL && (st->fp = fopen(_PATH_SERVICES, "re")) == NULL) {
344 if (serv_mdata->how == nss_lt_all)
348 stayopen = st->stayopen;
353 if (!st->compat_mode_active) {
354 if ((line = fgetln(st->fp, &linesize)) == NULL) {
360 if (*line=='+' && serv_mdata->compat_mode != 0)
361 st->compat_mode_active = 1;
364 if (st->compat_mode_active != 0) {
365 switch (serv_mdata->how) {
367 rv = nsdispatch(retval, compat_dtab,
368 NSDB_SERVICES_COMPAT, "getservbyname_r",
369 compat_src, name, proto, serv, buffer,
373 rv = nsdispatch(retval, compat_dtab,
374 NSDB_SERVICES_COMPAT, "getservbyport_r",
375 compat_src, port, proto, serv, buffer,
379 rv = nsdispatch(retval, compat_dtab,
380 NSDB_SERVICES_COMPAT, "getservent_r",
381 compat_src, serv, buffer, bufsize, errnop);
385 if (!(rv & NS_TERMINATE) ||
386 serv_mdata->how != nss_lt_all)
387 st->compat_mode_active = 0;
392 rv = parse_result(serv, buffer, bufsize, line, linesize,
394 if (rv == NS_NOTFOUND)
400 switch (serv_mdata->how) {
402 if (strcmp(name, serv->s_name) == 0)
404 for (cp = serv->s_aliases; *cp; cp++)
405 if (strcmp(name, *cp) == 0)
410 if (proto == NULL || strcmp(serv->s_proto, proto) == 0)
414 if (port != serv->s_port)
417 if (proto == NULL || strcmp(serv->s_proto, proto) == 0)
425 } while (!(rv & NS_TERMINATE));
427 if (!stayopen && st->fp != NULL) {
432 if ((rv == NS_SUCCESS) && (retval != NULL))
433 *(struct servent **)retval=serv;
439 files_setservent(void *retval, void *mdata, va_list ap)
441 struct files_state *st;
445 rv = files_getstate(&st);
449 switch ((enum constants)mdata) {
453 st->fp = fopen(_PATH_SERVICES, "re");
459 if (st->fp != NULL) {
469 st->compat_mode_active = 0;
473 /* db backend implementation */
482 db = ((struct db_state *)p)->db;
490 db_servent(void *retval, void *mdata, va_list ap)
493 DBT key, data, *result;
500 enum nss_lookup_type how;
505 struct servent *serv;
512 how = (enum nss_lookup_type)mdata;
515 name = va_arg(ap, char *);
516 proto = va_arg(ap, char *);
519 port = va_arg(ap, int);
520 proto = va_arg(ap, char *);
528 serv = va_arg(ap, struct servent *);
529 buffer = va_arg(ap, char *);
530 bufsize = va_arg(ap, size_t);
531 errnop = va_arg(ap,int *);
533 *errnop = db_getstate(&st);
537 if (how == nss_lt_all && st->keynum < 0)
538 return (NS_NOTFOUND);
540 if (st->db == NULL) {
541 st->db = dbopen(_PATH_SERVICES_DB, O_RDONLY, 0, DB_HASH, NULL);
542 if (st->db == NULL) {
548 stayopen = (how == nss_lt_all) ? 1 : st->stayopen;
556 key.size = snprintf(buf, sizeof(buf),
559 key.size = snprintf(buf, sizeof(buf),
560 "\376%s/%s", name, proto);
562 if (db->get(db, &key, &data, 0) != 0 ||
563 db->get(db, &data, &key, 0) != 0) {
573 key.size = snprintf(buf, sizeof(buf),
576 key.size = snprintf(buf, sizeof(buf),
577 "\377%d/%s", port, proto);
579 if (db->get(db, &key, &data, 0) != 0 ||
580 db->get(db, &data, &key, 0) != 0) {
588 key.size = snprintf(buf, sizeof(buf), "%d",
591 if (db->get(db, &key, &data, 0) != 0) {
600 rv = parse_result(serv, buffer, bufsize, result->data,
601 result->size - 1, errnop);
603 } while (!(rv & NS_TERMINATE) && how == nss_lt_all);
606 if (!stayopen && st->db != NULL) {
611 if (rv == NS_SUCCESS && retval != NULL)
612 *(struct servent **)retval = serv;
618 db_setservent(void *retval, void *mdata, va_list ap)
625 rv = db_getstate(&st);
629 switch ((enum constants)mdata) {
650 /* nis backend implementation */
653 nis_endstate(void *p)
658 free(((struct nis_state *)p)->yp_key);
663 nis_servent(void *retval, void *mdata, va_list ap)
665 char *resultbuf, *lastkey;
667 char buf[YPMAXRECORD + 2];
669 struct nis_state *st;
672 enum nss_lookup_type how;
677 struct servent *serv;
684 how = (enum nss_lookup_type)mdata;
687 name = va_arg(ap, char *);
688 proto = va_arg(ap, char *);
691 port = va_arg(ap, int);
692 proto = va_arg(ap, char *);
700 serv = va_arg(ap, struct servent *);
701 buffer = va_arg(ap, char *);
702 bufsize = va_arg(ap, size_t);
703 errnop = va_arg(ap, int *);
705 *errnop = nis_getstate(&st);
709 if (st->yp_domain[0] == '\0') {
710 if (getdomainname(st->yp_domain, sizeof st->yp_domain)) {
719 snprintf(buf, sizeof(buf), "%s/%s", name, proto);
720 if (yp_match(st->yp_domain, "services.byname", buf,
721 strlen(buf), &resultbuf, &resultbuflen)) {
727 snprintf(buf, sizeof(buf), "%d/%s", ntohs(port),
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);
794 if (rv == NS_SUCCESS && retval != NULL)
795 *(struct servent **)retval = serv;
801 nis_setservent(void *result, void *mdata, va_list ap)
803 struct nis_state *st;
806 rv = nis_getstate(&st);
810 switch ((enum constants)mdata) {
825 /* compat backend implementation */
827 compat_setservent(void *retval, void *mdata, va_list ap)
829 static const ns_src compat_src[] = {
831 { NSSRC_NIS, NS_SUCCESS },
835 ns_dtab compat_dtab[] = {
836 { NSSRC_DB, db_setservent, mdata },
838 { NSSRC_NIS, nis_setservent, mdata },
844 (void)files_setservent(retval, mdata, ap);
846 switch ((enum constants)mdata) {
849 (void)nsdispatch(retval, compat_dtab, NSDB_SERVICES_COMPAT,
850 "setservent", compat_src, f);
853 (void)nsdispatch(retval, compat_dtab, NSDB_SERVICES_COMPAT,
854 "endservent", compat_src);
865 serv_id_func(char *buffer, size_t *buffer_size, va_list ap, void *cache_mdata)
871 size_t desired_size, size, size2;
872 enum nss_lookup_type lookup_type;
873 int res = NS_UNAVAIL;
875 lookup_type = (enum nss_lookup_type)cache_mdata;
876 switch (lookup_type) {
878 name = va_arg(ap, char *);
879 proto = va_arg(ap, char *);
882 desired_size = sizeof(enum nss_lookup_type) + size + 1;
884 size2 = strlen(proto);
885 desired_size += size2 + 1;
889 if (desired_size > *buffer_size) {
894 memcpy(buffer, &lookup_type, sizeof(enum nss_lookup_type));
895 memcpy(buffer + sizeof(enum nss_lookup_type), name, size + 1);
898 memcpy(buffer + sizeof(enum nss_lookup_type) + size + 1,
904 port = va_arg(ap, int);
905 proto = va_arg(ap, char *);
907 desired_size = sizeof(enum nss_lookup_type) + sizeof(int);
909 size = strlen(proto);
910 desired_size += size + 1;
914 if (desired_size > *buffer_size) {
919 memcpy(buffer, &lookup_type, sizeof(enum nss_lookup_type));
920 memcpy(buffer + sizeof(enum nss_lookup_type), &port,
924 memcpy(buffer + sizeof(enum nss_lookup_type) +
925 sizeof(int), proto, size + 1);
930 /* should be unreachable */
935 *buffer_size = desired_size;
940 serv_marshal_func(char *buffer, size_t *buffer_size, void *retval, va_list ap,
946 struct servent *serv;
948 size_t orig_buf_size;
950 struct servent new_serv;
957 switch ((enum nss_lookup_type)cache_mdata) {
959 name = va_arg(ap, char *);
960 proto = va_arg(ap, char *);
963 port = va_arg(ap, int);
964 proto = va_arg(ap, char *);
969 /* should be unreachable */
973 serv = va_arg(ap, struct servent *);
974 orig_buf = va_arg(ap, char *);
975 orig_buf_size = va_arg(ap, size_t);
977 desired_size = _ALIGNBYTES + sizeof(struct servent) + sizeof(char *);
978 if (serv->s_name != NULL)
979 desired_size += strlen(serv->s_name) + 1;
980 if (serv->s_proto != NULL)
981 desired_size += strlen(serv->s_proto) + 1;
984 if (serv->s_aliases != NULL) {
985 for (alias = serv->s_aliases; *alias; ++alias) {
986 desired_size += strlen(*alias) + 1;
990 desired_size += _ALIGNBYTES +
991 sizeof(char *) * (aliases_size + 1);
994 if (*buffer_size < desired_size) {
995 /* this assignment is here for future use */
996 *buffer_size = desired_size;
1000 memcpy(&new_serv, serv, sizeof(struct servent));
1001 memset(buffer, 0, desired_size);
1003 *buffer_size = desired_size;
1004 p = buffer + sizeof(struct servent) + sizeof(char *);
1005 memcpy(buffer + sizeof(struct servent), &p, sizeof(char *));
1006 p = (char *)_ALIGN(p);
1008 if (new_serv.s_name != NULL) {
1009 size = strlen(new_serv.s_name);
1010 memcpy(p, new_serv.s_name, size);
1011 new_serv.s_name = p;
1015 if (new_serv.s_proto != NULL) {
1016 size = strlen(new_serv.s_proto);
1017 memcpy(p, new_serv.s_proto, size);
1018 new_serv.s_proto = p;
1022 if (new_serv.s_aliases != NULL) {
1023 p = (char *)_ALIGN(p);
1024 memcpy(p, new_serv.s_aliases, sizeof(char *) * aliases_size);
1025 new_serv.s_aliases = (char **)p;
1026 p += sizeof(char *) * (aliases_size + 1);
1028 for (alias = new_serv.s_aliases; *alias; ++alias) {
1029 size = strlen(*alias);
1030 memcpy(p, *alias, size);
1036 memcpy(buffer, &new_serv, sizeof(struct servent));
1037 return (NS_SUCCESS);
1041 serv_unmarshal_func(char *buffer, size_t buffer_size, void *retval, va_list ap,
1047 struct servent *serv;
1051 size_t orig_buf_size;
1054 switch ((enum nss_lookup_type)cache_mdata) {
1056 name = va_arg(ap, char *);
1057 proto = va_arg(ap, char *);
1060 port = va_arg(ap, int);
1061 proto = va_arg(ap, char *);
1066 /* should be unreachable */
1067 return (NS_UNAVAIL);
1070 serv = va_arg(ap, struct servent *);
1071 orig_buf = va_arg(ap, char *);
1072 orig_buf_size = va_arg(ap, size_t);
1073 ret_errno = va_arg(ap, int *);
1076 buffer_size - sizeof(struct servent) - sizeof(char *)) {
1077 *ret_errno = ERANGE;
1081 memcpy(serv, buffer, sizeof(struct servent));
1082 memcpy(&p, buffer + sizeof(struct servent), sizeof(char *));
1084 orig_buf = (char *)_ALIGN(orig_buf);
1085 memcpy(orig_buf, buffer + sizeof(struct servent) + sizeof(char *) +
1086 (_ALIGN(p) - (size_t)p),
1087 buffer_size - sizeof(struct servent) - sizeof(char *) -
1088 (_ALIGN(p) - (size_t)p));
1089 p = (char *)_ALIGN(p);
1091 NS_APPLY_OFFSET(serv->s_name, orig_buf, p, char *);
1092 NS_APPLY_OFFSET(serv->s_proto, orig_buf, p, char *);
1093 if (serv->s_aliases != NULL) {
1094 NS_APPLY_OFFSET(serv->s_aliases, orig_buf, p, char **);
1096 for (alias = serv->s_aliases; *alias; ++alias)
1097 NS_APPLY_OFFSET(*alias, orig_buf, p, char *);
1101 *((struct servent **)retval) = serv;
1102 return (NS_SUCCESS);
1105 NSS_MP_CACHE_HANDLING(services);
1106 #endif /* NS_CACHING */
1108 /* get**_r functions implementation */
1110 getservbyname_r(const char *name, const char *proto, struct servent *serv,
1111 char *buffer, size_t bufsize, struct servent **result)
1113 static const struct servent_mdata mdata = { nss_lt_name, 0 };
1114 static const struct servent_mdata compat_mdata = { nss_lt_name, 1 };
1116 static const nss_cache_info cache_info =
1117 NS_COMMON_CACHE_INFO_INITIALIZER(
1118 services, (void *)nss_lt_name,
1119 serv_id_func, serv_marshal_func, serv_unmarshal_func);
1120 #endif /* NS_CACHING */
1121 static const ns_dtab dtab[] = {
1122 { NSSRC_FILES, files_servent, (void *)&mdata },
1123 { NSSRC_DB, db_servent, (void *)nss_lt_name },
1125 { NSSRC_NIS, nis_servent, (void *)nss_lt_name },
1127 { NSSRC_COMPAT, files_servent, (void *)&compat_mdata },
1129 NS_CACHE_CB(&cache_info)
1131 { NULL, NULL, NULL }
1137 rv = nsdispatch(result, dtab, NSDB_SERVICES, "getservbyname_r",
1138 defaultsrc, name, proto, serv, buffer, bufsize, &ret_errno);
1140 if (rv == NS_SUCCESS)
1147 getservbyport_r(int port, const char *proto, struct servent *serv,
1148 char *buffer, size_t bufsize, struct servent **result)
1150 static const struct servent_mdata mdata = { nss_lt_id, 0 };
1151 static const struct servent_mdata compat_mdata = { nss_lt_id, 1 };
1153 static const nss_cache_info cache_info =
1154 NS_COMMON_CACHE_INFO_INITIALIZER(
1155 services, (void *)nss_lt_id,
1156 serv_id_func, serv_marshal_func, serv_unmarshal_func);
1158 static const ns_dtab dtab[] = {
1159 { NSSRC_FILES, files_servent, (void *)&mdata },
1160 { NSSRC_DB, db_servent, (void *)nss_lt_id },
1162 { NSSRC_NIS, nis_servent, (void *)nss_lt_id },
1164 { NSSRC_COMPAT, files_servent, (void *)&compat_mdata },
1166 NS_CACHE_CB(&cache_info)
1168 { NULL, NULL, NULL }
1174 rv = nsdispatch(result, dtab, NSDB_SERVICES, "getservbyport_r",
1175 defaultsrc, port, proto, serv, buffer, bufsize, &ret_errno);
1177 if (rv == NS_SUCCESS)
1184 getservent_r(struct servent *serv, char *buffer, size_t bufsize,
1185 struct servent **result)
1187 static const struct servent_mdata mdata = { nss_lt_all, 0 };
1188 static const struct servent_mdata compat_mdata = { nss_lt_all, 1 };
1190 static const nss_cache_info cache_info = NS_MP_CACHE_INFO_INITIALIZER(
1191 services, (void *)nss_lt_all,
1192 serv_marshal_func, serv_unmarshal_func);
1194 static const ns_dtab dtab[] = {
1195 { NSSRC_FILES, files_servent, (void *)&mdata },
1196 { NSSRC_DB, db_servent, (void *)nss_lt_all },
1198 { NSSRC_NIS, nis_servent, (void *)nss_lt_all },
1200 { NSSRC_COMPAT, files_servent, (void *)&compat_mdata },
1202 NS_CACHE_CB(&cache_info)
1204 { NULL, NULL, NULL }
1210 rv = nsdispatch(result, dtab, NSDB_SERVICES, "getservent_r",
1211 defaultsrc, serv, buffer, bufsize, &ret_errno);
1213 if (rv == NS_SUCCESS)
1220 setservent(int stayopen)
1223 static const nss_cache_info cache_info = NS_MP_CACHE_INFO_INITIALIZER(
1224 services, (void *)nss_lt_all,
1227 static const ns_dtab dtab[] = {
1228 { NSSRC_FILES, files_setservent, (void *)SETSERVENT },
1229 { NSSRC_DB, db_setservent, (void *)SETSERVENT },
1231 { NSSRC_NIS, nis_setservent, (void *)SETSERVENT },
1233 { NSSRC_COMPAT, compat_setservent, (void *)SETSERVENT },
1235 NS_CACHE_CB(&cache_info)
1237 { NULL, NULL, NULL }
1240 (void)nsdispatch(NULL, dtab, NSDB_SERVICES, "setservent", defaultsrc,
1248 static const nss_cache_info cache_info = NS_MP_CACHE_INFO_INITIALIZER(
1249 services, (void *)nss_lt_all,
1252 static const ns_dtab dtab[] = {
1253 { NSSRC_FILES, files_setservent, (void *)ENDSERVENT },
1254 { NSSRC_DB, db_setservent, (void *)ENDSERVENT },
1256 { NSSRC_NIS, nis_setservent, (void *)ENDSERVENT },
1258 { NSSRC_COMPAT, compat_setservent, (void *)ENDSERVENT },
1260 NS_CACHE_CB(&cache_info)
1262 { NULL, NULL, NULL }
1265 (void)nsdispatch(NULL, dtab, NSDB_SERVICES, "endservent", defaultsrc);
1268 /* get** wrappers for get**_r functions implementation */
1270 servent_endstate(void *p)
1275 free(((struct servent_state *)p)->buffer);
1280 wrap_getservbyname_r(struct key key, struct servent *serv, char *buffer,
1281 size_t bufsize, struct servent **res)
1283 return (getservbyname_r(key.name, key.proto, serv, buffer, bufsize,
1288 wrap_getservbyport_r(struct key key, struct servent *serv, char *buffer,
1289 size_t bufsize, struct servent **res)
1291 return (getservbyport_r(key.port, key.proto, serv, buffer, bufsize,
1296 wrap_getservent_r(struct key key, struct servent *serv, char *buffer,
1297 size_t bufsize, struct servent **res)
1299 return (getservent_r(serv, buffer, bufsize, res));
1302 static struct servent *
1303 getserv(int (*fn)(struct key, struct servent *, char *, size_t,
1304 struct servent **), struct key key)
1307 struct servent *res;
1308 struct servent_state * st;
1310 rv = servent_getstate(&st);
1316 if (st->buffer == NULL) {
1317 st->buffer = malloc(SERVENT_STORAGE_INITIAL);
1318 if (st->buffer == NULL)
1320 st->bufsize = SERVENT_STORAGE_INITIAL;
1323 rv = fn(key, &st->serv, st->buffer, st->bufsize, &res);
1324 if (res == NULL && rv == ERANGE) {
1326 if ((st->bufsize << 1) > SERVENT_STORAGE_MAX) {
1332 st->buffer = malloc(st->bufsize);
1333 if (st->buffer == NULL)
1336 } while (res == NULL && rv == ERANGE);
1344 getservbyname(const char *name, const char *proto)
1351 return (getserv(wrap_getservbyname_r, key));
1355 getservbyport(int port, const char *proto)
1362 return (getserv(wrap_getservbyport_r, key));
1373 return (getserv(wrap_getservent_r, key));