usr/src/uts/common/inet/optcom.c
author masputra
Sat, 22 Oct 2005 22:50:14 -0700
changeset 741 40027a3621ac
parent 0 68f95e015346
child 1676 37f4a3e2bd99
permissions -rw-r--r--
PSARC 2005/082 Yosemite: UDP Performance Enhancement 4796051 Solaris needs a more complete HW checksumming support 4905227 duplicate macros in ipclassifier.h and ip.h 4915681 need hardware checksum offload for the case of IP/UDP reassembly 6201076 outbound flow-control dysfunctional, ip to ce using mdt 6223331 ipv6 flow control may corrupt UDP packets 6223809 16-bit aligned IP header should be allowed for all x86 platforms 6275398 Galaxy hangs when running lmbench 6281836 Yosemite project integration into Solaris 6281885 xge needs to support IPv6 checksum offload 6282776 IPv6 NCE fast path is not created for incoming solicitation 6304890 IP transmit-side checksum logic needs to be tightened 6304902 IP6_IN_NOCKSUM is obsolete and should be torched 6304904 UDP should reject TI_GETPEERNAME for non-connected endpoint 6306768 IP and UDP device and module definitions need to be centralized
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     1
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     2
 * CDDL HEADER START
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     3
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     4
 * The contents of this file are subject to the terms of the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     5
 * Common Development and Distribution License, Version 1.0 only
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     6
 * (the "License").  You may not use this file except in compliance
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     7
 * with the License.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     8
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     9
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    10
 * or http://www.opensolaris.org/os/licensing.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    11
 * See the License for the specific language governing permissions
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    12
 * and limitations under the License.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    13
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    14
 * When distributing Covered Code, include this CDDL HEADER in each
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    15
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    16
 * If applicable, add the following below this CDDL HEADER, with the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    17
 * fields enclosed by brackets "[]" replaced with your own identifying
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    18
 * information: Portions Copyright [yyyy] [name of copyright owner]
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    19
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    20
 * CDDL HEADER END
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    21
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    22
/*
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 0
diff changeset
    23
 * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    24
 * Use is subject to license terms.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    25
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    26
/* Copyright (c) 1990 Mentat Inc. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    27
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    28
#pragma ident	"%Z%%M%	%I%	%E% SMI"
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    29
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    30
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    31
 * This file contains common code for handling Options Management requests.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    32
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    33
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    34
#include <sys/types.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    35
#include <sys/stream.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    36
#include <sys/stropts.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    37
#include <sys/strlog.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    38
#include <sys/strsubr.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    39
#include <sys/errno.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    40
#define	_SUN_TPI_VERSION 2
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    41
#include <sys/tihdr.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    42
#include <sys/timod.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    43
#include <sys/socket.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    44
#include <sys/ddi.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    45
#include <sys/cmn_err.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    46
#include <sys/debug.h>		/* for ASSERT */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    47
#include <sys/policy.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    48
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    49
#include <inet/common.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    50
#include <inet/mi.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    51
#include <inet/nd.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    52
#include <netinet/ip6.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    53
#include <inet/ip.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    54
#include <inet/mib2.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    55
#include <netinet/in.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    56
#include <netinet/tcp.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    57
#include <netinet/ip_mroute.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    58
#include "optcom.h"
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    59
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    60
#include <inet/optcom.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    61
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    62
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    63
 * Function prototypes
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    64
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    65
static t_scalar_t process_topthdrs_first_pass(mblk_t *, cred_t *, optdb_obj_t *,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    66
    boolean_t *, size_t *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    67
static t_scalar_t do_options_second_pass(queue_t *q, mblk_t *reqmp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    68
    mblk_t *ack_mp, cred_t *, optdb_obj_t *dbobjp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    69
    mblk_t *first_mp, boolean_t is_restart, boolean_t *queued_statusp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    70
static t_uscalar_t get_worst_status(t_uscalar_t, t_uscalar_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    71
static int do_opt_default(queue_t *, struct T_opthdr *, uchar_t **,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    72
    t_uscalar_t *, cred_t *, optdb_obj_t *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    73
static void do_opt_current(queue_t *, struct T_opthdr *, uchar_t **,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    74
    t_uscalar_t *, cred_t *cr, optdb_obj_t *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    75
static int do_opt_check_or_negotiate(queue_t *q, struct T_opthdr *reqopt,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    76
    uint_t optset_context, uchar_t **resptrp, t_uscalar_t *worst_statusp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    77
    cred_t *, optdb_obj_t *dbobjp, mblk_t *first_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    78
static opdes_t *opt_chk_lookup(t_uscalar_t, t_uscalar_t, opdes_t *, uint_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    79
static boolean_t opt_level_valid(t_uscalar_t, optlevel_t *, uint_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    80
static size_t opt_level_allopts_lengths(t_uscalar_t, opdes_t *, uint_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    81
static boolean_t opt_length_ok(opdes_t *, struct T_opthdr *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    82
static t_uscalar_t optcom_max_optbuf_len(opdes_t *, uint_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    83
static boolean_t opt_bloated_maxsize(opdes_t *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    84
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    85
/* Common code for sending back a T_ERROR_ACK. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    86
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    87
optcom_err_ack(queue_t *q, mblk_t *mp, t_scalar_t t_error, int sys_error)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    88
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    89
	if ((mp = mi_tpi_err_ack_alloc(mp, t_error, sys_error)) != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    90
		qreply(q, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    91
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    92
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    93
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    94
 * The option management routines svr4_optcom_req() and tpi_optcom_req() use
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    95
 * callback functions as arguments. Here is the expected interfaces
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    96
 * assumed from the callback functions
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    97
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    98
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    99
 * (1) deffn(q, optlevel, optname, optvalp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   100
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   101
 *	- Function only called when default value comes from protocol
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   102
 *	 specific code and not the option database table (indicated by
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   103
 *	  OP_DEF_FN property in option database.)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   104
 *	- Error return is -1. Valid returns are >=0.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   105
 *	- When valid, the return value represents the length used for storing
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   106
 *		the default value of the option.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   107
 *      - Error return implies the called routine did not recognize this
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   108
 *              option. Something downstream could so input is left unchanged
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   109
 *              in request buffer.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   110
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   111
 * (2) getfn(q, optlevel, optname, optvalp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   112
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   113
 *	- Error return is -1. Valid returns are >=0.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   114
 *	- When valid, the return value represents the length used for storing
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   115
 *		the actual value of the option.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   116
 *      - Error return implies the called routine did not recognize this
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   117
 *              option. Something downstream could so input is left unchanged
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   118
 *              in request buffer.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   119
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   120
 * (3) setfn(q, optset_context, optlevel, optname, inlen, invalp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   121
 *	outlenp, outvalp, attrp, cr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   122
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   123
 *	- OK return is 0, Error code is returned as a non-zero argument.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   124
 *      - If negative it is ignored by svr4_optcom_req(). If positive, error
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   125
 *        is returned. A negative return implies that option, while handled on
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   126
 *	  this stack is not handled at this level and will be handled further
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   127
 *	  downstream.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   128
 *	- Both negative and positive errors are treats as errors in an
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   129
 *	  identical manner by tpi_optcom_req(). The errors affect "status"
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   130
 *	  field of each option's T_opthdr. If sucessfull, an appropriate sucess
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   131
 *	  result is carried. If error, it instantiated to "failure" at the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   132
 *	  topmost level and left unchanged at other levels. (This "failure" can
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   133
 *	  turn to a success at another level).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   134
 *	- optset_context passed for tpi_optcom_req(). It is interpreted as:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   135
 *        - SETFN_OPTCOM_CHECKONLY
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   136
 *		semantics are to pretend to set the value and report
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   137
 *		back if it would be successful.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   138
 *		This is used with T_CHECK semantics in XTI
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   139
 *        - SETFN_OPTCOM_NEGOTIATE
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   140
 *		set the value. Call from option management primitive
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   141
 *		T_OPTMGMT_REQ when T_NEGOTIATE flags is used.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   142
 *	  - SETFN_UD_NEGOTIATE
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   143
 *		option request came riding on UNITDATA primitive most often
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   144
 *		has  "this datagram" semantics to influence prpoerties
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   145
 *		affecting an outgoig datagram or associated with recived
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   146
 *		datagram
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   147
 *		[ Note: XTI permits this use outside of "this datagram"
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   148
 *		semantics also and permits setting "management related"
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   149
 *		options in this	context and its test suite enforces it ]
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   150
 *	  - SETFN_CONN_NEGOTATE
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   151
 *		option request came riding on CONN_REQ/RES primitive and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   152
 *		most often has "this connection" (negotiation during
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   153
 *		"connection estblishment") semantics.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   154
 *		[ Note: XTI permits use of these outside of "this connection"
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   155
 *		semantics and permits "management related" options in this
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   156
 *		context and its test suite enforces it. ]
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   157
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   158
 *	- inlen, invalp is the option length,value requested to be set.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   159
 *	- outlenp, outvalp represent return parameters which contain the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   160
 *	  value set and it might be different from one passed on input.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   161
 *	- attrp points to a data structure that's used by v6 modules to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   162
 *	  store ancillary data options or sticky options.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   163
 *	- cr points to the caller's credentials
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   164
 *	- the caller might pass same buffers for input and output and the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   165
 *	  routine should protect against this case by not updating output
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   166
 *	  buffers until it is done referencing input buffers and any other
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   167
 *	  issues (e.g. not use bcopy() if we do not trust what it does).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   168
 *      - If option is not known, it returns error. We randomly pick EINVAL.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   169
 *        It can however get called with options that are handled downstream
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   170
 *        opr upstream so for svr4_optcom_req(), it does not return error for
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   171
 *        negative return values.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   172
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   173
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   174
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   175
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   176
 * Upper Level Protocols call this routine when they receive
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   177
 * a T_SVR4_OPTMGMT_REQ message.  They supply callback functions
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   178
 * for setting a new value for a single options, getting the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   179
 * current value for a single option, and checking for support
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   180
 * of a single option.  svr4_optcom_req validates the option management
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   181
 * buffer passed in, and calls the appropriate routines to do the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   182
 * job requested.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   183
 * XXX Code below needs some restructuring after we have some more
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   184
 * macros to support 'struct opthdr' in the headers.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   185
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   186
 * IP-MT notes: The option management framework functions svr4_optcom_req() and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   187
 * tpi_optcom_req() allocate and prepend an M_CTL mblk to the actual
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   188
 * T_optmgmt_req mblk and pass the chain as an additional parameter to the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   189
 * protocol set functions. If a protocol set function (such as ip_opt_set)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   190
 * cannot process the option immediately it can return EINPROGRESS. ip_opt_set
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   191
 * enqueues the message in the appropriate sq and returns EINPROGRESS. Later
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   192
 * the sq framework arranges to restart this operation and passes control to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   193
 * the restart function ip_restart_optmgmt() which in turn calls
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   194
 * svr4_optcom_req() or tpi_optcom_req() to restart the option processing.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   195
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   196
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   197
svr4_optcom_req(queue_t *q, mblk_t *mp, cred_t *cr, optdb_obj_t *dbobjp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   198
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   199
	pfi_t	deffn = dbobjp->odb_deffn;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   200
	pfi_t	getfn = dbobjp->odb_getfn;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   201
	opt_set_fn setfn = dbobjp->odb_setfn;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   202
	opdes_t	*opt_arr = dbobjp->odb_opt_des_arr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   203
	uint_t opt_arr_cnt = dbobjp->odb_opt_arr_cnt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   204
	boolean_t topmost_tpiprovider = dbobjp->odb_topmost_tpiprovider;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   205
	opt_restart_t *or;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   206
	struct opthdr *restart_opt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   207
	boolean_t is_restart = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   208
	mblk_t	*first_mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   209
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   210
	t_uscalar_t max_optbuf_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   211
	int len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   212
	mblk_t	*mp1 = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   213
	struct opthdr *next_opt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   214
	struct opthdr *opt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   215
	struct opthdr *opt1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   216
	struct opthdr *opt_end;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   217
	struct opthdr *opt_start;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   218
	opdes_t	*optd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   219
	boolean_t	pass_to_next = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   220
	boolean_t	pass_to_ip = B_FALSE;
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 0
diff changeset
   221
	boolean_t	is_tcp;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   222
	struct T_optmgmt_ack *toa;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   223
	struct T_optmgmt_req *tor;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   224
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 0
diff changeset
   225
	is_tcp = (dbobjp == &tcp_opt_obj);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 0
diff changeset
   226
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   227
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   228
	 * Allocate M_CTL and prepend to the packet for restarting this
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   229
	 * option if needed. IP may need to queue and restart the option
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   230
	 * if it cannot obtain exclusive conditions immediately. Please see
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   231
	 * IP-MT notes before the start of svr4_optcom_req
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   232
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   233
	if (mp->b_datap->db_type == M_CTL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   234
		is_restart = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   235
		first_mp = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   236
		mp = mp->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   237
		ASSERT(mp->b_wptr - mp->b_rptr >=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   238
		    sizeof (struct T_optmgmt_req));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   239
		tor = (struct T_optmgmt_req *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   240
		ASSERT(tor->MGMT_flags == T_NEGOTIATE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   241
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   242
		or = (opt_restart_t *)first_mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   243
		opt_start = or->or_start;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   244
		opt_end = or->or_end;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   245
		restart_opt = or->or_ropt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   246
		goto restart;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   247
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   248
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   249
	tor = (struct T_optmgmt_req *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   250
	/* Verify message integrity. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   251
	if (mp->b_wptr - mp->b_rptr < sizeof (struct T_optmgmt_req))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   252
		goto bad_opt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   253
	/* Verify MGMT_flags legal */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   254
	switch (tor->MGMT_flags) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   255
	case T_DEFAULT:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   256
	case T_NEGOTIATE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   257
	case T_CURRENT:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   258
	case T_CHECK:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   259
		/* OK - legal request flags */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   260
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   261
	default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   262
		optcom_err_ack(q, mp, TBADFLAG, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   263
		return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   264
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   265
	if (tor->MGMT_flags == T_DEFAULT) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   266
		/* Is it a request for default option settings? */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   267
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   268
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   269
		 * Note: XXX TLI and TPI specification was unclear about
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   270
		 * semantics of T_DEFAULT and the following historical note
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   271
		 * and its interpretation is incorrect (it implies a request
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   272
		 * for default values of only the identified options not all.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   273
		 * The semantics have been explained better in XTI spec.)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   274
		 * However, we do not modify (comment or code) here to keep
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   275
		 * compatibility.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   276
		 * We can rethink this if it ever becomes an issue.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   277
		 * ----historical comment start------
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   278
		 * As we understand it, the input buffer is meaningless
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   279
		 * so we ditch the message.  A T_DEFAULT request is a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   280
		 * request to obtain a buffer containing defaults for
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   281
		 * all supported options, so we allocate a maximum length
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   282
		 * reply.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   283
		 * ----historical comment end -------
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   284
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   285
		/* T_DEFAULT not passed down */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   286
		ASSERT(topmost_tpiprovider == B_TRUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   287
		freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   288
		max_optbuf_len = optcom_max_optbuf_len(opt_arr,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   289
		    opt_arr_cnt);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   290
		mp = allocb(max_optbuf_len, BPRI_MED);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   291
		if (!mp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   292
no_mem:;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   293
			optcom_err_ack(q, mp, TSYSERR, ENOMEM);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   294
			return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   295
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   296
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   297
		/* Initialize the T_optmgmt_ack header. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   298
		toa = (struct T_optmgmt_ack *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   299
		bzero((char *)toa, max_optbuf_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   300
		toa->PRIM_type = T_OPTMGMT_ACK;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   301
		toa->OPT_offset = (t_scalar_t)sizeof (struct T_optmgmt_ack);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   302
		/* TODO: Is T_DEFAULT the right thing to put in MGMT_flags? */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   303
		toa->MGMT_flags = T_DEFAULT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   304
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   305
		/* Now walk the table of options passed in */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   306
		opt = (struct opthdr *)&toa[1];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   307
		for (optd = opt_arr; optd < &opt_arr[opt_arr_cnt]; optd++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   308
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   309
			 * All the options in the table of options passed
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   310
			 * in are by definition supported by the protocol
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   311
			 * calling this function.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   312
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   313
			if (!OA_READ_PERMISSION(optd, cr))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   314
				continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   315
			opt->level = optd->opdes_level;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   316
			opt->name = optd->opdes_name;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   317
			if (!(optd->opdes_props & OP_DEF_FN) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   318
			    ((len = (*deffn)(q, opt->level,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   319
				opt->name, (uchar_t *)&opt[1])) < 0)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   320
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   321
				 * Fill length and value from table.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   322
				 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   323
				 * Default value not instantiated from function
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   324
				 * (or the protocol specific function failed it;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   325
				 * In this interpretation of T_DEFAULT, this is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   326
				 * the best we can do)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   327
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   328
				switch (optd->opdes_size) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   329
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   330
				 * Since options are guaranteed aligned only
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   331
				 * on a 4 byte boundary (t_scalar_t) any
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   332
				 * option that is greater in size will default
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   333
				 * to the bcopy below
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   334
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   335
				case sizeof (int32_t):
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   336
					*(int32_t *)&opt[1] =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   337
					    (int32_t)optd->opdes_default;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   338
					break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   339
				case sizeof (int16_t):
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   340
					*(int16_t *)&opt[1] =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   341
					    (int16_t)optd->opdes_default;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   342
					break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   343
				case sizeof (int8_t):
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   344
					*(int8_t *)&opt[1] =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   345
					    (int8_t)optd->opdes_default;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   346
					break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   347
				default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   348
					/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   349
					 * other length but still assume
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   350
					 * fixed - use bcopy
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   351
					 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   352
					bcopy(optd->opdes_defbuf,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   353
					    &opt[1], optd->opdes_size);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   354
					break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   355
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   356
				opt->len = optd->opdes_size;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   357
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   358
			else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   359
				opt->len = (t_uscalar_t)len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   360
			opt = (struct opthdr *)((char *)&opt[1] +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   361
			    _TPI_ALIGN_OPT(opt->len));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   362
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   363
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   364
		/* Now record the final length. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   365
		toa->OPT_length = (t_scalar_t)((char *)opt - (char *)&toa[1]);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   366
		mp->b_wptr = (uchar_t *)opt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   367
		mp->b_datap->db_type = M_PCPROTO;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   368
		/* Ship it back. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   369
		qreply(q, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   370
		return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   371
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   372
	/* T_DEFAULT processing complete - no more T_DEFAULT */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   373
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   374
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   375
	 * For T_NEGOTIATE, T_CURRENT, and T_CHECK requests, we make a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   376
	 * pass through the input buffer validating the details and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   377
	 * making sure each option is supported by the protocol.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   378
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   379
	if ((opt_start = (struct opthdr *)mi_offset_param(mp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   380
	    tor->OPT_offset, tor->OPT_length)) == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   381
		goto bad_opt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   382
	if (!__TPI_OPT_ISALIGNED(opt_start))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   383
		goto bad_opt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   384
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   385
	opt_end = (struct opthdr *)((uchar_t *)opt_start +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   386
	    tor->OPT_length);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   387
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   388
	for (opt = opt_start; opt < opt_end; opt = next_opt) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   389
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   390
		 * Verify we have room to reference the option header
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   391
		 * fields in the option buffer.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   392
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   393
		if ((uchar_t *)opt + sizeof (struct opthdr) >
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   394
		    (uchar_t *)opt_end)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   395
			goto bad_opt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   396
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   397
		 * We now compute pointer to next option in buffer 'next_opt'
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   398
		 * The next_opt computation above below 'opt->len' initialized
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   399
		 * by application which cannot be trusted. The usual value
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   400
		 * too large will be captured by the loop termination condition
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   401
		 * above. We check for the following which it will miss.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   402
		 * 	-pointer space wraparound arithmetic overflow
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   403
		 *	-last option in buffer with 'opt->len' being too large
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   404
		 *	 (only reason 'next_opt' should equal or exceed
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   405
		 *	 'opt_end' for last option is roundup unless length is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   406
		 *	 too-large/invalid)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   407
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   408
		next_opt = (struct opthdr *)((uchar_t *)&opt[1] +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   409
		    _TPI_ALIGN_OPT(opt->len));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   410
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   411
		if ((uchar_t *)next_opt < (uchar_t *)&opt[1] ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   412
		    ((next_opt >= opt_end) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   413
			(((uchar_t *)next_opt - (uchar_t *)opt_end) >=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   414
			    __TPI_ALIGN_SIZE)))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   415
			goto bad_opt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   416
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   417
		/* sanity check */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   418
		if (opt->name == T_ALLOPT)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   419
			goto bad_opt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   420
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   421
		/* Find the option in the opt_arr. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   422
		if ((optd = opt_chk_lookup(opt->level, opt->name,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   423
		    opt_arr, opt_arr_cnt)) == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   424
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   425
			 * Not found, that is a bad thing if
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   426
			 * the caller is a tpi provider
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   427
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   428
			if (topmost_tpiprovider)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   429
				goto bad_opt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   430
			else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   431
				continue; /* skip unmodified */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   432
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   433
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   434
		/* Additional checks dependent on operation. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   435
		switch (tor->MGMT_flags) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   436
		case T_NEGOTIATE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   437
			if (!OA_WRITE_OR_EXECUTE(optd, cr)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   438
				/* can't negotiate option */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   439
				if (!(OA_MATCHED_PRIV(optd, cr)) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   440
				    OA_WX_ANYPRIV(optd)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   441
					/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   442
					 * not privileged but privilege
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   443
					 * will help negotiate option.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   444
					 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   445
					optcom_err_ack(q, mp, TACCES, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   446
					return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   447
				} else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   448
					goto bad_opt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   449
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   450
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   451
			 * Verify size for options
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   452
			 * Note: For retaining compatibility with historical
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   453
			 * behavior, variable lengths options will have their
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   454
			 * length verified in the setfn() processing.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   455
			 * In order to be compatible with SunOS 4.X we return
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   456
			 * EINVAL errors for bad lengths.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   457
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   458
			if (!(optd->opdes_props & OP_VARLEN)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   459
				/* fixed length - size must match */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   460
				if (opt->len != optd->opdes_size) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   461
					optcom_err_ack(q, mp, TSYSERR, EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   462
					return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   463
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   464
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   465
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   466
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   467
		case T_CHECK:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   468
			if (!OA_RWX_ANYPRIV(optd))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   469
				/* any of "rwx" permission but not not none */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   470
				goto bad_opt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   471
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   472
			 * XXX Since T_CURRENT was not there in TLI and the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   473
			 * official TLI inspired TPI standard, getsockopt()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   474
			 * API uses T_CHECK (for T_CURRENT semantics)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   475
			 * The following fallthru makes sense because of its
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   476
			 * historical use as semantic equivalent to T_CURRENT.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   477
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   478
			/* FALLTHRU */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   479
		case T_CURRENT:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   480
			if (!OA_READ_PERMISSION(optd, cr)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   481
				/* can't read option value */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   482
				if (!(OA_MATCHED_PRIV(optd, cr)) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   483
				    OA_R_ANYPRIV(optd)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   484
					/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   485
					 * not privileged but privilege
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   486
					 * will help in reading option value.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   487
					 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   488
					optcom_err_ack(q, mp, TACCES, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   489
					return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   490
				} else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   491
					goto bad_opt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   492
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   493
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   494
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   495
		default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   496
			optcom_err_ack(q, mp, TBADFLAG, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   497
			return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   498
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   499
		/* We liked it.  Keep going. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   500
	} /* end for loop scanning option buffer */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   501
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   502
	/* Now complete the operation as required. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   503
	switch (tor->MGMT_flags) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   504
	case T_CHECK:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   505
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   506
		 * Historically used same as T_CURRENT (which was added to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   507
		 * standard later). Code retained for compatibility.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   508
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   509
		/* FALLTHROUGH */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   510
	case T_CURRENT:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   511
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   512
		 * Allocate a maximum size reply.  Perhaps we are supposed to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   513
		 * assume that the input buffer includes space for the answers
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   514
		 * as well as the opthdrs, but we don't know that for sure.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   515
		 * So, instead, we create a new output buffer, using the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   516
		 * input buffer only as a list of options.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   517
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   518
		max_optbuf_len = optcom_max_optbuf_len(opt_arr,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   519
		    opt_arr_cnt);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   520
		mp1 = allocb_cred(max_optbuf_len, cr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   521
		if (!mp1)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   522
			goto no_mem;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   523
		/* Initialize the header. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   524
		mp1->b_datap->db_type = M_PCPROTO;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   525
		mp1->b_wptr = &mp1->b_rptr[sizeof (struct T_optmgmt_ack)];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   526
		toa = (struct T_optmgmt_ack *)mp1->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   527
		toa->OPT_offset = (t_scalar_t)sizeof (struct T_optmgmt_ack);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   528
		toa->MGMT_flags = tor->MGMT_flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   529
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   530
		 * Walk through the input buffer again, this time adding
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   531
		 * entries to the output buffer for each option requested.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   532
		 * Note, sanity of option header, last option etc, verified
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   533
		 * in first pass.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   534
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   535
		opt1 = (struct opthdr *)&toa[1];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   536
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   537
		for (opt = opt_start; opt < opt_end; opt = next_opt) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   538
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   539
		    next_opt = (struct opthdr *)((uchar_t *)&opt[1] +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   540
			_TPI_ALIGN_OPT(opt->len));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   541
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   542
			opt1->name = opt->name;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   543
			opt1->level = opt->level;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   544
			len = (*getfn)(q, opt->level,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   545
			    opt->name, (uchar_t *)&opt1[1]);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   546
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   547
			 * Failure means option is not recognized. Copy input
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   548
			 * buffer as is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   549
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   550
			if (len < 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   551
				opt1->len = opt->len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   552
				bcopy(&opt[1], &opt1[1], opt->len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   553
				/*
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 0
diff changeset
   554
				 * Pass the option down to IP only
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 0
diff changeset
   555
				 * if TCP hasn't processed it.
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   556
				 */
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 0
diff changeset
   557
				if (is_tcp)
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   558
					pass_to_ip = B_TRUE;
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 0
diff changeset
   559
			} else {
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 0
diff changeset
   560
				opt1->len = (t_uscalar_t)len;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   561
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   562
			opt1 = (struct opthdr *)((uchar_t *)&opt1[1] +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   563
			    _TPI_ALIGN_OPT(opt1->len));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   564
		} /* end for loop */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   565
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   566
		/* Record the final length. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   567
		toa->OPT_length = (t_scalar_t)((uchar_t *)opt1 -
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   568
		    (uchar_t *)&toa[1]);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   569
		mp1->b_wptr = (uchar_t *)opt1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   570
		/* Ditch the input buffer. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   571
		freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   572
		mp = mp1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   573
		/* Always let the next module look at the option. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   574
		pass_to_next = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   575
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   576
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   577
	case T_NEGOTIATE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   578
		first_mp = allocb(sizeof (opt_restart_t), BPRI_LO);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   579
		if (first_mp == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   580
			optcom_err_ack(q, mp, TSYSERR, ENOMEM);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   581
			return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   582
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   583
		first_mp->b_datap->db_type = M_CTL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   584
		or = (opt_restart_t *)first_mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   585
		or->or_start = opt_start;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   586
		or->or_end =  opt_end;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   587
		or->or_type = T_SVR4_OPTMGMT_REQ;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   588
		or->or_private = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   589
		first_mp->b_cont = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   590
restart:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   591
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   592
		 * Here we are expecting that the response buffer is exactly
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   593
		 * the same size as the input buffer.  We pass each opthdr
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   594
		 * to the protocol's set function.  If the protocol doesn't
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   595
		 * like it, it can update the value in it return argument.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   596
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   597
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   598
		 * Pass each negotiated option through the protocol set
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   599
		 * function.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   600
		 * Note: sanity check on option header values done in first
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   601
		 * pass and not repeated here.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   602
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   603
		toa = (struct T_optmgmt_ack *)tor;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   604
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   605
		for (opt = is_restart ? restart_opt: opt_start; opt < opt_end;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   606
		    opt = next_opt) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   607
			int error;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   608
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   609
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   610
			 * Point to the current option in or, in case this
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   611
			 * option has to be restarted later on
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   612
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   613
			or->or_ropt = opt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   614
			next_opt = (struct opthdr *)((uchar_t *)&opt[1] +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   615
			    _TPI_ALIGN_OPT(opt->len));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   616
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   617
			error = (*setfn)(q, SETFN_OPTCOM_NEGOTIATE,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   618
			    opt->level, opt->name,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   619
			    opt->len, (uchar_t *)&opt[1],
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   620
			    &opt->len, (uchar_t *)&opt[1], NULL, cr, first_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   621
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   622
			 * Treat positive "errors" as real.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   623
			 * Note: negative errors are to be treated as
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   624
			 * non-fatal by svr4_optcom_req() and are
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   625
			 * returned by setfn() when it is passed an
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   626
			 * option it does not handle. Since the option
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   627
			 * passed opt_chk_lookup(), it is implied that
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   628
			 * it is valid but was either handled upstream
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   629
			 * or will be handled downstream.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   630
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   631
			if (error == EINPROGRESS) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   632
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   633
				 * The message is queued and will be
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   634
				 * reprocessed later. Typically ip queued
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   635
				 * the message to get some exclusive conditions
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   636
				 * and later on calls this func again.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   637
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   638
				return (EINPROGRESS);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   639
			} else if (error > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   640
				optcom_err_ack(q, mp, TSYSERR, error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   641
				freeb(first_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   642
				return (0);
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 0
diff changeset
   643
			} else if (error < 0 && is_tcp) {
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   644
				/*
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 0
diff changeset
   645
				 * Pass the option down to IP only
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 0
diff changeset
   646
				 * if TCP hasn't processed it.
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   647
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   648
				pass_to_ip = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   649
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   650
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   651
		/* Done with the restart control mp. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   652
		freeb(first_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   653
		pass_to_next = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   654
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   655
	default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   656
		optcom_err_ack(q, mp, TBADFLAG, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   657
		return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   658
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   659
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   660
	if (pass_to_next && (q->q_next != NULL || pass_to_ip)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   661
		/* Send it down to the next module and let it reply */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   662
		toa->PRIM_type = T_SVR4_OPTMGMT_REQ; /* Changed by IP to ACK */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   663
		if (q->q_next != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   664
			putnext(q, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   665
		else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   666
			ip_output(Q_TO_CONN(q), mp, q, IP_WPUT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   667
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   668
		/* Set common fields in the header. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   669
		toa->MGMT_flags = T_SUCCESS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   670
		mp->b_datap->db_type = M_PCPROTO;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   671
		toa->PRIM_type = T_OPTMGMT_ACK;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   672
		qreply(q, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   673
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   674
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   675
bad_opt:;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   676
	optcom_err_ack(q, mp, TBADOPT, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   677
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   678
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   679
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   680
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   681
 * New optcom_req inspired by TPI/XTI semantics
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   682
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   683
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   684
tpi_optcom_req(queue_t *q, mblk_t *mp, cred_t *cr, optdb_obj_t *dbobjp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   685
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   686
	t_scalar_t t_error;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   687
	mblk_t *toa_mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   688
	boolean_t pass_to_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   689
	size_t toa_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   690
	struct T_optmgmt_ack *toa;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   691
	struct T_optmgmt_req *tor =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   692
	    (struct T_optmgmt_req *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   693
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   694
	opt_restart_t *or;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   695
	boolean_t is_restart = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   696
	mblk_t	*first_mp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   697
	t_uscalar_t worst_status;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   698
	boolean_t queued_status;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   699
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   700
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   701
	 * Allocate M_CTL and prepend to the packet for restarting this
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   702
	 * option if needed. IP may need to queue and restart the option
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   703
	 * if it cannot obtain exclusive conditions immediately. Please see
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   704
	 * IP-MT notes before the start of svr4_optcom_req
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   705
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   706
	if (mp->b_datap->db_type == M_CTL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   707
		is_restart = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   708
		first_mp = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   709
		toa_mp = mp->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   710
		mp = toa_mp->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   711
		ASSERT(mp->b_wptr - mp->b_rptr >=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   712
		    sizeof (struct T_optmgmt_req));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   713
		tor = (struct T_optmgmt_req *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   714
		ASSERT(tor->MGMT_flags == T_NEGOTIATE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   715
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   716
		or = (opt_restart_t *)first_mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   717
		goto restart;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   718
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   719
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   720
	/* Verify message integrity. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   721
	if ((mp->b_wptr - mp->b_rptr) < sizeof (struct T_optmgmt_req)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   722
		optcom_err_ack(q, mp, TBADOPT, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   723
		return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   724
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   725
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   726
	/* Verify MGMT_flags legal */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   727
	switch (tor->MGMT_flags) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   728
	case T_DEFAULT:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   729
	case T_NEGOTIATE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   730
	case T_CURRENT:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   731
	case T_CHECK:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   732
		/* OK - legal request flags */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   733
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   734
	default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   735
		optcom_err_ack(q, mp, TBADFLAG, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   736
		return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   737
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   738
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   739
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   740
	 * In this design, there are two passes required on the input buffer
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   741
	 * mostly to accomodate variable length options and "T_ALLOPT" option
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   742
	 * which has the semantics "all options of the specified level".
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   743
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   744
	 * For T_DEFAULT, T_NEGOTIATE, T_CURRENT, and T_CHECK requests, we make
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   745
	 * a pass through the input buffer validating the details and making
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   746
	 * sure each option is supported by the protocol. We also determine the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   747
	 * length of the option buffer to return. (Variable length options and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   748
	 * T_ALLOPT mean that length can be different for output buffer).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   749
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   750
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   751
	pass_to_next = B_FALSE;	/* initial value */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   752
	toa_len = 0;		/* initial value */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   753
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   754
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   755
	 * First pass, we do the following
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   756
	 *	- estimate cumulative length needed for results
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   757
	 *	- set "status" field based on permissions, option header check
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   758
	 *	  etc.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   759
	 *	- determine "pass_to_next" whether we need to send request to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   760
	 *	  downstream module/driver.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   761
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   762
	if ((t_error = process_topthdrs_first_pass(mp, cr, dbobjp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   763
	    &pass_to_next, &toa_len)) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   764
		optcom_err_ack(q, mp, t_error, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   765
		return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   766
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   767
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   768
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   769
	 * A validation phase of the input buffer is done. We have also
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   770
	 * obtained the length requirement and and other details about the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   771
	 * input and we liked input buffer so far.  We make another scan
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   772
	 * through the input now and generate the output necessary to complete
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   773
	 * the operation.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   774
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   775
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   776
	toa_mp = allocb_cred(toa_len, cr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   777
	if (!toa_mp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   778
		optcom_err_ack(q, mp, TSYSERR, ENOMEM);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   779
		return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   780
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   781
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   782
	first_mp = allocb(sizeof (opt_restart_t), BPRI_LO);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   783
	if (first_mp == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   784
		freeb(toa_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   785
		optcom_err_ack(q, mp, TSYSERR, ENOMEM);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   786
		return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   787
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   788
	first_mp->b_datap->db_type = M_CTL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   789
	or = (opt_restart_t *)first_mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   790
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   791
	 * Set initial values for generating output.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   792
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   793
	or->or_worst_status = T_SUCCESS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   794
	or->or_type = T_OPTMGMT_REQ;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   795
	or->or_private = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   796
	/* remaining fields fileed in do_options_second_pass */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   797
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   798
restart:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   799
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   800
	 * This routine makes another pass through the option buffer this
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   801
	 * time acting on the request based on "status" result in the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   802
	 * first pass. It also performs "expansion" of T_ALLOPT into
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   803
	 * all options of a certain level and acts on each for this request.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   804
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   805
	if ((t_error = do_options_second_pass(q, mp, toa_mp, cr, dbobjp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   806
	    first_mp, is_restart, &queued_status)) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   807
		freemsg(toa_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   808
		optcom_err_ack(q, mp, t_error, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   809
		return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   810
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   811
	if (queued_status) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   812
		/* Option will be restarted */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   813
		return (EINPROGRESS);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   814
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   815
	worst_status = or->or_worst_status;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   816
	/* Done with the first mp */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   817
	freeb(first_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   818
	toa_mp->b_cont = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   819
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   820
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   821
	 * Following code relies on the coincidence that T_optmgmt_req
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   822
	 * and T_optmgmt_ack are identical in binary representation
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   823
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   824
	toa = (struct T_optmgmt_ack *)toa_mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   825
	toa->OPT_length = (t_scalar_t)(toa_mp->b_wptr - (toa_mp->b_rptr +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   826
	    sizeof (struct T_optmgmt_ack)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   827
	toa->OPT_offset = (t_scalar_t)sizeof (struct T_optmgmt_ack);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   828
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   829
	toa->MGMT_flags = tor->MGMT_flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   830
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   831
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   832
	freemsg(mp);		/* free input mblk */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   833
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   834
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   835
	 * If there is atleast one option that requires a downstream
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   836
	 * forwarding and if it is possible, we forward the message
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   837
	 * downstream. Else we ack it.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   838
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   839
	if (pass_to_next && (q->q_next != NULL || dbobjp == &tcp_opt_obj)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   840
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   841
		 * We pass it down as T_OPTMGMT_REQ. This code relies
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   842
		 * on the happy coincidence that T_optmgmt_req and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   843
		 * T_optmgmt_ack are identical data structures
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   844
		 * at the binary representation level.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   845
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   846
		toa_mp->b_datap->db_type = M_PROTO;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   847
		toa->PRIM_type = T_OPTMGMT_REQ;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   848
		if (q->q_next != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   849
			putnext(q, toa_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   850
		else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   851
			ip_output(Q_TO_CONN(q), toa_mp, q, IP_WPUT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   852
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   853
		toa->PRIM_type = T_OPTMGMT_ACK;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   854
		toa_mp->b_datap->db_type = M_PCPROTO;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   855
		toa->MGMT_flags |= worst_status; /* XXX "worst" or "OR" TPI ? */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   856
		qreply(q, toa_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   857
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   858
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   859
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   860
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   861
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   862
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   863
 * Following routine makes a pass through option buffer in mp and performs the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   864
 * following tasks.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   865
 *	- estimate cumulative length needed for results
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   866
 *	- set "status" field based on permissions, option header check
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   867
 *	  etc.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   868
 *	- determine "pass_to_next" whether we need to send request to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   869
 *	  downstream module/driver.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   870
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   871
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   872
static t_scalar_t
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   873
process_topthdrs_first_pass(mblk_t *mp, cred_t *cr, optdb_obj_t *dbobjp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   874
    boolean_t *pass_to_nextp, size_t *toa_lenp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   875
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   876
	opdes_t	*opt_arr = dbobjp->odb_opt_des_arr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   877
	uint_t opt_arr_cnt = dbobjp->odb_opt_arr_cnt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   878
	boolean_t topmost_tpiprovider = dbobjp->odb_topmost_tpiprovider;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   879
	optlevel_t *valid_level_arr = dbobjp->odb_valid_levels_arr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   880
	uint_t valid_level_arr_cnt = dbobjp->odb_valid_levels_arr_cnt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   881
	struct T_opthdr *opt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   882
	struct T_opthdr *opt_start, *opt_end;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   883
	opdes_t	*optd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   884
	size_t allopt_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   885
	struct T_optmgmt_req *tor =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   886
	    (struct T_optmgmt_req *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   887
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   888
	*toa_lenp = sizeof (struct T_optmgmt_ack); /* initial value */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   889
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   890
	if ((opt_start = (struct T_opthdr *)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   891
	    mi_offset_param(mp, tor->OPT_offset, tor->OPT_length)) == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   892
		return (TBADOPT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   893
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   894
	if (!__TPI_TOPT_ISALIGNED(opt_start))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   895
		return (TBADOPT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   896
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   897
	opt_end = (struct T_opthdr *)((uchar_t *)opt_start + tor->OPT_length);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   898
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   899
	for (opt = opt_start; opt && (opt < opt_end);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   900
	    opt = _TPI_TOPT_NEXTHDR(opt_start, tor->OPT_length, opt)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   901
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   902
		 * Validate the option for length and alignment
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   903
		 * before accessing anything in it.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   904
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   905
		if (!(_TPI_TOPT_VALID(opt, opt_start, opt_end)))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   906
			return (TBADOPT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   907
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   908
		/* Find the option in the opt_arr. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   909
		if (opt->name != T_ALLOPT) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   910
			optd = opt_chk_lookup(opt->level, opt->name,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   911
			    opt_arr, opt_arr_cnt);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   912
			if (optd == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   913
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   914
				 * Option not found
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   915
				 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   916
				 * Verify if level is "valid" or not.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   917
				 * Note: This check is required by XTI
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   918
				 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   919
				 * TPI provider always initializes
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   920
				 * the "not supported" (or whatever) status
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   921
				 * for the options. Other levels leave status
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   922
				 * unchanged if they do not understand an
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   923
				 * option.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   924
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   925
				if (topmost_tpiprovider) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   926
					if (!opt_level_valid(opt->level,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   927
					    valid_level_arr,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   928
					    valid_level_arr_cnt))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   929
						return (TBADOPT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   930
					/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   931
					 * level is valid - initialize
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   932
					 * option as not supported
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   933
					 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   934
					opt->status = T_NOTSUPPORT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   935
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   936
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   937
				*toa_lenp += _TPI_ALIGN_TOPT(opt->len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   938
				continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   939
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   940
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   941
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   942
			 * Handle T_ALLOPT case as a special case.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   943
			 * Note: T_ALLOPT does not mean anything
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   944
			 * for T_CHECK operation.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   945
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   946
			allopt_len = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   947
			if (tor->MGMT_flags == T_CHECK ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   948
			    !topmost_tpiprovider ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   949
			    ((allopt_len = opt_level_allopts_lengths(opt->level,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   950
				opt_arr, opt_arr_cnt)) == 0)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   951
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   952
				 * This is confusing but correct !
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   953
				 * It is not valid to to use T_ALLOPT with
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   954
				 * T_CHECK flag.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   955
				 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   956
				 * T_ALLOPT is assumed "expanded" at the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   957
				 * topmost_tpiprovider level so it should not
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   958
				 * be there as an "option name" if this is not
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   959
				 * a topmost_tpiprovider call and we fail it.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   960
				 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   961
				 * opt_level_allopts_lengths() is used to verify
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   962
				 * that "level" associated with the T_ALLOPT is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   963
				 * supported.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   964
				 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   965
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   966
				opt->status = T_FAILURE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   967
				*toa_lenp += _TPI_ALIGN_TOPT(opt->len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   968
				continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   969
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   970
			ASSERT(allopt_len != 0); /* remove ? */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   971
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   972
			*toa_lenp += allopt_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   973
			opt->status = T_SUCCESS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   974
			/* XXX - always set T_ALLOPT 'pass_to_next' for now */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   975
			*pass_to_nextp = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   976
			continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   977
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   978
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   979
		 * Check if option wants to flow downstream
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   980
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   981
		if (optd->opdes_props & OP_PASSNEXT)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   982
			*pass_to_nextp = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   983
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   984
		/* Additional checks dependent on operation. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   985
		switch (tor->MGMT_flags) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   986
		case T_DEFAULT:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   987
		case T_CURRENT:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   988
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   989
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   990
			 * The opt_chk_lookup() routine call above approved of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   991
			 * this option so we can work on the status for it
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   992
			 * based on the permissions for the operation. (This
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   993
			 * can override any status for it set at higher levels)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   994
			 * We assume this override is OK since chkfn at this
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   995
			 * level approved of this option.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   996
			 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   997
			 * T_CURRENT semantics:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   998
			 * The read access is required. Else option
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   999
			 * status is T_NOTSUPPORT.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1000
			 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1001
			 * T_DEFAULT semantics:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1002
			 * Note: specification is not clear on this but we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1003
			 * interpret T_DEFAULT semantics such that access to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1004
			 * read value is required for access even the default
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1005
			 * value. Otherwise the option status is T_NOTSUPPORT.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1006
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1007
			if (!OA_READ_PERMISSION(optd, cr)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1008
				opt->status = T_NOTSUPPORT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1009
				*toa_lenp += _TPI_ALIGN_TOPT(opt->len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1010
				/* skip to next */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1011
				continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1012
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1013
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1014
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1015
			 * T_DEFAULT/T_CURRENT semantics:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1016
			 * We know that read access is set. If no other access
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1017
			 * is set, then status is T_READONLY.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1018
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1019
			if (OA_READONLY_PERMISSION(optd, cr))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1020
				opt->status = T_READONLY;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1021
			else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1022
				opt->status = T_SUCCESS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1023
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1024
			 * Option passes all checks. Make room for it in the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1025
			 * ack. Note: size stored in table does not include
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1026
			 * space for option header.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1027
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1028
			*toa_lenp += sizeof (struct T_opthdr) +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1029
			    _TPI_ALIGN_TOPT(optd->opdes_size);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1030
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1031
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1032
		case T_CHECK:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1033
		case T_NEGOTIATE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1034
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1035
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1036
			 * T_NEGOTIATE semantics:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1037
			 * If for fixed length option value on input is not the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1038
			 * same as value supplied, then status is T_FAILURE.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1039
			 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1040
			 * T_CHECK semantics:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1041
			 * If value is supplied, semantics same as T_NEGOTIATE.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1042
			 * It is however ok not to supply a value with T_CHECK.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1043
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1044
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1045
			if (tor->MGMT_flags == T_NEGOTIATE ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1046
			    (opt->len != sizeof (struct T_opthdr))) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1047
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1048
				 * Implies "value" is specified in T_CHECK or
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1049
				 * it is a T_NEGOTIATE request.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1050
				 * Verify size.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1051
				 * Note: This can override anything about this
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1052
				 * option request done at a higher level.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1053
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1054
				if (!opt_length_ok(optd, opt)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1055
					/* bad size */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1056
					*toa_lenp += _TPI_ALIGN_TOPT(opt->len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1057
					opt->status = T_FAILURE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1058
					continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1059
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1060
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1061
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1062
			 * The opt_chk_lookup()  routine above() approved of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1063
			 * this option so we can work on the status for it based
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1064
			 * on the permissions for the operation. (This can
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1065
			 * override anything set at a higher level).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1066
			 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1067
			 * T_CHECK/T_NEGOTIATE semantics:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1068
			 * Set status to T_READONLY if read is the only access
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1069
			 * permitted
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1070
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1071
			if (OA_READONLY_PERMISSION(optd, cr)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1072
				opt->status = T_READONLY;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1073
				*toa_lenp += _TPI_ALIGN_TOPT(opt->len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1074
				/* skip to next */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1075
				continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1076
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1077
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1078
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1079
			 * T_CHECK/T_NEGOTIATE semantics:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1080
			 * If write (or execute) access is not set, then status
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1081
			 * is T_NOTSUPPORT.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1082
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1083
			if (!OA_WRITE_OR_EXECUTE(optd, cr)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1084
				opt->status = T_NOTSUPPORT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1085
				*toa_lenp += _TPI_ALIGN_TOPT(opt->len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1086
				/* skip to next option */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1087
				continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1088
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1089
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1090
			 * Option passes all checks. Make room for it in the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1091
			 * ack and set success in status.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1092
			 * Note: size stored in table does not include header
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1093
			 * length.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1094
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1095
			opt->status = T_SUCCESS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1096
			*toa_lenp += sizeof (struct T_opthdr) +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1097
			    _TPI_ALIGN_TOPT(optd->opdes_size);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1098
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1099
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1100
		default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1101
			return (TBADFLAG);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1102
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1103
	} /* for loop scanning input buffer */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1104
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1105
	return (0);		/* OK return */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1106
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1107
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1108
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1109
 * This routine makes another pass through the option buffer this
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1110
 * time acting on the request based on "status" result in the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1111
 * first pass. It also performs "expansion" of T_ALLOPT into
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1112
 * all options of a certain level and acts on each for this request.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1113
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1114
static t_scalar_t
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1115
do_options_second_pass(queue_t *q, mblk_t *reqmp, mblk_t *ack_mp, cred_t *cr,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1116
    optdb_obj_t *dbobjp, mblk_t *first_mp, boolean_t is_restart,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1117
    boolean_t *queued_statusp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1118
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1119
	boolean_t topmost_tpiprovider = dbobjp->odb_topmost_tpiprovider;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1120
	int failed_option;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1121
	struct T_opthdr *opt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1122
	struct T_opthdr *opt_start, *opt_end, *restart_opt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1123
	uchar_t *optr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1124
	uint_t optset_context;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1125
	struct T_optmgmt_req *tor = (struct T_optmgmt_req *)reqmp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1126
	opt_restart_t	*or;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1127
	t_uscalar_t	*worst_statusp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1128
	int	err;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1129
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1130
	*queued_statusp = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1131
	or = (opt_restart_t *)first_mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1132
	worst_statusp = &or->or_worst_status;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1133
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1134
	optr = (uchar_t *)ack_mp->b_rptr +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1135
	    sizeof (struct T_optmgmt_ack); /* assumed int32_t aligned */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1136
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1137
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1138
	 * Set initial values for scanning input
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1139
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1140
	if (is_restart) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1141
		opt_start = (struct T_opthdr *)or->or_start;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1142
		opt_end = (struct T_opthdr *)or->or_end;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1143
		restart_opt = (struct T_opthdr *)or->or_ropt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1144
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1145
		opt_start = (struct T_opthdr *)mi_offset_param(reqmp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1146
		    tor->OPT_offset, tor->OPT_length);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1147
		if (opt_start == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1148
			return (TBADOPT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1149
		opt_end = (struct T_opthdr *)((uchar_t *)opt_start +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1150
		    tor->OPT_length);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1151
		or->or_start = (struct opthdr *)opt_start;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1152
		or->or_end = (struct opthdr *)opt_end;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1153
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1154
		 * construct the mp chain, in case the setfn needs to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1155
		 * queue this and restart option processing later on.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1156
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1157
		first_mp->b_cont = ack_mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1158
		ack_mp->b_cont = reqmp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1159
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1160
	ASSERT(__TPI_TOPT_ISALIGNED(opt_start)); /* verified in first pass */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1161
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1162
	for (opt = is_restart ? restart_opt : opt_start;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1163
	    opt && (opt < opt_end);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1164
	    opt = _TPI_TOPT_NEXTHDR(opt_start, tor->OPT_length, opt)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1165
		or->or_ropt = (struct opthdr *)opt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1166
		/* verified in first pass */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1167
		ASSERT(_TPI_TOPT_VALID(opt, opt_start, opt_end));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1168
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1169
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1170
		 * If the first pass in process_topthdrs_first_pass()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1171
		 * has marked the option as a failure case for the MGMT_flags
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1172
		 * semantics then there is not much to do.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1173
		 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1174
		 * Note: For all practical purposes, T_READONLY status is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1175
		 * a "success" for T_DEFAULT/T_CURRENT and "failure" for
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1176
		 * T_CHECK/T_NEGOTIATE
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1177
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1178
		failed_option =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1179
		    (opt->status == T_NOTSUPPORT) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1180
		    (opt->status == T_FAILURE) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1181
		    ((tor->MGMT_flags & (T_NEGOTIATE|T_CHECK)) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1182
			(opt->status == T_READONLY));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1183
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1184
		if (failed_option) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1185
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1186
			 * According to T_DEFAULT/T_CURRENT semantics, the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1187
			 * input values, even if present, are to be ignored.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1188
			 * Note: Specification is not clear on this, but we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1189
			 * interpret that even though we ignore the values, we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1190
			 * can return them as is. So we process them similar to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1191
			 * T_CHECK/T_NEGOTIATE case which has the semantics to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1192
			 * return the values as is. XXX If interpretation is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1193
			 * ever determined incorrect fill in appropriate code
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1194
			 * here to treat T_DEFAULT/T_CURRENT differently.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1195
			 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1196
			 * According to T_CHECK/T_NEGOTIATE semantics,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1197
			 * in the case of T_NOTSUPPORT/T_FAILURE/T_READONLY,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1198
			 * the semantics are to return the "value" part of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1199
			 * option untouched. So here we copy the option
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1200
			 * head including value part if any to output.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1201
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1202
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1203
			bcopy(opt, optr, opt->len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1204
			optr += _TPI_ALIGN_TOPT(opt->len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1205
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1206
			*worst_statusp = get_worst_status(opt->status,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1207
			    *worst_statusp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1208
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1209
			/* skip to process next option in buffer */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1210
			continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1211
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1212
		} /* end if "failed option" */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1213
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1214
		 * The status is T_SUCCESS or T_READONLY
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1215
		 * We process the value part here
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1216
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1217
		ASSERT(opt->status == T_SUCCESS || opt->status == T_READONLY);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1218
		switch (tor->MGMT_flags) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1219
		case T_DEFAULT:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1220
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1221
			 * We fill default value from table or protocol specific
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1222
			 * function. If this call fails, we pass input through.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1223
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1224
			if (do_opt_default(q, opt, &optr, worst_statusp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1225
			    cr, dbobjp) < 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1226
				/* fail or pass transparently */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1227
				if (topmost_tpiprovider)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1228
					opt->status = T_FAILURE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1229
				bcopy(opt, optr, opt->len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1230
				optr += _TPI_ALIGN_TOPT(opt->len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1231
				*worst_statusp = get_worst_status(opt->status,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1232
				    *worst_statusp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1233
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1234
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1235
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1236
		case T_CURRENT:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1237
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1238
			do_opt_current(q, opt, &optr, worst_statusp, cr,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1239
			    dbobjp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1240
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1241
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1242
		case T_CHECK:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1243
		case T_NEGOTIATE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1244
			if (tor->MGMT_flags == T_CHECK)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1245
				optset_context = SETFN_OPTCOM_CHECKONLY;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1246
			else	/* T_NEGOTIATE */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1247
				optset_context = SETFN_OPTCOM_NEGOTIATE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1248
			err = do_opt_check_or_negotiate(q, opt, optset_context,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1249
			    &optr, worst_statusp, cr, dbobjp, first_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1250
			if (err == EINPROGRESS) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1251
				*queued_statusp = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1252
				return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1253
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1254
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1255
		default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1256
			return (TBADFLAG);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1257
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1258
	} /* end for loop scanning option buffer */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1259
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1260
	ack_mp->b_wptr = optr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1261
	ASSERT(ack_mp->b_wptr <= ack_mp->b_datap->db_lim);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1262
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1263
	return (0);		/* OK return */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1264
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1265
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1266
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1267
static t_uscalar_t
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1268
get_worst_status(t_uscalar_t status, t_uscalar_t current_worst_status)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1269
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1270
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1271
	 * Return the "worst" among the arguments "status" and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1272
	 * "current_worst_status".
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1273
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1274
	 * Note: Tracking "worst_status" can be made a bit simpler
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1275
	 * if we use the property that status codes are bitwise
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1276
	 * distinct.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1277
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1278
	 * The pecking order is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1279
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1280
	 * T_SUCCESS ..... best
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1281
	 * T_PARTSUCCESS
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1282
	 * T_FAILURE
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1283
	 * T_READONLY
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1284
	 * T_NOTSUPPORT... worst
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1285
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1286
	if (status == current_worst_status)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1287
		return (current_worst_status);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1288
	switch (current_worst_status) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1289
	case T_SUCCESS:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1290
		if (status == T_PARTSUCCESS)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1291
			return (T_PARTSUCCESS);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1292
		/* FALLTHROUGH */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1293
	case T_PARTSUCCESS:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1294
		if (status == T_FAILURE)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1295
			return (T_FAILURE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1296
		/* FALLTHROUGH */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1297
	case T_FAILURE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1298
		if (status == T_READONLY)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1299
			return (T_READONLY);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1300
		/* FALLTHROUGH */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1301
	case T_READONLY:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1302
		if (status == T_NOTSUPPORT)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1303
			return (T_NOTSUPPORT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1304
		/* FALLTHROUGH */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1305
	case T_NOTSUPPORT:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1306
	default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1307
		return (current_worst_status);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1308
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1309
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1310
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1311
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1312
do_opt_default(queue_t *q, struct T_opthdr *reqopt, uchar_t **resptrp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1313
    t_uscalar_t *worst_statusp, cred_t *cr, optdb_obj_t *dbobjp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1314
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1315
	pfi_t	deffn = dbobjp->odb_deffn;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1316
	opdes_t	*opt_arr = dbobjp->odb_opt_des_arr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1317
	uint_t opt_arr_cnt = dbobjp->odb_opt_arr_cnt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1318
	boolean_t topmost_tpiprovider = dbobjp->odb_topmost_tpiprovider;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1319
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1320
	struct T_opthdr *topth;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1321
	opdes_t *optd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1322
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1323
	if (reqopt->name != T_ALLOPT) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1324
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1325
		 * lookup the option in the table and fill default value
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1326
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1327
		optd = opt_chk_lookup(reqopt->level, reqopt->name,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1328
		    opt_arr, opt_arr_cnt);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1329
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1330
		if (optd == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1331
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1332
			 * not found - fail this one. Should not happen
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1333
			 * for topmost_tpiprovider as calling routine
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1334
			 * should have verified it.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1335
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1336
			ASSERT(!topmost_tpiprovider);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1337
			return (-1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1338
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1339
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1340
		topth = (struct T_opthdr *)(*resptrp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1341
		topth->level = reqopt->level;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1342
		topth->name = reqopt->name;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1343
		topth->status = reqopt->status;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1344
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1345
		*worst_statusp = get_worst_status(reqopt->status,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1346
		    *worst_statusp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1347
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1348
		if (optd->opdes_props & OP_NODEFAULT) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1349
			/* header only, no default "value" part */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1350
			topth->len = sizeof (struct T_opthdr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1351
			*resptrp += sizeof (struct T_opthdr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1352
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1353
			int deflen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1354
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1355
			if (optd->opdes_props & OP_DEF_FN) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1356
				deflen = (*deffn)(q, reqopt->level,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1357
				    reqopt->name, _TPI_TOPT_DATA(topth));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1358
				if (deflen >= 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1359
					topth->len = (t_uscalar_t)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1360
					    (sizeof (struct T_opthdr) + deflen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1361
				} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1362
					/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1363
					 * return error, this should 'pass
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1364
					 * through' the option and maybe some
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1365
					 * other level will fill it in or
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1366
					 * already did.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1367
					 * (No change in 'resptrp' upto here)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1368
					 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1369
					return (-1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1370
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1371
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1372
				/* fill length and value part */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1373
				switch (optd->opdes_size) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1374
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1375
				 * Since options are guaranteed aligned only
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1376
				 * on a 4 byte boundary (t_scalar_t) any
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1377
				 * option that is greater in size will default
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1378
				 * to the bcopy below
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1379
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1380
				case sizeof (int32_t):
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1381
					*(int32_t *)_TPI_TOPT_DATA(topth) =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1382
					    (int32_t)optd->opdes_default;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1383
					break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1384
				case sizeof (int16_t):
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1385
					*(int16_t *)_TPI_TOPT_DATA(topth) =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1386
					    (int16_t)optd->opdes_default;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1387
					break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1388
				case sizeof (int8_t):
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1389
					*(int8_t *)_TPI_TOPT_DATA(topth) =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1390
					    (int8_t)optd->opdes_default;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1391
					break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1392
				default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1393
					/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1394
					 * other length but still assume
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1395
					 * fixed - use bcopy
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1396
					 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1397
					bcopy(optd->opdes_defbuf,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1398
					    _TPI_TOPT_DATA(topth),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1399
					    optd->opdes_size);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1400
					break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1401
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1402
				topth->len = (t_uscalar_t)(optd->opdes_size +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1403
				    sizeof (struct T_opthdr));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1404
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1405
			*resptrp += _TPI_ALIGN_TOPT(topth->len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1406
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1407
		return (0);	/* OK return */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1408
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1409
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1410
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1411
	 * T_ALLOPT processing
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1412
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1413
	 * lookup and stuff default values of all the options of the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1414
	 * level specified
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1415
	 * Note: This expansion of T_ALLOPT should happen in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1416
	 * a topmost_tpiprovider.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1417
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1418
	ASSERT(topmost_tpiprovider);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1419
	for (optd = opt_arr; optd < &opt_arr[opt_arr_cnt]; optd++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1420
		if (reqopt->level != optd->opdes_level)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1421
			continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1422
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1423
		 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1424
		 * T_DEFAULT semantics:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1425
		 * XXX: we interpret T_DEFAULT semantics such that access to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1426
		 * read value is required for access even the default value.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1427
		 * Else option is ignored for T_ALLOPT request.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1428
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1429
		if (!OA_READ_PERMISSION(optd, cr))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1430
			/* skip this one */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1431
			continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1432
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1433
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1434
		 * Found option of same level as T_ALLOPT request
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1435
		 * that we can return.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1436
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1437
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1438
		topth = (struct T_opthdr *)(*resptrp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1439
		topth->level = optd->opdes_level;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1440
		topth->name = optd->opdes_name;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1441
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1442
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1443
		 * T_DEFAULT semantics:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1444
		 * We know that read access is set. If no other access is set,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1445
		 * then status is T_READONLY
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1446
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1447
		if (OA_READONLY_PERMISSION(optd, cr)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1448
			topth->status = T_READONLY;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1449
			*worst_statusp = get_worst_status(T_READONLY,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1450
			    *worst_statusp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1451
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1452
			topth->status = T_SUCCESS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1453
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1454
			 * Note: *worst_statusp has to be T_SUCCESS or
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1455
			 * worse so no need to adjust
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1456
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1457
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1458
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1459
		if (optd->opdes_props & OP_NODEFAULT) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1460
			/* header only, no value part */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1461
			topth->len = sizeof (struct T_opthdr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1462
			*resptrp += sizeof (struct T_opthdr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1463
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1464
			int deflen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1465
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1466
			if (optd->opdes_props & OP_DEF_FN) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1467
				deflen = (*deffn)(q, reqopt->level,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1468
				    reqopt->name, _TPI_TOPT_DATA(topth));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1469
				if (deflen >= 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1470
					topth->len = (t_uscalar_t)(deflen +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1471
					    sizeof (struct T_opthdr));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1472
				} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1473
					/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1474
					 * deffn failed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1475
					 * return just the header as T_ALLOPT
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1476
					 * expansion.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1477
					 * Some other level deffn may
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1478
					 * supply value part.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1479
					 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1480
					topth->len = sizeof (struct T_opthdr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1481
					topth->status = T_FAILURE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1482
					*worst_statusp =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1483
					    get_worst_status(T_FAILURE,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1484
						*worst_statusp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1485
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1486
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1487
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1488
				 * fill length and value part from
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1489
				 * table
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1490
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1491
				switch (optd->opdes_size) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1492
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1493
				 * Since options are guaranteed aligned only
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1494
				 * on a 4 byte boundary (t_scalar_t) any
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1495
				 * option that is greater in size will default
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1496
				 * to the bcopy below
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1497
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1498
				case sizeof (int32_t):
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1499
					*(int32_t *)_TPI_TOPT_DATA(topth) =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1500
					    (int32_t)optd->opdes_default;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1501
					break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1502
				case sizeof (int16_t):
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1503
					*(int16_t *)_TPI_TOPT_DATA(topth) =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1504
					    (int16_t)optd->opdes_default;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1505
					break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1506
				case sizeof (int8_t):
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1507
					*(int8_t *)_TPI_TOPT_DATA(topth) =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1508
					    (int8_t)optd->opdes_default;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1509
					break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1510
				default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1511
					/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1512
					 * other length but still assume
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1513
					 * fixed - use bcopy
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1514
					 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1515
					bcopy(optd->opdes_defbuf,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1516
					    _TPI_TOPT_DATA(topth),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1517
					    optd->opdes_size);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1518
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1519
				topth->len = (t_uscalar_t)(optd->opdes_size +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1520
				    sizeof (struct T_opthdr));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1521
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1522
			*resptrp += _TPI_ALIGN_TOPT(topth->len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1523
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1524
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1525
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1526
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1527
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1528
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1529
do_opt_current(queue_t *q, struct T_opthdr *reqopt, uchar_t **resptrp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1530
    t_uscalar_t *worst_statusp, cred_t *cr, optdb_obj_t *dbobjp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1531
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1532
	pfi_t	getfn = dbobjp->odb_getfn;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1533
	opdes_t	*opt_arr = dbobjp->odb_opt_des_arr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1534
	uint_t opt_arr_cnt = dbobjp->odb_opt_arr_cnt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1535
	boolean_t topmost_tpiprovider = dbobjp->odb_topmost_tpiprovider;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1536
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1537
	struct T_opthdr *topth;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1538
	opdes_t *optd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1539
	int optlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1540
	uchar_t *initptr = *resptrp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1541
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1542
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1543
	 * We call getfn to get the current value of an option. The call may
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1544
	 * fail in which case we copy the values from the input buffer. Maybe
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1545
	 * something downstream will fill it in or something upstream did.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1546
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1547
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1548
	if (reqopt->name != T_ALLOPT) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1549
		topth = (struct T_opthdr *)*resptrp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1550
		*resptrp += sizeof (struct T_opthdr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1551
		optlen = (*getfn)(q, reqopt->level, reqopt->name, *resptrp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1552
		if (optlen >= 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1553
			topth->len = (t_uscalar_t)(optlen +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1554
			    sizeof (struct T_opthdr));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1555
			topth->level = reqopt->level;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1556
			topth->name = reqopt->name;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1557
			topth->status = reqopt->status;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1558
			*resptrp += _TPI_ALIGN_TOPT(optlen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1559
			*worst_statusp = get_worst_status(topth->status,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1560
			    *worst_statusp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1561
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1562
			/* failed - reset "*resptrp" pointer */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1563
			*resptrp -= sizeof (struct T_opthdr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1564
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1565
	} else {		/* T_ALLOPT processing */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1566
		ASSERT(topmost_tpiprovider == B_TRUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1567
		/* scan and get all options */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1568
		for (optd = opt_arr; optd < &opt_arr[opt_arr_cnt]; optd++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1569
			/* skip other levels */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1570
			if (reqopt->level != optd->opdes_level)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1571
				continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1572
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1573
			if (!OA_READ_PERMISSION(optd, cr))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1574
				/* skip this one */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1575
				continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1576
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1577
			topth = (struct T_opthdr *)*resptrp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1578
			*resptrp += sizeof (struct T_opthdr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1579
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1580
			/* get option of this level */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1581
			optlen = (*getfn)(q, reqopt->level, optd->opdes_name,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1582
			    *resptrp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1583
			if (optlen >= 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1584
				/* success */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1585
				topth->len = (t_uscalar_t)(optlen +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1586
				    sizeof (struct T_opthdr));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1587
				topth->level = reqopt->level;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1588
				topth->name = optd->opdes_name;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1589
				if (OA_READONLY_PERMISSION(optd, cr))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1590
					topth->status = T_READONLY;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1591
				else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1592
					topth->status = T_SUCCESS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1593
				*resptrp += _TPI_ALIGN_TOPT(optlen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1594
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1595
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1596
				 * failed, return as T_FAILURE and null value
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1597
				 * part. Maybe something downstream will
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1598
				 * handle this one and fill in a value. Here
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1599
				 * it is just part of T_ALLOPT expansion.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1600
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1601
				topth->len = sizeof (struct T_opthdr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1602
				topth->level = reqopt->level;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1603
				topth->name = optd->opdes_name;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1604
				topth->status = T_FAILURE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1605
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1606
			*worst_statusp = get_worst_status(topth->status,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1607
			    *worst_statusp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1608
		} /* end for loop */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1609
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1610
	if (*resptrp == initptr) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1611
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1612
		 * getfn failed and does not want to handle this option. Maybe
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1613
		 * something downstream will or something upstream did. (If
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1614
		 * topmost_tpiprovider, initialize "status" to failure which
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1615
		 * can possibly change downstream). Copy the input "as is" from
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1616
		 * input option buffer if any to maintain transparency.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1617
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1618
		if (topmost_tpiprovider)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1619
			reqopt->status = T_FAILURE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1620
		bcopy(reqopt, *resptrp, reqopt->len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1621
		*resptrp += _TPI_ALIGN_TOPT(reqopt->len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1622
		*worst_statusp = get_worst_status(reqopt->status,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1623
		    *worst_statusp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1624
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1625
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1626
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1627
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1628
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1629
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1630
do_opt_check_or_negotiate(queue_t *q, struct T_opthdr *reqopt,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1631
    uint_t optset_context, uchar_t **resptrp, t_uscalar_t *worst_statusp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1632
    cred_t *cr, optdb_obj_t *dbobjp, mblk_t *first_mp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1633
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1634
	pfi_t	deffn = dbobjp->odb_deffn;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1635
	opt_set_fn setfn = dbobjp->odb_setfn;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1636
	opdes_t	*opt_arr = dbobjp->odb_opt_des_arr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1637
	uint_t opt_arr_cnt = dbobjp->odb_opt_arr_cnt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1638
	boolean_t topmost_tpiprovider = dbobjp->odb_topmost_tpiprovider;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1639
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1640
	struct T_opthdr *topth;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1641
	opdes_t *optd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1642
	int error;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1643
	t_uscalar_t optlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1644
	t_scalar_t optsize;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1645
	uchar_t *initptr = *resptrp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1646
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1647
	ASSERT(reqopt->status == T_SUCCESS);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1648
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1649
	if (reqopt->name != T_ALLOPT) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1650
		topth = (struct T_opthdr *)*resptrp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1651
		*resptrp += sizeof (struct T_opthdr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1652
		error = (*setfn)(q, optset_context, reqopt->level, reqopt->name,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1653
		    reqopt->len - sizeof (struct T_opthdr),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1654
		    _TPI_TOPT_DATA(reqopt), &optlen, _TPI_TOPT_DATA(topth),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1655
		    NULL, cr, first_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1656
		if (error) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1657
			/* failed - reset "*resptrp" */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1658
			*resptrp -= sizeof (struct T_opthdr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1659
			if (error == EINPROGRESS)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1660
				return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1661
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1662
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1663
			 * success - "value" already filled in setfn()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1664
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1665
			topth->len = (t_uscalar_t)(optlen +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1666
			    sizeof (struct T_opthdr));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1667
			topth->level = reqopt->level;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1668
			topth->name = reqopt->name;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1669
			topth->status = reqopt->status;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1670
			*resptrp += _TPI_ALIGN_TOPT(optlen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1671
			*worst_statusp = get_worst_status(topth->status,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1672
			    *worst_statusp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1673
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1674
	} else {		/* T_ALLOPT processing */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1675
		/* only for T_NEGOTIATE case */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1676
		ASSERT(optset_context == SETFN_OPTCOM_NEGOTIATE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1677
		ASSERT(topmost_tpiprovider == B_TRUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1678
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1679
		/* scan and set all options to default value */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1680
		for (optd = opt_arr; optd < &opt_arr[opt_arr_cnt]; optd++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1681
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1682
			/* skip other levels */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1683
			if (reqopt->level != optd->opdes_level)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1684
				continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1685
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1686
			if (OA_EXECUTE_PERMISSION(optd, cr) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1687
			    OA_NO_PERMISSION(optd, cr)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1688
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1689
				 * skip this one too. Does not make sense to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1690
				 * set anything to default value for "execute"
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1691
				 * options.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1692
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1693
				continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1694
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1695
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1696
			if (OA_READONLY_PERMISSION(optd, cr)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1697
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1698
				 * Return with T_READONLY status (and no value
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1699
				 * part). Note: spec is not clear but
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1700
				 * XTI test suite needs this.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1701
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1702
				topth = (struct T_opthdr *)*resptrp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1703
				topth->len = sizeof (struct T_opthdr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1704
				*resptrp += topth->len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1705
				topth->level = reqopt->level;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1706
				topth->name = optd->opdes_name;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1707
				topth->status = T_READONLY;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1708
				*worst_statusp = get_worst_status(topth->status,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1709
				    *worst_statusp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1710
				continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1711
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1712
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1713
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1714
			 * It is not read only or execute type
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1715
			 * the it must have write permission
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1716
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1717
			ASSERT(OA_WRITE_PERMISSION(optd, cr));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1718
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1719
			topth = (struct T_opthdr *)*resptrp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1720
			*resptrp += sizeof (struct T_opthdr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1721
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1722
			topth->len = sizeof (struct T_opthdr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1723
			topth->level = reqopt->level;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1724
			topth->name = optd->opdes_name;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1725
			if (optd->opdes_props & OP_NODEFAULT) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1726
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1727
				 * Option of "no default value" so it does not
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1728
				 * make sense to try to set it. We just return
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1729
				 * header with status of T_SUCCESS
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1730
				 * XXX should this be failure ?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1731
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1732
				topth->status = T_SUCCESS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1733
				continue; /* skip setting */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1734
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1735
			if (optd->opdes_props & OP_DEF_FN) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1736
				if ((optd->opdes_props & OP_VARLEN) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1737
				    ((optsize = (*deffn)(q, reqopt->level,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1738
					optd->opdes_name,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1739
					(uchar_t *)optd->opdes_defbuf)) < 0)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1740
					/* XXX - skip these too */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1741
					topth->status = T_SUCCESS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1742
					continue; /* skip setting */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1743
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1744
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1745
				optsize = optd->opdes_size;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1746
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1747
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1748
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1749
			/* set option of this level */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1750
			error = (*setfn)(q, SETFN_OPTCOM_NEGOTIATE,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1751
			    reqopt->level, optd->opdes_name, optsize,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1752
			    (uchar_t *)optd->opdes_defbuf, &optlen,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1753
			    _TPI_TOPT_DATA(topth), NULL, cr, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1754
			if (error) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1755
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1756
				 * failed, return as T_FAILURE and null value
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1757
				 * part. Maybe something downstream will
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1758
				 * handle this one and fill in a value. Here
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1759
				 * it is just part of T_ALLOPT expansion.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1760
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1761
				topth->status = T_FAILURE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1762
				*worst_statusp = get_worst_status(topth->status,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1763
				    *worst_statusp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1764
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1765
				/* success */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1766
				topth->len += optlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1767
				topth->status = T_SUCCESS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1768
				*resptrp += _TPI_ALIGN_TOPT(optlen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1769
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1770
		} /* end for loop */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1771
		/* END T_ALLOPT */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1772
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1773
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1774
	if (*resptrp == initptr) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1775
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1776
		 * setfn failed and does not want to handle this option. Maybe
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1777
		 * something downstream will or something upstream
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1778
		 * did. Copy the input as is from input option buffer if any to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1779
		 * maintain transparency (maybe something at a level above
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1780
		 * did something.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1781
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1782
		if (topmost_tpiprovider)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1783
			reqopt->status = T_FAILURE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1784
		bcopy(reqopt, *resptrp, reqopt->len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1785
		*resptrp += _TPI_ALIGN_TOPT(reqopt->len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1786
		*worst_statusp = get_worst_status(reqopt->status,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1787
		    *worst_statusp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1788
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1789
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1790
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1791
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1792
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1793
 * The following routines process options buffer passed with
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1794
 * T_CONN_REQ, T_CONN_RES and T_UNITDATA_REQ.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1795
 * This routine does the consistency check applied to the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1796
 * sanity of formatting of multiple options packed in the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1797
 * buffer.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1798
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1799
 * XTI brain damage alert:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1800
 * XTI interface adopts the notion of an option being an
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1801
 * "absolute requirement" from OSI transport service (but applies
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1802
 * it to all transports including Internet transports).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1803
 * The main effect of that is action on failure to "negotiate" a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1804
 * requested option to the exact requested value
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1805
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1806
 *          - if the option is an "absolute requirement", the primitive
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1807
 *            is aborted (e.g T_DISCON_REQ or T_UDERR generated)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1808
 *          - if the option is NOT and "absolute requirement" it can
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1809
 *            just be ignored.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1810
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1811
 * We would not support "negotiating" of options on connection
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1812
 * primitives for Internet transports. However just in case we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1813
 * forced to in order to pass strange test suites, the design here
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1814
 * tries to support these notions.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1815
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1816
 * tpi_optcom_buf(q, mp, opt_lenp, opt_offset, cred, dbobjp, thisdg_attrs,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1817
 *	*is_absreq_failurep)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1818
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1819
 * - Verify the option buffer, if formatted badly, return error 1
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1820
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1821
 * - If it is a "permissions" failure (read-only), return error 2
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1822
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1823
 * - Else, process the option "in place", the following can happen,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1824
 *	     - if a "privileged" option, mark it as "ignored".
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1825
 *	     - if "not supported", mark "ignored"
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1826
 *	     - if "supported" attempt negotiation and fill result in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1827
 *	       the outcome
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1828
 *			- if "absolute requirement", set "*is_absreq_failurep"
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1829
 *			- if NOT an "absolute requirement", then our
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1830
 *			  interpretation is to mark is at ignored if
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1831
 *			  negotiation fails (Spec allows partial success
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1832
 *			  as in OSI protocols but not failure)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1833
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1834
 *   Then delete "ignored" options from option buffer and return success.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1835
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1836
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1837
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1838
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1839
tpi_optcom_buf(queue_t *q, mblk_t *mp, t_scalar_t *opt_lenp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1840
    t_scalar_t opt_offset, cred_t *cr, optdb_obj_t *dbobjp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1841
    void *thisdg_attrs, int *is_absreq_failurep)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1842
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1843
	opt_set_fn setfn = dbobjp->odb_setfn;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1844
	opdes_t *opt_arr = dbobjp->odb_opt_des_arr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1845
	uint_t opt_arr_cnt = dbobjp->odb_opt_arr_cnt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1846
	struct T_opthdr *opt, *opt_start, *opt_end;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1847
	mblk_t  *copy_mp_head;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1848
	uchar_t *optr, *init_optr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1849
	opdes_t *optd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1850
	uint_t optset_context;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1851
	t_uscalar_t olen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1852
	int error = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1853
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1854
	ASSERT((uchar_t *)opt_lenp > mp->b_rptr &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1855
	    (uchar_t *)opt_lenp < mp->b_wptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1856
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1857
	copy_mp_head = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1858
	*is_absreq_failurep = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1859
	switch (((union T_primitives *)mp->b_rptr)->type) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1860
	case T_CONN_REQ:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1861
	case T_CONN_RES:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1862
		optset_context = SETFN_CONN_NEGOTIATE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1863
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1864
	case T_UNITDATA_REQ:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1865
		optset_context = SETFN_UD_NEGOTIATE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1866
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1867
	default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1868
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1869
		 * should never get here, all possible TPI primitives
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1870
		 * where this can be called from should be accounted
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1871
		 * for in the cases above
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1872
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1873
		return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1874
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1875
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1876
	if ((opt_start = (struct T_opthdr *)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1877
	    mi_offset_param(mp, opt_offset, *opt_lenp)) == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1878
		error = ENOPROTOOPT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1879
		goto error_ret;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1880
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1881
	if (!__TPI_TOPT_ISALIGNED(opt_start)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1882
		error = ENOPROTOOPT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1883
		goto error_ret;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1884
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1885
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1886
	opt_end = (struct T_opthdr *)((uchar_t *)opt_start
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1887
	    + *opt_lenp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1888
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1889
	if ((copy_mp_head = copyb(mp)) == (mblk_t *)NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1890
		error = ENOMEM;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1891
		goto error_ret;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1892
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1893
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1894
	init_optr = optr = (uchar_t *)&copy_mp_head->b_rptr[opt_offset];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1895
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1896
	for (opt = opt_start; opt && (opt < opt_end);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1897
	    opt = _TPI_TOPT_NEXTHDR(opt_start, *opt_lenp, opt)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1898
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1899
		 * Validate the option for length and alignment
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1900
		 * before accessing anything in it
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1901
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1902
		if (!_TPI_TOPT_VALID(opt, opt_start, opt_end)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1903
			error = ENOPROTOOPT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1904
			goto error_ret;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1905
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1906
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1907
		/* Find the option in the opt_arr. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1908
		optd = opt_chk_lookup(opt->level, opt->name,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1909
		    opt_arr, opt_arr_cnt);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1910
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1911
		if (optd == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1912
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1913
			 * Option not found
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1914
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1915
			opt->status = T_NOTSUPPORT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1916
			continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1917
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1918
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1919
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1920
		 * Weird but as in XTI spec.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1921
		 * Sec 6.3.6 "Privileged and ReadOnly Options"
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1922
		 * Permission problems (e.g.readonly) fail with bad access
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1923
		 * BUT "privileged" option request from those NOT PRIVILEGED
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1924
		 * are to be merely "ignored".
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1925
		 * XXX Prevents "probing" of privileged options ?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1926
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1927
		if (OA_READONLY_PERMISSION(optd, cr)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1928
			error = EACCES;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1929
			goto error_ret;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1930
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1931
		if (OA_MATCHED_PRIV(optd, cr)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1932
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1933
			 * For privileged options, we DO perform
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1934
			 * access checks as is common sense
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1935
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1936
			if (!OA_WX_ANYPRIV(optd)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1937
				error = EACCES;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1938
				goto error_ret;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1939
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1940
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1941
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1942
			 * For non privileged, we fail instead following
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1943
			 * "ignore" semantics dictated by XTI spec for
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1944
			 * permissions problems.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1945
			 * Sec 6.3.6 "Privileged and ReadOnly Options"
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1946
			 * XXX Should we do "ignore" semantics ?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1947
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1948
			if (!OA_WX_NOPRIV(optd)) { /* nopriv */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1949
				opt->status = T_FAILURE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1950
				continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1951
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1952
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1953
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1954
		 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1955
		 * If the negotiation fails, for options that
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1956
		 * are "absolute requirement", it is a fatal error.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1957
		 * For options that are NOT "absolute requirements",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1958
		 * and the value fails to negotiate, the XTI spec
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1959
		 * only considers the possibility of partial success
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1960
		 * (T_PARTSUCCES - not likely for Internet protocols).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1961
		 * The spec is in denial about complete failure
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1962
		 * (T_FAILURE) to negotiate for options that are
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1963
		 * carried on T_CONN_REQ/T_CONN_RES/T_UNITDATA
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1964
		 * We interpret the T_FAILURE to negotiate an option
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1965
		 * that is NOT an absolute requirement that it is safe
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1966
		 * to ignore it.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1967
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1968
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1969
		/* verify length */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1970
		if (!opt_length_ok(optd, opt)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1971
			/* bad size */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1972
			if ((optd->opdes_props & OP_NOT_ABSREQ) == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1973
				/* option is absolute requirement */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1974
				*is_absreq_failurep = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1975
				error = EINVAL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1976
				goto error_ret;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1977
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1978
			opt->status = T_FAILURE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1979
			continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1980
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1981
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1982
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1983
		 * verified generic attributes. Now call set function.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1984
		 * Note: We assume the following to simplify code.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1985
		 * XXX If this is found not to be valid, this routine
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1986
		 * will need to be rewritten. At this point it would
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1987
		 * be premature to introduce more complexity than is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1988
		 * needed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1989
		 * Assumption: For variable length options, we assume
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1990
		 * that the value returned will be same or less length
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1991
		 * (size does not increase). This makes it OK to pass the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1992
		 * same space for output as it is on input.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1993
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1994
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1995
		error = (*setfn)(q, optset_context, opt->level, opt->name,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1996
		    opt->len - (t_uscalar_t)sizeof (struct T_opthdr),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1997
		    _TPI_TOPT_DATA(opt), &olen, _TPI_TOPT_DATA(opt),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1998
		    thisdg_attrs, cr, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1999
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2000
		if (olen > (int)(opt->len - sizeof (struct T_opthdr))) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2001
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2002
			 * Space on output more than space on input. Should
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2003
			 * not happen and we consider it a bug/error.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2004
			 * More of a restriction than an error in our
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2005
			 * implementation. Will see if we can live with this
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2006
			 * otherwise code will get more hairy with multiple
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2007
			 * passes.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2008
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2009
			error = EINVAL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2010
			goto error_ret;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2011
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2012
		if (error != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2013
			if ((optd->opdes_props & OP_NOT_ABSREQ) == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2014
				/* option is absolute requirement. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2015
				*is_absreq_failurep = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2016
				goto error_ret;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2017
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2018
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2019
			 * failed - but option "not an absolute
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2020
			 * requirement"
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2021
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2022
			opt->status = T_FAILURE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2023
			continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2024
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2025
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2026
		 * Fill in the only possible successful result
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2027
		 * (Note: TPI allows for T_PARTSUCCESS - partial
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2028
		 * sucess result code which is relevant in OSI world
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2029
		 * and not possible in Internet code)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2030
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2031
		opt->status = T_SUCCESS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2032
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2033
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2034
		 * Add T_SUCCESS result code options to the "output" options.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2035
		 * No T_FAILURES or T_NOTSUPPORT here as they are to be
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2036
		 * ignored.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2037
		 * This code assumes output option buffer will
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2038
		 * be <= input option buffer.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2039
		 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2040
		 * Copy option header+value
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2041
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2042
		bcopy(opt, optr, opt->len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2043
		optr +=  _TPI_ALIGN_TOPT(opt->len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2044
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2045
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2046
	 * Overwrite the input mblk option buffer now with the output
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2047
	 * and update length, and contents in original mbl
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2048
	 * (offset remains unchanged).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2049
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2050
	*opt_lenp = (t_scalar_t)(optr - init_optr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2051
	if (*opt_lenp > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2052
		bcopy(init_optr, opt_start, *opt_lenp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2053
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2054
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2055
error_ret:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2056
	if (copy_mp_head != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2057
		freeb(copy_mp_head);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2058
	return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2059
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2060
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2061
static opdes_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2062
opt_chk_lookup(t_uscalar_t level, t_uscalar_t name, opdes_t *opt_arr,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2063
    uint_t opt_arr_cnt)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2064
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2065
	opdes_t		*optd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2066
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2067
	for (optd = opt_arr; optd < &opt_arr[opt_arr_cnt];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2068
	    optd++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2069
		if (level == (uint_t)optd->opdes_level &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2070
		    name == (uint_t)optd->opdes_name)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2071
			return (optd);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2072
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2073
	return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2074
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2075
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2076
static boolean_t
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2077
opt_level_valid(t_uscalar_t level, optlevel_t *valid_level_arr,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2078
    uint_t valid_level_arr_cnt)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2079
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2080
	optlevel_t		*olp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2081
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2082
	for (olp = valid_level_arr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2083
	    olp < &valid_level_arr[valid_level_arr_cnt];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2084
	    olp++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2085
		if (level == (uint_t)(*olp))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2086
			return (B_TRUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2087
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2088
	return (B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2089
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2090
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2091
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2092
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2093
 * Compute largest possible size for an option buffer containing
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2094
 * all options in one buffer.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2095
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2096
 * XXX TBD, investigate use of opt_bloated_maxsize() to avoid
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2097
 *     wastefully large buffer allocation.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2098
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2099
static size_t
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2100
opt_level_allopts_lengths(t_uscalar_t level, opdes_t *opt_arr,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2101
    uint_t opt_arr_cnt)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2102
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2103
	opdes_t		*optd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2104
	size_t allopt_len = 0;	/* 0 implies no option at this level */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2105
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2106
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2107
	 * Scan opt_arr computing aggregate length
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2108
	 * requirement for storing values of all
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2109
	 * options.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2110
	 * Note: we do not filter for permissions
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2111
	 * etc. This will be >= the real aggregate
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2112
	 * length required (upper bound).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2113
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2114
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2115
	for (optd = opt_arr; optd < &opt_arr[opt_arr_cnt];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2116
	    optd++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2117
		if (level == optd->opdes_level) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2118
			allopt_len += sizeof (struct T_opthdr) +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2119
			    _TPI_ALIGN_TOPT(optd->opdes_size);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2120
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2121
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2122
	return (allopt_len);	/* 0 implies level not found */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2123
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2124
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2125
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2126
 * Compute largest possible size for an option buffer containing
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2127
 * all options in one buffer - a (theoretical?) worst case scenario
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2128
 * for certain cases.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2129
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2130
t_uscalar_t
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2131
optcom_max_optbuf_len(opdes_t *opt_arr, uint_t opt_arr_cnt)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2132
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2133
	t_uscalar_t max_optbuf_len = sizeof (struct T_info_ack);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2134
	opdes_t		*optd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2135
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2136
	for (optd = opt_arr; optd < &opt_arr[opt_arr_cnt]; optd++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2137
		max_optbuf_len += (t_uscalar_t)sizeof (struct T_opthdr) +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2138
		    (t_uscalar_t)_TPI_ALIGN_TOPT(optd->opdes_size);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2139
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2140
	return (max_optbuf_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2141
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2142
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2143
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2144
 * Compute largest possible size for OPT_size for a transport.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2145
 * Heuristic used is to add all but certain extremely large
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2146
 * size options; this is done by calling opt_bloated_maxsize().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2147
 * It affects user level allocations in TLI/XTI code using t_alloc()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2148
 * and other TLI/XTI implementation instance strucutures.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2149
 * The large size options excluded are presumed to be
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2150
 * never accessed through the (theoretical?) worst case code paths
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2151
 * through TLI/XTI as they are currently IPv6 specific options.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2152
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2153
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2154
t_uscalar_t
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2155
optcom_max_optsize(opdes_t *opt_arr, uint_t opt_arr_cnt)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2156
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2157
	t_uscalar_t max_optbuf_len = sizeof (struct T_info_ack);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2158
	opdes_t		*optd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2159
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2160
	for (optd = opt_arr; optd < &opt_arr[opt_arr_cnt]; optd++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2161
		if (!opt_bloated_maxsize(optd)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2162
			max_optbuf_len +=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2163
			    (t_uscalar_t)sizeof (struct T_opthdr) +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2164
			    (t_uscalar_t)_TPI_ALIGN_TOPT(optd->opdes_size);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2165
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2166
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2167
	return (max_optbuf_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2168
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2169
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2170
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2171
 * The theoretical model used in optcom_max_optsize() and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2172
 * opt_level_allopts_lengths() accounts for the worst case of all
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2173
 * possible options for the theoretical cases and results in wasteful
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2174
 * memory allocations for certain theoretically correct usage scenarios.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2175
 * In practice, the "features" they support are rarely, if ever,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2176
 * used and even then only by test suites for those features (VSU, VST).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2177
 * However, they result in large allocations due to the increased transport
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2178
 * T_INFO_ACK OPT_size field affecting t_alloc() users and TLI/XTI library
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2179
 * instance data structures for applications.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2180
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2181
 * The following routine opt_bloated_maxsize() supports a hack that avoids
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2182
 * paying the tax for the bloated options by excluding them and pretending
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2183
 * they don't exist for certain features without affecting features that
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2184
 * do use them.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2185
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2186
 * XXX Currently implemented only for optcom_max_optsize()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2187
 *     (to reduce risk late in release).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2188
 *     TBD for future, investigate use in optcom_level_allopts_lengths() and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2189
 *     all the instances of T_ALLOPT processing to exclude "bloated options".
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2190
 *     Will not affect VSU/VST tests as they do not test with IPPROTO_IPV6
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2191
 *     level options which are the only ones that fit the "bloated maxsize"
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2192
 *     option profile now.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2193
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2194
static boolean_t
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2195
opt_bloated_maxsize(opdes_t *optd)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2196
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2197
	if (optd->opdes_level != IPPROTO_IPV6)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2198
		return (B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2199
	switch (optd->opdes_name) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2200
	case IPV6_HOPOPTS:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2201
	case IPV6_DSTOPTS:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2202
	case IPV6_RTHDRDSTOPTS:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2203
	case IPV6_RTHDR:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2204
	case IPV6_PATHMTU:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2205
		return (B_TRUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2206
	default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2207
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2208
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2209
	return (B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2210
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2211
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2212
static boolean_t
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2213
opt_length_ok(opdes_t *optd, struct T_opthdr *opt)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2214
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2215
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2216
	 * Verify length.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2217
	 * Value specified should match length of fixed length option or be
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2218
	 * less than maxlen of variable length option.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2219
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2220
	if (optd->opdes_props & OP_VARLEN) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2221
		if (opt->len <= optd->opdes_size +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2222
		    (t_uscalar_t)sizeof (struct T_opthdr))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2223
			return (B_TRUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2224
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2225
		/* fixed length option */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2226
		if (opt->len == optd->opdes_size +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2227
		    (t_uscalar_t)sizeof (struct T_opthdr))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2228
			return (B_TRUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2229
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2230
	return (B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2231
}