OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [net/] [sunrpc/] [pmap_clnt.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 * linux/net/sunrpc/pmap.c
3
 *
4
 * Portmapper client.
5
 *
6
 * FIXME: In a secure environment, we may want to use an authentication
7
 * flavor other than AUTH_NULL.
8
 *
9
 * Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de>
10
 */
11
 
12
#include <linux/config.h>
13
#include <linux/types.h>
14
#include <linux/socket.h>
15
#include <linux/kernel.h>
16
#include <linux/errno.h>
17
#include <linux/uio.h>
18
#include <linux/in.h>
19
#include <linux/sunrpc/clnt.h>
20
#include <linux/sunrpc/xprt.h>
21
#include <linux/sunrpc/sched.h>
22
 
23
#ifdef RPC_DEBUG
24
# define RPCDBG_FACILITY        RPCDBG_PMAP
25
#endif
26
 
27
#define PMAP_SET                1
28
#define PMAP_UNSET              2
29
#define PMAP_GETPORT            3
30
 
31
static struct rpc_clnt *        pmap_create(char *, struct sockaddr_in *, int);
32
static void                     pmap_getport_done(struct rpc_task *);
33
extern struct rpc_program       pmap_program;
34
static spinlock_t               pmap_lock = SPIN_LOCK_UNLOCKED;
35
 
36
/*
37
 * Obtain the port for a given RPC service on a given host. This one can
38
 * be called for an ongoing RPC request.
39
 */
40
void
41
rpc_getport(struct rpc_task *task, struct rpc_clnt *clnt)
42
{
43
        struct rpc_portmap *map = &clnt->cl_pmap;
44
        struct sockaddr_in *sap = &clnt->cl_xprt->addr;
45
        struct rpc_message msg = { PMAP_GETPORT, map, &clnt->cl_port, NULL };
46
        struct rpc_clnt *pmap_clnt;
47
        struct rpc_task *child;
48
 
49
        dprintk("RPC: %4d rpc_getport(%s, %d, %d, %d)\n",
50
                        task->tk_pid, clnt->cl_server,
51
                        map->pm_prog, map->pm_vers, map->pm_prot);
52
 
53
        spin_lock(&pmap_lock);
54
        if (clnt->cl_binding) {
55
                rpc_sleep_on(&clnt->cl_bindwait, task, NULL, 0);
56
                spin_unlock(&pmap_lock);
57
                return;
58
        }
59
        clnt->cl_binding = 1;
60
        spin_unlock(&pmap_lock);
61
 
62
        task->tk_status = -EACCES; /* why set this? returns -EIO below */
63
        if (!(pmap_clnt = pmap_create(clnt->cl_server, sap, map->pm_prot)))
64
                goto bailout;
65
        task->tk_status = 0;
66
 
67
        /*
68
         * Note: rpc_new_child will release client after a failure.
69
         */
70
        if (!(child = rpc_new_child(pmap_clnt, task)))
71
                goto bailout;
72
 
73
        /* Setup the call info struct */
74
        rpc_call_setup(child, &msg, 0);
75
 
76
        /* ... and run the child task */
77
        rpc_run_child(task, child, pmap_getport_done);
78
        return;
79
 
80
bailout:
81
        spin_lock(&pmap_lock);
82
        clnt->cl_binding = 0;
83
        rpc_wake_up(&clnt->cl_bindwait);
84
        spin_unlock(&pmap_lock);
85
        task->tk_status = -EIO;
86
        task->tk_action = NULL;
87
}
88
 
89
#ifdef CONFIG_ROOT_NFS
90
int
91
rpc_getport_external(struct sockaddr_in *sin, __u32 prog, __u32 vers, int prot)
92
{
93
        struct rpc_portmap map = { prog, vers, prot, 0 };
94
        struct rpc_clnt *pmap_clnt;
95
        char            hostname[32];
96
        int             status;
97
 
98
        dprintk("RPC:      rpc_getport_external(%u.%u.%u.%u, %d, %d, %d)\n",
99
                        NIPQUAD(sin->sin_addr.s_addr), prog, vers, prot);
100
 
101
        sprintf(hostname, "%u.%u.%u.%u", NIPQUAD(sin->sin_addr.s_addr));
102
        if (!(pmap_clnt = pmap_create(hostname, sin, prot)))
103
                return -EACCES;
104
 
105
        /* Setup the call info struct */
106
        status = rpc_call(pmap_clnt, PMAP_GETPORT, &map, &map.pm_port, 0);
107
 
108
        if (status >= 0) {
109
                if (map.pm_port != 0)
110
                        return map.pm_port;
111
                status = -EACCES;
112
        }
113
        return status;
114
}
115
#endif
116
 
117
static void
118
pmap_getport_done(struct rpc_task *task)
119
{
120
        struct rpc_clnt *clnt = task->tk_client;
121
 
122
        dprintk("RPC: %4d pmap_getport_done(status %d, port %d)\n",
123
                        task->tk_pid, task->tk_status, clnt->cl_port);
124
        if (task->tk_status < 0) {
125
                /* Make the calling task exit with an error */
126
                task->tk_action = NULL;
127
        } else if (clnt->cl_port == 0) {
128
                /* Program not registered */
129
                task->tk_status = -EACCES;
130
                task->tk_action = NULL;
131
        } else {
132
                /* byte-swap port number first */
133
                clnt->cl_port = htons(clnt->cl_port);
134
                clnt->cl_xprt->addr.sin_port = clnt->cl_port;
135
        }
136
        spin_lock(&pmap_lock);
137
        clnt->cl_binding = 0;
138
        rpc_wake_up(&clnt->cl_bindwait);
139
        spin_unlock(&pmap_lock);
140
}
141
 
142
/*
143
 * Set or unset a port registration with the local portmapper.
144
 * port == 0 means unregister, port != 0 means register.
145
 */
146
int
147
rpc_register(u32 prog, u32 vers, int prot, unsigned short port, int *okay)
148
{
149
        struct sockaddr_in      sin;
150
        struct rpc_portmap      map;
151
        struct rpc_clnt         *pmap_clnt;
152
        unsigned int            error = 0;
153
 
154
        dprintk("RPC: registering (%d, %d, %d, %d) with portmapper.\n",
155
                        prog, vers, prot, port);
156
 
157
        sin.sin_family = AF_INET;
158
        sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
159
        if (!(pmap_clnt = pmap_create("localhost", &sin, IPPROTO_UDP))) {
160
                dprintk("RPC: couldn't create pmap client\n");
161
                return -EACCES;
162
        }
163
 
164
        map.pm_prog = prog;
165
        map.pm_vers = vers;
166
        map.pm_prot = prot;
167
        map.pm_port = port;
168
 
169
        error = rpc_call(pmap_clnt, port? PMAP_SET : PMAP_UNSET,
170
                                        &map, okay, 0);
171
 
172
        if (error < 0) {
173
                printk(KERN_WARNING
174
                        "RPC: failed to contact portmap (errno %d).\n",
175
                        error);
176
        }
177
        dprintk("RPC: registration status %d/%d\n", error, *okay);
178
 
179
        /* Client deleted automatically because cl_oneshot == 1 */
180
        return error;
181
}
182
 
183
static struct rpc_clnt *
184
pmap_create(char *hostname, struct sockaddr_in *srvaddr, int proto)
185
{
186
        struct rpc_xprt *xprt;
187
        struct rpc_clnt *clnt;
188
 
189
        /* printk("pmap: create xprt\n"); */
190
        if (!(xprt = xprt_create_proto(proto, srvaddr, NULL)))
191
                return NULL;
192
        xprt->addr.sin_port = htons(RPC_PMAP_PORT);
193
 
194
        /* printk("pmap: create clnt\n"); */
195
        clnt = rpc_create_client(xprt, hostname,
196
                                &pmap_program, RPC_PMAP_VERSION,
197
                                RPC_AUTH_NULL);
198
        if (!clnt) {
199
                xprt_destroy(xprt);
200
        } else {
201
                clnt->cl_softrtry = 1;
202
                clnt->cl_chatty   = 1;
203
                clnt->cl_oneshot  = 1;
204
        }
205
        return clnt;
206
}
207
 
208
/*
209
 * XDR encode/decode functions for PMAP
210
 */
211
static int
212
xdr_error(struct rpc_rqst *req, u32 *p, void *dummy)
213
{
214
        return -EIO;
215
}
216
 
217
static int
218
xdr_encode_mapping(struct rpc_rqst *req, u32 *p, struct rpc_portmap *map)
219
{
220
        dprintk("RPC: xdr_encode_mapping(%d, %d, %d, %d)\n",
221
                map->pm_prog, map->pm_vers, map->pm_prot, map->pm_port);
222
        *p++ = htonl(map->pm_prog);
223
        *p++ = htonl(map->pm_vers);
224
        *p++ = htonl(map->pm_prot);
225
        *p++ = htonl(map->pm_port);
226
 
227
        req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
228
        return 0;
229
}
230
 
231
static int
232
xdr_decode_port(struct rpc_rqst *req, u32 *p, unsigned short *portp)
233
{
234
        *portp = (unsigned short) ntohl(*p++);
235
        return 0;
236
}
237
 
238
static int
239
xdr_decode_bool(struct rpc_rqst *req, u32 *p, unsigned int *boolp)
240
{
241
        *boolp = (unsigned int) ntohl(*p++);
242
        return 0;
243
}
244
 
245
static struct rpc_procinfo      pmap_procedures[4] = {
246
        { "pmap_null",
247
                (kxdrproc_t) xdr_error,
248
                (kxdrproc_t) xdr_error, 0, 0 },
249
        { "pmap_set",
250
                (kxdrproc_t) xdr_encode_mapping,
251
                (kxdrproc_t) xdr_decode_bool, 4, 1 },
252
        { "pmap_unset",
253
                (kxdrproc_t) xdr_encode_mapping,
254
                (kxdrproc_t) xdr_decode_bool, 4, 1 },
255
        { "pmap_get",
256
                (kxdrproc_t) xdr_encode_mapping,
257
                (kxdrproc_t) xdr_decode_port, 4, 1 },
258
};
259
 
260
static struct rpc_version       pmap_version2 = {
261
        2, 4, pmap_procedures
262
};
263
 
264
static struct rpc_version *     pmap_version[] = {
265
        NULL,
266
        NULL,
267
        &pmap_version2,
268
};
269
 
270
static struct rpc_stat          pmap_stats;
271
 
272
struct rpc_program      pmap_program = {
273
        "portmap",
274
        RPC_PMAP_PROGRAM,
275
        sizeof(pmap_version)/sizeof(pmap_version[0]),
276
        pmap_version,
277
        &pmap_stats,
278
};

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.