4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
25 /* Copyright (c) 1990 Mentat Inc. */
28 * This file contains common code for handling Options Management requests.
31 #include <sys/types.h>
32 #include <sys/stream.h>
33 #include <sys/stropts.h>
34 #include <sys/strsubr.h>
35 #include <sys/errno.h>
36 #define _SUN_TPI_VERSION 2
37 #include <sys/tihdr.h>
38 #include <sys/socket.h>
39 #include <sys/socketvar.h>
41 #include <sys/debug.h> /* for ASSERT */
42 #include <sys/policy.h>
44 #include <inet/common.h>
47 #include <netinet/ip6.h>
49 #include <inet/mib2.h>
50 #include <netinet/in.h>
51 #include <inet/optcom.h>
53 #include <inet/optcom.h>
54 #include <inet/ipclassifier.h>
55 #include <inet/proto_set.h>
60 static t_scalar_t
process_topthdrs_first_pass(mblk_t
*, cred_t
*, optdb_obj_t
*,
62 static t_scalar_t
do_options_second_pass(queue_t
*q
, mblk_t
*reqmp
,
63 mblk_t
*ack_mp
, cred_t
*, optdb_obj_t
*dbobjp
,
64 t_uscalar_t
*worst_statusp
);
65 static t_uscalar_t
get_worst_status(t_uscalar_t
, t_uscalar_t
);
66 static int do_opt_default(queue_t
*, struct T_opthdr
*, uchar_t
**,
67 t_uscalar_t
*, cred_t
*, optdb_obj_t
*);
68 static void do_opt_current(queue_t
*, struct T_opthdr
*, uchar_t
**,
69 t_uscalar_t
*, cred_t
*cr
, optdb_obj_t
*);
70 static void do_opt_check_or_negotiate(queue_t
*q
, struct T_opthdr
*reqopt
,
71 uint_t optset_context
, uchar_t
**resptrp
, t_uscalar_t
*worst_statusp
,
72 cred_t
*, optdb_obj_t
*dbobjp
);
73 static boolean_t
opt_level_valid(t_uscalar_t
, optlevel_t
*, uint_t
);
74 static size_t opt_level_allopts_lengths(t_uscalar_t
, opdes_t
*, uint_t
);
75 static boolean_t
opt_length_ok(opdes_t
*, t_uscalar_t optlen
);
76 static t_uscalar_t
optcom_max_optbuf_len(opdes_t
*, uint_t
);
77 static boolean_t
opt_bloated_maxsize(opdes_t
*);
79 /* Common code for sending back a T_ERROR_ACK. */
81 optcom_err_ack(queue_t
*q
, mblk_t
*mp
, t_scalar_t t_error
, int sys_error
)
83 if ((mp
= mi_tpi_err_ack_alloc(mp
, t_error
, sys_error
)) != NULL
)
88 * The option management routines svr4_optcom_req() and tpi_optcom_req() use
89 * callback functions as arguments. Here is the expected interfaces
90 * assumed from the callback functions
93 * (1) deffn(q, optlevel, optname, optvalp)
95 * - Function only called when default value comes from protocol
96 * specific code and not the option database table (indicated by
97 * OP_DEF_FN property in option database.)
98 * - Error return is -1. Valid returns are >=0.
99 * - When valid, the return value represents the length used for storing
100 * the default value of the option.
101 * - Error return implies the called routine did not recognize this
102 * option. Something downstream could so input is left unchanged
105 * (2) getfn(q, optlevel, optname, optvalp)
107 * - Error return is -1. Valid returns are >=0.
108 * - When valid, the return value represents the length used for storing
109 * the actual value of the option.
110 * - Error return implies the called routine did not recognize this
111 * option. Something downstream could so input is left unchanged
114 * (3) setfn(q, optset_context, optlevel, optname, inlen, invalp,
115 * outlenp, outvalp, attrp, cr);
117 * - OK return is 0, Error code is returned as a non-zero argument.
118 * - If negative it is ignored by svr4_optcom_req(). If positive, error
119 * is returned. A negative return implies that option, while handled on
120 * this stack is not handled at this level and will be handled further
122 * - Both negative and positive errors are treats as errors in an
123 * identical manner by tpi_optcom_req(). The errors affect "status"
124 * field of each option's T_opthdr. If sucessfull, an appropriate sucess
125 * result is carried. If error, it instantiated to "failure" at the
126 * topmost level and left unchanged at other levels. (This "failure" can
127 * turn to a success at another level).
128 * - optset_context passed for tpi_optcom_req(). It is interpreted as:
129 * - SETFN_OPTCOM_CHECKONLY
130 * semantics are to pretend to set the value and report
131 * back if it would be successful.
132 * This is used with T_CHECK semantics in XTI
133 * - SETFN_OPTCOM_NEGOTIATE
134 * set the value. Call from option management primitive
135 * T_OPTMGMT_REQ when T_NEGOTIATE flags is used.
136 * - SETFN_UD_NEGOTIATE
137 * option request came riding on UNITDATA primitive most often
138 * has "this datagram" semantics to influence prpoerties
139 * affecting an outgoig datagram or associated with recived
141 * [ Note: XTI permits this use outside of "this datagram"
142 * semantics also and permits setting "management related"
143 * options in this context and its test suite enforces it ]
144 * - SETFN_CONN_NEGOTATE
145 * option request came riding on CONN_REQ/RES primitive and
146 * most often has "this connection" (negotiation during
147 * "connection estblishment") semantics.
148 * [ Note: XTI permits use of these outside of "this connection"
149 * semantics and permits "management related" options in this
150 * context and its test suite enforces it. ]
152 * - inlen, invalp is the option length,value requested to be set.
153 * - outlenp, outvalp represent return parameters which contain the
154 * value set and it might be different from one passed on input.
155 * - attrp points to a data structure that's used by v6 modules to
156 * store ancillary data options or sticky options.
157 * - cr points to the caller's credentials
158 * - the caller might pass same buffers for input and output and the
159 * routine should protect against this case by not updating output
160 * buffers until it is done referencing input buffers and any other
161 * issues (e.g. not use bcopy() if we do not trust what it does).
162 * - If option is not known, it returns error. We randomly pick EINVAL.
163 * It can however get called with options that are handled downstream
164 * opr upstream so for svr4_optcom_req(), it does not return error for
165 * negative return values.
170 * Upper Level Protocols call this routine when they receive
171 * a T_SVR4_OPTMGMT_REQ message. They supply callback functions
172 * for setting a new value for a single options, getting the
173 * current value for a single option, and checking for support
174 * of a single option. svr4_optcom_req validates the option management
175 * buffer passed in, and calls the appropriate routines to do the
177 * XXX Code below needs some restructuring after we have some more
178 * macros to support 'struct opthdr' in the headers.
181 svr4_optcom_req(queue_t
*q
, mblk_t
*mp
, cred_t
*cr
, optdb_obj_t
*dbobjp
)
183 pfi_t deffn
= dbobjp
->odb_deffn
;
184 pfi_t getfn
= dbobjp
->odb_getfn
;
185 opt_set_fn setfn
= dbobjp
->odb_setfn
;
186 opdes_t
*opt_arr
= dbobjp
->odb_opt_des_arr
;
187 uint_t opt_arr_cnt
= dbobjp
->odb_opt_arr_cnt
;
188 t_uscalar_t max_optbuf_len
;
191 struct opthdr
*next_opt
;
194 struct opthdr
*opt_end
;
195 struct opthdr
*opt_start
;
197 struct T_optmgmt_ack
*toa
;
198 struct T_optmgmt_req
*tor
;
201 tor
= (struct T_optmgmt_req
*)mp
->b_rptr
;
202 /* Verify message integrity. */
203 if (mp
->b_wptr
- mp
->b_rptr
< sizeof (struct T_optmgmt_req
))
205 /* Verify MGMT_flags legal */
206 switch (tor
->MGMT_flags
) {
211 /* OK - legal request flags */
214 optcom_err_ack(q
, mp
, TBADFLAG
, 0);
217 if (tor
->MGMT_flags
== T_DEFAULT
) {
218 /* Is it a request for default option settings? */
221 * Note: XXX TLI and TPI specification was unclear about
222 * semantics of T_DEFAULT and the following historical note
223 * and its interpretation is incorrect (it implies a request
224 * for default values of only the identified options not all.
225 * The semantics have been explained better in XTI spec.)
226 * However, we do not modify (comment or code) here to keep
228 * We can rethink this if it ever becomes an issue.
229 * ----historical comment start------
230 * As we understand it, the input buffer is meaningless
231 * so we ditch the message. A T_DEFAULT request is a
232 * request to obtain a buffer containing defaults for
233 * all supported options, so we allocate a maximum length
235 * ----historical comment end -------
237 /* T_DEFAULT not passed down */
239 max_optbuf_len
= optcom_max_optbuf_len(opt_arr
,
241 mp
= allocb(max_optbuf_len
, BPRI_MED
);
244 optcom_err_ack(q
, mp
, TSYSERR
, ENOMEM
);
248 /* Initialize the T_optmgmt_ack header. */
249 toa
= (struct T_optmgmt_ack
*)mp
->b_rptr
;
250 bzero((char *)toa
, max_optbuf_len
);
251 toa
->PRIM_type
= T_OPTMGMT_ACK
;
252 toa
->OPT_offset
= (t_scalar_t
)sizeof (struct T_optmgmt_ack
);
253 /* TODO: Is T_DEFAULT the right thing to put in MGMT_flags? */
254 toa
->MGMT_flags
= T_DEFAULT
;
256 /* Now walk the table of options passed in */
257 opt
= (struct opthdr
*)&toa
[1];
258 for (optd
= opt_arr
; optd
< &opt_arr
[opt_arr_cnt
]; optd
++) {
260 * All the options in the table of options passed
261 * in are by definition supported by the protocol
262 * calling this function.
264 if (!OA_READ_PERMISSION(optd
, cr
))
266 opt
->level
= optd
->opdes_level
;
267 opt
->name
= optd
->opdes_name
;
268 if (!(optd
->opdes_props
& OP_DEF_FN
) ||
269 ((len
= (*deffn
)(q
, opt
->level
,
270 opt
->name
, (uchar_t
*)&opt
[1])) < 0)) {
272 * Fill length and value from table.
274 * Default value not instantiated from function
275 * (or the protocol specific function failed it;
276 * In this interpretation of T_DEFAULT, this is
277 * the best we can do)
279 switch (optd
->opdes_size
) {
281 * Since options are guaranteed aligned only
282 * on a 4 byte boundary (t_scalar_t) any
283 * option that is greater in size will default
286 case sizeof (int32_t):
287 *(int32_t *)&opt
[1] =
288 (int32_t)optd
->opdes_default
;
290 case sizeof (int16_t):
291 *(int16_t *)&opt
[1] =
292 (int16_t)optd
->opdes_default
;
294 case sizeof (int8_t):
296 (int8_t)optd
->opdes_default
;
300 * other length but still assume
303 bcopy(optd
->opdes_defbuf
,
304 &opt
[1], optd
->opdes_size
);
307 opt
->len
= optd
->opdes_size
;
310 opt
->len
= (t_uscalar_t
)len
;
311 opt
= (struct opthdr
*)((char *)&opt
[1] +
312 _TPI_ALIGN_OPT(opt
->len
));
315 /* Now record the final length. */
316 toa
->OPT_length
= (t_scalar_t
)((char *)opt
- (char *)&toa
[1]);
317 mp
->b_wptr
= (uchar_t
*)opt
;
318 mp
->b_datap
->db_type
= M_PCPROTO
;
323 /* T_DEFAULT processing complete - no more T_DEFAULT */
326 * For T_NEGOTIATE, T_CURRENT, and T_CHECK requests, we make a
327 * pass through the input buffer validating the details and
328 * making sure each option is supported by the protocol.
330 if ((opt_start
= (struct opthdr
*)mi_offset_param(mp
,
331 tor
->OPT_offset
, tor
->OPT_length
)) == NULL
)
333 if (!__TPI_OPT_ISALIGNED(opt_start
))
336 opt_end
= (struct opthdr
*)((uchar_t
*)opt_start
+
339 for (opt
= opt_start
; opt
< opt_end
; opt
= next_opt
) {
341 * Verify we have room to reference the option header
342 * fields in the option buffer.
344 if ((uchar_t
*)opt
+ sizeof (struct opthdr
) >
348 * We now compute pointer to next option in buffer 'next_opt'
349 * The next_opt computation above below 'opt->len' initialized
350 * by application which cannot be trusted. The usual value
351 * too large will be captured by the loop termination condition
352 * above. We check for the following which it will miss.
353 * -pointer space wraparound arithmetic overflow
354 * -last option in buffer with 'opt->len' being too large
355 * (only reason 'next_opt' should equal or exceed
356 * 'opt_end' for last option is roundup unless length is
359 next_opt
= (struct opthdr
*)((uchar_t
*)&opt
[1] +
360 _TPI_ALIGN_OPT(opt
->len
));
362 if ((uchar_t
*)next_opt
< (uchar_t
*)&opt
[1] ||
363 ((next_opt
>= opt_end
) &&
364 (((uchar_t
*)next_opt
- (uchar_t
*)opt_end
) >=
369 if (opt
->name
== T_ALLOPT
)
372 error
= proto_opt_check(opt
->level
, opt
->name
, opt
->len
, NULL
,
373 opt_arr
, opt_arr_cnt
,
374 tor
->MGMT_flags
== T_NEGOTIATE
, tor
->MGMT_flags
== T_CHECK
,
377 optcom_err_ack(q
, mp
, -error
, 0);
379 } else if (error
> 0) {
380 optcom_err_ack(q
, mp
, TSYSERR
, error
);
383 } /* end for loop scanning option buffer */
385 /* Now complete the operation as required. */
386 switch (tor
->MGMT_flags
) {
389 * Historically used same as T_CURRENT (which was added to
390 * standard later). Code retained for compatibility.
395 * Allocate a maximum size reply. Perhaps we are supposed to
396 * assume that the input buffer includes space for the answers
397 * as well as the opthdrs, but we don't know that for sure.
398 * So, instead, we create a new output buffer, using the
399 * input buffer only as a list of options.
401 max_optbuf_len
= optcom_max_optbuf_len(opt_arr
,
403 mp1
= allocb_tmpl(max_optbuf_len
, mp
);
406 /* Initialize the header. */
407 mp1
->b_datap
->db_type
= M_PCPROTO
;
408 mp1
->b_wptr
= &mp1
->b_rptr
[sizeof (struct T_optmgmt_ack
)];
409 toa
= (struct T_optmgmt_ack
*)mp1
->b_rptr
;
410 toa
->OPT_offset
= (t_scalar_t
)sizeof (struct T_optmgmt_ack
);
411 toa
->MGMT_flags
= tor
->MGMT_flags
;
413 * Walk through the input buffer again, this time adding
414 * entries to the output buffer for each option requested.
415 * Note, sanity of option header, last option etc, verified
418 opt1
= (struct opthdr
*)&toa
[1];
420 for (opt
= opt_start
; opt
< opt_end
; opt
= next_opt
) {
422 next_opt
= (struct opthdr
*)((uchar_t
*)&opt
[1] +
423 _TPI_ALIGN_OPT(opt
->len
));
425 opt1
->name
= opt
->name
;
426 opt1
->level
= opt
->level
;
427 len
= (*getfn
)(q
, opt
->level
,
428 opt
->name
, (uchar_t
*)&opt1
[1]);
430 * Failure means option is not recognized. Copy input
434 opt1
->len
= opt
->len
;
435 bcopy(&opt
[1], &opt1
[1], opt
->len
);
437 opt1
->len
= (t_uscalar_t
)len
;
439 opt1
= (struct opthdr
*)((uchar_t
*)&opt1
[1] +
440 _TPI_ALIGN_OPT(opt1
->len
));
443 /* Record the final length. */
444 toa
->OPT_length
= (t_scalar_t
)((uchar_t
*)opt1
-
446 mp1
->b_wptr
= (uchar_t
*)opt1
;
447 /* Ditch the input buffer. */
454 * Here we are expecting that the response buffer is exactly
455 * the same size as the input buffer. We pass each opthdr
456 * to the protocol's set function. If the protocol doesn't
457 * like it, it can update the value in it return argument.
460 * Pass each negotiated option through the protocol set
462 * Note: sanity check on option header values done in first
463 * pass and not repeated here.
465 toa
= (struct T_optmgmt_ack
*)tor
;
467 for (opt
= opt_start
; opt
< opt_end
; opt
= next_opt
) {
470 next_opt
= (struct opthdr
*)((uchar_t
*)&opt
[1] +
471 _TPI_ALIGN_OPT(opt
->len
));
473 error
= (*setfn
)(q
, SETFN_OPTCOM_NEGOTIATE
,
474 opt
->level
, opt
->name
,
475 opt
->len
, (uchar_t
*)&opt
[1],
476 &opt
->len
, (uchar_t
*)&opt
[1], NULL
, cr
);
478 * Treat positive "errors" as real.
479 * Note: negative errors are to be treated as
480 * non-fatal by svr4_optcom_req() and are
481 * returned by setfn() when it is passed an
482 * option it does not handle. Since the option
483 * passed proto_opt_lookup(), it is implied that
484 * it is valid but was either handled upstream
485 * or will be handled downstream.
488 optcom_err_ack(q
, mp
, TSYSERR
, error
);
492 * error < 0 means option is not recognized.
497 optcom_err_ack(q
, mp
, TBADFLAG
, 0);
501 /* Set common fields in the header. */
502 toa
->MGMT_flags
= T_SUCCESS
;
503 mp
->b_datap
->db_type
= M_PCPROTO
;
504 toa
->PRIM_type
= T_OPTMGMT_ACK
;
508 optcom_err_ack(q
, mp
, TBADOPT
, 0);
512 * New optcom_req inspired by TPI/XTI semantics
515 tpi_optcom_req(queue_t
*q
, mblk_t
*mp
, cred_t
*cr
, optdb_obj_t
*dbobjp
)
520 struct T_optmgmt_ack
*toa
;
521 struct T_optmgmt_req
*tor
=
522 (struct T_optmgmt_req
*)mp
->b_rptr
;
523 t_uscalar_t worst_status
;
525 /* Verify message integrity. */
526 if ((mp
->b_wptr
- mp
->b_rptr
) < sizeof (struct T_optmgmt_req
)) {
527 optcom_err_ack(q
, mp
, TBADOPT
, 0);
531 /* Verify MGMT_flags legal */
532 switch (tor
->MGMT_flags
) {
537 /* OK - legal request flags */
540 optcom_err_ack(q
, mp
, TBADFLAG
, 0);
545 * In this design, there are two passes required on the input buffer
546 * mostly to accomodate variable length options and "T_ALLOPT" option
547 * which has the semantics "all options of the specified level".
549 * For T_DEFAULT, T_NEGOTIATE, T_CURRENT, and T_CHECK requests, we make
550 * a pass through the input buffer validating the details and making
551 * sure each option is supported by the protocol. We also determine the
552 * length of the option buffer to return. (Variable length options and
553 * T_ALLOPT mean that length can be different for output buffer).
556 toa_len
= 0; /* initial value */
559 * First pass, we do the following
560 * - estimate cumulative length needed for results
561 * - set "status" field based on permissions, option header check
564 if ((t_error
= process_topthdrs_first_pass(mp
, cr
, dbobjp
,
566 optcom_err_ack(q
, mp
, t_error
, 0);
571 * A validation phase of the input buffer is done. We have also
572 * obtained the length requirement and and other details about the
573 * input and we liked input buffer so far. We make another scan
574 * through the input now and generate the output necessary to complete
578 toa_mp
= allocb_tmpl(toa_len
, mp
);
580 optcom_err_ack(q
, mp
, TSYSERR
, ENOMEM
);
585 * Set initial values for generating output.
587 worst_status
= T_SUCCESS
; /* initial value */
590 * This routine makes another pass through the option buffer this
591 * time acting on the request based on "status" result in the
592 * first pass. It also performs "expansion" of T_ALLOPT into
593 * all options of a certain level and acts on each for this request.
595 if ((t_error
= do_options_second_pass(q
, mp
, toa_mp
, cr
, dbobjp
,
596 &worst_status
)) != 0) {
598 optcom_err_ack(q
, mp
, t_error
, 0);
603 * Following code relies on the coincidence that T_optmgmt_req
604 * and T_optmgmt_ack are identical in binary representation
606 toa
= (struct T_optmgmt_ack
*)toa_mp
->b_rptr
;
607 toa
->OPT_length
= (t_scalar_t
)(toa_mp
->b_wptr
- (toa_mp
->b_rptr
+
608 sizeof (struct T_optmgmt_ack
)));
609 toa
->OPT_offset
= (t_scalar_t
)sizeof (struct T_optmgmt_ack
);
611 toa
->MGMT_flags
= tor
->MGMT_flags
;
613 freemsg(mp
); /* free input mblk */
615 toa
->PRIM_type
= T_OPTMGMT_ACK
;
616 toa_mp
->b_datap
->db_type
= M_PCPROTO
;
617 toa
->MGMT_flags
|= worst_status
; /* XXX "worst" or "OR" TPI ? */
623 * Following routine makes a pass through option buffer in mp and performs the
625 * - estimate cumulative length needed for results
626 * - set "status" field based on permissions, option header check
631 process_topthdrs_first_pass(mblk_t
*mp
, cred_t
*cr
, optdb_obj_t
*dbobjp
,
634 opdes_t
*opt_arr
= dbobjp
->odb_opt_des_arr
;
635 uint_t opt_arr_cnt
= dbobjp
->odb_opt_arr_cnt
;
636 optlevel_t
*valid_level_arr
= dbobjp
->odb_valid_levels_arr
;
637 uint_t valid_level_arr_cnt
= dbobjp
->odb_valid_levels_arr_cnt
;
638 struct T_opthdr
*opt
;
639 struct T_opthdr
*opt_start
, *opt_end
;
642 struct T_optmgmt_req
*tor
=
643 (struct T_optmgmt_req
*)mp
->b_rptr
;
645 *toa_lenp
= sizeof (struct T_optmgmt_ack
); /* initial value */
647 if ((opt_start
= (struct T_opthdr
*)
648 mi_offset_param(mp
, tor
->OPT_offset
, tor
->OPT_length
)) == NULL
) {
651 if (!__TPI_TOPT_ISALIGNED(opt_start
))
654 opt_end
= (struct T_opthdr
*)((uchar_t
*)opt_start
+ tor
->OPT_length
);
656 for (opt
= opt_start
; opt
&& (opt
< opt_end
);
657 opt
= _TPI_TOPT_NEXTHDR(opt_start
, tor
->OPT_length
, opt
)) {
659 * Validate the option for length and alignment
660 * before accessing anything in it.
662 if (!(_TPI_TOPT_VALID(opt
, opt_start
, opt_end
)))
665 /* Find the option in the opt_arr. */
666 if (opt
->name
!= T_ALLOPT
) {
667 optd
= proto_opt_lookup(opt
->level
, opt
->name
,
668 opt_arr
, opt_arr_cnt
);
673 * Verify if level is "valid" or not.
674 * Note: This check is required by XTI
676 * TPI provider always initializes
677 * the "not supported" (or whatever) status
678 * for the options. Other levels leave status
679 * unchanged if they do not understand an
682 if (!opt_level_valid(opt
->level
,
683 valid_level_arr
, valid_level_arr_cnt
))
686 * level is valid - initialize
687 * option as not supported
689 opt
->status
= T_NOTSUPPORT
;
690 *toa_lenp
+= _TPI_ALIGN_TOPT(opt
->len
);
695 * Handle T_ALLOPT case as a special case.
696 * Note: T_ALLOPT does not mean anything
697 * for T_CHECK operation.
700 if (tor
->MGMT_flags
== T_CHECK
||
701 ((allopt_len
= opt_level_allopts_lengths(opt
->level
,
702 opt_arr
, opt_arr_cnt
)) == 0)) {
704 * This is confusing but correct !
705 * It is not valid to to use T_ALLOPT with
708 * opt_level_allopts_lengths() is used to verify
709 * that "level" associated with the T_ALLOPT is
713 opt
->status
= T_FAILURE
;
714 *toa_lenp
+= _TPI_ALIGN_TOPT(opt
->len
);
717 ASSERT(allopt_len
!= 0); /* remove ? */
719 *toa_lenp
+= allopt_len
;
720 opt
->status
= T_SUCCESS
;
724 /* Additional checks dependent on operation. */
725 switch (tor
->MGMT_flags
) {
730 * The proto_opt_lookup() routine call above approved of
731 * this option so we can work on the status for it
732 * based on the permissions for the operation. (This
733 * can override any status for it set at higher levels)
734 * We assume this override is OK since chkfn at this
735 * level approved of this option.
737 * T_CURRENT semantics:
738 * The read access is required. Else option
739 * status is T_NOTSUPPORT.
741 * T_DEFAULT semantics:
742 * Note: specification is not clear on this but we
743 * interpret T_DEFAULT semantics such that access to
744 * read value is required for access even the default
745 * value. Otherwise the option status is T_NOTSUPPORT.
747 if (!OA_READ_PERMISSION(optd
, cr
)) {
748 opt
->status
= T_NOTSUPPORT
;
749 *toa_lenp
+= _TPI_ALIGN_TOPT(opt
->len
);
755 * T_DEFAULT/T_CURRENT semantics:
756 * We know that read access is set. If no other access
757 * is set, then status is T_READONLY.
759 if (OA_READONLY_PERMISSION(optd
, cr
))
760 opt
->status
= T_READONLY
;
762 opt
->status
= T_SUCCESS
;
764 * Option passes all checks. Make room for it in the
765 * ack. Note: size stored in table does not include
766 * space for option header.
768 *toa_lenp
+= sizeof (struct T_opthdr
) +
769 _TPI_ALIGN_TOPT(optd
->opdes_size
);
776 * T_NEGOTIATE semantics:
777 * If for fixed length option value on input is not the
778 * same as value supplied, then status is T_FAILURE.
781 * If value is supplied, semantics same as T_NEGOTIATE.
782 * It is however ok not to supply a value with T_CHECK.
785 if (tor
->MGMT_flags
== T_NEGOTIATE
||
786 (opt
->len
!= sizeof (struct T_opthdr
))) {
788 * Implies "value" is specified in T_CHECK or
789 * it is a T_NEGOTIATE request.
791 * Note: This can override anything about this
792 * option request done at a higher level.
794 if (opt
->len
< sizeof (struct T_opthdr
) ||
796 opt
->len
- sizeof (struct T_opthdr
))) {
798 *toa_lenp
+= _TPI_ALIGN_TOPT(opt
->len
);
799 opt
->status
= T_FAILURE
;
804 * The proto_opt_lookup() routine above() approved of
805 * this option so we can work on the status for it based
806 * on the permissions for the operation. (This can
807 * override anything set at a higher level).
809 * T_CHECK/T_NEGOTIATE semantics:
810 * Set status to T_READONLY if read is the only access
813 if (OA_READONLY_PERMISSION(optd
, cr
)) {
814 opt
->status
= T_READONLY
;
815 *toa_lenp
+= _TPI_ALIGN_TOPT(opt
->len
);
821 * T_CHECK/T_NEGOTIATE semantics:
822 * If write (or execute) access is not set, then status
825 if (!OA_WRITE_OR_EXECUTE(optd
, cr
)) {
826 opt
->status
= T_NOTSUPPORT
;
827 *toa_lenp
+= _TPI_ALIGN_TOPT(opt
->len
);
828 /* skip to next option */
832 * Option passes all checks. Make room for it in the
833 * ack and set success in status.
834 * Note: size stored in table does not include header
837 opt
->status
= T_SUCCESS
;
838 *toa_lenp
+= sizeof (struct T_opthdr
) +
839 _TPI_ALIGN_TOPT(optd
->opdes_size
);
845 } /* for loop scanning input buffer */
847 return (0); /* OK return */
851 * This routine makes another pass through the option buffer this
852 * time acting on the request based on "status" result in the
853 * first pass. It also performs "expansion" of T_ALLOPT into
854 * all options of a certain level and acts on each for this request.
857 do_options_second_pass(queue_t
*q
, mblk_t
*reqmp
, mblk_t
*ack_mp
, cred_t
*cr
,
858 optdb_obj_t
*dbobjp
, t_uscalar_t
*worst_statusp
)
861 struct T_opthdr
*opt
;
862 struct T_opthdr
*opt_start
, *opt_end
;
864 uint_t optset_context
;
865 struct T_optmgmt_req
*tor
= (struct T_optmgmt_req
*)reqmp
->b_rptr
;
867 optr
= (uchar_t
*)ack_mp
->b_rptr
+
868 sizeof (struct T_optmgmt_ack
); /* assumed int32_t aligned */
871 * Set initial values for scanning input
873 opt_start
= (struct T_opthdr
*)mi_offset_param(reqmp
,
874 tor
->OPT_offset
, tor
->OPT_length
);
875 if (opt_start
== NULL
)
877 opt_end
= (struct T_opthdr
*)((uchar_t
*)opt_start
+ tor
->OPT_length
);
878 ASSERT(__TPI_TOPT_ISALIGNED(opt_start
)); /* verified in first pass */
880 for (opt
= opt_start
; opt
&& (opt
< opt_end
);
881 opt
= _TPI_TOPT_NEXTHDR(opt_start
, tor
->OPT_length
, opt
)) {
883 /* verified in first pass */
884 ASSERT(_TPI_TOPT_VALID(opt
, opt_start
, opt_end
));
887 * If the first pass in process_topthdrs_first_pass()
888 * has marked the option as a failure case for the MGMT_flags
889 * semantics then there is not much to do.
891 * Note: For all practical purposes, T_READONLY status is
892 * a "success" for T_DEFAULT/T_CURRENT and "failure" for
893 * T_CHECK/T_NEGOTIATE
896 (opt
->status
== T_NOTSUPPORT
) ||
897 (opt
->status
== T_FAILURE
) ||
898 ((tor
->MGMT_flags
& (T_NEGOTIATE
|T_CHECK
)) &&
899 (opt
->status
== T_READONLY
));
903 * According to T_DEFAULT/T_CURRENT semantics, the
904 * input values, even if present, are to be ignored.
905 * Note: Specification is not clear on this, but we
906 * interpret that even though we ignore the values, we
907 * can return them as is. So we process them similar to
908 * T_CHECK/T_NEGOTIATE case which has the semantics to
909 * return the values as is. XXX If interpretation is
910 * ever determined incorrect fill in appropriate code
911 * here to treat T_DEFAULT/T_CURRENT differently.
913 * According to T_CHECK/T_NEGOTIATE semantics,
914 * in the case of T_NOTSUPPORT/T_FAILURE/T_READONLY,
915 * the semantics are to return the "value" part of
916 * option untouched. So here we copy the option
917 * head including value part if any to output.
920 bcopy(opt
, optr
, opt
->len
);
921 optr
+= _TPI_ALIGN_TOPT(opt
->len
);
923 *worst_statusp
= get_worst_status(opt
->status
,
926 /* skip to process next option in buffer */
929 } /* end if "failed option" */
931 * The status is T_SUCCESS or T_READONLY
932 * We process the value part here
934 ASSERT(opt
->status
== T_SUCCESS
|| opt
->status
== T_READONLY
);
935 switch (tor
->MGMT_flags
) {
938 * We fill default value from table or protocol specific
939 * function. If this call fails, we pass input through.
941 if (do_opt_default(q
, opt
, &optr
, worst_statusp
,
943 opt
->status
= T_FAILURE
;
944 bcopy(opt
, optr
, opt
->len
);
945 optr
+= _TPI_ALIGN_TOPT(opt
->len
);
946 *worst_statusp
= get_worst_status(opt
->status
,
953 do_opt_current(q
, opt
, &optr
, worst_statusp
, cr
,
959 if (tor
->MGMT_flags
== T_CHECK
)
960 optset_context
= SETFN_OPTCOM_CHECKONLY
;
961 else /* T_NEGOTIATE */
962 optset_context
= SETFN_OPTCOM_NEGOTIATE
;
963 do_opt_check_or_negotiate(q
, opt
, optset_context
,
964 &optr
, worst_statusp
, cr
, dbobjp
);
969 } /* end for loop scanning option buffer */
971 ack_mp
->b_wptr
= optr
;
972 ASSERT(ack_mp
->b_wptr
<= ack_mp
->b_datap
->db_lim
);
974 return (0); /* OK return */
979 get_worst_status(t_uscalar_t status
, t_uscalar_t current_worst_status
)
982 * Return the "worst" among the arguments "status" and
983 * "current_worst_status".
985 * Note: Tracking "worst_status" can be made a bit simpler
986 * if we use the property that status codes are bitwise
989 * The pecking order is
991 * T_SUCCESS ..... best
995 * T_NOTSUPPORT... worst
997 if (status
== current_worst_status
)
998 return (current_worst_status
);
999 switch (current_worst_status
) {
1001 if (status
== T_PARTSUCCESS
)
1002 return (T_PARTSUCCESS
);
1005 if (status
== T_FAILURE
)
1009 if (status
== T_READONLY
)
1010 return (T_READONLY
);
1013 if (status
== T_NOTSUPPORT
)
1014 return (T_NOTSUPPORT
);
1018 return (current_worst_status
);
1023 do_opt_default(queue_t
*q
, struct T_opthdr
*reqopt
, uchar_t
**resptrp
,
1024 t_uscalar_t
*worst_statusp
, cred_t
*cr
, optdb_obj_t
*dbobjp
)
1026 pfi_t deffn
= dbobjp
->odb_deffn
;
1027 opdes_t
*opt_arr
= dbobjp
->odb_opt_des_arr
;
1028 uint_t opt_arr_cnt
= dbobjp
->odb_opt_arr_cnt
;
1030 struct T_opthdr
*topth
;
1033 if (reqopt
->name
!= T_ALLOPT
) {
1035 * lookup the option in the table and fill default value
1037 optd
= proto_opt_lookup(reqopt
->level
, reqopt
->name
,
1038 opt_arr
, opt_arr_cnt
);
1040 /* Calling routine should have verified it it exists */
1041 ASSERT(optd
!= NULL
);
1043 topth
= (struct T_opthdr
*)(*resptrp
);
1044 topth
->level
= reqopt
->level
;
1045 topth
->name
= reqopt
->name
;
1046 topth
->status
= reqopt
->status
;
1048 *worst_statusp
= get_worst_status(reqopt
->status
,
1051 if (optd
->opdes_props
& OP_NODEFAULT
) {
1052 /* header only, no default "value" part */
1053 topth
->len
= sizeof (struct T_opthdr
);
1054 *resptrp
+= sizeof (struct T_opthdr
);
1058 if (optd
->opdes_props
& OP_DEF_FN
) {
1059 deflen
= (*deffn
)(q
, reqopt
->level
,
1060 reqopt
->name
, _TPI_TOPT_DATA(topth
));
1062 topth
->len
= (t_uscalar_t
)
1063 (sizeof (struct T_opthdr
) + deflen
);
1066 * return error, this should 'pass
1067 * through' the option and maybe some
1068 * other level will fill it in or
1070 * (No change in 'resptrp' upto here)
1075 /* fill length and value part */
1076 switch (optd
->opdes_size
) {
1078 * Since options are guaranteed aligned only
1079 * on a 4 byte boundary (t_scalar_t) any
1080 * option that is greater in size will default
1081 * to the bcopy below
1083 case sizeof (int32_t):
1084 *(int32_t *)_TPI_TOPT_DATA(topth
) =
1085 (int32_t)optd
->opdes_default
;
1087 case sizeof (int16_t):
1088 *(int16_t *)_TPI_TOPT_DATA(topth
) =
1089 (int16_t)optd
->opdes_default
;
1091 case sizeof (int8_t):
1092 *(int8_t *)_TPI_TOPT_DATA(topth
) =
1093 (int8_t)optd
->opdes_default
;
1097 * other length but still assume
1100 bcopy(optd
->opdes_defbuf
,
1101 _TPI_TOPT_DATA(topth
),
1105 topth
->len
= (t_uscalar_t
)(optd
->opdes_size
+
1106 sizeof (struct T_opthdr
));
1108 *resptrp
+= _TPI_ALIGN_TOPT(topth
->len
);
1110 return (0); /* OK return */
1114 * T_ALLOPT processing
1116 * lookup and stuff default values of all the options of the
1119 for (optd
= opt_arr
; optd
< &opt_arr
[opt_arr_cnt
]; optd
++) {
1120 if (reqopt
->level
!= optd
->opdes_level
)
1124 * T_DEFAULT semantics:
1125 * XXX: we interpret T_DEFAULT semantics such that access to
1126 * read value is required for access even the default value.
1127 * Else option is ignored for T_ALLOPT request.
1129 if (!OA_READ_PERMISSION(optd
, cr
))
1134 * Found option of same level as T_ALLOPT request
1135 * that we can return.
1138 topth
= (struct T_opthdr
*)(*resptrp
);
1139 topth
->level
= optd
->opdes_level
;
1140 topth
->name
= optd
->opdes_name
;
1143 * T_DEFAULT semantics:
1144 * We know that read access is set. If no other access is set,
1145 * then status is T_READONLY
1147 if (OA_READONLY_PERMISSION(optd
, cr
)) {
1148 topth
->status
= T_READONLY
;
1149 *worst_statusp
= get_worst_status(T_READONLY
,
1152 topth
->status
= T_SUCCESS
;
1154 * Note: *worst_statusp has to be T_SUCCESS or
1155 * worse so no need to adjust
1159 if (optd
->opdes_props
& OP_NODEFAULT
) {
1160 /* header only, no value part */
1161 topth
->len
= sizeof (struct T_opthdr
);
1162 *resptrp
+= sizeof (struct T_opthdr
);
1166 if (optd
->opdes_props
& OP_DEF_FN
) {
1167 deflen
= (*deffn
)(q
, reqopt
->level
,
1168 reqopt
->name
, _TPI_TOPT_DATA(topth
));
1170 topth
->len
= (t_uscalar_t
)(deflen
+
1171 sizeof (struct T_opthdr
));
1175 * return just the header as T_ALLOPT
1177 * Some other level deffn may
1178 * supply value part.
1180 topth
->len
= sizeof (struct T_opthdr
);
1181 topth
->status
= T_FAILURE
;
1183 get_worst_status(T_FAILURE
,
1188 * fill length and value part from
1191 switch (optd
->opdes_size
) {
1193 * Since options are guaranteed aligned only
1194 * on a 4 byte boundary (t_scalar_t) any
1195 * option that is greater in size will default
1196 * to the bcopy below
1198 case sizeof (int32_t):
1199 *(int32_t *)_TPI_TOPT_DATA(topth
) =
1200 (int32_t)optd
->opdes_default
;
1202 case sizeof (int16_t):
1203 *(int16_t *)_TPI_TOPT_DATA(topth
) =
1204 (int16_t)optd
->opdes_default
;
1206 case sizeof (int8_t):
1207 *(int8_t *)_TPI_TOPT_DATA(topth
) =
1208 (int8_t)optd
->opdes_default
;
1212 * other length but still assume
1215 bcopy(optd
->opdes_defbuf
,
1216 _TPI_TOPT_DATA(topth
),
1219 topth
->len
= (t_uscalar_t
)(optd
->opdes_size
+
1220 sizeof (struct T_opthdr
));
1222 *resptrp
+= _TPI_ALIGN_TOPT(topth
->len
);
1229 do_opt_current(queue_t
*q
, struct T_opthdr
*reqopt
, uchar_t
**resptrp
,
1230 t_uscalar_t
*worst_statusp
, cred_t
*cr
, optdb_obj_t
*dbobjp
)
1232 pfi_t getfn
= dbobjp
->odb_getfn
;
1233 opdes_t
*opt_arr
= dbobjp
->odb_opt_des_arr
;
1234 uint_t opt_arr_cnt
= dbobjp
->odb_opt_arr_cnt
;
1235 struct T_opthdr
*topth
;
1238 uchar_t
*initptr
= *resptrp
;
1241 * We call getfn to get the current value of an option. The call may
1242 * fail in which case we copy the values from the input buffer. Maybe
1243 * something downstream will fill it in or something upstream did.
1246 if (reqopt
->name
!= T_ALLOPT
) {
1247 topth
= (struct T_opthdr
*)*resptrp
;
1248 *resptrp
+= sizeof (struct T_opthdr
);
1249 optlen
= (*getfn
)(q
, reqopt
->level
, reqopt
->name
, *resptrp
);
1251 topth
->len
= (t_uscalar_t
)(optlen
+
1252 sizeof (struct T_opthdr
));
1253 topth
->level
= reqopt
->level
;
1254 topth
->name
= reqopt
->name
;
1255 topth
->status
= reqopt
->status
;
1256 *resptrp
+= _TPI_ALIGN_TOPT(optlen
);
1257 *worst_statusp
= get_worst_status(topth
->status
,
1260 /* failed - reset "*resptrp" pointer */
1261 *resptrp
-= sizeof (struct T_opthdr
);
1263 } else { /* T_ALLOPT processing */
1264 /* scan and get all options */
1265 for (optd
= opt_arr
; optd
< &opt_arr
[opt_arr_cnt
]; optd
++) {
1266 /* skip other levels */
1267 if (reqopt
->level
!= optd
->opdes_level
)
1270 if (!OA_READ_PERMISSION(optd
, cr
))
1274 topth
= (struct T_opthdr
*)*resptrp
;
1275 *resptrp
+= sizeof (struct T_opthdr
);
1277 /* get option of this level */
1278 optlen
= (*getfn
)(q
, reqopt
->level
, optd
->opdes_name
,
1282 topth
->len
= (t_uscalar_t
)(optlen
+
1283 sizeof (struct T_opthdr
));
1284 topth
->level
= reqopt
->level
;
1285 topth
->name
= optd
->opdes_name
;
1286 if (OA_READONLY_PERMISSION(optd
, cr
))
1287 topth
->status
= T_READONLY
;
1289 topth
->status
= T_SUCCESS
;
1290 *resptrp
+= _TPI_ALIGN_TOPT(optlen
);
1293 * failed, return as T_FAILURE and null value
1294 * part. Maybe something downstream will
1295 * handle this one and fill in a value. Here
1296 * it is just part of T_ALLOPT expansion.
1298 topth
->len
= sizeof (struct T_opthdr
);
1299 topth
->level
= reqopt
->level
;
1300 topth
->name
= optd
->opdes_name
;
1301 topth
->status
= T_FAILURE
;
1303 *worst_statusp
= get_worst_status(topth
->status
,
1305 } /* end for loop */
1307 if (*resptrp
== initptr
) {
1309 * getfn failed and does not want to handle this option.
1311 reqopt
->status
= T_FAILURE
;
1312 bcopy(reqopt
, *resptrp
, reqopt
->len
);
1313 *resptrp
+= _TPI_ALIGN_TOPT(reqopt
->len
);
1314 *worst_statusp
= get_worst_status(reqopt
->status
,
1320 do_opt_check_or_negotiate(queue_t
*q
, struct T_opthdr
*reqopt
,
1321 uint_t optset_context
, uchar_t
**resptrp
, t_uscalar_t
*worst_statusp
,
1322 cred_t
*cr
, optdb_obj_t
*dbobjp
)
1324 pfi_t deffn
= dbobjp
->odb_deffn
;
1325 opt_set_fn setfn
= dbobjp
->odb_setfn
;
1326 opdes_t
*opt_arr
= dbobjp
->odb_opt_des_arr
;
1327 uint_t opt_arr_cnt
= dbobjp
->odb_opt_arr_cnt
;
1328 struct T_opthdr
*topth
;
1333 uchar_t
*initptr
= *resptrp
;
1335 ASSERT(reqopt
->status
== T_SUCCESS
);
1337 if (reqopt
->name
!= T_ALLOPT
) {
1338 topth
= (struct T_opthdr
*)*resptrp
;
1339 *resptrp
+= sizeof (struct T_opthdr
);
1340 error
= (*setfn
)(q
, optset_context
, reqopt
->level
, reqopt
->name
,
1341 reqopt
->len
- sizeof (struct T_opthdr
),
1342 _TPI_TOPT_DATA(reqopt
), &optlen
, _TPI_TOPT_DATA(topth
),
1345 /* failed - reset "*resptrp" */
1346 *resptrp
-= sizeof (struct T_opthdr
);
1349 * success - "value" already filled in setfn()
1351 topth
->len
= (t_uscalar_t
)(optlen
+
1352 sizeof (struct T_opthdr
));
1353 topth
->level
= reqopt
->level
;
1354 topth
->name
= reqopt
->name
;
1355 topth
->status
= reqopt
->status
;
1356 *resptrp
+= _TPI_ALIGN_TOPT(optlen
);
1357 *worst_statusp
= get_worst_status(topth
->status
,
1360 } else { /* T_ALLOPT processing */
1361 /* only for T_NEGOTIATE case */
1362 ASSERT(optset_context
== SETFN_OPTCOM_NEGOTIATE
);
1364 /* scan and set all options to default value */
1365 for (optd
= opt_arr
; optd
< &opt_arr
[opt_arr_cnt
]; optd
++) {
1367 /* skip other levels */
1368 if (reqopt
->level
!= optd
->opdes_level
)
1371 if (OA_EXECUTE_PERMISSION(optd
, cr
) ||
1372 OA_NO_PERMISSION(optd
, cr
)) {
1374 * skip this one too. Does not make sense to
1375 * set anything to default value for "execute"
1381 if (OA_READONLY_PERMISSION(optd
, cr
)) {
1383 * Return with T_READONLY status (and no value
1384 * part). Note: spec is not clear but
1385 * XTI test suite needs this.
1387 topth
= (struct T_opthdr
*)*resptrp
;
1388 topth
->len
= sizeof (struct T_opthdr
);
1389 *resptrp
+= topth
->len
;
1390 topth
->level
= reqopt
->level
;
1391 topth
->name
= optd
->opdes_name
;
1392 topth
->status
= T_READONLY
;
1393 *worst_statusp
= get_worst_status(topth
->status
,
1399 * It is not read only or execute type
1400 * the it must have write permission
1402 ASSERT(OA_WRITE_PERMISSION(optd
, cr
));
1404 topth
= (struct T_opthdr
*)*resptrp
;
1405 *resptrp
+= sizeof (struct T_opthdr
);
1407 topth
->len
= sizeof (struct T_opthdr
);
1408 topth
->level
= reqopt
->level
;
1409 topth
->name
= optd
->opdes_name
;
1410 if (optd
->opdes_props
& OP_NODEFAULT
) {
1412 * Option of "no default value" so it does not
1413 * make sense to try to set it. We just return
1414 * header with status of T_SUCCESS
1415 * XXX should this be failure ?
1417 topth
->status
= T_SUCCESS
;
1418 continue; /* skip setting */
1420 if (optd
->opdes_props
& OP_DEF_FN
) {
1421 if ((optd
->opdes_props
& OP_VARLEN
) ||
1422 ((optsize
= (*deffn
)(q
, reqopt
->level
,
1424 (uchar_t
*)optd
->opdes_defbuf
)) < 0)) {
1425 /* XXX - skip these too */
1426 topth
->status
= T_SUCCESS
;
1427 continue; /* skip setting */
1430 optsize
= optd
->opdes_size
;
1434 /* set option of this level */
1435 error
= (*setfn
)(q
, SETFN_OPTCOM_NEGOTIATE
,
1436 reqopt
->level
, optd
->opdes_name
, optsize
,
1437 (uchar_t
*)optd
->opdes_defbuf
, &optlen
,
1438 _TPI_TOPT_DATA(topth
), NULL
, cr
);
1441 * failed, return as T_FAILURE and null value
1442 * part. Maybe something downstream will
1443 * handle this one and fill in a value. Here
1444 * it is just part of T_ALLOPT expansion.
1446 topth
->status
= T_FAILURE
;
1447 *worst_statusp
= get_worst_status(topth
->status
,
1451 topth
->len
+= optlen
;
1452 topth
->status
= T_SUCCESS
;
1453 *resptrp
+= _TPI_ALIGN_TOPT(optlen
);
1455 } /* end for loop */
1459 if (*resptrp
== initptr
) {
1461 * setfn failed and does not want to handle this option.
1463 reqopt
->status
= T_FAILURE
;
1464 bcopy(reqopt
, *resptrp
, reqopt
->len
);
1465 *resptrp
+= _TPI_ALIGN_TOPT(reqopt
->len
);
1466 *worst_statusp
= get_worst_status(reqopt
->status
,
1472 * The following routines process options buffer passed with
1473 * T_CONN_REQ, T_CONN_RES and T_UNITDATA_REQ.
1474 * This routine does the consistency check applied to the
1475 * sanity of formatting of multiple options packed in the
1478 * XTI brain damage alert:
1479 * XTI interface adopts the notion of an option being an
1480 * "absolute requirement" from OSI transport service (but applies
1481 * it to all transports including Internet transports).
1482 * The main effect of that is action on failure to "negotiate" a
1483 * requested option to the exact requested value
1485 * - if the option is an "absolute requirement", the primitive
1486 * is aborted (e.g T_DISCON_REQ or T_UDERR generated)
1487 * - if the option is NOT and "absolute requirement" it can
1490 * We would not support "negotiating" of options on connection
1491 * primitives for Internet transports. However just in case we
1492 * forced to in order to pass strange test suites, the design here
1493 * tries to support these notions.
1495 * tpi_optcom_buf(q, mp, opt_lenp, opt_offset, cred, dbobjp, thisdg_attrs,
1496 * *is_absreq_failurep)
1498 * - Verify the option buffer, if formatted badly, return error 1
1500 * - If it is a "permissions" failure (read-only), return error 2
1502 * - Else, process the option "in place", the following can happen,
1503 * - if a "privileged" option, mark it as "ignored".
1504 * - if "not supported", mark "ignored"
1505 * - if "supported" attempt negotiation and fill result in
1507 * - if "absolute requirement", set "*is_absreq_failurep"
1508 * - if NOT an "absolute requirement", then our
1509 * interpretation is to mark is at ignored if
1510 * negotiation fails (Spec allows partial success
1511 * as in OSI protocols but not failure)
1513 * Then delete "ignored" options from option buffer and return success.
1517 tpi_optcom_buf(queue_t
*q
, mblk_t
*mp
, t_scalar_t
*opt_lenp
,
1518 t_scalar_t opt_offset
, cred_t
*cr
, optdb_obj_t
*dbobjp
,
1519 void *thisdg_attrs
, int *is_absreq_failurep
)
1521 opt_set_fn setfn
= dbobjp
->odb_setfn
;
1522 opdes_t
*opt_arr
= dbobjp
->odb_opt_des_arr
;
1523 uint_t opt_arr_cnt
= dbobjp
->odb_opt_arr_cnt
;
1524 struct T_opthdr
*opt
, *opt_start
, *opt_end
;
1525 mblk_t
*copy_mp_head
;
1526 uchar_t
*optr
, *init_optr
;
1528 uint_t optset_context
;
1532 ASSERT((uchar_t
*)opt_lenp
> mp
->b_rptr
&&
1533 (uchar_t
*)opt_lenp
< mp
->b_wptr
);
1535 copy_mp_head
= NULL
;
1536 *is_absreq_failurep
= 0;
1537 switch (((union T_primitives
*)mp
->b_rptr
)->type
) {
1540 optset_context
= SETFN_CONN_NEGOTIATE
;
1542 case T_UNITDATA_REQ
:
1543 optset_context
= SETFN_UD_NEGOTIATE
;
1547 * should never get here, all possible TPI primitives
1548 * where this can be called from should be accounted
1549 * for in the cases above
1554 if ((opt_start
= (struct T_opthdr
*)
1555 mi_offset_param(mp
, opt_offset
, *opt_lenp
)) == NULL
) {
1556 error
= ENOPROTOOPT
;
1559 if (!__TPI_TOPT_ISALIGNED(opt_start
)) {
1560 error
= ENOPROTOOPT
;
1564 opt_end
= (struct T_opthdr
*)((uchar_t
*)opt_start
1567 if ((copy_mp_head
= copyb(mp
)) == NULL
) {
1572 init_optr
= optr
= (uchar_t
*)©_mp_head
->b_rptr
[opt_offset
];
1574 for (opt
= opt_start
; opt
&& (opt
< opt_end
);
1575 opt
= _TPI_TOPT_NEXTHDR(opt_start
, *opt_lenp
, opt
)) {
1577 * Validate the option for length and alignment
1578 * before accessing anything in it
1580 if (!_TPI_TOPT_VALID(opt
, opt_start
, opt_end
)) {
1581 error
= ENOPROTOOPT
;
1585 /* Find the option in the opt_arr. */
1586 optd
= proto_opt_lookup(opt
->level
, opt
->name
,
1587 opt_arr
, opt_arr_cnt
);
1593 opt
->status
= T_NOTSUPPORT
;
1598 * Weird but as in XTI spec.
1599 * Sec 6.3.6 "Privileged and ReadOnly Options"
1600 * Permission problems (e.g.readonly) fail with bad access
1601 * BUT "privileged" option request from those NOT PRIVILEGED
1602 * are to be merely "ignored".
1603 * XXX Prevents "probing" of privileged options ?
1605 if (OA_READONLY_PERMISSION(optd
, cr
)) {
1609 if (OA_MATCHED_PRIV(optd
, cr
)) {
1611 * For privileged options, we DO perform
1612 * access checks as is common sense
1614 if (!OA_WX_ANYPRIV(optd
)) {
1620 * For non privileged, we fail instead following
1621 * "ignore" semantics dictated by XTI spec for
1622 * permissions problems.
1623 * Sec 6.3.6 "Privileged and ReadOnly Options"
1624 * XXX Should we do "ignore" semantics ?
1626 if (!OA_WX_NOPRIV(optd
)) { /* nopriv */
1627 opt
->status
= T_FAILURE
;
1633 * If the negotiation fails, for options that
1634 * are "absolute requirement", it is a fatal error.
1635 * For options that are NOT "absolute requirements",
1636 * and the value fails to negotiate, the XTI spec
1637 * only considers the possibility of partial success
1638 * (T_PARTSUCCES - not likely for Internet protocols).
1639 * The spec is in denial about complete failure
1640 * (T_FAILURE) to negotiate for options that are
1641 * carried on T_CONN_REQ/T_CONN_RES/T_UNITDATA
1642 * We interpret the T_FAILURE to negotiate an option
1643 * that is NOT an absolute requirement that it is safe
1648 if (opt
->len
< (t_uscalar_t
)sizeof (struct T_opthdr
) ||
1649 !opt_length_ok(optd
, opt
->len
- sizeof (struct T_opthdr
))) {
1651 if ((optd
->opdes_props
& OP_NOT_ABSREQ
) == 0) {
1652 /* option is absolute requirement */
1653 *is_absreq_failurep
= 1;
1657 opt
->status
= T_FAILURE
;
1662 * verified generic attributes. Now call set function.
1663 * Note: We assume the following to simplify code.
1664 * XXX If this is found not to be valid, this routine
1665 * will need to be rewritten. At this point it would
1666 * be premature to introduce more complexity than is
1668 * Assumption: For variable length options, we assume
1669 * that the value returned will be same or less length
1670 * (size does not increase). This makes it OK to pass the
1671 * same space for output as it is on input.
1674 error
= (*setfn
)(q
, optset_context
, opt
->level
, opt
->name
,
1675 opt
->len
- (t_uscalar_t
)sizeof (struct T_opthdr
),
1676 _TPI_TOPT_DATA(opt
), &olen
, _TPI_TOPT_DATA(opt
),
1679 if (olen
> (int)(opt
->len
- sizeof (struct T_opthdr
))) {
1681 * Space on output more than space on input. Should
1682 * not happen and we consider it a bug/error.
1683 * More of a restriction than an error in our
1684 * implementation. Will see if we can live with this
1685 * otherwise code will get more hairy with multiple
1692 if ((optd
->opdes_props
& OP_NOT_ABSREQ
) == 0) {
1693 /* option is absolute requirement. */
1694 *is_absreq_failurep
= 1;
1698 * failed - but option "not an absolute
1701 opt
->status
= T_FAILURE
;
1705 * Fill in the only possible successful result
1706 * (Note: TPI allows for T_PARTSUCCESS - partial
1707 * sucess result code which is relevant in OSI world
1708 * and not possible in Internet code)
1710 opt
->status
= T_SUCCESS
;
1713 * Add T_SUCCESS result code options to the "output" options.
1714 * No T_FAILURES or T_NOTSUPPORT here as they are to be
1716 * This code assumes output option buffer will
1717 * be <= input option buffer.
1719 * Copy option header+value
1721 bcopy(opt
, optr
, opt
->len
);
1722 optr
+= _TPI_ALIGN_TOPT(opt
->len
);
1725 * Overwrite the input mblk option buffer now with the output
1726 * and update length, and contents in original mbl
1727 * (offset remains unchanged).
1729 *opt_lenp
= (t_scalar_t
)(optr
- init_optr
);
1730 if (*opt_lenp
> 0) {
1731 bcopy(init_optr
, opt_start
, *opt_lenp
);
1735 if (copy_mp_head
!= NULL
)
1736 freeb(copy_mp_head
);
1741 opt_level_valid(t_uscalar_t level
, optlevel_t
*valid_level_arr
,
1742 uint_t valid_level_arr_cnt
)
1746 for (olp
= valid_level_arr
;
1747 olp
< &valid_level_arr
[valid_level_arr_cnt
];
1749 if (level
== (uint_t
)(*olp
))
1757 * Compute largest possible size for an option buffer containing
1758 * all options in one buffer.
1760 * XXX TBD, investigate use of opt_bloated_maxsize() to avoid
1761 * wastefully large buffer allocation.
1764 opt_level_allopts_lengths(t_uscalar_t level
, opdes_t
*opt_arr
,
1768 size_t allopt_len
= 0; /* 0 implies no option at this level */
1771 * Scan opt_arr computing aggregate length
1772 * requirement for storing values of all
1774 * Note: we do not filter for permissions
1775 * etc. This will be >= the real aggregate
1776 * length required (upper bound).
1779 for (optd
= opt_arr
; optd
< &opt_arr
[opt_arr_cnt
];
1781 if (level
== optd
->opdes_level
) {
1782 allopt_len
+= sizeof (struct T_opthdr
) +
1783 _TPI_ALIGN_TOPT(optd
->opdes_size
);
1786 return (allopt_len
); /* 0 implies level not found */
1790 * Compute largest possible size for an option buffer containing
1791 * all options in one buffer - a (theoretical?) worst case scenario
1792 * for certain cases.
1795 optcom_max_optbuf_len(opdes_t
*opt_arr
, uint_t opt_arr_cnt
)
1797 t_uscalar_t max_optbuf_len
= sizeof (struct T_info_ack
);
1800 for (optd
= opt_arr
; optd
< &opt_arr
[opt_arr_cnt
]; optd
++) {
1801 max_optbuf_len
+= (t_uscalar_t
)sizeof (struct T_opthdr
) +
1802 (t_uscalar_t
)_TPI_ALIGN_TOPT(optd
->opdes_size
);
1804 return (max_optbuf_len
);
1808 * Compute largest possible size for OPT_size for a transport.
1809 * Heuristic used is to add all but certain extremely large
1810 * size options; this is done by calling opt_bloated_maxsize().
1811 * It affects user level allocations in TLI/XTI code using t_alloc()
1812 * and other TLI/XTI implementation instance strucutures.
1813 * The large size options excluded are presumed to be
1814 * never accessed through the (theoretical?) worst case code paths
1815 * through TLI/XTI as they are currently IPv6 specific options.
1819 optcom_max_optsize(opdes_t
*opt_arr
, uint_t opt_arr_cnt
)
1821 t_uscalar_t max_optbuf_len
= sizeof (struct T_info_ack
);
1824 for (optd
= opt_arr
; optd
< &opt_arr
[opt_arr_cnt
]; optd
++) {
1825 if (!opt_bloated_maxsize(optd
)) {
1827 (t_uscalar_t
)sizeof (struct T_opthdr
) +
1828 (t_uscalar_t
)_TPI_ALIGN_TOPT(optd
->opdes_size
);
1831 return (max_optbuf_len
);
1835 * The theoretical model used in optcom_max_optsize() and
1836 * opt_level_allopts_lengths() accounts for the worst case of all
1837 * possible options for the theoretical cases and results in wasteful
1838 * memory allocations for certain theoretically correct usage scenarios.
1839 * In practice, the "features" they support are rarely, if ever,
1840 * used and even then only by test suites for those features (VSU, VST).
1841 * However, they result in large allocations due to the increased transport
1842 * T_INFO_ACK OPT_size field affecting t_alloc() users and TLI/XTI library
1843 * instance data structures for applications.
1845 * The following routine opt_bloated_maxsize() supports a hack that avoids
1846 * paying the tax for the bloated options by excluding them and pretending
1847 * they don't exist for certain features without affecting features that
1850 * XXX Currently implemented only for optcom_max_optsize()
1851 * (to reduce risk late in release).
1852 * TBD for future, investigate use in optcom_level_allopts_lengths() and
1853 * all the instances of T_ALLOPT processing to exclude "bloated options".
1854 * Will not affect VSU/VST tests as they do not test with IPPROTO_IPV6
1855 * level options which are the only ones that fit the "bloated maxsize"
1856 * option profile now.
1859 opt_bloated_maxsize(opdes_t
*optd
)
1861 if (optd
->opdes_level
!= IPPROTO_IPV6
)
1863 switch (optd
->opdes_name
) {
1866 case IPV6_RTHDRDSTOPTS
:
1877 * optlen is the length of the option content
1878 * Caller should check the optlen is at least sizeof (struct T_opthdr)
1881 opt_length_ok(opdes_t
*optd
, t_uscalar_t optlen
)
1885 * Value specified should match length of fixed length option or be
1886 * less than maxlen of variable length option.
1888 if (optd
->opdes_props
& OP_VARLEN
) {
1889 if (optlen
<= optd
->opdes_size
)
1892 /* fixed length option */
1893 if (optlen
== optd
->opdes_size
)
1900 * This routine manages the allocation and free of the space for
1901 * an extension header or option. Returns failure if memory
1902 * can not be allocated.
1905 optcom_pkt_set(uchar_t
*invalp
, uint_t inlen
,
1906 uchar_t
**optbufp
, uint_t
*optlenp
)
1911 if (inlen
== *optlenp
) {
1912 /* Unchanged length - no need to reallocate */
1914 bcopy(invalp
, optp
, inlen
);
1918 /* Allocate new buffer before free */
1919 optbuf
= kmem_alloc(inlen
, KM_NOSLEEP
);
1926 /* Free old buffer */
1928 kmem_free(*optbufp
, *optlenp
);
1931 bcopy(invalp
, optbuf
, inlen
);
1939 process_auxiliary_options(conn_t
*connp
, void *control
, t_uscalar_t controllen
,
1940 void *optbuf
, optdb_obj_t
*dbobjp
, int (*opt_set_fn
)(conn_t
*,
1941 uint_t
, int, int, uint_t
, uchar_t
*, uint_t
*, uchar_t
*, void *, cred_t
*),
1944 struct cmsghdr
*cmsg
;
1947 int error
= EOPNOTSUPP
;
1949 uint_t opt_arr_cnt
= dbobjp
->odb_opt_arr_cnt
;
1950 opdes_t
*opt_arr
= dbobjp
->odb_opt_des_arr
;
1952 for (cmsg
= (struct cmsghdr
*)control
;
1953 CMSG_VALID(cmsg
, control
, (uintptr_t)control
+ controllen
);
1954 cmsg
= CMSG_NEXT(cmsg
)) {
1956 len
= (t_uscalar_t
)CMSG_CONTENTLEN(cmsg
);
1957 /* Find the option in the opt_arr. */
1958 optd
= proto_opt_lookup(cmsg
->cmsg_level
, cmsg
->cmsg_type
,
1959 opt_arr
, opt_arr_cnt
);
1963 if (OA_READONLY_PERMISSION(optd
, cr
)) {
1966 if (OA_MATCHED_PRIV(optd
, cr
)) {
1968 * For privileged options, we DO perform
1969 * access checks as is common sense
1971 if (!OA_WX_ANYPRIV(optd
)) {
1976 * For non privileged, we fail instead following
1977 * "ignore" semantics dictated by XTI spec for
1978 * permissions problems.
1980 if (!OA_WX_NOPRIV(optd
)) { /* nopriv */
1984 error
= opt_set_fn(connp
, SETFN_UD_NEGOTIATE
, optd
->opdes_level
,
1985 optd
->opdes_name
, len
, (uchar_t
*)CMSG_CONTENT(cmsg
),
1986 &outlen
, (uchar_t
*)CMSG_CONTENT(cmsg
), optbuf
, cr
);
1989 } else if (outlen
> len
) {
1993 * error can be -ve if the protocol wants to
1994 * pass the option to IP. We donot pass auxiliary