OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /or1k/trunk/linux/uClibc/libc/inet
    from Rev 1325 to Rev 1765
    Reverse comparison

Rev 1325 → Rev 1765

/getservice.c
0,0 → 1,259
/*
** services.c /etc/services access functions
**
** This file is part of the NYS Library.
**
** The NYS Library is free software; you can redistribute it and/or
** modify it under the terms of the GNU Library General Public License as
** published by the Free Software Foundation; either version 2 of the
** License, or (at your option) any later version.
**
** The NYS Library is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
** Library General Public License for more details.
**
** You should have received a copy of the GNU Library General Public
** License along with the NYS Library; see the file COPYING.LIB. If
** not, write to the Free Software Foundation, Inc., 675 Mass Ave,
** Cambridge, MA 02139, USA.
**
**
** Copyright (c) 1983 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.
** 3. All advertising materials mentioning features or use of this software
** must display the following acknowledgement:
** This product includes software developed by the University of
** California, Berkeley and its contributors.
** 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.
*/
 
 
#define __FORCE_GLIBC
#define _GNU_SOURCE
#include <features.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
 
 
 
#ifdef __UCLIBC_HAS_THREADS__
#include <pthread.h>
static pthread_mutex_t mylock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
# define LOCK __pthread_mutex_lock(&mylock)
# define UNLOCK __pthread_mutex_unlock(&mylock);
#else
# define LOCK
# define UNLOCK
#endif
 
 
 
 
#define MAXALIASES 35
 
static FILE *servf = NULL;
static struct servent serv;
static char buf[BUFSIZ+1 + sizeof(char *)*MAXALIASES];
static int serv_stayopen;
 
void setservent(int f)
{
LOCK;
if (servf == NULL)
servf = fopen(_PATH_SERVICES, "r" );
else
rewind(servf);
serv_stayopen |= f;
UNLOCK;
}
 
void endservent(void)
{
LOCK;
if (servf) {
fclose(servf);
servf = NULL;
}
serv_stayopen = 0;
UNLOCK;
}
 
struct servent * getservent(void)
{
struct servent *result;
getservent_r(&serv, buf, sizeof(buf), &result);
return result;
}
 
 
struct servent *getservbyname(const char *name, const char *proto)
{
struct servent *result;
getservbyname_r(name, proto, &serv, buf, sizeof(buf), &result);
return result;
}
 
 
struct servent * getservbyport(int port, const char *proto)
{
struct servent *result;
getservbyport_r(port, proto, &serv, buf, sizeof(buf), &result);
return result;
}
 
int getservent_r(struct servent * result_buf,
char * buf, size_t buflen,
struct servent ** result)
{
char *p;
register char *cp, **q;
char **serv_aliases;
char *line;
 
*result=NULL;
 
if (buflen < sizeof(*serv_aliases)*MAXALIASES) {
errno=ERANGE;
return errno;
}
LOCK;
serv_aliases=(char **)buf;
buf+=sizeof(*serv_aliases)*MAXALIASES;
buflen-=sizeof(*serv_aliases)*MAXALIASES;
 
if (buflen < BUFSIZ+1) {
UNLOCK;
errno=ERANGE;
return errno;
}
line=buf;
buf+=BUFSIZ+1;
buflen-=BUFSIZ+1;
 
if (servf == NULL && (servf = fopen(_PATH_SERVICES, "r" )) == NULL) {
UNLOCK;
errno=EIO;
return errno;
}
again:
if ((p = fgets(line, BUFSIZ, servf)) == NULL) {
UNLOCK;
errno=EIO;
return errno;
}
if (*p == '#')
goto again;
cp = strpbrk(p, "#\n");
if (cp == NULL)
goto again;
*cp = '\0';
result_buf->s_name = p;
p = strpbrk(p, " \t");
if (p == NULL)
goto again;
*p++ = '\0';
while (*p == ' ' || *p == '\t')
p++;
cp = strpbrk(p, ",/");
if (cp == NULL)
goto again;
*cp++ = '\0';
result_buf->s_port = htons((u_short)atoi(p));
result_buf->s_proto = cp;
q = result_buf->s_aliases = serv_aliases;
cp = strpbrk(cp, " \t");
if (cp != NULL)
*cp++ = '\0';
while (cp && *cp) {
if (*cp == ' ' || *cp == '\t') {
cp++;
continue;
}
if (q < &serv_aliases[MAXALIASES - 1])
*q++ = cp;
cp = strpbrk(cp, " \t");
if (cp != NULL)
*cp++ = '\0';
}
*q = NULL;
*result=result_buf;
UNLOCK;
return 0;
}
 
int getservbyname_r(const char *name, const char *proto,
struct servent * result_buf, char * buf, size_t buflen,
struct servent ** result)
{
register char **cp;
int ret;
 
LOCK;
setservent(serv_stayopen);
while (!(ret=getservent_r(result_buf, buf, buflen, result))) {
if (strcmp(name, result_buf->s_name) == 0)
goto gotname;
for (cp = result_buf->s_aliases; *cp; cp++)
if (strcmp(name, *cp) == 0)
goto gotname;
continue;
gotname:
if (proto == 0 || strcmp(result_buf->s_proto, proto) == 0)
break;
}
if (!serv_stayopen)
endservent();
UNLOCK;
return *result?0:ret;
}
 
int getservbyport_r(int port, const char *proto,
struct servent * result_buf, char * buf,
size_t buflen, struct servent ** result)
{
int ret;
 
LOCK;
setservent(serv_stayopen);
while (!(ret=getservent_r(result_buf, buf, buflen, result))) {
if (result_buf->s_port != port)
continue;
if (proto == 0 || strcmp(result_buf->s_proto, proto) == 0)
break;
}
if (!serv_stayopen)
endservent();
UNLOCK;
return *result?0:ret;
}
/herror.c
0,0 → 1,65
/*
* Copyright (c) 1987 Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms are permitted
* provided that: (1) source distributions retain this entire copyright
* notice and comment, and (2) distributions including binaries display
* the following acknowledgement: ``This product includes software
* developed by the University of California, Berkeley and its contributors''
* in the documentation or other materials provided with the distribution
* and in all advertising materials mentioning features or use of this
* software. 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
 
#define __FORCE_GLIBC
#include <features.h>
#include <stdio.h>
#include <string.h>
#include <netdb.h>
 
static const char *error_msg = "Resolver error";
static const char *const h_errlist[] = {
"Error 0",
"Unknown host", /* 1 HOST_NOT_FOUND */
"Host name lookup failure", /* 2 TRY_AGAIN */
"Unknown server error", /* 3 NO_RECOVERY */
"No address associated with name", /* 4 NO_ADDRESS */
};
static const int h_nerr = { sizeof(h_errlist)/sizeof(h_errlist[0]) };
 
/*
* herror -- print the error indicated by the h_errno value.
*/
void herror(const char *s)
{
static const char colon_space[] = ": ";
const char *p;
const char *c;
 
c = colon_space;
if (!s || !*s) {
c += 2;
}
p = error_msg;
if ((h_errno >= 0) && (h_errno < h_nerr)) {
p = h_errlist[h_errno];
}
fprintf(stderr, "%s%s%s\n", s, c, p);
}
 
 
const char *hstrerror(int err)
{
if (err < 0) {
return(error_msg);
} else if (err < h_nerr) {
return(h_errlist[err]);
}
return(error_msg);
}
/ether_addr.c
0,0 → 1,93
/* Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
 
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA.
*/
 
/*
* 2002-12-24 Nick Fedchik <nick@fedchik.org.ua>
* - initial uClibc port
*/
 
 
#define __FORCE_GLIBC
#include <features.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <netinet/ether.h>
#include <netinet/if_ether.h>
 
struct ether_addr *ether_aton(const char *asc)
{
static struct ether_addr result;
 
return ether_aton_r(asc, &result);
}
 
struct ether_addr *ether_aton_r(const char *asc, struct ether_addr *addr)
{
size_t cnt;
 
for (cnt = 0; cnt < 6; ++cnt) {
unsigned int number;
char ch;
 
ch = _tolower(*asc++);
if ((ch < '0' || ch > '9') && (ch < 'a' || ch > 'f'))
return NULL;
number = isdigit(ch) ? (ch - '0') : (ch - 'a' + 10);
 
ch = _tolower(*asc);
if ((cnt < 5 && ch != ':')
|| (cnt == 5 && ch != '\0' && !isspace(ch))) {
++asc;
if ((ch < '0' || ch > '9') && (ch < 'a' || ch > 'f'))
return NULL;
number <<= 4;
number += isdigit(ch) ? (ch - '0') : (ch - 'a' + 10);
 
ch = *asc;
if (cnt < 5 && ch != ':')
return NULL;
}
 
/* Store result. */
addr->ether_addr_octet[cnt] = (unsigned char) number;
 
/* Skip ':'. */
++asc;
}
 
return addr;
}
 
char *ether_ntoa(const struct ether_addr *addr)
{
static char asc[18];
 
return ether_ntoa_r(addr, asc);
}
 
char *ether_ntoa_r(const struct ether_addr *addr, char *buf)
{
sprintf(buf, "%x:%x:%x:%x:%x:%x",
addr->ether_addr_octet[0], addr->ether_addr_octet[1],
addr->ether_addr_octet[2], addr->ether_addr_octet[3],
addr->ether_addr_octet[4], addr->ether_addr_octet[5]);
return buf;
}
/gai_strerror.c
0,0 → 1,62
/* Copyright (C) 1997, 2001 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Philip Blundell <pjb27@cam.ac.uk>, 1997.
 
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
 
#define _GNU_SOURCE
#define __FORCE_GLIBC
#include <features.h>
#include <stdio.h>
#include <netdb.h>
 
#define N_(x) x
#define _(x) x
static struct
{
int code;
const char *msg;
}
values[] =
{
{ EAI_ADDRFAMILY, N_("Address family for hostname not supported") },
{ EAI_AGAIN, N_("Temporary failure in name resolution") },
{ EAI_BADFLAGS, N_("Bad value for ai_flags") },
{ EAI_FAIL, N_("Non-recoverable failure in name resolution") },
{ EAI_FAMILY, N_("ai_family not supported") },
{ EAI_MEMORY, N_("Memory allocation failure") },
{ EAI_NODATA, N_("No address associated with hostname") },
{ EAI_NONAME, N_("Name or service not known") },
{ EAI_SERVICE, N_("Servname not supported for ai_socktype") },
{ EAI_SOCKTYPE, N_("ai_socktype not supported") },
{ EAI_SYSTEM, N_("System error") },
{ EAI_INPROGRESS, N_("Processing request in progress") },
{ EAI_CANCELED, N_("Request canceled") },
{ EAI_NOTCANCELED, N_("Request not canceled") },
{ EAI_ALLDONE, N_("All requests done") },
{ EAI_INTR, N_("Interrupted by a signal") }
};
 
const char *
gai_strerror (int code)
{
size_t i;
for (i = 0; i < sizeof (values) / sizeof (values[0]); ++i)
if (values[i].code == code)
return _(values[i].msg);
 
return _("Unknown error");
}
/rpc/svc_unix.c
0,0 → 1,533
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
* media and as a part of the software program in whole or part. Users
* may copy or modify Sun RPC without charge, but are not authorized
* to license or distribute it to anyone else except as part of a product or
* program developed by the user.
*
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun RPC is provided with no support and without any obligation on the
* part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
 
/*
* svc_unix.c, Server side for TCP/IP based RPC.
*
* Copyright (C) 1984, Sun Microsystems, Inc.
*
* Actually implements two flavors of transporter -
* a unix rendezvouser (a listener and connection establisher)
* and a record/unix stream.
*/
 
#define __FORCE_GLIBC
#include <features.h>
 
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <rpc/rpc.h>
#include <rpc/svc.h>
#include <sys/socket.h>
#include <sys/uio.h>
#include <sys/poll.h>
#include <errno.h>
#include <stdlib.h>
 
#ifdef USE_IN_LIBIO
# include <wchar.h>
#endif
 
/*
* Ops vector for AF_UNIX based rpc service handle
*/
static bool_t svcunix_recv (SVCXPRT *, struct rpc_msg *);
static enum xprt_stat svcunix_stat (SVCXPRT *);
static bool_t svcunix_getargs (SVCXPRT *, xdrproc_t, caddr_t);
static bool_t svcunix_reply (SVCXPRT *, struct rpc_msg *);
static bool_t svcunix_freeargs (SVCXPRT *, xdrproc_t, caddr_t);
static void svcunix_destroy (SVCXPRT *);
 
static const struct xp_ops svcunix_op =
{
svcunix_recv,
svcunix_stat,
svcunix_getargs,
svcunix_reply,
svcunix_freeargs,
svcunix_destroy
};
 
/*
* Ops vector for AF_UNIX rendezvous handler
*/
static bool_t rendezvous_request (SVCXPRT *, struct rpc_msg *);
static enum xprt_stat rendezvous_stat (SVCXPRT *);
static void svcunix_rendezvous_abort (void);
 
/* This function makes sure abort() relocation goes through PLT
and thus can be lazy bound. */
static void
svcunix_rendezvous_abort (void)
{
abort ();
};
 
static const struct xp_ops svcunix_rendezvous_op =
{
rendezvous_request,
rendezvous_stat,
(bool_t (*) (SVCXPRT *, xdrproc_t, caddr_t)) svcunix_rendezvous_abort,
(bool_t (*) (SVCXPRT *, struct rpc_msg *)) svcunix_rendezvous_abort,
(bool_t (*) (SVCXPRT *, xdrproc_t, caddr_t)) svcunix_rendezvous_abort,
svcunix_destroy
};
 
static int readunix (char*, char *, int);
static int writeunix (char *, char *, int);
static SVCXPRT *makefd_xprt (int, u_int, u_int) internal_function;
 
struct unix_rendezvous { /* kept in xprt->xp_p1 */
u_int sendsize;
u_int recvsize;
};
 
struct unix_conn { /* kept in xprt->xp_p1 */
enum xprt_stat strm_stat;
u_long x_id;
XDR xdrs;
char verf_body[MAX_AUTH_BYTES];
};
 
/*
* Usage:
* xprt = svcunix_create(sock, send_buf_size, recv_buf_size);
*
* Creates, registers, and returns a (rpc) unix based transporter.
* Once *xprt is initialized, it is registered as a transporter
* see (svc.h, xprt_register). This routine returns
* a NULL if a problem occurred.
*
* If sock<0 then a socket is created, else sock is used.
* If the socket, sock is not bound to a port then svcunix_create
* binds it to an arbitrary port. The routine then starts a unix
* listener on the socket's associated port. In any (successful) case,
* xprt->xp_sock is the registered socket number and xprt->xp_port is the
* associated port number.
*
* Since unix streams do buffered io similar to stdio, the caller can specify
* how big the send and receive buffers are via the second and third parms;
* 0 => use the system default.
*/
SVCXPRT *
svcunix_create (int sock, u_int sendsize, u_int recvsize, char *path)
{
bool_t madesock = FALSE;
SVCXPRT *xprt;
struct unix_rendezvous *r;
struct sockaddr_un addr;
socklen_t len = sizeof (struct sockaddr_in);
 
if (sock == RPC_ANYSOCK)
{
if ((sock = socket (AF_UNIX, SOCK_STREAM, 0)) < 0)
{
perror (_("svc_unix.c - AF_UNIX socket creation problem"));
return (SVCXPRT *) NULL;
}
madesock = TRUE;
}
memset (&addr, '\0', sizeof (addr));
addr.sun_family = AF_UNIX;
len = strlen (path) + 1;
memcpy (addr.sun_path, path, len);
len += sizeof (addr.sun_family);
 
bind (sock, (struct sockaddr *) &addr, len);
 
if (getsockname (sock, (struct sockaddr *) &addr, &len) != 0
|| listen (sock, 2) != 0)
{
perror (_("svc_unix.c - cannot getsockname or listen"));
if (madesock)
close (sock);
return (SVCXPRT *) NULL;
}
 
r = (struct unix_rendezvous *) mem_alloc (sizeof (*r));
xprt = (SVCXPRT *) mem_alloc (sizeof (SVCXPRT));
if (r == NULL || xprt == NULL)
{
#ifdef USE_IN_LIBIO
if (_IO_fwide (stderr, 0) > 0)
__fwprintf (stderr, L"%s", _("svcunix_create: out of memory\n"));
else
#endif
fputs (_("svcunix_create: out of memory\n"), stderr);
mem_free (r, sizeof (*r));
mem_free (xprt, sizeof (SVCXPRT));
return NULL;
}
r->sendsize = sendsize;
r->recvsize = recvsize;
xprt->xp_p2 = NULL;
xprt->xp_p1 = (caddr_t) r;
xprt->xp_verf = _null_auth;
xprt->xp_ops = &svcunix_rendezvous_op;
xprt->xp_port = -1;
xprt->xp_sock = sock;
xprt_register (xprt);
return xprt;
}
 
/*
* Like svunix_create(), except the routine takes any *open* UNIX file
* descriptor as its first input.
*/
SVCXPRT *
svcunixfd_create (int fd, u_int sendsize, u_int recvsize)
{
return makefd_xprt (fd, sendsize, recvsize);
}
 
static SVCXPRT *
internal_function
makefd_xprt (int fd, u_int sendsize, u_int recvsize)
{
SVCXPRT *xprt;
struct unix_conn *cd;
 
xprt = (SVCXPRT *) mem_alloc (sizeof (SVCXPRT));
cd = (struct unix_conn *) mem_alloc (sizeof (struct unix_conn));
if (xprt == (SVCXPRT *) NULL || cd == (struct unix_conn *) NULL)
{
#ifdef USE_IN_LIBIO
if (_IO_fwide (stderr, 0) > 0)
(void) __fwprintf (stderr, L"%s",
_("svc_unix: makefd_xprt: out of memory\n"));
else
#endif
(void) fputs (_("svc_unix: makefd_xprt: out of memory\n"), stderr);
mem_free (xprt, sizeof (SVCXPRT));
mem_free (cd, sizeof (struct unix_conn));
return NULL;
}
cd->strm_stat = XPRT_IDLE;
xdrrec_create (&(cd->xdrs), sendsize, recvsize,
(caddr_t) xprt, readunix, writeunix);
xprt->xp_p2 = NULL;
xprt->xp_p1 = (caddr_t) cd;
xprt->xp_verf.oa_base = cd->verf_body;
xprt->xp_addrlen = 0;
xprt->xp_ops = &svcunix_op; /* truly deals with calls */
xprt->xp_port = 0; /* this is a connection, not a rendezvouser */
xprt->xp_sock = fd;
xprt_register (xprt);
return xprt;
}
 
static bool_t
rendezvous_request (SVCXPRT *xprt, struct rpc_msg *errmsg)
{
int sock;
struct unix_rendezvous *r;
struct sockaddr_un addr;
struct sockaddr_in in_addr;
socklen_t len;
 
r = (struct unix_rendezvous *) xprt->xp_p1;
again:
len = sizeof (struct sockaddr_un);
if ((sock = accept (xprt->xp_sock, (struct sockaddr *) &addr, &len)) < 0)
{
if (errno == EINTR)
goto again;
return FALSE;
}
/*
* make a new transporter (re-uses xprt)
*/
memset (&in_addr, '\0', sizeof (in_addr));
in_addr.sin_family = AF_UNIX;
xprt = makefd_xprt (sock, r->sendsize, r->recvsize);
memcpy (&xprt->xp_raddr, &in_addr, sizeof (in_addr));
xprt->xp_addrlen = len;
return FALSE; /* there is never an rpc msg to be processed */
}
 
static enum xprt_stat
rendezvous_stat (SVCXPRT *xprt)
{
return XPRT_IDLE;
}
 
static void
svcunix_destroy (SVCXPRT *xprt)
{
struct unix_conn *cd = (struct unix_conn *) xprt->xp_p1;
 
xprt_unregister (xprt);
close (xprt->xp_sock);
if (xprt->xp_port != 0)
{
/* a rendezvouser socket */
xprt->xp_port = 0;
}
else
{
/* an actual connection socket */
XDR_DESTROY (&(cd->xdrs));
}
mem_free ((caddr_t) cd, sizeof (struct unix_conn));
mem_free ((caddr_t) xprt, sizeof (SVCXPRT));
}
 
#ifdef SCM_CREDENTIALS
struct cmessage {
struct cmsghdr cmsg;
struct ucred cmcred;
/* hack to make sure we have enough memory */
char dummy[(CMSG_ALIGN (sizeof (struct ucred)) - sizeof (struct ucred) + sizeof (long))];
};
 
/* XXX This is not thread safe, but since the main functions in svc.c
and the rpcgen generated *_svc functions for the daemon are also not
thread safe and uses static global variables, it doesn't matter. */
static struct cmessage cm;
#endif
 
static int
__msgread (int sock, void *data, size_t cnt)
{
struct iovec iov;
struct msghdr msg;
int len;
 
iov.iov_base = data;
iov.iov_len = cnt;
 
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
msg.msg_name = NULL;
msg.msg_namelen = 0;
#ifdef SCM_CREDENTIALS
msg.msg_control = (caddr_t) &cm;
msg.msg_controllen = sizeof (struct cmessage);
#endif
msg.msg_flags = 0;
 
#ifdef SO_PASSCRED
{
int on = 1;
if (setsockopt (sock, SOL_SOCKET, SO_PASSCRED, &on, sizeof (on)))
return -1;
}
#endif
 
restart:
len = recvmsg (sock, &msg, 0);
if (len >= 0)
{
if (msg.msg_flags & MSG_CTRUNC || len == 0)
return 0;
else
return len;
}
if (errno == EINTR)
goto restart;
return -1;
}
 
static int
__msgwrite (int sock, void *data, size_t cnt)
{
#ifndef SCM_CREDENTIALS
/* We cannot implement this reliably. */
__set_errno (ENOSYS);
return -1;
#else
struct iovec iov;
struct msghdr msg;
struct cmsghdr *cmsg = &cm.cmsg;
struct ucred cred;
int len;
 
/* XXX I'm not sure, if gete?id() is always correct, or if we should use
get?id(). But since keyserv needs geteuid(), we have no other chance.
It would be much better, if the kernel could pass both to the server. */
cred.pid = getpid ();
cred.uid = geteuid ();
cred.gid = getegid ();
 
memcpy (CMSG_DATA(cmsg), &cred, sizeof (struct ucred));
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_CREDENTIALS;
cmsg->cmsg_len = sizeof(*cmsg) + sizeof(struct ucred);
 
iov.iov_base = data;
iov.iov_len = cnt;
 
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
msg.msg_name = NULL;
msg.msg_namelen = 0;
msg.msg_control = cmsg;
msg.msg_controllen = CMSG_ALIGN(cmsg->cmsg_len);
msg.msg_flags = 0;
 
restart:
len = sendmsg (sock, &msg, 0);
if (len >= 0)
return len;
if (errno == EINTR)
goto restart;
return -1;
 
#endif
}
 
/*
* reads data from the unix connection.
* any error is fatal and the connection is closed.
* (And a read of zero bytes is a half closed stream => error.)
*/
static int
readunix (char *xprtptr, char *buf, int len)
{
SVCXPRT *xprt = (SVCXPRT *) xprtptr;
int sock = xprt->xp_sock;
int milliseconds = 35 * 1000;
struct pollfd pollfd;
 
do
{
pollfd.fd = sock;
pollfd.events = POLLIN;
switch (poll (&pollfd, 1, milliseconds))
{
case -1:
if (errno == EINTR)
continue;
/*FALLTHROUGH*/
case 0:
goto fatal_err;
default:
if ((pollfd.revents & POLLERR) || (pollfd.revents & POLLHUP)
|| (pollfd.revents & POLLNVAL))
goto fatal_err;
break;
}
}
while ((pollfd.revents & POLLIN) == 0);
 
if ((len = __msgread (sock, buf, len)) > 0)
return len;
 
fatal_err:
((struct unix_conn *) (xprt->xp_p1))->strm_stat = XPRT_DIED;
return -1;
}
 
/*
* writes data to the unix connection.
* Any error is fatal and the connection is closed.
*/
static int
writeunix (char *xprtptr, char * buf, int len)
{
SVCXPRT *xprt = (SVCXPRT *) xprtptr;
int i, cnt;
 
for (cnt = len; cnt > 0; cnt -= i, buf += i)
{
if ((i = __msgwrite (xprt->xp_sock, buf, cnt)) < 0)
{
((struct unix_conn *) (xprt->xp_p1))->strm_stat = XPRT_DIED;
return -1;
}
}
return len;
}
 
static enum xprt_stat
svcunix_stat (SVCXPRT *xprt)
{
struct unix_conn *cd =
(struct unix_conn *) (xprt->xp_p1);
 
if (cd->strm_stat == XPRT_DIED)
return XPRT_DIED;
if (!xdrrec_eof (&(cd->xdrs)))
return XPRT_MOREREQS;
return XPRT_IDLE;
}
 
static bool_t
svcunix_recv (SVCXPRT *xprt, struct rpc_msg *msg)
{
struct unix_conn *cd = (struct unix_conn *) (xprt->xp_p1);
XDR *xdrs = &(cd->xdrs);
 
xdrs->x_op = XDR_DECODE;
xdrrec_skiprecord (xdrs);
if (xdr_callmsg (xdrs, msg))
{
cd->x_id = msg->rm_xid;
/* set up verifiers */
#ifdef SCM_CREDENTIALS
msg->rm_call.cb_verf.oa_flavor = AUTH_UNIX;
msg->rm_call.cb_verf.oa_base = (caddr_t) &cm;
msg->rm_call.cb_verf.oa_length = sizeof (cm);
#endif
return TRUE;
}
cd->strm_stat = XPRT_DIED; /* XXXX */
return FALSE;
}
 
static bool_t
svcunix_getargs (SVCXPRT *xprt, xdrproc_t xdr_args, caddr_t args_ptr)
{
return (*xdr_args) (&(((struct unix_conn *) (xprt->xp_p1))->xdrs),
args_ptr);
}
 
static bool_t
svcunix_freeargs (SVCXPRT *xprt, xdrproc_t xdr_args, caddr_t args_ptr)
{
XDR *xdrs = &(((struct unix_conn *) (xprt->xp_p1))->xdrs);
 
xdrs->x_op = XDR_FREE;
return (*xdr_args) (xdrs, args_ptr);
}
 
static bool_t
svcunix_reply (SVCXPRT *xprt, struct rpc_msg *msg)
{
struct unix_conn *cd = (struct unix_conn *) (xprt->xp_p1);
XDR *xdrs = &(cd->xdrs);
bool_t stat;
 
xdrs->x_op = XDR_ENCODE;
msg->rm_xid = cd->x_id;
stat = xdr_replymsg (xdrs, msg);
(void) xdrrec_endofrecord (xdrs, TRUE);
return stat;
}
/rpc/svc_tcp.c
0,0 → 1,426
/* @(#)svc_tcp.c 2.2 88/08/01 4.0 RPCSRC */
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
* media and as a part of the software program in whole or part. Users
* may copy or modify Sun RPC without charge, but are not authorized
* to license or distribute it to anyone else except as part of a product or
* program developed by the user.
*
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun RPC is provided with no support and without any obligation on the
* part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
#if 0
static char sccsid[] = "@(#)svc_tcp.c 1.21 87/08/11 Copyr 1984 Sun Micro";
#endif
 
/*
* svc_tcp.c, Server side for TCP/IP based RPC.
*
* Copyright (C) 1984, Sun Microsystems, Inc.
*
* Actually implements two flavors of transporter -
* a tcp rendezvouser (a listener and connection establisher)
* and a record/tcp stream.
*/
 
#define __FORCE_GLIBC
#define _GNU_SOURCE
#include <features.h>
 
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <rpc/rpc.h>
#include <sys/socket.h>
#include <sys/poll.h>
#include <errno.h>
#include <stdlib.h>
 
#ifdef USE_IN_LIBIO
# include <wchar.h>
# include <libio/iolibio.h>
# define fputs(s, f) _IO_fputs (s, f)
#endif
 
/*
* Ops vector for TCP/IP based rpc service handle
*/
static bool_t svctcp_recv (SVCXPRT *, struct rpc_msg *);
static enum xprt_stat svctcp_stat (SVCXPRT *);
static bool_t svctcp_getargs (SVCXPRT *, xdrproc_t, caddr_t);
static bool_t svctcp_reply (SVCXPRT *, struct rpc_msg *);
static bool_t svctcp_freeargs (SVCXPRT *, xdrproc_t, caddr_t);
static void svctcp_destroy (SVCXPRT *);
 
static const struct xp_ops svctcp_op =
{
svctcp_recv,
svctcp_stat,
svctcp_getargs,
svctcp_reply,
svctcp_freeargs,
svctcp_destroy
};
 
/*
* Ops vector for TCP/IP rendezvous handler
*/
static bool_t rendezvous_request (SVCXPRT *, struct rpc_msg *);
static enum xprt_stat rendezvous_stat (SVCXPRT *);
static void svctcp_rendezvous_abort (void);
 
/* This function makes sure abort() relocation goes through PLT
and thus can be lazy bound. */
static void
svctcp_rendezvous_abort (void)
{
abort ();
};
 
static const struct xp_ops svctcp_rendezvous_op =
{
rendezvous_request,
rendezvous_stat,
(bool_t (*) (SVCXPRT *, xdrproc_t, caddr_t)) svctcp_rendezvous_abort,
(bool_t (*) (SVCXPRT *, struct rpc_msg *)) svctcp_rendezvous_abort,
(bool_t (*) (SVCXPRT *, xdrproc_t, caddr_t)) svctcp_rendezvous_abort,
svctcp_destroy
};
 
static int readtcp (char*, char *, int);
static int writetcp (char *, char *, int);
static SVCXPRT *makefd_xprt (int, u_int, u_int) internal_function;
 
struct tcp_rendezvous
{ /* kept in xprt->xp_p1 */
u_int sendsize;
u_int recvsize;
};
 
struct tcp_conn
{ /* kept in xprt->xp_p1 */
enum xprt_stat strm_stat;
u_long x_id;
XDR xdrs;
char verf_body[MAX_AUTH_BYTES];
};
 
/*
* Usage:
* xprt = svctcp_create(sock, send_buf_size, recv_buf_size);
*
* Creates, registers, and returns a (rpc) tcp based transporter.
* Once *xprt is initialized, it is registered as a transporter
* see (svc.h, xprt_register). This routine returns
* a NULL if a problem occurred.
*
* If sock<0 then a socket is created, else sock is used.
* If the socket, sock is not bound to a port then svctcp_create
* binds it to an arbitrary port. The routine then starts a tcp
* listener on the socket's associated port. In any (successful) case,
* xprt->xp_sock is the registered socket number and xprt->xp_port is the
* associated port number.
*
* Since tcp streams do buffered io similar to stdio, the caller can specify
* how big the send and receive buffers are via the second and third parms;
* 0 => use the system default.
*/
SVCXPRT *
svctcp_create (int sock, u_int sendsize, u_int recvsize)
{
bool_t madesock = FALSE;
SVCXPRT *xprt;
struct tcp_rendezvous *r;
struct sockaddr_in addr;
socklen_t len = sizeof (struct sockaddr_in);
 
if (sock == RPC_ANYSOCK)
{
if ((sock = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
{
perror (_("svc_tcp.c - tcp socket creation problem"));
return (SVCXPRT *) NULL;
}
madesock = TRUE;
}
bzero ((char *) &addr, sizeof (addr));
addr.sin_family = AF_INET;
if (bindresvport (sock, &addr))
{
addr.sin_port = 0;
(void) bind (sock, (struct sockaddr *) &addr, len);
}
if ((getsockname (sock, (struct sockaddr *) &addr, &len) != 0) ||
(listen (sock, 2) != 0))
{
perror (_("svc_tcp.c - cannot getsockname or listen"));
if (madesock)
(void) close (sock);
return (SVCXPRT *) NULL;
}
r = (struct tcp_rendezvous *) mem_alloc (sizeof (*r));
xprt = (SVCXPRT *) mem_alloc (sizeof (SVCXPRT));
if (r == NULL || xprt == NULL)
{
#ifdef USE_IN_LIBIO
if (_IO_fwide (stderr, 0) > 0)
(void) __fwprintf (stderr, L"%s", _("svctcp_create: out of memory\n"));
else
#endif
(void) fputs (_("svctcp_create: out of memory\n"), stderr);
mem_free (r, sizeof (*r));
mem_free (xprt, sizeof (SVCXPRT));
return NULL;
}
r->sendsize = sendsize;
r->recvsize = recvsize;
xprt->xp_p2 = NULL;
xprt->xp_p1 = (caddr_t) r;
xprt->xp_verf = _null_auth;
xprt->xp_ops = &svctcp_rendezvous_op;
xprt->xp_port = ntohs (addr.sin_port);
xprt->xp_sock = sock;
xprt_register (xprt);
return xprt;
}
 
/*
* Like svtcp_create(), except the routine takes any *open* UNIX file
* descriptor as its first input.
*/
SVCXPRT *
svcfd_create (int fd, u_int sendsize, u_int recvsize)
{
return makefd_xprt (fd, sendsize, recvsize);
}
 
static SVCXPRT *
internal_function
makefd_xprt (int fd, u_int sendsize, u_int recvsize)
{
SVCXPRT *xprt;
struct tcp_conn *cd;
 
xprt = (SVCXPRT *) mem_alloc (sizeof (SVCXPRT));
cd = (struct tcp_conn *) mem_alloc (sizeof (struct tcp_conn));
if (xprt == (SVCXPRT *) NULL || cd == NULL)
{
#ifdef USE_IN_LIBIO
if (_IO_fwide (stderr, 0) > 0)
(void) __fwprintf (stderr, L"%s",
_("svc_tcp: makefd_xprt: out of memory\n"));
else
#endif
(void) fputs (_("svc_tcp: makefd_xprt: out of memory\n"), stderr);
mem_free (xprt, sizeof (SVCXPRT));
mem_free (cd, sizeof (struct tcp_conn));
return NULL;
}
cd->strm_stat = XPRT_IDLE;
xdrrec_create (&(cd->xdrs), sendsize, recvsize,
(caddr_t) xprt, readtcp, writetcp);
xprt->xp_p2 = NULL;
xprt->xp_p1 = (caddr_t) cd;
xprt->xp_verf.oa_base = cd->verf_body;
xprt->xp_addrlen = 0;
xprt->xp_ops = &svctcp_op; /* truly deals with calls */
xprt->xp_port = 0; /* this is a connection, not a rendezvouser */
xprt->xp_sock = fd;
xprt_register (xprt);
return xprt;
}
 
static bool_t
rendezvous_request (SVCXPRT *xprt, struct rpc_msg *errmsg)
{
int sock;
struct tcp_rendezvous *r;
struct sockaddr_in addr;
socklen_t len;
 
r = (struct tcp_rendezvous *) xprt->xp_p1;
again:
len = sizeof (struct sockaddr_in);
if ((sock = accept (xprt->xp_sock, (struct sockaddr *) &addr, &len)) < 0)
{
if (errno == EINTR)
goto again;
return FALSE;
}
/*
* make a new transporter (re-uses xprt)
*/
xprt = makefd_xprt (sock, r->sendsize, r->recvsize);
memcpy (&xprt->xp_raddr, &addr, sizeof (addr));
xprt->xp_addrlen = len;
return FALSE; /* there is never an rpc msg to be processed */
}
 
static enum xprt_stat
rendezvous_stat (SVCXPRT *xprt)
{
return XPRT_IDLE;
}
 
static void
svctcp_destroy (SVCXPRT *xprt)
{
struct tcp_conn *cd = (struct tcp_conn *) xprt->xp_p1;
 
xprt_unregister (xprt);
(void) close (xprt->xp_sock);
if (xprt->xp_port != 0)
{
/* a rendezvouser socket */
xprt->xp_port = 0;
}
else
{
/* an actual connection socket */
XDR_DESTROY (&(cd->xdrs));
}
mem_free ((caddr_t) cd, sizeof (struct tcp_conn));
mem_free ((caddr_t) xprt, sizeof (SVCXPRT));
}
 
 
/*
* reads data from the tcp connection.
* any error is fatal and the connection is closed.
* (And a read of zero bytes is a half closed stream => error.)
*/
static int
readtcp (char *xprtptr, char *buf, int len)
{
SVCXPRT *xprt = (SVCXPRT *)xprtptr;
int sock = xprt->xp_sock;
int milliseconds = 35 * 1000;
struct pollfd pollfd;
 
do
{
pollfd.fd = sock;
pollfd.events = POLLIN;
switch (poll (&pollfd, 1, milliseconds))
{
case -1:
if (errno == EINTR)
continue;
/*FALLTHROUGH*/
case 0:
goto fatal_err;
default:
if ((pollfd.revents & POLLERR) || (pollfd.revents & POLLHUP)
|| (pollfd.revents & POLLNVAL))
goto fatal_err;
break;
}
}
while ((pollfd.revents & POLLIN) == 0);
 
if ((len = read (sock, buf, len)) > 0)
return len;
 
fatal_err:
((struct tcp_conn *) (xprt->xp_p1))->strm_stat = XPRT_DIED;
return -1;
}
 
/*
* writes data to the tcp connection.
* Any error is fatal and the connection is closed.
*/
static int
writetcp (char *xprtptr, char * buf, int len)
{
SVCXPRT *xprt = (SVCXPRT *)xprtptr;
int i, cnt;
 
for (cnt = len; cnt > 0; cnt -= i, buf += i)
{
if ((i = write (xprt->xp_sock, buf, cnt)) < 0)
{
((struct tcp_conn *) (xprt->xp_p1))->strm_stat = XPRT_DIED;
return -1;
}
}
return len;
}
 
static enum xprt_stat
svctcp_stat (SVCXPRT *xprt)
{
struct tcp_conn *cd =
(struct tcp_conn *) (xprt->xp_p1);
 
if (cd->strm_stat == XPRT_DIED)
return XPRT_DIED;
if (!xdrrec_eof (&(cd->xdrs)))
return XPRT_MOREREQS;
return XPRT_IDLE;
}
 
static bool_t
svctcp_recv (SVCXPRT *xprt, struct rpc_msg *msg)
{
struct tcp_conn *cd = (struct tcp_conn *) (xprt->xp_p1);
XDR *xdrs = &(cd->xdrs);
 
xdrs->x_op = XDR_DECODE;
(void) xdrrec_skiprecord (xdrs);
if (xdr_callmsg (xdrs, msg))
{
cd->x_id = msg->rm_xid;
return TRUE;
}
cd->strm_stat = XPRT_DIED; /* XXXX */
return FALSE;
}
 
static bool_t
svctcp_getargs (SVCXPRT *xprt, xdrproc_t xdr_args, caddr_t args_ptr)
{
return ((*xdr_args) (&(((struct tcp_conn *)
(xprt->xp_p1))->xdrs), args_ptr));
}
 
static bool_t
svctcp_freeargs (SVCXPRT *xprt, xdrproc_t xdr_args, caddr_t args_ptr)
{
XDR *xdrs = &(((struct tcp_conn *) (xprt->xp_p1))->xdrs);
 
xdrs->x_op = XDR_FREE;
return ((*xdr_args) (xdrs, args_ptr));
}
 
static bool_t
svctcp_reply (SVCXPRT *xprt, struct rpc_msg *msg)
{
struct tcp_conn *cd = (struct tcp_conn *) (xprt->xp_p1);
XDR *xdrs = &(cd->xdrs);
bool_t stat;
 
xdrs->x_op = XDR_ENCODE;
msg->rm_xid = cd->x_id;
stat = xdr_replymsg (xdrs, msg);
(void) xdrrec_endofrecord (xdrs, TRUE);
return stat;
}
/rpc/pmap_getport.c
0,0 → 1,94
/* @(#)pmap_getport.c 2.2 88/08/01 4.0 RPCSRC */
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
* media and as a part of the software program in whole or part. Users
* may copy or modify Sun RPC without charge, but are not authorized
* to license or distribute it to anyone else except as part of a product or
* program developed by the user.
*
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun RPC is provided with no support and without any obligation on the
* part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
#if 0
static char sccsid[] = "@(#)pmap_getport.c 1.9 87/08/11 Copyr 1984 Sun Micro";
#endif
 
/*
* pmap_getport.c
* Client interface to pmap rpc service.
*
* Copyright (C) 1984, Sun Microsystems, Inc.
*/
 
#include <rpc/rpc.h>
#include <rpc/pmap_prot.h>
#include <rpc/pmap_clnt.h>
#include <sys/socket.h>
 
static const struct timeval timeout =
{5, 0};
static const struct timeval tottimeout =
{60, 0};
 
/*
* Find the mapped port for program,version.
* Calls the pmap service remotely to do the lookup.
* Returns 0 if no map exists.
*/
u_short
pmap_getport (address, program, version, protocol)
struct sockaddr_in *address;
u_long program;
u_long version;
u_int protocol;
{
u_short port = 0;
int socket = -1;
CLIENT *client;
struct pmap parms;
 
address->sin_port = htons (PMAPPORT);
client = clntudp_bufcreate (address, PMAPPROG,
PMAPVERS, timeout, &socket, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE);
if (client != (CLIENT *) NULL)
{
struct rpc_createerr *ce = &get_rpc_createerr ();
parms.pm_prog = program;
parms.pm_vers = version;
parms.pm_prot = protocol;
parms.pm_port = 0; /* not needed or used */
if (CLNT_CALL (client, PMAPPROC_GETPORT, (xdrproc_t)xdr_pmap,
(caddr_t)&parms, (xdrproc_t)xdr_u_short,
(caddr_t)&port, tottimeout) != RPC_SUCCESS)
{
ce->cf_stat = RPC_PMAPFAILURE;
clnt_geterr (client, &ce->cf_error);
}
else if (port == 0)
{
ce->cf_stat = RPC_PROGNOTREGISTERED;
}
CLNT_DESTROY (client);
}
/* (void)close(socket); CLNT_DESTROY already closed it */
address->sin_port = 0;
return port;
}
/rpc/auth_unix.c
0,0 → 1,325
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
* media and as a part of the software program in whole or part. Users
* may copy or modify Sun RPC without charge, but are not authorized
* to license or distribute it to anyone else except as part of a product or
* program developed by the user.
*
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun RPC is provided with no support and without any obligation on the
* part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
/*
* Copyright (C) 1984, Sun Microsystems, Inc.
*/
/*
* auth_unix.c, Implements UNIX style authentication parameters.
*
* The system is very weak. The client uses no encryption for it's
* credentials and only sends null verifiers. The server sends backs
* null verifiers or optionally a verifier that suggests a new short hand
* for the credentials.
*/
 
#define __FORCE_GLIBC
#include <features.h>
 
#include <limits.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/param.h>
 
#include <rpc/types.h>
#include <rpc/xdr.h>
#include <rpc/auth.h>
#include <rpc/auth_unix.h>
 
#ifdef USE_IN_LIBIO
# include <wchar.h>
#endif
 
/*
* Unix authenticator operations vector
*/
static void authunix_nextverf (AUTH *);
static bool_t authunix_marshal (AUTH *, XDR *);
static bool_t authunix_validate (AUTH *, struct opaque_auth *);
static bool_t authunix_refresh (AUTH *);
static void authunix_destroy (AUTH *);
 
static struct auth_ops auth_unix_ops = {
authunix_nextverf,
authunix_marshal,
authunix_validate,
authunix_refresh,
authunix_destroy
};
 
/*
* This struct is pointed to by the ah_private field of an auth_handle.
*/
struct audata {
struct opaque_auth au_origcred; /* original credentials */
struct opaque_auth au_shcred; /* short hand cred */
u_long au_shfaults; /* short hand cache faults */
char au_marshed[MAX_AUTH_BYTES];
u_int au_mpos; /* xdr pos at end of marshed */
};
#define AUTH_PRIVATE(auth) ((struct audata *)auth->ah_private)
 
static bool_t marshal_new_auth (AUTH *) internal_function;
 
 
/*
* Create a unix style authenticator.
* Returns an auth handle with the given stuff in it.
*/
AUTH *
authunix_create (char *machname, uid_t uid, gid_t gid, int len,
gid_t *aup_gids)
{
struct authunix_parms aup;
char mymem[MAX_AUTH_BYTES];
struct timeval now;
XDR xdrs;
AUTH *auth;
struct audata *au;
 
/*
* Allocate and set up auth handle
*/
auth = (AUTH *) mem_alloc (sizeof (*auth));
au = (struct audata *) mem_alloc (sizeof (*au));
if (auth == NULL || au == NULL)
{
no_memory:
#ifdef USE_IN_LIBIO
if (_IO_fwide (stderr, 0) > 0)
(void) __fwprintf (stderr, L"%s",
_("authunix_create: out of memory\n"));
else
#endif
(void) fputs (_("authunix_create: out of memory\n"), stderr);
mem_free (auth, sizeof (*auth));
mem_free (au, sizeof (*au));
return NULL;
}
auth->ah_ops = &auth_unix_ops;
auth->ah_private = (caddr_t) au;
auth->ah_verf = au->au_shcred = _null_auth;
au->au_shfaults = 0;
 
/*
* fill in param struct from the given params
*/
(void) gettimeofday (&now, (struct timezone *) 0);
aup.aup_time = now.tv_sec;
aup.aup_machname = machname;
aup.aup_uid = uid;
aup.aup_gid = gid;
aup.aup_len = (u_int) len;
aup.aup_gids = aup_gids;
 
/*
* Serialize the parameters into origcred
*/
xdrmem_create (&xdrs, mymem, MAX_AUTH_BYTES, XDR_ENCODE);
if (!xdr_authunix_parms (&xdrs, &aup))
abort ();
au->au_origcred.oa_length = len = XDR_GETPOS (&xdrs);
au->au_origcred.oa_flavor = AUTH_UNIX;
au->au_origcred.oa_base = mem_alloc ((u_int) len);
if (au->au_origcred.oa_base == NULL)
goto no_memory;
memcpy(au->au_origcred.oa_base, mymem, (u_int) len);
 
/*
* set auth handle to reflect new cred.
*/
auth->ah_cred = au->au_origcred;
marshal_new_auth (auth);
return auth;
}
 
/*
* Returns an auth handle with parameters determined by doing lots of
* syscalls.
*/
AUTH *
authunix_create_default (void)
{
int len;
char machname[MAX_MACHINE_NAME + 1];
uid_t uid;
gid_t gid;
int max_nr_groups = sysconf (_SC_NGROUPS_MAX);
gid_t gids[max_nr_groups];
 
if (gethostname (machname, MAX_MACHINE_NAME) == -1)
abort ();
machname[MAX_MACHINE_NAME] = 0;
uid = geteuid ();
gid = getegid ();
 
if ((len = getgroups (max_nr_groups, gids)) < 0)
abort ();
/* This braindamaged Sun code forces us here to truncate the
list of groups to NGRPS members since the code in
authuxprot.c transforms a fixed array. Grrr. */
return authunix_create (machname, uid, gid, MIN (NGRPS, len), gids);
}
 
/*
* authunix operations
*/
 
static void
authunix_nextverf (AUTH *auth)
{
/* no action necessary */
}
 
static bool_t
authunix_marshal (AUTH *auth, XDR *xdrs)
{
struct audata *au = AUTH_PRIVATE (auth);
 
return XDR_PUTBYTES (xdrs, au->au_marshed, au->au_mpos);
}
 
static bool_t
authunix_validate (AUTH *auth, struct opaque_auth *verf)
{
struct audata *au;
XDR xdrs;
 
if (verf->oa_flavor == AUTH_SHORT)
{
au = AUTH_PRIVATE (auth);
xdrmem_create (&xdrs, verf->oa_base, verf->oa_length,
XDR_DECODE);
 
if (au->au_shcred.oa_base != NULL)
{
mem_free (au->au_shcred.oa_base,
au->au_shcred.oa_length);
au->au_shcred.oa_base = NULL;
}
if (xdr_opaque_auth (&xdrs, &au->au_shcred))
{
auth->ah_cred = au->au_shcred;
}
else
{
xdrs.x_op = XDR_FREE;
(void) xdr_opaque_auth (&xdrs, &au->au_shcred);
au->au_shcred.oa_base = NULL;
auth->ah_cred = au->au_origcred;
}
marshal_new_auth (auth);
}
return TRUE;
}
 
static bool_t
authunix_refresh (AUTH *auth)
{
struct audata *au = AUTH_PRIVATE (auth);
struct authunix_parms aup;
struct timeval now;
XDR xdrs;
int stat;
 
if (auth->ah_cred.oa_base == au->au_origcred.oa_base)
{
/* there is no hope. Punt */
return FALSE;
}
au->au_shfaults++;
 
/* first deserialize the creds back into a struct authunix_parms */
aup.aup_machname = NULL;
aup.aup_gids = (gid_t *) NULL;
xdrmem_create (&xdrs, au->au_origcred.oa_base,
au->au_origcred.oa_length, XDR_DECODE);
stat = xdr_authunix_parms (&xdrs, &aup);
if (!stat)
goto done;
 
/* update the time and serialize in place */
(void) gettimeofday (&now, (struct timezone *) 0);
aup.aup_time = now.tv_sec;
xdrs.x_op = XDR_ENCODE;
XDR_SETPOS (&xdrs, 0);
stat = xdr_authunix_parms (&xdrs, &aup);
if (!stat)
goto done;
auth->ah_cred = au->au_origcred;
marshal_new_auth (auth);
done:
/* free the struct authunix_parms created by deserializing */
xdrs.x_op = XDR_FREE;
(void) xdr_authunix_parms (&xdrs, &aup);
XDR_DESTROY (&xdrs);
return stat;
}
 
static void
authunix_destroy (AUTH *auth)
{
struct audata *au = AUTH_PRIVATE (auth);
 
mem_free (au->au_origcred.oa_base, au->au_origcred.oa_length);
 
if (au->au_shcred.oa_base != NULL)
mem_free (au->au_shcred.oa_base, au->au_shcred.oa_length);
 
mem_free (auth->ah_private, sizeof (struct audata));
 
if (auth->ah_verf.oa_base != NULL)
mem_free (auth->ah_verf.oa_base, auth->ah_verf.oa_length);
 
mem_free ((caddr_t) auth, sizeof (*auth));
}
 
/*
* Marshals (pre-serializes) an auth struct.
* sets private data, au_marshed and au_mpos
*/
static bool_t
internal_function
marshal_new_auth (AUTH *auth)
{
XDR xdr_stream;
XDR *xdrs = &xdr_stream;
struct audata *au = AUTH_PRIVATE (auth);
 
xdrmem_create (xdrs, au->au_marshed, MAX_AUTH_BYTES, XDR_ENCODE);
if ((!xdr_opaque_auth (xdrs, &(auth->ah_cred))) ||
(!xdr_opaque_auth (xdrs, &(auth->ah_verf))))
perror (_("auth_none.c - Fatal marshalling problem"));
else
au->au_mpos = XDR_GETPOS (xdrs);
 
XDR_DESTROY (xdrs);
 
return TRUE;
}
/rpc/svc_raw.c
0,0 → 1,167
/* @(#)svc_raw.c 2.1 88/07/29 4.0 RPCSRC */
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
* media and as a part of the software program in whole or part. Users
* may copy or modify Sun RPC without charge, but are not authorized
* to license or distribute it to anyone else except as part of a product or
* program developed by the user.
*
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun RPC is provided with no support and without any obligation on the
* part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
#if 0
static char sccsid[] = "@(#)svc_raw.c 1.15 87/08/11 Copyr 1984 Sun Micro";
#endif
 
/*
* svc_raw.c, This a toy for simple testing and timing.
* Interface to create an rpc client and server in the same UNIX process.
* This lets us simulate rpc and get rpc (round trip) overhead, without
* any interference from the kernel.
*
* Copyright (C) 1984, Sun Microsystems, Inc.
*/
 
#define __FORCE_GLIBC
#include <features.h>
#include "rpc_private.h"
#include <rpc/svc.h>
 
/*
* This is the "network" that we will be moving data over
*/
struct svcraw_private_s
{
char _raw_buf[UDPMSGSIZE];
SVCXPRT server;
XDR xdr_stream;
char verf_body[MAX_AUTH_BYTES];
};
#ifdef __UCLIBC_HAS_THREADS__
#define svcraw_private ((struct svcraw_private_s *)RPC_THREAD_VARIABLE(svcraw_private_s))
#else
static struct svcraw_private_s *svcraw_private;
#endif
 
static bool_t svcraw_recv (SVCXPRT *, struct rpc_msg *);
static enum xprt_stat svcraw_stat (SVCXPRT *);
static bool_t svcraw_getargs (SVCXPRT *, xdrproc_t, caddr_t);
static bool_t svcraw_reply (SVCXPRT *, struct rpc_msg *);
static bool_t svcraw_freeargs (SVCXPRT *, xdrproc_t, caddr_t);
static void svcraw_destroy (SVCXPRT *);
 
static struct xp_ops server_ops =
{
svcraw_recv,
svcraw_stat,
svcraw_getargs,
svcraw_reply,
svcraw_freeargs,
svcraw_destroy
};
 
SVCXPRT *
svcraw_create (void)
{
struct svcraw_private_s *srp = svcraw_private;
 
if (srp == 0)
{
srp = (struct svcraw_private_s *) calloc (1, sizeof (*srp));
if (srp == 0)
return NULL;
}
srp->server.xp_sock = 0;
srp->server.xp_port = 0;
srp->server.xp_ops = &server_ops;
srp->server.xp_verf.oa_base = srp->verf_body;
xdrmem_create (&srp->xdr_stream, srp->_raw_buf, UDPMSGSIZE, XDR_FREE);
return &srp->server;
}
 
static enum xprt_stat
svcraw_stat (SVCXPRT *xprt)
{
return XPRT_IDLE;
}
 
static bool_t
svcraw_recv (xprt, msg)
SVCXPRT *xprt;
struct rpc_msg *msg;
{
struct svcraw_private_s *srp = svcraw_private;
XDR *xdrs;
 
if (srp == 0)
return FALSE;
xdrs = &srp->xdr_stream;
xdrs->x_op = XDR_DECODE;
XDR_SETPOS (xdrs, 0);
if (!xdr_callmsg (xdrs, msg))
return FALSE;
return TRUE;
}
 
static bool_t
svcraw_reply (SVCXPRT *xprt, struct rpc_msg *msg)
{
struct svcraw_private_s *srp = svcraw_private;
XDR *xdrs;
 
if (srp == 0)
return FALSE;
xdrs = &srp->xdr_stream;
xdrs->x_op = XDR_ENCODE;
XDR_SETPOS (xdrs, 0);
if (!xdr_replymsg (xdrs, msg))
return FALSE;
(void) XDR_GETPOS (xdrs); /* called just for overhead */
return TRUE;
}
 
static bool_t
svcraw_getargs (SVCXPRT *xprt, xdrproc_t xdr_args, caddr_t args_ptr)
{
struct svcraw_private_s *srp = svcraw_private;
 
if (srp == 0)
return FALSE;
return (*xdr_args) (&srp->xdr_stream, args_ptr);
}
 
static bool_t
svcraw_freeargs (SVCXPRT *xprt, xdrproc_t xdr_args, caddr_t args_ptr)
{
struct svcraw_private_s *srp = svcraw_private;
XDR *xdrs;
 
if (srp == 0)
return FALSE;
xdrs = &srp->xdr_stream;
xdrs->x_op = XDR_FREE;
return (*xdr_args) (xdrs, args_ptr);
}
 
static void
svcraw_destroy (SVCXPRT *xprt)
{
}
/rpc/svc_simple.c
0,0 → 1,194
/* @(#)svc_simple.c 2.2 88/08/01 4.0 RPCSRC */
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
* media and as a part of the software program in whole or part. Users
* may copy or modify Sun RPC without charge, but are not authorized
* to license or distribute it to anyone else except as part of a product or
* program developed by the user.
*
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun RPC is provided with no support and without any obligation on the
* part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
#if 0
static char sccsid[] = "@(#)svc_simple.c 1.18 87/08/11 Copyr 1984 Sun Micro";
#endif
 
/*
* svc_simple.c
* Simplified front end to rpc.
*
* Copyright (C) 1984, Sun Microsystems, Inc.
*/
#define __FORCE_GLIBC
#define _GNU_SOURCE
#include <features.h>
 
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "rpc_private.h"
#include <rpc/pmap_clnt.h>
#include <sys/socket.h>
#include <netdb.h>
 
#ifdef USE_IN_LIBIO
# include <wchar.h>
# include <libio/iolibio.h>
# define fputs(s, f) _IO_fputs (s, f)
#endif
 
struct proglst_
{
char *(*p_progname) (char *);
int p_prognum;
int p_procnum;
xdrproc_t p_inproc, p_outproc;
struct proglst_ *p_nxt;
};
#ifdef __UCLIBC_HAS_THREADS__
#define proglst ((struct proglst_ *)RPC_THREAD_VARIABLE(svcsimple_proglst_s))
#else
static struct proglst_ *proglst;
#endif
 
 
static void universal (struct svc_req *rqstp, SVCXPRT *transp_s);
#ifdef __UCLIBC_HAS_THREADS__
#define transp ((SVCXPRT *)RPC_THREAD_VARIABLE(svcsimple_transp_s))
#else
static SVCXPRT *transp;
#endif
 
int
registerrpc (u_long prognum, u_long versnum, u_long procnum,
char *(*progname) (char *), xdrproc_t inproc, xdrproc_t outproc)
{
struct proglst_ *pl;
char *buf;
 
if (procnum == NULLPROC)
{
 
(void) asprintf (&buf, _("can't reassign procedure number %ld\n"),
NULLPROC);
goto err_out;
}
if (transp == 0)
{
transp = svcudp_create (RPC_ANYSOCK);
if (transp == NULL)
{
buf = strdup (_("couldn't create an rpc server\n"));
goto err_out;
}
}
(void) pmap_unset ((u_long) prognum, (u_long) versnum);
if (!svc_register (transp, (u_long) prognum, (u_long) versnum,
universal, IPPROTO_UDP))
{
(void) asprintf (&buf, _("couldn't register prog %ld vers %ld\n"),
prognum, versnum);
goto err_out;
}
pl = (struct proglst_ *) malloc (sizeof (struct proglst_));
if (pl == NULL)
{
buf = strdup (_("registerrpc: out of memory\n"));
goto err_out;
}
pl->p_progname = progname;
pl->p_prognum = prognum;
pl->p_procnum = procnum;
pl->p_inproc = inproc;
pl->p_outproc = outproc;
pl->p_nxt = proglst;
proglst = pl;
return 0;
 
err_out:
#ifdef USE_IN_LIBIO
if (_IO_fwide (stderr, 0) > 0)
(void) __fwprintf (stderr, L"%s", buf);
else
#endif
(void) fputs (buf, stderr);
free (buf);
return -1;
}
 
static void
universal (struct svc_req *rqstp, SVCXPRT *transp_l)
{
int prog, proc;
char *outdata;
char xdrbuf[UDPMSGSIZE];
struct proglst_ *pl;
char *buf = NULL;
 
/*
* enforce "procnum 0 is echo" convention
*/
if (rqstp->rq_proc == NULLPROC)
{
if (svc_sendreply (transp_l, (xdrproc_t)xdr_void, (char *) NULL) == FALSE)
{
write (STDERR_FILENO, "xxx\n", 4);
exit (1);
}
return;
}
prog = rqstp->rq_prog;
proc = rqstp->rq_proc;
for (pl = proglst; pl != NULL; pl = pl->p_nxt)
if (pl->p_prognum == prog && pl->p_procnum == proc)
{
/* decode arguments into a CLEAN buffer */
bzero (xdrbuf, sizeof (xdrbuf)); /* required ! */
if (!svc_getargs (transp_l, pl->p_inproc, xdrbuf))
{
svcerr_decode (transp_l);
return;
}
outdata = (*(pl->p_progname)) (xdrbuf);
if (outdata == NULL && pl->p_outproc != (xdrproc_t)xdr_void)
/* there was an error */
return;
if (!svc_sendreply (transp_l, pl->p_outproc, outdata))
{
(void) asprintf (&buf,
_("trouble replying to prog %d\n"),
pl->p_prognum);
exit (1);
}
/* free the decoded arguments */
(void) svc_freeargs (transp_l, pl->p_inproc, xdrbuf);
return;
}
(void) asprintf (&buf, _("never registered prog %d\n"), prog);
#ifdef USE_IN_LIBIO
if (_IO_fwide (stderr, 0) > 0)
__fwprintf (stderr, L"%s", buf);
else
#endif
fputs (buf, stderr);
free (buf);
exit (1);
}
/rpc/clnt_tcp.c
0,0 → 1,540
/* @(#)clnt_tcp.c 2.2 88/08/01 4.0 RPCSRC */
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
* media and as a part of the software program in whole or part. Users
* may copy or modify Sun RPC without charge, but are not authorized
* to license or distribute it to anyone else except as part of a product or
* program developed by the user.
*
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun RPC is provided with no support and without any obligation on the
* part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
#if 0
static char sccsid[] = "@(#)clnt_tcp.c 1.37 87/10/05 Copyr 1984 Sun Micro";
#endif
 
/*
* clnt_tcp.c, Implements a TCP/IP based, client side RPC.
*
* Copyright (C) 1984, Sun Microsystems, Inc.
*
* TCP based RPC supports 'batched calls'.
* A sequence of calls may be batched-up in a send buffer. The rpc call
* return immediately to the client even though the call was not necessarily
* sent. The batching occurs if the results' xdr routine is NULL (0) AND
* the rpc timeout value is zero (see clnt.h, rpc).
*
* Clients should NOT casually batch calls that in fact return results; that is,
* the server side should be aware that a call is batched and not produce any
* return message. Batched calls that produce many result messages can
* deadlock (netlock) the client and the server....
*
* Now go hang yourself.
*/
 
#define __FORCE_GLIBC
#include <features.h>
 
#include <netdb.h>
#include <errno.h>
#include <stdio.h>
#include <unistd.h>
#include <rpc/rpc.h>
#include <sys/poll.h>
#include <sys/socket.h>
#include <rpc/pmap_clnt.h>
#ifdef USE_IN_LIBIO
# include <wchar.h>
#endif
 
extern u_long _create_xid (void);
 
#define MCALL_MSG_SIZE 24
 
struct ct_data
{
int ct_sock;
bool_t ct_closeit;
struct timeval ct_wait;
bool_t ct_waitset; /* wait set by clnt_control? */
struct sockaddr_in ct_addr;
struct rpc_err ct_error;
char ct_mcall[MCALL_MSG_SIZE]; /* marshalled callmsg */
u_int ct_mpos; /* pos after marshal */
XDR ct_xdrs;
};
 
static int readtcp (char *, char *, int);
static int writetcp (char *, char *, int);
 
static enum clnt_stat clnttcp_call (CLIENT *, u_long, xdrproc_t, caddr_t,
xdrproc_t, caddr_t, struct timeval);
static void clnttcp_abort (void);
static void clnttcp_geterr (CLIENT *, struct rpc_err *);
static bool_t clnttcp_freeres (CLIENT *, xdrproc_t, caddr_t);
static bool_t clnttcp_control (CLIENT *, int, char *);
static void clnttcp_destroy (CLIENT *);
 
static struct clnt_ops tcp_ops =
{
clnttcp_call,
clnttcp_abort,
clnttcp_geterr,
clnttcp_freeres,
clnttcp_destroy,
clnttcp_control
};
 
/*
* Create a client handle for a tcp/ip connection.
* If *sockp<0, *sockp is set to a newly created TCP socket and it is
* connected to raddr. If *sockp non-negative then
* raddr is ignored. The rpc/tcp package does buffering
* similar to stdio, so the client must pick send and receive buffer sizes,];
* 0 => use the default.
* If raddr->sin_port is 0, then a binder on the remote machine is
* consulted for the right port number.
* NB: *sockp is copied into a private area.
* NB: It is the clients responsibility to close *sockp.
* NB: The rpch->cl_auth is set null authentication. Caller may wish to set this
* something more useful.
*/
CLIENT *
clnttcp_create (struct sockaddr_in *raddr, u_long prog, u_long vers,
int *sockp, u_int sendsz, u_int recvsz)
{
CLIENT *h;
struct ct_data *ct;
struct rpc_msg call_msg;
 
h = (CLIENT *) mem_alloc (sizeof (*h));
ct = (struct ct_data *) mem_alloc (sizeof (*ct));
if (h == NULL || ct == NULL)
{
struct rpc_createerr *ce = &get_rpc_createerr ();
#ifdef USE_IN_LIBIO
if (_IO_fwide (stderr, 0) > 0)
(void) __fwprintf (stderr, L"%s",
_("clnttcp_create: out of memory\n"));
else
#endif
(void) fputs (_("clnttcp_create: out of memory\n"), stderr);
ce->cf_stat = RPC_SYSTEMERROR;
ce->cf_error.re_errno = ENOMEM;
goto fooy;
}
 
/*
* If no port number given ask the pmap for one
*/
if (raddr->sin_port == 0)
{
u_short port;
if ((port = pmap_getport (raddr, prog, vers, IPPROTO_TCP)) == 0)
{
mem_free ((caddr_t) ct, sizeof (struct ct_data));
mem_free ((caddr_t) h, sizeof (CLIENT));
return ((CLIENT *) NULL);
}
raddr->sin_port = htons (port);
}
 
/*
* If no socket given, open one
*/
if (*sockp < 0)
{
*sockp = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
(void) bindresvport (*sockp, (struct sockaddr_in *) 0);
if ((*sockp < 0)
|| (connect (*sockp, (struct sockaddr *) raddr,
sizeof (*raddr)) < 0))
{
struct rpc_createerr *ce = &get_rpc_createerr ();
ce->cf_stat = RPC_SYSTEMERROR;
ce->cf_error.re_errno = errno;
if (*sockp >= 0)
(void) close (*sockp);
goto fooy;
}
ct->ct_closeit = TRUE;
}
else
{
ct->ct_closeit = FALSE;
}
 
/*
* Set up private data struct
*/
ct->ct_sock = *sockp;
ct->ct_wait.tv_usec = 0;
ct->ct_waitset = FALSE;
ct->ct_addr = *raddr;
 
/*
* Initialize call message
*/
call_msg.rm_xid = _create_xid ();
call_msg.rm_direction = CALL;
call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
call_msg.rm_call.cb_prog = prog;
call_msg.rm_call.cb_vers = vers;
 
/*
* pre-serialize the static part of the call msg and stash it away
*/
xdrmem_create (&(ct->ct_xdrs), ct->ct_mcall, MCALL_MSG_SIZE,
XDR_ENCODE);
if (!xdr_callhdr (&(ct->ct_xdrs), &call_msg))
{
if (ct->ct_closeit)
{
(void) close (*sockp);
}
goto fooy;
}
ct->ct_mpos = XDR_GETPOS (&(ct->ct_xdrs));
XDR_DESTROY (&(ct->ct_xdrs));
 
/*
* Create a client handle which uses xdrrec for serialization
* and authnone for authentication.
*/
xdrrec_create (&(ct->ct_xdrs), sendsz, recvsz,
(caddr_t) ct, readtcp, writetcp);
h->cl_ops = &tcp_ops;
h->cl_private = (caddr_t) ct;
h->cl_auth = authnone_create ();
return h;
 
fooy:
/*
* Something goofed, free stuff and barf
*/
mem_free ((caddr_t) ct, sizeof (struct ct_data));
mem_free ((caddr_t) h, sizeof (CLIENT));
return ((CLIENT *) NULL);
}
 
static enum clnt_stat
clnttcp_call (h, proc, xdr_args, args_ptr, xdr_results, results_ptr, timeout)
CLIENT *h;
u_long proc;
xdrproc_t xdr_args;
caddr_t args_ptr;
xdrproc_t xdr_results;
caddr_t results_ptr;
struct timeval timeout;
{
struct ct_data *ct = (struct ct_data *) h->cl_private;
XDR *xdrs = &(ct->ct_xdrs);
struct rpc_msg reply_msg;
u_long x_id;
u_int32_t *msg_x_id = (u_int32_t *) (ct->ct_mcall); /* yuk */
bool_t shipnow;
int refreshes = 2;
 
if (!ct->ct_waitset)
{
ct->ct_wait = timeout;
}
 
shipnow =
(xdr_results == (xdrproc_t) 0 && ct->ct_wait.tv_sec == 0
&& ct->ct_wait.tv_usec == 0) ? FALSE : TRUE;
 
call_again:
xdrs->x_op = XDR_ENCODE;
ct->ct_error.re_status = RPC_SUCCESS;
x_id = ntohl (--(*msg_x_id));
if ((!XDR_PUTBYTES (xdrs, ct->ct_mcall, ct->ct_mpos)) ||
(!XDR_PUTLONG (xdrs, (long *) &proc)) ||
(!AUTH_MARSHALL (h->cl_auth, xdrs)) ||
(!(*xdr_args) (xdrs, args_ptr)))
{
if (ct->ct_error.re_status == RPC_SUCCESS)
ct->ct_error.re_status = RPC_CANTENCODEARGS;
(void) xdrrec_endofrecord (xdrs, TRUE);
return (ct->ct_error.re_status);
}
if (!xdrrec_endofrecord (xdrs, shipnow))
return ct->ct_error.re_status = RPC_CANTSEND;
if (!shipnow)
return RPC_SUCCESS;
/*
* Hack to provide rpc-based message passing
*/
if (ct->ct_wait.tv_sec == 0 && ct->ct_wait.tv_usec == 0)
{
return ct->ct_error.re_status = RPC_TIMEDOUT;
}
 
 
/*
* Keep receiving until we get a valid transaction id
*/
xdrs->x_op = XDR_DECODE;
while (TRUE)
{
reply_msg.acpted_rply.ar_verf = _null_auth;
reply_msg.acpted_rply.ar_results.where = NULL;
reply_msg.acpted_rply.ar_results.proc = (xdrproc_t)xdr_void;
if (!xdrrec_skiprecord (xdrs))
return (ct->ct_error.re_status);
/* now decode and validate the response header */
if (!xdr_replymsg (xdrs, &reply_msg))
{
if (ct->ct_error.re_status == RPC_SUCCESS)
continue;
return ct->ct_error.re_status;
}
if ((u_int32_t) reply_msg.rm_xid == (u_int32_t) x_id)
break;
}
 
/*
* process header
*/
_seterr_reply (&reply_msg, &(ct->ct_error));
if (ct->ct_error.re_status == RPC_SUCCESS)
{
if (!AUTH_VALIDATE (h->cl_auth, &reply_msg.acpted_rply.ar_verf))
{
ct->ct_error.re_status = RPC_AUTHERROR;
ct->ct_error.re_why = AUTH_INVALIDRESP;
}
else if (!(*xdr_results) (xdrs, results_ptr))
{
if (ct->ct_error.re_status == RPC_SUCCESS)
ct->ct_error.re_status = RPC_CANTDECODERES;
}
/* free verifier ... */
if (reply_msg.acpted_rply.ar_verf.oa_base != NULL)
{
xdrs->x_op = XDR_FREE;
(void) xdr_opaque_auth (xdrs, &(reply_msg.acpted_rply.ar_verf));
}
} /* end successful completion */
else
{
/* maybe our credentials need to be refreshed ... */
if (refreshes-- && AUTH_REFRESH (h->cl_auth))
goto call_again;
} /* end of unsuccessful completion */
return ct->ct_error.re_status;
}
 
static void
clnttcp_geterr (h, errp)
CLIENT *h;
struct rpc_err *errp;
{
struct ct_data *ct =
(struct ct_data *) h->cl_private;
 
*errp = ct->ct_error;
}
 
static bool_t
clnttcp_freeres (cl, xdr_res, res_ptr)
CLIENT *cl;
xdrproc_t xdr_res;
caddr_t res_ptr;
{
struct ct_data *ct = (struct ct_data *) cl->cl_private;
XDR *xdrs = &(ct->ct_xdrs);
 
xdrs->x_op = XDR_FREE;
return (*xdr_res) (xdrs, res_ptr);
}
 
static void
clnttcp_abort ()
{
}
 
static bool_t
clnttcp_control (CLIENT *cl, int request, char *info)
{
struct ct_data *ct = (struct ct_data *) cl->cl_private;
 
 
switch (request)
{
case CLSET_FD_CLOSE:
ct->ct_closeit = TRUE;
break;
case CLSET_FD_NCLOSE:
ct->ct_closeit = FALSE;
break;
case CLSET_TIMEOUT:
ct->ct_wait = *(struct timeval *) info;
ct->ct_waitset = TRUE;
break;
case CLGET_TIMEOUT:
*(struct timeval *) info = ct->ct_wait;
break;
case CLGET_SERVER_ADDR:
*(struct sockaddr_in *) info = ct->ct_addr;
break;
case CLGET_FD:
*(int *)info = ct->ct_sock;
break;
case CLGET_XID:
/*
* use the knowledge that xid is the
* first element in the call structure *.
* This will get the xid of the PREVIOUS call
*/
*(u_long *)info = ntohl (*(u_long *)ct->ct_mcall);
break;
case CLSET_XID:
/* This will set the xid of the NEXT call */
*(u_long *)ct->ct_mcall = htonl (*(u_long *)info - 1);
/* decrement by 1 as clnttcp_call() increments once */
case CLGET_VERS:
/*
* This RELIES on the information that, in the call body,
* the version number field is the fifth field from the
* begining of the RPC header. MUST be changed if the
* call_struct is changed
*/
*(u_long *)info = ntohl (*(u_long *)(ct->ct_mcall +
4 * BYTES_PER_XDR_UNIT));
break;
case CLSET_VERS:
*(u_long *)(ct->ct_mcall + 4 * BYTES_PER_XDR_UNIT)
= htonl (*(u_long *)info);
break;
case CLGET_PROG:
/*
* This RELIES on the information that, in the call body,
* the program number field is the field from the
* begining of the RPC header. MUST be changed if the
* call_struct is changed
*/
*(u_long *)info = ntohl(*(u_long *)(ct->ct_mcall +
3 * BYTES_PER_XDR_UNIT));
break;
case CLSET_PROG:
*(u_long *)(ct->ct_mcall + 3 * BYTES_PER_XDR_UNIT)
= htonl(*(u_long *)info);
break;
/* The following are only possible with TI-RPC */
case CLGET_RETRY_TIMEOUT:
case CLSET_RETRY_TIMEOUT:
case CLGET_SVC_ADDR:
case CLSET_SVC_ADDR:
case CLSET_PUSH_TIMOD:
case CLSET_POP_TIMOD:
default:
return FALSE;
}
return TRUE;
}
 
 
static void
clnttcp_destroy (CLIENT *h)
{
struct ct_data *ct =
(struct ct_data *) h->cl_private;
 
if (ct->ct_closeit)
{
(void) close (ct->ct_sock);
}
XDR_DESTROY (&(ct->ct_xdrs));
mem_free ((caddr_t) ct, sizeof (struct ct_data));
mem_free ((caddr_t) h, sizeof (CLIENT));
}
 
/*
* Interface between xdr serializer and tcp connection.
* Behaves like the system calls, read & write, but keeps some error state
* around for the rpc level.
*/
static int
readtcp (char *ctptr, char *buf, int len)
{
struct ct_data *ct = (struct ct_data *)ctptr;
struct pollfd fd;
int milliseconds = (ct->ct_wait.tv_sec * 1000) +
(ct->ct_wait.tv_usec / 1000);
 
if (len == 0)
return 0;
 
fd.fd = ct->ct_sock;
fd.events = POLLIN;
while (TRUE)
{
switch (poll(&fd, 1, milliseconds))
{
case 0:
ct->ct_error.re_status = RPC_TIMEDOUT;
return -1;
 
case -1:
if (errno == EINTR)
continue;
ct->ct_error.re_status = RPC_CANTRECV;
ct->ct_error.re_errno = errno;
return -1;
}
break;
}
switch (len = read (ct->ct_sock, buf, len))
{
 
case 0:
/* premature eof */
ct->ct_error.re_errno = ECONNRESET;
ct->ct_error.re_status = RPC_CANTRECV;
len = -1; /* it's really an error */
break;
 
case -1:
ct->ct_error.re_errno = errno;
ct->ct_error.re_status = RPC_CANTRECV;
break;
}
return len;
}
 
static int
writetcp (char *ctptr, char *buf, int len)
{
int i, cnt;
struct ct_data *ct = (struct ct_data*)ctptr;
 
for (cnt = len; cnt > 0; cnt -= i, buf += i)
{
if ((i = write (ct->ct_sock, buf, cnt)) == -1)
{
ct->ct_error.re_errno = errno;
ct->ct_error.re_status = RPC_CANTSEND;
return -1;
}
}
return len;
}
/rpc/clnt_raw.c
0,0 → 1,255
/* @(#)clnt_raw.c 2.2 88/08/01 4.0 RPCSRC */
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
* media and as a part of the software program in whole or part. Users
* may copy or modify Sun RPC without charge, but are not authorized
* to license or distribute it to anyone else except as part of a product or
* program developed by the user.
*
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun RPC is provided with no support and without any obligation on the
* part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
#if 0
static char sccsid[] = "@(#)clnt_raw.c 1.22 87/08/11 Copyr 1984 Sun Micro";
#endif
 
/*
* clnt_raw.c
*
* Copyright (C) 1984, Sun Microsystems, Inc.
*
* Memory based rpc for simple testing and timing.
* Interface to create an rpc client and server in the same process.
* This lets us simulate rpc and get round trip overhead, without
* any interference from the kernel.
*/
 
#define __FORCE_GLIBC
#include <features.h>
#include "rpc_private.h"
#include <rpc/svc.h>
#include <rpc/xdr.h>
 
#define MCALL_MSG_SIZE 24
 
/*
* This is the "network" we will be moving stuff over.
*/
struct clntraw_private_s
{
CLIENT client_object;
XDR xdr_stream;
char _raw_buf[UDPMSGSIZE];
char mashl_callmsg[MCALL_MSG_SIZE];
u_int mcnt;
};
#ifdef __UCLIBC_HAS_THREADS__
#define clntraw_private ((struct clntraw_private_s *)RPC_THREAD_VARIABLE(clntraw_private_s))
#else
static struct clntraw_private_s *clntraw_private;
#endif
 
static enum clnt_stat clntraw_call (CLIENT *, u_long, xdrproc_t, caddr_t,
xdrproc_t, caddr_t, struct timeval);
static void clntraw_abort (void);
static void clntraw_geterr (CLIENT *, struct rpc_err *);
static bool_t clntraw_freeres (CLIENT *, xdrproc_t, caddr_t);
static bool_t clntraw_control (CLIENT *, int, char *);
static void clntraw_destroy (CLIENT *);
 
static struct clnt_ops client_ops =
{
clntraw_call,
clntraw_abort,
clntraw_geterr,
clntraw_freeres,
clntraw_destroy,
clntraw_control
};
 
/*
* Create a client handle for memory based rpc.
*/
CLIENT *
clntraw_create (u_long prog, u_long vers)
{
struct clntraw_private_s *clp = clntraw_private;
struct rpc_msg call_msg;
XDR *xdrs = &clp->xdr_stream;
CLIENT *client = &clp->client_object;
 
if (clp == 0)
{
clp = (struct clntraw_private_s *) calloc (1, sizeof (*clp));
if (clp == 0)
return (0);
clntraw_private = clp;
}
/*
* pre-serialize the static part of the call msg and stash it away
*/
call_msg.rm_direction = CALL;
call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
call_msg.rm_call.cb_prog = prog;
call_msg.rm_call.cb_vers = vers;
xdrmem_create (xdrs, clp->mashl_callmsg, MCALL_MSG_SIZE, XDR_ENCODE);
if (!xdr_callhdr (xdrs, &call_msg))
{
perror (_ ("clnt_raw.c - Fatal header serialization error."));
}
clp->mcnt = XDR_GETPOS (xdrs);
XDR_DESTROY (xdrs);
 
/*
* Set xdrmem for client/server shared buffer
*/
xdrmem_create (xdrs, clp->_raw_buf, UDPMSGSIZE, XDR_FREE);
 
/*
* create client handle
*/
client->cl_ops = &client_ops;
client->cl_auth = authnone_create ();
return client;
}
 
static enum clnt_stat
clntraw_call (h, proc, xargs, argsp, xresults, resultsp, timeout)
CLIENT *h;
u_long proc;
xdrproc_t xargs;
caddr_t argsp;
xdrproc_t xresults;
caddr_t resultsp;
struct timeval timeout;
{
struct clntraw_private_s *clp = clntraw_private;
XDR *xdrs = &clp->xdr_stream;
struct rpc_msg msg;
enum clnt_stat status;
struct rpc_err error;
 
if (clp == NULL)
return RPC_FAILED;
call_again:
/*
* send request
*/
xdrs->x_op = XDR_ENCODE;
XDR_SETPOS (xdrs, 0);
((struct rpc_msg *) clp->mashl_callmsg)->rm_xid++;
if ((!XDR_PUTBYTES (xdrs, clp->mashl_callmsg, clp->mcnt)) ||
(!XDR_PUTLONG (xdrs, (long *) &proc)) ||
(!AUTH_MARSHALL (h->cl_auth, xdrs)) ||
(!(*xargs) (xdrs, argsp)))
{
return (RPC_CANTENCODEARGS);
}
(void) XDR_GETPOS (xdrs); /* called just to cause overhead */
 
/*
* We have to call server input routine here because this is
* all going on in one process. Yuk.
*/
svc_getreq (1);
 
/*
* get results
*/
xdrs->x_op = XDR_DECODE;
XDR_SETPOS (xdrs, 0);
msg.acpted_rply.ar_verf = _null_auth;
msg.acpted_rply.ar_results.where = resultsp;
msg.acpted_rply.ar_results.proc = xresults;
if (!xdr_replymsg (xdrs, &msg))
return RPC_CANTDECODERES;
_seterr_reply (&msg, &error);
status = error.re_status;
 
if (status == RPC_SUCCESS)
{
if (!AUTH_VALIDATE (h->cl_auth, &msg.acpted_rply.ar_verf))
{
status = RPC_AUTHERROR;
}
} /* end successful completion */
else
{
if (AUTH_REFRESH (h->cl_auth))
goto call_again;
} /* end of unsuccessful completion */
 
if (status == RPC_SUCCESS)
{
if (!AUTH_VALIDATE (h->cl_auth, &msg.acpted_rply.ar_verf))
{
status = RPC_AUTHERROR;
}
if (msg.acpted_rply.ar_verf.oa_base != NULL)
{
xdrs->x_op = XDR_FREE;
(void) xdr_opaque_auth (xdrs, &(msg.acpted_rply.ar_verf));
}
}
 
return status;
}
 
static void
clntraw_geterr (CLIENT *cl, struct rpc_err *err)
{
}
 
 
static bool_t
clntraw_freeres (cl, xdr_res, res_ptr)
CLIENT *cl;
xdrproc_t xdr_res;
caddr_t res_ptr;
{
struct clntraw_private_s *clp = clntraw_private;
XDR *xdrs = &clp->xdr_stream;
bool_t rval;
 
if (clp == NULL)
{
rval = (bool_t) RPC_FAILED;
return rval;
}
xdrs->x_op = XDR_FREE;
return (*xdr_res) (xdrs, res_ptr);
}
 
static void
clntraw_abort (void)
{
}
 
static bool_t
clntraw_control (CLIENT *cl, int i, char *c)
{
return FALSE;
}
 
static void
clntraw_destroy (CLIENT *cl)
{
}
/rpc/xdr_intXX_t.c
0,0 → 1,203
/* Copyright (c) 1998, 1999, 2000 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1998.
 
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
 
#include <rpc/types.h>
#include <rpc/xdr.h>
 
/* XDR 64bit integers */
bool_t
xdr_int64_t (XDR *xdrs, int64_t *ip)
{
int32_t t1;
/* This must be unsigned, otherwise we get problems with sign
extension in the DECODE case. */
uint32_t t2;
 
switch (xdrs->x_op)
{
case XDR_ENCODE:
t1 = (int32_t) ((*ip) >> 32);
t2 = (int32_t) (*ip);
return (XDR_PUTINT32(xdrs, &t1) && XDR_PUTINT32(xdrs, &t2));
case XDR_DECODE:
if (!XDR_GETINT32(xdrs, &t1) || !XDR_GETINT32(xdrs, &t2))
return FALSE;
*ip = ((int64_t) t1) << 32;
*ip |= t2;
return TRUE;
case XDR_FREE:
return TRUE;
default:
return FALSE;
}
}
 
/* XDR 64bit unsigned integers */
bool_t
xdr_uint64_t (XDR *xdrs, uint64_t *uip)
{
uint32_t t1;
uint32_t t2;
 
switch (xdrs->x_op)
{
case XDR_ENCODE:
t1 = (uint32_t) ((*uip) >> 32);
t2 = (uint32_t) (*uip);
return (XDR_PUTINT32 (xdrs, (int32_t *) &t1) &&
XDR_PUTINT32(xdrs, (int32_t *) &t2));
case XDR_DECODE:
if (!XDR_GETINT32(xdrs, (int32_t *) &t1) ||
!XDR_GETINT32(xdrs, (int32_t *) &t2))
return FALSE;
*uip = ((uint64_t) t1) << 32;
*uip |= t2;
return TRUE;
case XDR_FREE:
return TRUE;
default:
return FALSE;
}
}
 
/* XDR 32bit integers */
bool_t
xdr_int32_t (XDR *xdrs, int32_t *lp)
{
switch (xdrs->x_op)
{
case XDR_ENCODE:
return XDR_PUTINT32 (xdrs, lp);
case XDR_DECODE:
return XDR_GETINT32 (xdrs, lp);
case XDR_FREE:
return TRUE;
default:
return FALSE;
}
}
 
/* XDR 32bit unsigned integers */
bool_t
xdr_uint32_t (XDR *xdrs, uint32_t *ulp)
{
switch (xdrs->x_op)
{
case XDR_ENCODE:
return XDR_PUTINT32 (xdrs, (int32_t *) ulp);
case XDR_DECODE:
return XDR_GETINT32 (xdrs, (int32_t *) ulp);
case XDR_FREE:
return TRUE;
default:
return FALSE;
}
}
 
/* XDR 16bit integers */
bool_t
xdr_int16_t (XDR *xdrs, int16_t *ip)
{
int32_t t;
 
switch (xdrs->x_op)
{
case XDR_ENCODE:
t = (int32_t) *ip;
return XDR_PUTINT32 (xdrs, &t);
case XDR_DECODE:
if (!XDR_GETINT32 (xdrs, &t))
return FALSE;
*ip = (int16_t) t;
return TRUE;
case XDR_FREE:
return TRUE;
default:
return FALSE;
}
}
 
/* XDR 16bit unsigned integers */
bool_t
xdr_uint16_t (XDR *xdrs, uint16_t *uip)
{
uint32_t ut;
 
switch (xdrs->x_op)
{
case XDR_ENCODE:
ut = (uint32_t) *uip;
return XDR_PUTINT32 (xdrs, (int32_t *) &ut);
case XDR_DECODE:
if (!XDR_GETINT32 (xdrs, (int32_t *) &ut))
return FALSE;
*uip = (uint16_t) ut;
return TRUE;
case XDR_FREE:
return TRUE;
default:
return FALSE;
}
}
 
/* XDR 8bit integers */
bool_t
xdr_int8_t (XDR *xdrs, int8_t *ip)
{
int32_t t;
 
switch (xdrs->x_op)
{
case XDR_ENCODE:
t = (int32_t) *ip;
return XDR_PUTINT32 (xdrs, &t);
case XDR_DECODE:
if (!XDR_GETINT32 (xdrs, &t))
return FALSE;
*ip = (int8_t) t;
return TRUE;
case XDR_FREE:
return TRUE;
default:
return FALSE;
}
}
 
/* XDR 8bit unsigned integers */
bool_t
xdr_uint8_t (XDR *xdrs, uint8_t *uip)
{
uint32_t ut;
 
switch (xdrs->x_op)
{
case XDR_ENCODE:
ut = (uint32_t) *uip;
return XDR_PUTINT32 (xdrs, (int32_t *) &ut);
case XDR_DECODE:
if (!XDR_GETINT32 (xdrs, (int32_t *) &ut))
return FALSE;
*uip = (uint8_t) ut;
return TRUE;
case XDR_FREE:
return TRUE;
default:
return FALSE;
}
}
/rpc/xdr_reference.c
0,0 → 1,155
/* @(#)xdr_reference.c 2.1 88/07/29 4.0 RPCSRC */
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
* media and as a part of the software program in whole or part. Users
* may copy or modify Sun RPC without charge, but are not authorized
* to license or distribute it to anyone else except as part of a product or
* program developed by the user.
*
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun RPC is provided with no support and without any obligation on the
* part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
#if 0
static char sccsid[] = "@(#)xdr_reference.c 1.11 87/08/11 SMI";
#endif
 
/*
* xdr_reference.c, Generic XDR routines implementation.
*
* Copyright (C) 1987, Sun Microsystems, Inc.
*
* These are the "non-trivial" xdr primitives used to serialize and de-serialize
* "pointers". See xdr.h for more info on the interface to xdr.
*/
 
#define __FORCE_GLIBC
#define _GNU_SOURCE
#include <features.h>
 
#include <stdio.h>
#include <string.h>
#include <rpc/types.h>
#include <rpc/xdr.h>
 
#ifdef USE_IN_LIBIO
# include <wchar.h>
# include <libio/iolibio.h>
# define fputs(s, f) _IO_fputs (s, f)
#endif
 
#define LASTUNSIGNED ((u_int)0-1)
 
/*
* XDR an indirect pointer
* xdr_reference is for recursively translating a structure that is
* referenced by a pointer inside the structure that is currently being
* translated. pp references a pointer to storage. If *pp is null
* the necessary storage is allocated.
* size is the size of the referneced structure.
* proc is the routine to handle the referenced structure.
*/
bool_t
xdr_reference (xdrs, pp, size, proc)
XDR *xdrs;
caddr_t *pp; /* the pointer to work on */
u_int size; /* size of the object pointed to */
xdrproc_t proc; /* xdr routine to handle the object */
{
caddr_t loc = *pp;
bool_t stat;
 
if (loc == NULL)
switch (xdrs->x_op)
{
case XDR_FREE:
return TRUE;
 
case XDR_DECODE:
*pp = loc = (caddr_t) mem_alloc (size);
if (loc == NULL)
{
#ifdef USE_IN_LIBIO
if (_IO_fwide (stderr, 0) > 0)
(void) __fwprintf (stderr, L"%s",
_("xdr_reference: out of memory\n"));
else
#endif
(void) fputs (_("xdr_reference: out of memory\n"), stderr);
return FALSE;
}
bzero (loc, (int) size);
break;
default:
break;
}
 
stat = (*proc) (xdrs, loc, LASTUNSIGNED);
 
if (xdrs->x_op == XDR_FREE)
{
mem_free (loc, size);
*pp = NULL;
}
return stat;
}
 
 
/*
* xdr_pointer():
*
* XDR a pointer to a possibly recursive data structure. This
* differs with xdr_reference in that it can serialize/deserialize
* trees correctly.
*
* What's sent is actually a union:
*
* union object_pointer switch (boolean b) {
* case TRUE: object_data data;
* case FALSE: void nothing;
* }
*
* > objpp: Pointer to the pointer to the object.
* > obj_size: size of the object.
* > xdr_obj: routine to XDR an object.
*
*/
bool_t
xdr_pointer (xdrs, objpp, obj_size, xdr_obj)
XDR *xdrs;
char **objpp;
u_int obj_size;
xdrproc_t xdr_obj;
{
 
bool_t more_data;
 
more_data = (*objpp != NULL);
if (!xdr_bool (xdrs, &more_data))
{
return FALSE;
}
if (!more_data)
{
*objpp = NULL;
return TRUE;
}
return xdr_reference (xdrs, objpp, obj_size, xdr_obj);
}
/rpc/svc_auth.c
0,0 → 1,123
/* @(#)svc_auth.c 2.4 88/08/15 4.0 RPCSRC */
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
* media and as a part of the software program in whole or part. Users
* may copy or modify Sun RPC without charge, but are not authorized
* to license or distribute it to anyone else except as part of a product or
* program developed by the user.
*
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun RPC is provided with no support and without any obligation on the
* part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
#if 0
static char sccsid[] = "@(#)svc_auth.c 1.19 87/08/11 Copyr 1984 Sun Micro";
#endif
 
/*
* svc_auth.c, Server-side rpc authenticator interface.
*
* Copyright (C) 1984, Sun Microsystems, Inc.
*/
 
#include <rpc/rpc.h>
#include <rpc/svc.h>
#include <rpc/svc_auth.h>
 
/*
* svcauthsw is the bdevsw of server side authentication.
*
* Server side authenticators are called from authenticate by
* using the client auth struct flavor field to index into svcauthsw.
* The server auth flavors must implement a routine that looks
* like:
*
* enum auth_stat
* flavorx_auth(rqst, msg)
* register struct svc_req *rqst;
* register struct rpc_msg *msg;
*
*/
 
static enum auth_stat _svcauth_null (struct svc_req *, struct rpc_msg *);
/* no authentication */
extern enum auth_stat _svcauth_unix (struct svc_req *, struct rpc_msg *);
/* unix style (uid, gids) */
extern enum auth_stat _svcauth_short (struct svc_req *, struct rpc_msg *);
/* short hand unix style */
#ifdef CONFIG_AUTH_DES
extern enum auth_stat _svcauth_des (struct svc_req *, struct rpc_msg *);
/* des style */
#endif
 
static const struct
{
enum auth_stat (*authenticator) (struct svc_req *, struct rpc_msg *);
}
svcauthsw[] =
{
{ _svcauth_null }, /* AUTH_NULL */
{ _svcauth_unix }, /* AUTH_UNIX */
{ _svcauth_short }, /* AUTH_SHORT */
#ifdef CONFIG_AUTH_DES
{ _svcauth_des } /* AUTH_DES */
#endif
};
#define AUTH_MAX 3 /* HIGHEST AUTH NUMBER */
 
 
/*
* The call rpc message, msg has been obtained from the wire. The msg contains
* the raw form of credentials and verifiers. authenticate returns AUTH_OK
* if the msg is successfully authenticated. If AUTH_OK then the routine also
* does the following things:
* set rqst->rq_xprt->verf to the appropriate response verifier;
* sets rqst->rq_client_cred to the "cooked" form of the credentials.
*
* NB: rqst->rq_cxprt->verf must be pre-allocated;
* its length is set appropriately.
*
* The caller still owns and is responsible for msg->u.cmb.cred and
* msg->u.cmb.verf. The authentication system retains ownership of
* rqst->rq_client_cred, the cooked credentials.
*
* There is an assumption that any flavour less than AUTH_NULL is
* invalid.
*/
enum auth_stat
_authenticate (register struct svc_req *rqst, struct rpc_msg *msg)
{
register int cred_flavor;
 
rqst->rq_cred = msg->rm_call.cb_cred;
rqst->rq_xprt->xp_verf.oa_flavor = _null_auth.oa_flavor;
rqst->rq_xprt->xp_verf.oa_length = 0;
cred_flavor = rqst->rq_cred.oa_flavor;
if ((cred_flavor <= AUTH_MAX) && (cred_flavor >= AUTH_NULL))
return (*(svcauthsw[cred_flavor].authenticator)) (rqst, msg);
 
return AUTH_REJECTEDCRED;
}
 
static enum auth_stat
_svcauth_null (struct svc_req *rqst, struct rpc_msg *msg)
{
return AUTH_OK;
}
/rpc/.indent.pro
0,0 → 1,33
--blank-lines-after-declarations
--blank-lines-after-procedures
--break-before-boolean-operator
--no-blank-lines-after-commas
--braces-on-if-line
--braces-on-struct-decl-line
--comment-indentation25
--declaration-comment-column25
--no-comment-delimiters-on-blank-lines
--cuddle-else
--continuation-indentation4
--case-indentation0
--else-endif-column33
--space-after-cast
--line-comments-indentation0
--declaration-indentation1
--dont-format-first-column-comments
--dont-format-comments
--honour-newlines
--indent-level4
/* changed from 0 to 4 */
--parameter-indentation4
--line-length78 /* changed from 75 */
--continue-at-parentheses
--no-space-after-function-call-names
--dont-break-procedure-type
--dont-star-comments
--leave-optional-blank-lines
--dont-space-special-semicolon
--tab-size4
/* additions by Mark */
--case-brace-indentation0
--leave-preprocessor-space
/rpc/pmap_clnt.c
0,0 → 1,173
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
* media and as a part of the software program in whole or part. Users
* may copy or modify Sun RPC without charge, but are not authorized
* to license or distribute it to anyone else except as part of a product or
* program developed by the user.
*
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun RPC is provided with no support and without any obligation on the
* part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
/*
* Copyright (C) 1984, Sun Microsystems, Inc.
*/
/*
* pmap_clnt.c
* Client interface to pmap rpc service.
*/
 
#define __FORCE_GLIBC
#include <features.h>
 
#include <stdio.h>
#include <unistd.h>
#include <net/if.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <rpc/rpc.h>
#include <rpc/pmap_prot.h>
#include <rpc/pmap_clnt.h>
 
/*
* Same as get_myaddress, but we try to use the loopback
* interface. portmap caches interfaces, and on DHCP clients,
* it could be that only loopback is started at this time.
*/
static bool_t
__get_myaddress (struct sockaddr_in *addr)
{
int s;
char buf[BUFSIZ];
struct ifconf ifc;
struct ifreq ifreq, *ifr;
int len, loopback = 1;
 
if ((s = socket (AF_INET, SOCK_DGRAM, 0)) < 0)
{
perror ("__get_myaddress: socket");
exit (1);
}
ifc.ifc_len = sizeof (buf);
ifc.ifc_buf = buf;
if (ioctl (s, SIOCGIFCONF, (char *) &ifc) < 0)
{
perror (_("__get_myaddress: ioctl (get interface configuration)"));
exit (1);
}
 
again:
ifr = ifc.ifc_req;
for (len = ifc.ifc_len; len; len -= sizeof ifreq)
{
ifreq = *ifr;
if (ioctl (s, SIOCGIFFLAGS, (char *) &ifreq) < 0)
{
perror ("__get_myaddress: ioctl");
exit (1);
}
if ((ifreq.ifr_flags & IFF_UP) && (ifr->ifr_addr.sa_family == AF_INET)
&& ((ifreq.ifr_flags & IFF_LOOPBACK) || (loopback == 0)))
{
*addr = *((struct sockaddr_in *) &ifr->ifr_addr);
addr->sin_port = htons (PMAPPORT);
close (s);
return TRUE;
}
ifr++;
}
if (loopback == 1)
{
loopback = 0;
goto again;
}
close (s);
return FALSE;
}
 
 
static const struct timeval timeout = {5, 0};
static const struct timeval tottimeout = {60, 0};
 
/*
* Set a mapping between program,version and port.
* Calls the pmap service remotely to do the mapping.
*/
bool_t
pmap_set (u_long program, u_long version, int protocol, u_short port)
{
struct sockaddr_in myaddress;
int socket = -1;
CLIENT *client;
struct pmap parms;
bool_t rslt;
 
if (!__get_myaddress (&myaddress))
return FALSE;
client = clntudp_bufcreate (&myaddress, PMAPPROG, PMAPVERS,
timeout, &socket, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE);
if (client == (CLIENT *) NULL)
return (FALSE);
parms.pm_prog = program;
parms.pm_vers = version;
parms.pm_prot = protocol;
parms.pm_port = port;
if (CLNT_CALL (client, PMAPPROC_SET, (xdrproc_t)xdr_pmap, (caddr_t)&parms,
(xdrproc_t)xdr_bool, (caddr_t)&rslt,
tottimeout) != RPC_SUCCESS)
{
clnt_perror (client, _("Cannot register service"));
return FALSE;
}
CLNT_DESTROY (client);
/* (void)close(socket); CLNT_DESTROY closes it */
return rslt;
}
 
/*
* Remove the mapping between program,version and port.
* Calls the pmap service remotely to do the un-mapping.
*/
bool_t
pmap_unset (u_long program, u_long version)
{
struct sockaddr_in myaddress;
int socket = -1;
CLIENT *client;
struct pmap parms;
bool_t rslt;
 
if (!__get_myaddress (&myaddress))
return FALSE;
client = clntudp_bufcreate (&myaddress, PMAPPROG, PMAPVERS,
timeout, &socket, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE);
if (client == (CLIENT *) NULL)
return FALSE;
parms.pm_prog = program;
parms.pm_vers = version;
parms.pm_port = parms.pm_prot = 0;
CLNT_CALL (client, PMAPPROC_UNSET, (xdrproc_t)xdr_pmap, (caddr_t)&parms,
(xdrproc_t)xdr_bool, (caddr_t)&rslt, tottimeout);
CLNT_DESTROY (client);
/* (void)close(socket); CLNT_DESTROY already closed it */
return rslt;
}
/rpc/pmap_getmaps.c
0,0 → 1,80
/* @(#)pmap_getmaps.c 2.2 88/08/01 4.0 RPCSRC */
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
* media and as a part of the software program in whole or part. Users
* may copy or modify Sun RPC without charge, but are not authorized
* to license or distribute it to anyone else except as part of a product or
* program developed by the user.
*
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun RPC is provided with no support and without any obligation on the
* part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
#if 0
static char sccsid[] = "@(#)pmap_getmaps.c 1.10 87/08/11 Copyr 1984 Sun Micro";
#endif
 
/*
* pmap_getmap.c
* Client interface to pmap rpc service.
* contains pmap_getmaps, which is only tcp service involved
*
* Copyright (C) 1984, Sun Microsystems, Inc.
*/
 
#include <rpc/rpc.h>
#include <rpc/pmap_prot.h>
#include <rpc/pmap_clnt.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdio.h>
#include <errno.h>
 
/*
* Get a copy of the current port maps.
* Calls the pmap service remotely to do get the maps.
*/
struct pmaplist *
pmap_getmaps (struct sockaddr_in *address)
{
struct pmaplist *head = (struct pmaplist *) NULL;
int socket = -1;
struct timeval minutetimeout;
CLIENT *client;
 
minutetimeout.tv_sec = 60;
minutetimeout.tv_usec = 0;
address->sin_port = htons (PMAPPORT);
client = clnttcp_create (address, PMAPPROG,
PMAPVERS, &socket, 50, 500);
if (client != (CLIENT *) NULL)
{
if (CLNT_CALL (client, PMAPPROC_DUMP, (xdrproc_t)xdr_void, NULL,
(xdrproc_t)xdr_pmaplist, (caddr_t)&head,
minutetimeout) != RPC_SUCCESS)
{
clnt_perror (client, _("pmap_getmaps rpc problem"));
}
CLNT_DESTROY (client);
}
/* (void)close(socket); CLNT_DESTROY already closed it */
address->sin_port = 0;
return head;
}
/rpc/pmap_rmt.c
0,0 → 1,413
/* @(#)pmap_rmt.c 2.2 88/08/01 4.0 RPCSRC */
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
* media and as a part of the software program in whole or part. Users
* may copy or modify Sun RPC without charge, but are not authorized
* to license or distribute it to anyone else except as part of a product or
* program developed by the user.
*
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun RPC is provided with no support and without any obligation on the
* part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
#if 0
static char sccsid[] = "@(#)pmap_rmt.c 1.21 87/08/27 Copyr 1984 Sun Micro";
#endif
 
/*
* pmap_rmt.c
* Client interface to pmap rpc service.
* remote call and broadcast service
*
* Copyright (C) 1984, Sun Microsystems, Inc.
*/
 
#define __FORCE_GLIBC
#include <features.h>
 
#include <unistd.h>
#include <string.h>
#include <rpc/rpc.h>
#include <rpc/pmap_prot.h>
#include <rpc/pmap_clnt.h>
#include <rpc/pmap_rmt.h>
#include <sys/poll.h>
#include <sys/socket.h>
#include <stdio.h>
#include <errno.h>
#undef _POSIX_SOURCE /* Ultrix <sys/param.h> needs --roland@gnu */
#include <sys/param.h> /* Ultrix needs before net/if --roland@gnu */
#include <net/if.h>
#include <sys/ioctl.h>
#include <arpa/inet.h>
#define MAX_BROADCAST_SIZE 1400
 
extern u_long _create_xid (void);
 
static const struct timeval timeout = {3, 0};
 
/*
* pmapper remote-call-service interface.
* This routine is used to call the pmapper remote call service
* which will look up a service program in the port maps, and then
* remotely call that routine with the given parameters. This allows
* programs to do a lookup and call in one step.
*/
enum clnt_stat
pmap_rmtcall (addr, prog, vers, proc, xdrargs, argsp, xdrres, resp, tout, port_ptr)
struct sockaddr_in *addr;
u_long prog, vers, proc;
xdrproc_t xdrargs, xdrres;
caddr_t argsp, resp;
struct timeval tout;
u_long *port_ptr;
{
int socket = -1;
CLIENT *client;
struct rmtcallargs a;
struct rmtcallres r;
enum clnt_stat stat;
 
addr->sin_port = htons (PMAPPORT);
client = clntudp_create (addr, PMAPPROG, PMAPVERS, timeout, &socket);
if (client != (CLIENT *) NULL)
{
a.prog = prog;
a.vers = vers;
a.proc = proc;
a.args_ptr = argsp;
a.xdr_args = xdrargs;
r.port_ptr = port_ptr;
r.results_ptr = resp;
r.xdr_results = xdrres;
stat = CLNT_CALL (client, PMAPPROC_CALLIT, (xdrproc_t)xdr_rmtcall_args,
(caddr_t)&a, (xdrproc_t)xdr_rmtcallres,
(caddr_t)&r, tout);
CLNT_DESTROY (client);
}
else
{
stat = RPC_FAILED;
}
/* (void)__close(socket); CLNT_DESTROY already closed it */
addr->sin_port = 0;
return stat;
}
 
 
/*
* XDR remote call arguments
* written for XDR_ENCODE direction only
*/
bool_t
xdr_rmtcall_args (XDR *xdrs, struct rmtcallargs *cap)
{
u_int lenposition, argposition, position;
 
if (xdr_u_long (xdrs, &(cap->prog)) &&
xdr_u_long (xdrs, &(cap->vers)) &&
xdr_u_long (xdrs, &(cap->proc)))
{
lenposition = XDR_GETPOS (xdrs);
if (!xdr_u_long (xdrs, &(cap->arglen)))
return FALSE;
argposition = XDR_GETPOS (xdrs);
if (!(*(cap->xdr_args)) (xdrs, cap->args_ptr))
return FALSE;
position = XDR_GETPOS (xdrs);
cap->arglen = (u_long) position - (u_long) argposition;
XDR_SETPOS (xdrs, lenposition);
if (!xdr_u_long (xdrs, &(cap->arglen)))
return FALSE;
XDR_SETPOS (xdrs, position);
return TRUE;
}
return FALSE;
}
 
/*
* XDR remote call results
* written for XDR_DECODE direction only
*/
bool_t
xdr_rmtcallres (xdrs, crp)
XDR *xdrs;
struct rmtcallres *crp;
{
caddr_t port_ptr;
 
port_ptr = (caddr_t) crp->port_ptr;
if (xdr_reference (xdrs, &port_ptr, sizeof (u_long), (xdrproc_t) xdr_u_long)
&& xdr_u_long (xdrs, &crp->resultslen))
{
crp->port_ptr = (u_long *) port_ptr;
return (*(crp->xdr_results)) (xdrs, crp->results_ptr);
}
return FALSE;
}
 
 
/*
* The following is kludged-up support for simple rpc broadcasts.
* Someday a large, complicated system will replace these trivial
* routines which only support udp/ip .
*/
 
static int
internal_function
getbroadcastnets (struct in_addr *addrs, int sock, char *buf)
/* int sock: any valid socket will do */
/* char *buf: why allocate more when we can use existing... */
{
struct ifconf ifc;
struct ifreq ifreq, *ifr;
struct sockaddr_in *sin;
int n, i;
 
ifc.ifc_len = UDPMSGSIZE;
ifc.ifc_buf = buf;
if (ioctl (sock, SIOCGIFCONF, (char *) &ifc) < 0)
{
perror (_("broadcast: ioctl (get interface configuration)"));
return (0);
}
ifr = ifc.ifc_req;
for (i = 0, n = ifc.ifc_len / sizeof (struct ifreq); n > 0; n--, ifr++)
{
ifreq = *ifr;
if (ioctl (sock, SIOCGIFFLAGS, (char *) &ifreq) < 0)
{
perror (_("broadcast: ioctl (get interface flags)"));
continue;
}
if ((ifreq.ifr_flags & IFF_BROADCAST) &&
(ifreq.ifr_flags & IFF_UP) &&
ifr->ifr_addr.sa_family == AF_INET)
{
sin = (struct sockaddr_in *) &ifr->ifr_addr;
#ifdef SIOCGIFBRDADDR /* 4.3BSD */
if (ioctl (sock, SIOCGIFBRDADDR, (char *) &ifreq) < 0)
{
addrs[i++] = inet_makeaddr (inet_netof
/* Changed to pass struct instead of s_addr member
by roland@gnu. */
(sin->sin_addr), INADDR_ANY);
}
else
{
addrs[i++] = ((struct sockaddr_in *)
&ifreq.ifr_addr)->sin_addr;
}
#else /* 4.2 BSD */
addrs[i++] = inet_makeaddr (inet_netof
(sin->sin_addr.s_addr), INADDR_ANY);
#endif
}
}
return i;
}
 
 
enum clnt_stat
clnt_broadcast (prog, vers, proc, xargs, argsp, xresults, resultsp, eachresult)
u_long prog; /* program number */
u_long vers; /* version number */
u_long proc; /* procedure number */
xdrproc_t xargs; /* xdr routine for args */
caddr_t argsp; /* pointer to args */
xdrproc_t xresults; /* xdr routine for results */
caddr_t resultsp; /* pointer to results */
resultproc_t eachresult; /* call with each result obtained */
{
enum clnt_stat stat = RPC_FAILED;
AUTH *unix_auth = authunix_create_default ();
XDR xdr_stream;
XDR *xdrs = &xdr_stream;
struct timeval t;
int outlen, inlen, nets;
socklen_t fromlen;
int sock;
int on = 1;
struct pollfd fd;
int milliseconds;
int i;
bool_t done = FALSE;
u_long xid;
u_long port;
struct in_addr addrs[20];
struct sockaddr_in baddr, raddr; /* broadcast and response addresses */
struct rmtcallargs a;
struct rmtcallres r;
struct rpc_msg msg;
char outbuf[MAX_BROADCAST_SIZE], inbuf[UDPMSGSIZE];
 
/*
* initialization: create a socket, a broadcast address, and
* preserialize the arguments into a send buffer.
*/
if ((sock = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
{
perror (_("Cannot create socket for broadcast rpc"));
stat = RPC_CANTSEND;
goto done_broad;
}
#ifdef SO_BROADCAST
if (setsockopt (sock, SOL_SOCKET, SO_BROADCAST, &on, sizeof (on)) < 0)
{
perror (_("Cannot set socket option SO_BROADCAST"));
stat = RPC_CANTSEND;
goto done_broad;
}
#endif /* def SO_BROADCAST */
fd.fd = sock;
fd.events = POLLIN;
nets = getbroadcastnets (addrs, sock, inbuf);
bzero ((char *) &baddr, sizeof (baddr));
baddr.sin_family = AF_INET;
baddr.sin_port = htons (PMAPPORT);
baddr.sin_addr.s_addr = htonl (INADDR_ANY);
/* baddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY); */
msg.rm_xid = xid = _create_xid ();
t.tv_usec = 0;
msg.rm_direction = CALL;
msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
msg.rm_call.cb_prog = PMAPPROG;
msg.rm_call.cb_vers = PMAPVERS;
msg.rm_call.cb_proc = PMAPPROC_CALLIT;
msg.rm_call.cb_cred = unix_auth->ah_cred;
msg.rm_call.cb_verf = unix_auth->ah_verf;
a.prog = prog;
a.vers = vers;
a.proc = proc;
a.xdr_args = xargs;
a.args_ptr = argsp;
r.port_ptr = &port;
r.xdr_results = xresults;
r.results_ptr = resultsp;
xdrmem_create (xdrs, outbuf, MAX_BROADCAST_SIZE, XDR_ENCODE);
if ((!xdr_callmsg (xdrs, &msg)) || (!xdr_rmtcall_args (xdrs, &a)))
{
stat = RPC_CANTENCODEARGS;
goto done_broad;
}
outlen = (int) xdr_getpos (xdrs);
xdr_destroy (xdrs);
/*
* Basic loop: broadcast a packet and wait a while for response(s).
* The response timeout grows larger per iteration.
*/
for (t.tv_sec = 4; t.tv_sec <= 14; t.tv_sec += 2)
{
for (i = 0; i < nets; i++)
{
baddr.sin_addr = addrs[i];
if (sendto (sock, outbuf, outlen, 0,
(struct sockaddr *) &baddr,
sizeof (struct sockaddr)) != outlen)
{
perror (_("Cannot send broadcast packet"));
stat = RPC_CANTSEND;
goto done_broad;
}
}
if (eachresult == NULL)
{
stat = RPC_SUCCESS;
goto done_broad;
}
recv_again:
msg.acpted_rply.ar_verf = _null_auth;
msg.acpted_rply.ar_results.where = (caddr_t) & r;
msg.acpted_rply.ar_results.proc = (xdrproc_t) xdr_rmtcallres;
milliseconds = t.tv_sec * 1000 + t.tv_usec / 1000;
switch (poll(&fd, 1, milliseconds))
{
 
case 0: /* timed out */
stat = RPC_TIMEDOUT;
continue;
 
case -1: /* some kind of error */
if (errno == EINTR)
goto recv_again;
perror (_("Broadcast poll problem"));
stat = RPC_CANTRECV;
goto done_broad;
 
} /* end of poll results switch */
try_again:
fromlen = sizeof (struct sockaddr);
inlen = recvfrom (sock, inbuf, UDPMSGSIZE, 0,
(struct sockaddr *) &raddr, &fromlen);
if (inlen < 0)
{
if (errno == EINTR)
goto try_again;
perror (_("Cannot receive reply to broadcast"));
stat = RPC_CANTRECV;
goto done_broad;
}
if ((size_t) inlen < sizeof (u_long))
goto recv_again;
/*
* see if reply transaction id matches sent id.
* If so, decode the results.
*/
xdrmem_create (xdrs, inbuf, (u_int) inlen, XDR_DECODE);
if (xdr_replymsg (xdrs, &msg))
{
if (((u_int32_t) msg.rm_xid == (u_int32_t) xid) &&
(msg.rm_reply.rp_stat == MSG_ACCEPTED) &&
(msg.acpted_rply.ar_stat == SUCCESS))
{
raddr.sin_port = htons ((u_short) port);
done = (*eachresult) (resultsp, &raddr);
}
/* otherwise, we just ignore the errors ... */
}
else
{
#ifdef notdef
/* some kind of deserialization problem ... */
if ((u_int32_t) msg.rm_xid == (u_int32_t) xid)
fprintf (stderr, "Broadcast deserialization problem");
/* otherwise, just random garbage */
#endif
}
xdrs->x_op = XDR_FREE;
msg.acpted_rply.ar_results.proc = (xdrproc_t)xdr_void;
(void) xdr_replymsg (xdrs, &msg);
(void) (*xresults) (xdrs, resultsp);
xdr_destroy (xdrs);
if (done)
{
stat = RPC_SUCCESS;
goto done_broad;
}
else
{
goto recv_again;
}
}
done_broad:
(void) close (sock);
AUTH_DESTROY (unix_auth);
return stat;
}
/rpc/svc_auth_unix.c
0,0 → 1,155
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
* media and as a part of the software program in whole or part. Users
* may copy or modify Sun RPC without charge, but are not authorized
* to license or distribute it to anyone else except as part of a product or
* program developed by the user.
*
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun RPC is provided with no support and without any obligation on the
* part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
 
/*
* svc_auth_unix.c
* Handles UNIX flavor authentication parameters on the service side of rpc.
* There are two svc auth implementations here: AUTH_UNIX and AUTH_SHORT.
* _svcauth_unix does full blown unix style uid,gid+gids auth,
* _svcauth_short uses a shorthand auth to index into a cache of longhand auths.
* Note: the shorthand has been gutted for efficiency.
*
* Copyright (C) 1984, Sun Microsystems, Inc.
*/
 
#define __FORCE_GLIBC
#define _GNU_SOURCE
#include <features.h>
 
#include <stdio.h>
#include <string.h>
#include <rpc/rpc.h>
#include <rpc/svc.h>
 
/*
* Unix longhand authenticator
*/
enum auth_stat
_svcauth_unix (struct svc_req *rqst, struct rpc_msg *msg)
{
enum auth_stat stat;
XDR xdrs;
struct authunix_parms *aup;
int32_t *buf;
struct area
{
struct authunix_parms area_aup;
char area_machname[MAX_MACHINE_NAME + 1];
gid_t area_gids[NGRPS];
}
*area;
u_int auth_len;
u_int str_len, gid_len;
u_int i;
 
area = (struct area *) rqst->rq_clntcred;
aup = &area->area_aup;
aup->aup_machname = area->area_machname;
aup->aup_gids = area->area_gids;
auth_len = (u_int) msg->rm_call.cb_cred.oa_length;
xdrmem_create (&xdrs, msg->rm_call.cb_cred.oa_base, auth_len, XDR_DECODE);
buf = XDR_INLINE (&xdrs, auth_len);
if (buf != NULL)
{
aup->aup_time = IXDR_GET_LONG (buf);
str_len = IXDR_GET_U_INT32 (buf);
if (str_len > MAX_MACHINE_NAME)
{
stat = AUTH_BADCRED;
goto done;
}
memcpy (aup->aup_machname, (caddr_t) buf, (u_int) str_len);
aup->aup_machname[str_len] = 0;
str_len = RNDUP (str_len);
buf = (int32_t *) ((char *) buf + str_len);
aup->aup_uid = IXDR_GET_LONG (buf);
aup->aup_gid = IXDR_GET_LONG (buf);
gid_len = IXDR_GET_U_INT32 (buf);
if (gid_len > NGRPS)
{
stat = AUTH_BADCRED;
goto done;
}
aup->aup_len = gid_len;
for (i = 0; i < gid_len; i++)
{
aup->aup_gids[i] = IXDR_GET_LONG (buf);
}
/*
* five is the smallest unix credentials structure -
* timestamp, hostname len (0), uid, gid, and gids len (0).
*/
if ((5 + gid_len) * BYTES_PER_XDR_UNIT + str_len > auth_len)
{
(void) printf ("bad auth_len gid %d str %d auth %d\n",
gid_len, str_len, auth_len);
stat = AUTH_BADCRED;
goto done;
}
}
else if (!xdr_authunix_parms (&xdrs, aup))
{
xdrs.x_op = XDR_FREE;
(void) xdr_authunix_parms (&xdrs, aup);
stat = AUTH_BADCRED;
goto done;
}
 
/* get the verifier */
if ((u_int)msg->rm_call.cb_verf.oa_length)
{
rqst->rq_xprt->xp_verf.oa_flavor =
msg->rm_call.cb_verf.oa_flavor;
rqst->rq_xprt->xp_verf.oa_base =
msg->rm_call.cb_verf.oa_base;
rqst->rq_xprt->xp_verf.oa_length =
msg->rm_call.cb_verf.oa_length;
}
else
{
rqst->rq_xprt->xp_verf.oa_flavor = AUTH_NULL;
rqst->rq_xprt->xp_verf.oa_length = 0;
}
stat = AUTH_OK;
done:
XDR_DESTROY (&xdrs);
return stat;
}
 
 
/*
* Shorthand unix authenticator
* Looks up longhand in a cache.
*/
/*ARGSUSED */
enum auth_stat
_svcauth_short (struct svc_req *rqst, struct rpc_msg *msg)
{
return AUTH_REJECTEDCRED;
}
/rpc/svc_run.c
0,0 → 1,89
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
* media and as a part of the software program in whole or part. Users
* may copy or modify Sun RPC without charge, but are not authorized
* to license or distribute it to anyone else except as part of a product or
* program developed by the user.
*
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun RPC is provided with no support and without any obligation on the
* part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
/*
* This is the rpc server side idle loop
* Wait for input, call server program.
*/
 
#define __FORCE_GLIBC
#define _GNU_SOURCE
#include <features.h>
 
#include <errno.h>
#include <unistd.h>
#include <sys/poll.h>
#include <rpc/rpc.h>
 
/* This function can be used as a signal handler to terminate the
server loop. */
void
svc_exit (void)
{
free (svc_pollfd);
svc_pollfd = NULL;
svc_max_pollfd = 0;
}
 
void
svc_run (void)
{
int i;
 
for (;;)
{
struct pollfd *my_pollfd;
 
if (svc_max_pollfd == 0 && svc_pollfd == NULL)
return;
 
my_pollfd = malloc (sizeof (struct pollfd) * svc_max_pollfd);
for (i = 0; i < svc_max_pollfd; ++i)
{
my_pollfd[i].fd = svc_pollfd[i].fd;
my_pollfd[i].events = svc_pollfd[i].events;
my_pollfd[i].revents = 0;
}
 
switch (i = poll (my_pollfd, svc_max_pollfd, -1))
{
case -1:
free (my_pollfd);
if (errno == EINTR)
continue;
perror (_("svc_run: - poll failed"));
return;
case 0:
free (my_pollfd);
continue;
default:
svc_getreq_poll (my_pollfd, i);
free (my_pollfd);
}
}
}
/rpc/rtime.c
0,0 → 1,149
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
* media and as a part of the software program in whole or part. Users
* may copy or modify Sun RPC without charge, but are not authorized
* to license or distribute it to anyone else except as part of a product or
* program developed by the user.
*
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun RPC is provided with no support and without any obligation on the
* part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
#if 0
static char sccsid[] = "@(#)rtime.c 2.2 88/08/10 4.0 RPCSRC; from 1.8 88/02/08 SMI";
#endif
 
/*
* Copyright (c) 1988 by Sun Microsystems, Inc.
*/
/*
* rtime - get time from remote machine
*
* gets time, obtaining value from host
* on the udp/time socket. Since timeserver returns
* with time of day in seconds since Jan 1, 1900, must
* subtract seconds before Jan 1, 1970 to get
* what unix uses.
*/
#define __FORCE_GLIBC
#include <features.h>
 
#include <stdio.h>
#include <unistd.h>
#include <rpc/rpc.h>
#include <rpc/clnt.h>
#include <sys/types.h>
#include <sys/poll.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <rpc/auth_des.h>
#include <errno.h>
#include <netinet/in.h>
 
#define NYEARS (u_long)(1970 - 1900)
#define TOFFSET (u_long)(60*60*24*(365*NYEARS + (NYEARS/4)))
 
static void do_close (int);
 
static void
do_close (int s)
{
int save;
 
save = errno;
close (s);
__set_errno (save);
}
 
int
rtime (struct sockaddr_in *addrp, struct rpc_timeval *timep,
struct rpc_timeval *timeout)
{
int s;
struct pollfd fd;
int milliseconds;
int res;
unsigned long thetime;
struct sockaddr_in from;
int fromlen;
int type;
 
if (timeout == NULL)
type = SOCK_STREAM;
else
type = SOCK_DGRAM;
 
s = socket (AF_INET, type, 0);
if (s < 0)
return (-1);
 
addrp->sin_family = AF_INET;
addrp->sin_port = htons (IPPORT_TIMESERVER);
if (type == SOCK_DGRAM)
{
res = sendto (s, (char *) &thetime, sizeof (thetime), 0,
(struct sockaddr *) addrp, sizeof (*addrp));
if (res < 0)
{
do_close (s);
return -1;
}
milliseconds = (timeout->tv_sec * 1000) + (timeout->tv_usec / 1000);
fd.fd = s;
fd.events = POLLIN;
do
res = poll (&fd, 1, milliseconds);
while (res < 0 && errno == EINTR);
if (res <= 0)
{
if (res == 0)
__set_errno (ETIMEDOUT);
do_close (s);
return (-1);
}
fromlen = sizeof (from);
res = recvfrom (s, (char *) &thetime, sizeof (thetime), 0,
(struct sockaddr *) &from, &fromlen);
do_close (s);
if (res < 0)
return -1;
}
else
{
if (connect (s, (struct sockaddr *) addrp, sizeof (*addrp)) < 0)
{
do_close (s);
return -1;
}
res = read (s, (char *) &thetime, sizeof (thetime));
do_close (s);
if (res < 0)
return (-1);
}
if (res != sizeof (thetime))
{
__set_errno (EIO);
return -1;
}
thetime = ntohl (thetime);
timep->tv_sec = thetime - TOFFSET;
timep->tv_usec = 0;
return 0;
}
/rpc/bindresvport.c
0,0 → 1,88
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
* media and as a part of the software program in whole or part. Users
* may copy or modify Sun RPC without charge, but are not authorized
* to license or distribute it to anyone else except as part of a product or
* program developed by the user.
*
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun RPC is provided with no support and without any obligation on the
* part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
/*
* Copyright (c) 1987 by Sun Microsystems, Inc.
*/
 
#define __FORCE_GLIBC
#include <features.h>
 
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
 
/*
* Bind a socket to a privileged IP port
*/
int
bindresvport (int sd, struct sockaddr_in *sin)
{
int res;
static short port;
struct sockaddr_in myaddr;
int i;
 
#define STARTPORT 600
#define ENDPORT (IPPORT_RESERVED - 1)
#define NPORTS (ENDPORT - STARTPORT + 1)
 
if (sin == (struct sockaddr_in *) 0)
{
sin = &myaddr;
bzero (sin, sizeof (*sin));
sin->sin_family = AF_INET;
}
else if (sin->sin_family != AF_INET)
{
__set_errno (EPFNOSUPPORT);
return -1;
}
 
if (port == 0)
{
port = (getpid () % NPORTS) + STARTPORT;
}
res = -1;
__set_errno (EADDRINUSE);
 
for (i = 0; i < NPORTS && res < 0 && errno == EADDRINUSE; ++i)
{
sin->sin_port = htons (port);
if (++port > ENDPORT)
{
port = STARTPORT;
}
res = bind(sd, (struct sockaddr *)sin, sizeof(struct sockaddr_in));
}
 
return res;
}
/rpc/xdr_float.c
0,0 → 1,311
/* @(#)xdr_float.c 2.1 88/07/29 4.0 RPCSRC */
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
* media and as a part of the software program in whole or part. Users
* may copy or modify Sun RPC without charge, but are not authorized
* to license or distribute it to anyone else except as part of a product or
* program developed by the user.
*
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun RPC is provided with no support and without any obligation on the
* part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
#if 0
static char sccsid[] = "@(#)xdr_float.c 1.12 87/08/11 Copyr 1984 Sun Micro";
#endif
 
/*
* xdr_float.c, Generic XDR routines implementation.
*
* Copyright (C) 1984, Sun Microsystems, Inc.
*
* These are the "floating point" xdr routines used to (de)serialize
* most common data items. See xdr.h for more info on the interface to
* xdr.
*/
 
#define __FORCE_GLIBC
#define _GNU_SOURCE
#include <features.h>
 
#include <stdio.h>
#include <endian.h>
 
#include <rpc/types.h>
#include <rpc/xdr.h>
 
/*
* NB: Not portable.
* This routine works on Suns (Sky / 68000's) and Vaxen.
*/
 
#define LSW (__FLOAT_WORD_ORDER == __BIG_ENDIAN)
 
#ifdef vax
 
/* What IEEE single precision floating point looks like on a Vax */
struct ieee_single {
unsigned int mantissa: 23;
unsigned int exp : 8;
unsigned int sign : 1;
};
 
/* Vax single precision floating point */
struct vax_single {
unsigned int mantissa1 : 7;
unsigned int exp : 8;
unsigned int sign : 1;
unsigned int mantissa2 : 16;
};
 
#define VAX_SNG_BIAS 0x81
#define IEEE_SNG_BIAS 0x7f
 
static struct sgl_limits {
struct vax_single s;
struct ieee_single ieee;
} sgl_limits[2] = {
{{ 0x7f, 0xff, 0x0, 0xffff }, /* Max Vax */
{ 0x0, 0xff, 0x0 }}, /* Max IEEE */
{{ 0x0, 0x0, 0x0, 0x0 }, /* Min Vax */
{ 0x0, 0x0, 0x0 }} /* Min IEEE */
};
#endif /* vax */
 
bool_t
xdr_float(xdrs, fp)
XDR *xdrs;
float *fp;
{
#ifdef vax
struct ieee_single is;
struct vax_single vs, *vsp;
struct sgl_limits *lim;
int i;
#endif
switch (xdrs->x_op) {
 
case XDR_ENCODE:
#ifdef vax
vs = *((struct vax_single *)fp);
for (i = 0, lim = sgl_limits;
i < sizeof(sgl_limits)/sizeof(struct sgl_limits);
i++, lim++) {
if ((vs.mantissa2 == lim->s.mantissa2) &&
(vs.exp == lim->s.exp) &&
(vs.mantissa1 == lim->s.mantissa1)) {
is = lim->ieee;
goto shipit;
}
}
is.exp = vs.exp - VAX_SNG_BIAS + IEEE_SNG_BIAS;
is.mantissa = (vs.mantissa1 << 16) | vs.mantissa2;
shipit:
is.sign = vs.sign;
return (XDR_PUTLONG(xdrs, (long *)&is));
#else
if (sizeof(float) == sizeof(long))
return (XDR_PUTLONG(xdrs, (long *)fp));
else if (sizeof(float) == sizeof(int)) {
long tmp = *(int *)fp;
return (XDR_PUTLONG(xdrs, &tmp));
}
break;
#endif
 
case XDR_DECODE:
#ifdef vax
vsp = (struct vax_single *)fp;
if (!XDR_GETLONG(xdrs, (long *)&is))
return (FALSE);
for (i = 0, lim = sgl_limits;
i < sizeof(sgl_limits)/sizeof(struct sgl_limits);
i++, lim++) {
if ((is.exp == lim->ieee.exp) &&
(is.mantissa == lim->ieee.mantissa)) {
*vsp = lim->s;
goto doneit;
}
}
vsp->exp = is.exp - IEEE_SNG_BIAS + VAX_SNG_BIAS;
vsp->mantissa2 = is.mantissa;
vsp->mantissa1 = (is.mantissa >> 16);
doneit:
vsp->sign = is.sign;
return (TRUE);
#else
if (sizeof(float) == sizeof(long))
return (XDR_GETLONG(xdrs, (long *)fp));
else if (sizeof(float) == sizeof(int)) {
long tmp;
if (XDR_GETLONG(xdrs, &tmp)) {
*(int *)fp = tmp;
return (TRUE);
}
}
break;
#endif
 
case XDR_FREE:
return (TRUE);
}
return (FALSE);
}
 
/*
* This routine works on Suns (Sky / 68000's) and Vaxen.
*/
 
#ifdef vax
/* What IEEE double precision floating point looks like on a Vax */
struct ieee_double {
unsigned int mantissa1 : 20;
unsigned int exp : 11;
unsigned int sign : 1;
unsigned int mantissa2 : 32;
};
 
/* Vax double precision floating point */
struct vax_double {
unsigned int mantissa1 : 7;
unsigned int exp : 8;
unsigned int sign : 1;
unsigned int mantissa2 : 16;
unsigned int mantissa3 : 16;
unsigned int mantissa4 : 16;
};
 
#define VAX_DBL_BIAS 0x81
#define IEEE_DBL_BIAS 0x3ff
#define MASK(nbits) ((1 << nbits) - 1)
 
static struct dbl_limits {
struct vax_double d;
struct ieee_double ieee;
} dbl_limits[2] = {
{{ 0x7f, 0xff, 0x0, 0xffff, 0xffff, 0xffff }, /* Max Vax */
{ 0x0, 0x7ff, 0x0, 0x0 }}, /* Max IEEE */
{{ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, /* Min Vax */
{ 0x0, 0x0, 0x0, 0x0 }} /* Min IEEE */
};
 
#endif /* vax */
 
 
bool_t
xdr_double(xdrs, dp)
XDR *xdrs;
double *dp;
{
#ifdef vax
struct ieee_double id;
struct vax_double vd;
register struct dbl_limits *lim;
int i;
#endif
 
switch (xdrs->x_op) {
 
case XDR_ENCODE:
#ifdef vax
vd = *((struct vax_double *)dp);
for (i = 0, lim = dbl_limits;
i < sizeof(dbl_limits)/sizeof(struct dbl_limits);
i++, lim++) {
if ((vd.mantissa4 == lim->d.mantissa4) &&
(vd.mantissa3 == lim->d.mantissa3) &&
(vd.mantissa2 == lim->d.mantissa2) &&
(vd.mantissa1 == lim->d.mantissa1) &&
(vd.exp == lim->d.exp)) {
id = lim->ieee;
goto shipit;
}
}
id.exp = vd.exp - VAX_DBL_BIAS + IEEE_DBL_BIAS;
id.mantissa1 = (vd.mantissa1 << 13) | (vd.mantissa2 >> 3);
id.mantissa2 = ((vd.mantissa2 & MASK(3)) << 29) |
(vd.mantissa3 << 13) |
((vd.mantissa4 >> 3) & MASK(13));
shipit:
id.sign = vd.sign;
dp = (double *)&id;
#endif
if (2*sizeof(long) == sizeof(double)) {
long *lp = (long *)dp;
return (XDR_PUTLONG(xdrs, lp+!LSW) &&
XDR_PUTLONG(xdrs, lp+LSW));
} else if (2*sizeof(int) == sizeof(double)) {
int *ip = (int *)dp;
long tmp[2];
tmp[0] = ip[!LSW];
tmp[1] = ip[LSW];
return (XDR_PUTLONG(xdrs, tmp) &&
XDR_PUTLONG(xdrs, tmp+1));
}
break;
 
case XDR_DECODE:
#ifdef vax
lp = (long *)&id;
if (!XDR_GETLONG(xdrs, lp++) || !XDR_GETLONG(xdrs, lp))
return (FALSE);
for (i = 0, lim = dbl_limits;
i < sizeof(dbl_limits)/sizeof(struct dbl_limits);
i++, lim++) {
if ((id.mantissa2 == lim->ieee.mantissa2) &&
(id.mantissa1 == lim->ieee.mantissa1) &&
(id.exp == lim->ieee.exp)) {
vd = lim->d;
goto doneit;
}
}
vd.exp = id.exp - IEEE_DBL_BIAS + VAX_DBL_BIAS;
vd.mantissa1 = (id.mantissa1 >> 13);
vd.mantissa2 = ((id.mantissa1 & MASK(13)) << 3) |
(id.mantissa2 >> 29);
vd.mantissa3 = (id.mantissa2 >> 13);
vd.mantissa4 = (id.mantissa2 << 3);
doneit:
vd.sign = id.sign;
*dp = *((double *)&vd);
return (TRUE);
#else
if (2*sizeof(long) == sizeof(double)) {
long *lp = (long *)dp;
return (XDR_GETLONG(xdrs, lp+!LSW) &&
XDR_GETLONG(xdrs, lp+LSW));
} else if (2*sizeof(int) == sizeof(double)) {
int *ip = (int *)dp;
long tmp[2];
if (XDR_GETLONG(xdrs, tmp+!LSW) &&
XDR_GETLONG(xdrs, tmp+LSW)) {
ip[0] = tmp[0];
ip[1] = tmp[1];
return (TRUE);
}
}
break;
#endif
 
case XDR_FREE:
return (TRUE);
}
return (FALSE);
}
/rpc/pmap_prot2.c
0,0 → 1,118
/* @(#)pmap_prot2.c 2.1 88/07/29 4.0 RPCSRC */
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
* media and as a part of the software program in whole or part. Users
* may copy or modify Sun RPC without charge, but are not authorized
* to license or distribute it to anyone else except as part of a product or
* program developed by the user.
*
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun RPC is provided with no support and without any obligation on the
* part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
#if 0
static char sccsid[] = "@(#)pmap_prot2.c 1.3 87/08/11 Copyr 1984 Sun Micro";
#endif
 
/*
* pmap_prot2.c
* Protocol for the local binder service, or pmap.
*
* Copyright (C) 1984, Sun Microsystems, Inc.
*/
 
#include <rpc/types.h>
#include <rpc/xdr.h>
#include <rpc/pmap_prot.h>
 
 
/*
* What is going on with linked lists? (!)
* First recall the link list declaration from pmap_prot.h:
*
* struct pmaplist {
* struct pmap pml_map;
* struct pmaplist *pml_map;
* };
*
* Compare that declaration with a corresponding xdr declaration that
* is (a) pointer-less, and (b) recursive:
*
* typedef union switch (bool_t) {
*
* case TRUE: struct {
* struct pmap;
* pmaplist_t foo;
* };
*
* case FALSE: struct {};
* } pmaplist_t;
*
* Notice that the xdr declaration has no nxt pointer while
* the C declaration has no bool_t variable. The bool_t can be
* interpreted as ``more data follows me''; if FALSE then nothing
* follows this bool_t; if TRUE then the bool_t is followed by
* an actual struct pmap, and then (recursively) by the
* xdr union, pamplist_t.
*
* This could be implemented via the xdr_union primitive, though this
* would cause a one recursive call per element in the list. Rather than do
* that we can ``unwind'' the recursion
* into a while loop and do the union arms in-place.
*
* The head of the list is what the C programmer wishes to past around
* the net, yet is the data that the pointer points to which is interesting;
* this sounds like a job for xdr_reference!
*/
bool_t
xdr_pmaplist (xdrs, rp)
XDR *xdrs;
struct pmaplist **rp;
{
/*
* more_elements is pre-computed in case the direction is
* XDR_ENCODE or XDR_FREE. more_elements is overwritten by
* xdr_bool when the direction is XDR_DECODE.
*/
bool_t more_elements;
int freeing = (xdrs->x_op == XDR_FREE);
struct pmaplist **next = NULL;
 
while (TRUE)
{
more_elements = (bool_t) (*rp != NULL);
if (!xdr_bool (xdrs, &more_elements))
return FALSE;
if (!more_elements)
return TRUE; /* we are done */
/*
* the unfortunate side effect of non-recursion is that in
* the case of freeing we must remember the next object
* before we free the current object ...
*/
if (freeing)
next = &((*rp)->pml_next);
if (!xdr_reference (xdrs, (caddr_t *) rp,
(u_int) sizeof (struct pmaplist),
(xdrproc_t) xdr_pmap))
return FALSE;
rp = freeing ? next : &((*rp)->pml_next);
}
}
/rpc/rpc_private.h
0,0 → 1,54
#ifndef _RPC_RPC_H
#include <rpc/rpc.h>
 
/* Now define the internal interfaces. */
extern unsigned long _create_xid (void);
 
/*
* Multi-threaded support
* Group all global and static variables into a single spot.
* This area is allocated on a per-thread basis
*/
#ifdef __UCLIBC_HAS_THREADS__
#include <pthread.h>
struct rpc_thread_variables {
fd_set svc_fdset_s; /* Global, rpc_common.c */
struct rpc_createerr rpc_createerr_s; /* Global, rpc_common.c */
struct pollfd *svc_pollfd_s; /* Global, rpc_common.c */
int svc_max_pollfd_s; /* Global, rpc_common.c */
 
void *authnone_private_s; /* auth_none.c */
 
void *clnt_perr_buf_s; /* clnt_perr.c */
 
void *clntraw_private_s; /* clnt_raw.c */
 
void *callrpc_private_s; /* clnt_simp.c */
 
void *key_call_private_s; /* key_call.c */
 
void *authdes_cache_s; /* svcauth_des.c */
void *authdes_lru_s; /* svcauth_des.c */
 
void *svc_xports_s; /* svc.c */
void *svc_head_s; /* svc.c */
 
void *svcraw_private_s; /* svc_raw.c */
 
void *svcsimple_proglst_s; /* svc_simple.c */
void *svcsimple_transp_s; /* svc_simple.c */
};
 
extern struct rpc_thread_variables *__rpc_thread_variables(void)
__attribute__ ((const));
extern void __rpc_thread_svc_cleanup (void);
extern void __rpc_thread_clnt_cleanup (void);
extern void __rpc_thread_key_cleanup (void);
 
extern void __rpc_thread_destroy (void);
 
#define RPC_THREAD_VARIABLE(x) (__rpc_thread_variables()->x)
 
#endif /* __UCLIBC_HAS_THREADS__ */
 
#endif
/rpc/rcmd.c
0,0 → 1,704
/*
* Copyright (c) 1983, 1993, 1994
* 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.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 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 0
static char sccsid[] = "@(#)rcmd.c 8.3 (Berkeley) 3/26/94";
#endif /* LIBC_SCCS and not lint */
 
#define __FORCE_GLIBC
#include <features.h>
 
#define __USE_GNU
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <alloca.h>
#include <signal.h>
#include <fcntl.h>
#include <unistd.h>
#include <pwd.h>
#include <sys/param.h>
#include <sys/poll.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
 
#ifdef __UCLIBC_HAS_THREADS__
#undef __UCLIBC_HAS_THREADS__
#warning FIXME I am not reentrant yet...
#endif
 
 
/* some forward declarations */
static int __ivaliduser2(FILE *hostf, u_int32_t raddr,
const char *luser, const char *ruser, const char *rhost);
static int iruserok2 (u_int32_t raddr, int superuser, const char *ruser,
const char *luser, const char *rhost);
 
 
int rcmd(ahost, rport, locuser, remuser, cmd, fd2p)
char **ahost;
u_short rport;
const char *locuser, *remuser, *cmd;
int *fd2p;
{
#ifdef __UCLIBC_HAS_THREADS__
int herr;
struct hostent hostbuf;
size_t hstbuflen;
char *tmphstbuf;
#endif
struct hostent *hp;
struct sockaddr_in sin, from;
struct pollfd pfd[2];
int32_t oldmask;
pid_t pid;
int s, lport, timo;
char c;
 
pid = getpid();
 
#ifdef __UCLIBC_HAS_THREADS__
hstbuflen = 1024;
#ifdef __UCLIBC_HAS_MMU__
tmphstbuf = alloca (hstbuflen);
#else
tmphstbuf = malloc (hstbuflen);
#endif
 
while (gethostbyname_r (*ahost, &hostbuf, tmphstbuf,
hstbuflen, &hp, &herr) != 0 || hp == NULL)
{
if (herr != NETDB_INTERNAL || errno != ERANGE)
{
__set_h_errno (herr);
#ifndef __UCLIBC_HAS_MMU__
free(tmphstbuf);
#endif
herror(*ahost);
return -1;
}
else
{
/* Enlarge the buffer. */
hstbuflen *= 2;
#ifdef __UCLIBC_HAS_MMU__
tmphstbuf = alloca (hstbuflen);
#else
if (tmphstbuf) {
free(tmphstbuf);
}
tmphstbuf = malloc (hstbuflen);
#endif
}
}
#ifndef __UCLIBC_HAS_MMU__
free(tmphstbuf);
#endif
#else /* call the non-reentrant version */
if ((hp = gethostbyname(*ahost)) == NULL) {
return -1;
}
#endif
pfd[0].events = POLLIN;
pfd[1].events = POLLIN;
*ahost = hp->h_name;
oldmask = sigblock(sigmask(SIGURG)); /* __sigblock */
for (timo = 1, lport = IPPORT_RESERVED - 1;;) {
s = rresvport(&lport);
if (s < 0) {
if (errno == EAGAIN)
(void)fprintf(stderr,
"rcmd: socket: All ports in use\n");
else
(void)fprintf(stderr, "rcmd: socket: %m\n");
sigsetmask(oldmask); /* sigsetmask */
return -1;
}
fcntl(s, F_SETOWN, pid); /* __fcntl */
sin.sin_family = hp->h_addrtype;
bcopy(hp->h_addr_list[0], &sin.sin_addr,
MIN (sizeof (sin.sin_addr), hp->h_length));
sin.sin_port = rport;
if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) >= 0) /* __connect */
break;
(void)close(s); /* __close */
if (errno == EADDRINUSE) {
lport--;
continue;
}
if (errno == ECONNREFUSED && timo <= 16) {
(void)sleep(timo); /* __sleep */
timo *= 2;
continue;
}
if (hp->h_addr_list[1] != NULL) {
int oerrno = errno;
 
(void)fprintf(stderr, "connect to address %s: ",
inet_ntoa(sin.sin_addr));
__set_errno (oerrno);
perror(0);
hp->h_addr_list++;
bcopy(hp->h_addr_list[0], &sin.sin_addr,
MIN (sizeof (sin.sin_addr), hp->h_length));
(void)fprintf(stderr, "Trying %s...\n",
inet_ntoa(sin.sin_addr));
continue;
}
(void)fprintf(stderr, "%s: %m\n", hp->h_name);
sigsetmask(oldmask); /* __sigsetmask */
return -1;
}
lport--;
if (fd2p == 0) {
write(s, "", 1); /* __write */
lport = 0;
} else {
char num[8];
int s2 = rresvport(&lport), s3;
socklen_t len = sizeof(from);
 
if (s2 < 0)
goto bad;
listen(s2, 1);
(void)snprintf(num, sizeof(num), "%d", lport); /* __snprintf */
if (write(s, num, strlen(num)+1) != strlen(num)+1) {
(void)fprintf(stderr,
"rcmd: write (setting up stderr): %m\n");
(void)close(s2); /* __close */
goto bad;
}
pfd[0].fd = s;
pfd[1].fd = s2;
__set_errno (0);
if (poll (pfd, 2, -1) < 1 || (pfd[1].revents & POLLIN) == 0){
if (errno != 0)
(void)fprintf(stderr, "rcmd: poll (setting up stderr): %m\n");
else
(void)fprintf(stderr, "poll: protocol failure in circuit setup\n");
(void)close(s2);
goto bad;
}
s3 = accept(s2, (struct sockaddr *)&from, &len);
(void)close(s2);
if (s3 < 0) {
(void)fprintf(stderr,
"rcmd: accept: %m\n");
lport = 0;
goto bad;
}
*fd2p = s3;
from.sin_port = ntohs((u_short)from.sin_port);
if (from.sin_family != AF_INET ||
from.sin_port >= IPPORT_RESERVED ||
from.sin_port < IPPORT_RESERVED / 2) {
(void)fprintf(stderr,
"socket: protocol failure in circuit setup\n");
goto bad2;
}
}
(void)write(s, locuser, strlen(locuser)+1);
(void)write(s, remuser, strlen(remuser)+1);
(void)write(s, cmd, strlen(cmd)+1);
if (read(s, &c, 1) != 1) {
(void)fprintf(stderr,
"rcmd: %s: %m\n", *ahost);
goto bad2;
}
if (c != 0) {
while (read(s, &c, 1) == 1) {
(void)write(STDERR_FILENO, &c, 1);
if (c == '\n')
break;
}
goto bad2;
}
sigsetmask(oldmask);
return s;
bad2:
if (lport)
(void)close(*fd2p);
bad:
(void)close(s);
sigsetmask(oldmask);
return -1;
}
 
int rresvport(int *alport)
{
struct sockaddr_in sin;
int s;
 
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = INADDR_ANY;
s = socket(AF_INET, SOCK_STREAM, 0);
if (s < 0)
return -1;
for (;;) {
sin.sin_port = htons((u_short)*alport);
if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) >= 0)
return s;
if (errno != EADDRINUSE) {
(void)close(s);
return -1;
}
(*alport)--;
if (*alport == IPPORT_RESERVED/2) {
(void)close(s);
__set_errno (EAGAIN); /* close */
return -1;
}
}
return -1;
}
 
int __check_rhosts_file = 1;
char *__rcmd_errstr;
 
int ruserok(rhost, superuser, ruser, luser)
const char *rhost, *ruser, *luser;
int superuser;
{
struct hostent *hp;
u_int32_t addr;
char **ap;
#ifdef __UCLIBC_HAS_THREADS__
size_t buflen;
char *buffer;
int herr;
struct hostent hostbuf;
#endif
 
#ifdef __UCLIBC_HAS_THREADS__
buflen = 1024;
#ifdef __UCLIBC_HAS_MMU__
buffer = alloca (buflen);
#else
buffer = malloc (buflen);
#endif
 
while (gethostbyname_r (rhost, &hostbuf, buffer,
buflen, &hp, &herr) != 0 || hp == NULL)
{
if (herr != NETDB_INTERNAL || errno != ERANGE) {
#ifndef __UCLIBC_HAS_MMU__
free(buffer);
#endif
return -1;
} else
{
/* Enlarge the buffer. */
buflen *= 2;
#ifdef __UCLIBC_HAS_MMU__
buffer = alloca (buflen);
#else
if (buffer) {
free(buffer);
}
buffer = malloc (buflen);
#endif
}
}
#ifndef __UCLIBC_HAS_MMU__
free(buffer);
#endif
#else
if ((hp = gethostbyname(rhost)) == NULL) {
return -1;
}
#endif
for (ap = hp->h_addr_list; *ap; ++ap) {
bcopy(*ap, &addr, sizeof(addr));
if (iruserok2(addr, superuser, ruser, luser, rhost) == 0)
return 0;
}
return -1;
}
 
 
/* Extremely paranoid file open function. */
static FILE *
iruserfopen (char *file, uid_t okuser)
{
struct stat st;
char *cp = NULL;
FILE *res = NULL;
 
/* If not a regular file, if owned by someone other than user or
root, if writeable by anyone but the owner, or if hardlinked
anywhere, quit. */
cp = NULL;
if (lstat (file, &st))
cp = "lstat failed";
else if (!S_ISREG (st.st_mode))
cp = "not regular file";
else
{
res = fopen (file, "r");
if (!res)
cp = "cannot open";
else if (fstat (fileno (res), &st) < 0)
cp = "fstat failed";
else if (st.st_uid && st.st_uid != okuser)
cp = "bad owner";
else if (st.st_mode & (S_IWGRP|S_IWOTH))
cp = "writeable by other than owner";
else if (st.st_nlink > 1)
cp = "hard linked somewhere";
}
 
/* If there were any problems, quit. */
if (cp != NULL)
{
__rcmd_errstr = cp;
if (res)
fclose (res);
return NULL;
}
 
return res;
}
 
 
/*
* New .rhosts strategy: We are passed an ip address. We spin through
* hosts.equiv and .rhosts looking for a match. When the .rhosts only
* has ip addresses, we don't have to trust a nameserver. When it
* contains hostnames, we spin through the list of addresses the nameserver
* gives us and look for a match.
*
* Returns 0 if ok, -1 if not ok.
*/
static int
iruserok2 (raddr, superuser, ruser, luser, rhost)
u_int32_t raddr;
int superuser;
const char *ruser, *luser, *rhost;
{
FILE *hostf = NULL;
int isbad = -1;
 
if (!superuser)
hostf = iruserfopen (_PATH_HEQUIV, 0);
if (hostf) {
isbad = __ivaliduser2 (hostf, raddr, luser, ruser, rhost);
fclose (hostf);
 
if (!isbad)
return 0;
}
 
if (__check_rhosts_file || superuser) {
char *pbuf;
struct passwd *pwd;
size_t dirlen;
uid_t uid;
 
#ifdef __UCLIBC_HAS_THREADS__
size_t buflen = sysconf (_SC_GETPW_R_SIZE_MAX);
struct passwd pwdbuf;
#ifdef __UCLIBC_HAS_MMU__
char *buffer = alloca (buflen);
#else
char *buffer = malloc (buflen);
#endif
 
if (getpwnam_r (luser, &pwdbuf, buffer,
buflen, &pwd) != 0 || pwd == NULL)
{
#ifndef __UCLIBC_HAS_MMU__
free(buffer);
#endif
return -1;
}
#ifndef __UCLIBC_HAS_MMU__
free(buffer);
#endif
#else
if ((pwd = getpwnam(luser)) == NULL)
return -1;
#endif
 
dirlen = strlen (pwd->pw_dir);
pbuf = malloc (dirlen + sizeof "/.rhosts");
strcpy (pbuf, pwd->pw_dir);
strcat (pbuf, "/.rhosts");
 
/* Change effective uid while reading .rhosts. If root and
reading an NFS mounted file system, can't read files that
are protected read/write owner only. */
uid = geteuid ();
seteuid (pwd->pw_uid);
hostf = iruserfopen (pbuf, pwd->pw_uid);
free(pbuf);
if (hostf != NULL) {
isbad = __ivaliduser2 (hostf, raddr, luser, ruser, rhost);
fclose (hostf);
}
seteuid (uid);
return isbad;
}
return -1;
}
 
/* This is the exported version. */
int iruserok (u_int32_t raddr, int superuser, const char * ruser, const char * luser)
{
return iruserok2 (raddr, superuser, ruser, luser, "-");
}
 
 
/*
* XXX
* Don't make static, used by lpd(8).
*
* This function is not used anymore. It is only present because lpd(8)
* calls it (!?!). We simply call __invaliduser2() with an illegal rhost
* argument. This means that netgroups won't work in .rhost/hosts.equiv
* files. If you want lpd to work with netgroups, fix lpd to use ruserok()
* or PAM.
* Returns 0 if ok, -1 if not ok.
*/
int
__ivaliduser(FILE *hostf, u_int32_t raddr, const char *luser, const char *ruser)
{
return __ivaliduser2(hostf, raddr, luser, ruser, "-");
}
 
 
/* Returns 1 on positive match, 0 on no match, -1 on negative match. */
static int
__icheckhost (u_int32_t raddr, char *lhost, const char *rhost)
{
struct hostent *hp;
u_int32_t laddr;
int negate=1; /* Multiply return with this to get -1 instead of 1 */
char **pp;
 
#ifdef __UCLIBC_HAS_THREADS__
int save_errno;
size_t buflen;
char *buffer;
struct hostent hostbuf;
int herr;
#endif
 
#ifdef HAVE_NETGROUP
/* Check nis netgroup. */
if (strncmp ("+@", lhost, 2) == 0)
return innetgr (&lhost[2], rhost, NULL, NULL);
 
if (strncmp ("-@", lhost, 2) == 0)
return -innetgr (&lhost[2], rhost, NULL, NULL);
#endif /* HAVE_NETGROUP */
 
/* -host */
if (strncmp ("-", lhost,1) == 0) {
negate = -1;
lhost++;
} else if (strcmp ("+",lhost) == 0) {
return 1; /* asking for trouble, but ok.. */
}
 
/* Try for raw ip address first. */
if (isdigit (*lhost) && (laddr = inet_addr (lhost)) != INADDR_NONE)
return negate * (! (raddr ^ laddr));
 
/* Better be a hostname. */
#ifdef __UCLIBC_HAS_THREADS__
buflen = 1024;
buffer = malloc(buflen);
save_errno = errno;
 
while (gethostbyname_r (lhost, &hostbuf, buffer, buflen, &hp, &herr)
!= 0) {
free(buffer);
return (0);
}
free(buffer);
__set_errno (save_errno);
#else
hp = gethostbyname(lhost);
#endif /* __UCLIBC_HAS_THREADS__ */
 
if (hp == NULL)
return 0;
 
/* Spin through ip addresses. */
for (pp = hp->h_addr_list; *pp; ++pp)
if (!memcmp (&raddr, *pp, sizeof (u_int32_t)))
return negate;
 
/* No match. */
return (0);
}
 
/* Returns 1 on positive match, 0 on no match, -1 on negative match. */
static int
__icheckuser (const char *luser, const char *ruser)
{
 
/*
luser is user entry from .rhosts/hosts.equiv file
ruser is user id on remote host
*/
 
#ifdef HAVE_NETGROUP
/* [-+]@netgroup */
if (strncmp ("+@", luser, 2) == 0)
return innetgr (&luser[2], NULL, ruser, NULL);
 
if (strncmp ("-@", luser,2) == 0)
return -innetgr (&luser[2], NULL, ruser, NULL);
#endif /* HAVE_NETGROUP */
 
/* -user */
if (strncmp ("-", luser, 1) == 0)
return -(strcmp (&luser[1], ruser) == 0);
 
/* + */
if (strcmp ("+", luser) == 0)
return 1;
 
/* simple string match */
return strcmp (ruser, luser) == 0;
}
 
/*
* Returns 1 for blank lines (or only comment lines) and 0 otherwise
*/
static int
__isempty(char *p)
{
while (*p && isspace (*p)) {
++p;
}
 
return (*p == '\0' || *p == '#') ? 1 : 0 ;
}
 
/*
* Returns 0 if positive match, -1 if _not_ ok.
*/
static int
__ivaliduser2(hostf, raddr, luser, ruser, rhost)
FILE *hostf;
u_int32_t raddr;
const char *luser, *ruser, *rhost;
{
register const char *user;
register char *p;
int hcheck, ucheck;
char *buf = NULL;
size_t bufsize = 0;
int retval = -1;
 
while (getline (&buf, &bufsize, hostf) > 0) {
buf[bufsize - 1] = '\0'; /* Make sure it's terminated. */
p = buf;
 
/* Skip empty or comment lines */
if (__isempty (p)) {
continue;
}
 
/* Skip lines that are too long. */
if (strchr (p, '\n') == NULL) {
int ch = getc_unlocked (hostf);
 
while (ch != '\n' && ch != EOF)
ch = getc_unlocked (hostf);
continue;
}
 
for (;*p && !isspace(*p); ++p) {
*p = tolower (*p);
}
 
/* Next we want to find the permitted name for the remote user. */
if (*p == ' ' || *p == '\t') {
/* <nul> terminate hostname and skip spaces */
for (*p++='\0'; *p && isspace (*p); ++p);
 
user = p; /* this is the user's name */
while (*p && !isspace (*p))
++p; /* find end of user's name */
} else
user = p;
 
*p = '\0'; /* <nul> terminate username (+host?) */
 
/* buf -> host(?) ; user -> username(?) */
 
/* First check host part */
hcheck = __icheckhost (raddr, buf, rhost);
 
if (hcheck < 0)
break;
 
if (hcheck) {
/* Then check user part */
if (! (*user))
user = luser;
 
ucheck = __icheckuser (user, ruser);
 
/* Positive 'host user' match? */
if (ucheck > 0) {
retval = 0;
break;
}
 
/* Negative 'host -user' match? */
if (ucheck < 0)
break;
 
/* Neither, go on looking for match */
}
}
 
if (buf != NULL)
free (buf);
 
return retval;
}
/rpc/rpc_commondata.c
0,0 → 1,47
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
* media and as a part of the software program in whole or part. Users
* may copy or modify Sun RPC without charge, but are not authorized
* to license or distribute it to anyone else except as part of a product or
* program developed by the user.
*
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun RPC is provided with no support and without any obligation on the
* part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
#include <rpc/rpc.h>
#include <sys/poll.h>
#include <sys/select.h>
 
#undef svc_fdset
#undef rpc_createerr
#undef svc_pollfd
#undef svc_max_pollfd
 
 
/*
* This file should only contain common data (global data) that is exported
* by public interfaces
*/
struct opaque_auth _null_auth;
fd_set svc_fdset;
struct rpc_createerr rpc_createerr;
struct pollfd *svc_pollfd;
int svc_max_pollfd;
/rpc/ruserpass.c
0,0 → 1,329
/*
* Copyright (c) 1985, 1993, 1994
* 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.
*/
 
#define __FORCE_GLIBC
#include <features.h>
#include <sys/types.h>
#include <sys/stat.h>
 
#include <ctype.h>
#include <err.h>
#include <errno.h>
#include <netdb.h>
#include <stdio.h>
#include <stdio_ext.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
 
#define _(X) (X)
/* #include "ftp_var.h" */
 
static int token (void);
static FILE *cfile;
 
#define DEFAULT 1
#define LOGIN 2
#define PASSWD 3
#define ACCOUNT 4
#define MACDEF 5
#define ID 10
#define MACHINE 11
 
static char tokval[100];
 
static const char tokstr[] =
{
#define TOK_DEFAULT_IDX 0
"default\0"
#define TOK_LOGIN_IDX (TOK_DEFAULT_IDX + sizeof "default")
"login\0"
#define TOK_PASSWORD_IDX (TOK_LOGIN_IDX + sizeof "login")
"password\0"
#define TOK_PASSWD_IDX (TOK_PASSWORD_IDX + sizeof "password")
"passwd\0"
#define TOK_ACCOUNT_IDX (TOK_PASSWD_IDX + sizeof "passwd")
"account\0"
#define TOK_MACHINE_IDX (TOK_ACCOUNT_IDX + sizeof "account")
"machine\0"
#define TOK_MACDEF_IDX (TOK_MACHINE_IDX + sizeof "machine")
"macdef"
};
 
static const struct toktab {
int tokstr_off;
int tval;
} toktab[]= {
{ TOK_DEFAULT_IDX, DEFAULT },
{ TOK_LOGIN_IDX, LOGIN },
{ TOK_PASSWORD_IDX, PASSWD },
{ TOK_PASSWD_IDX, PASSWD },
{ TOK_ACCOUNT_IDX, ACCOUNT },
{ TOK_MACHINE_IDX, MACHINE },
{ TOK_MACDEF_IDX, MACDEF }
};
 
 
 
int ruserpass(const char *host, const char **aname, const char **apass)
{
char *hdir, *buf, *tmp;
char myname[1024], *mydomain;
int t, usedefault = 0;
struct stat stb;
 
/* Give up when running a setuid or setgid app. */
if ((getuid() != geteuid()) || getgid() != getegid())
return -1;
hdir = getenv("HOME");
if (hdir == NULL) {
/* If we can't get HOME, fail instead of trying ".",
which is no improvement. */
return -1;
}
 
buf = alloca (strlen(hdir) + 8);
strcpy(buf, hdir);
strcat(buf, "/.netrc");
cfile = fopen(buf, "r");
if (cfile == NULL) {
if (errno != ENOENT)
printf("%s", buf);
return (0);
}
/* No threads use this stream. */
#ifdef __UCLIBC_HAS_THREADS__
__fsetlocking (cfile, FSETLOCKING_BYCALLER);
#endif
if (gethostname(myname, sizeof(myname)) < 0)
myname[0] = '\0';
mydomain = strchr(myname, '.');
if (mydomain==NULL) {
mydomain=myname + strlen(myname);
}
next:
while ((t = token())) switch(t) {
 
case DEFAULT:
usedefault = 1;
/* FALL THROUGH */
 
case MACHINE:
if (!usedefault) {
if (token() != ID)
continue;
/*
* Allow match either for user's input host name
* or official hostname. Also allow match of
* incompletely-specified host in local domain.
*/
if (strcasecmp(host, tokval) == 0)
goto match;
/* if (__strcasecmp(hostname, tokval) == 0)
goto match;
if ((tmp = strchr(hostname, '.')) != NULL &&
__strcasecmp(tmp, mydomain) == 0 &&
__strncasecmp(hostname, tokval, tmp-hostname) == 0 &&
tokval[tmp - hostname] == '\0')
goto match; */
if ((tmp = strchr(host, '.')) != NULL &&
strcasecmp(tmp, mydomain) == 0 &&
strncasecmp(host, tokval, tmp - host) == 0 &&
tokval[tmp - host] == '\0')
goto match;
continue;
}
match:
while ((t = token()) && t != MACHINE && t != DEFAULT) switch(t) {
 
case LOGIN:
if (token()) {
if (*aname == 0) {
char *newp;
newp = malloc((unsigned) strlen(tokval) + 1);
if (newp == NULL)
{
printf(_("out of memory"));
goto bad;
}
*aname = strcpy(newp, tokval);
} else {
if (strcmp(*aname, tokval))
goto next;
}
}
break;
case PASSWD:
if (strcmp(*aname, "anonymous") &&
fstat(fileno(cfile), &stb) >= 0 &&
(stb.st_mode & 077) != 0) {
printf(_("Error: .netrc file is readable by others."));
printf(_("Remove password or make file unreadable by others."));
goto bad;
}
if (token() && *apass == 0) {
char *newp;
newp = malloc((unsigned) strlen(tokval) + 1);
if (newp == NULL)
{
printf(_("out of memory"));
goto bad;
}
*apass = strcpy(newp, tokval);
}
break;
case ACCOUNT:
#if 0
if (fstat(fileno(cfile), &stb) >= 0
&& (stb.st_mode & 077) != 0) {
printf("Error: .netrc file is readable by others.");
printf("Remove account or make file unreadable by others.");
goto bad;
}
if (token() && *aacct == 0) {
*aacct = malloc((unsigned) strlen(tokval) + 1);
(void) strcpy(*aacct, tokval);
}
#endif
break;
case MACDEF:
#if 0
if (proxy) {
(void) fclose(cfile);
return (0);
}
while ((c=getc_unlocked(cfile)) != EOF && c == ' '
|| c == '\t');
if (c == EOF || c == '\n') {
printf("Missing macdef name argument.\n");
goto bad;
}
if (macnum == 16) {
printf("Limit of 16 macros have already been defined\n");
goto bad;
}
tmp = macros[macnum].mac_name;
*tmp++ = c;
for (i=0; i < 8 && (c=getc_unlocked(cfile)) != EOF &&
!isspace(c); ++i) {
*tmp++ = c;
}
if (c == EOF) {
printf("Macro definition missing null line terminator.\n");
goto bad;
}
*tmp = '\0';
if (c != '\n') {
while ((c=getc_unlocked(cfile)) != EOF
&& c != '\n');
}
if (c == EOF) {
printf("Macro definition missing null line terminator.\n");
goto bad;
}
if (macnum == 0) {
macros[macnum].mac_start = macbuf;
}
else {
macros[macnum].mac_start = macros[macnum-1].mac_end + 1;
}
tmp = macros[macnum].mac_start;
while (tmp != macbuf + 4096) {
if ((c=getc_unlocked(cfile)) == EOF) {
printf("Macro definition missing null line terminator.\n");
goto bad;
}
*tmp = c;
if (*tmp == '\n') {
if (*(tmp-1) == '\0') {
macros[macnum++].mac_end = tmp - 1;
break;
}
*tmp = '\0';
}
tmp++;
}
if (tmp == macbuf + 4096) {
printf("4K macro buffer exceeded\n");
goto bad;
}
#endif
break;
default:
printf(_("Unknown .netrc keyword %s"), tokval);
break;
}
goto done;
}
done:
(void) fclose(cfile);
return (0);
bad:
(void) fclose(cfile);
return (-1);
}
 
static int
token()
{
char *cp;
int c;
int i;
 
if (feof_unlocked(cfile) || ferror_unlocked(cfile))
return (0);
while ((c = getc_unlocked(cfile)) != EOF &&
(c == '\n' || c == '\t' || c == ' ' || c == ','))
continue;
if (c == EOF)
return (0);
cp = tokval;
if (c == '"') {
while ((c = getc_unlocked(cfile)) != EOF && c != '"') {
if (c == '\\')
c = getc_unlocked(cfile);
*cp++ = c;
}
} else {
*cp++ = c;
while ((c = getc_unlocked(cfile)) != EOF
&& c != '\n' && c != '\t' && c != ' ' && c != ',') {
if (c == '\\')
c = getc_unlocked(cfile);
*cp++ = c;
}
}
*cp = 0;
if (tokval[0] == 0)
return (0);
for (i = 0; i < (int) (sizeof (toktab) / sizeof (toktab[0])); ++i)
if (!strcmp(&tokstr[toktab[i].tokstr_off], tokval))
return toktab[i].tval;
return (ID);
}
/rpc/clnt_perror.c
0,0 → 1,432
/* @(#)clnt_perror.c 2.1 88/07/29 4.0 RPCSRC */
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
* media and as a part of the software program in whole or part. Users
* may copy or modify Sun RPC without charge, but are not authorized
* to license or distribute it to anyone else except as part of a product or
* program developed by the user.
*
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun RPC is provided with no support and without any obligation on the
* part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
#if 0
static char sccsid[] = "@(#)clnt_perror.c 1.15 87/10/07 Copyr 1984 Sun Micro";
#endif
 
/*
* clnt_perror.c
*
* Copyright (C) 1984, Sun Microsystems, Inc.
*
*/
#define __FORCE_GLIBC
#include <features.h>
 
#include <stdio.h>
#include <string.h>
#include "rpc_private.h"
 
#ifdef USE_IN_LIBIO
# include <wchar.h>
# include <libio/iolibio.h>
# define fputs(s, f) _IO_fputs (s, f)
#endif
 
static char *auth_errmsg (enum auth_stat stat) internal_function;
 
#ifdef __UCLIBC_HAS_THREADS__
/*
* Making buf a preprocessor macro requires renaming the local
* buf variable in a few functions. Overriding a global variable
* with a local variable of the same name is a bad idea, anyway.
*/
#define buf ((char *)RPC_THREAD_VARIABLE(clnt_perr_buf_s))
#else
static char *buf;
#endif
 
static char *
_buf (void)
{
if (buf == NULL)
buf = (char *) malloc (256);
return buf;
}
 
/*
* Print reply error info
*/
char *
clnt_sperror (CLIENT * rpch, const char *msg)
{
char chrbuf[1024];
struct rpc_err e;
char *err;
char *str = _buf ();
char *strstart = str;
int len;
 
if (str == NULL)
return NULL;
CLNT_GETERR (rpch, &e);
 
len = sprintf (str, "%s: ", msg);
str += len;
 
(void) strcpy(str, clnt_sperrno(e.re_status));
str += strlen(str);
 
switch (e.re_status)
{
case RPC_SUCCESS:
case RPC_CANTENCODEARGS:
case RPC_CANTDECODERES:
case RPC_TIMEDOUT:
case RPC_PROGUNAVAIL:
case RPC_PROCUNAVAIL:
case RPC_CANTDECODEARGS:
case RPC_SYSTEMERROR:
case RPC_UNKNOWNHOST:
case RPC_UNKNOWNPROTO:
case RPC_PMAPFAILURE:
case RPC_PROGNOTREGISTERED:
case RPC_FAILED:
break;
 
case RPC_CANTSEND:
case RPC_CANTRECV:
strerror_r (e.re_errno, chrbuf, sizeof chrbuf);
len = sprintf (str, "; errno = %s", chrbuf);
str += len;
break;
 
case RPC_VERSMISMATCH:
len= sprintf (str, _("; low version = %lu, high version = %lu"),
e.re_vers.low, e.re_vers.high);
str += len;
break;
 
case RPC_AUTHERROR:
err = auth_errmsg (e.re_why);
(void) strcpy(str, _("; why = "));
str += strlen(str);
 
if (err != NULL)
{
(void) strcpy(str, err);
str += strlen(str);
}
else
{
len = sprintf (str, _("(unknown authentication error - %d)"),
(int) e.re_why);
str += len;
}
break;
 
case RPC_PROGVERSMISMATCH:
len = sprintf (str, _("; low version = %lu, high version = %lu"),
e.re_vers.low, e.re_vers.high);
str += len;
break;
 
default: /* unknown */
len = sprintf (str, "; s1 = %lu, s2 = %lu", e.re_lb.s1, e.re_lb.s2);
str += len;
break;
}
*str = '\n';
*++str = '\0';
return (strstart);
}
 
void
clnt_perror (CLIENT * rpch, const char *msg)
{
#ifdef USE_IN_LIBIO
if (_IO_fwide (stderr, 0) > 0)
(void) __fwprintf (stderr, L"%s", clnt_sperror (rpch, msg));
else
#endif
(void) fputs (clnt_sperror (rpch, msg), stderr);
}
 
 
struct rpc_errtab
{
enum clnt_stat status;
unsigned int message_off;
};
 
static const char rpc_errstr[] =
{
#define RPC_SUCCESS_IDX 0
_("RPC: Success")
"\0"
#define RPC_CANTENCODEARGS_IDX (RPC_SUCCESS_IDX + sizeof "RPC: Success")
_("RPC: Can't encode arguments")
"\0"
#define RPC_CANTDECODERES_IDX (RPC_CANTENCODEARGS_IDX \
+ sizeof "RPC: Can't encode arguments")
_("RPC: Can't decode result")
"\0"
#define RPC_CANTSEND_IDX (RPC_CANTDECODERES_IDX \
+ sizeof "RPC: Can't decode result")
_("RPC: Unable to send")
"\0"
#define RPC_CANTRECV_IDX (RPC_CANTSEND_IDX \
+ sizeof "RPC: Unable to send")
_("RPC: Unable to receive")
"\0"
#define RPC_TIMEDOUT_IDX (RPC_CANTRECV_IDX \
+ sizeof "RPC: Unable to receive")
_("RPC: Timed out")
"\0"
#define RPC_VERSMISMATCH_IDX (RPC_TIMEDOUT_IDX \
+ sizeof "RPC: Timed out")
_("RPC: Incompatible versions of RPC")
"\0"
#define RPC_AUTHERROR_IDX (RPC_VERSMISMATCH_IDX \
+ sizeof "RPC: Incompatible versions of RPC")
_("RPC: Authentication error")
"\0"
#define RPC_PROGUNAVAIL_IDX (RPC_AUTHERROR_IDX \
+ sizeof "RPC: Authentication error")
_("RPC: Program unavailable")
"\0"
#define RPC_PROGVERSMISMATCH_IDX (RPC_PROGUNAVAIL_IDX \
+ sizeof "RPC: Program unavailable")
_("RPC: Program/version mismatch")
"\0"
#define RPC_PROCUNAVAIL_IDX (RPC_PROGVERSMISMATCH_IDX \
+ sizeof "RPC: Program/version mismatch")
_("RPC: Procedure unavailable")
"\0"
#define RPC_CANTDECODEARGS_IDX (RPC_PROCUNAVAIL_IDX \
+ sizeof "RPC: Procedure unavailable")
_("RPC: Server can't decode arguments")
"\0"
#define RPC_SYSTEMERROR_IDX (RPC_CANTDECODEARGS_IDX \
+ sizeof "RPC: Server can't decode arguments")
_("RPC: Remote system error")
"\0"
#define RPC_UNKNOWNHOST_IDX (RPC_SYSTEMERROR_IDX \
+ sizeof "RPC: Remote system error")
_("RPC: Unknown host")
"\0"
#define RPC_UNKNOWNPROTO_IDX (RPC_UNKNOWNHOST_IDX \
+ sizeof "RPC: Unknown host")
_("RPC: Unknown protocol")
"\0"
#define RPC_PMAPFAILURE_IDX (RPC_UNKNOWNPROTO_IDX \
+ sizeof "RPC: Unknown protocol")
_("RPC: Port mapper failure")
"\0"
#define RPC_PROGNOTREGISTERED_IDX (RPC_PMAPFAILURE_IDX \
+ sizeof "RPC: Port mapper failure")
_("RPC: Program not registered")
"\0"
#define RPC_FAILED_IDX (RPC_PROGNOTREGISTERED_IDX \
+ sizeof "RPC: Program not registered")
_("RPC: Failed (unspecified error)")
};
 
static const struct rpc_errtab rpc_errlist[] =
{
{ RPC_SUCCESS, RPC_SUCCESS_IDX },
{ RPC_CANTENCODEARGS, RPC_CANTENCODEARGS_IDX },
{ RPC_CANTDECODERES, RPC_CANTDECODERES_IDX },
{ RPC_CANTSEND, RPC_CANTSEND_IDX },
{ RPC_CANTRECV, RPC_CANTRECV_IDX },
{ RPC_TIMEDOUT, RPC_TIMEDOUT_IDX },
{ RPC_VERSMISMATCH, RPC_VERSMISMATCH_IDX },
{ RPC_AUTHERROR, RPC_AUTHERROR_IDX },
{ RPC_PROGUNAVAIL, RPC_PROGUNAVAIL_IDX },
{ RPC_PROGVERSMISMATCH, RPC_PROGVERSMISMATCH_IDX },
{ RPC_PROCUNAVAIL, RPC_PROCUNAVAIL_IDX },
{ RPC_CANTDECODEARGS, RPC_CANTDECODEARGS_IDX },
{ RPC_SYSTEMERROR, RPC_SYSTEMERROR_IDX },
{ RPC_UNKNOWNHOST, RPC_UNKNOWNHOST_IDX },
{ RPC_UNKNOWNPROTO, RPC_UNKNOWNPROTO_IDX },
{ RPC_PMAPFAILURE, RPC_PMAPFAILURE_IDX },
{ RPC_PROGNOTREGISTERED, RPC_PROGNOTREGISTERED_IDX },
{ RPC_FAILED, RPC_FAILED_IDX }
};
 
 
/*
* This interface for use by clntrpc
*/
char *
clnt_sperrno (enum clnt_stat stat)
{
size_t i;
 
for (i = 0; i < sizeof (rpc_errlist) / sizeof (struct rpc_errtab); i++)
{
if (rpc_errlist[i].status == stat)
{
return (char*)_(rpc_errstr + rpc_errlist[i].message_off);
}
}
return _("RPC: (unknown error code)");
}
 
void
clnt_perrno (enum clnt_stat num)
{
#ifdef USE_IN_LIBIO
if (_IO_fwide (stderr, 0) > 0)
(void) __fwprintf (stderr, L"%s", clnt_sperrno (num));
else
#endif
(void) fputs (clnt_sperrno (num), stderr);
}
 
 
char *
clnt_spcreateerror (const char *msg)
{
char chrbuf[1024];
char *str = _buf ();
char *cp;
int len;
struct rpc_createerr *ce;
 
if (str == NULL)
return NULL;
ce = &get_rpc_createerr ();
len = sprintf (str, "%s: ", msg);
cp = str + len;
(void) strcpy(cp, clnt_sperrno (ce->cf_stat));
cp += strlen(cp);
 
switch (ce->cf_stat)
{
case RPC_PMAPFAILURE:
(void) strcpy(cp, " - ");
cp += strlen(cp);
 
(void) strcpy(cp, clnt_sperrno (ce->cf_error.re_status));
cp += strlen(cp);
 
break;
 
case RPC_SYSTEMERROR:
(void) strcpy(cp, " - ");
cp += strlen(cp);
 
strerror_r (ce->cf_error.re_errno, chrbuf, sizeof chrbuf);
(void) strcpy(cp, chrbuf);
cp += strlen(cp);
break;
default:
break;
}
*cp = '\n';
*++cp = '\0';
return str;
}
 
void
clnt_pcreateerror (const char *msg)
{
#ifdef USE_IN_LIBIO
if (_IO_fwide (stderr, 0) > 0)
(void) __fwprintf (stderr, L"%s", clnt_spcreateerror (msg));
else
#endif
(void) fputs (clnt_spcreateerror (msg), stderr);
}
 
struct auth_errtab
{
enum auth_stat status;
unsigned int message_off;
};
 
static const char auth_errstr[] =
{
#define AUTH_OK_IDX 0
_("Authentication OK")
"\0"
#define AUTH_BADCRED_IDX (AUTH_OK_IDX + sizeof "Authentication OK")
_("Invalid client credential")
"\0"
#define AUTH_REJECTEDCRED_IDX (AUTH_BADCRED_IDX \
+ sizeof "Invalid client credential")
_("Server rejected credential")
"\0"
#define AUTH_BADVERF_IDX (AUTH_REJECTEDCRED_IDX \
+ sizeof "Server rejected credential")
_("Invalid client verifier")
"\0"
#define AUTH_REJECTEDVERF_IDX (AUTH_BADVERF_IDX \
+ sizeof "Invalid client verifier")
_("Server rejected verifier")
"\0"
#define AUTH_TOOWEAK_IDX (AUTH_REJECTEDVERF_IDX \
+ sizeof "Server rejected verifier")
_("Client credential too weak")
"\0"
#define AUTH_INVALIDRESP_IDX (AUTH_TOOWEAK_IDX \
+ sizeof "Client credential too weak")
_("Invalid server verifier")
"\0"
#define AUTH_FAILED_IDX (AUTH_INVALIDRESP_IDX \
+ sizeof "Invalid server verifier")
_("Failed (unspecified error)")
};
 
static const struct auth_errtab auth_errlist[] =
{
{ AUTH_OK, AUTH_OK_IDX },
{ AUTH_BADCRED, AUTH_BADCRED_IDX },
{ AUTH_REJECTEDCRED, AUTH_REJECTEDCRED_IDX },
{ AUTH_BADVERF, AUTH_BADVERF_IDX },
{ AUTH_REJECTEDVERF, AUTH_REJECTEDVERF_IDX },
{ AUTH_TOOWEAK, AUTH_TOOWEAK_IDX },
{ AUTH_INVALIDRESP, AUTH_INVALIDRESP_IDX },
{ AUTH_FAILED, AUTH_FAILED_IDX }
};
 
static char *
internal_function
auth_errmsg (enum auth_stat stat)
{
size_t i;
 
for (i = 0; i < sizeof (auth_errlist) / sizeof (struct auth_errtab); i++)
{
if (auth_errlist[i].status == stat)
{
return (char*)_(auth_errstr + auth_errlist[i].message_off);
}
}
return NULL;
}
 
 
static void __attribute__ ((unused))
free_mem (void)
{
free (buf);
}
/rpc/xdr_array.c
0,0 → 1,180
/* @(#)xdr_array.c 2.1 88/07/29 4.0 RPCSRC */
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
* media and as a part of the software program in whole or part. Users
* may copy or modify Sun RPC without charge, but are not authorized
* to license or distribute it to anyone else except as part of a product or
* program developed by the user.
*
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun RPC is provided with no support and without any obligation on the
* part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
#if 0
static char sccsid[] = "@(#)xdr_array.c 1.10 87/08/11 Copyr 1984 Sun Micro";
#endif
 
/*
* xdr_array.c, Generic XDR routines implementation.
*
* Copyright (C) 1984, Sun Microsystems, Inc.
*
* These are the "non-trivial" xdr primitives used to serialize and de-serialize
* arrays. See xdr.h for more info on the interface to xdr.
*/
 
#define __FORCE_GLIBC
#define _GNU_SOURCE
#include <features.h>
 
#include <stdio.h>
#include <string.h>
#include <rpc/types.h>
#include <rpc/xdr.h>
#include <limits.h>
 
#ifdef USE_IN_LIBIO
# include <wchar.h>
#endif
 
#define LASTUNSIGNED ((u_int)0-1)
 
 
/*
* XDR an array of arbitrary elements
* *addrp is a pointer to the array, *sizep is the number of elements.
* If addrp is NULL (*sizep * elsize) bytes are allocated.
* elsize is the size (in bytes) of each element, and elproc is the
* xdr procedure to call to handle each element of the array.
*/
bool_t
xdr_array (xdrs, addrp, sizep, maxsize, elsize, elproc)
XDR *xdrs;
caddr_t *addrp; /* array pointer */
u_int *sizep; /* number of elements */
u_int maxsize; /* max numberof elements */
u_int elsize; /* size in bytes of each element */
xdrproc_t elproc; /* xdr routine to handle each element */
{
u_int i;
caddr_t target = *addrp;
u_int c; /* the actual element count */
bool_t stat = TRUE;
u_int nodesize;
 
/* like strings, arrays are really counted arrays */
if (!xdr_u_int (xdrs, sizep))
{
return FALSE;
}
c = *sizep;
/*
* XXX: Let the overflow possibly happen with XDR_FREE because mem_free()
* doesn't actually use its second argument anyway.
*/
if ((c > maxsize || c > UINT_MAX / elsize) && (xdrs->x_op != XDR_FREE))
{
return FALSE;
}
nodesize = c * elsize;
 
/*
* if we are deserializing, we may need to allocate an array.
* We also save time by checking for a null array if we are freeing.
*/
if (target == NULL)
switch (xdrs->x_op)
{
case XDR_DECODE:
if (c == 0)
return TRUE;
*addrp = target = mem_alloc (nodesize);
if (target == NULL)
{
#ifdef USE_IN_LIBIO
if (_IO_fwide (stderr, 0) > 0)
(void) __fwprintf (stderr, L"%s",
_("xdr_array: out of memory\n"));
else
#endif
(void) fputs (_("xdr_array: out of memory\n"), stderr);
return FALSE;
}
bzero (target, nodesize);
break;
 
case XDR_FREE:
return TRUE;
default:
break;
}
 
/*
* now we xdr each element of array
*/
for (i = 0; (i < c) && stat; i++)
{
stat = (*elproc) (xdrs, target, LASTUNSIGNED);
target += elsize;
}
 
/*
* the array may need freeing
*/
if (xdrs->x_op == XDR_FREE)
{
mem_free (*addrp, nodesize);
*addrp = NULL;
}
return stat;
}
 
/*
* xdr_vector():
*
* XDR a fixed length array. Unlike variable-length arrays,
* the storage of fixed length arrays is static and unfreeable.
* > basep: base of the array
* > size: size of the array
* > elemsize: size of each element
* > xdr_elem: routine to XDR each element
*/
bool_t
xdr_vector (xdrs, basep, nelem, elemsize, xdr_elem)
XDR *xdrs;
char *basep;
u_int nelem;
u_int elemsize;
xdrproc_t xdr_elem;
{
u_int i;
char *elptr;
 
elptr = basep;
for (i = 0; i < nelem; i++)
{
if (!(*xdr_elem) (xdrs, elptr, LASTUNSIGNED))
{
return FALSE;
}
elptr += elemsize;
}
return TRUE;
}
/rpc/svc.c
0,0 → 1,492
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
* media and as a part of the software program in whole or part. Users
* may copy or modify Sun RPC without charge, but are not authorized
* to license or distribute it to anyone else except as part of a product or
* program developed by the user.
*
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun RPC is provided with no support and without any obligation on the
* part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
/*
* svc.c, Server-side remote procedure call interface.
*
* There are two sets of procedures here. The xprt routines are
* for handling transport handles. The svc routines handle the
* list of service routines.
*
* Copyright (C) 1984, Sun Microsystems, Inc.
*/
 
#define __FORCE_GLIBC
#define _GNU_SOURCE
#include <features.h>
 
#include <errno.h>
#include <unistd.h>
#include "rpc_private.h"
#include <rpc/svc.h>
#include <rpc/pmap_clnt.h>
#include <sys/poll.h>
 
#ifdef __UCLIBC_HAS_THREADS__
#define xports ((SVCXPRT **)RPC_THREAD_VARIABLE(svc_xports_s))
#else
static SVCXPRT **xports;
#endif
 
#define NULL_SVC ((struct svc_callout *)0)
#define RQCRED_SIZE 400 /* this size is excessive */
 
/* The services list
Each entry represents a set of procedures (an rpc program).
The dispatch routine takes request structs and runs the
appropriate procedure. */
struct svc_callout {
struct svc_callout *sc_next;
rpcprog_t sc_prog;
rpcvers_t sc_vers;
void (*sc_dispatch) (struct svc_req *, SVCXPRT *);
};
#ifdef __UCLIBC_HAS_THREADS__
#define svc_head ((struct svc_callout *)RPC_THREAD_VARIABLE(svc_head_s))
#else
static struct svc_callout *svc_head;
#endif
 
/* *************** SVCXPRT related stuff **************** */
 
/* Activate a transport handle. */
void
xprt_register (SVCXPRT *xprt)
{
register int sock = xprt->xp_sock;
register int i;
 
if (xports == NULL)
{
xports = (SVCXPRT **) malloc (_rpc_dtablesize () * sizeof (SVCXPRT *));
 
return;
}
 
if (sock < _rpc_dtablesize ())
{
xports[sock] = xprt;
if (sock < FD_SETSIZE)
FD_SET (sock, &svc_fdset);
 
/* Check if we have an empty slot */
for (i = 0; i < svc_max_pollfd; ++i)
if (svc_pollfd[i].fd == -1)
{
svc_pollfd[i].fd = sock;
svc_pollfd[i].events = (POLLIN | POLLPRI |
POLLRDNORM | POLLRDBAND);
return;
}
 
++svc_max_pollfd;
svc_pollfd = realloc (svc_pollfd,
sizeof (struct pollfd) * svc_max_pollfd);
if (svc_pollfd == NULL) /* Out of memory */
return;
 
svc_pollfd[svc_max_pollfd - 1].fd = sock;
svc_pollfd[svc_max_pollfd - 1].events = (POLLIN | POLLPRI |
POLLRDNORM | POLLRDBAND);
}
}
 
/* De-activate a transport handle. */
void
xprt_unregister (SVCXPRT *xprt)
{
register int sock = xprt->xp_sock;
register int i;
 
if ((sock < _rpc_dtablesize ()) && (xports[sock] == xprt))
{
xports[sock] = (SVCXPRT *) 0;
 
if (sock < FD_SETSIZE)
FD_CLR (sock, &svc_fdset);
 
for (i = 0; i < svc_max_pollfd; ++i)
if (svc_pollfd[i].fd == sock)
svc_pollfd[i].fd = -1;
}
}
 
 
/* ********************** CALLOUT list related stuff ************* */
 
/* Search the callout list for a program number, return the callout
struct. */
static struct svc_callout *
svc_find (rpcprog_t prog, rpcvers_t vers, struct svc_callout **prev)
{
register struct svc_callout *s, *p;
 
p = NULL_SVC;
for (s = svc_head; s != NULL_SVC; s = s->sc_next)
{
if ((s->sc_prog == prog) && (s->sc_vers == vers))
goto done;
p = s;
}
done:
*prev = p;
return s;
}
 
/* Add a service program to the callout list.
The dispatch routine will be called when a rpc request for this
program number comes in. */
bool_t
svc_register (SVCXPRT * xprt, rpcprog_t prog, rpcvers_t vers,
void (*dispatch) (struct svc_req *, SVCXPRT *),
rpcproc_t protocol)
{
struct svc_callout *prev;
register struct svc_callout *s;
 
if ((s = svc_find (prog, vers, &prev)) != NULL_SVC)
{
if (s->sc_dispatch == dispatch)
goto pmap_it; /* he is registering another xptr */
return FALSE;
}
s = (struct svc_callout *) mem_alloc (sizeof (struct svc_callout));
if (s == (struct svc_callout *) 0)
return FALSE;
 
s->sc_prog = prog;
s->sc_vers = vers;
s->sc_dispatch = dispatch;
s->sc_next = svc_head;
svc_head = s;
 
pmap_it:
/* now register the information with the local binder service */
if (protocol)
return pmap_set (prog, vers, protocol, xprt->xp_port);
 
return TRUE;
}
 
/* Remove a service program from the callout list. */
void
svc_unregister (rpcprog_t prog, rpcvers_t vers)
{
struct svc_callout *prev;
register struct svc_callout *s;
 
if ((s = svc_find (prog, vers, &prev)) == NULL_SVC)
return;
 
if (prev == NULL_SVC)
svc_head = s->sc_next;
else
prev->sc_next = s->sc_next;
 
s->sc_next = NULL_SVC;
mem_free ((char *) s, (u_int) sizeof (struct svc_callout));
/* now unregister the information with the local binder service */
pmap_unset (prog, vers);
}
 
/* ******************* REPLY GENERATION ROUTINES ************ */
 
/* Send a reply to an rpc request */
bool_t
svc_sendreply (register SVCXPRT *xprt, xdrproc_t xdr_results,
caddr_t xdr_location)
{
struct rpc_msg rply;
 
rply.rm_direction = REPLY;
rply.rm_reply.rp_stat = MSG_ACCEPTED;
rply.acpted_rply.ar_verf = xprt->xp_verf;
rply.acpted_rply.ar_stat = SUCCESS;
rply.acpted_rply.ar_results.where = xdr_location;
rply.acpted_rply.ar_results.proc = xdr_results;
return SVC_REPLY (xprt, &rply);
}
 
/* No procedure error reply */
void
svcerr_noproc (register SVCXPRT *xprt)
{
struct rpc_msg rply;
 
rply.rm_direction = REPLY;
rply.rm_reply.rp_stat = MSG_ACCEPTED;
rply.acpted_rply.ar_verf = xprt->xp_verf;
rply.acpted_rply.ar_stat = PROC_UNAVAIL;
SVC_REPLY (xprt, &rply);
}
 
/* Can't decode args error reply */
void
svcerr_decode (register SVCXPRT *xprt)
{
struct rpc_msg rply;
 
rply.rm_direction = REPLY;
rply.rm_reply.rp_stat = MSG_ACCEPTED;
rply.acpted_rply.ar_verf = xprt->xp_verf;
rply.acpted_rply.ar_stat = GARBAGE_ARGS;
SVC_REPLY (xprt, &rply);
}
 
/* Some system error */
void
svcerr_systemerr (register SVCXPRT *xprt)
{
struct rpc_msg rply;
 
rply.rm_direction = REPLY;
rply.rm_reply.rp_stat = MSG_ACCEPTED;
rply.acpted_rply.ar_verf = xprt->xp_verf;
rply.acpted_rply.ar_stat = SYSTEM_ERR;
SVC_REPLY (xprt, &rply);
}
 
/* Authentication error reply */
void
svcerr_auth (SVCXPRT *xprt, enum auth_stat why)
{
struct rpc_msg rply;
 
rply.rm_direction = REPLY;
rply.rm_reply.rp_stat = MSG_DENIED;
rply.rjcted_rply.rj_stat = AUTH_ERROR;
rply.rjcted_rply.rj_why = why;
SVC_REPLY (xprt, &rply);
}
 
/* Auth too weak error reply */
void
svcerr_weakauth (SVCXPRT *xprt)
{
svcerr_auth (xprt, AUTH_TOOWEAK);
}
 
/* Program unavailable error reply */
void
svcerr_noprog (register SVCXPRT *xprt)
{
struct rpc_msg rply;
 
rply.rm_direction = REPLY;
rply.rm_reply.rp_stat = MSG_ACCEPTED;
rply.acpted_rply.ar_verf = xprt->xp_verf;
rply.acpted_rply.ar_stat = PROG_UNAVAIL;
SVC_REPLY (xprt, &rply);
}
 
/* Program version mismatch error reply */
void
svcerr_progvers (register SVCXPRT *xprt, rpcvers_t low_vers,
rpcvers_t high_vers)
{
struct rpc_msg rply;
 
rply.rm_direction = REPLY;
rply.rm_reply.rp_stat = MSG_ACCEPTED;
rply.acpted_rply.ar_verf = xprt->xp_verf;
rply.acpted_rply.ar_stat = PROG_MISMATCH;
rply.acpted_rply.ar_vers.low = low_vers;
rply.acpted_rply.ar_vers.high = high_vers;
SVC_REPLY (xprt, &rply);
}
 
/* ******************* SERVER INPUT STUFF ******************* */
 
/*
* Get server side input from some transport.
*
* Statement of authentication parameters management:
* This function owns and manages all authentication parameters, specifically
* the "raw" parameters (msg.rm_call.cb_cred and msg.rm_call.cb_verf) and
* the "cooked" credentials (rqst->rq_clntcred).
* However, this function does not know the structure of the cooked
* credentials, so it make the following assumptions:
* a) the structure is contiguous (no pointers), and
* b) the cred structure size does not exceed RQCRED_SIZE bytes.
* In all events, all three parameters are freed upon exit from this routine.
* The storage is trivially management on the call stack in user land, but
* is mallocated in kernel land.
*/
 
void
svc_getreq (int rdfds)
{
fd_set readfds;
 
FD_ZERO (&readfds);
readfds.fds_bits[0] = rdfds;
svc_getreqset (&readfds);
}
 
void
svc_getreqset (fd_set *readfds)
{
register u_int32_t mask;
register u_int32_t *maskp;
register int setsize;
register int sock;
register int bit;
 
setsize = _rpc_dtablesize ();
maskp = (u_int32_t *) readfds->fds_bits;
for (sock = 0; sock < setsize; sock += 32)
for (mask = *maskp++; (bit = ffs (mask)); mask ^= (1 << (bit - 1)))
svc_getreq_common (sock + bit - 1);
}
 
void
svc_getreq_poll (struct pollfd *pfdp, int pollretval)
{
register int i;
register int fds_found;
 
for (i = fds_found = 0; i < svc_max_pollfd && fds_found < pollretval; ++i)
{
register struct pollfd *p = &pfdp[i];
 
if (p->fd != -1 && p->revents)
{
/* fd has input waiting */
++fds_found;
 
if (p->revents & POLLNVAL)
xprt_unregister (xports[p->fd]);
else
svc_getreq_common (p->fd);
}
}
}
 
 
void
svc_getreq_common (const int fd)
{
enum xprt_stat stat;
struct rpc_msg msg;
register SVCXPRT *xprt;
char cred_area[2 * MAX_AUTH_BYTES + RQCRED_SIZE];
msg.rm_call.cb_cred.oa_base = cred_area;
msg.rm_call.cb_verf.oa_base = &(cred_area[MAX_AUTH_BYTES]);
 
xprt = xports[fd];
/* Do we control fd? */
if (xprt == NULL)
return;
 
/* now receive msgs from xprtprt (support batch calls) */
do
{
if (SVC_RECV (xprt, &msg))
{
/* now find the exported program and call it */
struct svc_callout *s;
struct svc_req r;
enum auth_stat why;
rpcvers_t low_vers;
rpcvers_t high_vers;
int prog_found;
 
r.rq_clntcred = &(cred_area[2 * MAX_AUTH_BYTES]);
r.rq_xprt = xprt;
r.rq_prog = msg.rm_call.cb_prog;
r.rq_vers = msg.rm_call.cb_vers;
r.rq_proc = msg.rm_call.cb_proc;
r.rq_cred = msg.rm_call.cb_cred;
 
/* first authenticate the message */
/* Check for null flavor and bypass these calls if possible */
 
if (msg.rm_call.cb_cred.oa_flavor == AUTH_NULL)
{
r.rq_xprt->xp_verf.oa_flavor = _null_auth.oa_flavor;
r.rq_xprt->xp_verf.oa_length = 0;
}
else if ((why = _authenticate (&r, &msg)) != AUTH_OK)
{
svcerr_auth (xprt, why);
goto call_done;
}
 
/* now match message with a registered service */
prog_found = FALSE;
low_vers = 0 - 1;
high_vers = 0;
 
for (s = svc_head; s != NULL_SVC; s = s->sc_next)
{
if (s->sc_prog == r.rq_prog)
{
if (s->sc_vers == r.rq_vers)
{
(*s->sc_dispatch) (&r, xprt);
goto call_done;
}
/* found correct version */
prog_found = TRUE;
if (s->sc_vers < low_vers)
low_vers = s->sc_vers;
if (s->sc_vers > high_vers)
high_vers = s->sc_vers;
}
/* found correct program */
}
/* if we got here, the program or version
is not served ... */
if (prog_found)
svcerr_progvers (xprt, low_vers, high_vers);
else
svcerr_noprog (xprt);
/* Fall through to ... */
}
call_done:
if ((stat = SVC_STAT (xprt)) == XPRT_DIED)
{
SVC_DESTROY (xprt);
break;
}
}
while (stat == XPRT_MOREREQS);
}
 
#ifdef __UCLIBC_HAS_THREADS__
 
void
__rpc_thread_svc_cleanup (void)
{
struct svc_callout *svcp;
 
while ((svcp = svc_head) != NULL)
svc_unregister (svcp->sc_prog, svcp->sc_vers);
}
 
#endif /* __UCLIBC_HAS_THREADS__ */
/rpc/getrpcent.c
0,0 → 1,263
/* @(#)getrpcent.c 2.2 88/07/29 4.0 RPCSRC */
#define __FORCE_GLIBC
#include <features.h>
 
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
* media and as a part of the software program in whole or part. Users
* may copy or modify Sun RPC without charge, but are not authorized
* to license or distribute it to anyone else except as part of a product or
* program developed by the user.
*
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun RPC is provided with no support and without any obligation on the
* part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
 
/*
* Copyright (c) 1985 by Sun Microsystems, Inc.
*/
 
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <rpc/rpc.h>
#include <netdb.h>
#include <sys/socket.h>
#include <arpa/inet.h>
 
/*
* Internet version.
*/
static struct rpcdata {
FILE *rpcf;
char *current;
int currentlen;
int stayopen;
#define MAXALIASES 35
char *rpc_aliases[MAXALIASES];
struct rpcent rpc;
char line[BUFSIZ + 1];
char *domain;
} *rpcdata;
 
static struct rpcent *interpret(const char *val, int len);
 
static char RPCDB[] = "/etc/rpc";
 
static struct rpcdata *_rpcdata(void)
{
register struct rpcdata *d = rpcdata;
 
if (d == 0) {
d = (struct rpcdata *) calloc(1, sizeof(struct rpcdata));
 
rpcdata = d;
}
return (d);
}
 
struct rpcent *getrpcbynumber(number)
register int number;
{
register struct rpcdata *d = _rpcdata();
register struct rpcent *p;
 
if (d == 0)
return (0);
setrpcent(0);
while ((p = getrpcent())) {
if (p->r_number == number)
break;
}
endrpcent();
return (p);
}
 
struct rpcent *
#ifdef __linux__
getrpcbyname(const char *name)
#else
getrpcbyname(name)
char *name;
#endif
{
struct rpcent *rpc;
char **rp;
 
setrpcent(0);
while ((rpc = getrpcent())) {
if (strcmp(rpc->r_name, name) == 0)
return (rpc);
for (rp = rpc->r_aliases; *rp != NULL; rp++) {
if (strcmp(*rp, name) == 0)
return (rpc);
}
}
endrpcent();
return (NULL);
}
 
#ifdef __linux__
void
#endif
setrpcent(f)
int f;
{
register struct rpcdata *d = _rpcdata();
 
if (d == 0)
return;
if (d->rpcf == NULL)
d->rpcf = fopen(RPCDB, "r");
else
rewind(d->rpcf);
if (d->current)
free(d->current);
d->current = NULL;
d->stayopen |= f;
}
 
#ifdef __linux__
void
#endif
endrpcent()
{
register struct rpcdata *d = _rpcdata();
 
if (d == 0)
return;
if (d->current && !d->stayopen) {
free(d->current);
d->current = NULL;
}
if (d->rpcf && !d->stayopen) {
fclose(d->rpcf);
d->rpcf = NULL;
}
}
 
struct rpcent *getrpcent()
{
register struct rpcdata *d = _rpcdata();
 
if (d == 0)
return (NULL);
if (d->rpcf == NULL && (d->rpcf = fopen(RPCDB, "r")) == NULL)
return (NULL);
if (fgets(d->line, BUFSIZ, d->rpcf) == NULL)
return (NULL);
return interpret(d->line, strlen(d->line));
}
 
#ifdef __linux__
static char *firstwhite(char *s)
{
char *s1, *s2;
 
s1 = index(s, ' ');
s2 = index(s, '\t');
if (s1) {
if (s2)
return (s1 < s2) ? s1 : s2;
else
return s1;
} else
return s2;
}
#endif
 
static struct rpcent *interpret(const char *val, int len)
{
register struct rpcdata *d = _rpcdata();
char *p;
register char *cp, **q;
 
if (d == 0)
return NULL;
strncpy(d->line, val, len);
p = d->line;
d->line[len] = '\n';
if (*p == '#')
return (getrpcent());
cp = index(p, '#');
if (cp == NULL) {
cp = index(p, '\n');
if (cp == NULL)
return (getrpcent());
}
*cp = '\0';
#ifdef __linux__
if ((cp = firstwhite(p)))
*cp++ = 0;
else
return (getrpcent());
#else
cp = index(p, ' ');
if (cp == NULL) {
cp = index(p, '\t');
if (cp == NULL)
return (getrpcent());
}
*cp++ = '\0';
#endif
/* THIS STUFF IS INTERNET SPECIFIC */
d->rpc.r_name = d->line;
while (*cp == ' ' || *cp == '\t')
cp++;
d->rpc.r_number = atoi(cp);
q = d->rpc.r_aliases = d->rpc_aliases;
#ifdef __linux__
if ((cp = firstwhite(cp)))
*cp++ = '\0';
#else
cp = index(p, ' ');
if (cp != NULL)
*cp++ = '\0';
else {
cp = index(p, '\t');
if (cp != NULL)
*cp++ = '\0';
}
#endif
while (cp && *cp) {
if (*cp == ' ' || *cp == '\t') {
cp++;
continue;
}
if (q < &(d->rpc_aliases[MAXALIASES - 1]))
*q++ = cp;
#ifdef __linux__
if ((cp = firstwhite(cp)))
*cp++ = '\0';
#else
cp = index(p, ' ');
if (cp != NULL)
*cp++ = '\0';
else {
cp = index(p, '\t');
if (cp != NULL)
*cp++ = '\0';
}
#endif
}
*q = NULL;
return (&d->rpc);
}
/rpc/Makefile
0,0 → 1,66
# Makefile for uClibc
#
# Copyright (C) 2000 by Lineo, inc.
# Copyright (C) 2000,2001,2002 Erik Andersen <andersen@uclibc.org>
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU Library General Public License as published by the Free
# Software Foundation; either version 2 of the License, or (at your option) any
# later version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more
# details.
#
# You should have received a copy of the GNU Library General Public License
# along with this program; if not, write to the Free Software Foundation, Inc.,
# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# Derived in part from the Linux-8086 C library, the GNU C Library, and several
# other sundry sources. Files within this library are copyright by their
# respective copyright holders.
 
TOPDIR=../../../
include $(TOPDIR)Rules.mak
CFLAGS+=-I$(TOPDIR)libpthread/linuxthreads/sysdeps/pthread
 
ifeq ($(strip $(UCLIBC_HAS_FULL_RPC)),y)
CSRC :=auth_none.c auth_unix.c authunix_prot.c bindresvport.c \
clnt_generic.c clnt_perror.c clnt_raw.c clnt_simple.c clnt_tcp.c \
clnt_udp.c rpc_dtablesize.c get_myaddress.c getrpcent.c getrpcport.c \
pmap_clnt.c pmap_getmaps.c pmap_getport.c pmap_prot.c \
pmap_prot2.c pmap_rmt.c rpc_prot.c rpc_commondata.c rpc_callmsg.c \
svc.c svc_auth.c svc_auth_unix.c svc_raw.c svc_run.c svc_simple.c \
svc_tcp.c svc_udp.c xdr.c xdr_array.c xdr_float.c xdr_mem.c \
xdr_rec.c xdr_reference.c xdr_stdio.c \
rtime.c clnt_unix.c svc_unix.c create_xid.c xdr_intXX_t.c rcmd.c \
rexec.c sa_len.c ruserpass.c rpc_thread.c
else
# For now, only compile the stuff needed to do an NFS mount....
CSRC:=create_xid.c pmap_clnt.c pmap_getmaps.c pmap_getport.c \
pmap_prot.c pmap_prot2.c clnt_simple.c clnt_perror.c \
clnt_tcp.c clnt_udp.c bindresvport.c authunix_prot.c \
auth_none.c auth_unix.c xdr.c xdr_array.c xdr_rec.c \
xdr_reference.c xdr_mem.c svc.c svc_auth.c svc_auth_unix.c \
rpc_callmsg.c rpc_prot.c rpc_dtablesize.c rpc_commondata.c \
rpc_thread.c rcmd.c rexec.c sa_len.c ruserpass.c rtime.c \
getrpcent.c
endif
COBJS=$(patsubst %.c,%.o, $(CSRC))
OBJS=$(COBJS)
 
all: ar-target
 
$(LIBC): $(OBJS)
 
ar-target: $(LIBC)
$(AR) $(ARFLAGS) $(LIBC) $(OBJS)
 
$(COBJS): %.o : %.c
$(CC) $(CFLAGS) -c $< -o $@
$(STRIPTOOL) -x -R .note -R .comment $*.o
 
clean:
$(RM) *.[oa] *~ core
 
/rpc/clnt_generic.c
0,0 → 1,168
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
* media and as a part of the software program in whole or part. Users
* may copy or modify Sun RPC without charge, but are not authorized
* to license or distribute it to anyone else except as part of a product or
* program developed by the user.
*
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun RPC is provided with no support and without any obligation on the
* part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
/*
* Copyright (C) 1987, Sun Microsystems, Inc.
*/
 
#define __FORCE_GLIBC
#include <features.h>
 
#include <alloca.h>
#include <errno.h>
#include <string.h>
#include <rpc/rpc.h>
#include <sys/socket.h>
#include <sys/errno.h>
#include <netdb.h>
 
/*
* Generic client creation: takes (hostname, program-number, protocol) and
* returns client handle. Default options are set, which the user can
* change using the rpc equivalent of ioctl()'s.
*/
CLIENT *
clnt_create (const char *hostname, u_long prog, u_long vers,
const char *proto)
{
struct hostent hostbuf, *h;
size_t hstbuflen;
char *hsttmpbuf;
struct protoent *p;
struct sockaddr_in sin;
struct sockaddr_un sun;
int sock;
struct timeval tv;
CLIENT *client;
int herr;
 
if (strcmp (proto, "unix") == 0)
{
bzero ((char *)&sun, sizeof (sun));
sun.sun_family = AF_UNIX;
strcpy (sun.sun_path, hostname);
sock = RPC_ANYSOCK;
client = clntunix_create (&sun, prog, vers, &sock, 0, 0);
if (client == NULL)
return NULL;
#if 0
/* This is not wanted. This would disable the user from having
a timeout in the clnt_call() call. Only a call to cnlt_control()
by the user should set the timeout value. */
tv.tv_sec = 25;
tv.tv_usec = 0;
clnt_control (client, CLSET_TIMEOUT, (char *)&tv);
#endif
return client;
}
 
hstbuflen = 1024;
hsttmpbuf = alloca (hstbuflen);
while (gethostbyname_r (hostname, &hostbuf, hsttmpbuf, hstbuflen,
&h, &herr) != 0
|| h == NULL)
if (herr != NETDB_INTERNAL || errno != ERANGE)
{
get_rpc_createerr().cf_stat = RPC_UNKNOWNHOST;
return NULL;
}
else
{
/* Enlarge the buffer. */
hstbuflen *= 2;
hsttmpbuf = alloca (hstbuflen);
}
 
if (h->h_addrtype != AF_INET)
{
/*
* Only support INET for now
*/
struct rpc_createerr *ce = &get_rpc_createerr ();
ce->cf_stat = RPC_SYSTEMERROR;
ce->cf_error.re_errno = EAFNOSUPPORT;
return NULL;
}
sin.sin_family = h->h_addrtype;
sin.sin_port = 0;
bzero (sin.sin_zero, sizeof (sin.sin_zero));
memcpy ((char *) &sin.sin_addr, h->h_addr, h->h_length);
 
#warning getprotobyname is not reentrant... Add getprotobyname_r
p = getprotobyname(proto);
if (p == NULL) {
struct rpc_createerr *ce = &get_rpc_createerr ();
ce->cf_stat = RPC_UNKNOWNPROTO;
ce->cf_error.re_errno = EPFNOSUPPORT;
return NULL;
}
 
sock = RPC_ANYSOCK;
switch (p->p_proto)
{
case IPPROTO_UDP:
tv.tv_sec = 5;
tv.tv_usec = 0;
client = clntudp_create (&sin, prog, vers, tv, &sock);
if (client == NULL)
{
return NULL;
}
#if 0
/* This is not wanted. This would disable the user from having
a timeout in the clnt_call() call. Only a call to cnlt_control()
by the user should set the timeout value. */
tv.tv_sec = 25;
clnt_control (client, CLSET_TIMEOUT, (char *)&tv);
#endif
break;
case IPPROTO_TCP:
client = clnttcp_create (&sin, prog, vers, &sock, 0, 0);
if (client == NULL)
{
return NULL;
}
#if 0
/* This is not wanted. This would disable the user from having
a timeout in the clnt_call() call. Only a call to cnlt_control()
by the user should set the timeout value. */
tv.tv_sec = 25;
tv.tv_usec = 0;
clnt_control (client, CLSET_TIMEOUT, (char *)&tv);
#endif
break;
default:
{
struct rpc_createerr *ce = &get_rpc_createerr ();
ce->cf_stat = RPC_SYSTEMERROR;
ce->cf_error.re_errno = EPFNOSUPPORT;
}
return (NULL);
}
return client;
}
/rpc/xdr.c
0,0 → 1,747
/* @(#)xdr.c 2.1 88/07/29 4.0 RPCSRC */
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
* media and as a part of the software program in whole or part. Users
* may copy or modify Sun RPC without charge, but are not authorized
* to license or distribute it to anyone else except as part of a product or
* program developed by the user.
*
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun RPC is provided with no support and without any obligation on the
* part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
#if 0
static char sccsid[] = "@(#)xdr.c 1.35 87/08/12";
#endif
 
/*
* xdr.c, Generic XDR routines implementation.
*
* Copyright (C) 1986, Sun Microsystems, Inc.
*
* These are the "generic" xdr routines used to serialize and de-serialize
* most common data items. See xdr.h for more info on the interface to
* xdr.
*/
 
#define __FORCE_GLIBC
#define _GNU_SOURCE
#include <features.h>
 
#include <stdio.h>
#include <limits.h>
#include <string.h>
 
#include <rpc/types.h>
#include <rpc/xdr.h>
 
#ifdef USE_IN_LIBIO
# include <wchar.h>
#endif
 
/*
* constants specific to the xdr "protocol"
*/
#define XDR_FALSE ((long) 0)
#define XDR_TRUE ((long) 1)
#define LASTUNSIGNED ((u_int) 0-1)
 
/*
* for unit alignment
*/
static const char xdr_zero[BYTES_PER_XDR_UNIT] = {0, 0, 0, 0};
 
/*
* Free a data structure using XDR
* Not a filter, but a convenient utility nonetheless
*/
void
xdr_free (xdrproc_t proc, char *objp)
{
XDR x;
 
x.x_op = XDR_FREE;
(*proc) (&x, objp);
}
 
/*
* XDR nothing
*/
bool_t
xdr_void (void)
{
return TRUE;
}
 
/*
* XDR integers
*/
bool_t
xdr_int (XDR *xdrs, int *ip)
{
 
#if INT_MAX < LONG_MAX
long l;
 
switch (xdrs->x_op)
{
case XDR_ENCODE:
l = (long) *ip;
return XDR_PUTLONG (xdrs, &l);
 
case XDR_DECODE:
if (!XDR_GETLONG (xdrs, &l))
{
return FALSE;
}
*ip = (int) l;
case XDR_FREE:
return TRUE;
}
return FALSE;
#elif INT_MAX == LONG_MAX
return xdr_long (xdrs, (long *) ip);
#elif INT_MAX == SHRT_MAX
return xdr_short (xdrs, (short *) ip);
#else
#error unexpected integer sizes in_xdr_int()
#endif
}
 
/*
* XDR unsigned integers
*/
bool_t
xdr_u_int (XDR *xdrs, u_int *up)
{
#if UINT_MAX < ULONG_MAX
u_long l;
 
switch (xdrs->x_op)
{
case XDR_ENCODE:
l = (u_long) * up;
return XDR_PUTLONG (xdrs, &l);
 
case XDR_DECODE:
if (!XDR_GETLONG (xdrs, &l))
{
return FALSE;
}
*up = (u_int) l;
case XDR_FREE:
return TRUE;
}
return FALSE;
#elif UINT_MAX == ULONG_MAX
return xdr_u_long (xdrs, (u_long *) up);
#elif UINT_MAX == USHRT_MAX
return xdr_short (xdrs, (short *) up);
#else
#error unexpected integer sizes in_xdr_u_int()
#endif
}
 
/*
* XDR long integers
* The definition of xdr_long() is kept for backward
* compatibility. Instead xdr_int() should be used.
*/
bool_t
xdr_long (XDR *xdrs, long *lp)
{
 
if (xdrs->x_op == XDR_ENCODE
&& (sizeof (int32_t) == sizeof (long)
|| (int32_t) *lp == *lp))
return XDR_PUTLONG (xdrs, lp);
 
if (xdrs->x_op == XDR_DECODE)
return XDR_GETLONG (xdrs, lp);
 
if (xdrs->x_op == XDR_FREE)
return TRUE;
 
return FALSE;
}
 
/*
* XDR unsigned long integers
* The definition of xdr_u_long() is kept for backward
* compatibility. Instead xdr_u_int() should be used.
*/
bool_t
xdr_u_long (XDR *xdrs, u_long *ulp)
{
switch (xdrs->x_op)
{
case XDR_DECODE:
{
long int tmp;
 
if (XDR_GETLONG (xdrs, &tmp) == FALSE)
return FALSE;
 
*ulp = (uint32_t) tmp;
return TRUE;
}
 
case XDR_ENCODE:
if (sizeof (uint32_t) != sizeof (u_long)
&& (uint32_t) *ulp != *ulp)
return FALSE;
 
return XDR_PUTLONG (xdrs, (long *) ulp);
 
case XDR_FREE:
return TRUE;
}
return FALSE;
}
 
/*
* XDR hyper integers
* same as xdr_u_hyper - open coded to save a proc call!
*/
bool_t
xdr_hyper (XDR *xdrs, quad_t *llp)
{
long t1;
unsigned long int t2;
 
if (xdrs->x_op == XDR_ENCODE)
{
t1 = (long) ((*llp) >> 32);
t2 = (long) (*llp);
return (XDR_PUTLONG(xdrs, &t1) && XDR_PUTLONG(xdrs, &t2));
}
 
if (xdrs->x_op == XDR_DECODE)
{
if (!XDR_GETLONG(xdrs, &t1) || !XDR_GETLONG(xdrs, &t2))
return FALSE;
*llp = ((quad_t) t1) << 32;
*llp |= t2;
return TRUE;
}
 
if (xdrs->x_op == XDR_FREE)
return TRUE;
 
return FALSE;
}
 
 
/*
* XDR hyper integers
* same as xdr_hyper - open coded to save a proc call!
*/
bool_t
xdr_u_hyper (XDR *xdrs, u_quad_t *ullp)
{
unsigned long t1;
unsigned long t2;
 
if (xdrs->x_op == XDR_ENCODE)
{
t1 = (unsigned long) ((*ullp) >> 32);
t2 = (unsigned long) (*ullp);
return (XDR_PUTLONG(xdrs, &t1) && XDR_PUTLONG(xdrs, &t2));
}
 
if (xdrs->x_op == XDR_DECODE)
{
if (!XDR_GETLONG(xdrs, &t1) || !XDR_GETLONG(xdrs, &t2))
return FALSE;
*ullp = ((u_quad_t) t1) << 32;
*ullp |= t2;
return TRUE;
}
 
if (xdrs->x_op == XDR_FREE)
return TRUE;
 
return FALSE;
}
 
bool_t
xdr_longlong_t (XDR *xdrs, quad_t *llp)
{
return xdr_hyper (xdrs, llp);
}
 
bool_t
xdr_u_longlong_t (XDR *xdrs, u_quad_t *ullp)
{
return xdr_u_hyper (xdrs, ullp);
}
 
/*
* XDR short integers
*/
bool_t
xdr_short (XDR *xdrs, short *sp)
{
long l;
 
switch (xdrs->x_op)
{
case XDR_ENCODE:
l = (long) *sp;
return XDR_PUTLONG (xdrs, &l);
 
case XDR_DECODE:
if (!XDR_GETLONG (xdrs, &l))
{
return FALSE;
}
*sp = (short) l;
return TRUE;
 
case XDR_FREE:
return TRUE;
}
return FALSE;
}
 
/*
* XDR unsigned short integers
*/
bool_t
xdr_u_short (XDR *xdrs, u_short *usp)
{
u_long l;
 
switch (xdrs->x_op)
{
case XDR_ENCODE:
l = (u_long) * usp;
return XDR_PUTLONG (xdrs, &l);
 
case XDR_DECODE:
if (!XDR_GETLONG (xdrs, &l))
{
return FALSE;
}
*usp = (u_short) l;
return TRUE;
 
case XDR_FREE:
return TRUE;
}
return FALSE;
}
 
 
/*
* XDR a char
*/
bool_t
xdr_char (XDR *xdrs, char *cp)
{
int i;
 
i = (*cp);
if (!xdr_int (xdrs, &i))
{
return FALSE;
}
*cp = i;
return TRUE;
}
 
/*
* XDR an unsigned char
*/
bool_t
xdr_u_char (XDR *xdrs, u_char *cp)
{
u_int u;
 
u = (*cp);
if (!xdr_u_int (xdrs, &u))
{
return FALSE;
}
*cp = u;
return TRUE;
}
 
/*
* XDR booleans
*/
bool_t
xdr_bool (XDR *xdrs, bool_t *bp)
{
long lb;
 
switch (xdrs->x_op)
{
case XDR_ENCODE:
lb = *bp ? XDR_TRUE : XDR_FALSE;
return XDR_PUTLONG (xdrs, &lb);
 
case XDR_DECODE:
if (!XDR_GETLONG (xdrs, &lb))
{
return FALSE;
}
*bp = (lb == XDR_FALSE) ? FALSE : TRUE;
return TRUE;
 
case XDR_FREE:
return TRUE;
}
return FALSE;
}
 
/*
* XDR enumerations
*/
bool_t
xdr_enum (XDR *xdrs, enum_t *ep)
{
enum sizecheck
{
SIZEVAL
}; /* used to find the size of an enum */
 
/*
* enums are treated as ints
*/
if (sizeof (enum sizecheck) == 4)
{
#if INT_MAX < LONG_MAX
long l;
 
switch (xdrs->x_op)
{
case XDR_ENCODE:
l = *ep;
return XDR_PUTLONG (xdrs, &l);
 
case XDR_DECODE:
if (!XDR_GETLONG (xdrs, &l))
{
return FALSE;
}
*ep = l;
case XDR_FREE:
return TRUE;
 
}
return FALSE;
#else
return xdr_long (xdrs, (long *) ep);
#endif
}
else if (sizeof (enum sizecheck) == sizeof (short))
{
return xdr_short (xdrs, (short *) ep);
}
else
{
return FALSE;
}
}
 
/*
* XDR opaque data
* Allows the specification of a fixed size sequence of opaque bytes.
* cp points to the opaque object and cnt gives the byte length.
*/
bool_t
xdr_opaque (XDR *xdrs, caddr_t cp, u_int cnt)
{
u_int rndup;
static char crud[BYTES_PER_XDR_UNIT];
 
/*
* if no data we are done
*/
if (cnt == 0)
return TRUE;
 
/*
* round byte count to full xdr units
*/
rndup = cnt % BYTES_PER_XDR_UNIT;
if (rndup > 0)
rndup = BYTES_PER_XDR_UNIT - rndup;
 
switch (xdrs->x_op)
{
case XDR_DECODE:
if (!XDR_GETBYTES (xdrs, cp, cnt))
{
return FALSE;
}
if (rndup == 0)
return TRUE;
return XDR_GETBYTES (xdrs, (caddr_t)crud, rndup);
 
case XDR_ENCODE:
if (!XDR_PUTBYTES (xdrs, cp, cnt))
{
return FALSE;
}
if (rndup == 0)
return TRUE;
return XDR_PUTBYTES (xdrs, xdr_zero, rndup);
 
case XDR_FREE:
return TRUE;
}
return FALSE;
}
 
/*
* XDR counted bytes
* *cpp is a pointer to the bytes, *sizep is the count.
* If *cpp is NULL maxsize bytes are allocated
*/
bool_t
xdr_bytes (xdrs, cpp, sizep, maxsize)
XDR *xdrs;
char **cpp;
u_int *sizep;
u_int maxsize;
{
char *sp = *cpp; /* sp is the actual string pointer */
u_int nodesize;
 
/*
* first deal with the length since xdr bytes are counted
*/
if (!xdr_u_int (xdrs, sizep))
{
return FALSE;
}
nodesize = *sizep;
if ((nodesize > maxsize) && (xdrs->x_op != XDR_FREE))
{
return FALSE;
}
 
/*
* now deal with the actual bytes
*/
switch (xdrs->x_op)
{
case XDR_DECODE:
if (nodesize == 0)
{
return TRUE;
}
if (sp == NULL)
{
*cpp = sp = (char *) mem_alloc (nodesize);
}
if (sp == NULL)
{
#ifdef USE_IN_LIBIO
if (_IO_fwide (stderr, 0) > 0)
(void) __fwprintf (stderr, L"%s", _("xdr_bytes: out of memory\n"));
else
#endif
(void) fputs (_("xdr_bytes: out of memory\n"), stderr);
return FALSE;
}
/* fall into ... */
 
case XDR_ENCODE:
return xdr_opaque (xdrs, sp, nodesize);
 
case XDR_FREE:
if (sp != NULL)
{
mem_free (sp, nodesize);
*cpp = NULL;
}
return TRUE;
}
return FALSE;
}
 
/*
* Implemented here due to commonality of the object.
*/
bool_t
xdr_netobj (xdrs, np)
XDR *xdrs;
struct netobj *np;
{
 
return xdr_bytes (xdrs, &np->n_bytes, &np->n_len, MAX_NETOBJ_SZ);
}
 
/*
* XDR a discriminated union
* Support routine for discriminated unions.
* You create an array of xdrdiscrim structures, terminated with
* an entry with a null procedure pointer. The routine gets
* the discriminant value and then searches the array of xdrdiscrims
* looking for that value. It calls the procedure given in the xdrdiscrim
* to handle the discriminant. If there is no specific routine a default
* routine may be called.
* If there is no specific or default routine an error is returned.
*/
bool_t
xdr_union (xdrs, dscmp, unp, choices, dfault)
XDR *xdrs;
enum_t *dscmp; /* enum to decide which arm to work on */
char *unp; /* the union itself */
const struct xdr_discrim *choices; /* [value, xdr proc] for each arm */
xdrproc_t dfault; /* default xdr routine */
{
enum_t dscm;
 
/*
* we deal with the discriminator; it's an enum
*/
if (!xdr_enum (xdrs, dscmp))
{
return FALSE;
}
dscm = *dscmp;
 
/*
* search choices for a value that matches the discriminator.
* if we find one, execute the xdr routine for that value.
*/
for (; choices->proc != NULL_xdrproc_t; choices++)
{
if (choices->value == dscm)
return (*(choices->proc)) (xdrs, unp, LASTUNSIGNED);
}
 
/*
* no match - execute the default xdr routine if there is one
*/
return ((dfault == NULL_xdrproc_t) ? FALSE :
(*dfault) (xdrs, unp, LASTUNSIGNED));
}
 
 
/*
* Non-portable xdr primitives.
* Care should be taken when moving these routines to new architectures.
*/
 
 
/*
* XDR null terminated ASCII strings
* xdr_string deals with "C strings" - arrays of bytes that are
* terminated by a NULL character. The parameter cpp references a
* pointer to storage; If the pointer is null, then the necessary
* storage is allocated. The last parameter is the max allowed length
* of the string as specified by a protocol.
*/
bool_t
xdr_string (xdrs, cpp, maxsize)
XDR *xdrs;
char **cpp;
u_int maxsize;
{
char *sp = *cpp; /* sp is the actual string pointer */
u_int size;
u_int nodesize;
 
/*
* first deal with the length since xdr strings are counted-strings
*/
switch (xdrs->x_op)
{
case XDR_FREE:
if (sp == NULL)
{
return TRUE; /* already free */
}
/* fall through... */
case XDR_ENCODE:
if (sp == NULL)
return FALSE;
size = strlen (sp);
break;
case XDR_DECODE:
break;
}
if (!xdr_u_int (xdrs, &size))
{
return FALSE;
}
if (size > maxsize)
{
return FALSE;
}
nodesize = size + 1;
 
/*
* now deal with the actual bytes
*/
switch (xdrs->x_op)
{
case XDR_DECODE:
if (nodesize == 0)
{
return TRUE;
}
if (sp == NULL)
*cpp = sp = (char *) mem_alloc (nodesize);
if (sp == NULL)
{
#ifdef USE_IN_LIBIO
if (_IO_fwide (stderr, 0) > 0)
(void) __fwprintf (stderr, L"%s",
_("xdr_string: out of memory\n"));
else
#endif
(void) fputs (_("xdr_string: out of memory\n"), stderr);
return FALSE;
}
sp[size] = 0;
/* fall into ... */
 
case XDR_ENCODE:
return xdr_opaque (xdrs, sp, size);
 
case XDR_FREE:
mem_free (sp, nodesize);
*cpp = NULL;
return TRUE;
}
return FALSE;
}
 
/*
* Wrapper for xdr_string that can be called directly from
* routines like clnt_call
*/
bool_t
xdr_wrapstring (xdrs, cpp)
XDR *xdrs;
char **cpp;
{
if (xdr_string (xdrs, cpp, LASTUNSIGNED))
{
return TRUE;
}
return FALSE;
}
/rpc/xdr_stdio.c
0,0 → 1,194
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
* media and as a part of the software program in whole or part. Users
* may copy or modify Sun RPC without charge, but are not authorized
* to license or distribute it to anyone else except as part of a product or
* program developed by the user.
*
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun RPC is provided with no support and without any obligation on the
* part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
 
/*
* xdr_stdio.c, XDR implementation on standard i/o file.
*
* Copyright (C) 1984, Sun Microsystems, Inc.
*
* This set of routines implements a XDR on a stdio stream.
* XDR_ENCODE serializes onto the stream, XDR_DECODE de-serializes
* from the stream.
*/
 
#include <rpc/types.h>
#include <stdio.h>
#include <rpc/xdr.h>
 
#ifdef USE_IN_LIBIO
# include <libio/iolibio.h>
# define fflush(s) _IO_fflush (s)
# define fread(p, m, n, s) _IO_fread (p, m, n, s)
# define ftell(s) _IO_ftell (s)
# define fwrite(p, m, n, s) _IO_fwrite (p, m, n, s)
#endif
 
static bool_t xdrstdio_getlong (XDR *, long *);
static bool_t xdrstdio_putlong (XDR *, const long *);
static bool_t xdrstdio_getbytes (XDR *, caddr_t, u_int);
static bool_t xdrstdio_putbytes (XDR *, const char *, u_int);
static u_int xdrstdio_getpos (const XDR *);
static bool_t xdrstdio_setpos (XDR *, u_int);
static int32_t *xdrstdio_inline (XDR *, int);
static void xdrstdio_destroy (XDR *);
static bool_t xdrstdio_getint32 (XDR *, int32_t *);
static bool_t xdrstdio_putint32 (XDR *, const int32_t *);
 
/*
* Ops vector for stdio type XDR
*/
static const struct xdr_ops xdrstdio_ops =
{
xdrstdio_getlong, /* deserialize a long int */
xdrstdio_putlong, /* serialize a long int */
xdrstdio_getbytes, /* deserialize counted bytes */
xdrstdio_putbytes, /* serialize counted bytes */
xdrstdio_getpos, /* get offset in the stream */
xdrstdio_setpos, /* set offset in the stream */
xdrstdio_inline, /* prime stream for inline macros */
xdrstdio_destroy, /* destroy stream */
xdrstdio_getint32, /* deserialize a int */
xdrstdio_putint32 /* serialize a int */
};
 
/*
* Initialize a stdio xdr stream.
* Sets the xdr stream handle xdrs for use on the stream file.
* Operation flag is set to op.
*/
void
xdrstdio_create (XDR *xdrs, FILE *file, enum xdr_op op)
{
xdrs->x_op = op;
/* We have to add the const since the `struct xdr_ops' in `struct XDR'
is not `const'. */
xdrs->x_ops = (struct xdr_ops *) &xdrstdio_ops;
xdrs->x_private = (caddr_t) file;
xdrs->x_handy = 0;
xdrs->x_base = 0;
}
 
/*
* Destroy a stdio xdr stream.
* Cleans up the xdr stream handle xdrs previously set up by xdrstdio_create.
*/
static void
xdrstdio_destroy (XDR *xdrs)
{
(void) fflush ((FILE *) xdrs->x_private);
/* xx should we close the file ?? */
};
 
static bool_t
xdrstdio_getlong (XDR *xdrs, long *lp)
{
int32_t mycopy;
 
if (fread ((caddr_t) & mycopy, 4, 1, (FILE *) xdrs->x_private) != 1)
return FALSE;
*lp = (int32_t) ntohl (mycopy);
return TRUE;
}
 
static bool_t
xdrstdio_putlong (XDR *xdrs, const long *lp)
{
long mycopy = htonl (*lp);
lp = &mycopy;
if (fwrite ((caddr_t) lp, 4, 1, (FILE *) xdrs->x_private) != 1)
return FALSE;
return TRUE;
}
 
static bool_t
xdrstdio_getbytes (XDR *xdrs, const caddr_t addr, u_int len)
{
if ((len != 0) && (fread (addr, (int) len, 1,
(FILE *) xdrs->x_private) != 1))
return FALSE;
return TRUE;
}
 
static bool_t
xdrstdio_putbytes (XDR *xdrs, const char *addr, u_int len)
{
if ((len != 0) && (fwrite (addr, (int) len, 1,
(FILE *) xdrs->x_private) != 1))
return FALSE;
return TRUE;
}
 
static u_int
xdrstdio_getpos (const XDR *xdrs)
{
return (u_int) ftell ((FILE *) xdrs->x_private);
}
 
static bool_t
xdrstdio_setpos (XDR *xdrs, u_int pos)
{
return fseek ((FILE *) xdrs->x_private, (long) pos, 0) < 0 ? FALSE : TRUE;
}
 
static int32_t *
xdrstdio_inline (XDR *xdrs, int len)
{
/*
* Must do some work to implement this: must insure
* enough data in the underlying stdio buffer,
* that the buffer is aligned so that we can indirect through a
* long *, and stuff this pointer in xdrs->x_buf. Doing
* a fread or fwrite to a scratch buffer would defeat
* most of the gains to be had here and require storage
* management on this buffer, so we don't do this.
*/
return NULL;
}
 
static bool_t
xdrstdio_getint32 (XDR *xdrs, int32_t *ip)
{
int32_t mycopy;
 
if (fread ((caddr_t) &mycopy, 4, 1, (FILE *) xdrs->x_private) != 1)
return FALSE;
*ip = ntohl (mycopy);
return TRUE;
}
 
static bool_t
xdrstdio_putint32 (XDR *xdrs, const int32_t *ip)
{
int32_t mycopy = htonl (*ip);
 
ip = &mycopy;
if (fwrite ((caddr_t) ip, 4, 1, (FILE *) xdrs->x_private) != 1)
return FALSE;
return TRUE;
}
/rpc/sa_len.c
0,0 → 1,62
/* Copyright (C) 1998, 1999 Free Software Foundation, Inc.
This file is part of the GNU C Library.
 
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
 
#define __FORCE_GLIBC
#include <features.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netipx/ipx.h>
#include <sys/un.h>
#if 0
#include <netash/ash.h>
#include <netatalk/at.h>
#include <netax25/ax25.h>
#include <neteconet/ec.h>
#include <netpacket/packet.h>
#include <netrose/rose.h>
#endif
 
int __libc_sa_len (sa_family_t af)
{
switch (af)
{
#if 0
case AF_APPLETALK:
return sizeof (struct sockaddr_at);
case AF_ASH:
return sizeof (struct sockaddr_ash);
case AF_AX25:
return sizeof (struct sockaddr_ax25);
case AF_ECONET:
return sizeof (struct sockaddr_ec);
case AF_ROSE:
return sizeof (struct sockaddr_rose);
case AF_PACKET:
return sizeof (struct sockaddr_ll);
#endif
case AF_INET:
return sizeof (struct sockaddr_in);
case AF_INET6:
return sizeof (struct sockaddr_in6);
case AF_IPX:
return sizeof (struct sockaddr_ipx);
case AF_LOCAL:
return sizeof (struct sockaddr_un);
}
return 0;
}
/rpc/pmap_prot.c
0,0 → 1,57
/* @(#)pmap_prot.c 2.1 88/07/29 4.0 RPCSRC */
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
* media and as a part of the software program in whole or part. Users
* may copy or modify Sun RPC without charge, but are not authorized
* to license or distribute it to anyone else except as part of a product or
* program developed by the user.
*
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun RPC is provided with no support and without any obligation on the
* part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
#if 0
static char sccsid[] = "@(#)pmap_prot.c 1.17 87/08/11 Copyr 1984 Sun Micro";
#endif
 
/*
* pmap_prot.c
* Protocol for the local binder service, or pmap.
*
* Copyright (C) 1984, Sun Microsystems, Inc.
*/
 
#include <rpc/types.h>
#include <rpc/xdr.h>
#include <rpc/pmap_prot.h>
 
 
bool_t
xdr_pmap (xdrs, regs)
XDR *xdrs;
struct pmap *regs;
{
 
if (xdr_u_long (xdrs, &regs->pm_prog) &&
xdr_u_long (xdrs, &regs->pm_vers) &&
xdr_u_long (xdrs, &regs->pm_prot))
return xdr_u_long (xdrs, &regs->pm_port);
return FALSE;
}
/rpc/errqueue.h
0,0 → 1,46
/* Copyright (C) 2000 Free Software Foundation, Inc.
This file is part of the GNU C Library.
 
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
 
/* Linux version. */
 
#ifndef _BITS_ERRQUEUE_H
#define _BITS_ERRQUEUE_H 1
 
#include <sys/types.h>
#include <sys/socket.h>
 
struct sock_extended_err
{
u_int32_t ee_errno;
u_int8_t ee_origin;
u_int8_t ee_type;
u_int8_t ee_code;
u_int8_t ee_pad;
u_int32_t ee_info;
u_int32_t ee_data;
};
 
#define SO_EE_ORIGIN_NONE 0
#define SO_EE_ORIGIN_LOCAL 1
#define SO_EE_ORIGIN_ICMP 2
#define SO_EE_ORIGIN_ICMP6 3
 
#define SO_EE_OFFENDER(see) \
((struct sockaddr *)(((struct sock_extended_err)(see))+1))
 
#endif /* bits/errqueue.h */
/rpc/svc_udp.c
0,0 → 1,612
/* @(#)svc_udp.c 2.2 88/07/29 4.0 RPCSRC */
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
* media and as a part of the software program in whole or part. Users
* may copy or modify Sun RPC without charge, but are not authorized
* to license or distribute it to anyone else except as part of a product or
* program developed by the user.
*
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun RPC is provided with no support and without any obligation on the
* part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
#if 0
static char sccsid[] = "@(#)svc_udp.c 1.24 87/08/11 Copyr 1984 Sun Micro";
#endif
 
/*
* svc_udp.c,
* Server side for UDP/IP based RPC. (Does some caching in the hopes of
* achieving execute-at-most-once semantics.)
*
* Copyright (C) 1984, Sun Microsystems, Inc.
*/
 
#define __FORCE_GLIBC
#define _GNU_SOURCE
#include <features.h>
 
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <rpc/rpc.h>
#include <sys/socket.h>
#include <errno.h>
 
#ifdef IP_PKTINFO
#include <sys/uio.h>
#endif
 
#ifdef USE_IN_LIBIO
# include <wchar.h>
# include <libio/iolibio.h>
# define fputs(s, f) _IO_fputs (s, f)
#endif
 
#define rpc_buffer(xprt) ((xprt)->xp_p1)
#ifndef MAX
#define MAX(a, b) ((a > b) ? a : b)
#endif
 
static bool_t svcudp_recv (SVCXPRT *, struct rpc_msg *);
static bool_t svcudp_reply (SVCXPRT *, struct rpc_msg *);
static enum xprt_stat svcudp_stat (SVCXPRT *);
static bool_t svcudp_getargs (SVCXPRT *, xdrproc_t, caddr_t);
static bool_t svcudp_freeargs (SVCXPRT *, xdrproc_t, caddr_t);
static void svcudp_destroy (SVCXPRT *);
 
static const struct xp_ops svcudp_op =
{
svcudp_recv,
svcudp_stat,
svcudp_getargs,
svcudp_reply,
svcudp_freeargs,
svcudp_destroy
};
 
static int cache_get (SVCXPRT *, struct rpc_msg *, char **replyp,
u_long *replylenp);
static void cache_set (SVCXPRT *xprt, u_long replylen);
 
/*
* kept in xprt->xp_p2
*/
struct svcudp_data
{
u_int su_iosz; /* byte size of send.recv buffer */
u_long su_xid; /* transaction id */
XDR su_xdrs; /* XDR handle */
char su_verfbody[MAX_AUTH_BYTES]; /* verifier body */
char *su_cache; /* cached data, NULL if no cache */
};
#define su_data(xprt) ((struct svcudp_data *)(xprt->xp_p2))
 
/*
* Usage:
* xprt = svcudp_create(sock);
*
* If sock<0 then a socket is created, else sock is used.
* If the socket, sock is not bound to a port then svcudp_create
* binds it to an arbitrary port. In any (successful) case,
* xprt->xp_sock is the registered socket number and xprt->xp_port is the
* associated port number.
* Once *xprt is initialized, it is registered as a transporter;
* see (svc.h, xprt_register).
* The routines returns NULL if a problem occurred.
*/
SVCXPRT *
svcudp_bufcreate (sock, sendsz, recvsz)
int sock;
u_int sendsz, recvsz;
{
bool_t madesock = FALSE;
SVCXPRT *xprt;
struct svcudp_data *su;
struct sockaddr_in addr;
socklen_t len = sizeof (struct sockaddr_in);
int pad;
void *buf;
 
if (sock == RPC_ANYSOCK)
{
if ((sock = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
{
perror (_("svcudp_create: socket creation problem"));
return (SVCXPRT *) NULL;
}
madesock = TRUE;
}
bzero ((char *) &addr, sizeof (addr));
addr.sin_family = AF_INET;
if (bindresvport (sock, &addr))
{
addr.sin_port = 0;
(void) bind (sock, (struct sockaddr *) &addr, len);
}
if (getsockname (sock, (struct sockaddr *) &addr, &len) != 0)
{
perror (_("svcudp_create - cannot getsockname"));
if (madesock)
(void) close (sock);
return (SVCXPRT *) NULL;
}
xprt = (SVCXPRT *) mem_alloc (sizeof (SVCXPRT));
su = (struct svcudp_data *) mem_alloc (sizeof (*su));
buf = mem_alloc (((MAX (sendsz, recvsz) + 3) / 4) * 4);
if (xprt == NULL || su == NULL || buf == NULL)
{
#ifdef USE_IN_LIBIO
if (_IO_fwide (stderr, 0) > 0)
(void) __fwprintf (stderr, L"%s", _("svcudp_create: out of memory\n"));
else
#endif
(void) fputs (_("svcudp_create: out of memory\n"), stderr);
mem_free (xprt, sizeof (SVCXPRT));
mem_free (su, sizeof (*su));
mem_free (buf, ((MAX (sendsz, recvsz) + 3) / 4) * 4);
return NULL;
}
su->su_iosz = ((MAX (sendsz, recvsz) + 3) / 4) * 4;
rpc_buffer (xprt) = buf;
xdrmem_create (&(su->su_xdrs), rpc_buffer (xprt), su->su_iosz, XDR_DECODE);
su->su_cache = NULL;
xprt->xp_p2 = (caddr_t) su;
xprt->xp_verf.oa_base = su->su_verfbody;
xprt->xp_ops = &svcudp_op;
xprt->xp_port = ntohs (addr.sin_port);
xprt->xp_sock = sock;
 
#ifdef IP_PKTINFO
if ((sizeof (struct iovec) + sizeof (struct msghdr)
+ sizeof(struct cmsghdr) + sizeof (struct in_pktinfo))
> sizeof (xprt->xp_pad))
{
# ifdef USE_IN_LIBIO
if (_IO_fwide (stderr, 0) > 0)
(void) __fwprintf (stderr, L"%s",
_("svcudp_create: xp_pad is too small for IP_PKTINFO\n"));
else
# endif
(void) fputs (_("svcudp_create: xp_pad is too small for IP_PKTINFO\n"),
stderr);
return NULL;
}
pad = 1;
if (setsockopt (sock, SOL_IP, IP_PKTINFO, (void *) &pad,
sizeof (pad)) == 0)
/* Set the padding to all 1s. */
pad = 0xff;
else
#endif
/* Clear the padding. */
pad = 0;
memset (&xprt->xp_pad [0], pad, sizeof (xprt->xp_pad));
 
xprt_register (xprt);
return xprt;
}
 
SVCXPRT *
svcudp_create (sock)
int sock;
{
 
return svcudp_bufcreate (sock, UDPMSGSIZE, UDPMSGSIZE);
}
 
static enum xprt_stat
svcudp_stat (xprt)
SVCXPRT *xprt;
{
 
return XPRT_IDLE;
}
 
static bool_t
svcudp_recv (xprt, msg)
SVCXPRT *xprt;
struct rpc_msg *msg;
{
struct svcudp_data *su = su_data (xprt);
XDR *xdrs = &(su->su_xdrs);
int rlen;
char *reply;
u_long replylen;
socklen_t len;
 
/* It is very tricky when you have IP aliases. We want to make sure
that we are sending the packet from the IP address where the
incoming packet is addressed to. H.J. */
#ifdef IP_PKTINFO
struct iovec *iovp;
struct msghdr *mesgp;
#endif
 
again:
/* FIXME -- should xp_addrlen be a size_t? */
len = (socklen_t) sizeof(struct sockaddr_in);
#ifdef IP_PKTINFO
iovp = (struct iovec *) &xprt->xp_pad [0];
mesgp = (struct msghdr *) &xprt->xp_pad [sizeof (struct iovec)];
if (mesgp->msg_iovlen)
{
iovp->iov_base = rpc_buffer (xprt);
iovp->iov_len = su->su_iosz;
mesgp->msg_iov = iovp;
mesgp->msg_iovlen = 1;
mesgp->msg_name = &(xprt->xp_raddr);
mesgp->msg_namelen = len;
mesgp->msg_control = &xprt->xp_pad [sizeof (struct iovec)
+ sizeof (struct msghdr)];
mesgp->msg_controllen = sizeof(xprt->xp_pad)
- sizeof (struct iovec) - sizeof (struct msghdr);
rlen = recvmsg (xprt->xp_sock, mesgp, 0);
if (rlen >= 0)
len = mesgp->msg_namelen;
}
else
#endif
rlen = recvfrom (xprt->xp_sock, rpc_buffer (xprt),
(int) su->su_iosz, 0,
(struct sockaddr *) &(xprt->xp_raddr), &len);
xprt->xp_addrlen = len;
if (rlen == -1 && errno == EINTR)
goto again;
if (rlen < 16) /* < 4 32-bit ints? */
return FALSE;
xdrs->x_op = XDR_DECODE;
XDR_SETPOS (xdrs, 0);
if (!xdr_callmsg (xdrs, msg))
return FALSE;
su->su_xid = msg->rm_xid;
if (su->su_cache != NULL)
{
if (cache_get (xprt, msg, &reply, &replylen))
{
#ifdef IP_PKTINFO
if (mesgp->msg_iovlen)
{
iovp->iov_base = reply;
iovp->iov_len = replylen;
(void) sendmsg (xprt->xp_sock, mesgp, 0);
}
else
#endif
(void) sendto (xprt->xp_sock, reply, (int) replylen, 0,
(struct sockaddr *) &xprt->xp_raddr, len);
return TRUE;
}
}
return TRUE;
}
 
static bool_t
svcudp_reply (xprt, msg)
SVCXPRT *xprt;
struct rpc_msg *msg;
{
struct svcudp_data *su = su_data (xprt);
XDR *xdrs = &(su->su_xdrs);
int slen, sent;
bool_t stat = FALSE;
#ifdef IP_PKTINFO
struct iovec *iovp;
struct msghdr *mesgp;
#endif
 
xdrs->x_op = XDR_ENCODE;
XDR_SETPOS (xdrs, 0);
msg->rm_xid = su->su_xid;
if (xdr_replymsg (xdrs, msg))
{
slen = (int) XDR_GETPOS (xdrs);
#ifdef IP_PKTINFO
mesgp = (struct msghdr *) &xprt->xp_pad [sizeof (struct iovec)];
if (mesgp->msg_iovlen)
{
iovp = (struct iovec *) &xprt->xp_pad [0];
iovp->iov_base = rpc_buffer (xprt);
iovp->iov_len = slen;
sent = sendmsg (xprt->xp_sock, mesgp, 0);
}
else
#endif
sent = sendto (xprt->xp_sock, rpc_buffer (xprt), slen, 0,
(struct sockaddr *) &(xprt->xp_raddr),
xprt->xp_addrlen);
if (sent == slen)
{
stat = TRUE;
if (su->su_cache && slen >= 0)
{
cache_set (xprt, (u_long) slen);
}
}
}
return stat;
}
 
static bool_t
svcudp_getargs (xprt, xdr_args, args_ptr)
SVCXPRT *xprt;
xdrproc_t xdr_args;
caddr_t args_ptr;
{
 
return (*xdr_args) (&(su_data (xprt)->su_xdrs), args_ptr);
}
 
static bool_t
svcudp_freeargs (xprt, xdr_args, args_ptr)
SVCXPRT *xprt;
xdrproc_t xdr_args;
caddr_t args_ptr;
{
XDR *xdrs = &(su_data (xprt)->su_xdrs);
 
xdrs->x_op = XDR_FREE;
return (*xdr_args) (xdrs, args_ptr);
}
 
static void
svcudp_destroy (xprt)
SVCXPRT *xprt;
{
struct svcudp_data *su = su_data (xprt);
 
xprt_unregister (xprt);
(void) close (xprt->xp_sock);
XDR_DESTROY (&(su->su_xdrs));
mem_free (rpc_buffer (xprt), su->su_iosz);
mem_free ((caddr_t) su, sizeof (struct svcudp_data));
mem_free ((caddr_t) xprt, sizeof (SVCXPRT));
}
 
 
/***********this could be a separate file*********************/
 
/*
* Fifo cache for udp server
* Copies pointers to reply buffers into fifo cache
* Buffers are sent again if retransmissions are detected.
*/
 
#define SPARSENESS 4 /* 75% sparse */
 
#ifdef USE_IN_LIBIO
# define CACHE_PERROR(msg) \
if (_IO_fwide (stderr, 0) > 0) \
(void) __fwprintf(stderr, L"%s\n", msg); \
else \
(void) fprintf(stderr, "%s\n", msg)
#else
# define CACHE_PERROR(msg) \
(void) fprintf(stderr,"%s\n", msg)
#endif
 
#define ALLOC(type, size) \
(type *) mem_alloc((unsigned) (sizeof(type) * (size)))
 
#define BZERO(addr, type, size) \
bzero((char *) addr, sizeof(type) * (int) (size))
 
/*
* An entry in the cache
*/
typedef struct cache_node *cache_ptr;
struct cache_node
{
/*
* Index into cache is xid, proc, vers, prog and address
*/
u_long cache_xid;
u_long cache_proc;
u_long cache_vers;
u_long cache_prog;
struct sockaddr_in cache_addr;
/*
* The cached reply and length
*/
char *cache_reply;
u_long cache_replylen;
/*
* Next node on the list, if there is a collision
*/
cache_ptr cache_next;
};
 
 
 
/*
* The entire cache
*/
struct udp_cache
{
u_long uc_size; /* size of cache */
cache_ptr *uc_entries; /* hash table of entries in cache */
cache_ptr *uc_fifo; /* fifo list of entries in cache */
u_long uc_nextvictim; /* points to next victim in fifo list */
u_long uc_prog; /* saved program number */
u_long uc_vers; /* saved version number */
u_long uc_proc; /* saved procedure number */
struct sockaddr_in uc_addr; /* saved caller's address */
};
 
 
/*
* the hashing function
*/
#define CACHE_LOC(transp, xid) \
(xid % (SPARSENESS*((struct udp_cache *) su_data(transp)->su_cache)->uc_size))
 
 
/*
* Enable use of the cache.
* Note: there is no disable.
*/
int
svcudp_enablecache (SVCXPRT *transp, u_long size)
{
struct svcudp_data *su = su_data (transp);
struct udp_cache *uc;
 
if (su->su_cache != NULL)
{
CACHE_PERROR (_("enablecache: cache already enabled"));
return 0;
}
uc = ALLOC (struct udp_cache, 1);
if (uc == NULL)
{
CACHE_PERROR (_("enablecache: could not allocate cache"));
return 0;
}
uc->uc_size = size;
uc->uc_nextvictim = 0;
uc->uc_entries = ALLOC (cache_ptr, size * SPARSENESS);
if (uc->uc_entries == NULL)
{
CACHE_PERROR (_("enablecache: could not allocate cache data"));
return 0;
}
BZERO (uc->uc_entries, cache_ptr, size * SPARSENESS);
uc->uc_fifo = ALLOC (cache_ptr, size);
if (uc->uc_fifo == NULL)
{
CACHE_PERROR (_("enablecache: could not allocate cache fifo"));
return 0;
}
BZERO (uc->uc_fifo, cache_ptr, size);
su->su_cache = (char *) uc;
return 1;
}
 
 
/*
* Set an entry in the cache
*/
static void
cache_set (SVCXPRT *xprt, u_long replylen)
{
cache_ptr victim;
cache_ptr *vicp;
struct svcudp_data *su = su_data (xprt);
struct udp_cache *uc = (struct udp_cache *) su->su_cache;
u_int loc;
char *newbuf;
 
/*
* Find space for the new entry, either by
* reusing an old entry, or by mallocing a new one
*/
victim = uc->uc_fifo[uc->uc_nextvictim];
if (victim != NULL)
{
loc = CACHE_LOC (xprt, victim->cache_xid);
for (vicp = &uc->uc_entries[loc];
*vicp != NULL && *vicp != victim;
vicp = &(*vicp)->cache_next)
;
if (*vicp == NULL)
{
CACHE_PERROR (_("cache_set: victim not found"));
return;
}
*vicp = victim->cache_next; /* remote from cache */
newbuf = victim->cache_reply;
}
else
{
victim = ALLOC (struct cache_node, 1);
if (victim == NULL)
{
CACHE_PERROR (_("cache_set: victim alloc failed"));
return;
}
newbuf = mem_alloc (su->su_iosz);
if (newbuf == NULL)
{
CACHE_PERROR (_("cache_set: could not allocate new rpc_buffer"));
return;
}
}
 
/*
* Store it away
*/
victim->cache_replylen = replylen;
victim->cache_reply = rpc_buffer (xprt);
rpc_buffer (xprt) = newbuf;
xdrmem_create (&(su->su_xdrs), rpc_buffer (xprt), su->su_iosz, XDR_ENCODE);
victim->cache_xid = su->su_xid;
victim->cache_proc = uc->uc_proc;
victim->cache_vers = uc->uc_vers;
victim->cache_prog = uc->uc_prog;
victim->cache_addr = uc->uc_addr;
loc = CACHE_LOC (xprt, victim->cache_xid);
victim->cache_next = uc->uc_entries[loc];
uc->uc_entries[loc] = victim;
uc->uc_fifo[uc->uc_nextvictim++] = victim;
uc->uc_nextvictim %= uc->uc_size;
}
 
/*
* Try to get an entry from the cache
* return 1 if found, 0 if not found
*/
static int
cache_get (xprt, msg, replyp, replylenp)
SVCXPRT *xprt;
struct rpc_msg *msg;
char **replyp;
u_long *replylenp;
{
u_int loc;
cache_ptr ent;
struct svcudp_data *su = su_data (xprt);
struct udp_cache *uc = (struct udp_cache *) su->su_cache;
 
#define EQADDR(a1, a2) (memcmp((char*)&a1, (char*)&a2, sizeof(a1)) == 0)
 
loc = CACHE_LOC (xprt, su->su_xid);
for (ent = uc->uc_entries[loc]; ent != NULL; ent = ent->cache_next)
{
if (ent->cache_xid == su->su_xid &&
ent->cache_proc == uc->uc_proc &&
ent->cache_vers == uc->uc_vers &&
ent->cache_prog == uc->uc_prog &&
EQADDR (ent->cache_addr, uc->uc_addr))
{
*replyp = ent->cache_reply;
*replylenp = ent->cache_replylen;
return 1;
}
}
/*
* Failed to find entry
* Remember a few things so we can do a set later
*/
uc->uc_proc = msg->rm_call.cb_proc;
uc->uc_vers = msg->rm_call.cb_vers;
uc->uc_prog = msg->rm_call.cb_prog;
memcpy (&uc->uc_addr, &xprt->xp_raddr, sizeof (uc->uc_addr));
return 0;
}
/rpc/clnt_unix.c
0,0 → 1,606
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
* media and as a part of the software program in whole or part. Users
* may copy or modify Sun RPC without charge, but are not authorized
* to license or distribute it to anyone else except as part of a product or
* program developed by the user.
*
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun RPC is provided with no support and without any obligation on the
* part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
 
/*
* clnt_unix.c, Implements a TCP/IP based, client side RPC.
*
* Copyright (C) 1984, Sun Microsystems, Inc.
*
* TCP based RPC supports 'batched calls'.
* A sequence of calls may be batched-up in a send buffer. The rpc call
* return immediately to the client even though the call was not necessarily
* sent. The batching occurs if the results' xdr routine is NULL (0) AND
* the rpc timeout value is zero (see clnt.h, rpc).
*
* Clients should NOT casually batch calls that in fact return results; that is,
* the server side should be aware that a call is batched and not produce any
* return message. Batched calls that produce many result messages can
* deadlock (netlock) the client and the server....
*
* Now go hang yourself.
*/
 
#define __FORCE_GLIBC
#include <features.h>
 
#include <netdb.h>
#include <errno.h>
#include <stdio.h>
#include <unistd.h>
#include <rpc/rpc.h>
#include <sys/uio.h>
#include <sys/poll.h>
#include <sys/socket.h>
#include <rpc/pmap_clnt.h>
#ifdef USE_IN_LIBIO
# include <wchar.h>
#endif
 
extern u_long _create_xid (void);
 
#define MCALL_MSG_SIZE 24
 
struct ct_data
{
int ct_sock;
bool_t ct_closeit;
struct timeval ct_wait;
bool_t ct_waitset; /* wait set by clnt_control? */
struct sockaddr_un ct_addr;
struct rpc_err ct_error;
char ct_mcall[MCALL_MSG_SIZE]; /* marshalled callmsg */
u_int ct_mpos; /* pos after marshal */
XDR ct_xdrs;
};
 
static int readunix (char *, char *, int);
static int writeunix (char *, char *, int);
 
static enum clnt_stat clntunix_call (CLIENT *, u_long, xdrproc_t, caddr_t,
xdrproc_t, caddr_t, struct timeval);
static void clntunix_abort (void);
static void clntunix_geterr (CLIENT *, struct rpc_err *);
static bool_t clntunix_freeres (CLIENT *, xdrproc_t, caddr_t);
static bool_t clntunix_control (CLIENT *, int, char *);
static void clntunix_destroy (CLIENT *);
 
static struct clnt_ops unix_ops =
{
clntunix_call,
clntunix_abort,
clntunix_geterr,
clntunix_freeres,
clntunix_destroy,
clntunix_control
};
 
/*
* Create a client handle for a tcp/ip connection.
* If *sockp<0, *sockp is set to a newly created TCP socket and it is
* connected to raddr. If *sockp non-negative then
* raddr is ignored. The rpc/tcp package does buffering
* similar to stdio, so the client must pick send and receive buffer sizes,];
* 0 => use the default.
* If raddr->sin_port is 0, then a binder on the remote machine is
* consulted for the right port number.
* NB: *sockp is copied into a private area.
* NB: It is the clients responsibility to close *sockp.
* NB: The rpch->cl_auth is set null authentication. Caller may wish to set this
* something more useful.
*/
CLIENT *
clntunix_create (struct sockaddr_un *raddr, u_long prog, u_long vers,
int *sockp, u_int sendsz, u_int recvsz)
{
CLIENT *h;
struct ct_data *ct = (struct ct_data *) mem_alloc (sizeof (*ct));
struct rpc_msg call_msg;
int len;
 
h = (CLIENT *) mem_alloc (sizeof (*h));
if (h == NULL || ct == NULL)
{
struct rpc_createerr *ce = &get_rpc_createerr ();
#ifdef USE_IN_LIBIO
if (_IO_fwide (stderr, 0) > 0)
(void) __fwprintf (stderr, L"%s",
_("clntunix_create: out of memory\n"));
else
#endif
(void) fputs (_("clntunix_create: out of memory\n"), stderr);
ce->cf_stat = RPC_SYSTEMERROR;
ce->cf_error.re_errno = ENOMEM;
goto fooy;
}
 
/*
* If no socket given, open one
*/
if (*sockp < 0)
{
*sockp = socket (AF_UNIX, SOCK_STREAM, 0);
len = strlen (raddr->sun_path) + sizeof (raddr->sun_family) + 1;
if (*sockp < 0
|| connect (*sockp, (struct sockaddr *) raddr, len) < 0)
{
struct rpc_createerr *ce = &get_rpc_createerr ();
ce->cf_stat = RPC_SYSTEMERROR;
ce->cf_error.re_errno = errno;
if (*sockp != -1)
close (*sockp);
goto fooy;
}
ct->ct_closeit = TRUE;
}
else
{
ct->ct_closeit = FALSE;
}
 
/*
* Set up private data struct
*/
ct->ct_sock = *sockp;
ct->ct_wait.tv_usec = 0;
ct->ct_waitset = FALSE;
ct->ct_addr = *raddr;
 
/*
* Initialize call message
*/
call_msg.rm_xid = _create_xid ();
call_msg.rm_direction = CALL;
call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
call_msg.rm_call.cb_prog = prog;
call_msg.rm_call.cb_vers = vers;
 
/*
* pre-serialize the static part of the call msg and stash it away
*/
xdrmem_create (&(ct->ct_xdrs), ct->ct_mcall, MCALL_MSG_SIZE, XDR_ENCODE);
if (!xdr_callhdr (&(ct->ct_xdrs), &call_msg))
{
if (ct->ct_closeit)
close (*sockp);
goto fooy;
}
ct->ct_mpos = XDR_GETPOS (&(ct->ct_xdrs));
XDR_DESTROY (&(ct->ct_xdrs));
 
/*
* Create a client handle which uses xdrrec for serialization
* and authnone for authentication.
*/
xdrrec_create (&(ct->ct_xdrs), sendsz, recvsz,
(caddr_t) ct, readunix, writeunix);
h->cl_ops = &unix_ops;
h->cl_private = (caddr_t) ct;
h->cl_auth = authnone_create ();
return h;
 
fooy:
/*
* Something goofed, free stuff and barf
*/
mem_free ((caddr_t) ct, sizeof (struct ct_data));
mem_free ((caddr_t) h, sizeof (CLIENT));
return (CLIENT *) NULL;
}
 
static enum clnt_stat
clntunix_call (h, proc, xdr_args, args_ptr, xdr_results, results_ptr, timeout)
CLIENT *h;
u_long proc;
xdrproc_t xdr_args;
caddr_t args_ptr;
xdrproc_t xdr_results;
caddr_t results_ptr;
struct timeval timeout;
{
struct ct_data *ct = (struct ct_data *) h->cl_private;
XDR *xdrs = &(ct->ct_xdrs);
struct rpc_msg reply_msg;
u_long x_id;
u_int32_t *msg_x_id = (u_int32_t *) (ct->ct_mcall); /* yuk */
bool_t shipnow;
int refreshes = 2;
 
if (!ct->ct_waitset)
{
ct->ct_wait = timeout;
}
 
shipnow =
(xdr_results == (xdrproc_t) 0 && ct->ct_wait.tv_sec == 0
&& ct->ct_wait.tv_usec == 0) ? FALSE : TRUE;
 
call_again:
xdrs->x_op = XDR_ENCODE;
ct->ct_error.re_status = RPC_SUCCESS;
x_id = ntohl (--(*msg_x_id));
if ((!XDR_PUTBYTES (xdrs, ct->ct_mcall, ct->ct_mpos)) ||
(!XDR_PUTLONG (xdrs, (long *) &proc)) ||
(!AUTH_MARSHALL (h->cl_auth, xdrs)) ||
(!(*xdr_args) (xdrs, args_ptr)))
{
if (ct->ct_error.re_status == RPC_SUCCESS)
ct->ct_error.re_status = RPC_CANTENCODEARGS;
(void) xdrrec_endofrecord (xdrs, TRUE);
return ct->ct_error.re_status;
}
if (!xdrrec_endofrecord (xdrs, shipnow))
return ct->ct_error.re_status = RPC_CANTSEND;
if (!shipnow)
return RPC_SUCCESS;
/*
* Hack to provide rpc-based message passing
*/
if (ct->ct_wait.tv_sec == 0 && ct->ct_wait.tv_usec == 0)
return ct->ct_error.re_status = RPC_TIMEDOUT;
 
 
/*
* Keep receiving until we get a valid transaction id
*/
xdrs->x_op = XDR_DECODE;
while (TRUE)
{
reply_msg.acpted_rply.ar_verf = _null_auth;
reply_msg.acpted_rply.ar_results.where = NULL;
reply_msg.acpted_rply.ar_results.proc = (xdrproc_t)xdr_void;
if (!xdrrec_skiprecord (xdrs))
return ct->ct_error.re_status;
/* now decode and validate the response header */
if (!xdr_replymsg (xdrs, &reply_msg))
{
if (ct->ct_error.re_status == RPC_SUCCESS)
continue;
return ct->ct_error.re_status;
}
if (reply_msg.rm_xid == x_id)
break;
}
 
/*
* process header
*/
_seterr_reply (&reply_msg, &(ct->ct_error));
if (ct->ct_error.re_status == RPC_SUCCESS)
{
if (!AUTH_VALIDATE (h->cl_auth, &reply_msg.acpted_rply.ar_verf))
{
ct->ct_error.re_status = RPC_AUTHERROR;
ct->ct_error.re_why = AUTH_INVALIDRESP;
}
else if (!(*xdr_results) (xdrs, results_ptr))
{
if (ct->ct_error.re_status == RPC_SUCCESS)
ct->ct_error.re_status = RPC_CANTDECODERES;
}
/* free verifier ... */
if (reply_msg.acpted_rply.ar_verf.oa_base != NULL)
{
xdrs->x_op = XDR_FREE;
(void) xdr_opaque_auth (xdrs, &(reply_msg.acpted_rply.ar_verf));
}
} /* end successful completion */
else
{
/* maybe our credentials need to be refreshed ... */
if (refreshes-- && AUTH_REFRESH (h->cl_auth))
goto call_again;
} /* end of unsuccessful completion */
return ct->ct_error.re_status;
}
 
static void
clntunix_geterr (CLIENT *h, struct rpc_err *errp)
{
struct ct_data *ct = (struct ct_data *) h->cl_private;
 
*errp = ct->ct_error;
}
 
static bool_t
clntunix_freeres (cl, xdr_res, res_ptr)
CLIENT *cl;
xdrproc_t xdr_res;
caddr_t res_ptr;
{
struct ct_data *ct = (struct ct_data *) cl->cl_private;
XDR *xdrs = &(ct->ct_xdrs);
 
xdrs->x_op = XDR_FREE;
return (*xdr_res) (xdrs, res_ptr);
}
 
static void
clntunix_abort ()
{
}
 
static bool_t
clntunix_control (CLIENT *cl, int request, char *info)
{
struct ct_data *ct = (struct ct_data *) cl->cl_private;
 
 
switch (request)
{
case CLSET_FD_CLOSE:
ct->ct_closeit = TRUE;
break;
case CLSET_FD_NCLOSE:
ct->ct_closeit = FALSE;
break;
case CLSET_TIMEOUT:
ct->ct_wait = *(struct timeval *) info;
break;
case CLGET_TIMEOUT:
*(struct timeval *) info = ct->ct_wait;
break;
case CLGET_SERVER_ADDR:
*(struct sockaddr_un *) info = ct->ct_addr;
break;
case CLGET_FD:
*(int *)info = ct->ct_sock;
break;
case CLGET_XID:
/*
* use the knowledge that xid is the
* first element in the call structure *.
* This will get the xid of the PREVIOUS call
*/
*(u_long *) info = ntohl (*(u_long *)ct->ct_mcall);
break;
case CLSET_XID:
/* This will set the xid of the NEXT call */
*(u_long *) ct->ct_mcall = htonl (*(u_long *)info - 1);
/* decrement by 1 as clntunix_call() increments once */
case CLGET_VERS:
/*
* This RELIES on the information that, in the call body,
* the version number field is the fifth field from the
* begining of the RPC header. MUST be changed if the
* call_struct is changed
*/
*(u_long *) info = ntohl (*(u_long *) (ct->ct_mcall
+ 4 * BYTES_PER_XDR_UNIT));
break;
case CLSET_VERS:
*(u_long *) (ct->ct_mcall + 4 * BYTES_PER_XDR_UNIT)
= htonl (*(u_long *) info);
break;
case CLGET_PROG:
/*
* This RELIES on the information that, in the call body,
* the program number field is the field from the
* begining of the RPC header. MUST be changed if the
* call_struct is changed
*/
*(u_long *) info = ntohl (*(u_long *) (ct->ct_mcall
+ 3 * BYTES_PER_XDR_UNIT));
break;
case CLSET_PROG:
*(u_long *) (ct->ct_mcall + 3 * BYTES_PER_XDR_UNIT)
= htonl(*(u_long *) info);
break;
/* The following are only possible with TI-RPC */
case CLGET_RETRY_TIMEOUT:
case CLSET_RETRY_TIMEOUT:
case CLGET_SVC_ADDR:
case CLSET_SVC_ADDR:
case CLSET_PUSH_TIMOD:
case CLSET_POP_TIMOD:
default:
return FALSE;
}
return TRUE;
}
 
 
static void
clntunix_destroy (CLIENT *h)
{
struct ct_data *ct =
(struct ct_data *) h->cl_private;
 
if (ct->ct_closeit)
{
(void) close (ct->ct_sock);
}
XDR_DESTROY (&(ct->ct_xdrs));
mem_free ((caddr_t) ct, sizeof (struct ct_data));
mem_free ((caddr_t) h, sizeof (CLIENT));
}
 
static int
__msgread (int sock, void *data, size_t cnt)
{
struct iovec iov;
struct msghdr msg;
#ifdef SCM_CREDENTIALS
static char cm[CMSG_SPACE(sizeof (struct ucred))];
#endif
int len;
 
iov.iov_base = data;
iov.iov_len = cnt;
 
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
msg.msg_name = NULL;
msg.msg_namelen = 0;
#ifdef SCM_CREDENTIALS
msg.msg_control = (caddr_t) &cm;
msg.msg_controllen = CMSG_SPACE(sizeof (struct ucred));
#endif
msg.msg_flags = 0;
 
#ifdef SO_PASSCRED
{
int on = 1;
if (setsockopt (sock, SOL_SOCKET, SO_PASSCRED, &on, sizeof (on)))
return -1;
}
#endif
 
restart:
len = recvmsg (sock, &msg, 0);
if (len >= 0)
{
if (msg.msg_flags & MSG_CTRUNC || len == 0)
return 0;
else
return len;
}
if (errno == EINTR)
goto restart;
return -1;
}
 
static int
__msgwrite (int sock, void *data, size_t cnt)
{
#ifndef SCM_CREDENTIALS
/* We cannot implement this reliably. */
__set_errno (ENOSYS);
return -1;
#else
struct iovec iov;
struct msghdr msg;
struct cmsghdr *cmsg = alloca (CMSG_SPACE(sizeof (struct ucred)));
struct ucred cred;
int len;
 
/* XXX I'm not sure, if gete?id() is always correct, or if we should use
get?id(). But since keyserv needs geteuid(), we have no other chance.
It would be much better, if the kernel could pass both to the server. */
cred.pid = getpid ();
cred.uid = geteuid ();
cred.gid = getegid ();
 
memcpy (CMSG_DATA(cmsg), &cred, sizeof (struct ucred));
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_CREDENTIALS;
cmsg->cmsg_len = sizeof(*cmsg) + sizeof(struct ucred);
 
iov.iov_base = data;
iov.iov_len = cnt;
 
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
msg.msg_name = NULL;
msg.msg_namelen = 0;
msg.msg_control = cmsg;
msg.msg_controllen = CMSG_ALIGN(cmsg->cmsg_len);
msg.msg_flags = 0;
 
restart:
len = sendmsg (sock, &msg, 0);
if (len >= 0)
return len;
if (errno == EINTR)
goto restart;
return -1;
 
#endif
}
 
 
/*
* Interface between xdr serializer and unix connection.
* Behaves like the system calls, read & write, but keeps some error state
* around for the rpc level.
*/
static int
readunix (char *ctptr, char *buf, int len)
{
struct ct_data *ct = (struct ct_data *) ctptr;
struct pollfd fd;
int milliseconds = ((ct->ct_wait.tv_sec * 1000)
+ (ct->ct_wait.tv_usec / 1000));
 
if (len == 0)
return 0;
 
fd.fd = ct->ct_sock;
fd.events = POLLIN;
while (TRUE)
{
switch (poll (&fd, 1, milliseconds))
{
case 0:
ct->ct_error.re_status = RPC_TIMEDOUT;
return -1;
 
case -1:
if (errno == EINTR)
continue;
ct->ct_error.re_status = RPC_CANTRECV;
ct->ct_error.re_errno = errno;
return -1;
}
break;
}
switch (len = __msgread (ct->ct_sock, buf, len))
{
 
case 0:
/* premature eof */
ct->ct_error.re_errno = ECONNRESET;
ct->ct_error.re_status = RPC_CANTRECV;
len = -1; /* it's really an error */
break;
 
case -1:
ct->ct_error.re_errno = errno;
ct->ct_error.re_status = RPC_CANTRECV;
break;
}
return len;
}
 
static int
writeunix (char *ctptr, char *buf, int len)
{
int i, cnt;
struct ct_data *ct = (struct ct_data *) ctptr;
 
for (cnt = len; cnt > 0; cnt -= i, buf += i)
{
if ((i = __msgwrite (ct->ct_sock, buf, cnt)) == -1)
{
ct->ct_error.re_errno = errno;
ct->ct_error.re_status = RPC_CANTSEND;
return -1;
}
}
return len;
}
/rpc/rexec.c
0,0 → 1,191
/*
* Copyright (c) 1980, 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.
*/
 
#define __FORCE_GLIBC
#include <features.h>
#include <sys/types.h>
#include <sys/socket.h>
 
#include <netinet/in.h>
 
#include <alloca.h>
#include <stdio.h>
#include <netdb.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
 
#define SA_LEN(_x) __libc_sa_len((_x)->sa_family)
extern int __libc_sa_len (sa_family_t __af) __THROW;
 
int rexecoptions;
char ahostbuf[NI_MAXHOST];
extern int ruserpass(const char *host, const char **aname, const char **apass);
 
int
rexec_af(ahost, rport, name, pass, cmd, fd2p, af)
char **ahost;
int rport;
const char *name, *pass, *cmd;
int *fd2p;
sa_family_t af;
{
struct sockaddr_storage sa2, from;
struct addrinfo hints, *res0;
const char *orig_name = name;
const char *orig_pass = pass;
u_short port = 0;
int s, timo = 1, s3;
char c;
int gai;
char servbuff[NI_MAXSERV];
 
snprintf(servbuff, sizeof(servbuff), "%d", ntohs(rport));
servbuff[sizeof(servbuff) - 1] = '\0';
 
memset(&hints, 0, sizeof(hints));
hints.ai_family = af;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_CANONNAME;
gai = getaddrinfo(*ahost, servbuff, &hints, &res0);
if (gai){
/* XXX: set errno? */
return -1;
}
 
if (res0->ai_canonname){
strncpy(ahostbuf, res0->ai_canonname, sizeof(ahostbuf));
ahostbuf[sizeof(ahostbuf)-1] = '\0';
*ahost = ahostbuf;
}
else{
*ahost = NULL;
}
ruserpass(res0->ai_canonname, &name, &pass);
retry:
s = socket(res0->ai_family, res0->ai_socktype, 0);
if (s < 0) {
perror("rexec: socket");
return (-1);
}
if (connect(s, res0->ai_addr, res0->ai_addrlen) < 0) {
if (errno == ECONNREFUSED && timo <= 16) {
(void) close(s);
sleep(timo);
timo *= 2;
goto retry;
}
perror(res0->ai_canonname);
return (-1);
}
if (fd2p == 0) {
(void) write(s, "", 1);
port = 0;
} else {
char num[32];
int s2, sa2len;
 
s2 = socket(res0->ai_family, res0->ai_socktype, 0);
if (s2 < 0) {
(void) close(s);
return (-1);
}
listen(s2, 1);
sa2len = sizeof (sa2);
if (getsockname(s2, (struct sockaddr *)&sa2, &sa2len) < 0) {
perror("getsockname");
(void) close(s2);
goto bad;
} else if (sa2len != SA_LEN((struct sockaddr *)&sa2)) {
__set_errno(EINVAL);
(void) close(s2);
goto bad;
}
port = 0;
if (!getnameinfo((struct sockaddr *)&sa2, sa2len,
NULL, 0, servbuff, sizeof(servbuff),
NI_NUMERICSERV))
port = atoi(servbuff);
(void) sprintf(num, "%u", port);
(void) write(s, num, strlen(num)+1);
{ socklen_t len = sizeof (from);
s3 = accept(s2, (struct sockaddr *)&from, &len);
close(s2);
if (s3 < 0) {
perror("accept");
port = 0;
goto bad;
}
}
*fd2p = s3;
}
(void) write(s, name, strlen(name) + 1);
/* should public key encypt the password here */
(void) write(s, pass, strlen(pass) + 1);
(void) write(s, cmd, strlen(cmd) + 1);
 
/* We don't need the memory allocated for the name and the password
in ruserpass anymore. */
if (name != orig_name)
free ((char *) name);
if (pass != orig_pass)
free ((char *) pass);
 
if (read(s, &c, 1) != 1) {
perror(*ahost);
goto bad;
}
if (c != 0) {
while (read(s, &c, 1) == 1) {
(void) write(2, &c, 1);
if (c == '\n')
break;
}
goto bad;
}
freeaddrinfo(res0);
return (s);
bad:
if (port)
(void) close(*fd2p);
(void) close(s);
freeaddrinfo(res0);
return (-1);
}
 
int
rexec(ahost, rport, name, pass, cmd, fd2p)
char **ahost;
int rport;
const char *name, *pass, *cmd;
int *fd2p;
{
return rexec_af(ahost, rport, name, pass, cmd, fd2p, AF_INET);
}
/rpc/create_xid.c
0,0 → 1,64
/* Copyright (c) 1998, 2000 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1998.
 
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
 
#define __FORCE_GLIBC
#include <features.h>
 
#include <unistd.h>
#include <stdlib.h>
#include <sys/time.h>
#include <rpc/rpc.h>
 
/* The RPC code is not threadsafe, but new code should be threadsafe. */
 
#ifdef __UCLIBC_HAS_THREADS__
#include <pthread.h>
static pthread_mutex_t createxid_lock = PTHREAD_MUTEX_INITIALIZER;
# define LOCK __pthread_mutex_lock(&createxid_lock)
# define UNLOCK __pthread_mutex_unlock(&createxid_lock);
#else
# define LOCK
# define UNLOCK
#endif
 
static int is_initialized;
static struct drand48_data __rpc_lrand48_data;
 
unsigned long
_create_xid (void)
{
unsigned long res;
 
LOCK;
 
if (!is_initialized)
{
struct timeval now;
 
gettimeofday (&now, (struct timezone *) 0);
srand48_r (now.tv_sec ^ now.tv_usec, &__rpc_lrand48_data);
is_initialized = 1;
}
 
lrand48_r (&__rpc_lrand48_data, &res);
 
UNLOCK;
 
return res;
}
/rpc/clnt_udp.c
0,0 → 1,609
/* @(#)clnt_udp.c 2.2 88/08/01 4.0 RPCSRC */
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
* media and as a part of the software program in whole or part. Users
* may copy or modify Sun RPC without charge, but are not authorized
* to license or distribute it to anyone else except as part of a product or
* program developed by the user.
*
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun RPC is provided with no support and without any obligation on the
* part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
#if 0
static char sccsid[] = "@(#)clnt_udp.c 1.39 87/08/11 Copyr 1984 Sun Micro";
#endif
 
/*
* clnt_udp.c, Implements a UDP/IP based, client side RPC.
*
* Copyright (C) 1984, Sun Microsystems, Inc.
*/
 
#define __FORCE_GLIBC
#include <features.h>
 
#include <stdio.h>
#include <unistd.h>
#include <rpc/rpc.h>
#include <rpc/xdr.h>
#include <rpc/clnt.h>
#include <sys/poll.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netdb.h>
#include <errno.h>
#include <rpc/pmap_clnt.h>
#include <net/if.h>
#ifdef USE_IN_LIBIO
# include <wchar.h>
#endif
 
#ifdef IP_RECVERR
#include "errqueue.h"
#include <sys/uio.h>
#endif
 
extern bool_t xdr_opaque_auth (XDR *, struct opaque_auth *);
extern u_long _create_xid (void);
 
/*
* UDP bases client side rpc operations
*/
static enum clnt_stat clntudp_call (CLIENT *, u_long, xdrproc_t, caddr_t,
xdrproc_t, caddr_t, struct timeval);
static void clntudp_abort (void);
static void clntudp_geterr (CLIENT *, struct rpc_err *);
static bool_t clntudp_freeres (CLIENT *, xdrproc_t, caddr_t);
static bool_t clntudp_control (CLIENT *, int, char *);
static void clntudp_destroy (CLIENT *);
 
static struct clnt_ops udp_ops =
{
clntudp_call,
clntudp_abort,
clntudp_geterr,
clntudp_freeres,
clntudp_destroy,
clntudp_control
};
 
/*
* Private data kept per client handle
*/
struct cu_data
{
int cu_sock;
bool_t cu_closeit;
struct sockaddr_in cu_raddr;
int cu_rlen;
struct timeval cu_wait;
struct timeval cu_total;
struct rpc_err cu_error;
XDR cu_outxdrs;
u_int cu_xdrpos;
u_int cu_sendsz;
char *cu_outbuf;
u_int cu_recvsz;
char cu_inbuf[1];
};
 
/*
* Create a UDP based client handle.
* If *sockp<0, *sockp is set to a newly created UPD socket.
* If raddr->sin_port is 0 a binder on the remote machine
* is consulted for the correct port number.
* NB: It is the clients responsibility to close *sockp.
* NB: The rpch->cl_auth is initialized to null authentication.
* Caller may wish to set this something more useful.
*
* wait is the amount of time used between retransmitting a call if
* no response has been heard; retransmission occurs until the actual
* rpc call times out.
*
* sendsz and recvsz are the maximum allowable packet sizes that can be
* sent and received.
*/
CLIENT *
clntudp_bufcreate (struct sockaddr_in *raddr, u_long program, u_long version,
struct timeval wait, int *sockp, u_int sendsz,
u_int recvsz)
{
CLIENT *cl;
struct cu_data *cu = NULL;
struct rpc_msg call_msg;
 
cl = (CLIENT *) mem_alloc (sizeof (CLIENT));
sendsz = ((sendsz + 3) / 4) * 4;
recvsz = ((recvsz + 3) / 4) * 4;
cu = (struct cu_data *) mem_alloc (sizeof (*cu) + sendsz + recvsz);
if (cl == NULL || cu == NULL)
{
struct rpc_createerr *ce = &get_rpc_createerr ();
#ifdef USE_IN_LIBIO
if (_IO_fwide (stderr, 0) > 0)
(void) __fwprintf (stderr, L"%s",
_("clntudp_create: out of memory\n"));
else
#endif
(void) fputs (_("clntudp_create: out of memory\n"), stderr);
ce->cf_stat = RPC_SYSTEMERROR;
ce->cf_error.re_errno = ENOMEM;
goto fooy;
}
cu->cu_outbuf = &cu->cu_inbuf[recvsz];
 
if (raddr->sin_port == 0)
{
u_short port;
if ((port =
pmap_getport (raddr, program, version, IPPROTO_UDP)) == 0)
{
goto fooy;
}
raddr->sin_port = htons (port);
}
cl->cl_ops = &udp_ops;
cl->cl_private = (caddr_t) cu;
cu->cu_raddr = *raddr;
cu->cu_rlen = sizeof (cu->cu_raddr);
cu->cu_wait = wait;
cu->cu_total.tv_sec = -1;
cu->cu_total.tv_usec = -1;
cu->cu_sendsz = sendsz;
cu->cu_recvsz = recvsz;
call_msg.rm_xid = _create_xid ();
call_msg.rm_direction = CALL;
call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
call_msg.rm_call.cb_prog = program;
call_msg.rm_call.cb_vers = version;
xdrmem_create (&(cu->cu_outxdrs), cu->cu_outbuf,
sendsz, XDR_ENCODE);
if (!xdr_callhdr (&(cu->cu_outxdrs), &call_msg))
{
goto fooy;
}
cu->cu_xdrpos = XDR_GETPOS (&(cu->cu_outxdrs));
if (*sockp < 0)
{
int dontblock = 1;
 
*sockp = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (*sockp < 0)
{
struct rpc_createerr *ce = &get_rpc_createerr ();
ce->cf_stat = RPC_SYSTEMERROR;
ce->cf_error.re_errno = errno;
goto fooy;
}
/* attempt to bind to prov port */
(void) bindresvport (*sockp, (struct sockaddr_in *) 0);
/* the sockets rpc controls are non-blocking */
(void) ioctl (*sockp, FIONBIO, (char *) &dontblock);
#ifdef IP_RECVERR
{
int on = 1;
setsockopt(*sockp, SOL_IP, IP_RECVERR, &on, sizeof(on));
}
#endif
cu->cu_closeit = TRUE;
}
else
{
cu->cu_closeit = FALSE;
}
cu->cu_sock = *sockp;
cl->cl_auth = authnone_create ();
return cl;
fooy:
if (cu)
mem_free ((caddr_t) cu, sizeof (*cu) + sendsz + recvsz);
if (cl)
mem_free ((caddr_t) cl, sizeof (CLIENT));
return (CLIENT *) NULL;
}
 
CLIENT *
clntudp_create (raddr, program, version, wait, sockp)
struct sockaddr_in *raddr;
u_long program;
u_long version;
struct timeval wait;
int *sockp;
{
 
return clntudp_bufcreate (raddr, program, version, wait, sockp,
UDPMSGSIZE, UDPMSGSIZE);
}
 
static int
is_network_up (int sock)
{
struct ifconf ifc;
char buf[UDPMSGSIZE];
struct ifreq ifreq, *ifr;
int n;
 
ifc.ifc_len = sizeof (buf);
ifc.ifc_buf = buf;
if (ioctl(sock, SIOCGIFCONF, (char *) &ifc) == 0)
{
ifr = ifc.ifc_req;
for (n = ifc.ifc_len / sizeof (struct ifreq); n > 0; n--, ifr++)
{
ifreq = *ifr;
if (ioctl (sock, SIOCGIFFLAGS, (char *) &ifreq) < 0)
break;
 
if ((ifreq.ifr_flags & IFF_UP)
&& ifr->ifr_addr.sa_family == AF_INET)
return 1;
}
}
return 0;
}
 
static enum clnt_stat
clntudp_call (cl, proc, xargs, argsp, xresults, resultsp, utimeout)
CLIENT *cl; /* client handle */
u_long proc; /* procedure number */
xdrproc_t xargs; /* xdr routine for args */
caddr_t argsp; /* pointer to args */
xdrproc_t xresults; /* xdr routine for results */
caddr_t resultsp; /* pointer to results */
struct timeval utimeout; /* seconds to wait before giving up */
{
struct cu_data *cu = (struct cu_data *) cl->cl_private;
XDR *xdrs;
int outlen = 0;
int inlen;
socklen_t fromlen;
struct pollfd fd;
int milliseconds = (cu->cu_wait.tv_sec * 1000) +
(cu->cu_wait.tv_usec / 1000);
struct sockaddr_in from;
struct rpc_msg reply_msg;
XDR reply_xdrs;
struct timeval time_waited;
bool_t ok;
int nrefreshes = 2; /* number of times to refresh cred */
struct timeval timeout;
int anyup; /* any network interface up */
 
if (cu->cu_total.tv_usec == -1)
{
timeout = utimeout; /* use supplied timeout */
}
else
{
timeout = cu->cu_total; /* use default timeout */
}
 
time_waited.tv_sec = 0;
time_waited.tv_usec = 0;
call_again:
xdrs = &(cu->cu_outxdrs);
if (xargs == NULL)
goto get_reply;
xdrs->x_op = XDR_ENCODE;
XDR_SETPOS (xdrs, cu->cu_xdrpos);
/*
* the transaction is the first thing in the out buffer
*/
(*(uint32_t *) (cu->cu_outbuf))++;
if ((!XDR_PUTLONG (xdrs, (long *) &proc)) ||
(!AUTH_MARSHALL (cl->cl_auth, xdrs)) ||
(!(*xargs) (xdrs, argsp)))
return (cu->cu_error.re_status = RPC_CANTENCODEARGS);
outlen = (int) XDR_GETPOS (xdrs);
 
send_again:
if (sendto (cu->cu_sock, cu->cu_outbuf, outlen, 0,
(struct sockaddr *) &(cu->cu_raddr), cu->cu_rlen)
!= outlen)
{
cu->cu_error.re_errno = errno;
return (cu->cu_error.re_status = RPC_CANTSEND);
}
 
/*
* Hack to provide rpc-based message passing
*/
if (timeout.tv_sec == 0 && timeout.tv_usec == 0)
{
return (cu->cu_error.re_status = RPC_TIMEDOUT);
}
get_reply:
/*
* sub-optimal code appears here because we have
* some clock time to spare while the packets are in flight.
* (We assume that this is actually only executed once.)
*/
reply_msg.acpted_rply.ar_verf = _null_auth;
reply_msg.acpted_rply.ar_results.where = resultsp;
reply_msg.acpted_rply.ar_results.proc = xresults;
fd.fd = cu->cu_sock;
fd.events = POLLIN;
anyup = 0;
for (;;)
{
switch (poll (&fd, 1, milliseconds))
{
 
case 0:
if (anyup == 0)
{
anyup = is_network_up (cu->cu_sock);
if (!anyup)
return (cu->cu_error.re_status = RPC_CANTRECV);
}
 
time_waited.tv_sec += cu->cu_wait.tv_sec;
time_waited.tv_usec += cu->cu_wait.tv_usec;
while (time_waited.tv_usec >= 1000000)
{
time_waited.tv_sec++;
time_waited.tv_usec -= 1000000;
}
if ((time_waited.tv_sec < timeout.tv_sec) ||
((time_waited.tv_sec == timeout.tv_sec) &&
(time_waited.tv_usec < timeout.tv_usec)))
goto send_again;
return (cu->cu_error.re_status = RPC_TIMEDOUT);
 
/*
* buggy in other cases because time_waited is not being
* updated.
*/
case -1:
if (errno == EINTR)
continue;
cu->cu_error.re_errno = errno;
return (cu->cu_error.re_status = RPC_CANTRECV);
}
#ifdef IP_RECVERR
if (fd.revents & POLLERR)
{
struct msghdr msg;
struct cmsghdr *cmsg;
struct sock_extended_err *e;
struct sockaddr_in err_addr;
struct iovec iov;
char *cbuf = (char *) alloca (outlen + 256);
int ret;
 
iov.iov_base = cbuf + 256;
iov.iov_len = outlen;
msg.msg_name = (void *) &err_addr;
msg.msg_namelen = sizeof (err_addr);
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
msg.msg_flags = 0;
msg.msg_control = cbuf;
msg.msg_controllen = 256;
ret = recvmsg (cu->cu_sock, &msg, MSG_ERRQUEUE);
if (ret >= 0
&& memcmp (cbuf + 256, cu->cu_outbuf, ret) == 0
&& (msg.msg_flags & MSG_ERRQUEUE)
&& ((msg.msg_namelen == 0
&& ret >= 12)
|| (msg.msg_namelen == sizeof (err_addr)
&& err_addr.sin_family == AF_INET
&& memcmp (&err_addr.sin_addr, &cu->cu_raddr.sin_addr,
sizeof (err_addr.sin_addr)) == 0
&& err_addr.sin_port == cu->cu_raddr.sin_port)))
for (cmsg = CMSG_FIRSTHDR (&msg); cmsg;
cmsg = CMSG_NXTHDR (&msg, cmsg))
if (cmsg->cmsg_level == SOL_IP && cmsg->cmsg_type == IP_RECVERR)
{
e = (struct sock_extended_err *) CMSG_DATA(cmsg);
cu->cu_error.re_errno = e->ee_errno;
return (cu->cu_error.re_status = RPC_CANTRECV);
}
}
#endif
do
{
fromlen = sizeof (struct sockaddr);
inlen = recvfrom (cu->cu_sock, cu->cu_inbuf,
(int) cu->cu_recvsz, 0,
(struct sockaddr *) &from, &fromlen);
}
while (inlen < 0 && errno == EINTR);
if (inlen < 0)
{
if (errno == EWOULDBLOCK)
continue;
cu->cu_error.re_errno = errno;
return (cu->cu_error.re_status = RPC_CANTRECV);
}
if (inlen < 4)
continue;
 
/* see if reply transaction id matches sent id.
Don't do this if we only wait for a replay */
if (xargs != NULL
&& (*((u_int32_t *) (cu->cu_inbuf))
!= *((u_int32_t *) (cu->cu_outbuf))))
continue;
/* we now assume we have the proper reply */
break;
}
 
/*
* now decode and validate the response
*/
xdrmem_create (&reply_xdrs, cu->cu_inbuf, (u_int) inlen, XDR_DECODE);
ok = xdr_replymsg (&reply_xdrs, &reply_msg);
/* XDR_DESTROY(&reply_xdrs); save a few cycles on noop destroy */
if (ok)
{
_seterr_reply (&reply_msg, &(cu->cu_error));
if (cu->cu_error.re_status == RPC_SUCCESS)
{
if (!AUTH_VALIDATE (cl->cl_auth,
&reply_msg.acpted_rply.ar_verf))
{
cu->cu_error.re_status = RPC_AUTHERROR;
cu->cu_error.re_why = AUTH_INVALIDRESP;
}
if (reply_msg.acpted_rply.ar_verf.oa_base != NULL)
{
xdrs->x_op = XDR_FREE;
(void) xdr_opaque_auth (xdrs,
&(reply_msg.acpted_rply.ar_verf));
}
} /* end successful completion */
else
{
/* maybe our credentials need to be refreshed ... */
if (nrefreshes > 0 && AUTH_REFRESH (cl->cl_auth))
{
nrefreshes--;
goto call_again;
}
} /* end of unsuccessful completion */
} /* end of valid reply message */
else
{
cu->cu_error.re_status = RPC_CANTDECODERES;
}
return cu->cu_error.re_status;
}
 
static void
clntudp_geterr (CLIENT *cl, struct rpc_err *errp)
{
struct cu_data *cu = (struct cu_data *) cl->cl_private;
 
*errp = cu->cu_error;
}
 
 
static bool_t
clntudp_freeres (CLIENT *cl, xdrproc_t xdr_res, caddr_t res_ptr)
{
struct cu_data *cu = (struct cu_data *) cl->cl_private;
XDR *xdrs = &(cu->cu_outxdrs);
 
xdrs->x_op = XDR_FREE;
return (*xdr_res) (xdrs, res_ptr);
}
 
static void
clntudp_abort (void)
{
}
 
static bool_t
clntudp_control (CLIENT *cl, int request, char *info)
{
struct cu_data *cu = (struct cu_data *) cl->cl_private;
 
switch (request)
{
case CLSET_FD_CLOSE:
cu->cu_closeit = TRUE;
break;
case CLSET_FD_NCLOSE:
cu->cu_closeit = FALSE;
break;
case CLSET_TIMEOUT:
cu->cu_total = *(struct timeval *) info;
break;
case CLGET_TIMEOUT:
*(struct timeval *) info = cu->cu_total;
break;
case CLSET_RETRY_TIMEOUT:
cu->cu_wait = *(struct timeval *) info;
break;
case CLGET_RETRY_TIMEOUT:
*(struct timeval *) info = cu->cu_wait;
break;
case CLGET_SERVER_ADDR:
*(struct sockaddr_in *) info = cu->cu_raddr;
break;
case CLGET_FD:
*(int *)info = cu->cu_sock;
break;
case CLGET_XID:
/*
* use the knowledge that xid is the
* first element in the call structure *.
* This will get the xid of the PREVIOUS call
*/
*(u_long *)info = ntohl(*(u_long *)cu->cu_outbuf);
break;
case CLSET_XID:
/* This will set the xid of the NEXT call */
*(u_long *)cu->cu_outbuf = htonl(*(u_long *)info - 1);
/* decrement by 1 as clntudp_call() increments once */
case CLGET_VERS:
/*
* This RELIES on the information that, in the call body,
* the version number field is the fifth field from the
* begining of the RPC header. MUST be changed if the
* call_struct is changed
*/
*(u_long *)info = ntohl(*(u_long *)(cu->cu_outbuf +
4 * BYTES_PER_XDR_UNIT));
break;
case CLSET_VERS:
*(u_long *)(cu->cu_outbuf + 4 * BYTES_PER_XDR_UNIT)
= htonl(*(u_long *)info);
break;
case CLGET_PROG:
/*
* This RELIES on the information that, in the call body,
* the program number field is the field from the
* begining of the RPC header. MUST be changed if the
* call_struct is changed
*/
*(u_long *)info = ntohl(*(u_long *)(cu->cu_outbuf +
3 * BYTES_PER_XDR_UNIT));
break;
case CLSET_PROG:
*(u_long *)(cu->cu_outbuf + 3 * BYTES_PER_XDR_UNIT)
= htonl(*(u_long *)info);
break;
/* The following are only possible with TI-RPC */
case CLGET_SVC_ADDR:
case CLSET_SVC_ADDR:
case CLSET_PUSH_TIMOD:
case CLSET_POP_TIMOD:
default:
return FALSE;
}
return TRUE;
}
 
static void
clntudp_destroy (CLIENT *cl)
{
struct cu_data *cu = (struct cu_data *) cl->cl_private;
 
if (cu->cu_closeit)
{
(void) close (cu->cu_sock);
}
XDR_DESTROY (&(cu->cu_outxdrs));
mem_free ((caddr_t) cu, (sizeof (*cu) + cu->cu_sendsz + cu->cu_recvsz));
mem_free ((caddr_t) cl, sizeof (CLIENT));
}
/rpc/clnt_simple.c
0,0 → 1,164
/* @(#)clnt_simple.c 2.2 88/08/01 4.0 RPCSRC */
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
* media and as a part of the software program in whole or part. Users
* may copy or modify Sun RPC without charge, but are not authorized
* to license or distribute it to anyone else except as part of a product or
* program developed by the user.
*
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun RPC is provided with no support and without any obligation on the
* part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
#if 0
static char sccsid[] = "@(#)clnt_simple.c 1.35 87/08/11 Copyr 1984 Sun Micro";
#endif
 
/*
* clnt_simple.c
* Simplified front end to rpc.
*
* Copyright (C) 1984, Sun Microsystems, Inc.
*/
 
#define __FORCE_GLIBC
#include <features.h>
 
#include <alloca.h>
#include <errno.h>
#include <stdio.h>
#include <unistd.h>
#include "rpc_private.h"
#include <sys/socket.h>
#include <netdb.h>
#include <string.h>
 
struct callrpc_private_s
{
CLIENT *client;
int socket;
u_long oldprognum, oldversnum, valid;
char *oldhost;
};
#ifdef __UCLIBC_HAS_THREADS__
#define callrpc_private ((struct callrpc_private_s *)RPC_THREAD_VARIABLE(callrpc_private_s))
#else
static struct callrpc_private_s *callrpc_private;
#endif
 
int
callrpc (const char *host, u_long prognum, u_long versnum, u_long procnum,
xdrproc_t inproc, const char *in, xdrproc_t outproc, char *out)
{
struct callrpc_private_s *crp = callrpc_private;
struct sockaddr_in server_addr;
enum clnt_stat clnt_stat;
struct hostent hostbuf, *hp;
struct timeval timeout, tottimeout;
 
if (crp == 0)
{
crp = (struct callrpc_private_s *) calloc (1, sizeof (*crp));
if (crp == 0)
return 0;
callrpc_private = crp;
}
if (crp->oldhost == NULL)
{
crp->oldhost = malloc (256);
crp->oldhost[0] = 0;
crp->socket = RPC_ANYSOCK;
}
if (crp->valid && crp->oldprognum == prognum && crp->oldversnum == versnum
&& strcmp (crp->oldhost, host) == 0)
{
/* reuse old client */
}
else
{
size_t buflen;
char *buffer;
int herr;
 
crp->valid = 0;
if (crp->socket != RPC_ANYSOCK)
{
(void) close (crp->socket);
crp->socket = RPC_ANYSOCK;
}
if (crp->client)
{
clnt_destroy (crp->client);
crp->client = NULL;
}
 
buflen = 1024;
buffer = alloca (buflen);
while (gethostbyname_r (host, &hostbuf, buffer, buflen,
&hp, &herr) != 0
|| hp == NULL)
if (herr != NETDB_INTERNAL || errno != ERANGE)
return (int) RPC_UNKNOWNHOST;
else
{
/* Enlarge the buffer. */
buflen *= 2;
buffer = alloca (buflen);
}
 
timeout.tv_usec = 0;
timeout.tv_sec = 5;
memcpy ((char *) &server_addr.sin_addr, hp->h_addr, hp->h_length);
server_addr.sin_family = AF_INET;
server_addr.sin_port = 0;
if ((crp->client = clntudp_create (&server_addr, (u_long) prognum,
(u_long) versnum, timeout, &crp->socket)) == NULL)
return (int) get_rpc_createerr().cf_stat;
crp->valid = 1;
crp->oldprognum = prognum;
crp->oldversnum = versnum;
(void) strncpy (crp->oldhost, host, 255);
crp->oldhost[255] = '\0';
}
tottimeout.tv_sec = 25;
tottimeout.tv_usec = 0;
clnt_stat = clnt_call (crp->client, procnum, inproc, (char *) in,
outproc, out, tottimeout);
/*
* if call failed, empty cache
*/
if (clnt_stat != RPC_SUCCESS)
crp->valid = 0;
return (int) clnt_stat;
}
 
#ifdef __UCLIBC_HAS_THREADS__
void
__rpc_thread_clnt_cleanup (void)
{
struct callrpc_private_s *rcp = RPC_THREAD_VARIABLE(callrpc_private_s);
 
if (rcp) {
if (rcp->client)
CLNT_DESTROY (rcp->client);
free (rcp);
}
}
#endif /* __UCLIBC_HAS_THREADS__ */
/rpc/authunix_prot.c
0,0 → 1,65
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
* media and as a part of the software program in whole or part. Users
* may copy or modify Sun RPC without charge, but are not authorized
* to license or distribute it to anyone else except as part of a product or
* program developed by the user.
*
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun RPC is provided with no support and without any obligation on the
* part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
/*
* Copyright (C) 1984, Sun Microsystems, Inc.
*/
/*
* authunix_prot.c
* XDR for UNIX style authentication parameters for RPC
*/
 
#include <rpc/types.h>
#include <rpc/xdr.h>
#include <rpc/auth.h>
#include <rpc/auth_unix.h>
 
/*
* XDR for unix authentication parameters.
* Unfortunately, none of these can be declared const.
*/
bool_t
xdr_authunix_parms (XDR * xdrs, struct authunix_parms *p)
{
if (xdr_u_long (xdrs, &(p->aup_time))
&& xdr_string (xdrs, &(p->aup_machname), MAX_MACHINE_NAME)
&& (sizeof (uid_t) == sizeof (short int)
? xdr_u_short (xdrs, (u_short *) & (p->aup_uid))
: xdr_u_int (xdrs, (u_int *) & (p->aup_uid)))
&& (sizeof (gid_t) == sizeof (short int)
? xdr_u_short (xdrs, (u_short *) & (p->aup_gid))
: xdr_u_int (xdrs, (u_int *) & (p->aup_gid)))
&& xdr_array (xdrs, (caddr_t *) & (p->aup_gids),
& (p->aup_len), NGRPS, sizeof (gid_t),
(sizeof (gid_t) == sizeof (short int)
? (xdrproc_t) xdr_u_short : (xdrproc_t) xdr_u_int)))
{
return TRUE;
}
return FALSE;
}
/rpc/rpc_thread.c
0,0 → 1,171
#define __FORCE_GLIBC
#include <features.h>
#include <stdio.h>
#include <assert.h>
#include <bits/libc-tsd.h>
#include "rpc_private.h"
 
#ifdef __UCLIBC_HAS_THREADS__
 
/* Variable used in non-threaded applications or for the first thread. */
static struct rpc_thread_variables __libc_tsd_RPC_VARS_mem;
static struct rpc_thread_variables *__libc_tsd_RPC_VARS_data =
&__libc_tsd_RPC_VARS_mem;
 
/*
* Task-variable destructor
*/
void
__rpc_thread_destroy (void)
{
struct rpc_thread_variables *tvp = __rpc_thread_variables();
 
if (tvp != NULL && tvp != &__libc_tsd_RPC_VARS_mem) {
__rpc_thread_svc_cleanup ();
__rpc_thread_clnt_cleanup ();
//__rpc_thread_key_cleanup ();
free (tvp->authnone_private_s);
free (tvp->clnt_perr_buf_s);
free (tvp->clntraw_private_s);
free (tvp->svcraw_private_s);
free (tvp->authdes_cache_s);
free (tvp->authdes_lru_s);
free (tvp);
}
}
 
 
extern int __pthread_once (pthread_once_t *__once_control,
void (*__init_routine) (void));
 
# define __libc_once_define(CLASS, NAME) \
CLASS pthread_once_t NAME = PTHREAD_ONCE_INIT
 
/* Call handler iff the first call. */
#define __libc_once(ONCE_CONTROL, INIT_FUNCTION) \
do { \
if (__pthread_once != NULL) \
__pthread_once (&(ONCE_CONTROL), (INIT_FUNCTION)); \
else if ((ONCE_CONTROL) == PTHREAD_ONCE_INIT) { \
INIT_FUNCTION (); \
(ONCE_CONTROL) = !PTHREAD_ONCE_INIT; \
} \
} while (0)
 
/*
* Initialize RPC multi-threaded operation
*/
static void
rpc_thread_multi (void)
{
__libc_tsd_set (RPC_VARS, &__libc_tsd_RPC_VARS_mem);
}
 
 
struct rpc_thread_variables *
__rpc_thread_variables (void)
{
__libc_once_define (static, once);
struct rpc_thread_variables *tvp;
 
tvp = __libc_tsd_get (RPC_VARS);
if (tvp == NULL) {
__libc_once (once, rpc_thread_multi);
tvp = __libc_tsd_get (RPC_VARS);
if (tvp == NULL) {
tvp = calloc (1, sizeof *tvp);
if (tvp != NULL)
__libc_tsd_set (RPC_VARS, tvp);
else
tvp = __libc_tsd_RPC_VARS_data;
}
}
return tvp;
}
 
 
/* Global variables If we're single-threaded, or if this is the first
thread using the variable, use the existing global variable. This
provides backwards compatability for existing applications which
dynamically link against this code. */
#undef svc_fdset
#undef rpc_createerr
#undef svc_pollfd
#undef svc_max_pollfd
 
fd_set *
__rpc_thread_svc_fdset (void)
{
struct rpc_thread_variables *tvp;
 
tvp = __rpc_thread_variables ();
if (tvp == &__libc_tsd_RPC_VARS_mem)
return &svc_fdset;
return &tvp->svc_fdset_s;
}
 
struct rpc_createerr *
__rpc_thread_createerr (void)
{
struct rpc_thread_variables *tvp;
 
tvp = __rpc_thread_variables ();
if (tvp == &__libc_tsd_RPC_VARS_mem)
return &rpc_createerr;
return &tvp->rpc_createerr_s;
}
 
struct pollfd **
__rpc_thread_svc_pollfd (void)
{
struct rpc_thread_variables *tvp;
 
tvp = __rpc_thread_variables ();
if (tvp == &__libc_tsd_RPC_VARS_mem)
return &svc_pollfd;
return &tvp->svc_pollfd_s;
}
 
int *
__rpc_thread_svc_max_pollfd (void)
{
struct rpc_thread_variables *tvp;
 
tvp = __rpc_thread_variables ();
if (tvp == &__libc_tsd_RPC_VARS_mem)
return &svc_max_pollfd;
return &tvp->svc_max_pollfd_s;
}
#else
 
#undef svc_fdset
#undef rpc_createerr
#undef svc_pollfd
#undef svc_max_pollfd
 
fd_set * __rpc_thread_svc_fdset (void)
{
extern fd_set svc_fdset;
return &(svc_fdset);
}
 
struct rpc_createerr * __rpc_thread_createerr (void)
{
extern struct rpc_createerr rpc_createerr;
return &(rpc_createerr);
}
 
struct pollfd ** __rpc_thread_svc_pollfd (void)
{
extern struct pollfd *svc_pollfd;
return &(svc_pollfd);
}
 
int * __rpc_thread_svc_max_pollfd (void)
{
extern int svc_max_pollfd;
return &(svc_max_pollfd);
}
 
#endif /* __UCLIBC_HAS_THREADS__ */
 
/rpc/auth_none.c
0,0 → 1,134
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
* media and as a part of the software program in whole or part. Users
* may copy or modify Sun RPC without charge, but are not authorized
* to license or distribute it to anyone else except as part of a product or
* program developed by the user.
*
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun RPC is provided with no support and without any obligation on the
* part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
/*
* Copyright (C) 1984, Sun Microsystems, Inc.
*/
/*
* auth_none.c
* Creates a client authentication handle for passing "null"
* credentials and verifiers to remote systems.
*/
 
#define __FORCE_GLIBC
#include <features.h>
#include "rpc_private.h"
 
#define MAX_MARSHEL_SIZE 20
 
/*
* Authenticator operations routines
*/
static void authnone_verf (AUTH *);
static void authnone_destroy (AUTH *);
static bool_t authnone_marshal (AUTH *, XDR *);
static bool_t authnone_validate (AUTH *, struct opaque_auth *);
static bool_t authnone_refresh (AUTH *);
 
static struct auth_ops ops = {
authnone_verf,
authnone_marshal,
authnone_validate,
authnone_refresh,
authnone_destroy
};
 
struct authnone_private_s {
AUTH no_client;
char marshalled_client[MAX_MARSHEL_SIZE];
u_int mcnt;
};
#ifdef __UCLIBC_HAS_THREADS__
#define authnone_private ((struct authnone_private_s *)RPC_THREAD_VARIABLE(authnone_private_s))
#else
static struct authnone_private_s *authnone_private;
#endif
 
AUTH *
authnone_create (void)
{
struct authnone_private_s *ap;
XDR xdr_stream;
XDR *xdrs;
 
ap = (struct authnone_private_s *) authnone_private;
if (ap == NULL)
{
ap = (struct authnone_private_s *) calloc (1, sizeof (*ap));
if (ap == NULL)
return NULL;
authnone_private = ap;
}
if (!ap->mcnt)
{
ap->no_client.ah_cred = ap->no_client.ah_verf = _null_auth;
ap->no_client.ah_ops = &ops;
xdrs = &xdr_stream;
xdrmem_create (xdrs, ap->marshalled_client, (u_int) MAX_MARSHEL_SIZE,
XDR_ENCODE);
(void) xdr_opaque_auth (xdrs, &ap->no_client.ah_cred);
(void) xdr_opaque_auth (xdrs, &ap->no_client.ah_verf);
ap->mcnt = XDR_GETPOS (xdrs);
XDR_DESTROY (xdrs);
}
return (&ap->no_client);
}
 
/*ARGSUSED */
static bool_t
authnone_marshal (AUTH *client, XDR *xdrs)
{
struct authnone_private_s *ap;
 
ap = (struct authnone_private_s *) authnone_private;
if (ap == NULL)
return FALSE;
return (*xdrs->x_ops->x_putbytes) (xdrs, ap->marshalled_client, ap->mcnt);
}
 
static void
authnone_verf (AUTH *auth)
{
}
 
static bool_t
authnone_validate (AUTH *auth, struct opaque_auth *oa)
{
return TRUE;
}
 
static bool_t
authnone_refresh (AUTH *auth)
{
return FALSE;
}
 
static void
authnone_destroy (AUTH *auth)
{
}
/rpc/xdr_rec.c
0,0 → 1,664
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
* media and as a part of the software program in whole or part. Users
* may copy or modify Sun RPC without charge, but are not authorized
* to license or distribute it to anyone else except as part of a product or
* program developed by the user.
*
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun RPC is provided with no support and without any obligation on the
* part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
 
/*
* xdr_rec.c, Implements TCP/IP based XDR streams with a "record marking"
* layer above tcp (for rpc's use).
*
* Copyright (C) 1984, Sun Microsystems, Inc.
*
* These routines interface XDRSTREAMS to a tcp/ip connection.
* There is a record marking layer between the xdr stream
* and the tcp transport level. A record is composed on one or more
* record fragments. A record fragment is a thirty-two bit header followed
* by n bytes of data, where n is contained in the header. The header
* is represented as a htonl(u_long). The high order bit encodes
* whether or not the fragment is the last fragment of the record
* (1 => fragment is last, 0 => more fragments to follow.
* The other 31 bits encode the byte length of the fragment.
*/
 
#define __FORCE_GLIBC
#define _GNU_SOURCE
#include <features.h>
 
 
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <rpc/rpc.h>
 
#ifdef USE_IN_LIBIO
# include <wchar.h>
# include <libio/iolibio.h>
# define fputs(s, f) _IO_fputs (s, f)
#endif
 
static bool_t xdrrec_getlong (XDR *, long *);
static bool_t xdrrec_putlong (XDR *, const long *);
static bool_t xdrrec_getbytes (XDR *, caddr_t, u_int);
static bool_t xdrrec_putbytes (XDR *, const char *, u_int);
static u_int xdrrec_getpos (const XDR *);
static bool_t xdrrec_setpos (XDR *, u_int);
static int32_t *xdrrec_inline (XDR *, int);
static void xdrrec_destroy (XDR *);
static bool_t xdrrec_getint32 (XDR *, int32_t *);
static bool_t xdrrec_putint32 (XDR *, const int32_t *);
 
static const struct xdr_ops xdrrec_ops = {
xdrrec_getlong,
xdrrec_putlong,
xdrrec_getbytes,
xdrrec_putbytes,
xdrrec_getpos,
xdrrec_setpos,
xdrrec_inline,
xdrrec_destroy,
xdrrec_getint32,
xdrrec_putint32
};
 
/*
* A record is composed of one or more record fragments.
* A record fragment is a two-byte header followed by zero to
* 2**32-1 bytes. The header is treated as a long unsigned and is
* encode/decoded to the network via htonl/ntohl. The low order 31 bits
* are a byte count of the fragment. The highest order bit is a boolean:
* 1 => this fragment is the last fragment of the record,
* 0 => this fragment is followed by more fragment(s).
*
* The fragment/record machinery is not general; it is constructed to
* meet the needs of xdr and rpc based on tcp.
*/
 
#define LAST_FRAG (1UL << 31)
 
typedef struct rec_strm
{
caddr_t tcp_handle;
caddr_t the_buffer;
/*
* out-going bits
*/
int (*writeit) (char *, char *, int);
caddr_t out_base; /* output buffer (points to frag header) */
caddr_t out_finger; /* next output position */
caddr_t out_boundry; /* data cannot up to this address */
u_int32_t *frag_header; /* beginning of curren fragment */
bool_t frag_sent; /* true if buffer sent in middle of record */
/*
* in-coming bits
*/
int (*readit) (char *, char *, int);
u_long in_size; /* fixed size of the input buffer */
caddr_t in_base;
caddr_t in_finger; /* location of next byte to be had */
caddr_t in_boundry; /* can read up to this location */
long fbtbc; /* fragment bytes to be consumed */
bool_t last_frag;
u_int sendsize;
u_int recvsize;
}
RECSTREAM;
 
static u_int fix_buf_size (u_int) internal_function;
static bool_t skip_input_bytes (RECSTREAM *, long) internal_function;
static bool_t flush_out (RECSTREAM *, bool_t) internal_function;
static bool_t set_input_fragment (RECSTREAM *) internal_function;
static bool_t get_input_bytes (RECSTREAM *, caddr_t, int) internal_function;
 
/*
* Create an xdr handle for xdrrec
* xdrrec_create fills in xdrs. Sendsize and recvsize are
* send and recv buffer sizes (0 => use default).
* tcp_handle is an opaque handle that is passed as the first parameter to
* the procedures readit and writeit. Readit and writeit are read and
* write respectively. They are like the system
* calls expect that they take an opaque handle rather than an fd.
*/
void
xdrrec_create (XDR *xdrs, u_int sendsize,
u_int recvsize, caddr_t tcp_handle,
int (*readit) (char *, char *, int),
int (*writeit) (char *, char *, int))
{
RECSTREAM *rstrm = (RECSTREAM *) mem_alloc (sizeof (RECSTREAM));
caddr_t tmp;
char *buf;
 
sendsize = fix_buf_size (sendsize);
recvsize = fix_buf_size (recvsize);
buf = mem_alloc (sendsize + recvsize + BYTES_PER_XDR_UNIT);
 
if (rstrm == NULL || buf == NULL)
{
#ifdef USE_IN_LIBIO
if (_IO_fwide (stderr, 0) > 0)
(void) __fwprintf (stderr, L"%s", _("xdrrec_create: out of memory\n"));
else
#endif
(void) fputs (_("xdrrec_create: out of memory\n"), stderr);
mem_free (rstrm, sizeof (RECSTREAM));
mem_free (buf, sendsize + recvsize + BYTES_PER_XDR_UNIT);
/*
* This is bad. Should rework xdrrec_create to
* return a handle, and in this case return NULL
*/
return;
}
/*
* adjust sizes and allocate buffer quad byte aligned
*/
rstrm->sendsize = sendsize;
rstrm->recvsize = recvsize;
rstrm->the_buffer = buf;
tmp = rstrm->the_buffer;
if ((size_t)tmp % BYTES_PER_XDR_UNIT)
tmp += BYTES_PER_XDR_UNIT - (size_t)tmp % BYTES_PER_XDR_UNIT;
rstrm->out_base = tmp;
rstrm->in_base = tmp + sendsize;
/*
* now the rest ...
*/
/* We have to add the const since the `struct xdr_ops' in `struct XDR'
is not `const'. */
xdrs->x_ops = (struct xdr_ops *) &xdrrec_ops;
xdrs->x_private = (caddr_t) rstrm;
rstrm->tcp_handle = tcp_handle;
rstrm->readit = readit;
rstrm->writeit = writeit;
rstrm->out_finger = rstrm->out_boundry = rstrm->out_base;
rstrm->frag_header = (u_int32_t *) rstrm->out_base;
rstrm->out_finger += 4;
rstrm->out_boundry += sendsize;
rstrm->frag_sent = FALSE;
rstrm->in_size = recvsize;
rstrm->in_boundry = rstrm->in_base;
rstrm->in_finger = (rstrm->in_boundry += recvsize);
rstrm->fbtbc = 0;
rstrm->last_frag = TRUE;
}
 
 
/*
* The routines defined below are the xdr ops which will go into the
* xdr handle filled in by xdrrec_create.
*/
 
static bool_t
xdrrec_getlong (XDR *xdrs, long *lp)
{
RECSTREAM *rstrm = (RECSTREAM *) xdrs->x_private;
int32_t *buflp = (int32_t *) rstrm->in_finger;
int32_t mylong;
 
/* first try the inline, fast case */
if (rstrm->fbtbc >= BYTES_PER_XDR_UNIT &&
rstrm->in_boundry - (char *) buflp >= BYTES_PER_XDR_UNIT)
{
*lp = (int32_t) ntohl (*buflp);
rstrm->fbtbc -= BYTES_PER_XDR_UNIT;
rstrm->in_finger += BYTES_PER_XDR_UNIT;
}
else
{
if (!xdrrec_getbytes (xdrs, (caddr_t) & mylong,
BYTES_PER_XDR_UNIT))
return FALSE;
*lp = (int32_t) ntohl (mylong);
}
return TRUE;
}
 
static bool_t
xdrrec_putlong (XDR *xdrs, const long *lp)
{
RECSTREAM *rstrm = (RECSTREAM *) xdrs->x_private;
int32_t *dest_lp = (int32_t *) rstrm->out_finger;
 
if ((rstrm->out_finger += BYTES_PER_XDR_UNIT) > rstrm->out_boundry)
{
/*
* this case should almost never happen so the code is
* inefficient
*/
rstrm->out_finger -= BYTES_PER_XDR_UNIT;
rstrm->frag_sent = TRUE;
if (!flush_out (rstrm, FALSE))
return FALSE;
dest_lp = (int32_t *) rstrm->out_finger;
rstrm->out_finger += BYTES_PER_XDR_UNIT;
}
*dest_lp = htonl (*lp);
return TRUE;
}
 
static bool_t /* must manage buffers, fragments, and records */
xdrrec_getbytes (XDR *xdrs, caddr_t addr, u_int len)
{
RECSTREAM *rstrm = (RECSTREAM *) xdrs->x_private;
u_int current;
 
while (len > 0)
{
current = rstrm->fbtbc;
if (current == 0)
{
if (rstrm->last_frag)
return FALSE;
if (!set_input_fragment (rstrm))
return FALSE;
continue;
}
current = (len < current) ? len : current;
if (!get_input_bytes (rstrm, addr, current))
return FALSE;
addr += current;
rstrm->fbtbc -= current;
len -= current;
}
return TRUE;
}
 
static bool_t
xdrrec_putbytes (XDR *xdrs, const char *addr, u_int len)
{
RECSTREAM *rstrm = (RECSTREAM *) xdrs->x_private;
u_int current;
 
while (len > 0)
{
current = rstrm->out_boundry - rstrm->out_finger;
current = (len < current) ? len : current;
memcpy (rstrm->out_finger, addr, current);
rstrm->out_finger += current;
addr += current;
len -= current;
if (rstrm->out_finger == rstrm->out_boundry && len > 0)
{
rstrm->frag_sent = TRUE;
if (!flush_out (rstrm, FALSE))
return FALSE;
}
}
return TRUE;
}
 
static u_int
xdrrec_getpos (const XDR *xdrs)
{
RECSTREAM *rstrm = (RECSTREAM *) xdrs->x_private;
long pos;
 
pos = lseek ((int) (long) rstrm->tcp_handle, (long) 0, 1);
if (pos != -1)
switch (xdrs->x_op)
{
 
case XDR_ENCODE:
pos += rstrm->out_finger - rstrm->out_base;
break;
 
case XDR_DECODE:
pos -= rstrm->in_boundry - rstrm->in_finger;
break;
 
default:
pos = (u_int) - 1;
break;
}
return (u_int) pos;
}
 
static bool_t
xdrrec_setpos (XDR *xdrs, u_int pos)
{
RECSTREAM *rstrm = (RECSTREAM *) xdrs->x_private;
u_int currpos = xdrrec_getpos (xdrs);
int delta = currpos - pos;
caddr_t newpos;
 
if ((int) currpos != -1)
switch (xdrs->x_op)
{
 
case XDR_ENCODE:
newpos = rstrm->out_finger - delta;
if (newpos > (caddr_t) rstrm->frag_header &&
newpos < rstrm->out_boundry)
{
rstrm->out_finger = newpos;
return TRUE;
}
break;
 
case XDR_DECODE:
newpos = rstrm->in_finger - delta;
if ((delta < (int) (rstrm->fbtbc)) &&
(newpos <= rstrm->in_boundry) &&
(newpos >= rstrm->in_base))
{
rstrm->in_finger = newpos;
rstrm->fbtbc -= delta;
return TRUE;
}
break;
 
default:
break;
}
return FALSE;
}
 
static int32_t *
xdrrec_inline (XDR *xdrs, int len)
{
RECSTREAM *rstrm = (RECSTREAM *) xdrs->x_private;
int32_t *buf = NULL;
 
switch (xdrs->x_op)
{
 
case XDR_ENCODE:
if ((rstrm->out_finger + len) <= rstrm->out_boundry)
{
buf = (int32_t *) rstrm->out_finger;
rstrm->out_finger += len;
}
break;
 
case XDR_DECODE:
if ((len <= rstrm->fbtbc) &&
((rstrm->in_finger + len) <= rstrm->in_boundry))
{
buf = (int32_t *) rstrm->in_finger;
rstrm->fbtbc -= len;
rstrm->in_finger += len;
}
break;
 
default:
break;
}
return buf;
}
 
static void
xdrrec_destroy (XDR *xdrs)
{
RECSTREAM *rstrm = (RECSTREAM *) xdrs->x_private;
 
mem_free (rstrm->the_buffer,
rstrm->sendsize + rstrm->recvsize + BYTES_PER_XDR_UNIT);
mem_free ((caddr_t) rstrm, sizeof (RECSTREAM));
}
 
static bool_t
xdrrec_getint32 (XDR *xdrs, int32_t *ip)
{
RECSTREAM *rstrm = (RECSTREAM *) xdrs->x_private;
int32_t *bufip = (int32_t *) rstrm->in_finger;
int32_t mylong;
 
/* first try the inline, fast case */
if (rstrm->fbtbc >= BYTES_PER_XDR_UNIT &&
rstrm->in_boundry - (char *) bufip >= BYTES_PER_XDR_UNIT)
{
*ip = ntohl (*bufip);
rstrm->fbtbc -= BYTES_PER_XDR_UNIT;
rstrm->in_finger += BYTES_PER_XDR_UNIT;
}
else
{
if (!xdrrec_getbytes (xdrs, (caddr_t) &mylong,
BYTES_PER_XDR_UNIT))
return FALSE;
*ip = ntohl (mylong);
}
return TRUE;
}
 
static bool_t
xdrrec_putint32 (XDR *xdrs, const int32_t *ip)
{
RECSTREAM *rstrm = (RECSTREAM *) xdrs->x_private;
int32_t *dest_ip = (int32_t *) rstrm->out_finger;
 
if ((rstrm->out_finger += BYTES_PER_XDR_UNIT) > rstrm->out_boundry)
{
/*
* this case should almost never happen so the code is
* inefficient
*/
rstrm->out_finger -= BYTES_PER_XDR_UNIT;
rstrm->frag_sent = TRUE;
if (!flush_out (rstrm, FALSE))
return FALSE;
dest_ip = (int32_t *) rstrm->out_finger;
rstrm->out_finger += BYTES_PER_XDR_UNIT;
}
*dest_ip = htonl (*ip);
return TRUE;
}
 
/*
* Exported routines to manage xdr records
*/
 
/*
* Before reading (deserializing from the stream, one should always call
* this procedure to guarantee proper record alignment.
*/
bool_t
xdrrec_skiprecord (XDR *xdrs)
{
RECSTREAM *rstrm = (RECSTREAM *) xdrs->x_private;
 
while (rstrm->fbtbc > 0 || (!rstrm->last_frag))
{
if (!skip_input_bytes (rstrm, rstrm->fbtbc))
return FALSE;
rstrm->fbtbc = 0;
if ((!rstrm->last_frag) && (!set_input_fragment (rstrm)))
return FALSE;
}
rstrm->last_frag = FALSE;
return TRUE;
}
 
/*
* Lookahead function.
* Returns TRUE iff there is no more input in the buffer
* after consuming the rest of the current record.
*/
bool_t
xdrrec_eof (XDR *xdrs)
{
RECSTREAM *rstrm = (RECSTREAM *) xdrs->x_private;
 
while (rstrm->fbtbc > 0 || (!rstrm->last_frag))
{
if (!skip_input_bytes (rstrm, rstrm->fbtbc))
return TRUE;
rstrm->fbtbc = 0;
if ((!rstrm->last_frag) && (!set_input_fragment (rstrm)))
return TRUE;
}
if (rstrm->in_finger == rstrm->in_boundry)
return TRUE;
return FALSE;
}
 
/*
* The client must tell the package when an end-of-record has occurred.
* The second parameter tells whether the record should be flushed to the
* (output) tcp stream. (This lets the package support batched or
* pipelined procedure calls.) TRUE => immediate flush to tcp connection.
*/
bool_t
xdrrec_endofrecord (XDR *xdrs, bool_t sendnow)
{
RECSTREAM *rstrm = (RECSTREAM *) xdrs->x_private;
u_long len; /* fragment length */
 
if (sendnow || rstrm->frag_sent
|| rstrm->out_finger + BYTES_PER_XDR_UNIT >= rstrm->out_boundry)
{
rstrm->frag_sent = FALSE;
return flush_out (rstrm, TRUE);
}
len = (rstrm->out_finger - (char *) rstrm->frag_header
- BYTES_PER_XDR_UNIT);
*rstrm->frag_header = htonl ((u_long) len | LAST_FRAG);
rstrm->frag_header = (u_int32_t *) rstrm->out_finger;
rstrm->out_finger += BYTES_PER_XDR_UNIT;
return TRUE;
}
 
 
/*
* Internal useful routines
*/
static bool_t
internal_function
flush_out (RECSTREAM *rstrm, bool_t eor)
{
u_long eormask = (eor == TRUE) ? LAST_FRAG : 0;
u_long len = (rstrm->out_finger - (char *) rstrm->frag_header
- BYTES_PER_XDR_UNIT);
 
*rstrm->frag_header = htonl (len | eormask);
len = rstrm->out_finger - rstrm->out_base;
if ((*(rstrm->writeit)) (rstrm->tcp_handle, rstrm->out_base, (int) len)
!= (int) len)
return FALSE;
rstrm->frag_header = (u_int32_t *) rstrm->out_base;
rstrm->out_finger = (caddr_t) rstrm->out_base + BYTES_PER_XDR_UNIT;
return TRUE;
}
 
static bool_t /* knows nothing about records! Only about input buffers */
fill_input_buf (RECSTREAM *rstrm)
{
caddr_t where;
size_t i;
int len;
 
where = rstrm->in_base;
i = (size_t) rstrm->in_boundry % BYTES_PER_XDR_UNIT;
where += i;
len = rstrm->in_size - i;
if ((len = (*(rstrm->readit)) (rstrm->tcp_handle, where, len)) == -1)
return FALSE;
rstrm->in_finger = where;
where += len;
rstrm->in_boundry = where;
return TRUE;
}
 
static bool_t /* knows nothing about records! Only about input buffers */
internal_function
get_input_bytes (RECSTREAM *rstrm, caddr_t addr, int len)
{
int current;
 
while (len > 0)
{
current = rstrm->in_boundry - rstrm->in_finger;
if (current == 0)
{
if (!fill_input_buf (rstrm))
return FALSE;
continue;
}
current = (len < current) ? len : current;
memcpy (addr, rstrm->in_finger, current);
rstrm->in_finger += current;
addr += current;
len -= current;
}
return TRUE;
}
 
static bool_t /* next two bytes of the input stream are treated as a header */
internal_function
set_input_fragment (RECSTREAM *rstrm)
{
uint32_t header;
 
if (! get_input_bytes (rstrm, (caddr_t)&header, BYTES_PER_XDR_UNIT))
return FALSE;
header = ntohl (header);
rstrm->last_frag = ((header & LAST_FRAG) == 0) ? FALSE : TRUE;
/*
* Sanity check. Try not to accept wildly incorrect fragment
* sizes. Unfortunately, only a size of zero can be identified as
* 'wildely incorrect', and this only, if it is not the last
* fragment of a message. Ridiculously large fragment sizes may look
* wrong, but we don't have any way to be certain that they aren't
* what the client actually intended to send us. Many existing RPC
* implementations may sent a fragment of size zero as the last
* fragment of a message.
*/
if (header == 0)
return FALSE;
rstrm->fbtbc = header & ~LAST_FRAG;
return TRUE;
}
 
static bool_t /* consumes input bytes; knows nothing about records! */
internal_function
skip_input_bytes (RECSTREAM *rstrm, long cnt)
{
int current;
 
while (cnt > 0)
{
current = rstrm->in_boundry - rstrm->in_finger;
if (current == 0)
{
if (!fill_input_buf (rstrm))
return FALSE;
continue;
}
current = (cnt < current) ? cnt : current;
rstrm->in_finger += current;
cnt -= current;
}
return TRUE;
}
 
static u_int
internal_function
fix_buf_size (u_int s)
{
if (s < 100)
s = 4000;
return RNDUP (s);
}
/rpc/rpc_callmsg.c
0,0 → 1,206
/* @(#)rpc_callmsg.c 2.1 88/07/29 4.0 RPCSRC */
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
* media and as a part of the software program in whole or part. Users
* may copy or modify Sun RPC without charge, but are not authorized
* to license or distribute it to anyone else except as part of a product or
* program developed by the user.
*
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun RPC is provided with no support and without any obligation on the
* part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
#if 0
static char sccsid[] = "@(#)rpc_callmsg.c 1.4 87/08/11 Copyr 1984 Sun Micro";
#endif
 
/*
* rpc_callmsg.c
*
* Copyright (C) 1984, Sun Microsystems, Inc.
*
*/
 
#define __FORCE_GLIBC
#include <features.h>
 
#include <string.h>
#include <sys/param.h>
#include <rpc/rpc.h>
 
/*
* XDR a call message
*/
bool_t
xdr_callmsg (XDR *xdrs, struct rpc_msg *cmsg)
{
int32_t *buf;
struct opaque_auth *oa;
 
if (xdrs->x_op == XDR_ENCODE)
{
if (cmsg->rm_call.cb_cred.oa_length > MAX_AUTH_BYTES)
{
return (FALSE);
}
if (cmsg->rm_call.cb_verf.oa_length > MAX_AUTH_BYTES)
{
return (FALSE);
}
buf = XDR_INLINE (xdrs, 8 * BYTES_PER_XDR_UNIT
+ RNDUP (cmsg->rm_call.cb_cred.oa_length)
+ 2 * BYTES_PER_XDR_UNIT
+ RNDUP (cmsg->rm_call.cb_verf.oa_length));
if (buf != NULL)
{
IXDR_PUT_LONG (buf, cmsg->rm_xid);
IXDR_PUT_ENUM (buf, cmsg->rm_direction);
if (cmsg->rm_direction != CALL)
return FALSE;
IXDR_PUT_LONG (buf, cmsg->rm_call.cb_rpcvers);
if (cmsg->rm_call.cb_rpcvers != RPC_MSG_VERSION)
return FALSE;
IXDR_PUT_LONG (buf, cmsg->rm_call.cb_prog);
IXDR_PUT_LONG (buf, cmsg->rm_call.cb_vers);
IXDR_PUT_LONG (buf, cmsg->rm_call.cb_proc);
oa = &cmsg->rm_call.cb_cred;
IXDR_PUT_ENUM (buf, oa->oa_flavor);
IXDR_PUT_INT32 (buf, oa->oa_length);
if (oa->oa_length)
{
memcpy ((caddr_t) buf, oa->oa_base, oa->oa_length);
buf = (int32_t *) ((char *) buf + RNDUP (oa->oa_length));
}
oa = &cmsg->rm_call.cb_verf;
IXDR_PUT_ENUM (buf, oa->oa_flavor);
IXDR_PUT_INT32 (buf, oa->oa_length);
if (oa->oa_length)
{
memcpy ((caddr_t) buf, oa->oa_base, oa->oa_length);
/* no real need....
buf = (long *) ((char *) buf + RNDUP(oa->oa_length));
*/
}
return TRUE;
}
}
if (xdrs->x_op == XDR_DECODE)
{
buf = XDR_INLINE (xdrs, 8 * BYTES_PER_XDR_UNIT);
if (buf != NULL)
{
cmsg->rm_xid = IXDR_GET_LONG (buf);
cmsg->rm_direction = IXDR_GET_ENUM (buf, enum msg_type);
if (cmsg->rm_direction != CALL)
{
return FALSE;
}
cmsg->rm_call.cb_rpcvers = IXDR_GET_LONG (buf);
if (cmsg->rm_call.cb_rpcvers != RPC_MSG_VERSION)
{
return FALSE;
}
cmsg->rm_call.cb_prog = IXDR_GET_LONG (buf);
cmsg->rm_call.cb_vers = IXDR_GET_LONG (buf);
cmsg->rm_call.cb_proc = IXDR_GET_LONG (buf);
oa = &cmsg->rm_call.cb_cred;
oa->oa_flavor = IXDR_GET_ENUM (buf, enum_t);
oa->oa_length = IXDR_GET_INT32 (buf);
if (oa->oa_length)
{
if (oa->oa_length > MAX_AUTH_BYTES)
return FALSE;
if (oa->oa_base == NULL)
{
oa->oa_base = (caddr_t)
mem_alloc (oa->oa_length);
}
buf = XDR_INLINE (xdrs, RNDUP (oa->oa_length));
if (buf == NULL)
{
if (xdr_opaque (xdrs, oa->oa_base,
oa->oa_length) == FALSE)
return FALSE;
}
else
{
memcpy (oa->oa_base, (caddr_t) buf, oa->oa_length);
/* no real need....
buf = (long *) ((char *) buf
+ RNDUP(oa->oa_length));
*/
}
}
oa = &cmsg->rm_call.cb_verf;
buf = XDR_INLINE (xdrs, 2 * BYTES_PER_XDR_UNIT);
if (buf == NULL)
{
if (xdr_enum (xdrs, &oa->oa_flavor) == FALSE ||
xdr_u_int (xdrs, &oa->oa_length) == FALSE)
{
return FALSE;
}
}
else
{
oa->oa_flavor = IXDR_GET_ENUM (buf, enum_t);
oa->oa_length = IXDR_GET_INT32 (buf);
}
if (oa->oa_length)
{
if (oa->oa_length > MAX_AUTH_BYTES)
return FALSE;
if (oa->oa_base == NULL)
{
oa->oa_base = (caddr_t)
mem_alloc (oa->oa_length);
}
buf = XDR_INLINE (xdrs, RNDUP (oa->oa_length));
if (buf == NULL)
{
if (xdr_opaque (xdrs, oa->oa_base,
oa->oa_length) == FALSE)
return FALSE;
}
else
{
memcpy (oa->oa_base, (caddr_t) buf, oa->oa_length);
/* no real need...
buf = (long *) ((char *) buf
+ RNDUP(oa->oa_length));
*/
}
}
return TRUE;
}
}
if (
xdr_u_long (xdrs, &(cmsg->rm_xid)) &&
xdr_enum (xdrs, (enum_t *) & (cmsg->rm_direction)) &&
(cmsg->rm_direction == CALL) &&
xdr_u_long (xdrs, &(cmsg->rm_call.cb_rpcvers)) &&
(cmsg->rm_call.cb_rpcvers == RPC_MSG_VERSION) &&
xdr_u_long (xdrs, &(cmsg->rm_call.cb_prog)) &&
xdr_u_long (xdrs, &(cmsg->rm_call.cb_vers)) &&
xdr_u_long (xdrs, &(cmsg->rm_call.cb_proc)) &&
xdr_opaque_auth (xdrs, &(cmsg->rm_call.cb_cred)))
return xdr_opaque_auth (xdrs, &(cmsg->rm_call.cb_verf));
return FALSE;
}
/rpc/rpc_prot.c
0,0 → 1,282
/* @(#)rpc_prot.c 2.3 88/08/07 4.0 RPCSRC */
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
* media and as a part of the software program in whole or part. Users
* may copy or modify Sun RPC without charge, but are not authorized
* to license or distribute it to anyone else except as part of a product or
* program developed by the user.
*
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun RPC is provided with no support and without any obligation on the
* part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
#if 0
static char sccsid[] = "@(#)rpc_prot.c 1.36 87/08/11 Copyr 1984 Sun Micro";
#endif
 
/*
* rpc_prot.c
*
* Copyright (C) 1984, Sun Microsystems, Inc.
*
* This set of routines implements the rpc message definition,
* its serializer and some common rpc utility routines.
* The routines are meant for various implementations of rpc -
* they are NOT for the rpc client or rpc service implementations!
* Because authentication stuff is easy and is part of rpc, the opaque
* routines are also in this program.
*/
 
#define __FORCE_GLIBC
#include <features.h>
 
#include <sys/param.h>
 
#include <rpc/rpc.h>
 
/* * * * * * * * * * * * * * XDR Authentication * * * * * * * * * * * */
 
/*
* XDR an opaque authentication struct
* (see auth.h)
*/
bool_t
xdr_opaque_auth (XDR *xdrs, struct opaque_auth *ap)
{
 
if (xdr_enum (xdrs, &(ap->oa_flavor)))
return xdr_bytes (xdrs, &ap->oa_base,
&ap->oa_length, MAX_AUTH_BYTES);
return FALSE;
}
 
/*
* XDR a DES block
*/
bool_t
xdr_des_block (XDR *xdrs, des_block *blkp)
{
return xdr_opaque (xdrs, (caddr_t) blkp, sizeof (des_block));
}
 
/* * * * * * * * * * * * * * XDR RPC MESSAGE * * * * * * * * * * * * * * * */
 
/*
* XDR the MSG_ACCEPTED part of a reply message union
*/
bool_t
xdr_accepted_reply (XDR *xdrs, struct accepted_reply *ar)
{
/* personalized union, rather than calling xdr_union */
if (!xdr_opaque_auth (xdrs, &(ar->ar_verf)))
return FALSE;
if (!xdr_enum (xdrs, (enum_t *) & (ar->ar_stat)))
return FALSE;
switch (ar->ar_stat)
{
case SUCCESS:
return ((*(ar->ar_results.proc)) (xdrs, ar->ar_results.where));
case PROG_MISMATCH:
if (!xdr_u_long (xdrs, &(ar->ar_vers.low)))
return FALSE;
return (xdr_u_long (xdrs, &(ar->ar_vers.high)));
default:
return TRUE;
}
return TRUE; /* TRUE => open ended set of problems */
}
 
/*
* XDR the MSG_DENIED part of a reply message union
*/
bool_t
xdr_rejected_reply (XDR *xdrs, struct rejected_reply *rr)
{
/* personalized union, rather than calling xdr_union */
if (!xdr_enum (xdrs, (enum_t *) & (rr->rj_stat)))
return FALSE;
switch (rr->rj_stat)
{
case RPC_MISMATCH:
if (!xdr_u_long (xdrs, &(rr->rj_vers.low)))
return FALSE;
return xdr_u_long (xdrs, &(rr->rj_vers.high));
 
case AUTH_ERROR:
return xdr_enum (xdrs, (enum_t *) & (rr->rj_why));
}
return FALSE;
}
 
static const struct xdr_discrim reply_dscrm[3] =
{
{(int) MSG_ACCEPTED, (xdrproc_t) xdr_accepted_reply},
{(int) MSG_DENIED, (xdrproc_t) xdr_rejected_reply},
{__dontcare__, NULL_xdrproc_t}};
 
/*
* XDR a reply message
*/
bool_t
xdr_replymsg (xdrs, rmsg)
XDR *xdrs;
struct rpc_msg *rmsg;
{
if (xdr_u_long (xdrs, &(rmsg->rm_xid)) &&
xdr_enum (xdrs, (enum_t *) & (rmsg->rm_direction)) &&
(rmsg->rm_direction == REPLY))
return xdr_union (xdrs, (enum_t *) & (rmsg->rm_reply.rp_stat),
(caddr_t) & (rmsg->rm_reply.ru), reply_dscrm,
NULL_xdrproc_t);
return FALSE;
}
 
 
/*
* Serializes the "static part" of a call message header.
* The fields include: rm_xid, rm_direction, rpcvers, prog, and vers.
* The rm_xid is not really static, but the user can easily munge on the fly.
*/
bool_t
xdr_callhdr (xdrs, cmsg)
XDR *xdrs;
struct rpc_msg *cmsg;
{
 
cmsg->rm_direction = CALL;
cmsg->rm_call.cb_rpcvers = RPC_MSG_VERSION;
if (
(xdrs->x_op == XDR_ENCODE) &&
xdr_u_long (xdrs, &(cmsg->rm_xid)) &&
xdr_enum (xdrs, (enum_t *) & (cmsg->rm_direction)) &&
xdr_u_long (xdrs, &(cmsg->rm_call.cb_rpcvers)) &&
xdr_u_long (xdrs, &(cmsg->rm_call.cb_prog)))
return xdr_u_long (xdrs, &(cmsg->rm_call.cb_vers));
return FALSE;
}
 
/* ************************** Client utility routine ************* */
 
static void
accepted (enum accept_stat acpt_stat,
struct rpc_err *error)
{
switch (acpt_stat)
{
 
case PROG_UNAVAIL:
error->re_status = RPC_PROGUNAVAIL;
return;
 
case PROG_MISMATCH:
error->re_status = RPC_PROGVERSMISMATCH;
return;
 
case PROC_UNAVAIL:
error->re_status = RPC_PROCUNAVAIL;
return;
 
case GARBAGE_ARGS:
error->re_status = RPC_CANTDECODEARGS;
return;
 
case SYSTEM_ERR:
error->re_status = RPC_SYSTEMERROR;
return;
 
case SUCCESS:
error->re_status = RPC_SUCCESS;
return;
}
/* something's wrong, but we don't know what ... */
error->re_status = RPC_FAILED;
error->re_lb.s1 = (long) MSG_ACCEPTED;
error->re_lb.s2 = (long) acpt_stat;
}
 
static void
rejected (enum reject_stat rjct_stat,
struct rpc_err *error)
{
switch (rjct_stat)
{
case RPC_VERSMISMATCH:
error->re_status = RPC_VERSMISMATCH;
return;
case AUTH_ERROR:
error->re_status = RPC_AUTHERROR;
return;
default:
/* something's wrong, but we don't know what ... */
error->re_status = RPC_FAILED;
error->re_lb.s1 = (long) MSG_DENIED;
error->re_lb.s2 = (long) rjct_stat;
return;
}
}
 
/*
* given a reply message, fills in the error
*/
void
_seterr_reply (struct rpc_msg *msg,
struct rpc_err *error)
{
/* optimized for normal, SUCCESSful case */
switch (msg->rm_reply.rp_stat)
{
case MSG_ACCEPTED:
if (msg->acpted_rply.ar_stat == SUCCESS)
{
error->re_status = RPC_SUCCESS;
return;
};
accepted (msg->acpted_rply.ar_stat, error);
break;
 
case MSG_DENIED:
rejected (msg->rjcted_rply.rj_stat, error);
break;
 
default:
error->re_status = RPC_FAILED;
error->re_lb.s1 = (long) (msg->rm_reply.rp_stat);
break;
}
switch (error->re_status)
{
 
case RPC_VERSMISMATCH:
error->re_vers.low = msg->rjcted_rply.rj_vers.low;
error->re_vers.high = msg->rjcted_rply.rj_vers.high;
break;
 
case RPC_AUTHERROR:
error->re_why = msg->rjcted_rply.rj_why;
break;
 
case RPC_PROGVERSMISMATCH:
error->re_vers.low = msg->acpted_rply.ar_vers.low;
error->re_vers.high = msg->acpted_rply.ar_vers.high;
break;
default:
break;
}
}
/rpc/getrpcport.c
0,0 → 1,77
/* @(#)getrpcport.c 2.1 88/07/29 4.0 RPCSRC */
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
* media and as a part of the software program in whole or part. Users
* may copy or modify Sun RPC without charge, but are not authorized
* to license or distribute it to anyone else except as part of a product or
* program developed by the user.
*
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun RPC is provided with no support and without any obligation on the
* part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
#if 0
static char sccsid[] = "@(#)getrpcport.c 1.3 87/08/11 SMI";
#endif
 
/*
* Copyright (c) 1985 by Sun Microsystems, Inc.
*/
 
#define __FORCE_GLIBC
#include <features.h>
 
#include <alloca.h>
#include <errno.h>
#include <stdio.h>
#include <netdb.h>
#include <string.h>
#include <rpc/rpc.h>
#include <rpc/clnt.h>
#include <rpc/pmap_clnt.h>
#include <sys/socket.h>
 
int
getrpcport (const char *host, u_long prognum, u_long versnum, u_int proto)
{
struct sockaddr_in addr;
struct hostent hostbuf, *hp;
size_t buflen;
char *buffer;
int herr;
 
buflen = 1024;
buffer = alloca (buflen);
while (gethostbyname_r (host, &hostbuf, buffer, buflen, &hp, &herr) != 0
|| hp == NULL)
if (herr != NETDB_INTERNAL || errno != ERANGE)
return 0;
else
{
/* Enlarge the buffer. */
buflen *= 2;
buffer = alloca (buflen);
}
 
memcpy ((char *) &addr.sin_addr, hp->h_addr, hp->h_length);
addr.sin_family = AF_INET;
addr.sin_port = 0;
return pmap_getport (&addr, prognum, versnum, proto);
}
/rpc/rpc_dtablesize.c
0,0 → 1,54
/* @(#)rpc_dtablesize.c 2.1 88/07/29 4.0 RPCSRC */
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
* media and as a part of the software program in whole or part. Users
* may copy or modify Sun RPC without charge, but are not authorized
* to license or distribute it to anyone else except as part of a product or
* program developed by the user.
*
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun RPC is provided with no support and without any obligation on the
* part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
#if 0
static char sccsid[] = "@(#)rpc_dtablesize.c 1.2 87/08/11 Copyr 1987 Sun Micro";
#endif
 
#define __FORCE_GLIBC
#define __USE_BSD
#include <features.h>
 
#include <unistd.h>
#include <rpc/clnt.h>
 
/*
* Cache the result of getdtablesize(), so we don't have to do an
* expensive system call every time.
*/
int
_rpc_dtablesize (void)
{
static int size;
 
if (size == 0)
size = getdtablesize ();
 
return size;
}
/rpc/get_myaddress.c
0,0 → 1,108
/* @(#)get_myaddress.c 2.1 88/07/29 4.0 RPCSRC */
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
* media and as a part of the software program in whole or part. Users
* may copy or modify Sun RPC without charge, but are not authorized
* to license or distribute it to anyone else except as part of a product or
* program developed by the user.
*
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun RPC is provided with no support and without any obligation on the
* part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
#if 0
static char sccsid[] = "@(#)get_myaddress.c 1.4 87/08/11 Copyr 1984 Sun Micro";
#endif
 
/*
* get_myaddress.c
*
* Get client's IP address via ioctl. This avoids using the yellowpages.
* Copyright (C) 1984, Sun Microsystems, Inc.
*/
 
#include <rpc/types.h>
#include <rpc/clnt.h>
#include <rpc/pmap_prot.h>
#include <sys/socket.h>
#include <stdio.h>
#include <unistd.h>
#include <net/if.h>
#include <sys/ioctl.h>
/* Order of following two #includes reversed by roland@gnu */
#include <netinet/in.h>
#include <arpa/inet.h>
 
/*
* don't use gethostbyname, which would invoke yellow pages
*
* Avoid loopback interfaces. We return information from a loopback
* interface only if there are no other possible interfaces.
*/
void
get_myaddress (struct sockaddr_in *addr)
{
int s;
char buf[BUFSIZ];
struct ifconf ifc;
struct ifreq ifreq, *ifr;
int len, loopback = 0;
 
if ((s = socket (AF_INET, SOCK_DGRAM, 0)) < 0)
{
perror ("get_myaddress: socket");
exit (1);
}
ifc.ifc_len = sizeof (buf);
ifc.ifc_buf = buf;
if (ioctl (s, SIOCGIFCONF, (char *) &ifc) < 0)
{
perror (_("get_myaddress: ioctl (get interface configuration)"));
exit (1);
}
 
again:
ifr = ifc.ifc_req;
for (len = ifc.ifc_len; len; len -= sizeof ifreq)
{
ifreq = *ifr;
if (ioctl (s, SIOCGIFFLAGS, (char *) &ifreq) < 0)
{
perror ("get_myaddress: ioctl");
exit (1);
}
if ((ifreq.ifr_flags & IFF_UP) && (ifr->ifr_addr.sa_family == AF_INET)
&& (!(ifreq.ifr_flags & IFF_LOOPBACK) ||
(loopback == 1 && (ifreq.ifr_flags & IFF_LOOPBACK))))
{
*addr = *((struct sockaddr_in *) &ifr->ifr_addr);
addr->sin_port = htons (PMAPPORT);
close (s);
return;
}
ifr++;
}
if (loopback == 0)
{
loopback = 1;
goto again;
}
close (s);
}
/rpc/xdr_mem.c
0,0 → 1,232
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
* media and as a part of the software program in whole or part. Users
* may copy or modify Sun RPC without charge, but are not authorized
* to license or distribute it to anyone else except as part of a product or
* program developed by the user.
*
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun RPC is provided with no support and without any obligation on the
* part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
 
/*
* xdr_mem.h, XDR implementation using memory buffers.
*
* Copyright (C) 1984, Sun Microsystems, Inc.
*
* If you have some data to be interpreted as external data representation
* or to be converted to external data representation in a memory buffer,
* then this is the package for you.
*
*/
 
#define __FORCE_GLIBC
#define _GNU_SOURCE
#include <features.h>
 
 
#include <string.h>
#include <rpc/rpc.h>
 
static bool_t xdrmem_getlong (XDR *, long *);
static bool_t xdrmem_putlong (XDR *, const long *);
static bool_t xdrmem_getbytes (XDR *, caddr_t, u_int);
static bool_t xdrmem_putbytes (XDR *, const char *, u_int);
static u_int xdrmem_getpos (const XDR *);
static bool_t xdrmem_setpos (XDR *, u_int);
static int32_t *xdrmem_inline (XDR *, int);
static void xdrmem_destroy (XDR *);
static bool_t xdrmem_getint32 (XDR *, int32_t *);
static bool_t xdrmem_putint32 (XDR *, const int32_t *);
 
static const struct xdr_ops xdrmem_ops =
{
xdrmem_getlong,
xdrmem_putlong,
xdrmem_getbytes,
xdrmem_putbytes,
xdrmem_getpos,
xdrmem_setpos,
xdrmem_inline,
xdrmem_destroy,
xdrmem_getint32,
xdrmem_putint32
};
 
/*
* The procedure xdrmem_create initializes a stream descriptor for a
* memory buffer.
*/
void
xdrmem_create (XDR *xdrs, const caddr_t addr, u_int size, enum xdr_op op)
{
xdrs->x_op = op;
/* We have to add the const since the `struct xdr_ops' in `struct XDR'
is not `const'. */
xdrs->x_ops = (struct xdr_ops *) &xdrmem_ops;
xdrs->x_private = xdrs->x_base = addr;
xdrs->x_handy = size;
}
 
/*
* Nothing needs to be done for the memory case. The argument is clearly
* const.
*/
 
static void
xdrmem_destroy (XDR *xdrs)
{
}
 
/*
* Gets the next word from the memory referenced by xdrs and places it
* in the long pointed to by lp. It then increments the private word to
* point at the next element. Neither object pointed to is const
*/
static bool_t
xdrmem_getlong (XDR *xdrs, long *lp)
{
if ((xdrs->x_handy -= 4) < 0)
return FALSE;
*lp = (int32_t) ntohl ((*((int32_t *) (xdrs->x_private))));
xdrs->x_private += 4;
return TRUE;
}
 
/*
* Puts the long pointed to by lp in the memory referenced by xdrs. It
* then increments the private word to point at the next element. The
* long pointed at is const
*/
static bool_t
xdrmem_putlong (XDR *xdrs, const long *lp)
{
if ((xdrs->x_handy -= 4) < 0)
return FALSE;
*(int32_t *) xdrs->x_private = htonl (*lp);
xdrs->x_private += 4;
return TRUE;
}
 
/*
* Gets an unaligned number of bytes from the xdrs structure and writes them
* to the address passed in addr. Be very careful when calling this routine
* as it could leave the xdrs pointing to an unaligned structure which is not
* a good idea. None of the things pointed to are const.
*/
static bool_t
xdrmem_getbytes (XDR *xdrs, caddr_t addr, u_int len)
{
if ((xdrs->x_handy -= len) < 0)
return FALSE;
memcpy (addr, xdrs->x_private, len);
xdrs->x_private += len;
return TRUE;
}
 
/*
* The complementary function to the above. The same warnings apply about
* unaligned data. The source address is const.
*/
static bool_t
xdrmem_putbytes (XDR *xdrs, const char *addr, u_int len)
{
if ((xdrs->x_handy -= len) < 0)
return FALSE;
memcpy (xdrs->x_private, addr, len);
xdrs->x_private += len;
return TRUE;
}
 
/*
* Not sure what this one does. But it clearly doesn't modify the contents
* of xdrs. **FIXME** does this not assume u_int == u_long?
*/
static u_int
xdrmem_getpos (const XDR *xdrs)
{
return (u_long) xdrs->x_private - (u_long) xdrs->x_base;
}
 
/*
* xdrs modified
*/
static bool_t
xdrmem_setpos (xdrs, pos)
XDR *xdrs;
u_int pos;
{
caddr_t newaddr = xdrs->x_base + pos;
caddr_t lastaddr = xdrs->x_private + xdrs->x_handy;
 
if ((long) newaddr > (long) lastaddr)
return FALSE;
xdrs->x_private = newaddr;
xdrs->x_handy = (long) lastaddr - (long) newaddr;
return TRUE;
}
 
/*
* xdrs modified
*/
static int32_t *
xdrmem_inline (XDR *xdrs, int len)
{
int32_t *buf = 0;
 
if (xdrs->x_handy >= len)
{
xdrs->x_handy -= len;
buf = (int32_t *) xdrs->x_private;
xdrs->x_private += len;
}
return buf;
}
 
/*
* Gets the next word from the memory referenced by xdrs and places it
* in the int pointed to by ip. It then increments the private word to
* point at the next element. Neither object pointed to is const
*/
static bool_t
xdrmem_getint32 (XDR *xdrs, int32_t *ip)
{
if ((xdrs->x_handy -= 4) < 0)
return FALSE;
*ip = ntohl ((*((int32_t *) (xdrs->x_private))));
xdrs->x_private += 4;
return TRUE;
}
 
/*
* Puts the long pointed to by lp in the memory referenced by xdrs. It
* then increments the private word to point at the next element. The
* long pointed at is const
*/
static bool_t
xdrmem_putint32 (XDR *xdrs, const int32_t *ip)
{
if ((xdrs->x_handy -= 4) < 0)
return FALSE;
*(int32_t *) xdrs->x_private = htonl (*ip);
xdrs->x_private += 4;
return TRUE;
}
/getproto.c
0,0 → 1,248
/*
** protocols.c /etc/protocols access functions
**
** This file is part of the NYS Library.
**
** The NYS Library is free software; you can redistribute it and/or
** modify it under the terms of the GNU Library General Public License as
** published by the Free Software Foundation; either version 2 of the
** License, or (at your option) any later version.
**
** The NYS Library is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
** Library General Public License for more details.
**
** You should have received a copy of the GNU Library General Public
** License along with the NYS Library; see the file COPYING.LIB. If
** not, write to the Free Software Foundation, Inc., 675 Mass Ave,
** Cambridge, MA 02139, USA.
**
**
** Copyright (c) 1983 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.
** 3. All advertising materials mentioning features or use of this software
** must display the following acknowledgement:
** This product includes software developed by the University of
** California, Berkeley and its contributors.
** 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.
*/
 
#define __FORCE_GLIBC
#define _GNU_SOURCE
#include <features.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
 
#ifdef __UCLIBC_HAS_THREADS__
#include <pthread.h>
static pthread_mutex_t mylock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
# define LOCK __pthread_mutex_lock(&mylock)
# define UNLOCK __pthread_mutex_unlock(&mylock);
#else
# define LOCK
# define UNLOCK
#endif
 
 
 
#define MAXALIASES 35
 
static FILE *protof = NULL;
static struct protoent proto;
static char static_aliases[BUFSIZ+1 + sizeof(char *)*MAXALIASES];
static int proto_stayopen;
 
void setprotoent(int f)
{
LOCK;
if (protof == NULL)
protof = fopen(_PATH_PROTOCOLS, "r" );
else
rewind(protof);
proto_stayopen |= f;
UNLOCK;
}
 
void endprotoent(void)
{
LOCK;
if (protof) {
fclose(protof);
protof = NULL;
}
proto_stayopen = 0;
UNLOCK;
}
 
int getprotoent_r(struct protoent *result_buf,
char *buf, size_t buflen,
struct protoent **result)
{
char *p;
register char *cp, **q;
char **proto_aliases;
char *line;
 
*result = NULL;
 
if (buflen < sizeof(*proto_aliases)*MAXALIASES) {
errno=ERANGE;
return errno;
}
LOCK;
proto_aliases=(char **)buf;
buf+=sizeof(*proto_aliases)*MAXALIASES;
buflen-=sizeof(*proto_aliases)*MAXALIASES;
 
if (buflen < BUFSIZ+1) {
UNLOCK;
errno=ERANGE;
return errno;
}
line=buf;
buf+=BUFSIZ+1;
buflen-=BUFSIZ+1;
 
if (protof == NULL && (protof = fopen(_PATH_PROTOCOLS, "r" )) == NULL) {
UNLOCK;
return errno;
}
again:
if ((p = fgets(line, BUFSIZ, protof)) == NULL) {
UNLOCK;
return TRY_AGAIN;
}
 
if (*p == '#')
goto again;
cp = strpbrk(p, "#\n");
if (cp == NULL)
goto again;
*cp = '\0';
result_buf->p_name = p;
cp = strpbrk(p, " \t");
if (cp == NULL)
goto again;
*cp++ = '\0';
while (*cp == ' ' || *cp == '\t')
cp++;
p = strpbrk(cp, " \t");
if (p != NULL)
*p++ = '\0';
result_buf->p_proto = atoi(cp);
q = result_buf->p_aliases = proto_aliases;
if (p != NULL) {
cp = p;
while (cp && *cp) {
if (*cp == ' ' || *cp == '\t') {
cp++;
continue;
}
if (q < &proto_aliases[MAXALIASES - 1])
*q++ = cp;
cp = strpbrk(cp, " \t");
if (cp != NULL)
*cp++ = '\0';
}
}
*q = NULL;
*result=result_buf;
UNLOCK;
return 0;
}
 
struct protoent * getprotoent(void)
{
struct protoent *result;
getprotoent_r(&proto, static_aliases, sizeof(static_aliases), &result);
return result;
}
 
 
int getprotobyname_r(const char *name,
struct protoent *result_buf,
char *buf, size_t buflen,
struct protoent **result)
{
register char **cp;
int ret;
 
LOCK;
setprotoent(proto_stayopen);
while (!(ret=getprotoent_r(result_buf, buf, buflen, result))) {
if (strcmp(result_buf->p_name, name) == 0)
break;
for (cp = result_buf->p_aliases; *cp != 0; cp++)
if (strcmp(*cp, name) == 0)
goto found;
}
found:
if (!proto_stayopen)
endprotoent();
UNLOCK;
return *result?0:ret;
}
 
 
struct protoent * getprotobyname(const char *name)
{
struct protoent *result;
getprotobyname_r(name, &proto, static_aliases, sizeof(static_aliases), &result);
return result;
}
 
 
int getprotobynumber_r (int proto_num,
struct protoent *result_buf,
char *buf, size_t buflen,
struct protoent **result)
{
int ret;
 
LOCK;
setprotoent(proto_stayopen);
while (!(ret=getprotoent_r(result_buf, buf, buflen, result)))
if (result_buf->p_proto == proto_num)
break;
if (!proto_stayopen)
endprotoent();
UNLOCK;
return *result?0:ret;
}
 
struct protoent * getprotobynumber(int proto_num)
{
struct protoent *result;
getprotobynumber_r(proto_num, &proto, static_aliases, sizeof(static_aliases), &result);
return result;
}
 
/inet_net.c
0,0 → 1,100
/*
* Copyright (c) 1983, 1993
* The Regents of the University of California. All rights reserved.
* 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.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 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.
*/
 
#define __FORCE_GLIBC
#include <features.h>
#include <ctype.h>
#include <netinet/in.h>
 
/*
* Internet network address interpretation routine.
* The library routines call this routine to interpret
* network numbers.
*/
in_addr_t
inet_network(const char *cp)
{
register in_addr_t val, base, n;
register char c;
in_addr_t parts[4], *pp = parts;
register int i;
 
again:
/*
* Collect number up to ``.''.
* Values are specified as for C:
* 0x=hex, 0=octal, other=decimal.
*/
val = 0; base = 10;
/*
* The 4.4BSD version of this file also accepts 'x__' as a hexa
* number. I don't think this is correct. -- Uli
*/
if (*cp == '0') {
if (*++cp == 'x' || *cp == 'X')
base = 16, cp++;
else
base = 8;
}
while ((c = *cp)) {
if (isdigit(c)) {
val = (val * base) + (c - '0');
cp++;
continue;
}
if (base == 16 && isxdigit(c)) {
val = (val << 4) + (c + 10 - (islower(c) ? 'a' : 'A'));
cp++;
continue;
}
break;
}
if (*cp == '.') {
if (pp >= parts + 4)
return (INADDR_NONE);
*pp++ = val, cp++;
goto again;
}
if (*cp && !isspace(*cp))
return (INADDR_NONE);
*pp++ = val;
n = pp - parts;
if (n > 4)
return (INADDR_NONE);
for (val = 0, i = 0; i < n; i++) {
val <<= 8;
val |= parts[i] & 0xff;
}
return (val);
}
/socketcalls.c
0,0 → 1,341
#define __FORCE_GLIBC
#include <features.h>
#include <errno.h>
#include <syscall.h>
#include <sys/socket.h>
 
#ifdef __NR_socketcall
extern int __socketcall(int call, unsigned long *args);
 
/* Various socketcall numbers */
#define SYS_SOCKET 1
#define SYS_BIND 2
#define SYS_CONNECT 3
#define SYS_LISTEN 4
#define SYS_ACCEPT 5
#define SYS_GETSOCKNAME 6
#define SYS_GETPEERNAME 7
#define SYS_SOCKETPAIR 8
#define SYS_SEND 9
#define SYS_RECV 10
#define SYS_SENDTO 11
#define SYS_RECVFROM 12
#define SYS_SHUTDOWN 13
#define SYS_SETSOCKOPT 14
#define SYS_GETSOCKOPT 15
#define SYS_SENDMSG 16
#define SYS_RECVMSG 17
#endif
 
 
#ifdef L_accept
#ifdef __NR_accept
#define __NR___libc_accept __NR_accept
_syscall3(int, __libc_accept, int, call, struct sockaddr *, addr, socklen_t *,addrlen);
#else
int __libc_accept(int s, struct sockaddr *addr, socklen_t * addrlen)
{
unsigned long args[3];
 
args[0] = s;
args[1] = (unsigned long) addr;
args[2] = (unsigned long) addrlen;
return __socketcall(SYS_ACCEPT, args);
}
#endif
weak_alias(__libc_accept, accept);
#endif
 
#ifdef L_bind
#ifdef __NR_bind
_syscall3(int, bind, int, sockfd, const struct sockaddr *, myaddr, socklen_t, addrlen);
#else
int bind(int sockfd, const struct sockaddr *myaddr, socklen_t addrlen)
{
unsigned long args[3];
 
args[0] = sockfd;
args[1] = (unsigned long) myaddr;
args[2] = addrlen;
return __socketcall(SYS_BIND, args);
}
#endif
#endif
 
#ifdef L_connect
#ifdef __NR_connect
#define __NR___libc_connect __NR_connect
_syscall3(int, __libc_connect, int, sockfd, const struct sockaddr *, saddr, socklen_t, addrlen);
#else
int __libc_connect(int sockfd, const struct sockaddr *saddr, socklen_t addrlen)
{
unsigned long args[3];
 
args[0] = sockfd;
args[1] = (unsigned long) saddr;
args[2] = addrlen;
return __socketcall(SYS_CONNECT, args);
}
#endif
weak_alias(__libc_connect, connect);
#endif
 
#ifdef L_getpeername
#ifdef __NR_getpeername
_syscall3(int, getpeername, int, sockfd, struct sockaddr *, addr, socklen_t *,paddrlen);
#else
int getpeername(int sockfd, struct sockaddr *addr, socklen_t * paddrlen)
{
unsigned long args[3];
 
args[0] = sockfd;
args[1] = (unsigned long) addr;
args[2] = (unsigned long) paddrlen;
return __socketcall(SYS_GETPEERNAME, args);
}
#endif
#endif
 
#ifdef L_getsockname
#ifdef __NR_getsockname
_syscall3(int, getsockname, int, sockfd, struct sockaddr *, addr, socklen_t *,paddrlen);
#else
int getsockname(int sockfd, struct sockaddr *addr, socklen_t * paddrlen)
{
unsigned long args[3];
 
args[0] = sockfd;
args[1] = (unsigned long) addr;
args[2] = (unsigned long) paddrlen;
return __socketcall(SYS_GETSOCKNAME, args);
}
#endif
#endif
 
#ifdef L_getsockopt
#ifdef __NR_getsockopt
_syscall5(int, getsockopt, int, fd, int, level, int, optname, __ptr_t, optval, socklen_t *, optlen);
#else
int getsockopt(int fd, int level, int optname, __ptr_t optval,
socklen_t * optlen)
{
unsigned long args[5];
 
args[0] = fd;
args[1] = level;
args[2] = optname;
args[3] = (unsigned long) optval;
args[4] = (unsigned long) optlen;
return (__socketcall(SYS_GETSOCKOPT, args));
}
#endif
#endif
 
#ifdef L_listen
#ifdef __NR_listen
_syscall2(int, listen, int, sockfd, int, backlog);
#else
int listen(int sockfd, int backlog)
{
unsigned long args[2];
 
args[0] = sockfd;
args[1] = backlog;
return __socketcall(SYS_LISTEN, args);
}
#endif
#endif
 
#ifdef L_recv
#ifdef __NR_recv
#define __NR___libc_recv __NR_recv
_syscall4(ssize_t, __libc_recv, int, sockfd, __ptr_t, buffer, size_t, len, int, flags);
#else
/* recv, recvfrom added by bir7@leland.stanford.edu */
ssize_t __libc_recv(int sockfd, __ptr_t buffer, size_t len, int flags)
{
unsigned long args[4];
 
args[0] = sockfd;
args[1] = (unsigned long) buffer;
args[2] = len;
args[3] = flags;
return (__socketcall(SYS_RECV, args));
}
#endif
weak_alias(__libc_recv, recv);
#endif
 
#ifdef L_recvfrom
#ifdef __NR_recvfrom
#define __NR___libc_recvfrom __NR_recvfrom
_syscall6(ssize_t, __libc_recvfrom, int, sockfd, __ptr_t, buffer, size_t, len, int, flags,
struct sockaddr *, to, socklen_t *, tolen);
#else
/* recv, recvfrom added by bir7@leland.stanford.edu */
ssize_t __libc_recvfrom(int sockfd, __ptr_t buffer, size_t len, int flags,
struct sockaddr *to, socklen_t * tolen)
{
unsigned long args[6];
 
args[0] = sockfd;
args[1] = (unsigned long) buffer;
args[2] = len;
args[3] = flags;
args[4] = (unsigned long) to;
args[5] = (unsigned long) tolen;
return (__socketcall(SYS_RECVFROM, args));
}
#endif
weak_alias(__libc_recvfrom, recvfrom);
#endif
 
#ifdef L_recvmsg
#ifdef __NR_recvmsg
#define __NR___libc_recvmsg __NR_recvmsg
_syscall3(ssize_t, __libc_recvmsg, int, sockfd, struct msghdr *, msg, int, flags);
#else
ssize_t __libc_recvmsg(int sockfd, struct msghdr *msg, int flags)
{
unsigned long args[3];
 
args[0] = sockfd;
args[1] = (unsigned long) msg;
args[2] = flags;
return (__socketcall(SYS_RECVMSG, args));
}
#endif
weak_alias(__libc_recvmsg, recvmsg);
#endif
 
#ifdef L_send
#ifdef __NR_send
#define __NR___libc_send __NR_send
_syscall4(ssize_t, __libc_send, int, sockfd, const void *, buffer, size_t, len, int, flags);
#else
/* send, sendto added by bir7@leland.stanford.edu */
ssize_t __libc_send(int sockfd, const void *buffer, size_t len, int flags)
{
unsigned long args[4];
 
args[0] = sockfd;
args[1] = (unsigned long) buffer;
args[2] = len;
args[3] = flags;
return (__socketcall(SYS_SEND, args));
}
#endif
weak_alias(__libc_send, send);
#endif
 
#ifdef L_sendmsg
#ifdef __NR_sendmsg
#define __NR___libc_sendmsg __NR_sendmsg
_syscall3(ssize_t, __libc_sendmsg, int, sockfd, const struct msghdr *, msg, int, flags);
#else
ssize_t __libc_sendmsg(int sockfd, const struct msghdr *msg, int flags)
{
unsigned long args[3];
 
args[0] = sockfd;
args[1] = (unsigned long) msg;
args[2] = flags;
return (__socketcall(SYS_SENDMSG, args));
}
#endif
weak_alias(__libc_sendmsg, sendmsg);
#endif
 
#ifdef L_sendto
#ifdef __NR_sendto
#define __NR___libc_sendto __NR_sendto
_syscall6(ssize_t, __libc_sendto, int, sockfd, const void *, buffer, size_t, len,
int, flags, const struct sockaddr *, to, socklen_t, tolen);
#else
/* send, sendto added by bir7@leland.stanford.edu */
ssize_t __libc_sendto(int sockfd, const void *buffer, size_t len, int flags,
const struct sockaddr *to, socklen_t tolen)
{
unsigned long args[6];
 
args[0] = sockfd;
args[1] = (unsigned long) buffer;
args[2] = len;
args[3] = flags;
args[4] = (unsigned long) to;
args[5] = tolen;
return (__socketcall(SYS_SENDTO, args));
}
#endif
weak_alias(__libc_sendto, sendto);
#endif
 
#ifdef L_setsockopt
#ifdef __NR_setsockopt
_syscall5(int, setsockopt, int, fd, int, level, int, optname, const void *, optval, socklen_t, optlen);
#else
/* [sg]etsockoptions by bir7@leland.stanford.edu */
int setsockopt(int fd, int level, int optname, const void *optval,
socklen_t optlen)
{
unsigned long args[5];
 
args[0] = fd;
args[1] = level;
args[2] = optname;
args[3] = (unsigned long) optval;
args[4] = optlen;
return (__socketcall(SYS_SETSOCKOPT, args));
}
#endif
#endif
 
#ifdef L_shutdown
#ifdef __NR_shutdown
_syscall2(int, shutdown, int, sockfd, int, how);
#else
/* shutdown by bir7@leland.stanford.edu */
int shutdown(int sockfd, int how)
{
unsigned long args[2];
 
args[0] = sockfd;
args[1] = how;
return (__socketcall(SYS_SHUTDOWN, args));
}
#endif
#endif
 
#ifdef L_socket
#ifdef __NR_socket
_syscall3(int, socket, int, family, int, type, int, protocol);
#else
int socket(int family, int type, int protocol)
{
unsigned long args[3];
 
args[0] = family;
args[1] = type;
args[2] = (unsigned long) protocol;
return __socketcall(SYS_SOCKET, args);
}
#endif
#endif
 
#ifdef L_socketpair
#ifdef __NR_socketpair
_syscall4(int, socketpair, int, family, int, type, int, protocol, int *, sockvec);
#else
int socketpair(int family, int type, int protocol, int sockvec[2])
{
unsigned long args[4];
 
args[0] = family;
args[1] = type;
args[2] = protocol;
args[3] = (unsigned long) sockvec;
return __socketcall(SYS_SOCKETPAIR, args);
}
#endif
#endif
 
/addr.c
0,0 → 1,184
/* Copyright (C) 1995,1996 Robert de Bath <rdebath@cix.compulink.co.uk>
* This file is part of the Linux-8086 C library and is distributed
* under the GNU Library General Public License.
*/
 
/*
* Manuel Novoa III Dec 2000
*
* Converted to use my new (un)signed long (long) to string routines, which
* are smaller than the previous functions and don't require static buffers.
* In the process, removed the reference to strcat and cut object size of
* inet_ntoa in half (from 190 bytes down to 94).
*
* Manuel Novoa III Feb 2002
*
* Changed to use _int10tostr.
*/
 
#define __FORCE_GLIBC
#include <features.h>
#define _STDIO_UTILITY /* For _int10tostr. */
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <netinet/in.h>
 
int inet_aton(const char *cp, struct in_addr *addrptr);
 
#ifdef L_inet_aton
int inet_aton(cp, addrptr)
const char *cp;
struct in_addr *addrptr;
{
in_addr_t addr;
int value;
int part;
 
addr = 0;
for (part = 1; part <= 4; part++) {
 
if (!isdigit(*cp))
return 0;
 
value = 0;
while (isdigit(*cp)) {
value *= 10;
value += *cp++ - '0';
if (value > 255)
return 0;
}
 
if (part < 4) {
if (*cp++ != '.')
return 0;
} else {
char c = *cp++;
if (c != '\0' && !isspace(c))
return 0;
}
 
addr <<= 8;
addr |= value;
}
 
/* W. Richard Stevens in his book UNIX Network Programming,
* Volume 1, second edition, on page 71 says:
*
* An undocumented feature of inet_aton is that if addrptr is
* a null pointer, the function still performs it validation
* of the input string, but does not store the result.
*/
if (addrptr) {
addrptr->s_addr = htonl(addr);
}
 
return 1;
}
#endif
 
#ifdef L_inet_addr
in_addr_t inet_addr(const char *cp)
{
struct in_addr a;
 
if (!inet_aton(cp, &a))
return INADDR_NONE;
else
return a.s_addr;
}
#endif
 
#ifdef L_inet_ntoa
 
#define INET_NTOA_MAX_LEN 16 /* max 12 digits + 3 '.'s + 1 nul */
 
char *inet_ntoa_r(struct in_addr in, char buf[INET_NTOA_MAX_LEN])
{
in_addr_t addr = ntohl(in.s_addr);
int i;
char *p, *q;
q = 0;
p = buf + INET_NTOA_MAX_LEN - 1; /* cannot use sizeof(buf) here */
for (i=0 ; i < 4 ; i++ ) {
p = _int10tostr(p, addr & 0xff) - 1;
addr >>= 8;
if (q) {
*q = '.';
}
q = p;
}
 
return p+1;
}
 
char *inet_ntoa(struct in_addr in)
{
static char buf[INET_NTOA_MAX_LEN];
return(inet_ntoa_r(in, buf));
}
#endif
 
#ifdef L_inet_makeaddr
/*
* Formulate an Internet address from network + host. Used in
* building addresses stored in the ifnet structure.
*/
struct in_addr inet_makeaddr(in_addr_t net, in_addr_t host)
{
in_addr_t addr;
 
if (net < 128)
addr = (net << IN_CLASSA_NSHIFT) | (host & IN_CLASSA_HOST);
else if (net < 65536)
addr = (net << IN_CLASSB_NSHIFT) | (host & IN_CLASSB_HOST);
else if (net < 16777216UL)
addr = (net << IN_CLASSC_NSHIFT) | (host & IN_CLASSC_HOST);
else
addr = net | host;
addr = htonl(addr);
return (*(struct in_addr *)&addr);
}
 
#endif
 
#ifdef L_inet_lnaof
/*
* Return the local network address portion of an
* internet address; handles class a/b/c network
* number formats.
*/
in_addr_t inet_lnaof(struct in_addr in)
{
in_addr_t i = ntohl(in.s_addr);
 
if (IN_CLASSA(i))
return ((i)&IN_CLASSA_HOST);
else if (IN_CLASSB(i))
return ((i)&IN_CLASSB_HOST);
else
return ((i)&IN_CLASSC_HOST);
}
#endif
 
#ifdef L_inet_netof
 
/*
* Return the network number from an internet
* address; handles class a/b/c network #'s.
*/
in_addr_t
inet_netof(struct in_addr in)
{
in_addr_t i = ntohl(in.s_addr);
 
if (IN_CLASSA(i))
return (((i)&IN_CLASSA_NET) >> IN_CLASSA_NSHIFT);
else if (IN_CLASSB(i))
return (((i)&IN_CLASSB_NET) >> IN_CLASSB_NSHIFT);
else
return (((i)&IN_CLASSC_NET) >> IN_CLASSC_NSHIFT);
}
 
#endif
/resolv.c
0,0 → 1,2303
/* resolv.c: DNS Resolver
*
* Copyright (C) 1998 Kenneth Albanowski <kjahds@kjahds.com>,
* The Silver Hammer Group, Ltd.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*/
 
/*
* Portions Copyright (c) 1985, 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.
*/
 
/*
* Portions Copyright (c) 1993 by Digital Equipment Corporation.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies, and that
* the name of Digital Equipment Corporation not be used in advertising or
* publicity pertaining to distribution of the document or software without
* specific, written prior permission.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
* WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
* CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
* SOFTWARE.
*/
 
/*
* Portions Copyright (c) 1996-1999 by Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
* ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
* CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
* SOFTWARE.
*/
 
/*
*
* 5-Oct-2000 W. Greathouse wgreathouse@smva.com
* Fix memory leak and memory corruption.
* -- Every name resolution resulted in
* a new parse of resolv.conf and new
* copy of nameservers allocated by
* strdup.
* -- Every name resolution resulted in
* a new read of resolv.conf without
* resetting index from prior read...
* resulting in exceeding array bounds.
*
* Limit nameservers read from resolv.conf
*
* Add "search" domains from resolv.conf
*
* Some systems will return a security
* signature along with query answer for
* dynamic DNS entries.
* -- skip/ignore this answer
*
* Include arpa/nameser.h for defines.
*
* General cleanup
*
* 20-Jun-2001 Michal Moskal <malekith@pld.org.pl>
* partial IPv6 support (i.e. gethostbyname2() and resolve_address2()
* functions added), IPv6 nameservers are also supported.
*
* 6-Oct-2001 Jari Korva <jari.korva@iki.fi>
* more IPv6 support (IPv6 support for gethostbyaddr();
* address family parameter and improved IPv6 support for get_hosts_byname
* and read_etc_hosts; getnameinfo() port from glibc; defined
* defined ip6addr_any and in6addr_loopback)
*
* 2-Feb-2002 Erik Andersen <andersee@debian.org>
* Added gethostent(), sethostent(), and endhostent()
*
* 17-Aug-2002 Manuel Novoa III <mjn3@codepoet.org>
* Fixed __read_etc_hosts_r to return alias list, and modified buffer
* allocation accordingly. See MAX_ALIASES and ALIAS_DIM below.
* This fixes the segfault in the Python 2.2.1 socket test.
*
* 04-Jan-2003 Jay Kulpinski <jskulpin@berkshire.rr.com>
* Fixed __decode_dotted to count the terminating null character
* in a host name.
*
* 02-Oct-2003 Tony J. White <tjw@tjw.org>
* Lifted dn_expand() and dependent ns_name_uncompress(), ns_name_unpack(),
* and ns_name_ntop() from glibc 2.3.2 for compatibility with ipsec-tools
* and openldap.
*
*/
 
#define __FORCE_GLIBC
#include <features.h>
#include <string.h>
#include <stdio.h>
#include <signal.h>
#include <errno.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <unistd.h>
#include <resolv.h>
#include <netdb.h>
#include <ctype.h>
#include <arpa/nameser.h>
#include <sys/utsname.h>
#include <sys/un.h>
 
#define MAX_RECURSE 5
#define REPLY_TIMEOUT 10
#define MAX_RETRIES 3
#define MAX_SERVERS 3
#define MAX_SEARCH 4
 
#define MAX_ALIASES 5
 
/* 1:ip + 1:full + MAX_ALIASES:aliases + 1:NULL */
#define ALIAS_DIM (2 + MAX_ALIASES + 1)
 
#undef DEBUG
/*#define DEBUG*/
 
#ifdef DEBUG
#define DPRINTF(X,args...) fprintf(stderr, X, ##args)
#else
#define DPRINTF(X,args...)
#endif /* DEBUG */
 
 
/* Global stuff (stuff needing to be locked to be thread safe)... */
extern int __nameservers;
extern char * __nameserver[MAX_SERVERS];
extern int __searchdomains;
extern char * __searchdomain[MAX_SEARCH];
 
#ifdef __UCLIBC_HAS_THREADS__
#include <pthread.h>
extern pthread_mutex_t __resolv_lock;
# define BIGLOCK __pthread_mutex_lock(&__resolv_lock)
# define BIGUNLOCK __pthread_mutex_unlock(&__resolv_lock);
#else
# define BIGLOCK
# define BIGUNLOCK
#endif
 
 
 
/* Structs */
struct resolv_header {
int id;
int qr,opcode,aa,tc,rd,ra,rcode;
int qdcount;
int ancount;
int nscount;
int arcount;
};
 
struct resolv_question {
char * dotted;
int qtype;
int qclass;
};
 
struct resolv_answer {
char * dotted;
int atype;
int aclass;
int ttl;
int rdlength;
unsigned char * rdata;
int rdoffset;
};
 
enum etc_hosts_action {
GET_HOSTS_BYNAME = 0,
GETHOSTENT,
GET_HOSTS_BYADDR,
};
 
/* function prototypes */
extern int __get_hosts_byname_r(const char * name, int type,
struct hostent * result_buf,
char * buf, size_t buflen,
struct hostent ** result,
int * h_errnop);
extern int __get_hosts_byaddr_r(const char * addr, int len, int type,
struct hostent * result_buf,
char * buf, size_t buflen,
struct hostent ** result,
int * h_errnop);
extern void __open_etc_hosts(FILE **fp);
extern int __read_etc_hosts_r(FILE *fp, const char * name, int type,
enum etc_hosts_action action,
struct hostent * result_buf,
char * buf, size_t buflen,
struct hostent ** result,
int * h_errnop);
extern int __dns_lookup(const char * name, int type, int nscount,
char ** nsip, unsigned char ** outpacket, struct resolv_answer * a);
 
extern int __encode_dotted(const char * dotted, unsigned char * dest, int maxlen);
extern int __decode_dotted(const unsigned char * message, int offset,
char * dest, int maxlen);
extern int __length_dotted(const unsigned char * message, int offset);
extern int __encode_header(struct resolv_header * h, unsigned char * dest, int maxlen);
extern int __decode_header(unsigned char * data, struct resolv_header * h);
extern int __encode_question(struct resolv_question * q,
unsigned char * dest, int maxlen);
extern int __decode_question(unsigned char * message, int offset,
struct resolv_question * q);
extern int __encode_answer(struct resolv_answer * a,
unsigned char * dest, int maxlen);
extern int __decode_answer(unsigned char * message, int offset,
struct resolv_answer * a);
extern int __length_question(unsigned char * message, int offset);
extern int __open_nameservers(void);
extern void __close_nameservers(void);
extern int __dn_expand(const u_char *, const u_char *, const u_char *,
char *, int);
extern int __ns_name_uncompress(const u_char *, const u_char *,
const u_char *, char *, size_t);
extern int __ns_name_ntop(const u_char *, char *, size_t);
extern int __ns_name_unpack(const u_char *, const u_char *, const u_char *,
u_char *, size_t);
 
 
#ifdef L_encodeh
int __encode_header(struct resolv_header *h, unsigned char *dest, int maxlen)
{
if (maxlen < HFIXEDSZ)
return -1;
 
dest[0] = (h->id & 0xff00) >> 8;
dest[1] = (h->id & 0x00ff) >> 0;
dest[2] = (h->qr ? 0x80 : 0) |
((h->opcode & 0x0f) << 3) |
(h->aa ? 0x04 : 0) |
(h->tc ? 0x02 : 0) |
(h->rd ? 0x01 : 0);
dest[3] = (h->ra ? 0x80 : 0) | (h->rcode & 0x0f);
dest[4] = (h->qdcount & 0xff00) >> 8;
dest[5] = (h->qdcount & 0x00ff) >> 0;
dest[6] = (h->ancount & 0xff00) >> 8;
dest[7] = (h->ancount & 0x00ff) >> 0;
dest[8] = (h->nscount & 0xff00) >> 8;
dest[9] = (h->nscount & 0x00ff) >> 0;
dest[10] = (h->arcount & 0xff00) >> 8;
dest[11] = (h->arcount & 0x00ff) >> 0;
 
return HFIXEDSZ;
}
#endif
 
#ifdef L_decodeh
int __decode_header(unsigned char *data, struct resolv_header *h)
{
h->id = (data[0] << 8) | data[1];
h->qr = (data[2] & 0x80) ? 1 : 0;
h->opcode = (data[2] >> 3) & 0x0f;
h->aa = (data[2] & 0x04) ? 1 : 0;
h->tc = (data[2] & 0x02) ? 1 : 0;
h->rd = (data[2] & 0x01) ? 1 : 0;
h->ra = (data[3] & 0x80) ? 1 : 0;
h->rcode = data[3] & 0x0f;
h->qdcount = (data[4] << 8) | data[5];
h->ancount = (data[6] << 8) | data[7];
h->nscount = (data[8] << 8) | data[9];
h->arcount = (data[10] << 8) | data[11];
 
return HFIXEDSZ;
}
#endif
 
#ifdef L_encoded
/* Encode a dotted string into nameserver transport-level encoding.
This routine is fairly dumb, and doesn't attempt to compress
the data */
 
int __encode_dotted(const char *dotted, unsigned char *dest, int maxlen)
{
int used = 0;
 
while (dotted && *dotted) {
char *c = strchr(dotted, '.');
int l = c ? c - dotted : strlen(dotted);
 
if (l >= (maxlen - used - 1))
return -1;
 
dest[used++] = l;
memcpy(dest + used, dotted, l);
used += l;
 
if (c)
dotted = c + 1;
else
break;
}
 
if (maxlen < 1)
return -1;
 
dest[used++] = 0;
 
return used;
}
#endif
 
#ifdef L_decoded
/* Decode a dotted string from nameserver transport-level encoding.
This routine understands compressed data. */
 
int __decode_dotted(const unsigned char *data, int offset,
char *dest, int maxlen)
{
int l;
int measure = 1;
int total = 0;
int used = 0;
 
if (!data)
return -1;
 
while ((l=data[offset++])) {
if (measure)
total++;
if ((l & 0xc0) == (0xc0)) {
if (measure)
total++;
/* compressed item, redirect */
offset = ((l & 0x3f) << 8) | data[offset];
measure = 0;
continue;
}
 
if ((used + l + 1) >= maxlen)
return -1;
 
memcpy(dest + used, data + offset, l);
offset += l;
used += l;
if (measure)
total += l;
 
if (data[offset] != 0)
dest[used++] = '.';
else
dest[used++] = '\0';
}
 
/* The null byte must be counted too */
if (measure) {
total++;
}
 
DPRINTF("Total decode len = %d\n", total);
 
return total;
}
#endif
 
#ifdef L_lengthd
 
int __length_dotted(const unsigned char *data, int offset)
{
int orig_offset = offset;
int l;
 
if (!data)
return -1;
 
while ((l = data[offset++])) {
 
if ((l & 0xc0) == (0xc0)) {
offset++;
break;
}
 
offset += l;
}
 
return offset - orig_offset;
}
#endif
 
#ifdef L_encodeq
int __encode_question(struct resolv_question *q,
unsigned char *dest, int maxlen)
{
int i;
 
i = __encode_dotted(q->dotted, dest, maxlen);
if (i < 0)
return i;
 
dest += i;
maxlen -= i;
 
if (maxlen < 4)
return -1;
 
dest[0] = (q->qtype & 0xff00) >> 8;
dest[1] = (q->qtype & 0x00ff) >> 0;
dest[2] = (q->qclass & 0xff00) >> 8;
dest[3] = (q->qclass & 0x00ff) >> 0;
 
return i + 4;
}
#endif
 
#ifdef L_decodeq
int __decode_question(unsigned char *message, int offset,
struct resolv_question *q)
{
char temp[256];
int i;
 
i = __decode_dotted(message, offset, temp, sizeof(temp));
if (i < 0)
return i;
 
offset += i;
 
q->dotted = strdup(temp);
q->qtype = (message[offset + 0] << 8) | message[offset + 1];
q->qclass = (message[offset + 2] << 8) | message[offset + 3];
 
return i + 4;
}
#endif
 
#ifdef L_lengthq
int __length_question(unsigned char *message, int offset)
{
int i;
 
i = __length_dotted(message, offset);
if (i < 0)
return i;
 
return i + 4;
}
#endif
 
#ifdef L_encodea
int __encode_answer(struct resolv_answer *a, unsigned char *dest, int maxlen)
{
int i;
 
i = __encode_dotted(a->dotted, dest, maxlen);
if (i < 0)
return i;
 
dest += i;
maxlen -= i;
 
if (maxlen < (RRFIXEDSZ+a->rdlength))
return -1;
 
*dest++ = (a->atype & 0xff00) >> 8;
*dest++ = (a->atype & 0x00ff) >> 0;
*dest++ = (a->aclass & 0xff00) >> 8;
*dest++ = (a->aclass & 0x00ff) >> 0;
*dest++ = (a->ttl & 0xff000000) >> 24;
*dest++ = (a->ttl & 0x00ff0000) >> 16;
*dest++ = (a->ttl & 0x0000ff00) >> 8;
*dest++ = (a->ttl & 0x000000ff) >> 0;
*dest++ = (a->rdlength & 0xff00) >> 8;
*dest++ = (a->rdlength & 0x00ff) >> 0;
memcpy(dest, a->rdata, a->rdlength);
 
return i + RRFIXEDSZ + a->rdlength;
}
#endif
 
#ifdef L_decodea
int __decode_answer(unsigned char *message, int offset,
struct resolv_answer *a)
{
char temp[256];
int i;
 
i = __decode_dotted(message, offset, temp, sizeof(temp));
if (i < 0)
return i;
 
message += offset + i;
 
a->dotted = strdup(temp);
a->atype = (message[0] << 8) | message[1];
message += 2;
a->aclass = (message[0] << 8) | message[1];
message += 2;
a->ttl = (message[0] << 24) |
(message[1] << 16) | (message[2] << 8) | (message[3] << 0);
message += 4;
a->rdlength = (message[0] << 8) | message[1];
message += 2;
a->rdata = message;
a->rdoffset = offset + i + RRFIXEDSZ;
 
DPRINTF("i=%d,rdlength=%d\n", i, a->rdlength);
 
return i + RRFIXEDSZ + a->rdlength;
}
#endif
 
#ifdef L_encodep
int __encode_packet(struct resolv_header *h,
struct resolv_question **q,
struct resolv_answer **an,
struct resolv_answer **ns,
struct resolv_answer **ar,
unsigned char *dest, int maxlen)
{
int i, total = 0;
int j;
 
i = __encode_header(h, dest, maxlen);
if (i < 0)
return i;
 
dest += i;
maxlen -= i;
total += i;
 
for (j = 0; j < h->qdcount; j++) {
i = __encode_question(q[j], dest, maxlen);
if (i < 0)
return i;
dest += i;
maxlen -= i;
total += i;
}
 
for (j = 0; j < h->ancount; j++) {
i = __encode_answer(an[j], dest, maxlen);
if (i < 0)
return i;
dest += i;
maxlen -= i;
total += i;
}
for (j = 0; j < h->nscount; j++) {
i = __encode_answer(ns[j], dest, maxlen);
if (i < 0)
return i;
dest += i;
maxlen -= i;
total += i;
}
for (j = 0; j < h->arcount; j++) {
i = __encode_answer(ar[j], dest, maxlen);
if (i < 0)
return i;
dest += i;
maxlen -= i;
total += i;
}
 
return total;
}
#endif
 
#ifdef L_decodep
int __decode_packet(unsigned char *data, struct resolv_header *h)
{
return __decode_header(data, h);
}
#endif
 
#ifdef L_formquery
int __form_query(int id, const char *name, int type, unsigned char *packet,
int maxlen)
{
struct resolv_header h;
struct resolv_question q;
int i, j;
 
memset(&h, 0, sizeof(h));
h.id = id;
h.qdcount = 1;
 
q.dotted = (char *) name;
q.qtype = type;
q.qclass = C_IN; /* CLASS_IN */
 
i = __encode_header(&h, packet, maxlen);
if (i < 0)
return i;
 
j = __encode_question(&q, packet + i, maxlen - i);
if (j < 0)
return j;
 
return i + j;
}
#endif
 
#ifdef L_dnslookup
 
#ifdef __UCLIBC_HAS_THREADS__
static pthread_mutex_t mylock = PTHREAD_MUTEX_INITIALIZER;
# define LOCK __pthread_mutex_lock(&mylock)
# define UNLOCK __pthread_mutex_unlock(&mylock);
#else
# define LOCK
# define UNLOCK
#endif
 
/* Just for the record, having to lock __dns_lookup() just for these two globals
* is pretty lame. I think these two variables can probably be de-global-ized,
* which should eliminate the need for doing locking here... Needs a closer
* look anyways. */
static int ns=0, id=1;
 
int __dns_lookup(const char *name, int type, int nscount, char **nsip,
unsigned char **outpacket, struct resolv_answer *a)
{
int i, j, len, fd, pos, rc;
struct timeval tv;
fd_set fds;
struct resolv_header h;
struct resolv_question q;
int retries = 0;
unsigned char * packet = malloc(PACKETSZ);
char *dns, *lookup = malloc(MAXDNAME);
int variant = 0;
struct sockaddr_in sa;
#ifdef __UCLIBC_HAS_IPV6__
int v6;
struct sockaddr_in6 sa6;
#endif
 
fd = -1;
 
if (!packet || !lookup || !nscount)
goto fail;
 
DPRINTF("Looking up type %d answer for '%s'\n", type, name);
 
LOCK;
ns %= nscount;
UNLOCK;
 
while (retries++ < MAX_RETRIES) {
if (fd != -1)
close(fd);
 
memset(packet, 0, PACKETSZ);
 
memset(&h, 0, sizeof(h));
 
/* Mess with globals while under lock */
LOCK;
++id;
id &= 0xffff;
h.id = id;
dns = nsip[ns];
UNLOCK;
 
h.qdcount = 1;
h.rd = 1;
 
DPRINTF("encoding header\n", h.rd);
 
i = __encode_header(&h, packet, PACKETSZ);
if (i < 0)
goto fail;
 
strncpy(lookup,name,MAXDNAME);
BIGLOCK;
if (variant < __searchdomains && strchr(lookup, '.') == NULL)
{
strncat(lookup,".", MAXDNAME);
strncat(lookup,__searchdomain[variant], MAXDNAME);
}
BIGUNLOCK;
DPRINTF("lookup name: %s\n", lookup);
q.dotted = (char *)lookup;
q.qtype = type;
q.qclass = C_IN; /* CLASS_IN */
 
j = __encode_question(&q, packet+i, PACKETSZ-i);
if (j < 0)
goto fail;
 
len = i + j;
 
DPRINTF("On try %d, sending query to port %d of machine %s\n",
retries, NAMESERVER_PORT, dns);
 
#ifdef __UCLIBC_HAS_IPV6__
v6 = inet_pton(AF_INET6, dns, &sa6.sin6_addr) > 0;
fd = socket(v6 ? AF_INET6 : AF_INET, SOCK_DGRAM, IPPROTO_UDP);
#else
fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
#endif
if (fd < 0) {
continue;
}
 
/* Connect to the UDP socket so that asyncronous errors are returned */
#ifdef __UCLIBC_HAS_IPV6__
if (v6) {
sa6.sin6_family = AF_INET6;
sa6.sin6_port = htons(NAMESERVER_PORT);
/* sa6.sin6_addr is already here */
rc = connect(fd, (struct sockaddr *) &sa6, sizeof(sa6));
} else {
#endif
sa.sin_family = AF_INET;
sa.sin_port = htons(NAMESERVER_PORT);
sa.sin_addr.s_addr = inet_addr(dns);
rc = connect(fd, (struct sockaddr *) &sa, sizeof(sa));
#ifdef __UCLIBC_HAS_IPV6__
}
#endif
if (rc < 0) {
if (errno == ENETUNREACH) {
/* routing error, presume not transient */
goto tryall;
} else
/* retry */
continue;
}
 
DPRINTF("Transmitting packet of length %d, id=%d, qr=%d\n",
len, h.id, h.qr);
 
send(fd, packet, len, 0);
 
FD_ZERO(&fds);
FD_SET(fd, &fds);
tv.tv_sec = REPLY_TIMEOUT;
tv.tv_usec = 0;
if (select(fd + 1, &fds, NULL, NULL, &tv) <= 0) {
DPRINTF("Timeout\n");
 
/* timed out, so retry send and receive,
* to next nameserver on queue */
goto again;
}
 
i = recv(fd, packet, 512, 0);
if (i < HFIXEDSZ) {
/* too short ! */
goto again;
}
 
__decode_header(packet, &h);
 
DPRINTF("id = %d, qr = %d\n", h.id, h.qr);
 
LOCK;
if ((h.id != id) || (!h.qr)) {
UNLOCK;
/* unsolicited */
goto again;
}
UNLOCK;
 
 
DPRINTF("Got response %s\n", "(i think)!");
DPRINTF("qrcount=%d,ancount=%d,nscount=%d,arcount=%d\n",
h.qdcount, h.ancount, h.nscount, h.arcount);
DPRINTF("opcode=%d,aa=%d,tc=%d,rd=%d,ra=%d,rcode=%d\n",
h.opcode, h.aa, h.tc, h.rd, h.ra, h.rcode);
 
if ((h.rcode) || (h.ancount < 1)) {
/* negative result, not present */
goto again;
}
 
pos = HFIXEDSZ;
 
for (j = 0; j < h.qdcount; j++) {
DPRINTF("Skipping question %d at %d\n", j, pos);
i = __length_question(packet, pos);
DPRINTF("Length of question %d is %d\n", j, i);
if (i < 0)
goto again;
pos += i;
}
DPRINTF("Decoding answer at pos %d\n", pos);
 
for (j=0;j<h.ancount;j++)
{
i = __decode_answer(packet, pos, a);
 
if (i<0) {
DPRINTF("failed decode %d\n", i);
goto again;
}
/* For all but T_SIG, accept first answer */
if (a->atype != T_SIG)
break;
 
DPRINTF("skipping T_SIG %d\n", i);
free(a->dotted);
pos += i;
}
 
DPRINTF("Answer name = |%s|\n", a->dotted);
DPRINTF("Answer type = |%d|\n", a->atype);
 
close(fd);
 
if (outpacket)
*outpacket = packet;
else
free(packet);
free(lookup);
return (0); /* success! */
 
tryall:
/* if there are other nameservers, give them a go,
otherwise return with error */
{
int sdomains;
 
BIGLOCK;
sdomains=__searchdomains;
BIGUNLOCK;
variant = 0;
if (retries >= nscount*(sdomains+1))
goto fail;
}
 
again:
/* if there are searchdomains, try them or fallback as passed */
{
int sdomains;
BIGLOCK;
sdomains=__searchdomains;
BIGUNLOCK;
 
if (variant < sdomains) {
/* next search */
variant++;
} else {
/* next server, first search */
LOCK;
ns = (ns + 1) % nscount;
UNLOCK;
variant = 0;
}
}
}
 
fail:
if (fd != -1)
close(fd);
if (lookup)
free(lookup);
if (packet)
free(packet);
return -1;
}
#endif
 
#ifdef L_opennameservers
 
int __nameservers;
char * __nameserver[MAX_SERVERS];
int __searchdomains;
char * __searchdomain[MAX_SEARCH];
#ifdef __UCLIBC_HAS_THREADS__
pthread_mutex_t __resolv_lock = PTHREAD_MUTEX_INITIALIZER;
#endif
 
/*
* we currently read formats not quite the same as that on normal
* unix systems, we can have a list of nameservers after the keyword.
*/
 
int __open_nameservers()
{
FILE *fp;
int i;
#define RESOLV_ARGS 5
char szBuffer[128], *p, *argv[RESOLV_ARGS];
int argc;
 
BIGLOCK;
if (__nameservers > 0) {
BIGUNLOCK;
return 0;
}
 
if ((fp = fopen("/etc/resolv.conf", "r")) ||
(fp = fopen("/etc/config/resolv.conf", "r"))) {
 
while (fgets(szBuffer, sizeof(szBuffer), fp) != NULL) {
 
for (p = szBuffer; *p && isspace(*p); p++)
/* skip white space */;
if (*p == '\0' || *p == '\n' || *p == '#') /* skip comments etc */
continue;
argc = 0;
while (*p && argc < RESOLV_ARGS) {
argv[argc++] = p;
while (*p && !isspace(*p) && *p != '\n')
p++;
while (*p && (isspace(*p) || *p == '\n')) /* remove spaces */
*p++ = '\0';
}
 
if (strcmp(argv[0], "nameserver") == 0) {
for (i = 1; i < argc && __nameservers < MAX_SERVERS; i++) {
__nameserver[__nameservers++] = strdup(argv[i]);
DPRINTF("adding nameserver %s\n", argv[i]);
}
}
 
/* domain and search are mutually exclusive, the last one wins */
if (strcmp(argv[0],"domain")==0 || strcmp(argv[0],"search")==0) {
while (__searchdomains > 0) {
free(__searchdomain[--__searchdomains]);
__searchdomain[__searchdomains] = NULL;
}
for (i=1; i < argc && __searchdomains < MAX_SEARCH; i++) {
__searchdomain[__searchdomains++] = strdup(argv[i]);
DPRINTF("adding search %s\n", argv[i]);
}
}
}
fclose(fp);
} else {
DPRINTF("failed to open %s\n", "resolv.conf");
}
DPRINTF("nameservers = %d\n", __nameservers);
BIGUNLOCK;
return 0;
}
#endif
 
 
#ifdef L_closenameservers
 
void __close_nameservers(void)
{
BIGLOCK;
while (__nameservers > 0) {
free(__nameserver[--__nameservers]);
__nameserver[__nameservers] = NULL;
}
while (__searchdomains > 0) {
free(__searchdomain[--__searchdomains]);
__searchdomain[__searchdomains] = NULL;
}
BIGUNLOCK;
}
#endif
 
#ifdef L_gethostbyname
 
struct hostent *gethostbyname(const char *name)
{
static struct hostent h;
static char buf[sizeof(struct in_addr) +
sizeof(struct in_addr *)*2 +
sizeof(char *)*(ALIAS_DIM) + 256/*namebuffer*/ + 32/* margin */];
struct hostent *hp;
 
gethostbyname_r(name, &h, buf, sizeof(buf), &hp, &h_errno);
 
return hp;
}
#endif
 
#ifdef L_gethostbyname2
 
struct hostent *gethostbyname2(const char *name, int family)
{
#ifndef __UCLIBC_HAS_IPV6__
return family == AF_INET ? gethostbyname(name) : (struct hostent*)0;
#else /* __UCLIBC_HAS_IPV6__ */
static struct hostent h;
static char buf[sizeof(struct in6_addr) +
sizeof(struct in6_addr *)*2 +
sizeof(char *)*(ALIAS_DIM) + 256/*namebuffer*/ + 32/* margin */];
struct hostent *hp;
 
gethostbyname2_r(name, family, &h, buf, sizeof(buf), &hp, &h_errno);
 
return hp;
#endif /* __UCLIBC_HAS_IPV6__ */
}
#endif
 
#ifdef L_getnetbyname
 
struct netent * getnetbyname(const char * name)
{
return NULL;
}
#endif
 
 
#ifdef L_res_init
struct __res_state _res;
 
int res_init(void)
{
struct __res_state *rp = &(_res);
 
__close_nameservers();
__open_nameservers();
rp->retrans = RES_TIMEOUT;
rp->retry = 4;
rp->options = RES_INIT;
rp->id = (u_int) random();
rp->nsaddr.sin_addr.s_addr = INADDR_ANY;
rp->nsaddr.sin_family = AF_INET;
rp->nsaddr.sin_port = htons(NAMESERVER_PORT);
rp->ndots = 1;
/** rp->pfcode = 0; **/
rp->_vcsock = -1;
/** rp->_flags = 0; **/
/** rp->qhook = NULL; **/
/** rp->rhook = NULL; **/
/** rp->_u._ext.nsinit = 0; **/
 
BIGLOCK;
if(__searchdomains) {
int i;
for(i=0; i<__searchdomains; i++) {
rp->dnsrch[i] = __searchdomain[i];
}
}
 
if(__nameservers) {
int i;
struct in_addr a;
for(i=0; i<__nameservers; i++) {
if (inet_aton(__nameserver[i], &a)) {
rp->nsaddr_list[i].sin_addr = a;
rp->nsaddr_list[i].sin_family = AF_INET;
rp->nsaddr_list[i].sin_port = htons(NAMESERVER_PORT);
}
}
}
rp->nscount = __nameservers;
BIGUNLOCK;
 
return(0);
}
 
void res_close( void )
{
return;
}
 
#endif
 
 
#ifdef L_res_query
 
#ifndef MIN
#define MIN(x, y) ((x) < (y) ? (x) : (y))
#endif
 
int res_query(const char *dname, int class, int type,
unsigned char *answer, int anslen)
{
int i;
unsigned char * packet = 0;
struct resolv_answer a;
int __nameserversXX;
char ** __nameserverXX;
 
__open_nameservers();
if (!dname || class != 1 /* CLASS_IN */)
return(-1);
memset((char *) &a, '\0', sizeof(a));
 
BIGLOCK;
__nameserversXX=__nameservers;
__nameserverXX=__nameserver;
BIGUNLOCK;
i = __dns_lookup(dname, type, __nameserversXX, __nameserverXX, &packet, &a);
if (i < 0)
return(-1);
free(a.dotted);
if (a.atype == type) { /* CNAME*/
if (anslen && answer)
memcpy(answer, a.rdata, MIN(anslen, a.rdlength));
if (packet)
free(packet);
return(MIN(anslen, a.rdlength));
}
if (packet)
free(packet);
return 0;
}
#endif
 
#ifdef L_gethostbyaddr
struct hostent *gethostbyaddr (const void *addr, socklen_t len, int type)
{
static struct hostent h;
static char buf[
#ifndef __UCLIBC_HAS_IPV6__
sizeof(struct in_addr) + sizeof(struct in_addr *)*2 +
#else
sizeof(struct in6_addr) + sizeof(struct in6_addr *)*2 +
#endif /* __UCLIBC_HAS_IPV6__ */
sizeof(char *)*(ALIAS_DIM) + 256/*namebuffer*/ + 32/* margin */];
struct hostent *hp;
 
gethostbyaddr_r(addr, len, type, &h, buf, sizeof(buf), &hp, &h_errno);
return hp;
}
#endif
 
 
#ifdef L_read_etc_hosts_r
 
void __open_etc_hosts(FILE **fp)
{
if ((*fp = fopen("/etc/hosts", "r")) == NULL) {
*fp = fopen("/etc/config/hosts", "r");
}
return;
}
 
int __read_etc_hosts_r(FILE * fp, const char * name, int type,
enum etc_hosts_action action,
struct hostent * result_buf,
char * buf, size_t buflen,
struct hostent ** result,
int * h_errnop)
{
struct in_addr *in=NULL;
struct in_addr **addr_list=NULL;
#ifdef __UCLIBC_HAS_IPV6__
struct in6_addr *in6=NULL;
struct in6_addr **addr_list6=NULL;
#endif /* __UCLIBC_HAS_IPV6__ */
char *cp;
char **alias;
int aliases, i;
int ret=HOST_NOT_FOUND;
 
if (buflen < sizeof(char *)*(ALIAS_DIM))
return ERANGE;
alias=(char **)buf;
buf+=sizeof(char **)*(ALIAS_DIM);
buflen-=sizeof(char **)*(ALIAS_DIM);
 
if (action!=GETHOSTENT) {
#ifdef __UCLIBC_HAS_IPV6__
char *p=buf;
size_t len=buflen;
#endif /* __UCLIBC_HAS_IPV6__ */
*h_errnop=NETDB_INTERNAL;
if (buflen < sizeof(*in))
return ERANGE;
in=(struct in_addr*)buf;
buf+=sizeof(*in);
buflen-=sizeof(*in);
 
if (buflen < sizeof(*addr_list)*2)
return ERANGE;
addr_list=(struct in_addr **)buf;
buf+=sizeof(*addr_list)*2;
buflen-=sizeof(*addr_list)*2;
 
#ifdef __UCLIBC_HAS_IPV6__
if (len < sizeof(*in6))
return ERANGE;
in6=(struct in6_addr*)p;
p+=sizeof(*in6);
len-=sizeof(*in6);
 
if (len < sizeof(*addr_list6)*2)
return ERANGE;
addr_list6=(struct in6_addr**)p;
p+=sizeof(*addr_list6)*2;
len-=sizeof(*addr_list6)*2;
 
if (len < buflen) {
buflen=len;
buf=p;
}
#endif /* __UCLIBC_HAS_IPV6__ */
 
if (buflen < 80)
return ERANGE;
 
__open_etc_hosts(&fp);
if (fp == NULL) {
result=NULL;
return errno;
}
}
 
*h_errnop=HOST_NOT_FOUND;
while (fgets(buf, buflen, fp)) {
if ((cp = strchr(buf, '#')))
*cp = '\0';
DPRINTF("Looking at: %s\n", buf);
aliases = 0;
 
cp = buf;
while (*cp) {
while (*cp && isspace(*cp))
*cp++ = '\0';
if (!*cp)
continue;
if (aliases < (2+MAX_ALIASES))
alias[aliases++] = cp;
while (*cp && !isspace(*cp))
cp++;
}
alias[aliases] = 0;
 
if (aliases < 2)
continue; /* syntax error really */
if (action==GETHOSTENT) {
/* Return whatever the next entry happens to be. */
break;
} else if (action==GET_HOSTS_BYADDR) {
if (strcmp(name, alias[0]) != 0)
continue;
} else {
/* GET_HOSTS_BYNAME */
for (i = 1; i < aliases; i++)
if (strcasecmp(name, alias[i]) == 0)
break;
if (i >= aliases)
continue;
}
 
if (type == AF_INET && inet_pton(AF_INET, alias[0], in) > 0) {
DPRINTF("Found INET\n");
addr_list[0] = in;
addr_list[1] = 0;
result_buf->h_name = alias[1];
result_buf->h_addrtype = AF_INET;
result_buf->h_length = sizeof(*in);
result_buf->h_addr_list = (char**) addr_list;
result_buf->h_aliases = alias + 2;
*result=result_buf;
ret=NETDB_SUCCESS;
#ifdef __UCLIBC_HAS_IPV6__
} else if (type == AF_INET6 && inet_pton(AF_INET6, alias[0], in6) > 0) {
DPRINTF("Found INET6\n");
addr_list6[0] = in6;
addr_list6[1] = 0;
result_buf->h_name = alias[1];
result_buf->h_addrtype = AF_INET6;
result_buf->h_length = sizeof(*in6);
result_buf->h_addr_list = (char**) addr_list6;
result_buf->h_aliases = alias + 2;
*result=result_buf;
ret=NETDB_SUCCESS;
#endif /* __UCLIBC_HAS_IPV6__ */
} else {
DPRINTF("Error\n");
ret=TRY_AGAIN;
break; /* bad ip address */
}
if (action!=GETHOSTENT) {
fclose(fp);
}
return ret;
}
if (action!=GETHOSTENT) {
fclose(fp);
}
return ret;
}
#endif
 
 
#ifdef L_gethostent
 
#ifdef __UCLIBC_HAS_THREADS__
static pthread_mutex_t mylock = PTHREAD_MUTEX_INITIALIZER;
# define LOCK __pthread_mutex_lock(&mylock)
# define UNLOCK __pthread_mutex_unlock(&mylock);
#else
# define LOCK
# define UNLOCK
#endif
 
static int __stay_open;
static FILE * __gethostent_fp;
 
void endhostent (void)
{
LOCK;
__stay_open = 0;
if (__gethostent_fp) {
fclose(__gethostent_fp);
}
UNLOCK;
}
 
void sethostent (int stay_open)
{
LOCK;
__stay_open = stay_open;
UNLOCK;
}
 
 
struct hostent *gethostent (void)
{
static struct hostent h;
static char buf[
#ifndef __UCLIBC_HAS_IPV6__
sizeof(struct in_addr) + sizeof(struct in_addr *)*2 +
#else
sizeof(struct in6_addr) + sizeof(struct in6_addr *)*2 +
#endif /* __UCLIBC_HAS_IPV6__ */
sizeof(char *)*(ALIAS_DIM) +
80/*namebuffer*/ + 2/* margin */];
struct hostent *host;
 
LOCK;
if (__gethostent_fp == NULL) {
__open_etc_hosts(&__gethostent_fp);
if (__gethostent_fp == NULL) {
UNLOCK;
return((struct hostent *)NULL);
}
}
 
__read_etc_hosts_r(__gethostent_fp, NULL, AF_INET, GETHOSTENT,
&h, buf, sizeof(buf), &host, &h_errno);
if (__stay_open==0) {
fclose(__gethostent_fp);
}
UNLOCK;
return(host);
}
#endif
 
#ifdef L_get_hosts_byname_r
 
int __get_hosts_byname_r(const char * name, int type,
struct hostent * result_buf,
char * buf, size_t buflen,
struct hostent ** result,
int * h_errnop)
{
return(__read_etc_hosts_r(NULL, name, type, GET_HOSTS_BYNAME, result_buf, buf, buflen, result, h_errnop));
}
#endif
 
#ifdef L_get_hosts_byaddr_r
 
int __get_hosts_byaddr_r(const char * addr, int len, int type,
struct hostent * result_buf,
char * buf, size_t buflen,
struct hostent ** result,
int * h_errnop)
{
#ifndef __UCLIBC_HAS_IPV6__
char ipaddr[INET_ADDRSTRLEN];
#else
char ipaddr[INET6_ADDRSTRLEN];
#endif /* __UCLIBC_HAS_IPV6__ */
 
switch (type) {
case AF_INET:
if (len != sizeof(struct in_addr))
return 0;
break;
#ifdef __UCLIBC_HAS_IPV6__
case AF_INET6:
if (len != sizeof(struct in6_addr))
return 0;
break;
#endif /* __UCLIBC_HAS_IPV6__ */
default:
return 0;
}
 
inet_ntop(type, addr, ipaddr, sizeof(ipaddr));
 
return(__read_etc_hosts_r(NULL, ipaddr, type, GET_HOSTS_BYADDR,
result_buf, buf, buflen, result, h_errnop));
}
#endif
 
#ifdef L_getnameinfo
 
#ifndef min
# define min(x,y) (((x) > (y)) ? (y) : (x))
#endif /* min */
 
int getnameinfo (const struct sockaddr *sa, socklen_t addrlen, char *host,
socklen_t hostlen, char *serv, socklen_t servlen,
unsigned int flags)
{
int serrno = errno;
int ok = 0;
struct hostent *h = NULL;
char domain[256];
if (flags & ~(NI_NUMERICHOST|NI_NUMERICSERV|NI_NOFQDN|NI_NAMEREQD|NI_DGRAM))
return EAI_BADFLAGS;
 
if (sa == NULL || addrlen < sizeof (sa_family_t))
return EAI_FAMILY;
 
switch (sa->sa_family) {
case AF_LOCAL:
break;
case AF_INET:
if (addrlen < sizeof (struct sockaddr_in))
return EAI_FAMILY;
break;
#ifdef __UCLIBC_HAS_IPV6__
case AF_INET6:
if (addrlen < sizeof (struct sockaddr_in6))
return EAI_FAMILY;
break;
#endif /* __UCLIBC_HAS_IPV6__ */
default:
return EAI_FAMILY;
}
 
if (host != NULL && hostlen > 0)
switch (sa->sa_family) {
case AF_INET:
#ifdef __UCLIBC_HAS_IPV6__
case AF_INET6:
#endif /* __UCLIBC_HAS_IPV6__ */
if (!(flags & NI_NUMERICHOST)) {
#ifdef __UCLIBC_HAS_IPV6__
if (sa->sa_family == AF_INET6)
h = gethostbyaddr ((const void *) &(((const struct sockaddr_in6 *) sa)->sin6_addr),
sizeof(struct in6_addr), AF_INET6);
else
#endif /* __UCLIBC_HAS_IPV6__ */
h = gethostbyaddr ((const void *) &(((const struct sockaddr_in *)sa)->sin_addr),
sizeof(struct in_addr), AF_INET);
 
if (h) {
char *c;
if ((flags & NI_NOFQDN)
&& (getdomainname (domain, sizeof(domain)) == 0)
&& (c = strstr (h->h_name, domain))
&& (c != h->h_name) && (*(--c) == '.')) {
strncpy (host, h->h_name,
min(hostlen, (size_t) (c - h->h_name)));
host[min(hostlen - 1, (size_t) (c - h->h_name))] = '\0';
ok = 1;
} else {
strncpy (host, h->h_name, hostlen);
ok = 1;
}
}
}
 
if (!ok) {
if (flags & NI_NAMEREQD) {
errno = serrno;
return EAI_NONAME;
} else {
const char *c;
#ifdef __UCLIBC_HAS_IPV6__
if (sa->sa_family == AF_INET6) {
const struct sockaddr_in6 *sin6p;
 
sin6p = (const struct sockaddr_in6 *) sa;
 
c = inet_ntop (AF_INET6,
(const void *) &sin6p->sin6_addr, host, hostlen);
#if 0
/* Does scope id need to be supported? */
uint32_t scopeid;
scopeid = sin6p->sin6_scope_id;
if (scopeid != 0) {
/* Buffer is >= IFNAMSIZ+1. */
char scopebuf[IFNAMSIZ + 1];
char *scopeptr;
int ni_numericscope = 0;
size_t real_hostlen = __strnlen (host, hostlen);
size_t scopelen = 0;
 
scopebuf[0] = SCOPE_DELIMITER;
scopebuf[1] = '\0';
scopeptr = &scopebuf[1];
 
if (IN6_IS_ADDR_LINKLOCAL (&sin6p->sin6_addr)
|| IN6_IS_ADDR_MC_LINKLOCAL (&sin6p->sin6_addr)) {
if (if_indextoname (scopeid, scopeptr) == NULL)
++ni_numericscope;
else
scopelen = strlen (scopebuf);
} else {
++ni_numericscope;
}
 
if (ni_numericscope)
scopelen = 1 + snprintf (scopeptr,
(scopebuf
+ sizeof scopebuf
- scopeptr),
"%u", scopeid);
 
if (real_hostlen + scopelen + 1 > hostlen)
return EAI_SYSTEM;
memcpy (host + real_hostlen, scopebuf, scopelen + 1);
}
#endif
} else
#endif /* __UCLIBC_HAS_IPV6__ */
c = inet_ntop (AF_INET,
(const void *) &(((const struct sockaddr_in *) sa)->sin_addr),
host, hostlen);
 
if (c == NULL) {
errno = serrno;
return EAI_SYSTEM;
}
}
ok = 1;
}
break;
 
case AF_LOCAL:
if (!(flags & NI_NUMERICHOST)) {
struct utsname utsname;
 
if (!uname (&utsname)) {
strncpy (host, utsname.nodename, hostlen);
break;
};
};
 
if (flags & NI_NAMEREQD) {
errno = serrno;
return EAI_NONAME;
}
 
strncpy (host, "localhost", hostlen);
break;
 
default:
return EAI_FAMILY;
}
 
if (serv && (servlen > 0)) {
switch (sa->sa_family) {
case AF_INET:
#ifdef __UCLIBC_HAS_IPV6__
case AF_INET6:
#endif /* __UCLIBC_HAS_IPV6__ */
if (!(flags & NI_NUMERICSERV)) {
struct servent *s;
s = getservbyport (((const struct sockaddr_in *) sa)->sin_port,
((flags & NI_DGRAM) ? "udp" : "tcp"));
if (s) {
strncpy (serv, s->s_name, servlen);
break;
}
}
snprintf (serv, servlen, "%d",
ntohs (((const struct sockaddr_in *) sa)->sin_port));
break;
 
case AF_LOCAL:
strncpy (serv, ((const struct sockaddr_un *) sa)->sun_path, servlen);
break;
}
}
if (host && (hostlen > 0))
host[hostlen-1] = 0;
if (serv && (servlen > 0))
serv[servlen-1] = 0;
errno = serrno;
return 0;
}
#endif
 
 
#ifdef L_gethostbyname_r
 
int gethostbyname_r(const char * name,
struct hostent * result_buf,
char * buf, size_t buflen,
struct hostent ** result,
int * h_errnop)
{
struct in_addr *in;
struct in_addr **addr_list;
unsigned char *packet;
struct resolv_answer a;
int i;
int nest = 0;
int __nameserversXX;
char ** __nameserverXX;
 
__open_nameservers();
 
*result=NULL;
if (!name)
return EINVAL;
 
/* do /etc/hosts first */
if ((i=__get_hosts_byname_r(name, AF_INET, result_buf,
buf, buflen, result, h_errnop))==0)
return i;
switch (*h_errnop) {
case HOST_NOT_FOUND:
case NO_ADDRESS:
break;
case NETDB_INTERNAL:
if (errno == ENOENT) {
break;
}
/* else fall through */
default:
return i;
}
 
DPRINTF("Nothing found in /etc/hosts\n");
 
*h_errnop = NETDB_INTERNAL;
if (buflen < sizeof(*in))
return ERANGE;
in=(struct in_addr*)buf;
buf+=sizeof(*in);
buflen-=sizeof(*in);
 
if (buflen < sizeof(*addr_list)*2)
return ERANGE;
addr_list=(struct in_addr**)buf;
buf+=sizeof(*addr_list)*2;
buflen-=sizeof(*addr_list)*2;
 
addr_list[0] = in;
addr_list[1] = 0;
if (buflen<256)
return ERANGE;
strncpy(buf, name, buflen);
 
/* First check if this is already an address */
if (inet_aton(name, in)) {
result_buf->h_name = buf;
result_buf->h_addrtype = AF_INET;
result_buf->h_length = sizeof(*in);
result_buf->h_addr_list = (char **) addr_list;
*result=result_buf;
*h_errnop = NETDB_SUCCESS;
return NETDB_SUCCESS;
}
 
for (;;) {
 
BIGLOCK;
__nameserversXX=__nameservers;
__nameserverXX=__nameserver;
BIGUNLOCK;
i = __dns_lookup(buf, T_A, __nameserversXX, __nameserverXX, &packet, &a);
 
if (i < 0) {
*h_errnop = HOST_NOT_FOUND;
DPRINTF("__dns_lookup\n");
return TRY_AGAIN;
}
 
strncpy(buf, a.dotted, buflen);
free(a.dotted);
 
if (a.atype == T_CNAME) { /* CNAME */
DPRINTF("Got a CNAME in gethostbyname()\n");
i = __decode_dotted(packet, a.rdoffset, buf, buflen);
free(packet);
 
if (i < 0) {
*h_errnop = NO_RECOVERY;
DPRINTF("__decode_dotted\n");
return -1;
}
if (++nest > MAX_RECURSE) {
*h_errnop = NO_RECOVERY;
DPRINTF("recursion\n");
return -1;
}
continue;
} else if (a.atype == T_A) { /* ADDRESS */
memcpy(in, a.rdata, sizeof(*in));
result_buf->h_name = buf;
result_buf->h_addrtype = AF_INET;
result_buf->h_length = sizeof(*in);
result_buf->h_addr_list = (char **) addr_list;
free(packet);
break;
} else {
free(packet);
*h_errnop=HOST_NOT_FOUND;
return TRY_AGAIN;
}
}
 
*result=result_buf;
*h_errnop = NETDB_SUCCESS;
return NETDB_SUCCESS;
}
#endif
 
#ifdef L_gethostbyname2_r
 
int gethostbyname2_r(const char *name, int family,
struct hostent * result_buf,
char * buf, size_t buflen,
struct hostent ** result,
int * h_errnop)
{
#ifndef __UCLIBC_HAS_IPV6__
return family == AF_INET ? gethostbyname_r(name, result_buf, buf, buflen, result, h_errnop) : HOST_NOT_FOUND;
#else /* __UCLIBC_HAS_IPV6__ */
struct in6_addr *in;
struct in6_addr **addr_list;
unsigned char *packet;
struct resolv_answer a;
int i;
int nest = 0;
int __nameserversXX;
char ** __nameserverXX;
 
if (family == AF_INET)
return gethostbyname_r(name, result_buf, buf, buflen, result, h_errnop);
if (family != AF_INET6)
return EINVAL;
__open_nameservers();
 
*result=NULL;
if (!name)
return EINVAL;
 
/* do /etc/hosts first */
if ((i=__get_hosts_byname_r(name, family, result_buf,
buf, buflen, result, h_errnop))==0)
return i;
switch (*h_errnop) {
case HOST_NOT_FOUND:
case NO_ADDRESS:
break;
default:
return i;
}
 
DPRINTF("Nothing found in /etc/hosts\n");
 
*h_errnop = NETDB_INTERNAL;
if (buflen < sizeof(*in))
return ERANGE;
in=(struct in6_addr*)buf;
buf+=sizeof(*in);
buflen-=sizeof(*in);
 
if (buflen < sizeof(*addr_list)*2)
return ERANGE;
addr_list=(struct in6_addr**)buf;
buf+=sizeof(*addr_list)*2;
buflen-=sizeof(*addr_list)*2;
 
addr_list[0] = in;
addr_list[1] = 0;
if (buflen<256)
return ERANGE;
strncpy(buf, name, buflen);
 
/* First check if this is already an address */
if (inet_pton(AF_INET6, name, in)) {
result_buf->h_name = buf;
result_buf->h_addrtype = AF_INET6;
result_buf->h_length = sizeof(*in);
result_buf->h_addr_list = (char **) addr_list;
*result=result_buf;
*h_errnop = NETDB_SUCCESS;
return NETDB_SUCCESS;
}
 
for (;;) {
BIGLOCK;
__nameserversXX=__nameservers;
__nameserverXX=__nameserver;
BIGUNLOCK;
 
i = __dns_lookup(buf, T_AAAA, __nameserversXX, __nameserverXX, &packet, &a);
 
if (i < 0) {
*h_errnop = HOST_NOT_FOUND;
return TRY_AGAIN;
}
 
strncpy(buf, a.dotted, buflen);
free(a.dotted);
 
if (a.atype == T_CNAME) { /* CNAME */
DPRINTF("Got a CNAME in gethostbyname()\n");
i = __decode_dotted(packet, a.rdoffset, buf, buflen);
free(packet);
 
if (i < 0) {
*h_errnop = NO_RECOVERY;
return -1;
}
if (++nest > MAX_RECURSE) {
*h_errnop = NO_RECOVERY;
return -1;
}
continue;
} else if (a.atype == T_AAAA) { /* ADDRESS */
memcpy(in, a.rdata, sizeof(*in));
result_buf->h_name = buf;
result_buf->h_addrtype = AF_INET6;
result_buf->h_length = sizeof(*in);
result_buf->h_addr_list = (char **) addr_list;
free(packet);
break;
} else {
free(packet);
*h_errnop=HOST_NOT_FOUND;
return TRY_AGAIN;
}
}
 
*result=result_buf;
*h_errnop = NETDB_SUCCESS;
return NETDB_SUCCESS;
#endif /* __UCLIBC_HAS_IPV6__ */
}
#endif
 
#ifdef L_gethostbyaddr_r
int gethostbyaddr_r (const void *addr, socklen_t len, int type,
struct hostent * result_buf,
char * buf, size_t buflen,
struct hostent ** result,
int * h_errnop)
 
{
struct in_addr *in;
struct in_addr **addr_list;
#ifdef __UCLIBC_HAS_IPV6__
char *qp;
size_t plen;
struct in6_addr *in6;
struct in6_addr **addr_list6;
#endif /* __UCLIBC_HAS_IPV6__ */
unsigned char *packet;
struct resolv_answer a;
int i;
int nest = 0;
int __nameserversXX;
char ** __nameserverXX;
 
*result=NULL;
if (!addr)
return EINVAL;
switch (type) {
case AF_INET:
if (len != sizeof(struct in_addr))
return EINVAL;
break;
#ifdef __UCLIBC_HAS_IPV6__
case AF_INET6:
if (len != sizeof(struct in6_addr))
return EINVAL;
break;
#endif /* __UCLIBC_HAS_IPV6__ */
default:
return EINVAL;
}
 
/* do /etc/hosts first */
if ((i=__get_hosts_byaddr_r(addr, len, type, result_buf,
buf, buflen, result, h_errnop))==0)
return i;
switch (*h_errnop) {
case HOST_NOT_FOUND:
case NO_ADDRESS:
break;
default:
return i;
}
 
__open_nameservers();
 
#ifdef __UCLIBC_HAS_IPV6__
qp=buf;
plen=buflen;
#endif /* __UCLIBC_HAS_IPV6__ */
 
*h_errnop = NETDB_INTERNAL;
if (buflen < sizeof(*in))
return ERANGE;
in=(struct in_addr*)buf;
buf+=sizeof(*in);
buflen-=sizeof(*in);
 
if (buflen < sizeof(*addr_list)*2)
return ERANGE;
addr_list=(struct in_addr**)buf;
buf+=sizeof(*addr_list)*2;
buflen-=sizeof(*addr_list)*2;
 
#ifdef __UCLIBC_HAS_IPV6__
if (plen < sizeof(*in6))
return ERANGE;
in6=(struct in6_addr*)qp;
qp+=sizeof(*in6);
plen-=sizeof(*in6);
 
if (plen < sizeof(*addr_list6)*2)
return ERANGE;
addr_list6=(struct in6_addr**)qp;
qp+=sizeof(*addr_list6)*2;
plen-=sizeof(*addr_list6)*2;
 
if (plen < buflen) {
buflen=plen;
buf=qp;
}
#endif /* __UCLIBC_HAS_IPV6__ */
 
if (buflen<256)
return ERANGE;
 
if(type == AF_INET) {
unsigned char *tmp_addr = (unsigned char *)addr;
 
memcpy(&in->s_addr, addr, len);
 
addr_list[0] = in;
 
sprintf(buf, "%u.%u.%u.%u.in-addr.arpa",
tmp_addr[3], tmp_addr[2], tmp_addr[1], tmp_addr[0]);
#ifdef __UCLIBC_HAS_IPV6__
} else {
memcpy(in6->s6_addr, addr, len);
 
addr_list6[0] = in6;
qp = buf;
 
for (i = len - 1; i >= 0; i--) {
qp += sprintf(qp, "%x.%x.", in6->s6_addr[i] & 0xf,
(in6->s6_addr[i] >> 4) & 0xf);
}
strcpy(qp, "ip6.int");
#endif /* __UCLIBC_HAS_IPV6__ */
}
 
addr_list[1] = 0;
 
for (;;) {
 
BIGLOCK;
__nameserversXX=__nameservers;
__nameserverXX=__nameserver;
BIGUNLOCK;
i = __dns_lookup(buf, T_PTR, __nameserversXX, __nameserverXX, &packet, &a);
 
if (i < 0) {
*h_errnop = HOST_NOT_FOUND;
return TRY_AGAIN;
}
 
strncpy(buf, a.dotted, buflen);
free(a.dotted);
 
if (a.atype == T_CNAME) { /* CNAME */
DPRINTF("Got a CNAME in gethostbyaddr()\n");
i = __decode_dotted(packet, a.rdoffset, buf, buflen);
free(packet);
 
if (i < 0) {
*h_errnop = NO_RECOVERY;
return -1;
}
if (++nest > MAX_RECURSE) {
*h_errnop = NO_RECOVERY;
return -1;
}
continue;
} else if (a.atype == T_PTR) { /* ADDRESS */
i = __decode_dotted(packet, a.rdoffset, buf, buflen);
free(packet);
 
result_buf->h_name = buf;
result_buf->h_addrtype = type;
 
if(type == AF_INET) {
result_buf->h_length = sizeof(*in);
#ifdef __UCLIBC_HAS_IPV6__
} else {
result_buf->h_length = sizeof(*in6);
#endif /* __UCLIBC_HAS_IPV6__ */
}
 
result_buf->h_addr_list = (char **) addr_list;
break;
} else {
free(packet);
*h_errnop = NO_ADDRESS;
return TRY_AGAIN;
}
}
 
*result=result_buf;
*h_errnop = NETDB_SUCCESS;
return NETDB_SUCCESS;
}
#endif
 
#ifdef L_res_comp
/*
* Expand compressed domain name 'comp_dn' to full domain name.
* 'msg' is a pointer to the begining of the message,
* 'eomorig' points to the first location after the message,
* 'exp_dn' is a pointer to a buffer of size 'length' for the result.
* Return size of compressed name or -1 if there was an error.
*/
int __dn_expand(const u_char *msg, const u_char *eom, const u_char *src,
char *dst, int dstsiz)
{
int n = ns_name_uncompress(msg, eom, src, dst, (size_t)dstsiz);
 
if (n > 0 && dst[0] == '.')
dst[0] = '\0';
return (n);
}
#endif /* L_res_comp */
 
#ifdef L_ns_name
/*
* printable(ch)
* Thinking in noninternationalized USASCII (per the DNS spec),
* is this character visible and not a space when printed ?
* return:
* boolean.
*/
static int printable(int ch)
{
return (ch > 0x20 && ch < 0x7f);
}
 
/*
* special(ch)
* Thinking in noninternationalized USASCII (per the DNS spec),
* is this characted special ("in need of quoting") ?
* return:
* boolean.
*/
static int special(int ch)
{
switch (ch) {
case 0x22: /* '"' */
case 0x2E: /* '.' */
case 0x3B: /* ';' */
case 0x5C: /* '\\' */
/* Special modifiers in zone files. */
case 0x40: /* '@' */
case 0x24: /* '$' */
return (1);
default:
return (0);
}
}
 
/*
* ns_name_uncompress(msg, eom, src, dst, dstsiz)
* Expand compressed domain name to presentation format.
* return:
* Number of bytes read out of `src', or -1 (with errno set).
* note:
* Root domain returns as "." not "".
*/
int __ns_name_uncompress(const u_char *msg, const u_char *eom,
const u_char *src, char *dst, size_t dstsiz)
{
u_char tmp[NS_MAXCDNAME];
int n;
 
if ((n = ns_name_unpack(msg, eom, src, tmp, sizeof tmp)) == -1)
return (-1);
if (ns_name_ntop(tmp, dst, dstsiz) == -1)
return (-1);
return (n);
}
 
 
/*
* ns_name_ntop(src, dst, dstsiz)
* Convert an encoded domain name to printable ascii as per RFC1035.
* return:
* Number of bytes written to buffer, or -1 (with errno set)
* notes:
* The root is returned as "."
* All other domains are returned in non absolute form
*/
int __ns_name_ntop(const u_char *src, char *dst, size_t dstsiz) {
const u_char *cp;
char *dn, *eom;
u_char c;
u_int n;
const char digits[] = "0123456789";
 
cp = src;
dn = dst;
eom = dst + dstsiz;
 
while ((n = *cp++) != 0) {
if ((n & NS_CMPRSFLGS) != 0) {
/* Some kind of compression pointer. */
__set_errno (EMSGSIZE);
return (-1);
}
if (dn != dst) {
if (dn >= eom) {
__set_errno (EMSGSIZE);
return (-1);
}
*dn++ = '.';
}
if (dn + n >= eom) {
__set_errno (EMSGSIZE);
return (-1);
}
for ((void)NULL; n > 0; n--) {
c = *cp++;
if (special(c)) {
if (dn + 1 >= eom) {
__set_errno (EMSGSIZE);
return (-1);
}
*dn++ = '\\';
*dn++ = (char)c;
} else if (!printable(c)) {
if (dn + 3 >= eom) {
__set_errno (EMSGSIZE);
return (-1);
}
*dn++ = '\\';
*dn++ = digits[c / 100];
*dn++ = digits[(c % 100) / 10];
*dn++ = digits[c % 10];
} else {
if (dn >= eom) {
__set_errno (EMSGSIZE);
return (-1);
}
*dn++ = (char)c;
}
}
}
if (dn == dst) {
if (dn >= eom) {
__set_errno (EMSGSIZE);
return (-1);
}
*dn++ = '.';
}
if (dn >= eom) {
__set_errno (EMSGSIZE);
return (-1);
}
*dn++ = '\0';
return (dn - dst);
}
 
/*
* ns_name_unpack(msg, eom, src, dst, dstsiz)
* Unpack a domain name from a message, source may be compressed.
* return:
* -1 if it fails, or consumed octets if it succeeds.
*/
int __ns_name_unpack(const u_char *msg, const u_char *eom, const u_char *src,
u_char *dst, size_t dstsiz)
{
const u_char *srcp, *dstlim;
u_char *dstp;
int n, len, checked;
 
len = -1;
checked = 0;
dstp = dst;
srcp = src;
dstlim = dst + dstsiz;
if (srcp < msg || srcp >= eom) {
__set_errno (EMSGSIZE);
return (-1);
}
/* Fetch next label in domain name. */
while ((n = *srcp++) != 0) {
/* Check for indirection. */
switch (n & NS_CMPRSFLGS) {
case 0:
/* Limit checks. */
if (dstp + n + 1 >= dstlim || srcp + n >= eom) {
__set_errno (EMSGSIZE);
return (-1);
}
checked += n + 1;
*dstp++ = n;
memcpy(dstp, srcp, n);
dstp += n;
srcp += n;
break;
 
case NS_CMPRSFLGS:
if (srcp >= eom) {
__set_errno (EMSGSIZE);
return (-1);
}
if (len < 0)
len = srcp - src + 1;
srcp = msg + (((n & 0x3f) << 8) | (*srcp & 0xff));
if (srcp < msg || srcp >= eom) { /* Out of range. */
__set_errno (EMSGSIZE);
return (-1);
}
checked += 2;
/*
* Check for loops in the compressed name;
* if we've looked at the whole message,
* there must be a loop.
*/
if (checked >= eom - msg) {
__set_errno (EMSGSIZE);
return (-1);
}
break;
 
default:
__set_errno (EMSGSIZE);
return (-1); /* flag error */
}
}
*dstp = '\0';
if (len < 0)
len = srcp - src;
return (len);
}
#endif /* L_ns_name */
/getnetbynm.c
0,0 → 1,43
/*
* Copyright (c) 1983 Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms are permitted
* provided that the above copyright notice and this paragraph are
* duplicated in all such forms and that any documentation,
* advertising materials, and other materials related to such
* distribution and use acknowledge that the software was developed
* by the University of California, Berkeley. The name of the
* University may not be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
 
#define __FORCE_GLIBC
#include <features.h>
#include <netdb.h>
#include <string.h>
 
extern int _net_stayopen;
 
struct netent *
getnetbyname(const char *name)
{
register struct netent *p;
register char **cp;
 
setnetent(_net_stayopen);
while ((p = getnetent())) {
if (strcmp(p->n_name, name) == 0)
break;
for (cp = p->n_aliases; *cp != 0; cp++)
if (strcmp(*cp, name) == 0)
goto found;
}
found:
if (!_net_stayopen)
endnetent();
return (p);
}
/.indent.pro
0,0 → 1,33
--blank-lines-after-declarations
--blank-lines-after-procedures
--break-before-boolean-operator
--no-blank-lines-after-commas
--braces-on-if-line
--braces-on-struct-decl-line
--comment-indentation25
--declaration-comment-column25
--no-comment-delimiters-on-blank-lines
--cuddle-else
--continuation-indentation4
--case-indentation0
--else-endif-column33
--space-after-cast
--line-comments-indentation0
--declaration-indentation1
--dont-format-first-column-comments
--dont-format-comments
--honour-newlines
--indent-level4
/* changed from 0 to 4 */
--parameter-indentation4
--line-length78 /* changed from 75 */
--continue-at-parentheses
--no-space-after-function-call-names
--dont-break-procedure-type
--dont-star-comments
--leave-optional-blank-lines
--dont-space-special-semicolon
--tab-size4
/* additions by Mark */
--case-brace-indentation0
--leave-preprocessor-space
/ntop.c
0,0 → 1,402
/*
* Copyright (c) 1996-1999 by Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
* ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
* CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
* SOFTWARE.
*/
 
#define __FORCE_GLIBC
#include <features.h>
#include <sys/param.h>
#include <sys/types.h>
#include <sys/socket.h>
 
#include <netinet/in.h>
#include <arpa/inet.h>
#include <arpa/nameser.h>
 
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
 
 
/*
* WARNING: Don't even consider trying to compile this on a system where
* sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
*/
 
 
/* const char *
* inet_ntop4(src, dst, size)
* format an IPv4 address
* return:
* `dst' (as a const)
* notes:
* (1) uses no statics
* (2) takes a u_char* not an in_addr as input
* author:
* Paul Vixie, 1996.
*/
static const char *
inet_ntop4(const u_char *src, char *dst, size_t size)
{
char tmp[sizeof ("255.255.255.255") + 1] = "\0";
int octet;
int i;
 
i = 0;
for (octet = 0; octet <= 3; octet++) {
 
if (src[octet] > 255) {
__set_errno (ENOSPC);
return (NULL);
}
tmp[i++] = '0' + src[octet] / 100;
if (tmp[i - 1] == '0') {
tmp[i - 1] = '0' + (src[octet] / 10 % 10);
if (tmp[i - 1] == '0') i--;
} else {
tmp[i++] = '0' + (src[octet] / 10 % 10);
}
tmp[i++] = '0' + src[octet] % 10;
tmp[i++] = '.';
}
tmp[i - 1] = '\0';
 
if (strlen (tmp) > size) {
__set_errno (ENOSPC);
return (NULL);
}
 
return strcpy(dst, tmp);
}
 
 
/* const char *
* inet_ntop6(src, dst, size)
* convert IPv6 binary address into presentation (printable) format
* author:
* Paul Vixie, 1996.
*/
 
#ifdef __UCLIBC_HAS_IPV6__
 
static const char *
inet_ntop6(const u_char *src, char *dst, size_t size)
{
/*
* Note that int32_t and int16_t need only be "at least" large enough
* to contain a value of the specified size. On some systems, like
* Crays, there is no such thing as an integer variable with 16 bits.
* Keep this in mind if you think this function should have been coded
* to use pointer overlays. All the world's not a VAX.
*/
char tmp[sizeof ("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")], *tp;
struct { int base, len; } best, cur;
u_int words[8];
int i;
 
/*
* Preprocess:
* Copy the input (bytewise) array into a wordwise array.
* Find the longest run of 0x00's in src[] for :: shorthanding.
*/
memset(words, '\0', sizeof words);
for (i = 0; i < 16; i += 2)
words[i / 2] = (src[i] << 8) | src[i + 1];
best.base = -1;
cur.base = -1;
for (i = 0; i < 8; i++) {
if (words[i] == 0) {
if (cur.base == -1)
cur.base = i, cur.len = 1;
else
cur.len++;
} else {
if (cur.base != -1) {
if (best.base == -1 || cur.len > best.len)
best = cur;
cur.base = -1;
}
}
}
if (cur.base != -1) {
if (best.base == -1 || cur.len > best.len)
best = cur;
}
if (best.base != -1 && best.len < 2)
best.base = -1;
 
/*
* Format the result.
*/
tp = tmp;
for (i = 0; i < 8; i++) {
/* Are we inside the best run of 0x00's? */
if (best.base != -1 && i >= best.base &&
i < (best.base + best.len)) {
if (i == best.base)
*tp++ = ':';
continue;
}
/* Are we following an initial run of 0x00s or any real hex? */
if (i != 0)
*tp++ = ':';
/* Is this address an encapsulated IPv4? */
if (i == 6 && best.base == 0 &&
(best.len == 6 || (best.len == 5 && words[5] == 0xffff))) {
if (!inet_ntop4(src+12, tp, sizeof tmp - (tp - tmp)))
return (NULL);
tp += strlen(tp);
break;
}
tp += sprintf(tp, "%x", words[i]);
}
/* Was it a trailing run of 0x00's? */
if (best.base != -1 && (best.base + best.len) == 8)
*tp++ = ':';
*tp++ = '\0';
 
/*
* Check for overflow, copy, and we're done.
*/
if ((size_t)(tp - tmp) > size) {
__set_errno (ENOSPC);
return (NULL);
}
return strcpy(dst, tmp);
}
#endif /* __UCLIBC_HAS_IPV6__ */
 
 
/* int
* inet_pton4(src, dst)
* like inet_aton() but without all the hexadecimal and shorthand.
* return:
* 1 if `src' is a valid dotted quad, else 0.
* notice:
* does not touch `dst' unless it's returning 1.
* author:
* Paul Vixie, 1996.
*/
static int
inet_pton4(const char *src, u_char *dst)
{
int saw_digit, octets, ch;
u_char tmp[4], *tp;
 
saw_digit = 0;
octets = 0;
*(tp = tmp) = 0;
while ((ch = *src++) != '\0') {
 
if (ch >= '0' && ch <= '9') {
u_int new = *tp * 10 + (ch - '0');
 
if (new > 255)
return (0);
*tp = new;
if (! saw_digit) {
if (++octets > 4)
return (0);
saw_digit = 1;
}
} else if (ch == '.' && saw_digit) {
if (octets == 4)
return (0);
*++tp = 0;
saw_digit = 0;
} else
return (0);
}
if (octets < 4)
return (0);
memcpy(dst, tmp, 4);
return (1);
}
 
/* int
* inet_pton6(src, dst)
* convert presentation level address to network order binary form.
* return:
* 1 if `src' is a valid [RFC1884 2.2] address, else 0.
* notice:
* (1) does not touch `dst' unless it's returning 1.
* (2) :: in a full address is silently ignored.
* credit:
* inspired by Mark Andrews.
* author:
* Paul Vixie, 1996.
*/
 
#ifdef __UCLIBC_HAS_IPV6__
 
/* We cannot use the macro version of tolower() or very bad
* things happen when '*src++' gets evaluated multiple times.
* So * undef it here so we get the function version of tolower
* instead.
*/
#undef tolower
 
static int
inet_pton6(const char *src, u_char *dst)
{
static const char xdigits[] = "0123456789abcdef";
u_char tmp[16], *tp, *endp, *colonp;
const char *curtok;
int ch, saw_xdigit;
u_int val;
 
 
tp = memset(tmp, '\0', 16);
endp = tp + 16;
colonp = NULL;
/* Leading :: requires some special handling. */
if (*src == ':')
if (*++src != ':')
return (0);
curtok = src;
saw_xdigit = 0;
val = 0;
while ((ch = tolower (*src++)) != '\0') {
const char *pch;
 
pch = strchr(xdigits, ch);
if (pch != NULL) {
val <<= 4;
val |= (pch - xdigits);
if (val > 0xffff)
return (0);
saw_xdigit = 1;
continue;
}
if (ch == ':') {
curtok = src;
if (!saw_xdigit) {
if (colonp)
return (0);
colonp = tp;
continue;
} else if (*src == '\0') {
return (0);
}
if (tp + 2 > endp)
return (0);
*tp++ = (u_char) (val >> 8) & 0xff;
*tp++ = (u_char) val & 0xff;
saw_xdigit = 0;
val = 0;
continue;
}
if (ch == '.' && ((tp + 4) <= endp) &&
inet_pton4(curtok, tp) > 0) {
tp += 4;
saw_xdigit = 0;
break; /* '\0' was seen by inet_pton4(). */
}
return (0);
}
if (saw_xdigit) {
if (tp + 2 > endp)
return (0);
*tp++ = (u_char) (val >> 8) & 0xff;
*tp++ = (u_char) val & 0xff;
}
if (colonp != NULL) {
/*
* Since some memmove()'s erroneously fail to handle
* overlapping regions, we'll do the shift by hand.
*/
const int n = tp - colonp;
int i;
 
if (tp == endp)
return (0);
for (i = 1; i <= n; i++) {
endp[- i] = colonp[n - i];
colonp[n - i] = 0;
}
tp = endp;
}
if (tp != endp)
return (0);
memcpy(dst, tmp, 16);
return (1);
}
 
#endif /* __UCLIBC_HAS_IPV6__ */
 
 
 
/* char *
* inet_ntop(af, src, dst, size)
* convert a network format address to presentation format.
* return:
* pointer to presentation format address (`dst'), or NULL (see errno).
* author:
* Paul Vixie, 1996.
*/
extern const char *
inet_ntop(af, src, dst, size)
int af;
const void *src;
char *dst;
socklen_t size;
{
switch (af) {
case AF_INET:
return (inet_ntop4(src, dst, size));
#ifdef __UCLIBC_HAS_IPV6__
case AF_INET6:
return (inet_ntop6(src, dst, size));
#endif
default:
__set_errno (EAFNOSUPPORT);
return (NULL);
}
/* NOTREACHED */
}
 
 
/* int
* inet_pton(af, src, dst)
* convert from presentation format (which usually means ASCII printable)
* to network format (which is usually some kind of binary format).
* return:
* 1 if the address was valid for the specified address family
* 0 if the address wasn't valid (`dst' is untouched in this case)
* -1 if some other error occurred (`dst' is untouched in this case, too)
* author:
* Paul Vixie, 1996.
*/
extern int
inet_pton(af, src, dst)
int af;
const char *src;
void *dst;
{
switch (af) {
case AF_INET:
return (inet_pton4(src, dst));
#ifdef __UCLIBC_HAS_IPV6__
case AF_INET6:
return (inet_pton6(src, dst));
#endif
default:
__set_errno (EAFNOSUPPORT);
return (-1);
}
/* NOTREACHED */
}
 
/ntohl.c
0,0 → 1,67
/* vi: set sw=4 ts=4:
* Functions to convert between host and network byte order.
*
* Copyright (C) 2003 by Erik Andersen <andersen@uclibc.org>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Library General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
* for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
 
#include <stdint.h>
#include <endian.h>
#include <byteswap.h>
 
#if __BYTE_ORDER == __BIG_ENDIAN
extern uint32_t ntohl (uint32_t x)
{
return x;
}
 
extern uint16_t ntohs (uint16_t x)
{
return x;
}
 
extern uint32_t htonl (uint32_t x)
{
return x;
}
 
extern uint16_t htons (uint16_t x)
{
return x;
}
#elif __BYTE_ORDER == __LITTLE_ENDIAN
extern uint32_t ntohl (uint32_t x)
{
return __bswap_32(x);
}
 
extern uint16_t ntohs (uint16_t x)
{
return __bswap_16(x);
}
 
extern uint32_t htonl (uint32_t x)
{
return __bswap_32(x);
}
 
extern uint16_t htons (uint16_t x)
{
return __bswap_16(x);
}
#else
#error "You seem to have an unsupported byteorder"
#endif
/in6_addr.c
0,0 → 1,33
/* Copyright (C) 1997, 1998, 2002 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Philip Blundell <pjb27@cam.ac.uk>, 1997.
 
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
 
#define __FORCE_GLIBC
#include <features.h>
#include <netinet/in.h>
 
#ifdef __UCLIBC_HAS_IPV6__
const struct in6_addr __in6addr_any =
{ { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } } };
weak_alias (__in6addr_any, in6addr_any)
const struct in6_addr __in6addr_loopback =
{ { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 } } };
weak_alias(__in6addr_loopback, in6addr_loopback);
#endif /* __UCLIBC_HAS_IPV6__ */
 
 
/getnetbyad.c
0,0 → 1,35
/*
* Copyright (c) 1983 Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms are permitted
* provided that the above copyright notice and this paragraph are
* duplicated in all such forms and that any documentation,
* advertising materials, and other materials related to such
* distribution and use acknowledge that the software was developed
* by the University of California, Berkeley. The name of the
* University may not be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
 
#define __FORCE_GLIBC
#include <features.h>
#include <netdb.h>
 
extern int _net_stayopen;
 
struct netent *getnetbyaddr (uint32_t net, int type)
{
register struct netent *p;
 
setnetent(_net_stayopen);
while ((p = getnetent()))
if (p->n_addrtype == type && p->n_net == net)
break;
if (!_net_stayopen)
endnetent();
return (p);
}
/getaddrinfo.c
0,0 → 1,873
/* $USAGI: getaddrinfo.c,v 1.16 2001/10/04 09:52:03 sekiya Exp $ */
 
/* The Inner Net License, Version 2.00
 
The author(s) grant permission for redistribution and use in source and
binary forms, with or without modification, of the software and documentation
provided that the following conditions are met:
 
0. If you receive a version of the software that is specifically labelled
as not being for redistribution (check the version message and/or README),
you are not permitted to redistribute that version of the software in any
way or form.
1. All terms of the all other applicable copyrights and licenses must be
followed.
2. Redistributions of source code must retain the authors' copyright
notice(s), this list of conditions, and the following disclaimer.
3. Redistributions in binary form must reproduce the authors' copyright
notice(s), this list of conditions, and the following disclaimer in the
documentation and/or other materials provided with the distribution.
4. All advertising materials mentioning features or use of this software
must display the following acknowledgement with the name(s) of the
authors as specified in the copyright notice(s) substituted where
indicated:
 
This product includes software developed by <name(s)>, The Inner
Net, and other contributors.
 
5. Neither the name(s) of the author(s) 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 ITS AUTHORS 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 AUTHORS 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 these license terms cause you a real problem, contact the author. */
 
/* This software is Copyright 1996 by Craig Metz, All Rights Reserved. */
 
#define _GNU_SOURCE
#define __FORCE_GLIBC
#include <features.h>
#include <assert.h>
#include <errno.h>
#include <netdb.h>
#include <resolv.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/un.h>
#include <sys/utsname.h>
#include <net/if.h>
 
/* The following declarations and definitions have been removed from
* the public header since we don't want people to use them. */
#define AI_V4MAPPED 0x0008 /* IPv4-mapped addresses are acceptable. */
#define AI_ALL 0x0010 /* Return both IPv4 and IPv6 addresses. */
#define AI_ADDRCONFIG 0x0020 /* Use configuration of this host to choose
returned address type. */
#define AI_DEFAULT (AI_V4MAPPED | AI_ADDRCONFIG)
 
 
#define GAIH_OKIFUNSPEC 0x0100
#define GAIH_EAI ~(GAIH_OKIFUNSPEC)
 
#ifndef UNIX_PATH_MAX
#define UNIX_PATH_MAX 108
#endif
 
struct gaih_service
{
const char *name;
int num;
};
 
struct gaih_servtuple
{
struct gaih_servtuple *next;
int socktype;
int protocol;
int port;
};
 
static const struct gaih_servtuple nullserv;
 
struct gaih_addrtuple
{
struct gaih_addrtuple *next;
int family;
char addr[16];
uint32_t scopeid;
};
 
struct gaih_typeproto
{
int socktype;
int protocol;
char name[4];
int protoflag;
};
 
/* Values for `protoflag'. */
#define GAI_PROTO_NOSERVICE 1
#define GAI_PROTO_PROTOANY 2
 
static const struct gaih_typeproto gaih_inet_typeproto[] =
{
{ 0, 0, "", 0 },
{ SOCK_STREAM, IPPROTO_TCP, "tcp", 0 },
{ SOCK_DGRAM, IPPROTO_UDP, "udp", 0 },
{ SOCK_RAW, 0, "raw", GAI_PROTO_PROTOANY|GAI_PROTO_NOSERVICE },
{ 0, 0, "", 0 }
};
 
struct gaih
{
int family;
int (*gaih)(const char *name, const struct gaih_service *service,
const struct addrinfo *req, struct addrinfo **pai);
};
 
#if PF_UNSPEC == 0
static const struct addrinfo default_hints;
#else
static const struct addrinfo default_hints =
{ 0, PF_UNSPEC, 0, 0, 0, NULL, NULL, NULL };
#endif
 
 
static int addrconfig (sa_family_t af)
{
int s;
int ret;
int saved_errno = errno;
s = socket(af, SOCK_DGRAM, 0);
if (s < 0)
ret = (errno == EMFILE) ? 1 : 0;
else
{
close(s);
ret = 1;
}
__set_errno (saved_errno);
return ret;
}
 
#if 0
/* Using Unix sockets this way is a security risk. */
static int
gaih_local (const char *name, const struct gaih_service *service,
const struct addrinfo *req, struct addrinfo **pai)
{
struct utsname utsname;
 
if ((name != NULL) && (req->ai_flags & AI_NUMERICHOST))
return GAIH_OKIFUNSPEC | -EAI_NONAME;
 
if ((name != NULL) || (req->ai_flags & AI_CANONNAME))
if (uname (&utsname) < 0)
return -EAI_SYSTEM;
 
if (name != NULL)
{
if (strcmp(name, "localhost") &&
strcmp(name, "local") &&
strcmp(name, "unix") &&
strcmp(name, utsname.nodename))
return GAIH_OKIFUNSPEC | -EAI_NONAME;
}
 
if (req->ai_protocol || req->ai_socktype)
{
const struct gaih_typeproto *tp = gaih_inet_typeproto + 1;
 
while (tp->name[0]
&& ((tp->protoflag & GAI_PROTO_NOSERVICE) != 0
|| (req->ai_socktype != 0 && req->ai_socktype != tp->socktype)
|| (req->ai_protocol != 0
&& !(tp->protoflag & GAI_PROTO_PROTOANY)
&& req->ai_protocol != tp->protocol)))
++tp;
 
if (! tp->name[0])
{
if (req->ai_socktype)
return (GAIH_OKIFUNSPEC | -EAI_SOCKTYPE);
else
return (GAIH_OKIFUNSPEC | -EAI_SERVICE);
}
}
 
*pai = malloc (sizeof (struct addrinfo) + sizeof (struct sockaddr_un)
+ ((req->ai_flags & AI_CANONNAME)
? (strlen(utsname.nodename) + 1): 0));
if (*pai == NULL)
return -EAI_MEMORY;
 
(*pai)->ai_next = NULL;
(*pai)->ai_flags = req->ai_flags;
(*pai)->ai_family = AF_LOCAL;
(*pai)->ai_socktype = req->ai_socktype ? req->ai_socktype : SOCK_STREAM;
(*pai)->ai_protocol = req->ai_protocol;
(*pai)->ai_addrlen = sizeof (struct sockaddr_un);
(*pai)->ai_addr = (void *) (*pai) + sizeof (struct addrinfo);
 
#if SALEN
((struct sockaddr_un *) (*pai)->ai_addr)->sun_len =
sizeof (struct sockaddr_un);
#endif /* SALEN */
 
((struct sockaddr_un *)(*pai)->ai_addr)->sun_family = AF_LOCAL;
memset(((struct sockaddr_un *)(*pai)->ai_addr)->sun_path, 0, UNIX_PATH_MAX);
 
if (service)
{
struct sockaddr_un *sunp = (struct sockaddr_un *) (*pai)->ai_addr;
 
if (strchr (service->name, '/') != NULL)
{
if (strlen (service->name) >= sizeof (sunp->sun_path))
return GAIH_OKIFUNSPEC | -EAI_SERVICE;
 
strcpy (sunp->sun_path, service->name);
}
else
{
if (strlen (P_tmpdir "/") + 1 + strlen (service->name) >=
sizeof (sunp->sun_path))
return GAIH_OKIFUNSPEC | -EAI_SERVICE;
 
__stpcpy (__stpcpy (sunp->sun_path, P_tmpdir "/"), service->name);
}
}
else
{
/* This is a dangerous use of the interface since there is a time
window between the test for the file and the actual creation
(done by the caller) in which a file with the same name could
be created. */
char *buf = ((struct sockaddr_un *) (*pai)->ai_addr)->sun_path;
 
if (__builtin_expect (__path_search (buf, L_tmpnam, NULL, NULL, 0),
0) != 0
|| __builtin_expect (__gen_tempname (buf, __GT_NOCREATE), 0) != 0)
return -EAI_SYSTEM;
}
 
if (req->ai_flags & AI_CANONNAME)
(*pai)->ai_canonname = strcpy ((char *) *pai + sizeof (struct addrinfo)
+ sizeof (struct sockaddr_un),
utsname.nodename);
else
(*pai)->ai_canonname = NULL;
return 0;
}
#endif /* 0 */
 
static int
gaih_inet_serv (const char *servicename, const struct gaih_typeproto *tp,
const struct addrinfo *req, struct gaih_servtuple *st)
{
struct servent *s;
size_t tmpbuflen = 1024;
struct servent ts;
char *tmpbuf;
int r;
 
do
{
tmpbuf = alloca (tmpbuflen);
 
r = getservbyname_r (servicename, tp->name, &ts, tmpbuf, tmpbuflen,
&s);
if (r != 0 || s == NULL)
{
if (r == ERANGE)
tmpbuflen *= 2;
else
return GAIH_OKIFUNSPEC | -EAI_SERVICE;
}
}
while (r);
 
st->next = NULL;
st->socktype = tp->socktype;
st->protocol = ((tp->protoflag & GAI_PROTO_PROTOANY)
? req->ai_protocol : tp->protocol);
st->port = s->s_port;
 
return 0;
}
 
#define gethosts(_family, _type) \
{ \
int i, herrno; \
size_t tmpbuflen; \
struct hostent th; \
char *tmpbuf; \
tmpbuflen = 512; \
no_data = 0; \
do { \
tmpbuflen *= 2; \
tmpbuf = alloca (tmpbuflen); \
rc = gethostbyname2_r (name, _family, &th, tmpbuf, \
tmpbuflen, &h, &herrno); \
} while (rc == ERANGE && herrno == NETDB_INTERNAL); \
if (rc != 0) \
{ \
if (herrno == NETDB_INTERNAL) \
{ \
__set_h_errno (herrno); \
return -EAI_SYSTEM; \
} \
if (herrno == TRY_AGAIN) \
no_data = EAI_AGAIN; \
else \
no_data = herrno == NO_DATA; \
} \
else if (h != NULL) \
{ \
for (i = 0; h->h_addr_list[i]; i++) \
{ \
if (*pat == NULL) { \
*pat = alloca (sizeof(struct gaih_addrtuple)); \
(*pat)->scopeid = 0; \
} \
(*pat)->next = NULL; \
(*pat)->family = _family; \
memcpy ((*pat)->addr, h->h_addr_list[i], \
sizeof(_type)); \
pat = &((*pat)->next); \
} \
} \
}
 
static int
gaih_inet (const char *name, const struct gaih_service *service,
const struct addrinfo *req, struct addrinfo **pai)
{
const struct gaih_typeproto *tp = gaih_inet_typeproto;
struct gaih_servtuple *st = (struct gaih_servtuple *) &nullserv;
struct gaih_addrtuple *at = NULL;
int rc;
int v4mapped = (req->ai_family == PF_UNSPEC || req->ai_family == PF_INET6) &&
(req->ai_flags & AI_V4MAPPED);
 
if (req->ai_protocol || req->ai_socktype)
{
++tp;
 
while (tp->name[0]
&& ((req->ai_socktype != 0 && req->ai_socktype != tp->socktype)
|| (req->ai_protocol != 0
&& !(tp->protoflag & GAI_PROTO_PROTOANY)
&& req->ai_protocol != tp->protocol)))
++tp;
 
if (! tp->name[0])
{
if (req->ai_socktype)
return (GAIH_OKIFUNSPEC | -EAI_SOCKTYPE);
else
return (GAIH_OKIFUNSPEC | -EAI_SERVICE);
}
}
 
if (service != NULL)
{
if ((tp->protoflag & GAI_PROTO_NOSERVICE) != 0)
return (GAIH_OKIFUNSPEC | -EAI_SERVICE);
 
if (service->num < 0)
{
if (tp->name[0])
{
st = (struct gaih_servtuple *)
alloca (sizeof (struct gaih_servtuple));
 
if ((rc = gaih_inet_serv (service->name, tp, req, st)))
return rc;
}
else
{
struct gaih_servtuple **pst = &st;
for (tp++; tp->name[0]; tp++)
{
struct gaih_servtuple *newp;
 
if ((tp->protoflag & GAI_PROTO_NOSERVICE) != 0)
continue;
 
if (req->ai_socktype != 0
&& req->ai_socktype != tp->socktype)
continue;
if (req->ai_protocol != 0
&& !(tp->protoflag & GAI_PROTO_PROTOANY)
&& req->ai_protocol != tp->protocol)
continue;
 
newp = (struct gaih_servtuple *)
alloca (sizeof (struct gaih_servtuple));
 
if ((rc = gaih_inet_serv (service->name, tp, req, newp)))
{
if (rc & GAIH_OKIFUNSPEC)
continue;
return rc;
}
 
*pst = newp;
pst = &(newp->next);
}
if (st == (struct gaih_servtuple *) &nullserv)
return (GAIH_OKIFUNSPEC | -EAI_SERVICE);
}
}
else
{
st = alloca (sizeof (struct gaih_servtuple));
st->next = NULL;
st->socktype = tp->socktype;
st->protocol = ((tp->protoflag & GAI_PROTO_PROTOANY)
? req->ai_protocol : tp->protocol);
st->port = htons (service->num);
}
}
else if (req->ai_socktype || req->ai_protocol)
{
st = alloca (sizeof (struct gaih_servtuple));
st->next = NULL;
st->socktype = tp->socktype;
st->protocol = ((tp->protoflag & GAI_PROTO_PROTOANY)
? req->ai_protocol : tp->protocol);
st->port = 0;
}
else
{
/*
* Neither socket type nor protocol is set. Return all socket types
* we know about.
*/
struct gaih_servtuple **lastp = &st;
for (++tp; tp->name[0]; ++tp)
{
struct gaih_servtuple *newp;
 
newp = alloca (sizeof (struct gaih_servtuple));
newp->next = NULL;
newp->socktype = tp->socktype;
newp->protocol = tp->protocol;
newp->port = 0;
 
*lastp = newp;
lastp = &newp->next;
}
}
 
if (name != NULL)
{
at = alloca (sizeof (struct gaih_addrtuple));
 
at->family = AF_UNSPEC;
at->scopeid = 0;
at->next = NULL;
 
if (inet_pton (AF_INET, name, at->addr) > 0)
{
if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET || v4mapped)
at->family = AF_INET;
else
return -EAI_FAMILY;
}
 
#if __UCLIBC_HAS_IPV6__
if (at->family == AF_UNSPEC)
{
char *namebuf = strdupa (name);
char *scope_delim;
 
scope_delim = strchr (namebuf, SCOPE_DELIMITER);
if (scope_delim != NULL)
*scope_delim = '\0';
 
if (inet_pton (AF_INET6, namebuf, at->addr) > 0)
{
if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET6)
at->family = AF_INET6;
else
return -EAI_FAMILY;
 
if (scope_delim != NULL)
{
int try_numericscope = 0;
if (IN6_IS_ADDR_LINKLOCAL (at->addr)
|| IN6_IS_ADDR_MC_LINKLOCAL (at->addr))
{
at->scopeid = if_nametoindex (scope_delim + 1);
if (at->scopeid == 0)
try_numericscope = 1;
}
else
try_numericscope = 1;
 
if (try_numericscope != 0)
{
char *end;
assert (sizeof (uint32_t) <= sizeof (unsigned long));
at->scopeid = (uint32_t) strtoul (scope_delim + 1, &end,
10);
if (*end != '\0')
return GAIH_OKIFUNSPEC | -EAI_NONAME;
}
}
}
}
#endif
 
if (at->family == AF_UNSPEC && (req->ai_flags & AI_NUMERICHOST) == 0)
{
struct hostent *h;
struct gaih_addrtuple **pat = &at;
int no_data = 0;
int no_inet6_data;
 
/*
* If we are looking for both IPv4 and IPv6 address we don't want
* the lookup functions to automatically promote IPv4 addresses to
* IPv6 addresses.
*/
 
#if __UCLIBC_HAS_IPV6__
if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET6)
gethosts (AF_INET6, struct in6_addr);
#endif
no_inet6_data = no_data;
 
if (req->ai_family == AF_INET ||
(!v4mapped && req->ai_family == AF_UNSPEC) ||
(v4mapped && (no_inet6_data != 0 || (req->ai_flags & AI_ALL))))
gethosts (AF_INET, struct in_addr);
 
if (no_data != 0 && no_inet6_data != 0)
{
/* If both requests timed out report this. */
if (no_data == EAI_AGAIN && no_inet6_data == EAI_AGAIN)
return -EAI_AGAIN;
 
/*
* We made requests but they turned out no data.
* The name is known, though.
*/
return (GAIH_OKIFUNSPEC | -EAI_AGAIN);
}
}
 
if (at->family == AF_UNSPEC)
return (GAIH_OKIFUNSPEC | -EAI_NONAME);
}
else
{
struct gaih_addrtuple *atr;
atr = at = alloca (sizeof (struct gaih_addrtuple));
memset (at, '\0', sizeof (struct gaih_addrtuple));
 
if (req->ai_family == 0)
{
at->next = alloca (sizeof (struct gaih_addrtuple));
memset (at->next, '\0', sizeof (struct gaih_addrtuple));
}
 
#if __UCLIBC_HAS_IPV6__
if (req->ai_family == 0 || req->ai_family == AF_INET6)
{
extern const struct in6_addr __in6addr_loopback;
at->family = AF_INET6;
if ((req->ai_flags & AI_PASSIVE) == 0)
memcpy (at->addr, &__in6addr_loopback, sizeof (struct in6_addr));
atr = at->next;
}
#endif
 
if (req->ai_family == 0 || req->ai_family == AF_INET)
{
atr->family = AF_INET;
if ((req->ai_flags & AI_PASSIVE) == 0)
*(uint32_t *) atr->addr = htonl (INADDR_LOOPBACK);
}
}
 
if (pai == NULL)
return 0;
 
{
const char *c = NULL;
struct gaih_servtuple *st2;
struct gaih_addrtuple *at2 = at;
size_t socklen, namelen;
sa_family_t family;
 
/*
* buffer is the size of an unformatted IPv6 address in
* printable format.
*/
char buffer[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"];
 
while (at2 != NULL)
{
if (req->ai_flags & AI_CANONNAME)
{
struct hostent *h = NULL;
 
int herrno;
struct hostent th;
size_t tmpbuflen = 512;
char *tmpbuf;
 
do
{
tmpbuflen *= 2;
tmpbuf = alloca (tmpbuflen);
 
if (tmpbuf == NULL)
return -EAI_MEMORY;
 
rc = gethostbyaddr_r (at2->addr,
((at2->family == AF_INET6)
? sizeof(struct in6_addr)
: sizeof(struct in_addr)),
at2->family, &th, tmpbuf, tmpbuflen,
&h, &herrno);
 
}
while (rc == errno && herrno == NETDB_INTERNAL);
 
if (rc != 0 && herrno == NETDB_INTERNAL)
{
__set_h_errno (herrno);
return -EAI_SYSTEM;
}
 
if (h == NULL)
c = inet_ntop (at2->family, at2->addr, buffer, sizeof(buffer));
else
c = h->h_name;
 
if (c == NULL)
return GAIH_OKIFUNSPEC | -EAI_NONAME;
 
namelen = strlen (c) + 1;
}
else
namelen = 0;
 
#if __UCLIBC_HAS_IPV6__
if (at2->family == AF_INET6 || v4mapped)
{
family = AF_INET6;
socklen = sizeof (struct sockaddr_in6);
}
else
#endif
{
family = AF_INET;
socklen = sizeof (struct sockaddr_in);
}
 
for (st2 = st; st2 != NULL; st2 = st2->next)
{
*pai = malloc (sizeof (struct addrinfo) + socklen + namelen);
if (*pai == NULL)
return -EAI_MEMORY;
 
(*pai)->ai_flags = req->ai_flags;
(*pai)->ai_family = family;
(*pai)->ai_socktype = st2->socktype;
(*pai)->ai_protocol = st2->protocol;
(*pai)->ai_addrlen = socklen;
(*pai)->ai_addr = (void *) (*pai) + sizeof(struct addrinfo);
#if SALEN
(*pai)->ai_addr->sa_len = socklen;
#endif /* SALEN */
(*pai)->ai_addr->sa_family = family;
 
#if __UCLIBC_HAS_IPV6__
if (family == AF_INET6)
{
struct sockaddr_in6 *sin6p =
(struct sockaddr_in6 *) (*pai)->ai_addr;
 
sin6p->sin6_flowinfo = 0;
if (at2->family == AF_INET6)
{
memcpy (&sin6p->sin6_addr,
at2->addr, sizeof (struct in6_addr));
}
else
{
sin6p->sin6_addr.s6_addr32[0] = 0;
sin6p->sin6_addr.s6_addr32[1] = 0;
sin6p->sin6_addr.s6_addr32[2] = htonl(0x0000ffff);
memcpy(&sin6p->sin6_addr.s6_addr32[3],
at2->addr, sizeof (sin6p->sin6_addr.s6_addr32[3]));
}
sin6p->sin6_port = st2->port;
sin6p->sin6_scope_id = at2->scopeid;
}
else
#endif
{
struct sockaddr_in *sinp =
(struct sockaddr_in *) (*pai)->ai_addr;
 
memcpy (&sinp->sin_addr,
at2->addr, sizeof (struct in_addr));
sinp->sin_port = st2->port;
memset (sinp->sin_zero, '\0', sizeof (sinp->sin_zero));
}
 
if (c)
{
(*pai)->ai_canonname = ((void *) (*pai) +
sizeof (struct addrinfo) + socklen);
strcpy ((*pai)->ai_canonname, c);
}
else
(*pai)->ai_canonname = NULL;
 
(*pai)->ai_next = NULL;
pai = &((*pai)->ai_next);
}
 
at2 = at2->next;
}
}
return 0;
}
 
static struct gaih gaih[] =
{
#if __UCLIBC_HAS_IPV6__
{ PF_INET6, gaih_inet },
#endif
{ PF_INET, gaih_inet },
#if 0
{ PF_LOCAL, gaih_local },
#endif
{ PF_UNSPEC, NULL }
};
 
int
getaddrinfo (const char *name, const char *service,
const struct addrinfo *hints, struct addrinfo **pai)
{
int i = 0, j = 0, last_i = 0;
struct addrinfo *p = NULL, **end;
struct gaih *g = gaih, *pg = NULL;
struct gaih_service gaih_service, *pservice;
 
if (name != NULL && name[0] == '*' && name[1] == 0)
name = NULL;
 
if (service != NULL && service[0] == '*' && service[1] == 0)
service = NULL;
 
if (name == NULL && service == NULL)
return EAI_NONAME;
 
if (hints == NULL)
hints = &default_hints;
 
if (hints->ai_flags & ~(AI_PASSIVE|AI_CANONNAME|AI_NUMERICHOST|
AI_ADDRCONFIG|AI_V4MAPPED|AI_ALL))
return EAI_BADFLAGS;
 
if ((hints->ai_flags & AI_CANONNAME) && name == NULL)
return EAI_BADFLAGS;
 
if (service && service[0])
{
char *c;
gaih_service.name = service;
gaih_service.num = strtoul (gaih_service.name, &c, 10);
if (*c)
gaih_service.num = -1;
else
/*
* Can't specify a numerical socket unless a protocol
* family was given.
*/
if (hints->ai_socktype == 0 && hints->ai_protocol == 0)
return EAI_SERVICE;
pservice = &gaih_service;
}
else
pservice = NULL;
 
if (pai)
end = &p;
else
end = NULL;
 
while (g->gaih)
{
if (hints->ai_family == g->family || hints->ai_family == AF_UNSPEC)
{
if ((hints->ai_flags & AI_ADDRCONFIG) && !addrconfig(g->family))
continue;
j++;
if (pg == NULL || pg->gaih != g->gaih)
{
pg = g;
i = g->gaih (name, pservice, hints, end);
if (i != 0)
{
last_i = i;
 
if (hints->ai_family == AF_UNSPEC && (i & GAIH_OKIFUNSPEC))
continue;
 
if (p)
freeaddrinfo (p);
 
return -(i & GAIH_EAI);
}
if (end)
while(*end) end = &((*end)->ai_next);
}
}
++g;
}
 
if (j == 0)
return EAI_FAMILY;
 
if (p)
{
*pai = p;
return 0;
}
 
if (pai == NULL && last_i == 0)
return 0;
 
if (p)
freeaddrinfo (p);
 
return last_i ? -(last_i & GAIH_EAI) : EAI_NONAME;
}
 
void
freeaddrinfo (struct addrinfo *ai)
{
struct addrinfo *p;
 
while (ai != NULL)
{
p = ai;
ai = ai->ai_next;
free (p);
}
}
/if_nametoindex.c
0,0 → 1,167
/* Copyright (C) 1997,98,99,2000,02 Free Software Foundation, Inc.
* This file is part of the GNU C Library.
*
* The GNU C Library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* The GNU C Library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with the GNU C Library; if not, write to the Free
* Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
* 02111-1307 USA.
*
* Reworked Dec 2002 by Erik Andersen <andersen@codepoet.org>
*/
 
#define __FORCE_GLIBC
#include <features.h>
#include <string.h>
#include <errno.h>
#include <net/if.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <stdlib.h>
 
static int __opensock(void)
{
int fd;
#ifdef __UCLIBC_HAS_IPV6__
fd=socket(AF_INET6,SOCK_DGRAM,0);
if (fd<0)
#endif /* __UCLIBC_HAS_IPV6__ */
fd=socket(AF_INET,SOCK_DGRAM,0);
return(fd);
}
 
unsigned int if_nametoindex(const char* ifname)
{
#ifndef SIOCGIFINDEX
__set_errno (ENOSYS);
return 0;
#else
int fd;
struct ifreq ifr;
 
fd = __opensock();
if (fd < 0)
return 0;
strncpy (ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
if (ioctl(fd,SIOCGIFINDEX,&ifr) < 0) {
int saved_errno = errno;
close(fd);
if (saved_errno == EINVAL)
__set_errno(ENOSYS);
return 0;
}
close(fd);
return ifr.ifr_ifindex;
 
#endif /* SIOCGIFINDEX */
}
 
void if_freenameindex (struct if_nameindex *ifn)
{
struct if_nameindex *ptr = ifn;
while (ptr->if_name || ptr->if_index) {
if (ptr->if_name) {
free (ptr->if_name);
}
++ptr;
}
free (ifn);
}
 
struct if_nameindex * if_nameindex (void)
{
#ifndef SIOCGIFINDEX
__set_errno (ENOSYS);
return NULL;
#else
int fd;
struct ifconf ifc;
unsigned int nifs, i;
int rq_len;
struct if_nameindex *idx = NULL;
# define RQ_IFS 4
 
fd = __opensock();
if (fd < 0)
return 0;
 
ifc.ifc_buf = NULL;
 
/* Guess on the correct buffer size... */
rq_len = RQ_IFS * sizeof (struct ifreq);
 
/* Read all the interfaces out of the kernel. */
do {
ifc.ifc_buf = realloc(ifc.ifc_buf, ifc.ifc_len = rq_len);
if (ifc.ifc_buf == NULL || ioctl(fd, SIOCGIFCONF, &ifc) < 0) {
close(fd);
return NULL;
}
rq_len *= 2;
} while (ifc.ifc_len == rq_len);
 
nifs = ifc.ifc_len / sizeof(struct ifreq);
 
idx = malloc ((nifs + 1) * sizeof(struct if_nameindex));
if (idx == NULL) {
close(fd);
__set_errno(ENOBUFS);
return NULL;
}
 
for (i = 0; i < nifs; ++i) {
struct ifreq *ifr = &ifc.ifc_req[i];
idx[i].if_name = strdup (ifr->ifr_name);
if (idx[i].if_name == NULL || ioctl(fd,SIOCGIFINDEX,ifr) < 0) {
int saved_errno = errno;
unsigned int j;
for (j = 0; j < i; ++j)
free (idx[j].if_name);
free(idx);
close(fd);
if (saved_errno == EINVAL)
saved_errno = ENOSYS;
else if (saved_errno == ENOMEM)
saved_errno = ENOBUFS;
__set_errno (saved_errno);
return NULL;
}
idx[i].if_index = ifr->ifr_ifindex;
}
 
idx[i].if_index = 0;
idx[i].if_name = NULL;
 
close(fd);
return idx;
#endif
}
 
char * if_indextoname (unsigned int ifindex, char *ifname)
{
struct if_nameindex *idx;
struct if_nameindex *p;
char *result = NULL;
 
idx = if_nameindex();
if (idx != NULL) {
for (p = idx; p->if_index || p->if_name; ++p) {
if (p->if_index == ifindex) {
result = strncpy (ifname, p->if_name, IFNAMSIZ);
break;
}
}
if_freenameindex (idx);
}
return result;
}
 
/hostid.c
0,0 → 1,76
#define __FORCE_GLIBC
#include <features.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/param.h>
#include <netinet/in.h>
#include <netdb.h>
#include <fcntl.h>
#include <unistd.h>
 
 
#define HOSTID "/etc/hostid"
 
int sethostid(long int new_id)
{
int fd;
int ret;
 
if (geteuid() || getuid()) return __set_errno(EPERM);
if ((fd=open(HOSTID,O_CREAT|O_WRONLY,0644))<0) return -1;
ret = write(fd,(void *)&new_id,sizeof(new_id)) == sizeof(new_id)
? 0 : -1;
close (fd);
return ret;
}
 
long int gethostid(void)
{
char host[MAXHOSTNAMELEN + 1];
int fd, id;
 
/* If hostid was already set the we can return that value.
* It is not an error if we cannot read this file. It is not even an
* error if we cannot read all the bytes, we just carry on trying...
*/
if ((fd=open(HOSTID,O_RDONLY))>=0 && read(fd,(void *)&id,sizeof(id)))
{
close (fd);
return id;
}
if (fd >= 0) close (fd);
 
/* Try some methods of returning a unique 32 bit id. Clearly IP
* numbers, if on the internet, will have a unique address. If they
* are not on the internet then we can return 0 which means they should
* really set this number via a sethostid() call. If their hostname
* returns the loopback number (i.e. if they have put their hostname
* in the /etc/hosts file with 127.0.0.1) then all such hosts will
* have a non-unique hostid, but it doesn't matter anyway and
* gethostid() will return a non zero number without the need for
* setting one anyway.
* Mitch
*/
if (gethostname(host,MAXHOSTNAMELEN)>=0 && *host) {
struct hostent *hp;
struct in_addr in;
 
if ((hp = gethostbyname(host)) == (struct hostent *)NULL)
 
/* This is not a error if we get here, as all it means is that
* this host is not on a network and/or they have not
* configured their network properly. So we return the unset
* hostid which should be 0, meaning that they should set it !!
*/
return 0;
else {
memcpy((char *) &in, (char *) hp->h_addr, hp->h_length);
 
/* Just so it doesn't look exactly like the IP addr */
return(in.s_addr<<16|in.s_addr>>16);
}
}
else return 0;
 
}
/Makefile
0,0 → 1,98
# Makefile for uClibc
#
# Copyright (C) 2000 by Lineo, inc.
# Copyright (C) 2000,2001 Erik Andersen <andersen@uclibc.org>
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU Library General Public License as published by the Free
# Software Foundation; either version 2 of the License, or (at your option) any
# later version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more
# details.
#
# You should have received a copy of the GNU Library General Public License
# along with this program; if not, write to the Free Software Foundation, Inc.,
# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# Derived in part from the Linux-8086 C library, the GNU C Library, and several
# other sundry sources. Files within this library are copyright by their
# respective copyright holders.
 
TOPDIR=../../
include $(TOPDIR)Rules.mak
 
ifeq ($(strip $(UCLIBC_HAS_RPC)),y)
DIRS=rpc
else
DIRS=
endif
ALL_SUBDIRS = rpc
 
MSRC=addr.c
MOBJ=inet_aton.o inet_addr.o inet_ntoa.o inet_makeaddr.o inet_lnaof.o \
inet_netof.o
 
MSRC2=resolv.c
MOBJ2=encodeh.o decodeh.o encoded.o decoded.o lengthd.o encodeq.o \
decodeq.o lengthq.o encodea.o decodea.o encodep.o decodep.o \
formquery.o dnslookup.o resolveaddress.o opennameservers.o \
closenameservers.o resolvename.o gethostbyname.o res_init.o \
res_query.o gethostbyaddr.o read_etc_hosts_r.o get_hosts_byname_r.o \
get_hosts_byaddr_r.o gethostbyname2.o getnameinfo.o gethostent.o \
gethostbyname_r.o gethostbyname2_r.o gethostbyaddr_r.o \
res_comp.o ns_name.o
 
MSRC3=socketcalls.c
MOBJ3= accept.o bind.o connect.o getpeername.o getsockname.o getsockopt.o \
listen.o recv.o recvfrom.o recvmsg.o send.o sendmsg.o sendto.o \
setsockopt.o shutdown.o socket.o socketpair.o
 
CSRC =getservice.c getproto.c hostid.c getnetent.c getnetbynm.c getnetbyad.c \
inet_net.c ntop.c herror.c if_nametoindex.c gai_strerror.c getaddrinfo.c \
in6_addr.c ether_addr.c ntohl.c
 
COBJS=$(patsubst %.c,%.o, $(CSRC))
 
OBJS=$(MOBJ) $(MOBJ2) $(MOBJ3) $(COBJS)
 
 
all: $(OBJS) $(LIBC)
 
$(LIBC): ar-target subdirs
 
ar-target: $(OBJS)
$(AR) $(ARFLAGS) $(LIBC) $(OBJS)
 
$(MOBJ): $(MSRC)
$(CC) $(CFLAGS) -DL_$* $< -c -o $*.o
$(STRIPTOOL) -x -R .note -R .comment $*.o
 
$(MOBJ2): $(MSRC2)
$(CC) $(CFLAGS) -DL_$* $< -c -o $*.o
$(STRIPTOOL) -x -R .note -R .comment $*.o
 
$(MOBJ3): $(MSRC3)
$(CC) $(CFLAGS) -DL_$* $< -c -o $*.o
$(STRIPTOOL) -x -R .note -R .comment $*.o
 
$(COBJS): %.o : %.c
$(CC) $(CFLAGS) -c $< -o $@
$(STRIPTOOL) -x -R .note -R .comment $*.o
 
clean: subdirs_clean
$(RM) *.[oa] *~ core
 
subdirs: $(patsubst %, _dir_%, $(DIRS))
subdirs_clean: $(patsubst %, _dirclean_%, $(ALL_SUBDIRS))
 
$(patsubst %, _dir_%, $(DIRS)) : dummy
$(MAKE) -C $(patsubst _dir_%, %, $@)
 
$(patsubst %, _dirclean_%, $(ALL_SUBDIRS)) : dummy
$(MAKE) -C $(patsubst _dirclean_%, %, $@) clean
 
.PHONY: dummy
 
/getnetent.c
0,0 → 1,134
/*
* Copyright (c) 1983 Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms are permitted
* provided that the above copyright notice and this paragraph are
* duplicated in all such forms and that any documentation,
* advertising materials, and other materials related to such
* distribution and use acknowledge that the software was developed
* by the University of California, Berkeley. The name of the
* University may not be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
 
#define __FORCE_GLIBC
#include <features.h>
#include <stdio.h>
#include <netdb.h>
#include <arpa/inet.h>
 
 
#ifdef __UCLIBC_HAS_THREADS__
#include <pthread.h>
static pthread_mutex_t mylock = PTHREAD_MUTEX_INITIALIZER;
# define LOCK __pthread_mutex_lock(&mylock)
# define UNLOCK __pthread_mutex_unlock(&mylock);
#else
# define LOCK
# define UNLOCK
#endif
 
 
 
#define MAXALIASES 35
static const char NETDB[] = _PATH_NETWORKS;
static FILE *netf = NULL;
static char line[BUFSIZ+1];
static struct netent net;
static char *net_aliases[MAXALIASES];
 
int _net_stayopen;
 
void setnetent(int f)
{
LOCK;
if (netf == NULL)
netf = fopen(NETDB, "r" );
else
rewind(netf);
_net_stayopen |= f;
UNLOCK;
return;
}
 
void endnetent(void)
{
LOCK;
if (netf) {
fclose(netf);
netf = NULL;
}
_net_stayopen = 0;
UNLOCK;
}
 
static char * any(register char *cp, char *match)
{
register char *mp, c;
 
while ((c = *cp)) {
for (mp = match; *mp; mp++)
if (*mp == c)
return (cp);
cp++;
}
return ((char *)0);
}
 
struct netent * getnetent(void)
{
char *p;
register char *cp, **q;
 
LOCK;
if (netf == NULL && (netf = fopen(NETDB, "r" )) == NULL) {
UNLOCK;
return (NULL);
}
again:
p = fgets(line, BUFSIZ, netf);
if (p == NULL) {
UNLOCK;
return (NULL);
}
if (*p == '#')
goto again;
cp = any(p, "#\n");
if (cp == NULL)
goto again;
*cp = '\0';
net.n_name = p;
cp = any(p, " \t");
if (cp == NULL)
goto again;
*cp++ = '\0';
while (*cp == ' ' || *cp == '\t')
cp++;
p = any(cp, " \t");
if (p != NULL)
*p++ = '\0';
net.n_net = inet_network(cp);
net.n_addrtype = AF_INET;
q = net.n_aliases = net_aliases;
if (p != NULL)
cp = p;
while (cp && *cp) {
if (*cp == ' ' || *cp == '\t') {
cp++;
continue;
}
if (q < &net_aliases[MAXALIASES - 1])
*q++ = cp;
cp = any(cp, " \t");
if (cp != NULL)
*cp++ = '\0';
}
*q = NULL;
UNLOCK;
return (&net);
}
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.