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 */