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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rtems/] [c/] [src/] [librpc/] [src/] [rpc/] [rtems_portmapper.c] - Blame information for rev 1771

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 158 chris
/*
2
 * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
3
 * unrestricted use provided that this legend is included on all tape
4
 * media and as a part of the software program in whole or part.  Users
5
 * may copy or modify Sun RPC without charge, but are not authorized
6
 * to license or distribute it to anyone else except as part of a product or
7
 * program developed by the user.
8
 *
9
 * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
10
 * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
11
 * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
12
 *
13
 * Sun RPC is provided with no support and without any obligation on the
14
 * part of Sun Microsystems, Inc. to assist in its use, correction,
15
 * modification or enhancement.
16
 *
17
 * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
18
 * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
19
 * OR ANY PART THEREOF.
20
 *
21
 * In no event will Sun Microsystems, Inc. be liable for any lost revenue
22
 * or profits or other special, indirect and consequential damages, even if
23
 * Sun has been advised of the possibility of such damages.
24
 *
25
 * Sun Microsystems, Inc.
26
 * 2550 Garcia Avenue
27
 * Mountain View, California  94043
28
 */
29
 
30
#include <rpc/rpc.h>
31
#include <rpc/pmap_prot.h>
32
#include <stdio.h>
33
#include <unistd.h>
34
#include <malloc.h>
35
#include <netdb.h>
36
#include <sys/socket.h>
37
#include <sys/ioctl.h>
38
#include <sys/wait.h>
39
#include <sys/signal.h>
40
 
41
static void reg_service();
42
static void callit();
43
static struct pmaplist *pmaplist;
44
static int debugging = 0;
45
 
46
#include <rtems.h>
47
#define fork()  (-1)
48
 
49
 
50
static rtems_task rtems_portmapper (rtems_task_argument unused)
51
{
52
        SVCXPRT *xprt;
53
        int sock;
54
        struct sockaddr_in addr;
55
        int len = sizeof(struct sockaddr_in);
56
        register struct pmaplist *pml;
57
 
58
        rtems_rpc_task_init ();
59
        if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
60
                perror("portmap cannot create socket");
61
                rtems_task_delete (RTEMS_SELF);
62
        }
63
 
64
        addr.sin_addr.s_addr = 0;
65
        addr.sin_family = AF_INET;
66
        addr.sin_port = htons(PMAPPORT);
67
        if (bind(sock, (struct sockaddr *)&addr, len) != 0) {
68
                perror("portmap cannot bind");
69
                close (sock);
70
                rtems_task_delete (RTEMS_SELF);
71
        }
72
 
73
        if ((xprt = svcudp_create(sock)) == (SVCXPRT *)NULL) {
74
                fprintf(stderr, "couldn't do udp_create\n");
75
                close (sock);
76
                rtems_task_delete (RTEMS_SELF);
77
        }
78
        /* make an entry for ourself */
79
        pml = (struct pmaplist *)malloc((u_int)sizeof(struct pmaplist));
80
        pml->pml_next = 0;
81
        pml->pml_map.pm_prog = PMAPPROG;
82
        pml->pml_map.pm_vers = PMAPVERS;
83
        pml->pml_map.pm_prot = IPPROTO_UDP;
84
        pml->pml_map.pm_port = PMAPPORT;
85
        pmaplist = pml;
86
 
87
        if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
88
                perror("portmap cannot create socket");
89
                close (sock);
90
                rtems_task_delete (RTEMS_SELF);
91
        }
92
        if (bind(sock, (struct sockaddr *)&addr, len) != 0) {
93
                perror("portmap cannot bind");
94
                close (sock);
95
                rtems_task_delete (RTEMS_SELF);
96
        }
97
        if ((xprt = svctcp_create(sock, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE))
98
            == (SVCXPRT *)NULL) {
99
                fprintf(stderr, "couldn't do tcp_create\n");
100
                close (sock);
101
                rtems_task_delete (RTEMS_SELF);
102
        }
103
        /* make an entry for ourself */
104
        pml = (struct pmaplist *)malloc((u_int)sizeof(struct pmaplist));
105
        pml->pml_map.pm_prog = PMAPPROG;
106
        pml->pml_map.pm_vers = PMAPVERS;
107
        pml->pml_map.pm_prot = IPPROTO_TCP;
108
        pml->pml_map.pm_port = PMAPPORT;
109
        pml->pml_next = pmaplist;
110
        pmaplist = pml;
111
 
112
        (void)svc_register(xprt, PMAPPROG, PMAPVERS, reg_service, FALSE);
113
 
114
        svc_run();
115
        fprintf(stderr, "run_svc returned unexpectedly\n");
116
        close (sock);
117
        rtems_task_delete (RTEMS_SELF);
118
}
119
 
120
static struct pmaplist *
121
find_service(prog, vers, prot)
122
u_long prog;
123
u_long vers;
124
{
125
register struct pmaplist *hit = NULL;
126
register struct pmaplist *pml;
127
 
128
for (pml = pmaplist; pml != NULL; pml = pml->pml_next) {
129
        if ((pml->pml_map.pm_prog != prog) ||
130
                (pml->pml_map.pm_prot != prot))
131
                continue;
132
        hit = pml;
133
        if (pml->pml_map.pm_vers == vers)
134
            break;
135
}
136
        return (hit);
137
}
138
 
139
/*
140
 * 1 OK, 0 not
141
 */
142
static void reg_service(rqstp, xprt)
143
        struct svc_req *rqstp;
144
        SVCXPRT *xprt;
145
{
146
        struct pmap reg;
147
        struct pmaplist *pml, *prevpml, *fnd;
148
        int ans, port;
149
        caddr_t t;
150
 
151
#ifdef DEBUG
152
        fprintf(stderr, "server: about do a switch\n");
153
#endif
154
        switch (rqstp->rq_proc) {
155
 
156
        case PMAPPROC_NULL:
157
                /*
158
                 * Null proc call
159
                 */
160
                if ((!svc_sendreply(xprt, xdr_void, NULL)) && debugging) {
161
                        abort();
162
                }
163
                break;
164
 
165
        case PMAPPROC_SET:
166
                /*
167
                 * Set a program,version to port mapping
168
                 */
169
                if (!svc_getargs(xprt, xdr_pmap, (caddr_t)&reg))
170
                        svcerr_decode(xprt);
171
                else {
172
                        /*
173
                         * check to see if already used
174
                         * find_service returns a hit even if
175
                         * the versions don't match, so check for it
176
                         */
177
                        fnd = find_service(reg.pm_prog, reg.pm_vers, reg.pm_prot);
178
                        if (fnd && fnd->pml_map.pm_vers == reg.pm_vers) {
179
                                if (fnd->pml_map.pm_port == reg.pm_port) {
180
                                        ans = 1;
181
                                        goto done;
182
                                }
183
                                else {
184
                                        ans = 0;
185
                                        goto done;
186
                                }
187
                        } else {
188
                                /*
189
                                 * add to END of list
190
                                 */
191
                                pml = (struct pmaplist *)
192
                                    malloc((u_int)sizeof(struct pmaplist));
193
                                pml->pml_map = reg;
194
                                pml->pml_next = 0;
195
                                if (pmaplist == 0) {
196
                                        pmaplist = pml;
197
                                } else {
198
                                        for (fnd= pmaplist; fnd->pml_next != 0;
199
                                            fnd = fnd->pml_next);
200
                                        fnd->pml_next = pml;
201
                                }
202
                                ans = 1;
203
                        }
204
                done:
205
                        if ((!svc_sendreply(xprt, xdr_long, (caddr_t)&ans)) &&
206
                            debugging) {
207
                                fprintf(stderr, "svc_sendreply\n");
208
                                abort();
209
                        }
210
                }
211
                break;
212
 
213
        case PMAPPROC_UNSET:
214
                /*
215
                 * Remove a program,version to port mapping.
216
                 */
217
                if (!svc_getargs(xprt, xdr_pmap, (caddr_t)&reg))
218
                        svcerr_decode(xprt);
219
                else {
220
                        ans = 0;
221
                        for (prevpml = NULL, pml = pmaplist; pml != NULL; ) {
222
                                if ((pml->pml_map.pm_prog != reg.pm_prog) ||
223
                                        (pml->pml_map.pm_vers != reg.pm_vers)) {
224
                                        /* both pml & prevpml move forwards */
225
                                        prevpml = pml;
226
                                        pml = pml->pml_next;
227
                                        continue;
228
                                }
229
                                /* found it; pml moves forward, prevpml stays */
230
                                ans = 1;
231
                                t = (caddr_t)pml;
232
                                pml = pml->pml_next;
233
                                if (prevpml == NULL)
234
                                        pmaplist = pml;
235
                                else
236
                                        prevpml->pml_next = pml;
237
                                free(t);
238
                        }
239
                        if ((!svc_sendreply(xprt, xdr_long, (caddr_t)&ans)) &&
240
                            debugging) {
241
                                fprintf(stderr, "svc_sendreply\n");
242
                                abort();
243
                        }
244
                }
245
                break;
246
 
247
        case PMAPPROC_GETPORT:
248
                /*
249
                 * Lookup the mapping for a program,version and return its port
250
                 */
251
                if (!svc_getargs(xprt, xdr_pmap, (caddr_t)&reg))
252
                        svcerr_decode(xprt);
253
                else {
254
                        fnd = find_service(reg.pm_prog, reg.pm_vers, reg.pm_prot);
255
                        if (fnd)
256
                                port = fnd->pml_map.pm_port;
257
                        else
258
                                port = 0;
259
                        if ((!svc_sendreply(xprt, xdr_long, (caddr_t)&port)) &&
260
                            debugging) {
261
                                fprintf(stderr, "svc_sendreply\n");
262
                                abort();
263
                        }
264
                }
265
                break;
266
 
267
        case PMAPPROC_DUMP:
268
                /*
269
                 * Return the current set of mapped program,version
270
                 */
271
                if (!svc_getargs(xprt, xdr_void, NULL))
272
                        svcerr_decode(xprt);
273
                else {
274
                        if ((!svc_sendreply(xprt, xdr_pmaplist,
275
                            (caddr_t)&pmaplist)) && debugging) {
276
                                fprintf(stderr, "svc_sendreply\n");
277
                                abort();
278
                        }
279
                }
280
                break;
281
 
282
        case PMAPPROC_CALLIT:
283
                /*
284
                 * Calls a procedure on the local machine.  If the requested
285
                 * procedure is not registered this procedure does not return
286
                 * error information!!
287
                 * This procedure is only supported on rpc/udp and calls via
288
                 * rpc/udp.  It passes null authentication parameters.
289
                 */
290
                callit(rqstp, xprt);
291
                break;
292
 
293
        default:
294
                svcerr_noproc(xprt);
295
                break;
296
        }
297
}
298
 
299
 
300
/*
301
 * Stuff for the rmtcall service
302
 */
303
#define ARGSIZE 9000
304
 
305
struct encap_parms {
306
        u_long arglen;
307
        char *args;
308
};
309
 
310
static bool_t
311
xdr_encap_parms(xdrs, epp)
312
        XDR *xdrs;
313
        struct encap_parms *epp;
314
{
315
 
316
        return (xdr_bytes(xdrs, &(epp->args), (u_int*)&(epp->arglen), ARGSIZE));
317
}
318
 
319
struct rmtcallargs {
320
        u_long  rmt_prog;
321
        u_long  rmt_vers;
322
        u_long  rmt_port;
323
        u_long  rmt_proc;
324
        struct encap_parms rmt_args;
325
};
326
 
327
static bool_t
328
xdr_rmtcall_args(xdrs, cap)
329
        register XDR *xdrs;
330
        register struct rmtcallargs *cap;
331
{
332
 
333
        /* does not get a port number */
334
        if (xdr_u_long(xdrs, &(cap->rmt_prog)) &&
335
            xdr_u_long(xdrs, &(cap->rmt_vers)) &&
336
            xdr_u_long(xdrs, &(cap->rmt_proc))) {
337
                return (xdr_encap_parms(xdrs, &(cap->rmt_args)));
338
        }
339
        return (FALSE);
340
}
341
 
342
static bool_t
343
xdr_rmtcall_result(xdrs, cap)
344
        register XDR *xdrs;
345
        register struct rmtcallargs *cap;
346
{
347
        if (xdr_u_long(xdrs, &(cap->rmt_port)))
348
                return (xdr_encap_parms(xdrs, &(cap->rmt_args)));
349
        return (FALSE);
350
}
351
 
352
/*
353
 * only worries about the struct encap_parms part of struct rmtcallargs.
354
 * The arglen must already be set!!
355
 */
356
static bool_t
357
xdr_opaque_parms(xdrs, cap)
358
        XDR *xdrs;
359
        struct rmtcallargs *cap;
360
{
361
 
362
        return (xdr_opaque(xdrs, cap->rmt_args.args, cap->rmt_args.arglen));
363
}
364
 
365
/*
366
 * This routine finds and sets the length of incoming opaque paraters
367
 * and then calls xdr_opaque_parms.
368
 */
369
static bool_t
370
xdr_len_opaque_parms(xdrs, cap)
371
        register XDR *xdrs;
372
        struct rmtcallargs *cap;
373
{
374
        register u_int beginpos, lowpos, highpos, currpos, pos;
375
 
376
        beginpos = lowpos = pos = xdr_getpos(xdrs);
377
        highpos = lowpos + ARGSIZE;
378
        while ((int)(highpos - lowpos) >= 0) {
379
                currpos = (lowpos + highpos) / 2;
380
                if (xdr_setpos(xdrs, currpos)) {
381
                        pos = currpos;
382
                        lowpos = currpos + 1;
383
                } else {
384
                        highpos = currpos - 1;
385
                }
386
        }
387
        xdr_setpos(xdrs, beginpos);
388
        cap->rmt_args.arglen = pos - beginpos;
389
        return (xdr_opaque_parms(xdrs, cap));
390
}
391
 
392
/*
393
 * Call a remote procedure service
394
 * This procedure is very quiet when things go wrong.
395
 * The proc is written to support broadcast rpc.  In the broadcast case,
396
 * a machine should shut-up instead of complain, less the requestor be
397
 * overrun with complaints at the expense of not hearing a valid reply ...
398
 *
399
 * This now forks so that the program & process that it calls can call
400
 * back to the portmapper.
401
 */
402
static void
403
callit(rqstp, xprt)
404
        struct svc_req *rqstp;
405
        SVCXPRT *xprt;
406
{
407
        struct rmtcallargs a;
408
        struct pmaplist *pml;
409
        u_short port;
410
        struct sockaddr_in me;
411
        int pid, socket = -1;
412
        CLIENT *client;
413
        struct authunix_parms *au = (struct authunix_parms *)rqstp->rq_clntcred;
414
        struct timeval timeout;
415
        char buf[ARGSIZE];
416
 
417
        timeout.tv_sec = 5;
418
        timeout.tv_usec = 0;
419
        a.rmt_args.args = buf;
420
        if (!svc_getargs(xprt, xdr_rmtcall_args, (caddr_t)&a))
421
            return;
422
        if ((pml = find_service(a.rmt_prog, a.rmt_vers, IPPROTO_UDP)) == NULL)
423
            return;
424
        /*
425
         * fork a child to do the work.  Parent immediately returns.
426
         * Child exits upon completion.
427
         */
428
        if ((pid = fork()) != 0) {
429
                if (debugging && (pid < 0)) {
430
                        fprintf(stderr, "portmap CALLIT: cannot fork.\n");
431
                }
432
                return;
433
        }
434
        port = pml->pml_map.pm_port;
435
        get_myaddress(&me);
436
        me.sin_port = htons(port);
437
        client = clntudp_create(&me, a.rmt_prog, a.rmt_vers, timeout, &socket);
438
        if (client != (CLIENT *)NULL) {
439
                if (rqstp->rq_cred.oa_flavor == AUTH_UNIX) {
440
                        client->cl_auth = authunix_create(au->aup_machname,
441
                           au->aup_uid, au->aup_gid, au->aup_len, au->aup_gids);
442
                }
443
                a.rmt_port = (u_long)port;
444
                if (clnt_call(client, a.rmt_proc, xdr_opaque_parms, &a,
445
                    xdr_len_opaque_parms, &a, timeout) == RPC_SUCCESS) {
446
                        svc_sendreply(xprt, xdr_rmtcall_result, (caddr_t)&a);
447
                }
448
                AUTH_DESTROY(client->cl_auth);
449
                clnt_destroy(client);
450
        }
451
        (void)close(socket);
452
        exit(0);
453
}
454
 
455
/*
456
 * Start the RPC portmapper
457
 */
458
int rtems_rpc_start_portmapper (int priority)
459
{
460
        rtems_mode mode;
461
        rtems_status_code sc;
462
        rtems_id tid;
463
        static int started;
464
 
465
        rtems_task_mode (RTEMS_NO_PREEMPT, RTEMS_PREEMPT_MASK, &mode);
466
        if (started) {
467
                rtems_task_mode (mode, RTEMS_PREEMPT_MASK, &mode);
468
                return RTEMS_SUCCESSFUL;
469
        }
470
        sc = rtems_task_create (rtems_build_name('P', 'M', 'A', 'P'),
471
                priority,
472
                8000,
473
                RTEMS_PREEMPT|RTEMS_NO_TIMESLICE|RTEMS_NO_ASR|RTEMS_INTERRUPT_LEVEL(0),
474
                RTEMS_NO_FLOATING_POINT|RTEMS_LOCAL,
475
                &tid);
476
        if (sc != RTEMS_SUCCESSFUL) {
477
                rtems_task_mode (mode, RTEMS_PREEMPT_MASK, &mode);
478
                return sc;
479
        }
480
        sc = rtems_task_start (tid, rtems_portmapper, 0);
481
        if (sc != RTEMS_SUCCESSFUL) {
482
                rtems_task_mode (mode, RTEMS_PREEMPT_MASK, &mode);
483
                return sc;
484
        }
485
        started = 1;
486
        rtems_task_mode (mode, RTEMS_PREEMPT_MASK, &mode);
487
        return RTEMS_SUCCESSFUL;
488
}

powered by: WebSVN 2.1.0

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