/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (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 (c) 1988 AT&T */
/* All Rights Reserved */
/*
* svc_generic.c, Server side for RPC.
*
*/
#include "mt.h"
#include <stdlib.h>
#include <inttypes.h>
#include "rpc_mt.h"
#include <stdio.h>
#include <errno.h>
#include <syslog.h>
#include <malloc.h>
#include <string.h>
#include <stropts.h>
#include <rpcsvc/nsm_addr.h>
#include <rpcsvc/sm_inter.h>
#include <rpcsvc/nlm_prot.h>
extern int __svc_vc_setflag(SVCXPRT *, int);
/*
* The highest level interface for server creation.
* It tries for all the nettokens in that particular class of token
*
* It creates a link list of all the handles it could create.
* If svc_create() is called multiple times, it uses the handle
* created earlier instead of creating a new handle every time.
*/
/* VARIABLES PROTECTED BY xprtlist_lock: xprtlist */
extern mutex_t xprtlist_lock;
{
/* This is a list of identified multilevel service provider */
return (B_TRUE);
return (B_FALSE);
}
void
__svc_free_xprtlist(void)
{
}
int
const char *nettype)
{
SVCXPRT_LIST *l;
int num = 0;
void *handle;
/*
* Check if service should register over doors transport.
*/
"svc_create: could not register over doors");
else
num++;
}
if (!try_others)
return (num);
return (0);
}
(void) mutex_lock(&xprtlist_lock);
for (l = _svc_xprtlist; l; l = l->next) {
/* Found an old one, use it */
"svc_create: could not register prog %d vers %d on %s",
else
num++;
break;
}
}
(void) mutex_unlock(&xprtlist_lock);
if (l == NULL) {
/* It was not found. Now create a new one */
if (xprt) {
&xprtlist_lock)) {
"svc_create: no memory");
return (0);
}
num++;
}
}
}
/*
* In case of num == 0; the error messages are generated by the
* underlying layers; and hence not needed here.
*/
return (num);
}
/*
* The high level interface to svc_tli_create().
* It tries to create a server for "nconf" and registers the service
* with the rpcbind. It calls svc_tli_create();
*/
SVCXPRT *
{
"svc_tp_create: invalid netconfig structure for prog %d vers %d",
return (NULL);
}
/* Some programs need to allocate MLP for multilevel services */
return (NULL);
"svc_tp_create: Could not register prog %d vers %d on %s",
return (NULL);
}
return (xprt);
}
SVCXPRT *
{
}
/*
* If fd is RPC_ANYFD, then it opens a fd for the given transport
* provider (nconf cannot be NULL then). If the t_state is T_UNBND and
* bindaddr is NON-NULL, it performs a t_bind using the bindaddr. For
* NULL bindadr and Connection oriented transports, the value of qlen
* is set arbitrarily.
*
* If sendsz or recvsz are zero, their default values are chosen.
*/
SVCXPRT *
{
"svc_tli_create: invalid netconfig");
return (NULL);
}
if (fd == -1) {
"svc_tli_create: could not open connection for %s: %s",
return (NULL);
}
} else {
/*
* It is an open descriptor. Sync it & get the transport info.
*/
"svc_tli_create: could not do t_sync: %s",
errorstr);
return (NULL);
}
"svc_tli_create: could not get transport information: %s",
errorstr);
return (NULL);
}
/* Enable options of returning the ip's for udp */
if (nconf) {
int ret = 0;
IPV6_RECVPKTINFO, 1);
if (ret < 0) {
"svc_tli_create: IPV6_RECVPKTINFO(1): %s",
errorstr);
return (NULL);
}
IP_RECVDSTADDR, 1);
if (ret < 0) {
"svc_tli_create: IP_RECVDSTADDR(1): %s",
errorstr);
return (NULL);
}
}
}
}
/*
* If the fd is unbound, try to bind it.
* In any case, try to get its bound info in tres
*/
goto freedata;
}
switch (state) {
case T_UNBND:
/* If this is a labeled system, then ask for an MLP */
if (is_system_labeled() &&
SO_RECVUCRED, 1);
if (mlp_flag)
SO_ANON_MLP, 1);
}
/*
* SO_EXCLBIND has the following properties
* - an fd bound to port P via IPv4 will prevent an IPv6
* bind to port P (and vice versa)
* - an fd bound to a wildcard IP address for port P will
* prevent a more specific IP address bind to port P
* (see {tcp,udp}.c for details)
*
* We use the latter property to prevent hijacking of RPC
* services that reside at non-privileged ports.
*/
if (nconf &&
if (exclbind) {
SO_EXCLBIND, 1) < 0) {
"svc_tli_create: can't set EXCLBIND [netid='%s']",
goto freedata;
}
}
}
if (bindaddr) {
tres) == -1) {
"svc_tli_create: could not bind: %s",
errorstr);
goto freedata;
}
/*
* Should compare the addresses only if addr.len
* was non-zero
*/
"svc_tli_create: could not bind to requested address: %s",
"address mismatch");
goto freedata;
}
} else {
"svc_tli_create: could not bind: %s",
errorstr);
goto freedata;
}
}
/* Enable options of returning the ip's for udp */
if (nconf) {
int ret = 0;
IPV6_RECVPKTINFO, 1);
if (ret < 0) {
"svc_tli_create: IPV6_RECVPKTINFO(2): %s",
errorstr);
goto freedata;
}
IP_RECVDSTADDR, 1);
if (ret < 0) {
"svc_tli_create: IP_RECVDSTADDR(2): %s",
errorstr);
goto freedata;
}
}
}
break;
case T_IDLE:
if (bindaddr) {
/* Copy the entire stuff in tres */
"svc_tli_create: illegal netbuf length");
goto freedata;
}
} else
break;
case T_INREL:
"svc_tli_create: other side wants to\
release connection");
goto freedata;
case T_INCON:
/* Do nothing here. Assume this is handled in rendezvous */
break;
case T_DATAXFER:
/*
* This takes care of the case where a fd
* is passed on which a connection has already
* been accepted.
*/
break;
default:
"svc_tli_create: connection in a wierd state (%d)", state);
goto freedata;
}
/*
* call transport specific function.
*/
case T_COTS_ORD:
case T_COTS:
if (state == T_DATAXFER)
recvsz);
else
recvsz);
break;
(state != T_DATAXFER) &&
break;
case T_CLTS:
break;
default:
"svc_tli_create: bad service type");
goto freedata;
}
/*
* The error messages here are spitted out by the lower layers:
* svc_vc_create(), svc_fd_create() and svc_dg_create().
*/
goto freedata;
/* fill in the other xprt information */
/* Assign the local bind address */
/* Fill in type of service */
/* Allocate space for the remote bind info */
goto freedata;
}
if (nconf) {
goto freedata;
}
goto freedata;
}
}
/*
* if (madefd && (tinfo.servtype == T_CLTS))
* (void) ioctl(fd, I_POP, NULL);
*/
return (xprt);
if (madefd)
if (tres)
if (xprt) {
if (!madefd) /* so that svc_destroy doesnt close fd */
}
return (NULL);
}