/* libc_hidden_proto(clntudp_create) */ CLIENT * clntudp_create (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); }
/* * 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 sock = -1; CLIENT *client; struct pmap parms; assert(address != NULL); address->sin_port = htons(PMAPPORT); client = clntudp_bufcreate(address, PMAPPROG, PMAPVERS, timeout, &sock, 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); } address->sin_port = 0; return (port); }
CLIENT * clntudp_create(struct sockaddr_in *raddr, rpcprog_t program, rpcvers_t version, struct timeval wait, int *sockp) { return (clntudp_bufcreate(raddr, program, version, wait, sockp, UDPMSGSIZE, UDPMSGSIZE)); }
/* * Set a mapping between program,version and port. * Calls the pmap service remotely to do the mapping. */ bool_t pmap_set( rpcprog_t program, rpcvers_t version, rpcprot_t protocol, u_int port) { struct sockaddr_in myaddress; int socket = -1; register CLIENT *client; struct pmap parms; bool_t rslt; get_myaddress(&myaddress); 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, xdr_pmap, &parms, xdr_bool, &rslt, tottimeout) != RPC_SUCCESS) { clnt_perror(client, "Cannot register service"); return (FALSE); } CLNT_DESTROY(client); (void)close(socket); return (rslt); }
/* * Remove the mapping between program,version and port. * Calls the pmap service remotely to do the un-mapping. */ bool_t pmap_unset( rpcprog_t program, rpcvers_t version) { struct sockaddr_in myaddress; int socket = -1; register CLIENT *client; struct pmap parms; bool_t rslt; get_myaddress(&myaddress); 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, xdr_pmap, &parms, xdr_bool, &rslt, tottimeout); CLNT_DESTROY(client); (void)close(socket); return (rslt); }
int key_gendes (des_block *key) { struct sockaddr_in sin; CLIENT *client; int socket; enum clnt_stat stat; sin.sin_family = AF_INET; sin.sin_port = 0; sin.sin_addr.s_addr = htonl (INADDR_LOOPBACK); __bzero (sin.sin_zero, sizeof (sin.sin_zero)); socket = RPC_ANYSOCK; client = clntudp_bufcreate (&sin, (u_long) KEY_PROG, (u_long) KEY_VERS, trytimeout, &socket, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE); if (client == NULL) return -1; stat = clnt_call (client, KEY_GEN, (xdrproc_t) xdr_void, NULL, (xdrproc_t) xdr_des_block, (caddr_t) key, tottimeout); clnt_destroy (client); __close (socket); if (stat != RPC_SUCCESS) return -1; return 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( struct sockaddr_in *address, rpcprog_t program, rpcvers_t version, rpcprot_t protocol) { unsigned short port = 0; int sock = -1; register CLIENT *client; struct pmap parms; address->sin_port = htons(PMAPPORT); client = clntudp_bufcreate(address, PMAPPROG, PMAPVERS, timeout, &sock, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE); if (client != (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, PMAPPROC_GETPORT, xdr_pmap, &parms, 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); } (void)close(sock); address->sin_port = 0; return (port); }
/* * 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 sock = -1; CLIENT *client; struct pmap parms; bool_t rslt; if (get_myaddress(&myaddress) != 0) return (FALSE); myaddress.sin_addr.s_addr = htonl(INADDR_LOOPBACK); client = clntudp_bufcreate(&myaddress, PMAPPROG, PMAPVERS, timeout, &sock, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE); if (client == NULL) return (FALSE); parms.pm_prog = program; parms.pm_vers = version; parms.pm_port = parms.pm_prot = 0; CLNT_CALL(client, PMAPPROC_UNSET, xdr_pmap, &parms, xdr_bool, &rslt, tottimeout); CLNT_DESTROY(client); if (sock != -1) (void)close(sock); return (rslt); }
/* * 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, u_int protocol, int iport) { struct sockaddr_in myaddress; int sock = -1; CLIENT *client; struct pmap parms; bool_t rslt; u_short port = iport; if (get_myaddress(&myaddress) != 0) return (FALSE); myaddress.sin_addr.s_addr = htonl(INADDR_LOOPBACK); client = clntudp_bufcreate(&myaddress, PMAPPROG, PMAPVERS, timeout, &sock, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE); if (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, xdr_pmap, &parms, xdr_bool, &rslt, tottimeout) != RPC_SUCCESS) { int save_errno = errno; clnt_perror(client, "Cannot register service"); errno = save_errno; return (FALSE); } CLNT_DESTROY(client); if (sock != -1) (void)close(sock); return (rslt); }
CLIENT * clntudp_create( struct sockaddr_in *raddr, unsigned long program, unsigned long version, struct timeval waitval, register int *sockp) { return(clntudp_bufcreate(raddr, program, version, waitval, sockp, UDPMSGSIZE, UDPMSGSIZE)); }
/* * Create a UDP RPC client */ static CLIENT* create_udp_client(struct conn_info *info) { int fd; CLIENT *client; struct sockaddr_in laddr, raddr; struct hostent *hp; if (info->proto->p_proto != IPPROTO_UDP) return NULL; memset(&laddr, 0, sizeof(laddr)); memset(&raddr, 0, sizeof(raddr)); hp = gethostbyname(info->host); if (!hp) return NULL; raddr.sin_family = AF_INET; raddr.sin_port = htons(info->port); memcpy(&raddr.sin_addr.s_addr, hp->h_addr, hp->h_length); /* * bind to any unused port. If we left this up to the rpc * layer, it would bind to a reserved port, which has been shown * to exhaust the reserved port range in some situations. */ fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); if (fd < 0) return NULL; laddr.sin_family = AF_INET; laddr.sin_port = 0; laddr.sin_addr.s_addr = htonl(INADDR_ANY); if (bind(fd, (struct sockaddr *)&laddr, sizeof(struct sockaddr_in)) < 0) { close(fd); fd = RPC_ANYSOCK; /* FALLTHROUGH */ } client = clntudp_bufcreate(&raddr, info->program, info->version, info->timeout, &fd, info->send_sz, info->recv_sz); if (client) clnt_control(client, CLSET_FD_CLOSE, NULL); return client; }
int main(int argn, char *argc[]) { //Program parameters : argc[1] : HostName or Host IP // argc[2] : Server Program Number // other arguments depend on test case //run_mode can switch into stand alone program or program launch by shell script //1 : stand alone, debug mode, more screen information //0 : launch by shell script as test case, only one printf -> result status int run_mode = 0; int test_status = 1; //Default test result set to FAILED int progNum = atoi(argc[2]); CLIENT *clnt = NULL; struct sockaddr_in server_addr; struct hostent *hp = NULL; struct timeval pertry_timeout; int sock = RPC_ANYSOCK; //Test initialization if ((hp = gethostbyname(argc[1])) == NULL) { fprintf(stderr, "can't get addr for %s\n",argc[1]); exit(-1); } pertry_timeout.tv_sec = 1; pertry_timeout.tv_usec = 0; bcopy(hp->h_addr, (caddr_t)&server_addr.sin_addr, hp->h_length); server_addr.sin_family = AF_INET; server_addr.sin_port = 0; //First of all, create a client clnt = clntudp_bufcreate(&server_addr, progNum, VERSNUM, pertry_timeout, &sock, 1024, 1024); if (run_mode == 1) { printf("CLIENT : %d\n", clnt); } //If we are here, macro call was successful test_status = ((CLIENT *)clnt != NULL) ? 0 : 1; //This last printf gives the result status to the tests suite //normally should be 0: test has passed or 1: test has failed printf("%d\n", test_status); return test_status; }
InitRFSnfsClient(HPERIPHERAL PrinterHandle, RFSItemCount MaxTransferSize) { #ifdef CLIENT_USING_TAL #define TIMEOUT_SEC 5 struct timeval timeout; timeout.tv_usec = 0; timeout.tv_sec = TIMEOUT_SEC; return clnttal_bufcreate(PrinterHandle, NFS_PROGRAM, NFS_VERSION, timeout, MaxTransferSize, MaxTransferSize); #else /* not CLIENT_USING_TAL */ /* * This was modelled after callrpc() in the * pre-TLI version of clntsimp.c . * * If we get serious about non-TAL platforms, this * should use the TLI interface and a generic * clnt_create (see TLI version of clntgnc.c). */ #define TIMEOUT_SEC 5 struct sockaddr_in server_addr; struct hostent *hp; struct timeval timeout; socket_t ClientSocket = RPC_ANYSOCK; if ((hp = gethostbyname((char *)PrinterHandle)) == NULL) return NULL; timeout.tv_usec = 0; timeout.tv_sec = TIMEOUT_SEC; memmove((char *)&(server_addr.sin_addr), hp->h_addr, hp->h_length); server_addr.sin_family = AF_INET; server_addr.sin_port = 0; return clntudp_bufcreate(&server_addr, NFS_PROGRAM, NFS_VERSION, timeout, &ClientSocket, MaxTransferSize, MaxTransferSize); #endif /* not CLIENT_USING_TAL */ } /* InitRFSnfsClient */
fsal_status_t fsal_proxy_create_rpc_clnt(proxyfsal_op_context_t * ctx) { int sock; struct sockaddr_in addr_rpc; struct timeval timeout = TIMEOUTRPC; int rc; int priv_port = 0 ; fsal_status_t fsal_status; char addr[INET_ADDRSTRLEN]; memset(&addr_rpc, 0, sizeof(addr_rpc)); addr_rpc.sin_port = ctx->srv_port; addr_rpc.sin_family = AF_INET; addr_rpc.sin_addr.s_addr = ctx->srv_addr; if(!strcmp(ctx->srv_proto, "udp")) { struct timeval tv = { 25, 0}; if((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) ReturnCode(ERR_FSAL_FAULT, errno); ctx->rpc_client = clntudp_bufcreate(&addr_rpc, ctx->srv_prognum, FSAL_PROXY_NFS_V4, tv, &sock, ctx->srv_sendsize, ctx->srv_recvsize); if(ctx->rpc_client == NULL) { LogCrit(COMPONENT_FSAL, "Cannot contact server addr=%s port=%u prognum=%u using NFSv4 protocol", inet_ntop(AF_INET, &ctx->srv_addr, addr, sizeof(addr)), ntohs(ctx->srv_port), ctx->srv_prognum); ReturnCode(ERR_FSAL_INVAL, 0); } } else if(!strcmp(ctx->srv_proto, "tcp")) { if( ctx->use_privileged_client_port == TRUE ) { if( (sock = rresvport( &priv_port ) )< 0 ) { LogCrit(COMPONENT_FSAL, "Cannot create a tcp socket on a privileged port"); ReturnCode(ERR_FSAL_FAULT, 0); } } else { if((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { LogCrit(COMPONENT_FSAL, "Cannot create a tcp socket - %d", errno); ReturnCode(ERR_FSAL_FAULT, 0); } } if(connect(sock, (struct sockaddr *)&addr_rpc, sizeof(addr_rpc)) < 0) { LogCrit(COMPONENT_FSAL, "Cannot connect to server addr=%s port=%u", inet_ntop(AF_INET, &ctx->srv_addr, addr, sizeof(addr)), ntohs(ctx->srv_port)); ReturnCode(ERR_FSAL_FAULT, 0); } ctx->rpc_client = clnttcp_create(&addr_rpc, ctx->srv_prognum, FSAL_PROXY_NFS_V4, &sock, ctx->srv_sendsize, ctx->srv_recvsize); if(ctx->rpc_client == NULL) { LogCrit(COMPONENT_FSAL, "Cannot contact server addr=%s port=%u prognum=%u using NFSv4 protocol", inet_ntop(AF_INET, &ctx->srv_addr, addr, sizeof(addr)), ntohs(ctx->srv_port), ctx->srv_prognum); ReturnCode(ERR_FSAL_INVAL, 0); } } else { ReturnCode(ERR_FSAL_INVAL, 0); } ctx->socket = sock; #ifdef _USE_GSSRPC if(global_fsal_proxy_specific_info.active_krb5 == TRUE) { fsal_status = fsal_internal_set_auth_gss(ctx); if(FSAL_IS_ERROR(fsal_status)) ReturnCode(fsal_status.major, fsal_status.minor); } else #endif /* _USE_GSSRPC */ if((ctx->rpc_auth = authunix_create_default()) == NULL) ReturnCode(ERR_FSAL_INVAL, 0); /* test if the newly created context can 'ping' the server via PROC_NULL */ rc = clnt_call(ctx->rpc_client, ctx->rpc_auth, NFSPROC4_NULL, (xdrproc_t) xdr_void, (caddr_t) NULL, (xdrproc_t) xdr_void, (caddr_t) NULL, timeout); if(rc != RPC_SUCCESS) ReturnCode(ERR_FSAL_INVAL, rc); fsal_status = FSAL_proxy_setclientid(ctx); if(FSAL_IS_ERROR(fsal_status)) ReturnCode(ERR_FSAL_FAULT, 0); ReturnCode(ERR_FSAL_NO_ERROR, 0); }
void setup_resolv(bool *fwding, int *child, CLIENT **client, char *tp_type, long prognum) { enum clnt_stat stat; struct timeval tv; char prog_str[15], fd_str[5]; SVCXPRT *xprt = NULL; char *tp; #ifdef TDRPC struct sockaddr_in addr; int sock; #else char name[257]; struct netconfig *nc; void *h; #endif verbose = silent == FALSE ? 1 : 0; if (! *fwding) return; #ifdef TDRPC tp = (tp_type && strcmp(tp_type, "udp") != 0) ? "udp" : "tcp"; #else /* try the specified netid (default ticots), then any loopback */ tp = (tp_type && *tp_type) ? tp_type : "ticots"; if (!getconf(tp, &h, &nc)) { /* dont forget endnetconfig() */ syslog(LOG_ERR, "can't get resolv_clnt netconf %s.\n", tp); *fwding = FALSE; return; } tp = nc->nc_netid; #endif /* * Startup the resolv server: use transient prognum if prognum * isn't set. Using transient means we create mapping then * pass child the fd to use for service. */ if (!getprognum(&prognum, &xprt, fd_str, prog_str, YPDNSVERS, tp)) { syslog(LOG_ERR, "can't create resolv xprt for transient.\n"); *fwding = FALSE; #ifndef TDRPC endnetconfig(h); #endif return; } switch (*child = vfork()) { case -1: /* error */ syslog(LOG_ERR, "can't startup resolv daemon\n"); #ifndef TDRPC endnetconfig(h); #endif *fwding = FALSE; return; case 0: /* child */ /* * if using transient we must maintain fd across * exec cause unset/set on prognum isn't automic. * * if using transient we'll just do svc_tli_create * in child on our bound fd. */ execlp(RESOLV_EXEC_PATH, "rpc.nisd_resolv", "-F", /* forground */ "-C", fd_str, /* dont close */ "-p", prog_str, /* prognum */ "-t", tp, /* tp type */ NULL); syslog(LOG_ERR, RESOLV_EXEC_ERR, strerror(errno)); exit(1); default: /* parent */ /* close fd, free xprt, but leave mapping */ if (xprt) svc_destroy(xprt); /* let it crank up before we create client */ sleep(4); } #ifdef TDRPC get_myaddress(&addr); addr.sin_port = 0; sock = RPC_ANYSOCK; tv.tv_sec = 3; tv.tv_usec = 0; if (strcmp(tp, "udp") != 0) { *client = clntudp_bufcreate(&addr, prognum, YPDNSVERS, tv, &sock, YPMSGSZ, YPMSGSZ); } else { *client = clnttcp_create(&addr, prognum, YPDNSVERS, &sock, YPMSGSZ, YPMSGSZ); } if (*client == NULL) { syslog(LOG_ERR, "can't create resolv client handle.\n"); (void) kill (*child, SIGINT); *fwding = FALSE; return; } #else if (sysinfo(SI_HOSTNAME, name, sizeof (name)-1) == -1) { syslog(LOG_ERR, "can't get local hostname.\n"); (void) kill (*child, SIGINT); endnetconfig(h); *fwding = FALSE; return; } if ((*client = clnt_tp_create(HOST_SELF_CONNECT, prognum, YPDNSVERS, nc)) == NULL) { syslog(LOG_ERR, "can't create resolv_clnt\n"); (void) kill (*child, SIGINT); endnetconfig(h); *fwding = FALSE; return; } endnetconfig(h); #endif /* ping for comfort */ tv.tv_sec = 10; tv.tv_usec = 0; if ((stat = clnt_call(*client, 0, xdr_void, 0, xdr_void, 0, tv)) != RPC_SUCCESS) { syslog(LOG_ERR, "can't talk with resolv server\n"); clnt_destroy (*client); (void) kill (*child, SIGINT); *fwding = FALSE; return; } if (verbose) syslog(LOG_INFO, "finished setup for dns fwding.\n"); }
static int nfs_probe_statd(void) { struct sockaddr_in addr = { .sin_family = AF_INET, .sin_addr.s_addr = htonl(INADDR_LOOPBACK), }; rpcprog_t program = nfs_getrpcbyname(NSMPROG, nfs_ns_pgmtbl); return nfs_getport_ping((struct sockaddr *)&addr, sizeof(addr), program, (rpcvers_t)1, IPPROTO_UDP); } /** * start_statd - attempt to start rpc.statd * * Returns 1 if statd is running; otherwise zero. */ int start_statd(void) { #ifdef START_STATD struct stat stb; #endif if (nfs_probe_statd()) return 1; #ifdef START_STATD if (stat(START_STATD, &stb) == 0) { if (S_ISREG(stb.st_mode) && (stb.st_mode & S_IXUSR)) { pid_t pid = fork(); switch (pid) { case 0: /* child */ execl(START_STATD, START_STATD, NULL); exit(1); case -1: /* error */ nfs_error(_("fork failed: %s"), strerror(errno)); break; default: /* parent */ waitpid(pid, NULL,0); break; } if (nfs_probe_statd()) return 1; } } #endif return 0; } /** * nfs_advise_umount - ask the server to remove a share from it's rmtab * @sap: pointer to IP address of server to call * @salen: length of server address * @pmap: partially filled-in mountd RPC service tuple * @argp: directory path of share to "unmount" * * Returns one if the unmount call succeeded; zero if the unmount * failed for any reason; rpccreateerr.cf_stat is set to reflect * the nature of the error. * * We use a fast timeout since this call is advisory only. */ int nfs_advise_umount(const struct sockaddr *sap, const socklen_t salen, const struct pmap *pmap, const dirpath *argp) { struct sockaddr_storage address; struct sockaddr *saddr = (struct sockaddr *)&address; struct pmap mnt_pmap = *pmap; struct timeval timeout = { .tv_sec = MOUNT_TIMEOUT >> 3, }; CLIENT *client; enum clnt_stat res = 0; if (nfs_probe_mntport(sap, salen, &mnt_pmap) == 0) return 0; memcpy(saddr, sap, salen); nfs_set_port(saddr, mnt_pmap.pm_port); client = nfs_get_rpcclient(saddr, salen, mnt_pmap.pm_prot, mnt_pmap.pm_prog, mnt_pmap.pm_vers, &timeout); if (client == NULL) return 0; client->cl_auth = authunix_create_default(); res = CLNT_CALL(client, MOUNTPROC_UMNT, (xdrproc_t)xdr_dirpath, (caddr_t)argp, (xdrproc_t)xdr_void, NULL, timeout); auth_destroy(client->cl_auth); CLNT_DESTROY(client); if (res != RPC_SUCCESS) return 0; return 1; } /** * nfs_call_umount - ask the server to remove a share from it's rmtab * @mnt_server: address of RPC MNT program server * @argp: directory path of share to "unmount" * * Returns one if the unmount call succeeded; zero if the unmount * failed for any reason. * * Note that a side effect of calling this function is that rpccreateerr * is set. */ int nfs_call_umount(clnt_addr_t *mnt_server, dirpath *argp) { struct sockaddr *sap = (struct sockaddr *)&mnt_server->saddr; socklen_t salen = sizeof(mnt_server->saddr); struct pmap *pmap = &mnt_server->pmap; CLIENT *clnt; enum clnt_stat res = 0; int msock; if (!nfs_probe_mntport(sap, salen, pmap)) return 0; clnt = mnt_openclnt(mnt_server, &msock); if (!clnt) return 0; res = clnt_call(clnt, MOUNTPROC_UMNT, (xdrproc_t)xdr_dirpath, (caddr_t)argp, (xdrproc_t)xdr_void, NULL, TIMEOUT); mnt_closeclnt(clnt, msock); if (res == RPC_SUCCESS) return 1; return 0; } /** * mnt_openclnt - get a handle for a remote mountd service * @mnt_server: address and pmap arguments of mountd service * @msock: returns a file descriptor of the underlying transport socket * * Returns an active handle for the remote's mountd service */ CLIENT *mnt_openclnt(clnt_addr_t *mnt_server, int *msock) { struct sockaddr_in *mnt_saddr = &mnt_server->saddr; struct pmap *mnt_pmap = &mnt_server->pmap; CLIENT *clnt = NULL; mnt_saddr->sin_port = htons((u_short)mnt_pmap->pm_port); *msock = get_socket(mnt_saddr, mnt_pmap->pm_prot, MOUNT_TIMEOUT, TRUE, FALSE); if (*msock == RPC_ANYSOCK) { if (rpc_createerr.cf_error.re_errno == EADDRINUSE) /* * Probably in-use by a TIME_WAIT connection, * It is worth waiting a while and trying again. */ rpc_createerr.cf_stat = RPC_TIMEDOUT; return NULL; } switch (mnt_pmap->pm_prot) { case IPPROTO_UDP: clnt = clntudp_bufcreate(mnt_saddr, mnt_pmap->pm_prog, mnt_pmap->pm_vers, RETRY_TIMEOUT, msock, MNT_SENDBUFSIZE, MNT_RECVBUFSIZE); break; case IPPROTO_TCP: clnt = clnttcp_create(mnt_saddr, mnt_pmap->pm_prog, mnt_pmap->pm_vers, msock, MNT_SENDBUFSIZE, MNT_RECVBUFSIZE); break; } if (clnt) { /* try to mount hostname:dirname */ clnt->cl_auth = authunix_create_default(); return clnt; } return NULL; } /** * mnt_closeclnt - terminate a handle for a remote mountd service * @clnt: pointer to an active handle for a remote mountd service * @msock: file descriptor of the underlying transport socket * */ void mnt_closeclnt(CLIENT *clnt, int msock) { auth_destroy(clnt->cl_auth); clnt_destroy(clnt); close(msock); } /** * clnt_ping - send an RPC ping to the remote RPC service endpoint * @saddr: server's address * @prog: target RPC program number * @vers: target RPC version number * @prot: target RPC protocol * @caddr: filled in with our network address * * Sigh... GETPORT queries don't actually check the version number. * In order to make sure that the server actually supports the service * we're requesting, we open an RPC client, and fire off a NULL * RPC call. * * caddr is the network address that the server will use to call us back. * On multi-homed clients, this address depends on which NIC we use to * route requests to the server. * * Returns one if successful, otherwise zero. */ int clnt_ping(struct sockaddr_in *saddr, const unsigned long prog, const unsigned long vers, const unsigned int prot, struct sockaddr_in *caddr) { CLIENT *clnt = NULL; int sock, stat; static char clnt_res; struct sockaddr dissolve; rpc_createerr.cf_stat = stat = 0; sock = get_socket(saddr, prot, CONNECT_TIMEOUT, FALSE, TRUE); if (sock == RPC_ANYSOCK) { if (rpc_createerr.cf_error.re_errno == ETIMEDOUT) { /* * TCP timeout. Bubble up the error to see * how it should be handled. */ rpc_createerr.cf_stat = RPC_TIMEDOUT; } return 0; } if (caddr) { /* Get the address of our end of this connection */ socklen_t len = sizeof(*caddr); if (getsockname(sock, caddr, &len) != 0) caddr->sin_family = 0; } switch(prot) { case IPPROTO_UDP: /* The socket is connected (so we could getsockname successfully), * but some servers on multi-homed hosts reply from * the wrong address, so if we stay connected, we lose the reply. */ dissolve.sa_family = AF_UNSPEC; connect(sock, &dissolve, sizeof(dissolve)); clnt = clntudp_bufcreate(saddr, prog, vers, RETRY_TIMEOUT, &sock, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE); break; case IPPROTO_TCP: clnt = clnttcp_create(saddr, prog, vers, &sock, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE); break; } if (!clnt) { close(sock); return 0; } memset(&clnt_res, 0, sizeof(clnt_res)); stat = clnt_call(clnt, NULLPROC, (xdrproc_t)xdr_void, (caddr_t)NULL, (xdrproc_t)xdr_void, (caddr_t)&clnt_res, TIMEOUT); if (stat) { clnt_geterr(clnt, &rpc_createerr.cf_error); rpc_createerr.cf_stat = stat; } clnt_destroy(clnt); close(sock); if (stat == RPC_SUCCESS) return 1; else return 0; }