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 /*      Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T     */
  22 /*      All Rights Reserved     */
  23 
  24 
  25 /*
  26  * Copyright (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved.
  27  * Copyright 2020 Joyent, Inc.
  28  */
  29 
  30 #ifndef _SYS_TIHDR_H
  31 #define _SYS_TIHDR_H
  32 
  33 #include <sys/types.h>
  34 /*
  35  * Include declarations implicit to TPI and shared with user level code
  36  */
  37 #include <sys/tpicommon.h>
  38 
  39 #ifdef  __cplusplus
  40 extern "C" {
  41 #endif
  42 
  43 /*
  44  * The feature test macro, _SUN_TPI_VERSION makes some of additional
  45  * declarations available and changes some existing ones. There was
  46  * some changes done to this interface and this feature test macro
  47  * enables transitioning to those changes while maintaining retaining
  48  * backward compatibility.
  49  *
  50  * The following is all the information
  51  * needed by the Transport Service Interface.
  52  */
  53 
  54 /*
  55  * The following are the definitions of the Transport
  56  * Service Interface primitives.
  57  */
  58 
  59 /*
  60  * Primitives that are initiated by the transport user.
  61  */
  62 #define T_CONN_REQ      0       /* connection request           */
  63 #if _SUN_TPI_VERSION > 1
  64 #define O_T_CONN_RES    1       /* old connection response      */
  65 #else
  66 #define T_CONN_RES      1       /* connection response          */
  67 #endif /* _SUN_TPI_VERSION > 1 */
  68 #define T_DISCON_REQ    2       /* disconnect request           */
  69 #define T_DATA_REQ      3       /* data request                 */
  70 #define T_EXDATA_REQ    4       /* expedited data request       */
  71 #define T_INFO_REQ      5       /* information request          */
  72 /*
  73  * Bind Request primitive (TLI inspired
  74  * address binding semantics). If requested address is
  75  * found to be busy, an alternative free address is
  76  * returned. (Requires comparison of requested address to
  77  * returned address to verify if the requested address was
  78  * bound)
  79  *
  80  */
  81 #if _SUN_TPI_VERSION > 0
  82 #define O_T_BIND_REQ    6
  83 #else
  84 #define T_BIND_REQ      6
  85 #endif /* _SUN_TPI_VERSION > 0 */
  86 
  87 #define T_UNBIND_REQ    7       /* unbind request               */
  88 #define T_UNITDATA_REQ  8       /* unitdata request             */
  89 
  90 /*
  91  * Option management request (with TLI inspired semantics )
  92  * The preferred name for this primitive in new code is T_SVR4_OPTMGMT_REQ.
  93  * This primitive had the name T_OPTMGMT_REQ in old SVR4 derived TPI.
  94  * This primitive is used for TLI and Socket API support.
  95  * The packing of options in option buffer is private contract
  96  * between transport provider and its users and can differ
  97  * between different transports.
  98  * (The name O_T_OPTMGMT_REQ continues to exist for Solaris 2.6
  99  *  compilation environment compatibility only)
 100  *
 101  */
 102 #define T_SVR4_OPTMGMT_REQ      9
 103 #if _SUN_TPI_VERSION > 0
 104 #define O_T_OPTMGMT_REQ T_SVR4_OPTMGMT_REQ
 105 #else
 106 #define T_OPTMGMT_REQ   T_SVR4_OPTMGMT_REQ
 107 #endif  /* _SUN_TPI_VERSION > 0 */
 108 
 109 #define T_ORDREL_REQ    10      /* orderly release req          */
 110 
 111 /*
 112  * Primitives that are initiated by the transport provider.
 113  */
 114 #define T_CONN_IND      11      /* connection indication        */
 115 #define T_CONN_CON      12      /* connection confirmation      */
 116 #define T_DISCON_IND    13      /* disconnect indication        */
 117 #define T_DATA_IND      14      /* data indication              */
 118 #define T_EXDATA_IND    15      /* expeditied data indication   */
 119 #define T_INFO_ACK      16      /* information acknowledgment   */
 120 #define T_BIND_ACK      17      /* bind acknowledment           */
 121 #define T_ERROR_ACK     18      /* error acknowledgment         */
 122 #define T_OK_ACK        19      /* ok acknowledgment            */
 123 #define T_UNITDATA_IND  20      /* unitdata indication          */
 124 #define T_UDERROR_IND   21      /* unitdata error indication    */
 125 #define T_OPTMGMT_ACK   22      /* manage options ack           */
 126 #define T_ORDREL_IND    23      /* orderly release ind          */
 127 /*
 128  * Primitives added to namespace and contain a mix of ones
 129  * initiated by transport user or provider.
 130  */
 131 #define T_ADDR_REQ      24      /* address request              */
 132 #define T_ADDR_ACK      25      /* address acknowledgement      */
 133 
 134 #if _SUN_TPI_VERSION > 0
 135 /*
 136  * Bind request primitive with better address
 137  * binding semantics. (XTI inspired)
 138  * If the requested address is found to be busy,
 139  * an error is returned. (No need to compare addresses on successful
 140  * bind acknowledgement).
 141  */
 142 #define T_BIND_REQ      26      /* bind request                 */
 143 
 144 /*
 145  * Option management request (with XTI inspired semantics)
 146  * The packing of options in option buffer is required to
 147  * be with 'struct T_opthdr' data structure defined later in
 148  * this header.
 149  */
 150 #define T_OPTMGMT_REQ   27 /* manage options req - T_opthdr option header */
 151 #endif /* _SUN_TPI_VERSION > 0 */
 152 
 153 #if _SUN_TPI_VERSION > 1
 154 /*
 155  * The connection response that expects its ACCEPTOR_id to have been
 156  * filled in from the value supplied via a T_CAPABILITY_ACK.
 157  */
 158 #define T_CONN_RES      28      /* connection response          */
 159 
 160 /*
 161  * Capability request and ack.  These primitives are optional and
 162  * subsume the functionality of T_INFO_{REQ,ACK}.
 163  */
 164 #define T_CAPABILITY_REQ        30
 165 #define T_CAPABILITY_ACK        31
 166 #endif /* _SUN_TPI_VERSION > 1 */
 167 
 168 #ifdef _KERNEL
 169 /*
 170  * Sun private TPI extensions. They are currently used for transparently
 171  * passing options through the connection-oriented loopback transport.
 172  * Values assigned to them may change.
 173  *
 174  * T_EXTCONN_IND (extended T_CONN_IND) is used to return dst as well as
 175  * src addr/port.
 176  */
 177 #define T_OPTDATA_REQ   0x1001  /* data (with options) request  */
 178 #define T_OPTDATA_IND   0x1002  /* data (with options) indication */
 179 #define T_EXTCONN_IND   0x1003  /* extended T_CONN_IND to return dst as well */
 180 
 181 #endif /* _KERNEL */
 182 
 183 /*
 184  * The following are the possible states of the Transport
 185  * Service Interface
 186  */
 187 
 188 #define TS_UNBND                0       /* unbound                      */
 189 #define TS_WACK_BREQ            1       /* waiting ack of BIND_REQ      */
 190 #define TS_WACK_UREQ            2       /* waiting ack of UNBIND_REQ    */
 191 #define TS_IDLE                 3       /* idle                         */
 192 #define TS_WACK_OPTREQ          4       /* wait ack options request     */
 193 #define TS_WACK_CREQ            5       /* waiting ack of CONN_REQ      */
 194 #define TS_WCON_CREQ            6       /* waiting confirm of CONN_REQ  */
 195 #define TS_WRES_CIND            7       /* waiting response of CONN_IND */
 196 #define TS_WACK_CRES            8       /* waiting ack of CONN_RES      */
 197 #define TS_DATA_XFER            9       /* data transfer                */
 198 #define TS_WIND_ORDREL          10      /* releasing rd but not wr      */
 199 #define TS_WREQ_ORDREL          11      /* wait to release wr but not rd */
 200 #define TS_WACK_DREQ6           12      /* waiting ack of DISCON_REQ    */
 201 #define TS_WACK_DREQ7           13      /* waiting ack of DISCON_REQ    */
 202 #define TS_WACK_DREQ9           14      /* waiting ack of DISCON_REQ    */
 203 #define TS_WACK_DREQ10          15      /* waiting ack of DISCON_REQ    */
 204 #define TS_WACK_DREQ11          16      /* waiting ack of DISCON_REQ    */
 205 
 206 #define TS_NOSTATES             17
 207 
 208 
 209 /*
 210  * The following structure definitions define the format of the
 211  * stream message block of the above primitives.
 212  * (everything is declared t_scalar_t to ensure proper alignment
 213  * across different machines)
 214  */
 215 
 216 /* connection request */
 217 
 218 struct T_conn_req {
 219         t_scalar_t      PRIM_type;      /* always T_CONN_REQ            */
 220         t_scalar_t      DEST_length;    /* dest addr length             */
 221         t_scalar_t      DEST_offset;    /* dest addr offset             */
 222         t_scalar_t      OPT_length;     /* options length               */
 223         t_scalar_t      OPT_offset;     /* options offset               */
 224 };
 225 
 226 /* connect response */
 227 
 228 /*
 229  * Historical compatibility note for "struct T_conn_res" usage.
 230  *        "QUEUE_ptr" field of type "queue_t" is obsolete to support
 231  *        code portability  and application binary compatibility
 232  *        between ILP32(32-bit) and LP64 (64-bit) environments.
 233  *        Use field "ACCEPTOR_id" instead.
 234  *        For compatibility, drivers using (_SUN_TPI_VERSION >= 2) interface
 235  *        can support treating ACCEPTOR_id content as queue pointer
 236  *        only when PRIM_type is O_T_CONN_RES.
 237  */
 238 struct T_conn_res {
 239         t_scalar_t      PRIM_type;      /* T_CONN_RES (or O_T_CONN_RES) */
 240         t_uscalar_t     ACCEPTOR_id;    /* id of accepting endpoint     */
 241         t_scalar_t      OPT_length;     /* options length               */
 242         t_scalar_t      OPT_offset;     /* options offset               */
 243         t_scalar_t      SEQ_number;     /* sequence number              */
 244 };
 245 
 246 /* disconnect request */
 247 
 248 struct T_discon_req {
 249         t_scalar_t      PRIM_type;      /* always T_DISCON_REQ          */
 250         t_scalar_t      SEQ_number;     /* sequnce number               */
 251 };
 252 
 253 /* data request */
 254 
 255 struct T_data_req {
 256         t_scalar_t      PRIM_type;      /* always T_DATA_REQ            */
 257         t_scalar_t      MORE_flag;      /* more data                    */
 258 };
 259 
 260 /* expedited data request */
 261 
 262 struct T_exdata_req {
 263         t_scalar_t      PRIM_type;      /* always T_EXDATA_REQ          */
 264         t_scalar_t      MORE_flag;      /* more data                    */
 265 };
 266 
 267 /* information request */
 268 
 269 struct T_info_req {
 270         t_scalar_t      PRIM_type;      /* always T_INFO_REQ            */
 271 };
 272 
 273 /* bind request */
 274 
 275 struct T_bind_req {
 276         t_scalar_t      PRIM_type;      /* T_BIND_REQ (or O_T_BIND_REQ) */
 277         t_scalar_t      ADDR_length;    /* addr length                  */
 278         t_scalar_t      ADDR_offset;    /* addr offset                  */
 279         t_uscalar_t     CONIND_number;  /* connect indications requested */
 280 };
 281 
 282 /* unbind request */
 283 
 284 struct T_unbind_req {
 285         t_scalar_t      PRIM_type;      /* always T_UNBIND_REQ          */
 286 };
 287 
 288 /* unitdata request */
 289 
 290 struct T_unitdata_req {
 291         t_scalar_t      PRIM_type;      /* always T_UNITDATA_REQ        */
 292         t_scalar_t      DEST_length;    /* dest addr length             */
 293         t_scalar_t      DEST_offset;    /* dest addr offset             */
 294         t_scalar_t      OPT_length;     /* options length               */
 295         t_scalar_t      OPT_offset;     /* options offset               */
 296 };
 297 
 298 /* manage options request */
 299 
 300 struct T_optmgmt_req {
 301         t_scalar_t      PRIM_type;      /* T_OPTMGMT_REQ or             */
 302                                         /* T_SVR4_OPTMGMT_REQ           */
 303         t_scalar_t      OPT_length;     /* options length               */
 304         t_scalar_t      OPT_offset;     /* options offset               */
 305         t_scalar_t      MGMT_flags;     /* options flags                */
 306 };
 307 
 308 /* orderly release request */
 309 
 310 struct T_ordrel_req {
 311         t_scalar_t      PRIM_type;      /* always T_ORDREL_REQ          */
 312 };
 313 
 314 /* protocol address request */
 315 
 316 struct T_addr_req {
 317         t_scalar_t      PRIM_type;      /* always T_ADDR_REQ            */
 318 };
 319 
 320 /* connect indication */
 321 
 322 struct T_conn_ind {
 323         t_scalar_t      PRIM_type;      /* always T_CONN_IND            */
 324         t_scalar_t      SRC_length;     /* src addr length              */
 325         t_scalar_t      SRC_offset;     /* src addr offset              */
 326         t_scalar_t      OPT_length;     /* option length                */
 327         t_scalar_t      OPT_offset;     /* option offset                */
 328         t_scalar_t      SEQ_number;     /* sequnce number               */
 329 };
 330 
 331 /* connect confirmation */
 332 
 333 struct T_conn_con {
 334         t_scalar_t      PRIM_type;      /* always T_CONN_CON            */
 335         t_scalar_t      RES_length;     /* responding addr length       */
 336         t_scalar_t      RES_offset;     /* responding addr offset       */
 337         t_scalar_t      OPT_length;     /* option length                */
 338         t_scalar_t      OPT_offset;     /* option offset                */
 339 };
 340 
 341 /* disconnect indication */
 342 
 343 struct T_discon_ind {
 344         t_scalar_t      PRIM_type;      /* always T_DISCON_IND          */
 345         t_scalar_t      DISCON_reason;  /* disconnect reason            */
 346         t_scalar_t      SEQ_number;     /* sequnce number               */
 347 };
 348 
 349 /* data indication */
 350 
 351 struct T_data_ind {
 352         t_scalar_t      PRIM_type;      /* always T_DATA_IND            */
 353         t_scalar_t      MORE_flag;      /* more data                    */
 354 };
 355 
 356 /* expedited data indication */
 357 
 358 struct T_exdata_ind {
 359         t_scalar_t      PRIM_type;      /* always T_EXDATA_IND          */
 360         t_scalar_t      MORE_flag;      /* more data                    */
 361 };
 362 
 363 /* information acknowledgment */
 364 
 365 struct T_info_ack {
 366         t_scalar_t      PRIM_type;      /* always T_INFO_ACK            */
 367         t_scalar_t      TSDU_size;      /* max TSDU size                */
 368         t_scalar_t      ETSDU_size;     /* max ETSDU size               */
 369         t_scalar_t      CDATA_size;     /* max connect data size        */
 370         t_scalar_t      DDATA_size;     /* max discon data size         */
 371         t_scalar_t      ADDR_size;      /* address size                 */
 372         t_scalar_t      OPT_size;       /* options size                 */
 373         t_scalar_t      TIDU_size;      /* max TIDU size                */
 374         t_scalar_t      SERV_type;      /* provider service type        */
 375         t_scalar_t      CURRENT_state;  /* current state                */
 376         t_scalar_t      PROVIDER_flag;  /* provider flags               */
 377 };
 378 
 379 /*
 380  * The following are definitions of flags available to the transport
 381  * provider to set in the PROVIDER_flag field of the T_info_ack
 382  * structure.
 383  */
 384 
 385 #if _SUN_TPI_VERSION > 0
 386 #define SENDZERO        0x0001  /* provider can handle --length TSDUs */
 387 
 388 #define OLD_SENDZERO    0x1000  /* reserved for compatibility with */
 389                                 /* old providers- old value of */
 390                                 /* SENDZERO defined in <sys/timod.h> */
 391 #else
 392 #define SENDZERO        0x1000  /* old SENDZERO value */
 393 #endif /* _SUN_TPI_VERSION > 0 */
 394 
 395 #define EXPINLINE       0x0002  /* provider wants ETSDUs in band 0 */
 396 /*
 397  * Flag XPG4_1:
 398  *              transport provider supports TPI modifications motivated by and
 399  *              in conjunction with XTI inspired TPI support and all the
 400  *              compatibility baggage that implies.
 401  *    It implies, - primitives T_ADDR_REQ & T_ADDR_ACK supported
 402  *                - primitives O_T_BIND_REQ & T_BIND_REQ separately supported
 403  *                - primitives T_SVR4_OPTMGMT_REQ & T_OPTMGMT_REQ separately
 404  *                  supported.
 405  */
 406 #define XPG4_1          0x0004
 407 
 408 /* bind acknowledgment */
 409 
 410 struct T_bind_ack {
 411         t_scalar_t      PRIM_type;      /* always T_BIND_ACK            */
 412         t_scalar_t      ADDR_length;    /* addr length                  */
 413         t_scalar_t      ADDR_offset;    /* addr offset                  */
 414         t_uscalar_t     CONIND_number;  /* connect ind to be queued     */
 415 };
 416 
 417 /* error acknowledgment */
 418 
 419 struct T_error_ack {
 420         t_scalar_t      PRIM_type;      /* always T_ERROR_ACK           */
 421         t_scalar_t      ERROR_prim;     /* primitive in error           */
 422         t_scalar_t      TLI_error;      /* TLI error code               */
 423         t_scalar_t      UNIX_error;     /* UNIX error code              */
 424 };
 425 
 426 /* ok acknowledgment */
 427 
 428 struct T_ok_ack {
 429         t_scalar_t      PRIM_type;      /* always T_OK_ACK              */
 430         t_scalar_t      CORRECT_prim;   /* correct primitive            */
 431 };
 432 
 433 /* unitdata indication */
 434 
 435 struct T_unitdata_ind {
 436         t_scalar_t      PRIM_type;      /* always T_UNITDATA_IND        */
 437         t_scalar_t      SRC_length;     /* source addr length           */
 438         t_scalar_t      SRC_offset;     /* source addr offset           */
 439         t_scalar_t      OPT_length;     /* options length               */
 440         t_scalar_t      OPT_offset;     /* options offset               */
 441 };
 442 
 443 /* unitdata error indication */
 444 
 445 struct T_uderror_ind {
 446         t_scalar_t      PRIM_type;      /* always T_UDERROR_IND         */
 447         t_scalar_t      DEST_length;    /* dest addr length             */
 448         t_scalar_t      DEST_offset;    /* dest addr offset             */
 449         t_scalar_t      OPT_length;     /* options length               */
 450         t_scalar_t      OPT_offset;     /* options offset               */
 451         t_scalar_t      ERROR_type;     /* error type                   */
 452 };
 453 
 454 /* manage options ack */
 455 
 456 struct T_optmgmt_ack {
 457         t_scalar_t      PRIM_type;      /* always T_OPTMGMT_ACK         */
 458         t_scalar_t      OPT_length;     /* options length               */
 459         t_scalar_t      OPT_offset;     /* options offset               */
 460         t_scalar_t      MGMT_flags;     /* managment flags              */
 461 };
 462 
 463 /* orderly release indication */
 464 
 465 struct T_ordrel_ind {
 466         t_scalar_t      PRIM_type;      /* always T_ORDREL_IND          */
 467 };
 468 
 469 
 470 /* protocol address acknowledgment */
 471 
 472 struct T_addr_ack {
 473         t_scalar_t      PRIM_type;      /* always T_ADDR_ACK            */
 474         t_scalar_t      LOCADDR_length; /* length of local address      */
 475         t_scalar_t      LOCADDR_offset; /* offset of local address      */
 476         t_scalar_t      REMADDR_length; /* length of remote address     */
 477         t_scalar_t      REMADDR_offset; /* offset of remote address     */
 478 };
 479 
 480 #if _SUN_TPI_VERSION > 1
 481 /*
 482  * Capability request and ack.  These primitives are optional and
 483  * subsume the functionality of T_INFO_{REQ,ACK}.
 484  */
 485 struct T_capability_req {
 486         t_scalar_t      PRIM_type;      /* always T_CAPABILITY_REQ      */
 487         t_uscalar_t     CAP_bits1;      /* capability bits #1           */
 488 };
 489 
 490 struct T_capability_ack {
 491         t_scalar_t      PRIM_type;      /* always T_CAPABILITY_ACK      */
 492         t_uscalar_t     CAP_bits1;      /* capability bits #1           */
 493         struct T_info_ack
 494                         INFO_ack;       /* info acknowledgement         */
 495         t_uscalar_t     ACCEPTOR_id;    /* accepting endpoint id        */
 496 };
 497 
 498 #define TC1_INFO        (1u << 0) /* Info request/ack             */
 499 #define TC1_ACCEPTOR_ID (1u << 1) /* Acceptor_id request/ack      */
 500 #define TC1_CAP_BITS2   (1u << 31)        /* Reserved for future use      */
 501 
 502 #endif /* _SUN_TPI_VERSION > 1 */
 503 
 504 #ifdef _KERNEL
 505 /*
 506  * Private Sun TPI extensions.
 507  */
 508 
 509 /* data (with options) request */
 510 struct T_optdata_req {
 511         t_scalar_t      PRIM_type;      /* always T_OPTDATA_REQ         */
 512         t_scalar_t      DATA_flag;      /* flags like "more data"       */
 513         t_scalar_t      OPT_length;     /* options length               */
 514         t_scalar_t      OPT_offset;     /* options offset               */
 515 };
 516 
 517 /* data (with options) indication */
 518 struct T_optdata_ind {
 519         t_scalar_t      PRIM_type;      /* always T_OPTDATA_IND         */
 520         t_scalar_t      DATA_flag;      /* flags like "more data"       */
 521         t_scalar_t      OPT_length;     /* options length               */
 522         t_scalar_t      OPT_offset;     /* options offset               */
 523 };
 524 
 525 /* extended connect indication to return dst addr/port as well as src */
 526 struct T_extconn_ind {
 527         t_scalar_t      PRIM_type;      /* always T_EXTCONN_IND         */
 528         t_scalar_t      SRC_length;     /* src addr length              */
 529         t_scalar_t      SRC_offset;     /* src addr offset              */
 530         t_scalar_t      OPT_length;     /* option length                */
 531         t_scalar_t      OPT_offset;     /* option offset                */
 532         t_scalar_t      SEQ_number;     /* sequnce number               */
 533         t_scalar_t      DEST_length;    /* dest addr length             */
 534         t_scalar_t      DEST_offset;    /* dest addr offset             */
 535 };
 536 #endif /* _KERNEL */
 537 
 538 /*
 539  * The following is a union of the primitives
 540  */
 541 union T_primitives {
 542         t_scalar_t              type;           /* primitive type       */
 543         struct T_conn_req       conn_req;       /* connect request      */
 544         struct T_conn_res       conn_res;       /* connect response     */
 545         struct T_discon_req     discon_req;     /* disconnect request   */
 546         struct T_data_req       data_req;       /* data request         */
 547         struct T_exdata_req     exdata_req;     /* expedited data req   */
 548         struct T_info_req       info_req;       /* information req      */
 549         struct T_bind_req       bind_req;       /* bind request         */
 550         struct T_unbind_req     unbind_req;     /* unbind request       */
 551         struct T_unitdata_req   unitdata_req;   /* unitdata requset     */
 552         struct T_optmgmt_req    optmgmt_req;    /* manage opt req       */
 553         struct T_ordrel_req     ordrel_req;     /* orderly rel req      */
 554         struct T_addr_req       addr_req;       /* address request      */
 555         struct T_conn_ind       conn_ind;       /* connect indication   */
 556         struct T_conn_con       conn_con;       /* connect corfirm      */
 557         struct T_discon_ind     discon_ind;     /* discon indication    */
 558         struct T_data_ind       data_ind;       /* data indication      */
 559         struct T_exdata_ind     exdata_ind;     /* expedited data ind   */
 560         struct T_info_ack       info_ack;       /* info ack             */
 561         struct T_bind_ack       bind_ack;       /* bind ack             */
 562         struct T_error_ack      error_ack;      /* error ack            */
 563         struct T_ok_ack         ok_ack;         /* ok ack               */
 564         struct T_unitdata_ind   unitdata_ind;   /* unitdata ind         */
 565         struct T_uderror_ind    uderror_ind;    /* unitdata error ind   */
 566         struct T_optmgmt_ack    optmgmt_ack;    /* manage opt ack       */
 567         struct T_ordrel_ind     ordrel_ind;     /* orderly rel ind      */
 568         struct T_addr_ack       addr_ack;       /* address ack          */
 569 #if _SUN_TPI_VERSION > 1
 570         struct T_capability_req capability_req; /* capability req       */
 571         struct T_capability_ack capability_ack; /* capability ack       */
 572 #endif /* _SUN_TPI_VERSION > 1 */
 573 #ifdef _KERNEL
 574         struct T_optdata_req    optdata_req;    /* option data request  */
 575         struct T_optdata_ind    optdata_ind;    /* option data ind      */
 576         struct T_extconn_ind    extconn_ind;    /* above plus dst addr  */
 577 #endif /* _KERNEL */
 578 };
 579 
 580 /*
 581  * TPI specification is not clear on how to pack options in option
 582  * buffers. What follows is the Solaris TPI interpretation of it.
 583  *
 584  * struct T_opthdr data structure is used to pack options in T_OPTMGMT_{REQ,ACK}
 585  * message primitives in buffer delimited by [OPT_offset, OPT_length] fields in
 586  * struct T_optmgmt_req/T_optmgmt_ack data structures.
 587  *
 588  * It is also used to pack options in similar buffers for data structures in
 589  * T_CONN_{REQ,IND,RES,CONN} primitives and T_UNITDATA_{REQ,IND} primitives
 590  * Needs to be on t_uscalar_t (32-bit word) aligned boundary.
 591  *
 592  * Note: T_SVR4_OPTMGMT_REQ primitive can, but need not, use this data
 593  *       structure for packing options. The format of option buffer for
 594  *       T_SVR4_OPTMGMT_REQ primitive is undefined and is a private contract
 595  *       between transport provider and its users.
 596  *
 597  * |<--------------first option---------------->|     |<--second option--...
 598  * ______________________________________ _ _ _ ____________________________
 599  * | len | level | name | status |  value.......| / / | len ...
 600  * -------------------------------------- - - - ----------------------------
 601  * |32bit| 32bit |32bit |  32bit |                 ^  | 32bit...
 602  *                                                 |
 603  *                                                 |
 604  *                                        alignment characters
 605  */
 606 struct T_opthdr {
 607         t_uscalar_t     len;    /* total length of option (header+value) */
 608         t_uscalar_t     level;  /* protocol level */
 609         t_uscalar_t     name;   /* option name */
 610         t_uscalar_t     status; /* status value */
 611         /* option value aligned on t_uscalar_t (32-bit) alignment boundary */
 612 };
 613 
 614 /*
 615  * ------------------------------------------------------------------------
 616  * Common experimental private TPI alignment related macros. Not for
 617  * use outside Solaris bundled code and can change in any release.
 618  * The alignment boundary _TPI_ALIGN_SIZE represents an implementation
 619  * choice for aligning many data objects which are directly or indirectly
 620  * associated with Solaris TPI implementation.
 621  * ------------------------------------------------------------------------
 622  */
 623 
 624 #define __TPI_ALIGN_SIZE                (sizeof (t_scalar_t))
 625 #define __TPI_ALIGN(x) \
 626         (((uintptr_t)(x) + __TPI_ALIGN_SIZE - 1) & ~(__TPI_ALIGN_SIZE - 1))
 627 #define __TPI_SIZE_ISALIGNED(x) \
 628                 (((uintptr_t)(x) & (__TPI_ALIGN_SIZE - 1)) == 0)
 629 
 630 /*
 631  * TPI primitive in message must be aligned at _TPI_ALIGN_SIZE boundary
 632  */
 633 #define __TPI_PRIM_ISALIGNED(x) __TPI_SIZE_ISALIGNED(x)
 634 
 635 /*
 636  * TPI option header "struct opthdr" objects must be aligned
 637  * at __TPI_ALIGN_SIZE boundary.
 638  */
 639 #define __TPI_OPT_ISALIGNED(x)  __TPI_SIZE_ISALIGNED(x)
 640 #define _TPI_ALIGN_OPT(x)       __TPI_ALIGN(x)
 641 
 642 /*
 643  * TPI option header "struct T_opthdr" objects must be aligned
 644  * at __TPI_ALIGN_SIZE boundary.
 645  */
 646 #define __TPI_TOPT_ISALIGNED(x) __TPI_SIZE_ISALIGNED(x)
 647 #define _TPI_ALIGN_TOPT(x)      __TPI_ALIGN(x)
 648 
 649 /*
 650  * --------------------------------------------------------------------
 651  * Private experimental macros. Not for use outside Solaris bundled
 652  * source code and can change in any release.
 653  * Macros that operate on struct T_opthdr. These are roughly modelled
 654  * after the corresponding Socket CMSG_*() and XTI T_OPT_*() macros, but
 655  * are applied to TPI option buffers.
 656  * --------------------------------------------------------------------
 657  *
 658  * unsigned char *
 659  * _TPI_TOPT_DATA(struct T_opthdr *tohp):
 660  *      Get start of data part after option header
 661  */
 662 #define _TPI_TOPT_DATA(tohp)    \
 663         ((unsigned char *)((char *)(tohp) + sizeof (struct T_opthdr)))
 664 
 665 /*
 666  * t_uscalar_t
 667  * _TPI_TOPT_DATALEN(tohp)
 668  *      Get length of contents of option data excluding header (and
 669  *      padding etc if any).
 670  */
 671 #define _TPI_TOPT_DATALEN(tohp) ((tohp)->len - sizeof (struct T_opthdr))
 672 
 673 /*
 674  * struct T_opthdr *
 675  * _TPI_TOPT_FIRSTHDR(char *pbuf, t_scalar_t buflen):
 676  *      Get pointer to the first option header in buffer 'pbuf'
 677  *      Return NULL if there is not enough room for the header
 678  *
 679  * struct T_opthdr *
 680  * _TPI_TOPT_NEXTHDR(char *pbuf, t_scalar_t buflen,
 681  *                                      struct T_opthdr *popt):
 682  *      Skip to next option header
 683  *
 684  * Notes:  _TPI_TOPT_NEXTHDR performs the roundup of the length.
 685  *
 686  *      If _TPI_TOPT_{FIRST,NEXT}HDR returns a non-null value, the user of
 687  *      _TPI_TOPT_{FIRST,NEXT}HDR must still verify that the resulting pointer
 688  *      is valid, by making a call to _TPI_TOPT_VALID. The _TPI_TOPT_VALID
 689  *      macro does not assume that the last option buffer is padded.
 690  */
 691 #define _TPI_TOPT_FIRSTHDR(pbuf, buflen) \
 692         ((((buflen) >= (unsigned int) sizeof (struct T_opthdr)) && \
 693                 __TPI_TOPT_ISALIGNED(pbuf)) ? \
 694             (struct T_opthdr *)(pbuf) : (struct T_opthdr *)0)
 695 
 696 #define _TPI_TOPT_NEXTHDR(pbuf, buflen, popt) \
 697         (((char *)(popt) + _TPI_ALIGN_TOPT((popt)->len)) < \
 698             ((char *)(pbuf) + (buflen)) ?  \
 699         (struct T_opthdr *)((char *)(popt) + _TPI_ALIGN_TOPT((popt)->len)) : \
 700             (struct T_opthdr *)0)
 701 
 702 /*
 703  * bool_t
 704  * _TPI_TOPT_VALID(struct T_opthdr *tohp, char *start, char *end)
 705  *      Validate the option header at tohp, for its alignment and length.
 706  *      1. check that tohp is aligned at t_scalar_t boundary
 707  *      2. check that start <= tohp < end
 708  *      3. validate the length, should be >= sizeof(T_opthdr) and
 709  *         check that there is no pointer arithmetic overflow.
 710  *         (could be caused by a very large value for tohp->len)
 711  */
 712 
 713 #define _TPI_TOPT_VALID(tohp, start, end)                       \
 714         (__TPI_TOPT_ISALIGNED(tohp) &&                          \
 715         ((uintptr_t)(tohp) >= (uintptr_t)(start)) &&         \
 716         ((uintptr_t)(tohp) < (uintptr_t)(end)) &&            \
 717         ((ssize_t)(tohp)->len >= sizeof (struct T_opthdr)) &&     \
 718         ((uintptr_t)(tohp) + (tohp)->len <= (uintptr_t)(end)) && \
 719         ((uintptr_t)(tohp) + (tohp)->len >= (uintptr_t)(tohp) +   \
 720             sizeof (struct T_opthdr)))
 721 
 722 #ifdef __cplusplus
 723 }
 724 #endif
 725 
 726 #endif /* _SYS_TIHDR_H */