/* * 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 = 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 != NULL) { if (CLNT_CALL(client, (rpcproc_t)PMAPPROC_DUMP, (xdrproc_t)xdr_void, NULL, (xdrproc_t)xdr_pmaplist, &head, minutetimeout) != RPC_SUCCESS) { clnt_perror(client, "pmap_getmaps rpc problem"); } CLNT_DESTROY(client); } if (socket != -1) (void)_RPC_close(socket); address->sin_port = 0; return (head); }
static void clnttcp_destroy( CLIENT *h) { struct ct_data *ct = (struct ct_data *) h->cl_private; if (ct->ct_closeit) { (void)_RPC_close(ct->ct_sock); } XDR_DESTROY(&(ct->ct_xdrs)); mem_free(ct, sizeof(struct ct_data)); mem_free(h, sizeof(CLIENT)); }
/* * 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( 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 != NULL) { parms.pm_prog = program; parms.pm_vers = version; parms.pm_prot = protocol; parms.pm_port = 0; /* not needed or used */ if (CLNT_CALL(client, (rpcproc_t)PMAPPROC_GETPORT, (xdrproc_t)xdr_pmap, &parms, (xdrproc_t)xdr_u_short, &port, tottimeout) != RPC_SUCCESS){ rpc_createerr.cf_stat = RPC_PMAPFAILURE; clnt_geterr(client, &rpc_createerr.cf_error); } else if (port == 0) { rpc_createerr.cf_stat = RPC_PROGNOTREGISTERED; } CLNT_DESTROY(client); } if (socket != -1) (void)_RPC_close(socket); address->sin_port = 0; return (port); }
/* * 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, /* program number */ u_long vers, /* version number */ int *sockp, u_int sendsz, u_int recvsz) { CLIENT *h; struct ct_data *ct = NULL; /* client handle */ struct timeval now; struct rpc_msg call_msg; static uintptr_t disrupt; if (disrupt == 0) disrupt = (uintptr_t)raddr; 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->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)) { rpc_createerr.cf_stat = RPC_SYSTEMERROR; rpc_createerr.cf_error.re_errno = errno; if (*sockp != -1) (void)_RPC_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, (struct timezone *)0); call_msg.rm_xid = (++disrupt) ^ 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 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)_RPC_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 */ if (ct) mem_free((caddr_t)ct, sizeof(struct ct_data)); if (h) mem_free((caddr_t)h, sizeof(CLIENT)); return ((CLIENT *)NULL); }
/* * 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. */ int get_myaddress( struct sockaddr_in *addr) { int s; struct ifconf ifc; struct ifreq ifreq, *ifr; int loopback = 0, gotit = 0; if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { return(-1); } again: ifc.ifc_len = sizeof ( struct ifreq ) * 8u; ifc.ifc_buf = malloc ( ifc.ifc_len ); if ( ! ifc.ifc_buf ) { _RPC_close(s); return -1; } if (ioctl(s, SIOCGIFCONF, (char *)&ifc) < 0) { _RPC_close(s); free ( ifc.ifc_buf ); return(-1); } ifr = ifc.ifc_req; while ( ifc.ifc_len >= ifreqSize ( ifr ) ) { ifreq = *ifr; if (ioctl(s, SIOCGIFFLAGS, (char *) &ifreq ) < 0) { _RPC_close(s); free ( ifc.ifc_buf ); return(-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) && (ifr->ifr_addr.sa_family == AF_INET) && (ifreq.ifr_flags & IFF_UP))) { *addr = *((struct sockaddr_in *)&ifr->ifr_addr); addr->sin_port = htons(PMAPPORT); gotit = 1; break; } const size_t len = ifreqSize ( ifr ); ifc.ifc_len -= len; /* * RTEMS seems to require copy up to properly aligned * boundary at the beginning of the buffer? */ memmove ( ifr, len + (char *) ifr, ifc.ifc_len ); } if (gotit == 0 && loopback == 0) { free ( ifc.ifc_buf ); loopback = 1; goto again; } (void)_RPC_close(s); free ( ifc.ifc_buf ); return (gotit ? 0 : -1); }
int callrpc( char *host, int prognum, int versnum, int procnum, xdrproc_t inproc, char *in, xdrproc_t outproc, char *out ) { register struct call_rpc_private *crp = callrpc_private; struct sockaddr_in server_addr; enum clnt_stat clnt_stat; struct hostent *hp; struct timeval timeout, tottimeout; if (crp == 0) { crp = (struct call_rpc_private *)calloc(1, sizeof (*crp)); if (crp == 0) return (0); callrpc_private = crp; } if (crp->oldhost == NULL) { crp->oldhost = malloc(MAXHOSTNAMELEN); 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 { crp->valid = 0; if (crp->socket != -1) (void)_RPC_close(crp->socket); crp->socket = RPC_ANYSOCK; if (crp->client) { clnt_destroy(crp->client); crp->client = NULL; } if ((hp = gethostbyname(host)) == NULL) return ((int) RPC_UNKNOWNHOST); timeout.tv_usec = 0; timeout.tv_sec = 5; memset(&server_addr, 0, sizeof(server_addr)); memcpy((char *)&server_addr.sin_addr, hp->h_addr, hp->h_length); server_addr.sin_len = sizeof(struct sockaddr_in); 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) rpc_createerr.cf_stat); crp->valid = 1; crp->oldprognum = prognum; crp->oldversnum = versnum; (void) strcpy(crp->oldhost, host); } tottimeout.tv_sec = 25; tottimeout.tv_usec = 0; clnt_stat = clnt_call(crp->client, procnum, inproc, in, outproc, out, tottimeout); /* * if call failed, empty cache */ if (clnt_stat != RPC_SUCCESS) crp->valid = 0; return ((int) clnt_stat); }