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