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