source: rtems/cpukit/librpc/src/rpc/rtems_portmapper.c @ 5220ae2

4.104.114.84.9
Last change on this file since 5220ae2 was 5220ae2, checked in by Ralf Corsepius <ralf.corsepius@…>, on Nov 21, 2004 at 5:33:00 AM

2004-11-21 Ralf Corsepius <ralf.corsepius@…>

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