4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
29 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
30 /* All Rights Reserved */
32 * University Copyright- Copyright (c) 1982, 1986, 1988
33 * The Regents of the University of California
36 * University Acknowledgment- Portions of this document are derived from
37 * software developed by the University of California, Berkeley, and its
43 * The server procedure for the version 2 portmaper.
44 * All the portmapper related interface from the portmap side.
56 #include <rpc/pmap_prot.h>
57 #include <rpc/rpcb_prot.h>
60 static bool_t
pmapproc_change(struct svc_req
*, SVCXPRT
*, unsigned long);
61 static bool_t
pmapproc_getport(struct svc_req
*, SVCXPRT
*);
62 static bool_t
pmapproc_dump(struct svc_req
*, SVCXPRT
*);
65 * Called for all the version 2 inquiries.
68 pmap_service(struct svc_req
*rqstp
, SVCXPRT
*xprt
)
70 rpcbs_procinfo(RPCBVERS_2_STAT
, rqstp
->rq_proc
);
72 switch (rqstp
->rq_proc
) {
77 PMAP_CHECK(xprt
, rqstp
->rq_proc
);
79 if ((!svc_sendreply(xprt
, (xdrproc_t
)xdr_void
, NULL
)) &&
89 * Set a program, version to port mapping
91 pmapproc_change(rqstp
, xprt
, rqstp
->rq_proc
);
96 * Remove a program, version to port mapping.
98 pmapproc_change(rqstp
, xprt
, rqstp
->rq_proc
);
101 case PMAPPROC_GETPORT
:
103 * Lookup the mapping for a program, version and return its
106 pmapproc_getport(rqstp
, xprt
);
111 * Return the current set of mapped program, version
113 PMAP_CHECK(xprt
, rqstp
->rq_proc
);
114 pmapproc_dump(rqstp
, xprt
);
117 case PMAPPROC_CALLIT
:
119 * Calls a procedure on the local machine. If the requested
120 * procedure is not registered this procedure does not return
121 * error information!!
122 * This procedure is only supported on rpc/udp and calls via
123 * rpc/udp. It passes null authentication parameters.
125 rpcbproc_callit_com(rqstp
, xprt
, PMAPPROC_CALLIT
, PMAPVERS
);
129 PMAP_CHECK(xprt
, rqstp
->rq_proc
);
136 * returns the item with the given program, version number. If that version
137 * number is not found, it returns the item with that program number, so that
138 * the port number is now returned to the caller. The caller when makes a
139 * call to this program, version number, the call will fail and it will
140 * return with PROGVERS_MISMATCH. The user can then determine the highest
141 * and the lowest version number for this program using clnt_geterr() and
142 * use those program version numbers.
145 find_service_pmap(rpcprog_t prog
, rpcvers_t vers
, rpcprot_t prot
)
147 PMAPLIST
*hit
= NULL
;
150 assert(RW_LOCK_HELD(&list_pml_lock
));
152 for (pml
= list_pml
; pml
!= NULL
; pml
= pml
->pml_next
) {
153 if ((pml
->pml_map
.pm_prog
!= prog
) ||
154 (pml
->pml_map
.pm_prot
!= prot
))
157 if (pml
->pml_map
.pm_vers
== vers
)
166 pmapproc_change(struct svc_req
*rqstp
, SVCXPRT
*xprt
, unsigned long op
)
171 struct sockaddr_in
*who
;
174 if (!svc_getargs(xprt
, (xdrproc_t
)xdr_pmap
, (char *)®
)) {
178 who
= (struct sockaddr_in
*)svc_getrpccaller(xprt
)->buf
;
180 /* Don't allow unset/set from remote. */
181 if (!localxprt(xprt
, B_TRUE
)) {
186 rpcbreg
.r_owner
= getowner(xprt
, owner
);
188 if ((op
== PMAPPROC_SET
) && (reg
.pm_port
< IPPORT_RESERVED
) &&
189 (ntohs(who
->sin_port
) >= IPPORT_RESERVED
)) {
193 rpcbreg
.r_prog
= reg
.pm_prog
;
194 rpcbreg
.r_vers
= reg
.pm_vers
;
196 if (op
== PMAPPROC_SET
) {
199 sprintf(buf
, "0.0.0.0.%d.%d", (reg
.pm_port
>> 8) & 0xff,
201 rpcbreg
.r_addr
= buf
;
202 if (reg
.pm_prot
== IPPROTO_UDP
) {
203 rpcbreg
.r_netid
= udptrans
;
204 } else if (reg
.pm_prot
== IPPROTO_TCP
) {
205 rpcbreg
.r_netid
= tcptrans
;
210 ans
= map_set(&rpcbreg
, rpcbreg
.r_owner
);
211 } else if (op
== PMAPPROC_UNSET
) {
214 rpcbreg
.r_addr
= NULL
;
215 rpcbreg
.r_netid
= tcptrans
;
216 ans1
= map_unset(&rpcbreg
, rpcbreg
.r_owner
);
217 rpcbreg
.r_netid
= udptrans
;
218 ans2
= map_unset(&rpcbreg
, rpcbreg
.r_owner
);
224 PMAP_LOG(ans
, xprt
, op
, reg
.pm_prog
);
226 if ((!svc_sendreply(xprt
, (xdrproc_t
)xdr_long
, (caddr_t
)&ans
)) &&
228 fprintf(stderr
, "portmap: svc_sendreply\n");
233 if (op
== PMAPPROC_SET
)
234 rpcbs_set(RPCBVERS_2_STAT
, ans
);
236 rpcbs_unset(RPCBVERS_2_STAT
, ans
);
242 pmapproc_getport(struct svc_req
*rqstp
, SVCXPRT
*xprt
)
247 bool_t rbl_locked
= FALSE
;
249 if (!svc_getargs(xprt
, (xdrproc_t
)xdr_pmap
, (char *)®
)) {
253 PMAP_CHECK_RET(xprt
, rqstp
->rq_proc
, FALSE
);
255 (void) rw_rdlock(&list_pml_lock
);
257 fnd
= find_service_pmap(reg
.pm_prog
, reg
.pm_vers
, reg
.pm_prot
);
259 char serveuaddr
[32], *ua
;
260 int h1
, h2
, h3
, h4
, p1
, p2
;
263 if (reg
.pm_prot
== IPPROTO_UDP
) {
267 ua
= tcp_uaddr
; /* To get the len */
271 (void) rw_unlock(&list_pml_lock
);
273 (void) rw_unlock(&list_rbl_lock
);
276 if (sscanf(ua
, "%d.%d.%d.%d.%d.%d", &h1
, &h2
, &h3
,
277 &h4
, &p1
, &p2
) == 6) {
278 p1
= (fnd
->pml_map
.pm_port
>> 8) & 0xff;
279 p2
= (fnd
->pml_map
.pm_port
) & 0xff;
280 sprintf(serveuaddr
, "%d.%d.%d.%d.%d.%d",
281 h1
, h2
, h3
, h4
, p1
, p2
);
282 if (is_bound(netid
, serveuaddr
)) {
283 port
= fnd
->pml_map
.pm_port
;
284 } else { /* this service is dead; delete it */
286 (void) rw_unlock(&list_pml_lock
);
287 (void) rw_wrlock(&list_rbl_lock
);
288 (void) rw_wrlock(&list_pml_lock
);
292 delete_prog(reg
.pm_prog
);
296 (void) rw_unlock(&list_pml_lock
);
298 (void) rw_unlock(&list_rbl_lock
);
301 if ((!svc_sendreply(xprt
, (xdrproc_t
)xdr_long
, (caddr_t
)&port
)) &&
303 (void) fprintf(stderr
, "portmap: svc_sendreply\n");
308 rpcbs_getaddr(RPCBVERS_2_STAT
, reg
.pm_prog
, reg
.pm_vers
,
309 reg
.pm_prot
== IPPROTO_UDP
? udptrans
: tcptrans
,
310 port
? udptrans
: "");
317 pmapproc_dump(struct svc_req
*rqstp
, SVCXPRT
*xprt
)
319 if (!svc_getargs(xprt
, (xdrproc_t
)xdr_void
, NULL
)) {
324 (void) rw_rdlock(&list_pml_lock
);
325 if ((!svc_sendreply(xprt
, (xdrproc_t
)xdr_pmaplist_ptr
,
326 (caddr_t
)&list_pml
)) && debugging
) {
327 (void) rw_unlock(&list_pml_lock
);
328 (void) fprintf(stderr
, "portmap: svc_sendreply\n");
333 (void) rw_unlock(&list_pml_lock
);
341 * Is the transport local? The original rpcbind code tried to
342 * figure out all the network interfaces but there can be a nearly
343 * infinite number of network interfaces. And the number of interfaces can
346 * Note that when we get here, we've already establised that we're
347 * dealing with a TCP/IP endpoint.
350 localxprt(SVCXPRT
*transp
, boolean_t forceipv4
)
352 struct sockaddr_gen
*sgen
= svc_getgencaller(transp
);
354 switch (SGFAM(sgen
)) {
366 * Get the peer's uid; if it is known it is sufficiently
367 * authenticated and considered local. The magic behind this
368 * call is all in libnsl.
370 return (rpcb_caller_uid(transp
) != -1);