static char sccsid
[] = "@(#)portmap.c 1.2 85/03/13 Copyr 1984 Sun Micro";
* Copyright (c) 1984 by Sun Microsystems, Inc.
* 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>
static int debugging
= 0;
int len
= sizeof(struct sockaddr_in
);
ioctl(t
, TIOCNOTTY
, (char *)0);
if ((sock
= socket(AF_INET
, SOCK_DGRAM
, IPPROTO_UDP
)) < 0) {
perror("portmap cannot create socket");
addr
.sin_addr
.s_addr
= 0;
addr
.sin_family
= AF_INET
;
addr
.sin_port
= htons(PMAPPORT
);
if (bind(sock
, (struct sockaddr
*)&addr
, len
) != 0) {
perror("portmap cannot bind");
if ((xprt
= svcudp_create(sock
)) == (SVCXPRT
*)NULL
) {
fprintf(stderr
, "couldn't do udp_create\n");
if ((sock
= socket(AF_INET
, SOCK_STREAM
, IPPROTO_TCP
)) < 0) {
perror("portmap cannot create socket");
if (bind(sock
, (struct sockaddr
*)&addr
, len
) != 0) {
perror("portmap cannot bind");
if ((xprt
= svctcp_create(sock
, 0, 0)) == (SVCXPRT
*)NULL
) {
fprintf(stderr
, "couldn't do tcp_create\n");
(void)svc_register(xprt
, PMAPPROG
, PMAPVERS
, reg_service
, FALSE
);
fprintf(stderr
, "run_svc returned unexpectedly\n");
struct pmaplist
*pmaplist
;
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
;
fprintf(stderr
, "server: about do a switch\n");
switch (rqstp
->rq_proc
) {
if ((!svc_sendreply(xprt
, xdr_void
, NULL
)) && 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
));
pml
->pml_next
= pmaplist
;
if ((!svc_sendreply(xprt
, xdr_long
, (caddr_t
)&ans
)) &&
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
)) &&
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
)) &&
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
) {
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
typedef struct encap_parms
{
xdr_encap_parms(xdrs
, epp
)
return (xdr_bytes(xdrs
, &(epp
->args
), &(epp
->arglen
), ARGSIZE
));
typedef struct rmtcallargs
{
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 ...
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
, IPPROTO_UDP
)) == NULL
)
port
= pml
->pml_map
.pm_port
;
me
.sin_port
= htons(port
);
client
= clntudp_create(&me
, a
.rmt_prog
, a
.rmt_vers
, timeout
, &socket
);
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
, &a
);
AUTH_DESTROY(client
->cl_auth
);