diff options
Diffstat (limited to 'lib/libc/net/getservent.c')
-rw-r--r-- | lib/libc/net/getservent.c | 1373 |
1 files changed, 0 insertions, 1373 deletions
diff --git a/lib/libc/net/getservent.c b/lib/libc/net/getservent.c deleted file mode 100644 index 3228bdc..0000000 --- a/lib/libc/net/getservent.c +++ /dev/null @@ -1,1373 +0,0 @@ -/* - * Copyright (c) 1983, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)getservent.c 8.1 (Berkeley) 6/4/93"; -#endif /* LIBC_SCCS and not lint */ -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <sys/param.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <arpa/inet.h> -#include <db.h> -#include <errno.h> -#include <fcntl.h> -#include <limits.h> -#include <netdb.h> -#include <nsswitch.h> -#include <stdio.h> -#include <string.h> -#include <stdlib.h> -#include <unistd.h> -#ifdef YP -#include <rpc/rpc.h> -#include <rpcsvc/yp_prot.h> -#include <rpcsvc/ypclnt.h> -#endif -#include "namespace.h" -#include "reentrant.h" -#include "un-namespace.h" -#include "netdb_private.h" -#ifdef NS_CACHING -#include "nscache.h" -#endif -#include "nss_tls.h" - -enum constants -{ - SETSERVENT = 1, - ENDSERVENT = 2, - SERVENT_STORAGE_INITIAL = 1 << 10, /* 1 KByte */ - SERVENT_STORAGE_MAX = 1 << 20, /* 1 MByte */ -}; - -struct servent_mdata -{ - enum nss_lookup_type how; - int compat_mode; -}; - -static const ns_src defaultsrc[] = { - { NSSRC_COMPAT, NS_SUCCESS }, - { NULL, 0 } -}; - -static int servent_unpack(char *, struct servent *, char **, size_t, int *); - -/* files backend declarations */ -struct files_state -{ - FILE *fp; - int stayopen; - - int compat_mode_active; -}; -static void files_endstate(void *); -NSS_TLS_HANDLING(files); - -static int files_servent(void *, void *, va_list); -static int files_setservent(void *, void *, va_list); - -/* db backend declarations */ -struct db_state -{ - DB *db; - int stayopen; - int keynum; -}; -static void db_endstate(void *); -NSS_TLS_HANDLING(db); - -static int db_servent(void *, void *, va_list); -static int db_setservent(void *, void *, va_list); - -#ifdef YP -/* nis backend declarations */ -static int nis_servent(void *, void *, va_list); -static int nis_setservent(void *, void *, va_list); - -struct nis_state -{ - int yp_stepping; - char yp_domain[MAXHOSTNAMELEN]; - char *yp_key; - int yp_keylen; -}; -static void nis_endstate(void *); -NSS_TLS_HANDLING(nis); - -static int nis_servent(void *, void *, va_list); -static int nis_setservent(void *, void *, va_list); -#endif - -/* compat backend declarations */ -static int compat_setservent(void *, void *, va_list); - -/* get** wrappers for get**_r functions declarations */ -struct servent_state { - struct servent serv; - char *buffer; - size_t bufsize; -}; -static void servent_endstate(void *); -NSS_TLS_HANDLING(servent); - -struct key { - const char *proto; - union { - const char *name; - int port; - }; -}; - -static int wrap_getservbyname_r(struct key, struct servent *, char *, size_t, - struct servent **); -static int wrap_getservbyport_r(struct key, struct servent *, char *, size_t, - struct servent **); -static int wrap_getservent_r(struct key, struct servent *, char *, size_t, - struct servent **); -static struct servent *getserv(int (*fn)(struct key, struct servent *, char *, - size_t, struct servent **), struct key); - -#ifdef NS_CACHING -static int serv_id_func(char *, size_t *, va_list, void *); -static int serv_marshal_func(char *, size_t *, void *, va_list, void *); -static int serv_unmarshal_func(char *, size_t, void *, va_list, void *); -#endif - -static int -servent_unpack(char *p, struct servent *serv, char **aliases, - size_t aliases_size, int *errnop) -{ - char *cp, **q, *endp; - long l; - - if (*p == '#') - return -1; - - memset(serv, 0, sizeof(struct servent)); - - cp = strpbrk(p, "#\n"); - if (cp != NULL) - *cp = '\0'; - serv->s_name = p; - - p = strpbrk(p, " \t"); - if (p == NULL) - return -1; - *p++ = '\0'; - while (*p == ' ' || *p == '\t') - p++; - cp = strpbrk(p, ",/"); - if (cp == NULL) - return -1; - - *cp++ = '\0'; - l = strtol(p, &endp, 10); - if (endp == p || *endp != '\0' || l < 0 || l > USHRT_MAX) - return -1; - serv->s_port = htons((in_port_t)l); - serv->s_proto = cp; - - q = serv->s_aliases = aliases; - cp = strpbrk(cp, " \t"); - if (cp != NULL) - *cp++ = '\0'; - while (cp && *cp) { - if (*cp == ' ' || *cp == '\t') { - cp++; - continue; - } - if (q < &aliases[aliases_size - 1]) { - *q++ = cp; - } else { - *q = NULL; - *errnop = ERANGE; - return -1; - } - cp = strpbrk(cp, " \t"); - if (cp != NULL) - *cp++ = '\0'; - } - *q = NULL; - - return 0; -} - -static int -parse_result(struct servent *serv, char *buffer, size_t bufsize, - char *resultbuf, size_t resultbuflen, int *errnop) -{ - char **aliases; - int aliases_size; - - if (bufsize <= resultbuflen + _ALIGNBYTES + sizeof(char *)) { - *errnop = ERANGE; - return (NS_RETURN); - } - aliases = (char **)_ALIGN(&buffer[resultbuflen + 1]); - aliases_size = (buffer + bufsize - (char *)aliases) / sizeof(char *); - if (aliases_size < 1) { - *errnop = ERANGE; - return (NS_RETURN); - } - - memcpy(buffer, resultbuf, resultbuflen); - buffer[resultbuflen] = '\0'; - - if (servent_unpack(buffer, serv, aliases, aliases_size, errnop) != 0) - return ((*errnop == 0) ? NS_NOTFOUND : NS_RETURN); - return (NS_SUCCESS); -} - -/* files backend implementation */ -static void -files_endstate(void *p) -{ - FILE * f; - - if (p == NULL) - return; - - f = ((struct files_state *)p)->fp; - if (f != NULL) - fclose(f); - - free(p); -} - -/* - * compat structures. compat and files sources functionalities are almost - * equal, so they all are managed by files_servent function - */ -static int -files_servent(void *retval, void *mdata, va_list ap) -{ - static const ns_src compat_src[] = { -#ifdef YP - { NSSRC_NIS, NS_SUCCESS }, -#endif - { NULL, 0 } - }; - ns_dtab compat_dtab[] = { - { NSSRC_DB, db_servent, - (void *)((struct servent_mdata *)mdata)->how }, -#ifdef YP - { NSSRC_NIS, nis_servent, - (void *)((struct servent_mdata *)mdata)->how }, -#endif - { NULL, NULL, NULL } - }; - - struct files_state *st; - int rv; - int stayopen; - - struct servent_mdata *serv_mdata; - char *name; - char *proto; - int port; - - struct servent *serv; - char *buffer; - size_t bufsize; - int *errnop; - - size_t linesize; - char *line; - char **cp; - - name = NULL; - proto = NULL; - serv_mdata = (struct servent_mdata *)mdata; - switch (serv_mdata->how) { - case nss_lt_name: - name = va_arg(ap, char *); - proto = va_arg(ap, char *); - break; - case nss_lt_id: - port = va_arg(ap, int); - proto = va_arg(ap, char *); - break; - case nss_lt_all: - break; - default: - return NS_NOTFOUND; - }; - - serv = va_arg(ap, struct servent *); - buffer = va_arg(ap, char *); - bufsize = va_arg(ap, size_t); - errnop = va_arg(ap,int *); - - *errnop = files_getstate(&st); - if (*errnop != 0) - return (NS_UNAVAIL); - - if (st->fp == NULL) - st->compat_mode_active = 0; - - if (st->fp == NULL && (st->fp = fopen(_PATH_SERVICES, "r")) == NULL) { - *errnop = errno; - return (NS_UNAVAIL); - } - - if (serv_mdata->how == nss_lt_all) - stayopen = 1; - else { - rewind(st->fp); - stayopen = st->stayopen; - } - - rv = NS_NOTFOUND; - do { - if (!st->compat_mode_active) { - if ((line = fgetln(st->fp, &linesize)) == NULL) { - *errnop = errno; - rv = NS_RETURN; - break; - } - - if (*line=='+' && serv_mdata->compat_mode != 0) - st->compat_mode_active = 1; - } - - if (st->compat_mode_active != 0) { - switch (serv_mdata->how) { - case nss_lt_name: - rv = nsdispatch(retval, compat_dtab, - NSDB_SERVICES_COMPAT, "getservbyname_r", - compat_src, name, proto, serv, buffer, - bufsize, errnop); - break; - case nss_lt_id: - rv = nsdispatch(retval, compat_dtab, - NSDB_SERVICES_COMPAT, "getservbyport_r", - compat_src, port, proto, serv, buffer, - bufsize, errnop); - break; - case nss_lt_all: - rv = nsdispatch(retval, compat_dtab, - NSDB_SERVICES_COMPAT, "getservent_r", - compat_src, serv, buffer, bufsize, errnop); - break; - } - - if (!(rv & NS_TERMINATE) || - serv_mdata->how != nss_lt_all) - st->compat_mode_active = 0; - - continue; - } - - rv = parse_result(serv, buffer, bufsize, line, linesize, - errnop); - if (rv == NS_NOTFOUND) - continue; - if (rv == NS_RETURN) - break; - - rv = NS_NOTFOUND; - switch (serv_mdata->how) { - case nss_lt_name: - if (strcmp(name, serv->s_name) == 0) - goto gotname; - for (cp = serv->s_aliases; *cp; cp++) - if (strcmp(name, *cp) == 0) - goto gotname; - - continue; - gotname: - if (proto == 0 || strcmp(serv->s_proto, proto) == 0) - rv = NS_SUCCESS; - break; - case nss_lt_id: - if (port != serv->s_port) - continue; - - if (proto == 0 || strcmp(serv->s_proto, proto) == 0) - rv = NS_SUCCESS; - break; - case nss_lt_all: - rv = NS_SUCCESS; - break; - } - - } while (!(rv & NS_TERMINATE)); - - if (!stayopen && st->fp != NULL) { - fclose(st->fp); - st->fp = NULL; - } - - if ((rv == NS_SUCCESS) && (retval != NULL)) - *(struct servent **)retval=serv; - - return (rv); -} - -static int -files_setservent(void *retval, void *mdata, va_list ap) -{ - struct files_state *st; - int rv; - int f; - - rv = files_getstate(&st); - if (rv != 0) - return (NS_UNAVAIL); - - switch ((enum constants)mdata) { - case SETSERVENT: - f = va_arg(ap,int); - if (st->fp == NULL) - st->fp = fopen(_PATH_SERVICES, "r"); - else - rewind(st->fp); - st->stayopen |= f; - break; - case ENDSERVENT: - if (st->fp != NULL) { - fclose(st->fp); - st->fp = NULL; - } - st->stayopen = 0; - break; - default: - break; - }; - - st->compat_mode_active = 0; - return (NS_UNAVAIL); -} - -/* db backend implementation */ -static void -db_endstate(void *p) -{ - DB *db; - - if (p == NULL) - return; - - db = ((struct db_state *)p)->db; - if (db != NULL) - db->close(db); - - free(p); -} - -static int -db_servent(void *retval, void *mdata, va_list ap) -{ - char buf[BUFSIZ]; - DBT key, data, *result; - DB *db; - - struct db_state *st; - int rv; - int stayopen; - - enum nss_lookup_type how; - char *name; - char *proto; - int port; - - struct servent *serv; - char *buffer; - size_t bufsize; - int *errnop; - - name = NULL; - proto = NULL; - how = (enum nss_lookup_type)mdata; - switch (how) { - case nss_lt_name: - name = va_arg(ap, char *); - proto = va_arg(ap, char *); - break; - case nss_lt_id: - port = va_arg(ap, int); - proto = va_arg(ap, char *); - break; - case nss_lt_all: - break; - default: - return NS_NOTFOUND; - }; - - serv = va_arg(ap, struct servent *); - buffer = va_arg(ap, char *); - bufsize = va_arg(ap, size_t); - errnop = va_arg(ap,int *); - - *errnop = db_getstate(&st); - if (*errnop != 0) - return (NS_UNAVAIL); - - if (how == nss_lt_all && st->keynum < 0) - return (NS_NOTFOUND); - - if (st->db == NULL) { - st->db = dbopen(_PATH_SERVICES_DB, O_RDONLY, 0, DB_HASH, NULL); - if (st->db == NULL) { - *errnop = errno; - return (NS_UNAVAIL); - } - } - - stayopen = (how == nss_lt_all) ? 1 : st->stayopen; - db = st->db; - - do { - switch (how) { - case nss_lt_name: - key.data = buf; - if (proto == NULL) - key.size = snprintf(buf, sizeof(buf), - "\376%s", name); - else - key.size = snprintf(buf, sizeof(buf), - "\376%s/%s", name, proto); - key.size++; - if (db->get(db, &key, &data, 0) != 0 || - db->get(db, &data, &key, 0) != 0) { - rv = NS_NOTFOUND; - goto db_fin; - } - result = &key; - break; - case nss_lt_id: - key.data = buf; - port = htons(port); - if (proto == NULL) - key.size = snprintf(buf, sizeof(buf), - "\377%d", port); - else - key.size = snprintf(buf, sizeof(buf), - "\377%d/%s", port, proto); - key.size++; - if (db->get(db, &key, &data, 0) != 0 || - db->get(db, &data, &key, 0) != 0) { - rv = NS_NOTFOUND; - goto db_fin; - } - result = &key; - break; - case nss_lt_all: - key.data = buf; - key.size = snprintf(buf, sizeof(buf), "%d", - st->keynum++); - key.size++; - if (db->get(db, &key, &data, 0) != 0) { - st->keynum = -1; - rv = NS_NOTFOUND; - goto db_fin; - } - result = &data; - break; - } - - rv = parse_result(serv, buffer, bufsize, result->data, - result->size - 1, errnop); - - } while (!(rv & NS_TERMINATE) && how == nss_lt_all); - -db_fin: - if (!stayopen && st->db != NULL) { - db->close(db); - st->db = NULL; - } - - if (rv == NS_SUCCESS && retval != NULL) - *(struct servent **)retval = serv; - - return (rv); -} - -static int -db_setservent(void *retval, void *mdata, va_list ap) -{ - DB *db; - struct db_state *st; - int rv; - int f; - - rv = db_getstate(&st); - if (rv != 0) - return (NS_UNAVAIL); - - switch ((enum constants)mdata) { - case SETSERVENT: - f = va_arg(ap, int); - st->stayopen |= f; - st->keynum = 0; - break; - case ENDSERVENT: - db = st->db; - if (db != NULL) { - db->close(db); - st->db = NULL; - } - st->stayopen = 0; - break; - default: - break; - }; - - return (NS_UNAVAIL); -} - -/* nis backend implementation */ -#ifdef YP -static void -nis_endstate(void *p) -{ - if (p == NULL) - return; - - free(((struct nis_state *)p)->yp_key); - free(p); -} - -static int -nis_servent(void *retval, void *mdata, va_list ap) -{ - char *resultbuf, *lastkey; - int resultbuflen; - char buf[YPMAXRECORD + 2]; - - struct nis_state *st; - int rv; - - enum nss_lookup_type how; - char *name; - char *proto; - int port; - - struct servent *serv; - char *buffer; - size_t bufsize; - int *errnop; - - name = NULL; - proto = NULL; - how = (enum nss_lookup_type)mdata; - switch (how) { - case nss_lt_name: - name = va_arg(ap, char *); - proto = va_arg(ap, char *); - break; - case nss_lt_id: - port = va_arg(ap, int); - proto = va_arg(ap, char *); - break; - case nss_lt_all: - break; - default: - return NS_NOTFOUND; - }; - - serv = va_arg(ap, struct servent *); - buffer = va_arg(ap, char *); - bufsize = va_arg(ap, size_t); - errnop = va_arg(ap, int *); - - *errnop = nis_getstate(&st); - if (*errnop != 0) - return (NS_UNAVAIL); - - if (st->yp_domain[0] == '\0') { - if (getdomainname(st->yp_domain, sizeof st->yp_domain)) { - *errnop = errno; - return (NS_UNAVAIL); - } - } - - do { - switch (how) { - case nss_lt_name: - snprintf(buf, sizeof(buf), "%s/%s", name, proto); - if (yp_match(st->yp_domain, "services.byname", buf, - strlen(buf), &resultbuf, &resultbuflen)) { - rv = NS_NOTFOUND; - goto fin; - } - break; - case nss_lt_id: - snprintf(buf, sizeof(buf), "%d/%s", ntohs(port), - proto); - - /* - * We have to be a little flexible - * here. Ideally you're supposed to have both - * a services.byname and a services.byport - * map, but some systems have only - * services.byname. FreeBSD cheats a little by - * putting the services.byport information in - * the same map as services.byname so that - * either case will work. We allow for both - * possibilities here: if there is no - * services.byport map, we try services.byname - * instead. - */ - rv = yp_match(st->yp_domain, "services.byport", buf, - strlen(buf), &resultbuf, &resultbuflen); - if (rv) { - if (rv == YPERR_MAP) { - if (yp_match(st->yp_domain, - "services.byname", buf, - strlen(buf), &resultbuf, - &resultbuflen)) { - rv = NS_NOTFOUND; - goto fin; - } - } else { - rv = NS_NOTFOUND; - goto fin; - } - } - - break; - case nss_lt_all: - if (!st->yp_stepping) { - free(st->yp_key); - rv = yp_first(st->yp_domain, "services.byname", - &st->yp_key, &st->yp_keylen, &resultbuf, - &resultbuflen); - if (rv) { - rv = NS_NOTFOUND; - goto fin; - } - st->yp_stepping = 1; - } else { - lastkey = st->yp_key; - rv = yp_next(st->yp_domain, "services.byname", - st->yp_key, st->yp_keylen, &st->yp_key, - &st->yp_keylen, &resultbuf, &resultbuflen); - free(lastkey); - if (rv) { - st->yp_stepping = 0; - rv = NS_NOTFOUND; - goto fin; - } - } - break; - }; - - rv = parse_result(serv, buffer, bufsize, resultbuf, - resultbuflen, errnop); - free(resultbuf); - - } while (!(rv & NS_TERMINATE) && how == nss_lt_all); - -fin: - if (rv == NS_SUCCESS && retval != NULL) - *(struct servent **)retval = serv; - - return (rv); -} - -static int -nis_setservent(void *result, void *mdata, va_list ap) -{ - struct nis_state *st; - int rv; - - rv = nis_getstate(&st); - if (rv != 0) - return (NS_UNAVAIL); - - switch ((enum constants)mdata) { - case SETSERVENT: - case ENDSERVENT: - free(st->yp_key); - st->yp_key = NULL; - st->yp_stepping = 0; - break; - default: - break; - }; - - return (NS_UNAVAIL); -} -#endif - -/* compat backend implementation */ -static int -compat_setservent(void *retval, void *mdata, va_list ap) -{ - static const ns_src compat_src[] = { -#ifdef YP - { NSSRC_NIS, NS_SUCCESS }, -#endif - { NULL, 0 } - }; - ns_dtab compat_dtab[] = { - { NSSRC_DB, db_setservent, mdata }, -#ifdef YP - { NSSRC_NIS, nis_setservent, mdata }, -#endif - { NULL, NULL, NULL } - }; - int f; - - (void)files_setservent(retval, mdata, ap); - - switch ((enum constants)mdata) { - case SETSERVENT: - f = va_arg(ap,int); - (void)nsdispatch(retval, compat_dtab, NSDB_SERVICES_COMPAT, - "setservent", compat_src, f); - break; - case ENDSERVENT: - (void)nsdispatch(retval, compat_dtab, NSDB_SERVICES_COMPAT, - "endservent", compat_src); - break; - default: - break; - } - - return (NS_UNAVAIL); -} - -#ifdef NS_CACHING -static int -serv_id_func(char *buffer, size_t *buffer_size, va_list ap, void *cache_mdata) -{ - char *name; - char *proto; - int port; - - size_t desired_size, size, size2; - enum nss_lookup_type lookup_type; - int res = NS_UNAVAIL; - - lookup_type = (enum nss_lookup_type)cache_mdata; - switch (lookup_type) { - case nss_lt_name: - name = va_arg(ap, char *); - proto = va_arg(ap, char *); - - size = strlen(name); - desired_size = sizeof(enum nss_lookup_type) + size + 1; - if (proto != NULL) { - size2 = strlen(proto); - desired_size += size2 + 1; - } else - size2 = 0; - - if (desired_size > *buffer_size) { - res = NS_RETURN; - goto fin; - } - - memcpy(buffer, &lookup_type, sizeof(enum nss_lookup_type)); - memcpy(buffer + sizeof(enum nss_lookup_type), name, size + 1); - - if (proto != NULL) - memcpy(buffer + sizeof(enum nss_lookup_type) + size + 1, - proto, size2 + 1); - - res = NS_SUCCESS; - break; - case nss_lt_id: - port = va_arg(ap, int); - proto = va_arg(ap, char *); - - desired_size = sizeof(enum nss_lookup_type) + sizeof(int); - if (proto != NULL) { - size = strlen(proto); - desired_size += size + 1; - } else - size = 0; - - if (desired_size > *buffer_size) { - res = NS_RETURN; - goto fin; - } - - memcpy(buffer, &lookup_type, sizeof(enum nss_lookup_type)); - memcpy(buffer + sizeof(enum nss_lookup_type), &port, - sizeof(int)); - - if (proto != NULL) - memcpy(buffer + sizeof(enum nss_lookup_type) + - sizeof(int), proto, size + 1); - - res = NS_SUCCESS; - break; - default: - /* should be unreachable */ - return (NS_UNAVAIL); - } - -fin: - *buffer_size = desired_size; - return (res); -} - -int -serv_marshal_func(char *buffer, size_t *buffer_size, void *retval, va_list ap, - void *cache_mdata) -{ - char *name; - char *proto; - int port; - struct servent *serv; - char *orig_buf; - size_t orig_buf_size; - - struct servent new_serv; - size_t desired_size; - char **alias; - char *p; - size_t size; - size_t aliases_size; - - switch ((enum nss_lookup_type)cache_mdata) { - case nss_lt_name: - name = va_arg(ap, char *); - proto = va_arg(ap, char *); - break; - case nss_lt_id: - port = va_arg(ap, int); - proto = va_arg(ap, char *); - break; - case nss_lt_all: - break; - default: - /* should be unreachable */ - return (NS_UNAVAIL); - } - - serv = va_arg(ap, struct servent *); - orig_buf = va_arg(ap, char *); - orig_buf_size = va_arg(ap, size_t); - - desired_size = _ALIGNBYTES + sizeof(struct servent) + sizeof(char *); - if (serv->s_name != NULL) - desired_size += strlen(serv->s_name) + 1; - if (serv->s_proto != NULL) - desired_size += strlen(serv->s_proto) + 1; - - aliases_size = 0; - if (serv->s_aliases != NULL) { - for (alias = serv->s_aliases; *alias; ++alias) { - desired_size += strlen(*alias) + 1; - ++aliases_size; - } - - desired_size += _ALIGNBYTES + - sizeof(char *) * (aliases_size + 1); - } - - if (*buffer_size < desired_size) { - /* this assignment is here for future use */ - *buffer_size = desired_size; - return (NS_RETURN); - } - - memcpy(&new_serv, serv, sizeof(struct servent)); - memset(buffer, 0, desired_size); - - *buffer_size = desired_size; - p = buffer + sizeof(struct servent) + sizeof(char *); - memcpy(buffer + sizeof(struct servent), &p, sizeof(char *)); - p = (char *)_ALIGN(p); - - if (new_serv.s_name != NULL) { - size = strlen(new_serv.s_name); - memcpy(p, new_serv.s_name, size); - new_serv.s_name = p; - p += size + 1; - } - - if (new_serv.s_proto != NULL) { - size = strlen(new_serv.s_proto); - memcpy(p, new_serv.s_proto, size); - new_serv.s_proto = p; - p += size + 1; - } - - if (new_serv.s_aliases != NULL) { - p = (char *)_ALIGN(p); - memcpy(p, new_serv.s_aliases, sizeof(char *) * aliases_size); - new_serv.s_aliases = (char **)p; - p += sizeof(char *) * (aliases_size + 1); - - for (alias = new_serv.s_aliases; *alias; ++alias) { - size = strlen(*alias); - memcpy(p, *alias, size); - *alias = p; - p += size + 1; - } - } - - memcpy(buffer, &new_serv, sizeof(struct servent)); - return (NS_SUCCESS); -} - -int -serv_unmarshal_func(char *buffer, size_t buffer_size, void *retval, va_list ap, - void *cache_mdata) -{ - char *name; - char *proto; - int port; - struct servent *serv; - char *orig_buf; - char *p; - char **alias; - size_t orig_buf_size; - int *ret_errno; - - switch ((enum nss_lookup_type)cache_mdata) { - case nss_lt_name: - name = va_arg(ap, char *); - proto = va_arg(ap, char *); - break; - case nss_lt_id: - port = va_arg(ap, int); - proto = va_arg(ap, char *); - break; - case nss_lt_all: - break; - default: - /* should be unreachable */ - return (NS_UNAVAIL); - } - - serv = va_arg(ap, struct servent *); - orig_buf = va_arg(ap, char *); - orig_buf_size = va_arg(ap, size_t); - ret_errno = va_arg(ap, int *); - - if (orig_buf_size < - buffer_size - sizeof(struct servent) - sizeof(char *)) { - *ret_errno = ERANGE; - return (NS_RETURN); - } - - memcpy(serv, buffer, sizeof(struct servent)); - memcpy(&p, buffer + sizeof(struct servent), sizeof(char *)); - - orig_buf = (char *)_ALIGN(orig_buf); - memcpy(orig_buf, buffer + sizeof(struct servent) + sizeof(char *) + - (_ALIGN(p) - (size_t)p), - buffer_size - sizeof(struct servent) - sizeof(char *) - - (_ALIGN(p) - (size_t)p)); - p = (char *)_ALIGN(p); - - NS_APPLY_OFFSET(serv->s_name, orig_buf, p, char *); - NS_APPLY_OFFSET(serv->s_proto, orig_buf, p, char *); - if (serv->s_aliases != NULL) { - NS_APPLY_OFFSET(serv->s_aliases, orig_buf, p, char **); - - for (alias = serv->s_aliases; *alias; ++alias) - NS_APPLY_OFFSET(*alias, orig_buf, p, char *); - } - - if (retval != NULL) - *((struct servent **)retval) = serv; - return (NS_SUCCESS); -} - -NSS_MP_CACHE_HANDLING(services); -#endif /* NS_CACHING */ - -/* get**_r functions implementation */ -int -getservbyname_r(const char *name, const char *proto, struct servent *serv, - char *buffer, size_t bufsize, struct servent **result) -{ - static const struct servent_mdata mdata = { nss_lt_name, 0 }; - static const struct servent_mdata compat_mdata = { nss_lt_name, 1 }; -#ifdef NS_CACHING - static const nss_cache_info cache_info = - NS_COMMON_CACHE_INFO_INITIALIZER( - services, (void *)nss_lt_name, - serv_id_func, serv_marshal_func, serv_unmarshal_func); -#endif /* NS_CACHING */ - static const ns_dtab dtab[] = { - { NSSRC_FILES, files_servent, (void *)&mdata }, - { NSSRC_DB, db_servent, (void *)nss_lt_name }, -#ifdef YP - { NSSRC_NIS, nis_servent, (void *)nss_lt_name }, -#endif - { NSSRC_COMPAT, files_servent, (void *)&compat_mdata }, -#ifdef NS_CACHING - NS_CACHE_CB(&cache_info) -#endif - { NULL, NULL, NULL } - }; - int rv, ret_errno; - - ret_errno = 0; - *result = NULL; - rv = nsdispatch(result, dtab, NSDB_SERVICES, "getservbyname_r", - defaultsrc, name, proto, serv, buffer, bufsize, &ret_errno); - - if (rv == NS_SUCCESS) - return (0); - else - return (ret_errno); -} - -int -getservbyport_r(int port, const char *proto, struct servent *serv, - char *buffer, size_t bufsize, struct servent **result) -{ - static const struct servent_mdata mdata = { nss_lt_id, 0 }; - static const struct servent_mdata compat_mdata = { nss_lt_id, 1 }; -#ifdef NS_CACHING - static const nss_cache_info cache_info = - NS_COMMON_CACHE_INFO_INITIALIZER( - services, (void *)nss_lt_id, - serv_id_func, serv_marshal_func, serv_unmarshal_func); -#endif - static const ns_dtab dtab[] = { - { NSSRC_FILES, files_servent, (void *)&mdata }, - { NSSRC_DB, db_servent, (void *)nss_lt_id }, -#ifdef YP - { NSSRC_NIS, nis_servent, (void *)nss_lt_id }, -#endif - { NSSRC_COMPAT, files_servent, (void *)&compat_mdata }, -#ifdef NS_CACHING - NS_CACHE_CB(&cache_info) -#endif - { NULL, NULL, NULL } - }; - int rv, ret_errno; - - ret_errno = 0; - *result = NULL; - rv = nsdispatch(result, dtab, NSDB_SERVICES, "getservbyport_r", - defaultsrc, port, proto, serv, buffer, bufsize, &ret_errno); - - if (rv == NS_SUCCESS) - return (0); - else - return (ret_errno); -} - -int -getservent_r(struct servent *serv, char *buffer, size_t bufsize, - struct servent **result) -{ - static const struct servent_mdata mdata = { nss_lt_all, 0 }; - static const struct servent_mdata compat_mdata = { nss_lt_all, 1 }; -#ifdef NS_CACHING - static const nss_cache_info cache_info = NS_MP_CACHE_INFO_INITIALIZER( - services, (void *)nss_lt_all, - serv_marshal_func, serv_unmarshal_func); -#endif - static const ns_dtab dtab[] = { - { NSSRC_FILES, files_servent, (void *)&mdata }, - { NSSRC_DB, db_servent, (void *)nss_lt_all }, -#ifdef YP - { NSSRC_NIS, nis_servent, (void *)nss_lt_all }, -#endif - { NSSRC_COMPAT, files_servent, (void *)&compat_mdata }, -#ifdef NS_CACHING - NS_CACHE_CB(&cache_info) -#endif - { NULL, NULL, NULL } - }; - int rv, ret_errno; - - ret_errno = 0; - *result = NULL; - rv = nsdispatch(result, dtab, NSDB_SERVICES, "getservent_r", - defaultsrc, serv, buffer, bufsize, &ret_errno); - - if (rv == NS_SUCCESS) - return (0); - else - return (ret_errno); -} - -void -setservent(int stayopen) -{ -#ifdef NS_CACHING - static const nss_cache_info cache_info = NS_MP_CACHE_INFO_INITIALIZER( - services, (void *)nss_lt_all, - NULL, NULL); -#endif - static const ns_dtab dtab[] = { - { NSSRC_FILES, files_setservent, (void *)SETSERVENT }, - { NSSRC_DB, db_setservent, (void *)SETSERVENT }, -#ifdef YP - { NSSRC_NIS, nis_setservent, (void *)SETSERVENT }, -#endif - { NSSRC_COMPAT, compat_setservent, (void *)SETSERVENT }, -#ifdef NS_CACHING - NS_CACHE_CB(&cache_info) -#endif - { NULL, NULL, NULL } - }; - - (void)nsdispatch(NULL, dtab, NSDB_SERVICES, "setservent", defaultsrc, - stayopen); -} - -void -endservent() -{ -#ifdef NS_CACHING - static const nss_cache_info cache_info = NS_MP_CACHE_INFO_INITIALIZER( - services, (void *)nss_lt_all, - NULL, NULL); -#endif - static const ns_dtab dtab[] = { - { NSSRC_FILES, files_setservent, (void *)ENDSERVENT }, - { NSSRC_DB, db_setservent, (void *)ENDSERVENT }, -#ifdef YP - { NSSRC_NIS, nis_setservent, (void *)ENDSERVENT }, -#endif - { NSSRC_COMPAT, compat_setservent, (void *)ENDSERVENT }, -#ifdef NS_CACHING - NS_CACHE_CB(&cache_info) -#endif - { NULL, NULL, NULL } - }; - - (void)nsdispatch(NULL, dtab, NSDB_SERVICES, "endservent", defaultsrc); -} - -/* get** wrappers for get**_r functions implementation */ -static void -servent_endstate(void *p) -{ - if (p == NULL) - return; - - free(((struct servent_state *)p)->buffer); - free(p); -} - -static int -wrap_getservbyname_r(struct key key, struct servent *serv, char *buffer, - size_t bufsize, struct servent **res) -{ - return (getservbyname_r(key.name, key.proto, serv, buffer, bufsize, - res)); -} - -static int -wrap_getservbyport_r(struct key key, struct servent *serv, char *buffer, - size_t bufsize, struct servent **res) -{ - return (getservbyport_r(key.port, key.proto, serv, buffer, bufsize, - res)); -} - -static int -wrap_getservent_r(struct key key, struct servent *serv, char *buffer, - size_t bufsize, struct servent **res) -{ - return (getservent_r(serv, buffer, bufsize, res)); -} - -static struct servent * -getserv(int (*fn)(struct key, struct servent *, char *, size_t, - struct servent **), struct key key) -{ - int rv; - struct servent *res; - struct servent_state * st; - - rv = servent_getstate(&st); - if (rv != 0) { - errno = rv; - return NULL; - } - - if (st->buffer == NULL) { - st->buffer = malloc(SERVENT_STORAGE_INITIAL); - if (st->buffer == NULL) - return (NULL); - st->bufsize = SERVENT_STORAGE_INITIAL; - } - do { - rv = fn(key, &st->serv, st->buffer, st->bufsize, &res); - if (res == NULL && rv == ERANGE) { - free(st->buffer); - if ((st->bufsize << 1) > SERVENT_STORAGE_MAX) { - st->buffer = NULL; - errno = ERANGE; - return (NULL); - } - st->bufsize <<= 1; - st->buffer = malloc(st->bufsize); - if (st->buffer == NULL) - return (NULL); - } - } while (res == NULL && rv == ERANGE); - if (rv != 0) - errno = rv; - - return (res); -} - -struct servent * -getservbyname(const char *name, const char *proto) -{ - struct key key; - - key.name = name; - key.proto = proto; - - return (getserv(wrap_getservbyname_r, key)); -} - -struct servent * -getservbyport(int port, const char *proto) -{ - struct key key; - - key.port = port; - key.proto = proto; - - return (getserv(wrap_getservbyport_r, key)); -} - -struct servent * -getservent() -{ - struct key key; - - key.proto = NULL; - key.port = 0; - - return (getserv(wrap_getservent_r, key)); -} |