int CMInitCommunicationWithSocketAndConverter(int socket, xdrproc_t converterf) { if ( socket < 0 || NULL == converterf ) return errno = EINVAL, -1; unsigned int index = -1U; pthread_mutex_t *mutex = &CMInternalData.mutex; pthread_mutex_lock(mutex); CMCommunicationDescriptionContext *communicationContexts = CMInternalData.CMCommunicationContexts; pthread_cleanup_push( (void (*)())pthread_mutex_lock, mutex); if ( NULL == communicationContexts ) { /* On initialization */ /* alloc */ const unsigned int initialSize = 1<<4; /* 16 */ communicationContexts = calloc((size_t)initialSize, sizeof(CMCommunicationDescriptionContext)); if ( communicationContexts == NULL ) return pthread_mutex_unlock(mutex), errno = ENOMEM, -1; CMInternalData.CMCommunicationContexts = communicationContexts; CMInternalData.capacity = initialSize; /* initialize at -1 */ for (unsigned int i=0; i<CMInternalData.capacity; communicationContexts[i].socket = -1, i++); } for (unsigned int i=0; i<CMInternalData.capacity; i++) if (communicationContexts[i].socket == -1) { index = i; break; } if (index >= CMInternalData.capacity) { /* No space left => should make some space */ /* If doubling the size of the array will exceed limits then */ if (UINT_MAX - CMInternalData.capacity >= CMInternalData.capacity) return pthread_mutex_unlock(mutex), errno = ENOMEM, -1; unsigned int newCapacity = CMInternalData.capacity<<1; /* double the size */ CMCommunicationDescriptionContext *newCommunicationContexts = realloc(communicationContexts, newCapacity * sizeof(CMCommunicationDescriptionContext)); if (NULL == newCommunicationContexts) return pthread_mutex_unlock(mutex), errno = ENOMEM, -1; for (unsigned int i=CMInternalData.capacity; i<newCapacity; newCommunicationContexts[i].socket=-1, i++); CMInternalData.CMCommunicationContexts = communicationContexts = newCommunicationContexts; CMInternalData.capacity = newCapacity; } /* Initialization */ CMCommunicationDescriptionContext *context = &(communicationContexts[index]); context->socket = socket; context->converterf = converterf; context->communicationDescriptor = (int)index; #if defined(__APPLE__) && defined(__MACH__) xdrrec_create( &(context->xdrs), 0, 0, (void *)context, readit, writeit); #else xdrrec_create( &(context->xdrs), 0, 0, (void *)context, (int (*)(char*,char*,int))readit, (int (*)(char*,char*,int))writeit); #endif pthread_cleanup_pop(0); pthread_mutex_unlock(mutex); return (int)index; }
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 enum clnt_stat clnttcp_call(struct client *clnt, uint32_t procnum, xdrproc_t inproc, char *in, xdrproc_t outproc, char *out, struct timeval timeout) { struct xdr xstream; struct rpc_msg msg_reply, msg_call; assert((clnt != NULL) && (inproc != NULL)); msg_call.xid = (uint32_t)rand(); msg_call.type = CALL; msg_call.b.call.rpcvers = RPC_VERSION; msg_call.b.call.prog = clnt->prognum; msg_call.b.call.vers = clnt->versnum; msg_call.b.call.proc = procnum; memcpy(&msg_call.b.call.cred, &clnt->ath->cred, sizeof clnt->ath->cred); memcpy(&msg_call.b.call.verf, &clnt->ath->verf, sizeof clnt->ath->verf); if (-1 == setsockopt(clnt->sock, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof timeout)) { LOG_ERROR("clnttcp_call", "setsockopt error"); clnt->err.extra.error = errno; return clnt->err.status = RPC_SYSTEMERROR; } xdrrec_create(&xstream, clnt->extra.tcp.sendsz, clnt->extra.tcp.recvsz, (char *)clnt, (xdrrec_hnd_t)readtcp, (xdrrec_hnd_t)writetcp); xstream.oper = XDR_ENCODE; clnt->err.status = RPC_SUCCESS; if (!xdr_rpc_msg(&xstream, &msg_call) || !(*inproc)(&xstream, in)) { if (clnt->err.status == RPC_SUCCESS) { clnt->err.status = RPC_CANTENCODEARGS; } goto exit_with_status; } if (!xdrrec_endofrecord(&xstream, 1)) { clnt->err.status = RPC_CANTSEND; goto exit_with_status; } xstream.oper = XDR_DECODE; msg_reply.b.reply.r.accepted.d.result.decoder = outproc; msg_reply.b.reply.r.accepted.d.result.param = out; assert(clnt->err.status == RPC_SUCCESS); if (!xdr_rpc_msg(&xstream, &msg_reply)) { if (clnt->err.status == RPC_SUCCESS) { clnt->err.status = RPC_CANTDECODERES; } goto exit_with_status; } assert(clnt->err.status == RPC_SUCCESS); exit_with_status: xdr_destroy(&xstream); return clnt->err.status; }
/* * ndmp_create_connection * * Allocate and initialize a connection structure. * * Parameters: * handler_tbl (input) - message handlers. * * Returns: * NULL - error * connection pointer * * Notes: * The returned connection should be destroyed using * ndmp_destroy_connection(). */ ndmp_connection_t * ndmp_create_connection(void) { ndmp_connection_t *connection; connection = ndmp_malloc(sizeof (ndmp_connection_t)); if (connection == NULL) return (NULL); connection->conn_sock = -1; connection->conn_my_sequence = 0; connection->conn_authorized = FALSE; connection->conn_eof = FALSE; connection->conn_msginfo.mi_body = 0; connection->conn_version = ndmp_ver; connection->conn_client_data = 0; (void) mutex_init(&connection->conn_lock, 0, NULL); connection->conn_xdrs.x_ops = 0; xdrrec_create(&connection->conn_xdrs, 0, 0, (caddr_t)connection, ndmp_readit, ndmp_writeit); if (connection->conn_xdrs.x_ops == 0) { NDMP_LOG(LOG_DEBUG, "xdrrec_create failed"); (void) mutex_destroy(&connection->conn_lock); (void) close(connection->conn_sock); free(connection); return (0); } return ((ndmp_connection_t *)connection); }
/* * Like svtcp_create(), except the routine takes any *open* UNIX file * descriptor as its first input. It is only called by Rendezvous_request * which will use poll() not select() so it doesn't need to call Xprt_register. */ static SVCXPRT *Makefd_xprt(int fd, u_int sendsize, u_int recvsize) { register SVCXPRT *xprt; register struct tcp_conn *cd; xprt = (SVCXPRT *) Mem_Alloc(sizeof(SVCXPRT)); if(xprt == (SVCXPRT *) NULL) { goto done; } cd = (struct tcp_conn *)Mem_Alloc(sizeof(struct tcp_conn)); if(cd == (struct tcp_conn *)NULL) { Mem_Free((char *)xprt); xprt = (SVCXPRT *) NULL; goto done; } 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; /* truely deals with calls */ xprt->xp_port = 0; /* this is a connection, not a rendezvouser */ xprt->XP_SOCK = fd; Xports[fd] = xprt; done: return (xprt); }
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) { (void) __fxprintf (NULL, "%s: %s", "svc_unix: makefd_xprt", _("out of memory\n")); 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; }
RttfClient::RttfClient() : m_socket(INVALID_SOCKET), m_connected(FALSE), m_available(FALSE), m_running(FALSE), #ifndef _WIN32 m_tidRead(0), m_tidWrite(0), m_tidQueue(0), #endif m_pInQ(NULL), m_pOutQ(NULL) { #ifdef _WIN32 memset(m_user_id, 0, sizeof(m_user_id)); memset(&m_tids, 0, sizeof(m_tids)); memset(&m_threads, 0, sizeof(m_threads)); // Initialize WinSock // Note, this really shouldn't be in the constructor! WSADATA wsaData; memset(&wsaData, 0, sizeof(wsaData)); WORD wVersionRequested = MAKEWORD(2, 0); WSAStartup(wVersionRequested, &wsaData); if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 0) { fprintf(stderr, "Failed to initialize Winsock 2.0!\n"); exit(-1); } #endif // Initialize XDR (read and write side) xdrrec_create(&m_xdrread, 4096, 4096, (caddr_t) this, readit, writeit); xdrrec_create(&m_xdrwrite, 4096, 4096, (caddr_t) this, readit, writeit); // Initialize Queues m_pInQ = new PQueue<FocCsMsg*> (); m_pOutQ = new PQueue<FocCsMsg*> (); }
static SVCXPRT * makefd_xprt(int fd, u_int sendsize, u_int recvsize) { SVCXPRT *xprt; struct cf_conn *cd; const char *netid; struct __rpc_sockinfo si; assert(fd != -1); xprt = mem_alloc(sizeof(SVCXPRT)); if (xprt == NULL) { warnx("svc_vc: makefd_xprt: out of memory"); goto done; } memset(xprt, 0, sizeof *xprt); cd = mem_alloc(sizeof(struct cf_conn)); if (cd == NULL) { warnx("svc_tcp: makefd_xprt: out of memory"); mem_free(xprt, sizeof(SVCXPRT)); xprt = NULL; goto done; } cd->strm_stat = XPRT_IDLE; xdrrec_create(&(cd->xdrs), sendsize, recvsize, xprt, read_vc, write_vc); xprt->xp_p1 = cd; xprt->xp_verf.oa_base = cd->verf_body; svc_vc_ops(xprt); /* truely deals with calls */ xprt->xp_port = 0; /* this is a connection, not a rendezvouser */ xprt->xp_fd = fd; if (__rpc_fd2sockinfo(fd, &si) && __rpc_sockinfo2netid(&si, &netid)) xprt->xp_netid = strdup(netid); xprt_register(xprt); done: return (xprt); }
static SVCXPRT * makefd_xprt( int fd, unsigned sendsize, unsigned recvsize) { register SVCXPRT *xprt; register struct tcp_conn *cd; xprt = (SVCXPRT *)mem_alloc(sizeof(SVCXPRT)); if (xprt == (SVCXPRT *)NULL) { (void) fprintf(stderr, "svc_tcp: makefd_xprt: out of memory\n"); goto done; } cd = (struct tcp_conn *)mem_alloc(sizeof(struct tcp_conn)); if (cd == (struct tcp_conn *)NULL) { (void) fprintf(stderr, "svc_tcp: makefd_xprt: out of memory\n"); mem_free((char *) xprt, sizeof(SVCXPRT)); xprt = (SVCXPRT *)NULL; goto done; } cd->strm_stat = XPRT_IDLE; xdrrec_create(&(cd->xdrs), sendsize, recvsize, (char*)xprt, (int(*)(void*, char*, int))readtcp, (int(*)(void*, char*, int))writetcp); xprt->xp_p2 = NULL; xprt->xp_p1 = (char*)cd; xprt->xp_verf.oa_base = cd->verf_body; xprt->xp_addrlen = 0; xprt->xp_ops = &svctcp_op; /* truely deals with calls */ xprt->xp_port = 0; /* this is a connection, not a rendezvouser */ xprt->xp_sock = fd; xprt_register(xprt); done: return (xprt); }
/* * 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 client's responsibility to close *sockp, unless * clnttcp_create() was called with *sockp = -1 (so it created * the socket), and CLNT_DESTROY() is used. * 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 = NULL; struct timeval now; struct rpc_msg call_msg; h = (CLIENT *)mem_alloc(sizeof(*h)); if (h == NULL) { rpc_createerr.cf_stat = RPC_SYSTEMERROR; rpc_createerr.cf_error.re_errno = errno; goto fooy; } ct = (struct ct_data *)mem_alloc(sizeof(*ct)); if (ct == NULL) { rpc_createerr.cf_stat = RPC_SYSTEMERROR; rpc_createerr.cf_error.re_errno = errno; 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 (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, NULL); if ((*sockp < 0) || (connect(*sockp, (struct sockaddr *)raddr, sizeof(*raddr)) < 0)) { rpc_createerr.cf_stat = RPC_SYSTEMERROR; rpc_createerr.cf_error.re_errno = errno; if (*sockp != -1) (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 */ (void)gettimeofday(&now, NULL); call_msg.rm_xid = arc4random(); 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, (int(*)(caddr_t, caddr_t, int))readtcp, (int(*)(caddr_t, caddr_t, int))writetcp); h->cl_ops = &tcp_ops; h->cl_private = (caddr_t) ct; h->cl_auth = authnone_create(); if (h->cl_auth == NULL) { rpc_createerr.cf_stat = RPC_SYSTEMERROR; rpc_createerr.cf_error.re_errno = errno; goto fooy; } return (h); fooy: /* * Something goofed, free stuff and barf */ if (ct) mem_free((caddr_t)ct, sizeof(struct ct_data)); if (h) mem_free((caddr_t)h, sizeof(CLIENT)); return (NULL); }
/* * Create a client handle for a connection. * Default options are set, which the user can change using clnt_control()'s. * The rpc/vc package does buffering similar to stdio, so the client * must pick send and receive buffer sizes, 0 => use the default. * NB: fd is copied into a private area. * NB: The rpch->cl_auth is set null authentication. Caller may wish to * set this something more useful. * * fd should be an open socket */ CLIENT * clnt_vc_create( int fd, const struct netbuf *raddr, rpcprog_t prog, rpcvers_t vers, u_int sendsz, u_int recvsz ) { CLIENT *h; struct ct_data *ct = NULL; struct rpc_msg call_msg; #ifdef _REENTRANT sigset_t mask; #endif sigset_t newmask; struct sockaddr_storage ss; socklen_t slen; struct __rpc_sockinfo si; _DIAGASSERT(raddr != NULL); h = mem_alloc(sizeof(*h)); if (h == NULL) { warnx("clnt_vc_create: out of memory"); rpc_createerr.cf_stat = RPC_SYSTEMERROR; rpc_createerr.cf_error.re_errno = errno; goto fooy; } ct = mem_alloc(sizeof(*ct)); if (ct == NULL) { warnx("clnt_vc_create: out of memory"); rpc_createerr.cf_stat = RPC_SYSTEMERROR; rpc_createerr.cf_error.re_errno = errno; goto fooy; } __clnt_sigfillset(&newmask); thr_sigsetmask(SIG_SETMASK, &newmask, &mask); #ifdef _REENTRANT mutex_lock(&clnt_fd_lock); if (vc_fd_locks == NULL) { size_t cv_allocsz, fd_allocsz; int dtbsize = __rpc_dtbsize(); fd_allocsz = dtbsize * sizeof (int); vc_fd_locks = mem_alloc(fd_allocsz); if (vc_fd_locks == NULL) { goto blooy; } else memset(vc_fd_locks, '\0', fd_allocsz); _DIAGASSERT(vc_cv == NULL); cv_allocsz = dtbsize * sizeof (cond_t); vc_cv = mem_alloc(cv_allocsz); if (vc_cv == NULL) { mem_free(vc_fd_locks, fd_allocsz); vc_fd_locks = NULL; goto blooy; } else { int i; for (i = 0; i < dtbsize; i++) cond_init(&vc_cv[i], 0, (void *) 0); } } else _DIAGASSERT(vc_cv != NULL); #endif /* * XXX - fvdl connecting while holding a mutex? */ slen = sizeof ss; if (getpeername(fd, (struct sockaddr *)(void *)&ss, &slen) < 0) { if (errno != ENOTCONN) { rpc_createerr.cf_stat = RPC_SYSTEMERROR; rpc_createerr.cf_error.re_errno = errno; goto blooy; } if (connect(fd, (struct sockaddr *)raddr->buf, raddr->len) < 0){ rpc_createerr.cf_stat = RPC_SYSTEMERROR; rpc_createerr.cf_error.re_errno = errno; goto blooy; } } mutex_unlock(&clnt_fd_lock); thr_sigsetmask(SIG_SETMASK, &(mask), NULL); if (!__rpc_fd2sockinfo(fd, &si)) goto fooy; ct->ct_closeit = FALSE; /* * Set up private data struct */ ct->ct_fd = fd; ct->ct_wait.tv_usec = 0; ct->ct_waitset = FALSE; ct->ct_addr.buf = malloc((size_t)raddr->maxlen); if (ct->ct_addr.buf == NULL) goto fooy; memcpy(ct->ct_addr.buf, raddr->buf, (size_t)raddr->len); ct->ct_addr.len = raddr->len; ct->ct_addr.maxlen = raddr->maxlen; /* * Initialize call message */ call_msg.rm_xid = __RPC_GETXID(); call_msg.rm_direction = CALL; call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION; call_msg.rm_call.cb_prog = (u_int32_t)prog; call_msg.rm_call.cb_vers = (u_int32_t)vers; /* * pre-serialize the static part of the call msg and stash it away */ xdrmem_create(&(ct->ct_xdrs), ct->ct_u.ct_mcallc, MCALL_MSG_SIZE, XDR_ENCODE); if (! xdr_callhdr(&(ct->ct_xdrs), &call_msg)) { if (ct->ct_closeit) { (void)close(fd); } 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. */ h->cl_ops = clnt_vc_ops(); h->cl_private = ct; h->cl_auth = authnone_create(); sendsz = __rpc_get_t_size(si.si_af, si.si_proto, (int)sendsz); recvsz = __rpc_get_t_size(si.si_af, si.si_proto, (int)recvsz); xdrrec_create(&(ct->ct_xdrs), sendsz, recvsz, h->cl_private, read_vc, write_vc); return (h); blooy: mutex_unlock(&clnt_fd_lock); thr_sigsetmask(SIG_SETMASK, &(mask), NULL); fooy: /* * Something goofed, free stuff and barf */ if (ct) mem_free(ct, sizeof(struct ct_data)); if (h) mem_free(h, sizeof(CLIENT)); return (NULL); }
/* * 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 (); (void) __fxprintf (NULL, "%s: %s", __func__, _("out of memory\n")); 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 = (struct clnt_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; }
void P_xdrrec_create(XDR *x, const u_int send_sz, const u_int rec_sz, const caddr_t handle, xdr_rd_func readit, xdr_wr_func writeit) { xdrrec_create(x, send_sz, rec_sz, handle, (int(*)())readit, (int(*)())writeit);}
/* * Duplicate xprt from original to copy. */ SVCXPRT *Svcxprt_copy(SVCXPRT *xprt_copy, SVCXPRT *xprt_orig) { if(xprt_copy) FreeXprt(xprt_copy); xprt_copy = (SVCXPRT *) Mem_Alloc(sizeof(SVCXPRT)); if(xprt_copy == NULL) goto fail_no_xprt; LogFullDebug(COMPONENT_RPC, "Svcxprt_copy copying xprt_orig=%p to xprt_copy=%p", xprt_orig, xprt_copy); memcpy(xprt_copy, xprt_orig, sizeof(SVCXPRT)); xprt_copy->xp_p1 = NULL; xprt_copy->xp_p2 = NULL; if(xprt_orig->xp_ops == &Svcudp_op) { if(Su_data(xprt_orig)) { struct Svcudp_data *su_o = Su_data(xprt_orig), *su_c; su_c = (struct Svcudp_data *) Mem_Alloc(sizeof(*su_c)); if(!su_c) goto fail; Su_data_set(xprt_copy) = (void *) su_c; memcpy(su_c, su_o, sizeof(*su_c)); rpc_buffer(xprt_copy) = Mem_Alloc_Label(su_c->su_iosz, "UDP IO Buffer"); if(!rpc_buffer(xprt_copy)) goto fail; xdrmem_create(&(su_c->su_xdrs), rpc_buffer(xprt_copy), su_c->su_iosz, XDR_DECODE); if(xprt_orig->xp_verf.oa_base == su_o->su_verfbody) xprt_copy->xp_verf.oa_base = su_c->su_verfbody; else xprt_copy->xp_verf.oa_base = xprt_orig->xp_verf.oa_base; xprt_copy->xp_verf.oa_flavor = xprt_orig->xp_verf.oa_flavor; xprt_copy->xp_verf.oa_length = xprt_orig->xp_verf.oa_length; } else goto fail; } else if (xprt_orig->xp_ops == &Svctcp_op) { struct tcp_conn *cd_o = (struct tcp_conn *)xprt_orig->xp_p1, *cd_c; cd_c = (struct tcp_conn *) Mem_Alloc(sizeof(*cd_c)); if(!cd_c) goto fail; memcpy(cd_c, cd_o, sizeof(*cd_c)); xprt_copy->xp_p1 = (void *) cd_c; xdrrec_create(&(cd_c->xdrs), 32768, 32768, (caddr_t) xprt_copy, Readtcp, Writetcp); if(xprt_orig->xp_verf.oa_base == cd_o->verf_body) xprt_copy->xp_verf.oa_base = cd_c->verf_body; else xprt_copy->xp_verf.oa_base = xprt_orig->xp_verf.oa_base; xprt_copy->xp_verf.oa_flavor = xprt_orig->xp_verf.oa_flavor; xprt_copy->xp_verf.oa_length = xprt_orig->xp_verf.oa_length; } else if (xprt_orig->xp_ops == &Svctcp_rendezvous_op) { goto fail; } else { LogDebug(COMPONENT_RPC, "Attempt to copy unknown xprt %p", xprt_orig); Mem_Free(xprt_copy); goto fail_no_xprt; } return xprt_copy; fail: FreeXprt(xprt_copy); fail_no_xprt: /* Let caller know about failure */ LogCrit(COMPONENT_RPC, "Failed to copy xprt"); svcerr_systemerr(xprt_orig); return NULL; }
/* * Create a client handle for a connection. * Default options are set, which the user can change using clnt_control()'s. * The rpc/vc package does buffering similar to stdio, so the client * must pick send and receive buffer sizes, 0 => use the default. * NB: fd is copied into a private area. * NB: The rpch->cl_auth is set null authentication. Caller may wish to * set this something more useful. * * fd should be an open socket * * fd - open file descriptor * raddr - servers address * prog - program number * vers - version number * sendsz - buffer send size * recvsz - buffer recv size */ CLIENT * clnt_vc_create(int fd, const struct netbuf *raddr, const rpcprog_t prog, const rpcvers_t vers, u_int sendsz, u_int recvsz) { CLIENT *cl; /* client handle */ struct ct_data *ct = NULL; /* client handle */ struct timeval now; struct rpc_msg call_msg; static u_int32_t disrupt; sigset_t mask; sigset_t newmask; struct sockaddr_storage ss; socklen_t slen; struct __rpc_sockinfo si; if (disrupt == 0) disrupt = (u_int32_t)(long)raddr; cl = (CLIENT *)mem_alloc(sizeof (*cl)); ct = (struct ct_data *)mem_alloc(sizeof (*ct)); if ((cl == (CLIENT *)NULL) || (ct == (struct ct_data *)NULL)) { (void) syslog(LOG_ERR, clnt_vc_errstr, clnt_vc_str, __no_mem_str); rpc_createerr.cf_stat = RPC_SYSTEMERROR; rpc_createerr.cf_error.re_errno = errno; goto err; } ct->ct_addr.buf = NULL; sigfillset(&newmask); thr_sigsetmask(SIG_SETMASK, &newmask, &mask); mutex_lock(&clnt_fd_lock); if (vc_fd_locks == (int *) NULL) { int cv_allocsz, fd_allocsz; int dtbsize = __rpc_dtbsize(); fd_allocsz = dtbsize * sizeof (int); vc_fd_locks = (int *) mem_alloc(fd_allocsz); if (vc_fd_locks == (int *) NULL) { mutex_unlock(&clnt_fd_lock); thr_sigsetmask(SIG_SETMASK, &(mask), NULL); goto err; } else memset(vc_fd_locks, '\0', fd_allocsz); assert(vc_cv == (cond_t *) NULL); cv_allocsz = dtbsize * sizeof (cond_t); vc_cv = (cond_t *) mem_alloc(cv_allocsz); if (vc_cv == (cond_t *) NULL) { mem_free(vc_fd_locks, fd_allocsz); vc_fd_locks = (int *) NULL; mutex_unlock(&clnt_fd_lock); thr_sigsetmask(SIG_SETMASK, &(mask), NULL); goto err; } else { int i; for (i = 0; i < dtbsize; i++) cond_init(&vc_cv[i], 0, (void *) 0); } } else assert(vc_cv != (cond_t *) NULL); /* * XXX - fvdl connecting while holding a mutex? */ slen = sizeof ss; if (_getpeername(fd, (struct sockaddr *)(void *)&ss, &slen) < 0) { if (errno != ENOTCONN) { rpc_createerr.cf_stat = RPC_SYSTEMERROR; rpc_createerr.cf_error.re_errno = errno; mutex_unlock(&clnt_fd_lock); thr_sigsetmask(SIG_SETMASK, &(mask), NULL); goto err; } if (_connect(fd, (struct sockaddr *)raddr->buf, raddr->len) < 0){ rpc_createerr.cf_stat = RPC_SYSTEMERROR; rpc_createerr.cf_error.re_errno = errno; mutex_unlock(&clnt_fd_lock); thr_sigsetmask(SIG_SETMASK, &(mask), NULL); goto err; } } mutex_unlock(&clnt_fd_lock); thr_sigsetmask(SIG_SETMASK, &(mask), NULL); if (!__rpc_fd2sockinfo(fd, &si)) goto err; ct->ct_closeit = FALSE; /* * Set up private data struct */ ct->ct_fd = fd; ct->ct_wait.tv_usec = 0; ct->ct_waitset = FALSE; ct->ct_addr.buf = malloc(raddr->maxlen); if (ct->ct_addr.buf == NULL) goto err; memcpy(ct->ct_addr.buf, raddr->buf, raddr->len); ct->ct_addr.len = raddr->len; ct->ct_addr.maxlen = raddr->maxlen; /* * Initialize call message */ (void)gettimeofday(&now, NULL); call_msg.rm_xid = ((u_int32_t)++disrupt) ^ __RPC_GETXID(&now); call_msg.rm_direction = CALL; call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION; call_msg.rm_call.cb_prog = (u_int32_t)prog; call_msg.rm_call.cb_vers = (u_int32_t)vers; /* * pre-serialize the static part of the call msg and stash it away */ xdrmem_create(&(ct->ct_xdrs), ct->ct_u.ct_mcallc, MCALL_MSG_SIZE, XDR_ENCODE); if (! xdr_callhdr(&(ct->ct_xdrs), &call_msg)) { if (ct->ct_closeit) { (void)_close(fd); } goto err; } ct->ct_mpos = XDR_GETPOS(&(ct->ct_xdrs)); XDR_DESTROY(&(ct->ct_xdrs)); assert(ct->ct_mpos + sizeof(uint32_t) <= MCALL_MSG_SIZE); /* * Create a client handle which uses xdrrec for serialization * and authnone for authentication. */ cl->cl_ops = clnt_vc_ops(); cl->cl_private = ct; cl->cl_auth = authnone_create(); sendsz = __rpc_get_t_size(si.si_af, si.si_proto, (int)sendsz); recvsz = __rpc_get_t_size(si.si_af, si.si_proto, (int)recvsz); xdrrec_create(&(ct->ct_xdrs), sendsz, recvsz, cl->cl_private, read_vc, write_vc); return (cl); err: if (ct) { if (ct->ct_addr.len) mem_free(ct->ct_addr.buf, ct->ct_addr.len); mem_free(ct, sizeof (struct ct_data)); } if (cl) mem_free(cl, sizeof (CLIENT)); return ((CLIENT *)NULL); }
static SVCXPRT * makefd_xprt_with_lock(int fd, u_int sendsize, u_int recvsize) { SVCXPRT *xprt; mtxprt_t *mtxprt; struct tcp_conn *cd; tprintf(2, "fd=%d, sendsize=%u, recvsize=%u\n", fd, sendsize, recvsize); xprt = alloc_xprt(); cd = (struct tcp_conn *)guard_malloc(sizeof (struct tcp_conn)); cd->strm_stat = XPRT_IDLE; xdrrec_create(&(cd->xdrs), sendsize, recvsize, (caddr_t)xprt, readtcp, writetcp); /* * Constructor for @type{SVCXPRT}, including the additional @type{mtxprt_t} * Order of construction is important. * We want to create a lock for each @type{SVCXPRT}. * The rest of the contructor should all be done while the lock is held. * Even if it is not _really_ necessary, it will keep Valgrind/Helgrind * happy. And they are our friends. * Second step is to initialize the "magic" value, so that other * helper functions that validate it will be happy. */ mtxprt = xprt_to_mtxprt_nocheck(xprt); if (pthread_mutex_init(&(mtxprt->mtxp_lock), NULL) != 0) { abort(); } if (pthread_mutex_init(&(mtxprt->mtxp_progress_lock), NULL) != 0) { abort(); } if (pthread_mutex_init(&(mtxprt->mtxp_mtready), NULL) != 0) { abort(); } // Start off locked. svctcp_getargs() will unlock it. if (pthread_mutex_lock(&(mtxprt->mtxp_mtready)) != 0) { abort(); } /* * Do not use xprt_lock(xprt) here. * The constructor has not progressed far enough, yet. */ if (pthread_mutex_lock(&(mtxprt->mtxp_lock)) != 0) { abort(); } mtxprt->mtxp_progress = 0; mtxprt->mtxp_busy = 0; 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; #if 0 XDR *xdrs; xdrs = &(cd->xdrs); xdrs->x_op = XDR_DECODE; #endif /* * Set "magic", right away. * Other functions validate it. Keep them happy. */ mtxprt->mtxp_magic = MTXPRT_MAGIC; mtxprt->mtxp_creator = pthread_self(); mtxprt->mtxp_id = XPRT_ID_INVALID; mtxprt->mtxp_clone = NULL; mtxprt->mtxp_parent = NO_PARENT; mtxprt->mtxp_refcnt = 0; #ifdef CHECK_CREDENTIALS memset(mtxprt->mtxp_cred, 0, sizeof (mtxprt->mtxp_cred)); #endif memcpy(mtxprt->mtxp_guard, MTXPRT_GUARD, sizeof (mtxprt->mtxp_guard)); xprt_unlock(xprt); xprt_register(xprt); return (xprt); }
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); }
/* * 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, rpcprog_t prog, rpcvers_t vers, SOCKET *sockp, u_int sendsz, u_int recvsz) { CLIENT *h; struct ct_data *ct = 0; struct timeval now; struct rpc_msg call_msg; h = (CLIENT *)mem_alloc(sizeof(*h)); if (h == NULL) { (void)fprintf(stderr, "clnttcp_create: out of memory\n"); rpc_createerr.cf_stat = RPC_SYSTEMERROR; rpc_createerr.cf_error.re_errno = errno; goto fooy; } ct = (struct ct_data *)mem_alloc(sizeof(*ct)); if (ct == NULL) { (void)fprintf(stderr, "clnttcp_create: out of memory\n"); rpc_createerr.cf_stat = RPC_SYSTEMERROR; rpc_createerr.cf_error.re_errno = errno; goto fooy; } /* * If no port number given ask the pmap for one */ if (raddr != NULL && 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_sa(*sockp, NULL); if ((*sockp < 0) || (connect(*sockp, (struct sockaddr *)raddr, sizeof(*raddr)) < 0)) { rpc_createerr.cf_stat = RPC_SYSTEMERROR; rpc_createerr.cf_error.re_errno = errno; (void)closesocket(*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; if (raddr == NULL) { /* Get the remote address from the socket, if it's IPv4. */ struct sockaddr_in sin; socklen_t len = sizeof(sin); int ret = getpeername(ct->ct_sock, (struct sockaddr *)&sin, &len); if (ret == 0 && len == sizeof(sin) && sin.sin_family == AF_INET) ct->ct_addr = sin; else memset(&ct->ct_addr, 0, sizeof(ct->ct_addr)); } else ct->ct_addr = *raddr; /* * Initialize call message */ (void)gettimeofday(&now, (struct timezone *)0); call_msg.rm_xid = getpid() ^ now.tv_sec ^ now.tv_usec; 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 staic part of the call msg and stash it away */ xdrmem_create(&(ct->ct_xdrs), ct->ct_u.ct_mcall, MCALL_MSG_SIZE, XDR_ENCODE); if (! xdr_callhdr(&(ct->ct_xdrs), &call_msg)) { if (ct->ct_closeit) (void)closesocket(*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); }