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