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, ®s->pm_prog) && |
xdr_u_long (xdrs, ®s->pm_vers) && |
xdr_u_long (xdrs, ®s->pm_prot)) |
return xdr_u_long (xdrs, ®s->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); |
} |
|