* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
* %sccs.include.redist.c%
static char copyright
[] =
"@(#) Copyright (c) 1990, 1993\n\
The Regents of the University of California. All rights reserved.\n";
static char sccsid
[] = "@(#)portmap.c 8.1 (Berkeley) %G%";
@(#)portmap.c 2.3 88/08/11 4.0 RPCSRC
static char sccsid[] = "@(#)portmap.c 1.32 87/08/06 Copyr 1984 Sun Micro";
* portmap.c, Implements the program,version to port number mapping for
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
* media and as a part of the software program in whole or part. Users
* may copy or modify Sun RPC without charge, but are not authorized
* to license or distribute it to anyone else except as part of a product or
* program developed by the user.
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
* Sun RPC is provided with no support and without any obligation on the
* part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
* Mountain View, California 94043
#include <rpc/pmap_prot.h>
#include <sys/resource.h>
struct pmaplist
*pmaplist
;
int len
= sizeof(struct sockaddr_in
);
register struct pmaplist
*pml
;
while ((c
= getopt(argc
, argv
, "d")) != EOF
) {
(void) fprintf(stderr
, "usage: %s [-d]\n", argv
[0]);
if (!debugging
&& daemon(0, 0)) {
(void) fprintf(stderr
, "portmap: fork: %s", strerror(errno
));
openlog("portmap", debugging
? LOG_PID
| LOG_PERROR
: LOG_PID
,
if ((sock
= socket(AF_INET
, SOCK_DGRAM
, IPPROTO_UDP
)) < 0) {
syslog(LOG_ERR
, "cannot create udp socket: %m");
addr
.sin_addr
.s_addr
= 0;
addr
.sin_family
= AF_INET
;
addr
.sin_port
= htons(PMAPPORT
);
if (bind(sock
, (struct sockaddr
*)&addr
, len
) != 0) {
syslog(LOG_ERR
, "cannot bind udp: %m");
if ((xprt
= svcudp_create(sock
)) == (SVCXPRT
*)NULL
) {
syslog(LOG_ERR
, "couldn't do udp_create");
/* make an entry for ourself */
pml
= (struct pmaplist
*)malloc((u_int
)sizeof(struct pmaplist
));
pml
->pml_map
.pm_prog
= PMAPPROG
;
pml
->pml_map
.pm_vers
= PMAPVERS
;
pml
->pml_map
.pm_prot
= IPPROTO_UDP
;
pml
->pml_map
.pm_port
= PMAPPORT
;
if ((sock
= socket(AF_INET
, SOCK_STREAM
, IPPROTO_TCP
)) < 0) {
syslog(LOG_ERR
, "cannot create tcp socket: %m");
if (bind(sock
, (struct sockaddr
*)&addr
, len
) != 0) {
syslog(LOG_ERR
, "cannot bind udp: %m");
if ((xprt
= svctcp_create(sock
, RPCSMALLMSGSIZE
, RPCSMALLMSGSIZE
))
syslog(LOG_ERR
, "couldn't do tcp_create");
/* make an entry for ourself */
pml
= (struct pmaplist
*)malloc((u_int
)sizeof(struct pmaplist
));
pml
->pml_map
.pm_prog
= PMAPPROG
;
pml
->pml_map
.pm_vers
= PMAPVERS
;
pml
->pml_map
.pm_prot
= IPPROTO_TCP
;
pml
->pml_map
.pm_port
= PMAPPORT
;
pml
->pml_next
= pmaplist
;
(void)svc_register(xprt
, PMAPPROG
, PMAPVERS
, reg_service
, FALSE
);
(void)signal(SIGCHLD
, reap
);
syslog(LOG_ERR
, "run_svc returned unexpectedly");
/* need to override perror calls in rpc library */
syslog(LOG_ERR
, "%s: %m", what
);
find_service(prog
, vers
, prot
)
register struct pmaplist
*hit
= NULL
;
register struct pmaplist
*pml
;
for (pml
= pmaplist
; pml
!= NULL
; pml
= pml
->pml_next
) {
if ((pml
->pml_map
.pm_prog
!= prog
) ||
(pml
->pml_map
.pm_prot
!= prot
))
if (pml
->pml_map
.pm_vers
== vers
)
struct pmaplist
*pml
, *prevpml
, *fnd
;
(void) fprintf(stderr
, "server: about do a switch\n");
switch (rqstp
->rq_proc
) {
if (!svc_sendreply(xprt
, xdr_void
, (caddr_t
)0) && debugging
) {
* Set a program,version to port mapping
if (!svc_getargs(xprt
, xdr_pmap
, ®
))
* check to see if already used
* find_service returns a hit even if
* the versions don't match, so check for it
fnd
= find_service(reg
.pm_prog
, reg
.pm_vers
, reg
.pm_prot
);
if (fnd
&& fnd
->pml_map
.pm_vers
== reg
.pm_vers
) {
if (fnd
->pml_map
.pm_port
== reg
.pm_port
) {
pml
= (struct pmaplist
*)
malloc((u_int
)sizeof(struct pmaplist
));
for (fnd
= pmaplist
; fnd
->pml_next
!= 0;
if ((!svc_sendreply(xprt
, xdr_long
, (caddr_t
)&ans
)) &&
(void) fprintf(stderr
, "svc_sendreply\n");
* Remove a program,version to port mapping.
if (!svc_getargs(xprt
, xdr_pmap
, ®
))
for (prevpml
= NULL
, pml
= pmaplist
; pml
!= NULL
; ) {
if ((pml
->pml_map
.pm_prog
!= reg
.pm_prog
) ||
(pml
->pml_map
.pm_vers
!= reg
.pm_vers
)) {
/* both pml & prevpml move forwards */
/* found it; pml moves forward, prevpml stays */
if ((!svc_sendreply(xprt
, xdr_long
, (caddr_t
)&ans
)) &&
(void) fprintf(stderr
, "svc_sendreply\n");
* Lookup the mapping for a program,version and return its port
if (!svc_getargs(xprt
, xdr_pmap
, ®
))
fnd
= find_service(reg
.pm_prog
, reg
.pm_vers
, reg
.pm_prot
);
port
= fnd
->pml_map
.pm_port
;
if ((!svc_sendreply(xprt
, xdr_long
, (caddr_t
)&port
)) &&
(void) fprintf(stderr
, "svc_sendreply\n");
* Return the current set of mapped program,version
if (!svc_getargs(xprt
, xdr_void
, NULL
))
if ((!svc_sendreply(xprt
, xdr_pmaplist
,
(caddr_t
)&pmaplist
)) && debugging
) {
(void) fprintf(stderr
, "svc_sendreply\n");
* Calls a procedure on the local machine. If the requested
* procedure is not registered this procedure does not return
* This procedure is only supported on rpc/udp and calls via
* rpc/udp. It passes null authentication parameters.
* Stuff for the rmtcall service
xdr_encap_parms(xdrs
, epp
)
return (xdr_bytes(xdrs
, &(epp
->args
), &(epp
->arglen
), ARGSIZE
));
struct encap_parms rmt_args
;
xdr_rmtcall_args(xdrs
, cap
)
register struct rmtcallargs
*cap
;
/* does not get a port number */
if (xdr_u_long(xdrs
, &(cap
->rmt_prog
)) &&
xdr_u_long(xdrs
, &(cap
->rmt_vers
)) &&
xdr_u_long(xdrs
, &(cap
->rmt_proc
))) {
return (xdr_encap_parms(xdrs
, &(cap
->rmt_args
)));
xdr_rmtcall_result(xdrs
, cap
)
register struct rmtcallargs
*cap
;
if (xdr_u_long(xdrs
, &(cap
->rmt_port
)))
return (xdr_encap_parms(xdrs
, &(cap
->rmt_args
)));
* only worries about the struct encap_parms part of struct rmtcallargs.
* The arglen must already be set!!
xdr_opaque_parms(xdrs
, cap
)
return (xdr_opaque(xdrs
, cap
->rmt_args
.args
, cap
->rmt_args
.arglen
));
* This routine finds and sets the length of incoming opaque paraters
* and then calls xdr_opaque_parms.
xdr_len_opaque_parms(xdrs
, cap
)
register u_int beginpos
, lowpos
, highpos
, currpos
, pos
;
beginpos
= lowpos
= pos
= xdr_getpos(xdrs
);
highpos
= lowpos
+ ARGSIZE
;
while ((int)(highpos
- lowpos
) >= 0) {
currpos
= (lowpos
+ highpos
) / 2;
if (xdr_setpos(xdrs
, currpos
)) {
xdr_setpos(xdrs
, beginpos
);
cap
->rmt_args
.arglen
= pos
- beginpos
;
return (xdr_opaque_parms(xdrs
, cap
));
* Call a remote procedure service
* This procedure is very quiet when things go wrong.
* The proc is written to support broadcast rpc. In the broadcast case,
* a machine should shut-up instead of complain, less the requestor be
* overrun with complaints at the expense of not hearing a valid reply ...
* This now forks so that the program & process that it calls can call
* back to the portmapper.
struct authunix_parms
*au
= (struct authunix_parms
*)rqstp
->rq_clntcred
;
if (!svc_getargs(xprt
, xdr_rmtcall_args
, &a
))
if ((pml
= find_service(a
.rmt_prog
, a
.rmt_vers
,
(u_long
)IPPROTO_UDP
)) == NULL
)
* fork a child to do the work. Parent immediately returns.
* Child exits upon completion.
if ((pid
= fork()) != 0) {
syslog(LOG_ERR
, "CALLIT (prog %lu): fork: %m",
port
= pml
->pml_map
.pm_port
;
me
.sin_port
= htons(port
);
client
= clntudp_create(&me
, a
.rmt_prog
, a
.rmt_vers
, timeout
, &so
);
if (client
!= (CLIENT
*)NULL
) {
if (rqstp
->rq_cred
.oa_flavor
== AUTH_UNIX
) {
client
->cl_auth
= authunix_create(au
->aup_machname
,
au
->aup_uid
, au
->aup_gid
, au
->aup_len
, au
->aup_gids
);
a
.rmt_port
= (u_long
)port
;
if (clnt_call(client
, a
.rmt_proc
, xdr_opaque_parms
, &a
,
xdr_len_opaque_parms
, &a
, timeout
) == RPC_SUCCESS
) {
svc_sendreply(xprt
, xdr_rmtcall_result
, (caddr_t
)&a
);
AUTH_DESTROY(client
->cl_auth
);
while (wait3((int *)NULL
, WNOHANG
, (struct rusage
*)NULL
) > 0);