/* * Create NSM client for the local host */ static struct rpc_clnt * nsm_create(void) { struct rpc_xprt *xprt; struct rpc_clnt *clnt; struct sockaddr_in sin; sin.sin_family = AF_INET; sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); sin.sin_port = 0; xprt = xprt_create_proto(IPPROTO_UDP, &sin, NULL); if (IS_ERR(xprt)) return (struct rpc_clnt *)xprt; clnt = rpc_create_client(xprt, "localhost", &nsm_program, SM_VERSION, RPC_AUTH_NULL); if (IS_ERR(clnt)) goto out_destroy; clnt->cl_softrtry = 1; clnt->cl_chatty = 1; clnt->cl_oneshot = 1; xprt->resvport = 1; /* NSM requires a reserved port */ return clnt; out_destroy: xprt_destroy(xprt); return clnt; }
/* * Create NSM client for the local host */ static struct rpc_clnt * nsm_create(void) { struct rpc_xprt *xprt; struct rpc_clnt *clnt = NULL; struct sockaddr_in sin; sin.sin_family = AF_INET; sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); sin.sin_port = 0; xprt = xprt_create_proto(IPPROTO_UDP, &sin, NULL); if (!xprt) goto out; clnt = rpc_create_client(xprt, "localhost", &nsm_program, SM_VERSION, RPC_AUTH_NULL); if (!clnt) goto out_destroy; clnt->cl_softrtry = 1; clnt->cl_chatty = 1; clnt->cl_oneshot = 1; out: return clnt; out_destroy: xprt_destroy(xprt); goto out; }
/* * Create the NLM RPC client for an NLM peer */ struct rpc_clnt * nlm_bind_host(struct nlm_host *host) { struct rpc_clnt *clnt; struct rpc_xprt *xprt; dprintk("lockd: nlm_bind_host(%08x)\n", (unsigned)ntohl(host->h_addr.sin_addr.s_addr)); /* Lock host handle */ down(&host->h_sema); /* If we've already created an RPC client, check whether * RPC rebind is required * Note: why keep rebinding if we're on a tcp connection? */ if ((clnt = host->h_rpcclnt) != NULL) { xprt = clnt->cl_xprt; if (!xprt->stream && time_after_eq(jiffies, host->h_nextrebind)) { clnt->cl_port = 0; host->h_nextrebind = jiffies + NLM_HOST_REBIND; dprintk("lockd: next rebind in %ld jiffies\n", host->h_nextrebind - jiffies); } } else { xprt = xprt_create_proto(host->h_proto, &host->h_addr, NULL); if (IS_ERR(xprt)) { dprintk("lockd: xprt_create_proto failed: %ld\n", PTR_ERR(xprt)); goto forgetit; } xprt_set_timeout(&xprt->timeout, 5, nlmsvc_timeout); /* Existing NLM servers accept AUTH_UNIX only */ clnt = rpc_create_client(xprt, host->h_name, &nlm_program, host->h_version, RPC_AUTH_UNIX); if (IS_ERR(clnt)) { xprt_destroy(xprt); dprintk("lockd: rpc_create_client failed: %ld\n", PTR_ERR(clnt)); goto forgetit; } clnt->cl_autobind = 1; /* turn on pmap queries */ xprt->nocong = 1; /* No congestion control for NLM */ xprt->resvport = 1; /* NLM requires a reserved port */ host->h_rpcclnt = clnt; } up(&host->h_sema); return clnt; forgetit: printk("lockd: couldn't create RPC handle for %s\n", host->h_name); up(&host->h_sema); return NULL; }
drcl_status rcl_connect(struct child_node* node) { int retval; assert(node); assert(node->address); retval = rpc_create_client(node->address->universal_address, "3333", RCL_PROGRAM, RCL_V1, &node->rcl_node); if (retval) return DRCL_CONNECTION_ERROR; retval = rpc_call(node->rcl_node, RCLPROC_NULL, NULL, NULL, NULL, NULL); if (retval) { rcl_disconnect(node); return DRCL_CONNECTION_ERROR; } return DRCL_OK; }
static struct rpc_clnt * mnt_create(char *hostname, struct sockaddr_in *srvaddr) { struct rpc_xprt *xprt; struct rpc_clnt *clnt; if (!(xprt = xprt_create_proto(IPPROTO_UDP, srvaddr, NULL))) return NULL; clnt = rpc_create_client(xprt, hostname, &mnt_program, NFS_MNT_VERSION, RPC_AUTH_NULL); if (!clnt) { xprt_destroy(xprt); } else { clnt->cl_softrtry = 1; clnt->cl_chatty = 1; clnt->cl_oneshot = 1; clnt->cl_intr = 1; } return clnt; }
/* * Set up the callback client and put a NFSPROC4_CB_NULL on the wire... */ void nfsd4_probe_callback(struct nfs4_client *clp) { struct sockaddr_in addr; struct nfs4_callback *cb = &clp->cl_callback; struct rpc_timeout timeparms; struct rpc_xprt * xprt; struct rpc_program * program = &cb->cb_program; struct rpc_stat * stat = &cb->cb_stat; struct rpc_clnt * clnt; struct rpc_message msg = { .rpc_proc = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_NULL], .rpc_argp = clp, }; char hostname[32]; int status; dprintk("NFSD: probe_callback. cb_parsed %d cb_set %d\n", cb->cb_parsed, atomic_read(&cb->cb_set)); if (!cb->cb_parsed || atomic_read(&cb->cb_set)) return; /* Initialize address */ memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = htons(cb->cb_port); addr.sin_addr.s_addr = htonl(cb->cb_addr); /* Initialize timeout */ timeparms.to_initval = (NFSD_LEASE_TIME/4) * HZ; timeparms.to_retries = 0; timeparms.to_maxval = (NFSD_LEASE_TIME/2) * HZ; timeparms.to_exponential = 1; /* Create RPC transport */ xprt = xprt_create_proto(IPPROTO_TCP, &addr, &timeparms); if (IS_ERR(xprt)) { dprintk("NFSD: couldn't create callback transport!\n"); goto out_err; } /* Initialize rpc_program */ program->name = "nfs4_cb"; program->number = cb->cb_prog; program->nrvers = sizeof(nfs_cb_version)/sizeof(nfs_cb_version[0]); program->version = nfs_cb_version; program->stats = stat; /* Initialize rpc_stat */ memset(stat, 0, sizeof(struct rpc_stat)); stat->program = program; /* Create RPC client * * XXX AUTH_UNIX only - need AUTH_GSS.... */ sprintf(hostname, "%u.%u.%u.%u", NIPQUAD(addr.sin_addr.s_addr)); clnt = rpc_create_client(xprt, hostname, program, 1, RPC_AUTH_UNIX); if (IS_ERR(clnt)) { dprintk("NFSD: couldn't create callback client\n"); goto out_xprt; } clnt->cl_intr = 0; clnt->cl_softrtry = 1; clnt->cl_chatty = 1; /* Kick rpciod, put the call on the wire. */ if (rpciod_up() != 0) { dprintk("nfsd: couldn't start rpciod for callbacks!\n"); goto out_clnt; } /* the task holds a reference to the nfs4_client struct */ cb->cb_client = clnt; atomic_inc(&clp->cl_count); msg.rpc_cred = nfsd4_lookupcred(clp,0); if (IS_ERR(msg.rpc_cred)) goto out_rpciod; status = rpc_call_async(clnt, &msg, RPC_TASK_ASYNC, nfs4_cb_null, NULL); put_rpccred(msg.rpc_cred); if (status != 0) { dprintk("NFSD: asynchronous NFSPROC4_CB_NULL failed!\n"); goto out_rpciod; } return; out_rpciod: atomic_dec(&clp->cl_count); rpciod_down(); out_clnt: rpc_shutdown_client(clnt); goto out_err; out_xprt: xprt_destroy(xprt); out_err: dprintk("NFSD: warning: no callback path to client %.*s\n", (int)clp->cl_name.len, clp->cl_name.data); cb->cb_client = NULL; }
/* * The way this works is that the mount process passes a structure * in the data argument which contains the server's IP address * and the root file handle obtained from the server's mount * daemon. We stash these away in the private superblock fields. */ struct super_block * nfs_read_super(struct super_block *sb, void *raw_data, int silent) { struct nfs_mount_data *data = (struct nfs_mount_data *) raw_data; struct nfs_server *server; struct rpc_xprt *xprt; struct rpc_clnt *clnt; struct nfs_fh *root_fh; struct inode *root_inode; unsigned int authflavor; int tcp; struct sockaddr_in srvaddr; struct rpc_timeout timeparms; struct nfs_fattr fattr; MOD_INC_USE_COUNT; if (!data) goto out_miss_args; /* No NFS V3. */ if (data->flags & NFS_MOUNT_VER3) goto out_fail; /* Don't complain if "mount" is newer. */ if (data->version < NFS_MOUNT_VERSION) { printk("nfs warning: mount version %s than kernel\n", data->version < NFS_MOUNT_VERSION ? "older" : "newer"); if (data->version < 2) data->namlen = 0; if (data->version < 3) data->bsize = 0; } /* We now require that the mount process passes the remote address */ memcpy(&srvaddr, &data->addr, sizeof(srvaddr)); if (srvaddr.sin_addr.s_addr == INADDR_ANY) goto out_no_remote; lock_super(sb); sb->s_flags |= MS_ODD_RENAME; /* This should go away */ sb->s_magic = NFS_SUPER_MAGIC; sb->s_op = &nfs_sops; sb->s_blocksize = nfs_block_size(data->bsize, &sb->s_blocksize_bits); sb->u.nfs_sb.s_root = data->root; server = &sb->u.nfs_sb.s_server; server->rsize = nfs_block_size(data->rsize, NULL); server->wsize = nfs_block_size(data->wsize, NULL); server->flags = data->flags; if (data->flags & NFS_MOUNT_NOAC) { data->acregmin = data->acregmax = 0; data->acdirmin = data->acdirmax = 0; } server->acregmin = data->acregmin*HZ; server->acregmax = data->acregmax*HZ; server->acdirmin = data->acdirmin*HZ; server->acdirmax = data->acdirmax*HZ; server->hostname = kmalloc(strlen(data->hostname) + 1, GFP_KERNEL); if (!server->hostname) goto out_unlock; strcpy(server->hostname, data->hostname); /* Which protocol do we use? */ tcp = (data->flags & NFS_MOUNT_TCP); /* Initialize timeout values */ timeparms.to_initval = data->timeo * HZ / 10; timeparms.to_retries = data->retrans; timeparms.to_maxval = tcp? RPC_MAX_TCP_TIMEOUT : RPC_MAX_UDP_TIMEOUT; timeparms.to_exponential = 1; /* Now create transport and client */ xprt = xprt_create_proto(tcp? IPPROTO_TCP : IPPROTO_UDP, &srvaddr, &timeparms); if (xprt == NULL) goto out_no_xprt; /* Choose authentication flavor */ authflavor = RPC_AUTH_UNIX; if (data->flags & NFS_MOUNT_SECURE) authflavor = RPC_AUTH_DES; else if (data->flags & NFS_MOUNT_KERBEROS) authflavor = RPC_AUTH_KRB; clnt = rpc_create_client(xprt, server->hostname, &nfs_program, NFS_VERSION, authflavor); if (clnt == NULL) goto out_no_client; clnt->cl_intr = (data->flags & NFS_MOUNT_INTR)? 1 : 0; clnt->cl_softrtry = (data->flags & NFS_MOUNT_SOFT)? 1 : 0; clnt->cl_chatty = 1; server->client = clnt; /* Fire up rpciod if not yet running */ if (rpciod_up() != 0) goto out_no_iod; /* * Keep the super block locked while we try to get * the root fh attributes. */ root_fh = kmalloc(sizeof(struct nfs_fh), GFP_KERNEL); if (!root_fh) goto out_no_fh; *root_fh = data->root; if (nfs_proc_getattr(server, root_fh, &fattr) != 0) goto out_no_fattr; clnt->cl_to_err = 1; root_inode = __nfs_fhget(sb, &fattr); if (!root_inode) goto out_no_root; sb->s_root = d_alloc_root(root_inode, NULL); if (!sb->s_root) goto out_no_root; sb->s_root->d_op = &nfs_dentry_operations; sb->s_root->d_fsdata = root_fh; /* We're airborne */ unlock_super(sb); /* Check whether to start the lockd process */ if (!(server->flags & NFS_MOUNT_NONLM)) lockd_up(); return sb; /* Yargs. It didn't work out. */ out_no_root: printk("nfs_read_super: get root inode failed\n"); iput(root_inode); goto out_free_fh; out_no_fattr: printk("nfs_read_super: get root fattr failed\n"); out_free_fh: kfree(root_fh); out_no_fh: rpciod_down(); goto out_shutdown; out_no_iod: printk(KERN_WARNING "NFS: couldn't start rpciod!\n"); out_shutdown: rpc_shutdown_client(server->client); goto out_free_host; out_no_client: printk(KERN_WARNING "NFS: cannot create RPC client.\n"); xprt_destroy(xprt); goto out_free_host; out_no_xprt: printk(KERN_WARNING "NFS: cannot create RPC transport.\n"); out_free_host: kfree(server->hostname); out_unlock: unlock_super(sb); goto out_fail; out_no_remote: printk("NFS: mount program didn't pass remote address!\n"); goto out_fail; out_miss_args: printk("nfs_read_super: missing data argument\n"); out_fail: sb->s_dev = 0; MOD_DEC_USE_COUNT; return NULL; }
/* * Obtain the port for a given RPC service on a given host. This one can * be called for an ongoing RPC request. */ void rpc_getport(struct rpc_task *task, struct rpc_clnt *clnt) { struct rpc_portmap *map = clnt->cl_pmap; struct sockaddr_in *sap = &clnt->cl_xprt->addr; struct rpc_message msg = { .rpc_proc = &pmap_procedures[PMAP_GETPORT], .rpc_argp = map, .rpc_resp = &clnt->cl_port, .rpc_cred = NULL }; struct rpc_clnt *pmap_clnt; struct rpc_task *child; dprintk("RPC: %4d rpc_getport(%s, %d, %d, %d)\n", task->tk_pid, clnt->cl_server, map->pm_prog, map->pm_vers, map->pm_prot); spin_lock(&pmap_lock); if (map->pm_binding) { rpc_sleep_on(&map->pm_bindwait, task, NULL, 0); spin_unlock(&pmap_lock); return; } map->pm_binding = 1; spin_unlock(&pmap_lock); pmap_clnt = pmap_create(clnt->cl_server, sap, map->pm_prot); if (IS_ERR(pmap_clnt)) { task->tk_status = PTR_ERR(pmap_clnt); goto bailout; } task->tk_status = 0; /* * Note: rpc_new_child will release client after a failure. */ if (!(child = rpc_new_child(pmap_clnt, task))) goto bailout; /* Setup the call info struct */ rpc_call_setup(child, &msg, 0); /* ... and run the child task */ rpc_run_child(task, child, pmap_getport_done); return; bailout: spin_lock(&pmap_lock); map->pm_binding = 0; rpc_wake_up(&map->pm_bindwait); spin_unlock(&pmap_lock); task->tk_status = -EIO; task->tk_action = NULL; } #ifdef CONFIG_ROOT_NFS int rpc_getport_external(struct sockaddr_in *sin, __u32 prog, __u32 vers, int prot) { struct rpc_portmap map = { .pm_prog = prog, .pm_vers = vers, .pm_prot = prot, .pm_port = 0 }; struct rpc_clnt *pmap_clnt; char hostname[32]; int status; dprintk("RPC: rpc_getport_external(%u.%u.%u.%u, %d, %d, %d)\n", NIPQUAD(sin->sin_addr.s_addr), prog, vers, prot); sprintf(hostname, "%u.%u.%u.%u", NIPQUAD(sin->sin_addr.s_addr)); pmap_clnt = pmap_create(hostname, sin, prot); if (IS_ERR(pmap_clnt)) return PTR_ERR(pmap_clnt); /* Setup the call info struct */ status = rpc_call(pmap_clnt, PMAP_GETPORT, &map, &map.pm_port, 0); if (status >= 0) { if (map.pm_port != 0) return map.pm_port; status = -EACCES; } return status; } #endif static void pmap_getport_done(struct rpc_task *task) { struct rpc_clnt *clnt = task->tk_client; struct rpc_portmap *map = clnt->cl_pmap; dprintk("RPC: %4d pmap_getport_done(status %d, port %d)\n", task->tk_pid, task->tk_status, clnt->cl_port); if (task->tk_status < 0) { /* Make the calling task exit with an error */ task->tk_action = NULL; } else if (clnt->cl_port == 0) { /* Program not registered */ task->tk_status = -EACCES; task->tk_action = NULL; } else { /* byte-swap port number first */ clnt->cl_port = htons(clnt->cl_port); clnt->cl_xprt->addr.sin_port = clnt->cl_port; } spin_lock(&pmap_lock); map->pm_binding = 0; rpc_wake_up(&map->pm_bindwait); spin_unlock(&pmap_lock); } /* * Set or unset a port registration with the local portmapper. * port == 0 means unregister, port != 0 means register. */ int rpc_register(u32 prog, u32 vers, int prot, unsigned short port, int *okay) { struct sockaddr_in sin; struct rpc_portmap map; struct rpc_clnt *pmap_clnt; int error = 0; dprintk("RPC: registering (%d, %d, %d, %d) with portmapper.\n", prog, vers, prot, port); sin.sin_family = AF_INET; sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); pmap_clnt = pmap_create("localhost", &sin, IPPROTO_UDP); if (IS_ERR(pmap_clnt)) { error = PTR_ERR(pmap_clnt); dprintk("RPC: couldn't create pmap client. Error = %d\n", error); return error; } map.pm_prog = prog; map.pm_vers = vers; map.pm_prot = prot; map.pm_port = port; error = rpc_call(pmap_clnt, port? PMAP_SET : PMAP_UNSET, &map, okay, 0); if (error < 0) { printk(KERN_WARNING "RPC: failed to contact portmap (errno %d).\n", error); } dprintk("RPC: registration status %d/%d\n", error, *okay); /* Client deleted automatically because cl_oneshot == 1 */ return error; } static struct rpc_clnt * pmap_create(char *hostname, struct sockaddr_in *srvaddr, int proto) { struct rpc_xprt *xprt; struct rpc_clnt *clnt; /* printk("pmap: create xprt\n"); */ xprt = xprt_create_proto(proto, srvaddr, NULL); if (IS_ERR(xprt)) return (struct rpc_clnt *)xprt; xprt->addr.sin_port = htons(RPC_PMAP_PORT); /* printk("pmap: create clnt\n"); */ clnt = rpc_create_client(xprt, hostname, &pmap_program, RPC_PMAP_VERSION, RPC_AUTH_NULL); if (IS_ERR(clnt)) { xprt_destroy(xprt); } else { clnt->cl_softrtry = 1; clnt->cl_chatty = 1; clnt->cl_oneshot = 1; } return clnt; } /* * XDR encode/decode functions for PMAP */ static int xdr_encode_mapping(struct rpc_rqst *req, u32 *p, struct rpc_portmap *map) { dprintk("RPC: xdr_encode_mapping(%d, %d, %d, %d)\n", map->pm_prog, map->pm_vers, map->pm_prot, map->pm_port); *p++ = htonl(map->pm_prog); *p++ = htonl(map->pm_vers); *p++ = htonl(map->pm_prot); *p++ = htonl(map->pm_port); req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); return 0; } static int xdr_decode_port(struct rpc_rqst *req, u32 *p, unsigned short *portp) { *portp = (unsigned short) ntohl(*p++); return 0; }