/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* This file contains the routines that maintain a linked list of known
* program to udp port mappings. There are three static members initialized
* by default, one for the portmapper itself (of course), one for rpcbind,
* and one for nfs. If a program number is not in the list, then routines
* in this file contact the portmapper on the server, and dynamically add
* new members to this list.
*
* This file also contains bpmap_rmtcall() - which lets one get the port
* number AND run the rpc call in one step. Only the server that successfully
* completes the rpc call will return a result.
*
* NOTE: Because we will end up caching the port entries we need
* before the kernel begins running, we can use dynamic allocation here.
* boot_memfree() calls bpmap_memfree() to free up any dynamically
* allocated entries when the boot program has finished its job.
*/
#include <netinet/if_ether.h>
#include "clnt.h"
#include <rpc/pmap_prot.h>
#include <rpc/pmap_rmt.h>
#include "brpc.h"
#include "pmap.h"
#include "nfs_inet.h"
#include <rpcsvc/nfs_prot.h>
#include <rpc/rpcb_prot.h>
#include "socket_inet.h"
#include <sys/bootdebug.h>
/* portmap structure */
/* SVR4 rpcbind listens to old portmapper port */
};
/*
* bpmap_addport: adds a new entry on to the end of the pmap cache.
* Items are kept in host order.
*/
static void
{
/* allocate new pmaplist */
return; /* not fatal here, we'll just throw out the entry */
}
/*
* bpmap_delport: deletes an existing entry from the list. Caution - don't
* call this function to delete statically allocated entries. Why would
* you want to, anyway? Only IPPROTO_UDP is supported, of course.
*/
static void
{
} else {
/* internal delete */
}
#ifdef DEBUG
vers);
#endif /* DEBUG */
break;
} else
}
}
/*
* Modified strtol(3).
*/
static int
{
int c, val;
val *= 10;
val += c - '0';
}
return (val);
}
/*
* (from dlboot_inet.c) (kernel)
* Convert a port number from a sockaddr_in expressed
* in universal address format.
*/
static int
{
char *next;
/*
* A struct sockaddr_in expressed in universal address
* format looks like:
*
* "IP.IP.IP.IP.PORT[top byte].PORT[bot. byte]"
*
* Where each component expresses as a charactor,
* the corresponding part of the IP address
* and port number.
* Thus 127.0.0.1, port 2345 looks like:
*
* 49 50 55 46 48 46 48 46 49 46 57 46 52 49
* 1 2 7 . 0 . 0 . 1 . 9 . 4 1
*
* 2345 = 929base16 = 9.32+9 = 9.41
*/
}
/*
* Xdr routines used for calling portmapper/rpcbind.
*/
{
return (FALSE);
}
{
return (FALSE);
return (FALSE);
return (FALSE);
return (FALSE);
return (FALSE);
return (TRUE);
}
/*
* XDR remote call arguments
* written for XDR_ENCODE direction only
*/
{
return (FALSE);
return (FALSE);
return (FALSE);
return (TRUE);
}
return (FALSE);
}
/*
* XDR remote call results
* written for XDR_DECODE direction only
*/
{
}
return (FALSE);
}
/*
* XDR remote call arguments
* written for XDR_ENCODE direction only
*/
{
return (FALSE);
return (FALSE);
return (FALSE);
/*
* All the jugglery for just getting the size of the arguments
*/
return (FALSE);
return (FALSE);
return (FALSE);
return (TRUE);
}
/*
* XDR remote call results
* written for XDR_DECODE direction only
*/
{
return (FALSE);
return (FALSE);
}
/*
* bpmap_rmtcall: does PMAPPROC_CALLIT broadcasts w/ rpc_call requests.
* Lets one do a PMAPGETPORT/RPC PROC call in one easy step. sockaddr_in args
* are taken as network order.
*
* Code adapted from bpmap_rmtcall() in dlboot_inet.c (kernel)
*/
/*ARGSUSED*/
enum clnt_stat
int rexmit, /* retransmission interval (secs) */
int wait, /* how long (secs) to wait for a resp */
{
/* initialize pmap */
if (status != RPC_PROGUNAVAIL) {
if (status == RPC_SUCCESS) {
/* delete old port mapping, if it exists */
/* save the new port mapping */
}
return (status);
}
/*
* PMAP is unavailable. Maybe there's a SVR4 machine, with rpcbind.
*/
/* initialize rpcb */
if (status == RPC_SUCCESS) {
/* delete old port mapping, if it exists */
/* save the new port mapping */
}
return (status);
}
/*
* bpmap_getport: Queries current list of cached pmap_list entries,
* returns the port number of the entry found. If the port number
* is not cached, then getport makes a rpc call first to the portmapper,
* and then to rpcbind (SVR4) if the portmapper does not respond. The
* returned port is then added to the cache, and the port number is
* returned. If both portmapper and rpc bind fail to give us the necessary
* port, we return 0 to signal we hit an error, and set rpc_stat to
* the appropriate RPC error code. Only IPPROTO_UDP protocol is supported.
*
* Port and sockaddr_in arguments taken in network order. rpcport_t is returned
* in host order.
*/
{
#ifdef DEBUG
#endif /* DEBUG */
#ifdef DEBUG
printf("bpmap_getport: Found in cache. returning: %d\n",
#endif /* DEBUG */
}
}
/*
* Not in the cache. First try the portmapper (SunOS server?) and
* if that fails, try rpcbind (SVR4 server).
*/
if (*rpc_stat == RPC_PROGUNAVAIL) {
/*
* The portmapper isn't available. Try rpcbind.
* Maybe the server is a SVR4 server.
*/
/*
* Again, default # of retries. xdr_wrapstring()
* wants a char **.
*/
if (*rpc_stat == RPC_SUCCESS) {
if (ua[0] != '\0')
else
return (0); /* Address unknown */
}
} else {
/*
* Why are rpcport_t's uint32_t? port numbers are uint16_t
* for ipv4 AND ipv6.... XXXX
*/
}
if (*rpc_stat != RPC_SUCCESS) {
dprintf("pmap_getport: Failed getting port.\n");
return (0); /* we failed. */
}
#ifdef DEBUG
printf("bpmap_getport: prog: %d, vers: %d; returning port: %d.\n",
#endif /* DEBUG */
return (dport);
}
/*
* bpmap_memfree: frees up any dynamically allocated entries.
*/
void
bpmap_memfree(void)
{
return; /* no dynamic entries */
/* free from head of the list to the tail. */
}
}