6b462d2762
Since YP protocol definition uses the constant to declare variable-size opaque byte strings, the change should be binary compatible with existing installations which do not expose keys or values larger than 1024 bytes. All uses of local variables with YPMAXRECORD sizes were removed to avoid insane stack use. On the other hand, variables with static lifetime should be fine and only result in increased VA use. Glibc made same change, increasing the allowed length for keys and values in YP to 16M, in 2013. Reviewed by: markj Discussed with: ian Sponsored by: Mellanox Technologies MFC after: 3 weeks Differential revision: https://reviews.freebsd.org/D20900
1058 lines
22 KiB
C
1058 lines
22 KiB
C
/* $NetBSD: getrpcent.c,v 1.17 2000/01/22 22:19:17 mycroft Exp $ */
|
|
|
|
/*-
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*
|
|
* Copyright (c) 2009, Sun Microsystems, Inc.
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions are met:
|
|
* - Redistributions of source code must retain the above copyright notice,
|
|
* this list of conditions and the following disclaimer.
|
|
* - 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.
|
|
* - Neither the name of Sun Microsystems, Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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 = "@(#)getrpcent.c 1.14 91/03/11 Copyr 1984 Sun Micro";
|
|
#endif
|
|
#include <sys/cdefs.h>
|
|
__FBSDID("$FreeBSD$");
|
|
|
|
/*
|
|
* Copyright (c) 1984 by Sun Microsystems, Inc.
|
|
*/
|
|
|
|
#include <sys/param.h>
|
|
#include <sys/socket.h>
|
|
#include <arpa/inet.h>
|
|
#include <assert.h>
|
|
#include <errno.h>
|
|
#include <nsswitch.h>
|
|
#include <netinet/in.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <stdarg.h>
|
|
#include <stdlib.h>
|
|
#include <rpc/rpc.h>
|
|
#ifdef YP
|
|
#include <rpcsvc/yp_prot.h>
|
|
#include <rpcsvc/ypclnt.h>
|
|
#endif
|
|
#include <unistd.h>
|
|
#include "namespace.h"
|
|
#include "reentrant.h"
|
|
#include "un-namespace.h"
|
|
#include "libc_private.h"
|
|
#include "nss_tls.h"
|
|
#ifdef NS_CACHING
|
|
#include "nscache.h"
|
|
#endif
|
|
|
|
#define RPCDB "/etc/rpc"
|
|
|
|
/* nsswitch declarations */
|
|
enum constants
|
|
{
|
|
SETRPCENT = 1,
|
|
ENDRPCENT = 2,
|
|
RPCENT_STORAGE_INITIAL = 1 << 10, /* 1 KByte */
|
|
RPCENT_STORAGE_MAX = 1 << 20, /* 1 MByte */
|
|
};
|
|
|
|
static const ns_src defaultsrc[] = {
|
|
{ NSSRC_FILES, NS_SUCCESS },
|
|
#ifdef YP
|
|
{ NSSRC_NIS, NS_SUCCESS },
|
|
#endif
|
|
{ NULL, 0 }
|
|
};
|
|
|
|
/* files backend declarations */
|
|
struct files_state {
|
|
FILE *fp;
|
|
int stayopen;
|
|
};
|
|
|
|
static int files_rpcent(void *, void *, va_list);
|
|
static int files_setrpcent(void *, void *, va_list);
|
|
|
|
static void files_endstate(void *);
|
|
NSS_TLS_HANDLING(files);
|
|
|
|
/* nis backend declarations */
|
|
#ifdef YP
|
|
struct nis_state {
|
|
char domain[MAXHOSTNAMELEN];
|
|
char *current;
|
|
int currentlen;
|
|
int stepping;
|
|
int no_name_map;
|
|
};
|
|
|
|
static int nis_rpcent(void *, void *, va_list);
|
|
static int nis_setrpcent(void *, void *, va_list);
|
|
|
|
static void nis_endstate(void *);
|
|
NSS_TLS_HANDLING(nis);
|
|
#endif
|
|
|
|
/* get** wrappers for get**_r functions declarations */
|
|
struct rpcent_state {
|
|
struct rpcent rpc;
|
|
char *buffer;
|
|
size_t bufsize;
|
|
};
|
|
static void rpcent_endstate(void *);
|
|
NSS_TLS_HANDLING(rpcent);
|
|
|
|
union key {
|
|
const char *name;
|
|
int number;
|
|
};
|
|
|
|
static int wrap_getrpcbyname_r(union key, struct rpcent *, char *,
|
|
size_t, struct rpcent **);
|
|
static int wrap_getrpcbynumber_r(union key, struct rpcent *, char *,
|
|
size_t, struct rpcent **);
|
|
static int wrap_getrpcent_r(union key, struct rpcent *, char *,
|
|
size_t, struct rpcent **);
|
|
static struct rpcent *getrpc(int (*fn)(union key, struct rpcent *, char *,
|
|
size_t, struct rpcent **), union key);
|
|
|
|
#ifdef NS_CACHING
|
|
static int rpc_id_func(char *, size_t *, va_list, void *);
|
|
static int rpc_marshal_func(char *, size_t *, void *, va_list, void *);
|
|
static int rpc_unmarshal_func(char *, size_t, void *, va_list, void *);
|
|
#endif
|
|
|
|
static int
|
|
rpcent_unpack(char *p, struct rpcent *rpc, char **r_aliases,
|
|
size_t aliases_size, int *errnop)
|
|
{
|
|
char *cp, **q;
|
|
|
|
assert(p != NULL);
|
|
|
|
if (*p == '#')
|
|
return (-1);
|
|
cp = strpbrk(p, "#\n");
|
|
if (cp == NULL)
|
|
return (-1);
|
|
*cp = '\0';
|
|
cp = strpbrk(p, " \t");
|
|
if (cp == NULL)
|
|
return (-1);
|
|
*cp++ = '\0';
|
|
/* THIS STUFF IS INTERNET SPECIFIC */
|
|
rpc->r_name = p;
|
|
while (*cp == ' ' || *cp == '\t')
|
|
cp++;
|
|
rpc->r_number = atoi(cp);
|
|
q = rpc->r_aliases = r_aliases;
|
|
cp = strpbrk(cp, " \t");
|
|
if (cp != NULL)
|
|
*cp++ = '\0';
|
|
while (cp && *cp) {
|
|
if (*cp == ' ' || *cp == '\t') {
|
|
cp++;
|
|
continue;
|
|
}
|
|
if (q < &(r_aliases[aliases_size - 1]))
|
|
*q++ = cp;
|
|
else {
|
|
*errnop = ERANGE;
|
|
return -1;
|
|
}
|
|
|
|
cp = strpbrk(cp, " \t");
|
|
if (cp != NULL)
|
|
*cp++ = '\0';
|
|
}
|
|
*q = NULL;
|
|
return 0;
|
|
}
|
|
|
|
/* 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);
|
|
}
|
|
|
|
static int
|
|
files_rpcent(void *retval, void *mdata, va_list ap)
|
|
{
|
|
char *name;
|
|
int number;
|
|
struct rpcent *rpc;
|
|
char *buffer;
|
|
size_t bufsize;
|
|
int *errnop;
|
|
|
|
char *line;
|
|
size_t linesize;
|
|
char **aliases;
|
|
int aliases_size;
|
|
char **rp;
|
|
|
|
struct files_state *st;
|
|
int rv;
|
|
int stayopen;
|
|
enum nss_lookup_type how;
|
|
|
|
how = (enum nss_lookup_type)mdata;
|
|
switch (how)
|
|
{
|
|
case nss_lt_name:
|
|
name = va_arg(ap, char *);
|
|
break;
|
|
case nss_lt_id:
|
|
number = va_arg(ap, int);
|
|
break;
|
|
case nss_lt_all:
|
|
break;
|
|
default:
|
|
return (NS_NOTFOUND);
|
|
}
|
|
|
|
rpc = va_arg(ap, struct rpcent *);
|
|
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->fp = fopen(RPCDB, "r")) == NULL) {
|
|
*errnop = errno;
|
|
return (NS_UNAVAIL);
|
|
}
|
|
|
|
if (how == nss_lt_all)
|
|
stayopen = 1;
|
|
else {
|
|
rewind(st->fp);
|
|
stayopen = st->stayopen;
|
|
}
|
|
|
|
do {
|
|
if ((line = fgetln(st->fp, &linesize)) == NULL) {
|
|
*errnop = errno;
|
|
rv = NS_RETURN;
|
|
break;
|
|
}
|
|
|
|
if (bufsize <= linesize + _ALIGNBYTES + sizeof(char *)) {
|
|
*errnop = ERANGE;
|
|
rv = NS_RETURN;
|
|
break;
|
|
}
|
|
|
|
aliases = (char **)_ALIGN(&buffer[linesize+1]);
|
|
aliases_size = (buffer + bufsize -
|
|
(char *)aliases)/sizeof(char *);
|
|
if (aliases_size < 1) {
|
|
*errnop = ERANGE;
|
|
rv = NS_RETURN;
|
|
break;
|
|
}
|
|
|
|
memcpy(buffer, line, linesize);
|
|
buffer[linesize] = '\0';
|
|
|
|
rv = rpcent_unpack(buffer, rpc, aliases, aliases_size, errnop);
|
|
if (rv != 0) {
|
|
if (*errnop == 0) {
|
|
rv = NS_NOTFOUND;
|
|
continue;
|
|
}
|
|
else {
|
|
rv = NS_RETURN;
|
|
break;
|
|
}
|
|
}
|
|
|
|
switch (how)
|
|
{
|
|
case nss_lt_name:
|
|
if (strcmp(rpc->r_name, name) == 0)
|
|
goto done;
|
|
for (rp = rpc->r_aliases; *rp != NULL; rp++) {
|
|
if (strcmp(*rp, name) == 0)
|
|
goto done;
|
|
}
|
|
rv = NS_NOTFOUND;
|
|
continue;
|
|
done:
|
|
rv = NS_SUCCESS;
|
|
break;
|
|
case nss_lt_id:
|
|
rv = (rpc->r_number == number) ? NS_SUCCESS :
|
|
NS_NOTFOUND;
|
|
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 rpcent **)retval) = rpc;
|
|
|
|
return (rv);
|
|
}
|
|
|
|
static int
|
|
files_setrpcent(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 SETRPCENT:
|
|
f = va_arg(ap,int);
|
|
if (st->fp == NULL)
|
|
st->fp = fopen(RPCDB, "r");
|
|
else
|
|
rewind(st->fp);
|
|
st->stayopen |= f;
|
|
break;
|
|
case ENDRPCENT:
|
|
if (st->fp != NULL) {
|
|
fclose(st->fp);
|
|
st->fp = 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)->current);
|
|
free(p);
|
|
}
|
|
|
|
static int
|
|
nis_rpcent(void *retval, void *mdata, va_list ap)
|
|
{
|
|
char *name;
|
|
int number;
|
|
struct rpcent *rpc;
|
|
char *buffer;
|
|
size_t bufsize;
|
|
int *errnop;
|
|
|
|
char **rp;
|
|
char **aliases;
|
|
int aliases_size;
|
|
|
|
char *lastkey;
|
|
char *resultbuf;
|
|
int resultbuflen;
|
|
char *buf;
|
|
|
|
struct nis_state *st;
|
|
int rv;
|
|
enum nss_lookup_type how;
|
|
int no_name_active;
|
|
|
|
how = (enum nss_lookup_type)mdata;
|
|
switch (how)
|
|
{
|
|
case nss_lt_name:
|
|
name = va_arg(ap, char *);
|
|
break;
|
|
case nss_lt_id:
|
|
number = va_arg(ap, int);
|
|
break;
|
|
case nss_lt_all:
|
|
break;
|
|
default:
|
|
return (NS_NOTFOUND);
|
|
}
|
|
|
|
buf = NULL;
|
|
rpc = va_arg(ap, struct rpcent *);
|
|
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->domain[0] == '\0') {
|
|
if (getdomainname(st->domain, sizeof(st->domain)) != 0) {
|
|
*errnop = errno;
|
|
return (NS_UNAVAIL);
|
|
}
|
|
}
|
|
|
|
no_name_active = 0;
|
|
do {
|
|
switch (how)
|
|
{
|
|
case nss_lt_name:
|
|
if (!st->no_name_map)
|
|
{
|
|
free(buf);
|
|
asprintf(&buf, "%s", name);
|
|
if (buf == NULL)
|
|
return (NS_TRYAGAIN);
|
|
rv = yp_match(st->domain, "rpc.byname", buf,
|
|
strlen(buf), &resultbuf, &resultbuflen);
|
|
|
|
switch (rv) {
|
|
case 0:
|
|
break;
|
|
case YPERR_MAP:
|
|
st->stepping = 0;
|
|
no_name_active = 1;
|
|
how = nss_lt_all;
|
|
|
|
rv = NS_NOTFOUND;
|
|
continue;
|
|
default:
|
|
rv = NS_NOTFOUND;
|
|
goto fin;
|
|
}
|
|
} else {
|
|
st->stepping = 0;
|
|
no_name_active = 1;
|
|
how = nss_lt_all;
|
|
|
|
rv = NS_NOTFOUND;
|
|
continue;
|
|
}
|
|
break;
|
|
case nss_lt_id:
|
|
free(buf);
|
|
asprintf(&buf, "%d", number);
|
|
if (buf == NULL)
|
|
return (NS_TRYAGAIN);
|
|
if (yp_match(st->domain, "rpc.bynumber", buf,
|
|
strlen(buf), &resultbuf, &resultbuflen)) {
|
|
rv = NS_NOTFOUND;
|
|
goto fin;
|
|
}
|
|
break;
|
|
case nss_lt_all:
|
|
if (!st->stepping) {
|
|
rv = yp_first(st->domain, "rpc.bynumber",
|
|
&st->current,
|
|
&st->currentlen, &resultbuf,
|
|
&resultbuflen);
|
|
if (rv) {
|
|
rv = NS_NOTFOUND;
|
|
goto fin;
|
|
}
|
|
st->stepping = 1;
|
|
} else {
|
|
lastkey = st->current;
|
|
rv = yp_next(st->domain, "rpc.bynumber",
|
|
st->current,
|
|
st->currentlen, &st->current,
|
|
&st->currentlen,
|
|
&resultbuf, &resultbuflen);
|
|
free(lastkey);
|
|
if (rv) {
|
|
st->stepping = 0;
|
|
rv = NS_NOTFOUND;
|
|
goto fin;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
/* we need a room for additional \n symbol */
|
|
if (bufsize <= resultbuflen + 1 + _ALIGNBYTES +
|
|
sizeof(char *)) {
|
|
*errnop = ERANGE;
|
|
rv = NS_RETURN;
|
|
free(resultbuf);
|
|
break;
|
|
}
|
|
|
|
aliases=(char **)_ALIGN(&buffer[resultbuflen+2]);
|
|
aliases_size = (buffer + bufsize - (char *)aliases) /
|
|
sizeof(char *);
|
|
if (aliases_size < 1) {
|
|
*errnop = ERANGE;
|
|
rv = NS_RETURN;
|
|
free(resultbuf);
|
|
break;
|
|
}
|
|
|
|
/*
|
|
* rpcent_unpack expects lines terminated with \n -- make it happy
|
|
*/
|
|
memcpy(buffer, resultbuf, resultbuflen);
|
|
buffer[resultbuflen] = '\n';
|
|
buffer[resultbuflen+1] = '\0';
|
|
free(resultbuf);
|
|
|
|
if (rpcent_unpack(buffer, rpc, aliases, aliases_size,
|
|
errnop) != 0) {
|
|
if (*errnop == 0)
|
|
rv = NS_NOTFOUND;
|
|
else
|
|
rv = NS_RETURN;
|
|
} else {
|
|
if ((how == nss_lt_all) && (no_name_active != 0)) {
|
|
if (strcmp(rpc->r_name, name) == 0)
|
|
goto done;
|
|
for (rp = rpc->r_aliases; *rp != NULL; rp++) {
|
|
if (strcmp(*rp, name) == 0)
|
|
goto done;
|
|
}
|
|
rv = NS_NOTFOUND;
|
|
continue;
|
|
done:
|
|
rv = NS_SUCCESS;
|
|
} else
|
|
rv = NS_SUCCESS;
|
|
}
|
|
|
|
} while (!(rv & NS_TERMINATE) && (how == nss_lt_all));
|
|
|
|
fin:
|
|
free(buf);
|
|
if ((rv == NS_SUCCESS) && (retval != NULL))
|
|
*((struct rpcent **)retval) = rpc;
|
|
|
|
return (rv);
|
|
}
|
|
|
|
static int
|
|
nis_setrpcent(void *retval, 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 SETRPCENT:
|
|
case ENDRPCENT:
|
|
free(st->current);
|
|
st->current = NULL;
|
|
st->stepping = 0;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return (NS_UNAVAIL);
|
|
}
|
|
#endif
|
|
|
|
#ifdef NS_CACHING
|
|
static int
|
|
rpc_id_func(char *buffer, size_t *buffer_size, va_list ap, void *cache_mdata)
|
|
{
|
|
char *name;
|
|
int rpc;
|
|
|
|
size_t desired_size, size;
|
|
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 *);
|
|
|
|
size = strlen(name);
|
|
desired_size = sizeof(enum nss_lookup_type) + size + 1;
|
|
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);
|
|
|
|
res = NS_SUCCESS;
|
|
break;
|
|
case nss_lt_id:
|
|
rpc = va_arg(ap, int);
|
|
|
|
desired_size = sizeof(enum nss_lookup_type) + sizeof(int);
|
|
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), &rpc,
|
|
sizeof(int));
|
|
|
|
res = NS_SUCCESS;
|
|
break;
|
|
default:
|
|
/* should be unreachable */
|
|
return (NS_UNAVAIL);
|
|
}
|
|
|
|
fin:
|
|
*buffer_size = desired_size;
|
|
return (res);
|
|
}
|
|
|
|
static int
|
|
rpc_marshal_func(char *buffer, size_t *buffer_size, void *retval, va_list ap,
|
|
void *cache_mdata)
|
|
{
|
|
char *name;
|
|
int num;
|
|
struct rpcent *rpc;
|
|
char *orig_buf;
|
|
size_t orig_buf_size;
|
|
|
|
struct rpcent new_rpc;
|
|
size_t desired_size, size, aliases_size;
|
|
char *p;
|
|
char **alias;
|
|
|
|
switch ((enum nss_lookup_type)cache_mdata) {
|
|
case nss_lt_name:
|
|
name = va_arg(ap, char *);
|
|
break;
|
|
case nss_lt_id:
|
|
num = va_arg(ap, int);
|
|
break;
|
|
case nss_lt_all:
|
|
break;
|
|
default:
|
|
/* should be unreachable */
|
|
return (NS_UNAVAIL);
|
|
}
|
|
|
|
rpc = va_arg(ap, struct rpcent *);
|
|
orig_buf = va_arg(ap, char *);
|
|
orig_buf_size = va_arg(ap, size_t);
|
|
|
|
desired_size = _ALIGNBYTES + sizeof(struct rpcent) + sizeof(char *);
|
|
if (rpc->r_name != NULL)
|
|
desired_size += strlen(rpc->r_name) + 1;
|
|
|
|
if (rpc->r_aliases != NULL) {
|
|
aliases_size = 0;
|
|
for (alias = rpc->r_aliases; *alias; ++alias) {
|
|
desired_size += strlen(*alias) + 1;
|
|
++aliases_size;
|
|
}
|
|
|
|
desired_size += _ALIGNBYTES + (aliases_size + 1) *
|
|
sizeof(char *);
|
|
}
|
|
|
|
if (*buffer_size < desired_size) {
|
|
/* this assignment is here for future use */
|
|
*buffer_size = desired_size;
|
|
return (NS_RETURN);
|
|
}
|
|
|
|
new_rpc = *rpc;
|
|
|
|
*buffer_size = desired_size;
|
|
memset(buffer, 0, desired_size);
|
|
p = buffer + sizeof(struct rpcent) + sizeof(char *);
|
|
memcpy(buffer + sizeof(struct rpcent), &p, sizeof(char *));
|
|
p = (char *)_ALIGN(p);
|
|
|
|
if (new_rpc.r_name != NULL) {
|
|
size = strlen(new_rpc.r_name);
|
|
memcpy(p, new_rpc.r_name, size);
|
|
new_rpc.r_name = p;
|
|
p += size + 1;
|
|
}
|
|
|
|
if (new_rpc.r_aliases != NULL) {
|
|
p = (char *)_ALIGN(p);
|
|
memcpy(p, new_rpc.r_aliases, sizeof(char *) * aliases_size);
|
|
new_rpc.r_aliases = (char **)p;
|
|
p += sizeof(char *) * (aliases_size + 1);
|
|
|
|
for (alias = new_rpc.r_aliases; *alias; ++alias) {
|
|
size = strlen(*alias);
|
|
memcpy(p, *alias, size);
|
|
*alias = p;
|
|
p += size + 1;
|
|
}
|
|
}
|
|
|
|
memcpy(buffer, &new_rpc, sizeof(struct rpcent));
|
|
return (NS_SUCCESS);
|
|
}
|
|
|
|
static int
|
|
rpc_unmarshal_func(char *buffer, size_t buffer_size, void *retval, va_list ap,
|
|
void *cache_mdata)
|
|
{
|
|
char *name;
|
|
int num;
|
|
struct rpcent *rpc;
|
|
char *orig_buf;
|
|
size_t orig_buf_size;
|
|
int *ret_errno;
|
|
|
|
char *p;
|
|
char **alias;
|
|
|
|
switch ((enum nss_lookup_type)cache_mdata) {
|
|
case nss_lt_name:
|
|
name = va_arg(ap, char *);
|
|
break;
|
|
case nss_lt_id:
|
|
num = va_arg(ap, int);
|
|
break;
|
|
case nss_lt_all:
|
|
break;
|
|
default:
|
|
/* should be unreachable */
|
|
return (NS_UNAVAIL);
|
|
}
|
|
|
|
rpc = va_arg(ap, struct rpcent *);
|
|
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 rpcent) - sizeof(char *)) {
|
|
*ret_errno = ERANGE;
|
|
return (NS_RETURN);
|
|
}
|
|
|
|
memcpy(rpc, buffer, sizeof(struct rpcent));
|
|
memcpy(&p, buffer + sizeof(struct rpcent), sizeof(char *));
|
|
|
|
orig_buf = (char *)_ALIGN(orig_buf);
|
|
memcpy(orig_buf, buffer + sizeof(struct rpcent) + sizeof(char *) +
|
|
_ALIGN(p) - (size_t)p,
|
|
buffer_size - sizeof(struct rpcent) - sizeof(char *) -
|
|
_ALIGN(p) + (size_t)p);
|
|
p = (char *)_ALIGN(p);
|
|
|
|
NS_APPLY_OFFSET(rpc->r_name, orig_buf, p, char *);
|
|
if (rpc->r_aliases != NULL) {
|
|
NS_APPLY_OFFSET(rpc->r_aliases, orig_buf, p, char **);
|
|
|
|
for (alias = rpc->r_aliases ; *alias; ++alias)
|
|
NS_APPLY_OFFSET(*alias, orig_buf, p, char *);
|
|
}
|
|
|
|
if (retval != NULL)
|
|
*((struct rpcent **)retval) = rpc;
|
|
|
|
return (NS_SUCCESS);
|
|
}
|
|
|
|
NSS_MP_CACHE_HANDLING(rpc);
|
|
#endif /* NS_CACHING */
|
|
|
|
|
|
/* get**_r functions implementation */
|
|
static int
|
|
getrpcbyname_r(const char *name, struct rpcent *rpc, char *buffer,
|
|
size_t bufsize, struct rpcent **result)
|
|
{
|
|
#ifdef NS_CACHING
|
|
static const nss_cache_info cache_info =
|
|
NS_COMMON_CACHE_INFO_INITIALIZER(
|
|
rpc, (void *)nss_lt_name,
|
|
rpc_id_func, rpc_marshal_func, rpc_unmarshal_func);
|
|
#endif
|
|
static const ns_dtab dtab[] = {
|
|
{ NSSRC_FILES, files_rpcent, (void *)nss_lt_name },
|
|
#ifdef YP
|
|
{ NSSRC_NIS, nis_rpcent, (void *)nss_lt_name },
|
|
#endif
|
|
#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_RPC, "getrpcbyname_r", defaultsrc,
|
|
name, rpc, buffer, bufsize, &ret_errno);
|
|
|
|
if (rv == NS_SUCCESS)
|
|
return (0);
|
|
else
|
|
return (ret_errno);
|
|
}
|
|
|
|
static int
|
|
getrpcbynumber_r(int number, struct rpcent *rpc, char *buffer,
|
|
size_t bufsize, struct rpcent **result)
|
|
{
|
|
#ifdef NS_CACHING
|
|
static const nss_cache_info cache_info =
|
|
NS_COMMON_CACHE_INFO_INITIALIZER(
|
|
rpc, (void *)nss_lt_id,
|
|
rpc_id_func, rpc_marshal_func, rpc_unmarshal_func);
|
|
#endif
|
|
static const ns_dtab dtab[] = {
|
|
{ NSSRC_FILES, files_rpcent, (void *)nss_lt_id },
|
|
#ifdef YP
|
|
{ NSSRC_NIS, nis_rpcent, (void *)nss_lt_id },
|
|
#endif
|
|
#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_RPC, "getrpcbynumber_r", defaultsrc,
|
|
number, rpc, buffer, bufsize, &ret_errno);
|
|
|
|
if (rv == NS_SUCCESS)
|
|
return (0);
|
|
else
|
|
return (ret_errno);
|
|
}
|
|
|
|
static int
|
|
getrpcent_r(struct rpcent *rpc, char *buffer, size_t bufsize,
|
|
struct rpcent **result)
|
|
{
|
|
#ifdef NS_CACHING
|
|
static const nss_cache_info cache_info = NS_MP_CACHE_INFO_INITIALIZER(
|
|
rpc, (void *)nss_lt_all,
|
|
rpc_marshal_func, rpc_unmarshal_func);
|
|
#endif
|
|
static const ns_dtab dtab[] = {
|
|
{ NSSRC_FILES, files_rpcent, (void *)nss_lt_all },
|
|
#ifdef YP
|
|
{ NSSRC_NIS, nis_rpcent, (void *)nss_lt_all },
|
|
#endif
|
|
#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_RPC, "getrpcent_r", defaultsrc,
|
|
rpc, buffer, bufsize, &ret_errno);
|
|
|
|
if (rv == NS_SUCCESS)
|
|
return (0);
|
|
else
|
|
return (ret_errno);
|
|
}
|
|
|
|
/* get** wrappers for get**_r functions implementation */
|
|
static void
|
|
rpcent_endstate(void *p)
|
|
{
|
|
if (p == NULL)
|
|
return;
|
|
|
|
free(((struct rpcent_state *)p)->buffer);
|
|
free(p);
|
|
}
|
|
|
|
static int
|
|
wrap_getrpcbyname_r(union key key, struct rpcent *rpc, char *buffer,
|
|
size_t bufsize, struct rpcent **res)
|
|
{
|
|
return (getrpcbyname_r(key.name, rpc, buffer, bufsize, res));
|
|
}
|
|
|
|
static int
|
|
wrap_getrpcbynumber_r(union key key, struct rpcent *rpc, char *buffer,
|
|
size_t bufsize, struct rpcent **res)
|
|
{
|
|
return (getrpcbynumber_r(key.number, rpc, buffer, bufsize, res));
|
|
}
|
|
|
|
static int
|
|
wrap_getrpcent_r(union key key __unused, struct rpcent *rpc, char *buffer,
|
|
size_t bufsize, struct rpcent **res)
|
|
{
|
|
return (getrpcent_r(rpc, buffer, bufsize, res));
|
|
}
|
|
|
|
static struct rpcent *
|
|
getrpc(int (*fn)(union key, struct rpcent *, char *, size_t, struct rpcent **),
|
|
union key key)
|
|
{
|
|
int rv;
|
|
struct rpcent *res;
|
|
struct rpcent_state * st;
|
|
|
|
rv=rpcent_getstate(&st);
|
|
if (rv != 0) {
|
|
errno = rv;
|
|
return NULL;
|
|
}
|
|
|
|
if (st->buffer == NULL) {
|
|
st->buffer = malloc(RPCENT_STORAGE_INITIAL);
|
|
if (st->buffer == NULL)
|
|
return (NULL);
|
|
st->bufsize = RPCENT_STORAGE_INITIAL;
|
|
}
|
|
do {
|
|
rv = fn(key, &st->rpc, st->buffer, st->bufsize, &res);
|
|
if (res == NULL && rv == ERANGE) {
|
|
free(st->buffer);
|
|
if ((st->bufsize << 1) > RPCENT_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 rpcent *
|
|
getrpcbyname(const char *name)
|
|
{
|
|
union key key;
|
|
|
|
key.name = name;
|
|
|
|
return (getrpc(wrap_getrpcbyname_r, key));
|
|
}
|
|
|
|
struct rpcent *
|
|
getrpcbynumber(int number)
|
|
{
|
|
union key key;
|
|
|
|
key.number = number;
|
|
|
|
return (getrpc(wrap_getrpcbynumber_r, key));
|
|
}
|
|
|
|
struct rpcent *
|
|
getrpcent(void)
|
|
{
|
|
union key key;
|
|
|
|
key.number = 0; /* not used */
|
|
|
|
return (getrpc(wrap_getrpcent_r, key));
|
|
}
|
|
|
|
void
|
|
setrpcent(int stayopen)
|
|
{
|
|
#ifdef NS_CACHING
|
|
static const nss_cache_info cache_info = NS_MP_CACHE_INFO_INITIALIZER(
|
|
rpc, (void *)nss_lt_all,
|
|
NULL, NULL);
|
|
#endif
|
|
|
|
static const ns_dtab dtab[] = {
|
|
{ NSSRC_FILES, files_setrpcent, (void *)SETRPCENT },
|
|
#ifdef YP
|
|
{ NSSRC_NIS, nis_setrpcent, (void *)SETRPCENT },
|
|
#endif
|
|
#ifdef NS_CACHING
|
|
NS_CACHE_CB(&cache_info)
|
|
#endif
|
|
{ NULL, NULL, NULL }
|
|
};
|
|
|
|
(void)nsdispatch(NULL, dtab, NSDB_RPC, "setrpcent", defaultsrc,
|
|
stayopen);
|
|
}
|
|
|
|
void
|
|
endrpcent(void)
|
|
{
|
|
#ifdef NS_CACHING
|
|
static const nss_cache_info cache_info = NS_MP_CACHE_INFO_INITIALIZER(
|
|
rpc, (void *)nss_lt_all,
|
|
NULL, NULL);
|
|
#endif
|
|
|
|
static const ns_dtab dtab[] = {
|
|
{ NSSRC_FILES, files_setrpcent, (void *)ENDRPCENT },
|
|
#ifdef YP
|
|
{ NSSRC_NIS, nis_setrpcent, (void *)ENDRPCENT },
|
|
#endif
|
|
#ifdef NS_CACHING
|
|
NS_CACHE_CB(&cache_info)
|
|
#endif
|
|
{ NULL, NULL, NULL }
|
|
};
|
|
|
|
(void)nsdispatch(NULL, dtab, NSDB_RPC, "endrpcent", defaultsrc);
|
|
}
|