4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
25 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
26 /* All Rights Reserved */
30 * Transport Interface Library cooperating module - issue 2
33 #include <sys/param.h>
34 #include <sys/types.h>
35 #include <sys/stream.h>
36 #include <sys/stropts.h>
37 #include <sys/strsubr.h>
38 #define _SUN_TPI_VERSION 2
39 #include <sys/tihdr.h>
40 #include <sys/timod.h>
41 #include <sys/suntpi.h>
42 #include <sys/debug.h>
43 #include <sys/strlog.h>
44 #include <sys/errno.h>
46 #include <sys/cmn_err.h>
48 #include <sys/sysmacros.h>
50 #include <sys/sunddi.h>
51 #include <sys/strsun.h>
55 * This is the loadable module wrapper.
58 #include <sys/modctl.h>
60 static struct streamtab timinfo
;
62 static struct fmodsw fsw
= {
69 * Module linkage information for the kernel.
72 static struct modlstrmod modlstrmod
= {
73 &mod_strmodops
, "transport interface str mod", &fsw
76 static struct modlinkage modlinkage
= {
77 MODREV_1
, &modlstrmod
, NULL
80 static krwlock_t tim_list_rwlock
;
83 * This module keeps track of capabilities of underlying transport. Information
84 * is persistent through module invocations (open/close). Currently it remembers
85 * whether underlying transport supports TI_GET{MY,PEER}NAME ioctls and
86 * T_CAPABILITY_REQ message. This module either passes ioctl/messages to the
87 * transport or emulates it when transport doesn't understand these
90 * It is assumed that transport supports T_CAPABILITY_REQ when timod receives
91 * T_CAPABILITY_ACK from the transport. There is no current standard describing
92 * transport behaviour when it receives unknown message type, so following
93 * reactions are expected and handled:
95 * 1) Transport drops unknown T_CAPABILITY_REQ message type. In this case timod
96 * will wait for tcap_wait time and assume that transport doesn't provide
97 * this message type. T_CAPABILITY_REQ should never travel over the wire, so
98 * timeout value should only take into consideration internal processing time
99 * for the message. From user standpoint it may mean that an application will
100 * hang for TCAP_WAIT time in the kernel the first time this message is used
101 * with some particular transport (e.g. TCP/IP) during system uptime.
103 * 2) Transport responds with T_ERROR_ACK specifying T_CAPABILITY_REQ as
104 * original message type. In this case it is assumed that transport doesn't
105 * support it (which may not always be true - some transports return
106 * T_ERROR_ACK in other cases like lack of system memory).
108 * 3) Transport responds with M_ERROR, effectively shutting down the
109 * stream. Unfortunately there is no standard way to pass the reason of
110 * M_ERROR message back to the caller, so it is assumed that if M_ERROR was
111 * sent in response to T_CAPABILITY_REQ message, transport doesn't support
114 * It is possible under certain circumstances that timod will incorrectly assume
115 * that underlying transport doesn't provide T_CAPABILITY_REQ message type. In
116 * this "worst-case" scenario timod will emulate its functionality by itself and
117 * will provide only TC1_INFO capability. All other bits in CAP_bits1 field are
118 * cleaned. TC1_INFO is emulated by sending T_INFO_REQ down to transport
123 * Notes about locking:
125 * tim_list_rwlock protects the list of tim_tim structures itself. When this
126 * lock is held, the list itself is stable, but the contents of the entries
127 * themselves might not be.
129 * The rest of the members are generally protected by D_MTQPAIR, which
130 * specifies a default exclusive inner perimeter. If you're looking at
131 * q->q_ptr, then it's stable.
133 * There's one exception to this rule: tim_peer{maxlen,len,name}. These members
134 * are touched without entering the associated STREAMS perimeter because we
135 * get the pointer via tim_findlink() rather than q_ptr. These are protected
136 * by tim_mutex instead. If you don't hold that lock, don't look at them.
138 * (It would be possible to separate out the 'set by T_CONN_RES' cases from the
139 * others, but there appears to be no reason to do so.)
143 t_uscalar_t tim_backlog
;
145 t_scalar_t tim_mymaxlen
;
146 t_scalar_t tim_mylen
;
148 t_scalar_t tim_peermaxlen
;
149 t_scalar_t tim_peerlen
;
150 caddr_t tim_peername
;
151 cred_t
*tim_peercred
;
153 bufcall_id_t tim_wbufcid
;
154 bufcall_id_t tim_rbufcid
;
155 timeout_id_t tim_wtimoutid
;
156 timeout_id_t tim_rtimoutid
;
157 /* Protected by the global tim_list_rwlock for all instances */
158 struct tim_tim
*tim_next
;
159 struct tim_tim
**tim_ptpn
;
160 t_uscalar_t tim_acceptor
;
161 t_scalar_t tim_saved_prim
; /* Primitive from message */
163 timeout_id_t tim_tcap_timoutid
; /* For T_CAP_REQ timeout */
164 tpi_provinfo_t
*tim_provinfo
; /* Transport description */
165 kmutex_t tim_mutex
; /* protect tim_peer* */
171 * Local flags used with tim_flags field in instance structure of
172 * type 'struct _ti_user' declared above.
174 * This namespace constants were previously declared in a
175 * a very messed up namespace in timod.h
177 * There may be 3 states for transport:
179 * 1) It provides T_CAPABILITY_REQ
180 * 2) It does not provide T_CAPABILITY_REQ
181 * 3) It is not known yet whether transport provides T_CAPABILITY_REQ or not.
183 * It is assumed that the underlying transport either provides
184 * T_CAPABILITY_REQ or not and this does not changes during the
188 #define PEEK_RDQ_EXPIND 0x0001 /* look for expinds on stream rd queues */
189 #define WAITIOCACK 0x0002 /* waiting for info for ioctl act */
190 #define CLTS 0x0004 /* connectionless transport */
191 #define COTS 0x0008 /* connection-oriented transport */
192 #define CONNWAIT 0x0010 /* waiting for connect confirmation */
193 #define LOCORDREL 0x0020 /* local end has orderly released */
194 #define REMORDREL 0x0040 /* remote end had orderly released */
195 #define NAMEPROC 0x0080 /* processing a NAME ioctl */
196 #define DO_MYNAME 0x0100 /* timod handles TI_GETMYNAME */
197 #define DO_PEERNAME 0x0200 /* timod handles TI_GETPEERNAME */
198 #define TI_CAP_RECVD 0x0400 /* TI_CAPABILITY received */
199 #define CAP_WANTS_INFO 0x0800 /* TI_CAPABILITY has TC1_INFO set */
200 #define WAIT_IOCINFOACK 0x1000 /* T_INFO_REQ generated from ioctl */
201 #define WAIT_CONNRESACK 0x2000 /* waiting for T_OK_ACK to T_CONN_RES */
204 /* Debugging facilities */
206 * Logging needed for debugging timod should only appear in DEBUG kernel.
209 #define TILOG(msg, arg) tilog((msg), (arg))
210 #define TILOGP(msg, arg) tilogp((msg), (arg))
212 #define TILOG(msg, arg)
213 #define TILOGP(msg, arg)
218 * Sleep timeout for T_CAPABILITY_REQ. This message never travels across
219 * network, so timeout value should be enough to cover all internal processing
222 clock_t tim_tcap_wait
= 2;
224 /* Sleep timeout in tim_recover() */
225 #define TIMWAIT (1*hz)
226 /* Sleep timeout in tim_ioctl_retry() 0.2 seconds */
227 #define TIMIOCWAIT (200*hz/1000)
230 * Return values for ti_doname().
232 #define DONAME_FAIL 0 /* failing ioctl (done) */
233 #define DONAME_DONE 1 /* done processing */
234 #define DONAME_CONT 2 /* continue proceesing (not done yet) */
237 * Function prototypes
239 static int ti_doname(queue_t
*, mblk_t
*);
240 static int ti_expind_on_rdqueues(queue_t
*);
241 static void tim_ioctl_send_reply(queue_t
*, mblk_t
*, mblk_t
*);
242 static void tim_send_ioc_error_ack(queue_t
*, struct tim_tim
*, mblk_t
*);
243 static void tim_tcap_timer(void *);
244 static void tim_tcap_genreply(queue_t
*, struct tim_tim
*);
245 static void tim_send_reply(queue_t
*, mblk_t
*, struct tim_tim
*, t_scalar_t
);
246 static void tim_answer_ti_sync(queue_t
*, mblk_t
*, struct tim_tim
*,
248 static void tim_send_ioctl_tpi_msg(queue_t
*, mblk_t
*, struct tim_tim
*,
250 static void tim_clear_peer(struct tim_tim
*);
257 rw_init(&tim_list_rwlock
, NULL
, RW_DRIVER
, NULL
);
258 error
= mod_install(&modlinkage
);
260 rw_destroy(&tim_list_rwlock
);
272 error
= mod_remove(&modlinkage
);
275 rw_destroy(&tim_list_rwlock
);
280 _info(struct modinfo
*modinfop
)
282 return (mod_info(&modlinkage
, modinfop
));
287 * Hash list for all instances. Used to find tim_tim structure based on
288 * ACCEPTOR_id in T_CONN_RES. Protected by tim_list_rwlock.
290 #define TIM_HASH_SIZE 256
292 #define TIM_HASH(id) (((uintptr_t)(id) >> 8) % TIM_HASH_SIZE)
294 #define TIM_HASH(id) ((uintptr_t)(id) % TIM_HASH_SIZE)
296 static struct tim_tim
*tim_hash
[TIM_HASH_SIZE
];
299 static void tilog(char *, t_scalar_t
);
300 static void tilogp(char *, uintptr_t);
301 static mblk_t
*tim_filladdr(queue_t
*, mblk_t
*, boolean_t
);
302 static void tim_addlink(struct tim_tim
*);
303 static void tim_dellink(struct tim_tim
*);
304 static struct tim_tim
*tim_findlink(t_uscalar_t
);
305 static void tim_recover(queue_t
*, mblk_t
*, t_scalar_t
);
306 static void tim_ioctl_retry(queue_t
*);
312 static int timodopen(queue_t
*, dev_t
*, int, int, cred_t
*);
313 static int timodclose(queue_t
*, int, cred_t
*);
314 static void timodwput(queue_t
*, mblk_t
*);
315 static void timodrput(queue_t
*, mblk_t
*);
316 static void timodrsrv(queue_t
*);
317 static void timodwsrv(queue_t
*);
318 static int timodrproc(queue_t
*, mblk_t
*);
319 static int timodwproc(queue_t
*, mblk_t
*);
321 /* stream data structure definitions */
323 static struct module_info timod_info
=
324 {TIMOD_ID
, "timod", 0, INFPSZ
, 512, 128};
325 static struct qinit timodrinit
= {
326 (int (*)())timodrput
,
327 (int (*)())timodrsrv
,
334 static struct qinit timodwinit
= {
335 (int (*)())timodwput
,
336 (int (*)())timodwsrv
,
343 static struct streamtab timinfo
= { &timodrinit
, &timodwinit
, NULL
, NULL
};
346 * timodopen - open routine gets called when the module gets pushed
359 struct stroptions
*sop
;
368 if ((bp
= allocb(sizeof (struct stroptions
), BPRI_MED
)) == 0)
371 tp
= kmem_zalloc(sizeof (struct tim_tim
), KM_SLEEP
);
374 tp
->tim_saved_prim
= -1;
376 mutex_init(&tp
->tim_mutex
, NULL
, MUTEX_DEFAULT
, NULL
);
378 q
->q_ptr
= (caddr_t
)tp
;
379 WR(q
)->q_ptr
= (caddr_t
)tp
;
381 tilogp("timodopen: Allocated for tp %lx\n", (uintptr_t)tp
);
382 tilogp("timodopen: Allocated for q %lx\n", (uintptr_t)q
);
384 /* Must be done before tpi_findprov and _ILP32 q_next walk below */
387 tp
->tim_provinfo
= tpi_findprov(q
);
390 * Defer allocation of the buffers for the local address and
391 * the peer's address until we need them.
392 * Assume that timod has to handle getname until we here
393 * an iocack from the transport provider or we know that
394 * transport provider doesn't understand it.
396 if (tp
->tim_provinfo
->tpi_myname
!= PI_YES
) {
397 TILOG("timodopen: setting DO_MYNAME\n", 0);
398 tp
->tim_flags
|= DO_MYNAME
;
401 if (tp
->tim_provinfo
->tpi_peername
!= PI_YES
) {
402 TILOG("timodopen: setting DO_PEERNAME\n", 0);
403 tp
->tim_flags
|= DO_PEERNAME
;
411 * Find my driver's read queue (for T_CONN_RES handling)
414 while (SAMESTR(driverq
))
415 driverq
= driverq
->q_next
;
417 tp
->tim_acceptor
= (t_uscalar_t
)RD(driverq
);
420 tp
->tim_acceptor
= (t_uscalar_t
)getminor(*devp
);
424 * Add this one to the list.
429 * Send M_SETOPTS to stream head to make sure M_PCPROTO messages
430 * are not flushed. This prevents application deadlocks.
432 bp
->b_datap
->db_type
= M_SETOPTS
;
433 bp
->b_wptr
+= sizeof (struct stroptions
);
434 sop
= (struct stroptions
*)bp
->b_rptr
;
435 sop
->so_flags
= SO_READOPT
;
436 sop
->so_readopt
= RFLUSHPCPROT
;
447 struct tim_tim
*tp
= (struct tim_tim
*)q
->q_ptr
;
451 if (q
->q_flag
& QREADR
) {
452 ASSERT(tp
->tim_rtimoutid
);
453 tp
->tim_rtimoutid
= 0;
455 ASSERT(tp
->tim_wtimoutid
);
456 tp
->tim_wtimoutid
= 0;
463 tim_buffer(void *arg
)
466 struct tim_tim
*tp
= (struct tim_tim
*)q
->q_ptr
;
470 if (q
->q_flag
& QREADR
) {
471 ASSERT(tp
->tim_rbufcid
);
474 ASSERT(tp
->tim_wbufcid
);
482 * timodclose - This routine gets called when the module gets popped
498 tp
= (struct tim_tim
*)q
->q_ptr
;
503 tilogp("timodclose: Entered for tp %lx\n", (uintptr_t)tp
);
504 tilogp("timodclose: Entered for q %lx\n", (uintptr_t)q
);
510 * Cancel any outstanding bufcall
511 * or timeout requests.
513 if (tp
->tim_wbufcid
) {
514 qunbufcall(q
, tp
->tim_wbufcid
);
517 if (tp
->tim_rbufcid
) {
518 qunbufcall(q
, tp
->tim_rbufcid
);
521 if (tp
->tim_wtimoutid
) {
522 (void) quntimeout(q
, tp
->tim_wtimoutid
);
523 tp
->tim_wtimoutid
= 0;
525 if (tp
->tim_rtimoutid
) {
526 (void) quntimeout(q
, tp
->tim_rtimoutid
);
527 tp
->tim_rtimoutid
= 0;
530 if (tp
->tim_tcap_timoutid
!= 0) {
531 (void) quntimeout(q
, tp
->tim_tcap_timoutid
);
532 tp
->tim_tcap_timoutid
= 0;
535 if (tp
->tim_iocsave
!= NULL
)
536 freemsg(tp
->tim_iocsave
);
537 mp
= tp
->tim_consave
;
544 ASSERT(tp
->tim_mymaxlen
>= 0);
545 if (tp
->tim_mymaxlen
!= 0)
546 kmem_free(tp
->tim_myname
, (size_t)tp
->tim_mymaxlen
);
547 ASSERT(tp
->tim_peermaxlen
>= 0);
548 if (tp
->tim_peermaxlen
!= 0)
549 kmem_free(tp
->tim_peername
, (size_t)tp
->tim_peermaxlen
);
551 q
->q_ptr
= WR(q
)->q_ptr
= NULL
;
553 mutex_destroy(&tp
->tim_mutex
);
555 if (tp
->tim_peercred
!= NULL
)
556 crfree(tp
->tim_peercred
);
558 kmem_free(tp
, sizeof (struct tim_tim
));
564 * timodrput - Module read put procedure. This is called from
565 * the module, driver, or stream head upstream/downstream.
566 * Handles M_FLUSH, M_DATA and some M_PROTO (T_DATA_IND,
567 * and T_UNITDATA_IND) messages. All others are queued to
568 * be handled by the service procedures.
571 timodrput(queue_t
*q
, mblk_t
*mp
)
573 union T_primitives
*pptr
;
576 * During flow control and other instances when messages
577 * are on queue, queue up a non high priority message
579 if (q
->q_first
!= 0 && mp
->b_datap
->db_type
< QPCTL
) {
585 * Inline processing of data (to avoid additional procedure call).
586 * Rest is handled in timodrproc.
589 switch (mp
->b_datap
->db_type
) {
591 if (bcanputnext(q
, mp
->b_band
))
598 if (MBLKL(mp
) < sizeof (t_scalar_t
)) {
599 if (mp
->b_datap
->db_type
== M_PCPROTO
||
600 bcanputnext(q
, mp
->b_band
)) {
607 pptr
= (union T_primitives
*)mp
->b_rptr
;
608 switch (pptr
->type
) {
612 if (bcanputnext(q
, mp
->b_band
))
618 (void) timodrproc(q
, mp
);
623 (void) timodrproc(q
, mp
);
629 * timodrsrv - Module read queue service procedure. This is called when
630 * messages are placed on an empty queue, when high priority
631 * messages are placed on the queue, and when flow control
632 * restrictions subside. This code used to be included in a
633 * put procedure, but it was moved to a service procedure
634 * because several points were added where memory allocation
635 * could fail, and there is no reasonable recovery mechanism
636 * from the put procedure.
640 timodrsrv(queue_t
*q
)
647 tp
= (struct tim_tim
*)q
->q_ptr
;
651 while ((mp
= getq(q
)) != NULL
) {
652 if (timodrproc(q
, mp
)) {
654 * timodrproc did a putbq - stop processing
663 * Perform common processing when a T_CAPABILITY_ACK or T_INFO_ACK
664 * arrive. Set the queue properties and adjust the tim_flags according
665 * to the service type.
668 timodprocessinfo(queue_t
*q
, struct tim_tim
*tp
, struct T_info_ack
*tia
)
670 TILOG("timodprocessinfo: strqset(%d)\n", tia
->TIDU_size
);
671 (void) strqset(q
, QMAXPSZ
, 0, tia
->TIDU_size
);
672 (void) strqset(OTHERQ(q
), QMAXPSZ
, 0, tia
->TIDU_size
);
674 if ((tia
->SERV_type
== T_COTS
) || (tia
->SERV_type
== T_COTS_ORD
))
675 tp
->tim_flags
= (tp
->tim_flags
& ~CLTS
) | COTS
;
676 else if (tia
->SERV_type
== T_CLTS
)
677 tp
->tim_flags
= (tp
->tim_flags
& ~COTS
) | CLTS
;
681 timodrproc(queue_t
*q
, mblk_t
*mp
)
683 uint32_t auditing
= AU_AUDITING();
684 union T_primitives
*pptr
;
686 struct iocblk
*iocbp
;
690 tp
= (struct tim_tim
*)q
->q_ptr
;
692 switch (mp
->b_datap
->db_type
) {
698 TILOG("timodrproc: Got M_ERROR, flags = %x\n", tp
->tim_flags
);
700 * There is no specified standard response for driver when it
701 * receives unknown message type and M_ERROR is one
702 * possibility. If we send T_CAPABILITY_REQ down and transport
703 * provider responds with M_ERROR we assume that it doesn't
704 * understand this message type. This assumption may be
705 * sometimes incorrect (transport may reply with M_ERROR for
706 * some other reason) but there is no way for us to distinguish
707 * between different cases. In the worst case timod and everyone
708 * else sharing global transport description with it may end up
709 * emulating T_CAPABILITY_REQ.
713 * Check that we are waiting for T_CAPABILITY_ACK and
714 * T_CAPABILITY_REQ is not implemented by transport or emulated
717 if ((tp
->tim_provinfo
->tpi_capability
== PI_DONTKNOW
) &&
718 ((tp
->tim_flags
& TI_CAP_RECVD
) != 0)) {
720 * Good chances that this transport doesn't provide
721 * T_CAPABILITY_REQ. Mark this information permanently
722 * for the module + transport combination.
724 PI_PROVLOCK(tp
->tim_provinfo
);
725 if (tp
->tim_provinfo
->tpi_capability
== PI_DONTKNOW
)
726 tp
->tim_provinfo
->tpi_capability
= PI_NO
;
727 PI_PROVUNLOCK(tp
->tim_provinfo
);
728 if (tp
->tim_tcap_timoutid
!= 0) {
729 (void) quntimeout(q
, tp
->tim_tcap_timoutid
);
730 tp
->tim_tcap_timoutid
= 0;
736 if (!bcanputnext(q
, mp
->b_band
)) {
746 if (blen
< sizeof (t_scalar_t
)) {
748 * Note: it's not actually possible to get
749 * here with db_type M_PCPROTO, because
750 * timodrput has already checked MBLKL, and
751 * thus the assertion below. If the length
752 * was too short, then the message would have
753 * already been putnext'd, and would thus
754 * never appear here. Just the same, the code
755 * below handles the impossible case since
756 * it's easy to do and saves future
757 * maintainers from unfortunate accidents.
759 ASSERT(mp
->b_datap
->db_type
== M_PROTO
);
760 if (mp
->b_datap
->db_type
== M_PROTO
&&
761 !bcanputnext(q
, mp
->b_band
)) {
769 pptr
= (union T_primitives
*)mp
->b_rptr
;
770 switch (pptr
->type
) {
774 audit_sock(T_UNITDATA_IND
, q
, mp
, TIMOD_ID
);
779 /* Restore db_type - recover() might have changed it */
780 mp
->b_datap
->db_type
= M_PCPROTO
;
781 if (blen
< sizeof (struct T_error_ack
)) {
786 tilog("timodrproc: Got T_ERROR_ACK, flags = %x\n",
789 if ((tp
->tim_flags
& WAIT_CONNRESACK
) &&
790 tp
->tim_saved_prim
== pptr
->error_ack
.ERROR_prim
) {
792 ~(WAIT_CONNRESACK
| WAITIOCACK
);
793 freemsg(tp
->tim_iocsave
);
794 tp
->tim_iocsave
= NULL
;
795 tp
->tim_saved_prim
= -1;
797 } else if (tp
->tim_flags
& WAITIOCACK
) {
798 tim_send_ioc_error_ack(q
, tp
, mp
);
805 if (blen
< sizeof (pptr
->ok_ack
)) {
806 mp
->b_datap
->db_type
= M_PCPROTO
;
811 tilog("timodrproc: Got T_OK_ACK\n", 0);
813 if (pptr
->ok_ack
.CORRECT_prim
== T_UNBIND_REQ
)
816 if ((tp
->tim_flags
& WAIT_CONNRESACK
) &&
817 tp
->tim_saved_prim
== pptr
->ok_ack
.CORRECT_prim
) {
818 struct T_conn_res
*resp
;
819 struct T_conn_ind
*indp
;
823 rw_enter(&tim_list_rwlock
, RW_READER
);
824 resp
= (struct T_conn_res
*)
825 tp
->tim_iocsave
->b_rptr
;
826 ntp
= tim_findlink(resp
->ACCEPTOR_id
);
830 mutex_enter(&ntp
->tim_mutex
);
831 if (ntp
->tim_peercred
!= NULL
)
832 crfree(ntp
->tim_peercred
);
834 msg_getcred(tp
->tim_iocsave
->b_cont
,
836 if (ntp
->tim_peercred
!= NULL
)
837 crhold(ntp
->tim_peercred
);
839 if (!(ntp
->tim_flags
& DO_PEERNAME
)) {
840 mutex_exit(&ntp
->tim_mutex
);
844 indp
= (struct T_conn_ind
*)
845 tp
->tim_iocsave
->b_cont
->b_rptr
;
846 /* true as message is put on list */
847 ASSERT(indp
->SRC_length
>= 0);
849 if (indp
->SRC_length
> ntp
->tim_peermaxlen
) {
850 ptr
= kmem_alloc(indp
->SRC_length
,
853 mutex_exit(&ntp
->tim_mutex
);
854 rw_exit(&tim_list_rwlock
);
855 tilog("timodwproc: kmem_alloc "
856 "failed, attempting "
862 if (ntp
->tim_peermaxlen
> 0)
863 kmem_free(ntp
->tim_peername
,
864 ntp
->tim_peermaxlen
);
865 ntp
->tim_peername
= ptr
;
866 ntp
->tim_peermaxlen
= indp
->SRC_length
;
868 ntp
->tim_peerlen
= indp
->SRC_length
;
869 ptr
= (caddr_t
)indp
+ indp
->SRC_offset
;
870 bcopy(ptr
, ntp
->tim_peername
, ntp
->tim_peerlen
);
872 mutex_exit(&ntp
->tim_mutex
);
875 rw_exit(&tim_list_rwlock
);
877 ~(WAIT_CONNRESACK
| WAITIOCACK
);
878 freemsg(tp
->tim_iocsave
);
879 tp
->tim_iocsave
= NULL
;
880 tp
->tim_saved_prim
= -1;
883 tim_send_reply(q
, mp
, tp
, pptr
->ok_ack
.CORRECT_prim
);
887 struct T_bind_ack
*ackp
=
888 (struct T_bind_ack
*)mp
->b_rptr
;
890 /* Restore db_type - recover() might have changed it */
891 mp
->b_datap
->db_type
= M_PCPROTO
;
892 if (blen
< sizeof (*ackp
)) {
897 /* save negotiated backlog */
898 tp
->tim_backlog
= ackp
->CONIND_number
;
900 if (((tp
->tim_flags
& WAITIOCACK
) == 0) ||
901 ((tp
->tim_saved_prim
!= O_T_BIND_REQ
) &&
902 (tp
->tim_saved_prim
!= T_BIND_REQ
))) {
906 ASSERT(tp
->tim_iocsave
!= NULL
);
908 if (tp
->tim_flags
& DO_MYNAME
) {
911 if (ackp
->ADDR_length
< 0 ||
912 mp
->b_rptr
+ ackp
->ADDR_offset
+
913 ackp
->ADDR_length
> mp
->b_wptr
) {
917 if (ackp
->ADDR_length
> tp
->tim_mymaxlen
) {
918 p
= kmem_alloc(ackp
->ADDR_length
,
921 tilog("timodrproc: kmem_alloc "
922 "failed attempt recovery",
929 ASSERT(tp
->tim_mymaxlen
>= 0);
930 if (tp
->tim_mymaxlen
!= NULL
) {
931 kmem_free(tp
->tim_myname
,
935 tp
->tim_mymaxlen
= ackp
->ADDR_length
;
937 tp
->tim_mylen
= ackp
->ADDR_length
;
938 bcopy(mp
->b_rptr
+ ackp
->ADDR_offset
,
939 tp
->tim_myname
, tp
->tim_mylen
);
941 tim_ioctl_send_reply(q
, tp
->tim_iocsave
, mp
);
942 tp
->tim_iocsave
= NULL
;
943 tp
->tim_saved_prim
= -1;
944 tp
->tim_flags
&= ~(WAITIOCACK
| WAIT_IOCINFOACK
|
945 TI_CAP_RECVD
| CAP_WANTS_INFO
);
951 tilog("timodrproc: Got T_OPTMGMT_ACK\n", 0);
953 /* Restore db_type - recover() might have change it */
954 mp
->b_datap
->db_type
= M_PCPROTO
;
956 if (((tp
->tim_flags
& WAITIOCACK
) == 0) ||
957 ((tp
->tim_saved_prim
!= T_SVR4_OPTMGMT_REQ
) &&
958 (tp
->tim_saved_prim
!= T_OPTMGMT_REQ
))) {
961 ASSERT(tp
->tim_iocsave
!= NULL
);
962 tim_ioctl_send_reply(q
, tp
->tim_iocsave
, mp
);
963 tp
->tim_iocsave
= NULL
;
964 tp
->tim_saved_prim
= -1;
965 tp
->tim_flags
&= ~(WAITIOCACK
|
966 WAIT_IOCINFOACK
| TI_CAP_RECVD
|
972 struct T_info_ack
*tia
= (struct T_info_ack
*)pptr
;
974 /* Restore db_type - recover() might have changed it */
975 mp
->b_datap
->db_type
= M_PCPROTO
;
977 if (blen
< sizeof (*tia
)) {
982 tilog("timodrproc: Got T_INFO_ACK, flags = %x\n",
985 timodprocessinfo(q
, tp
, tia
);
987 TILOG("timodrproc: flags = %x\n", tp
->tim_flags
);
988 if ((tp
->tim_flags
& WAITIOCACK
) != 0) {
989 size_t expected_ack_size
;
992 struct T_capability_ack
*tcap
;
995 * The only case when T_INFO_ACK may be received back
996 * when we are waiting for ioctl to complete is when
997 * this ioctl sent T_INFO_REQ down.
999 if (!(tp
->tim_flags
& WAIT_IOCINFOACK
)) {
1003 ASSERT(tp
->tim_iocsave
!= NULL
);
1005 iocbp
= (struct iocblk
*)tp
->tim_iocsave
->b_rptr
;
1006 ioc_cmd
= iocbp
->ioc_cmd
;
1009 * Was it sent from TI_CAPABILITY emulation?
1011 if (ioc_cmd
== TI_CAPABILITY
) {
1012 struct T_info_ack saved_info
;
1015 * Perform sanity checks. The only case when we
1016 * send T_INFO_REQ from TI_CAPABILITY is when
1017 * timod emulates T_CAPABILITY_REQ and CAP_bits1
1020 if ((tp
->tim_flags
&
1021 (TI_CAP_RECVD
| CAP_WANTS_INFO
)) !=
1022 (TI_CAP_RECVD
| CAP_WANTS_INFO
)) {
1027 TILOG("timodrproc: emulating TI_CAPABILITY/"
1030 /* Save info & reuse mp for T_CAPABILITY_ACK */
1033 mp
= tpi_ack_alloc(mp
,
1034 sizeof (struct T_capability_ack
),
1035 M_PCPROTO
, T_CAPABILITY_ACK
);
1038 tilog("timodrproc: realloc failed, "
1039 "no recovery attempted\n", 0);
1044 * Copy T_INFO information into T_CAPABILITY_ACK
1046 tcap
= (struct T_capability_ack
*)mp
->b_rptr
;
1047 tcap
->CAP_bits1
= TC1_INFO
;
1048 tcap
->INFO_ack
= saved_info
;
1049 tp
->tim_flags
&= ~(WAITIOCACK
|
1050 WAIT_IOCINFOACK
| TI_CAP_RECVD
|
1052 tim_ioctl_send_reply(q
, tp
->tim_iocsave
, mp
);
1053 tp
->tim_iocsave
= NULL
;
1054 tp
->tim_saved_prim
= -1;
1059 * The code for TI_SYNC/TI_GETINFO is left here only for
1060 * backward compatibility with staticaly linked old
1061 * applications. New TLI/XTI code should use
1062 * TI_CAPABILITY for getting transport info and should
1063 * not use TI_GETINFO/TI_SYNC for this purpose.
1067 * make sure the message sent back is the size of
1068 * the "expected ack"
1069 * For TI_GETINFO, expected ack size is
1070 * sizeof (T_info_ack)
1071 * For TI_SYNC, expected ack size is
1072 * sizeof (struct ti_sync_ack);
1074 if (ioc_cmd
!= TI_GETINFO
&& ioc_cmd
!= TI_SYNC
) {
1080 sizeof (struct T_info_ack
); /* TI_GETINFO */
1081 if (iocbp
->ioc_cmd
== TI_SYNC
) {
1082 expected_ack_size
= 2 * sizeof (uint32_t) +
1083 sizeof (struct ti_sync_ack
);
1085 deficit
= expected_ack_size
- blen
;
1088 if (mp
->b_datap
->db_lim
- mp
->b_wptr
<
1090 mblk_t
*tmp
= allocb(expected_ack_size
,
1093 ASSERT(MBLKSIZE(mp
) >=
1094 sizeof (struct T_error_ack
));
1096 tilog("timodrproc: allocb failed no "
1097 "recovery attempt\n", 0);
1099 mp
->b_rptr
= mp
->b_datap
->db_base
;
1100 pptr
= (union T_primitives
*)
1102 pptr
->error_ack
.ERROR_prim
= T_INFO_REQ
;
1103 pptr
->error_ack
.TLI_error
= TSYSERR
;
1104 pptr
->error_ack
.UNIX_error
= EAGAIN
;
1105 pptr
->error_ack
.PRIM_type
= T_ERROR_ACK
;
1106 mp
->b_datap
->db_type
= M_PCPROTO
;
1107 tim_send_ioc_error_ack(q
, tp
, mp
);
1110 bcopy(mp
->b_rptr
, tmp
->b_rptr
, blen
);
1111 tmp
->b_wptr
+= blen
;
1112 pptr
= (union T_primitives
*)
1120 * We now have "mp" which has enough space for an
1121 * appropriate ack and contains struct T_info_ack
1122 * that the transport provider returned. We now
1123 * stuff it with more stuff to fullfill
1124 * TI_SYNC ioctl needs, as necessary
1126 if (iocbp
->ioc_cmd
== TI_SYNC
) {
1128 * Assumes struct T_info_ack is first embedded
1129 * type in struct ti_sync_ack so it is
1130 * automatically there.
1132 struct ti_sync_ack
*tsap
=
1133 (struct ti_sync_ack
*)mp
->b_rptr
;
1136 * tsap->tsa_qlen needs to be set only if
1137 * TSRF_QLEN_REQ flag is set, but for
1138 * compatibility with statically linked
1139 * applications it is set here regardless of the
1140 * flag since old XTI library expected it to be
1143 tsap
->tsa_qlen
= tp
->tim_backlog
;
1144 tsap
->tsa_flags
= 0x0; /* intialize clear */
1145 if (tp
->tim_flags
& PEEK_RDQ_EXPIND
) {
1147 * Request to peek for EXPIND in
1150 if (ti_expind_on_rdqueues(q
)) {
1153 * queued on the stream
1162 mp
->b_wptr
+= 2*sizeof (uint32_t);
1164 tim_ioctl_send_reply(q
, tp
->tim_iocsave
, mp
);
1165 tp
->tim_iocsave
= NULL
;
1166 tp
->tim_saved_prim
= -1;
1167 tp
->tim_flags
&= ~(WAITIOCACK
| WAIT_IOCINFOACK
|
1168 TI_CAP_RECVD
| CAP_WANTS_INFO
);
1177 tilog("timodrproc: Got T_ADDR_ACK\n", 0);
1178 tim_send_reply(q
, mp
, tp
, T_ADDR_REQ
);
1182 struct T_conn_ind
*tcip
=
1183 (struct T_conn_ind
*)mp
->b_rptr
;
1185 tilog("timodrproc: Got T_CONN_IND\n", 0);
1187 if (blen
>= sizeof (*tcip
) &&
1188 MBLKIN(mp
, tcip
->SRC_offset
, tcip
->SRC_length
)) {
1189 if (((nbp
= dupmsg(mp
)) != NULL
) ||
1190 ((nbp
= copymsg(mp
)) != NULL
)) {
1191 nbp
->b_next
= tp
->tim_consave
;
1192 tp
->tim_consave
= nbp
;
1195 (t_scalar_t
)sizeof (mblk_t
));
1200 audit_sock(T_CONN_IND
, q
, mp
, TIMOD_ID
);
1206 mutex_enter(&tp
->tim_mutex
);
1207 if (tp
->tim_peercred
!= NULL
)
1208 crfree(tp
->tim_peercred
);
1209 tp
->tim_peercred
= msg_getcred(mp
, &tp
->tim_cpid
);
1210 if (tp
->tim_peercred
!= NULL
)
1211 crhold(tp
->tim_peercred
);
1212 mutex_exit(&tp
->tim_mutex
);
1214 tilog("timodrproc: Got T_CONN_CON\n", 0);
1216 tp
->tim_flags
&= ~CONNWAIT
;
1220 case T_DISCON_IND
: {
1221 struct T_discon_ind
*disp
;
1222 struct T_conn_ind
*conp
;
1225 if (q
->q_first
!= 0)
1226 tilog("timodrput: T_DISCON_IND - flow control\n", 0);
1228 if (blen
< sizeof (*disp
)) {
1233 disp
= (struct T_discon_ind
*)mp
->b_rptr
;
1235 tilog("timodrproc: Got T_DISCON_IND Reason: %d\n",
1236 disp
->DISCON_reason
);
1238 tp
->tim_flags
&= ~(CONNWAIT
|LOCORDREL
|REMORDREL
);
1240 for (nbp
= tp
->tim_consave
; nbp
; nbp
= nbp
->b_next
) {
1241 conp
= (struct T_conn_ind
*)nbp
->b_rptr
;
1242 if (conp
->SEQ_number
== disp
->SEQ_number
)
1248 pbp
->b_next
= nbp
->b_next
;
1250 tp
->tim_consave
= nbp
->b_next
;
1260 tilog("timodrproc: Got T_ORDREL_IND\n", 0);
1262 if (tp
->tim_flags
& LOCORDREL
) {
1263 tp
->tim_flags
&= ~(LOCORDREL
|REMORDREL
);
1266 tp
->tim_flags
|= REMORDREL
;
1273 case T_UNITDATA_IND
:
1274 if (pptr
->type
== T_EXDATA_IND
)
1275 tilog("timodrproc: Got T_EXDATA_IND\n", 0);
1277 if (!bcanputnext(q
, mp
->b_band
)) {
1278 (void) putbq(q
, mp
);
1284 case T_CAPABILITY_ACK
: {
1285 struct T_capability_ack
*tca
;
1287 if (blen
< sizeof (*tca
)) {
1292 /* This transport supports T_CAPABILITY_REQ */
1293 tilog("timodrproc: Got T_CAPABILITY_ACK\n", 0);
1295 PI_PROVLOCK(tp
->tim_provinfo
);
1296 if (tp
->tim_provinfo
->tpi_capability
!= PI_YES
)
1297 tp
->tim_provinfo
->tpi_capability
= PI_YES
;
1298 PI_PROVUNLOCK(tp
->tim_provinfo
);
1300 /* Reset possible pending timeout */
1301 if (tp
->tim_tcap_timoutid
!= 0) {
1302 (void) quntimeout(q
, tp
->tim_tcap_timoutid
);
1303 tp
->tim_tcap_timoutid
= 0;
1306 tca
= (struct T_capability_ack
*)mp
->b_rptr
;
1308 if (tca
->CAP_bits1
& TC1_INFO
)
1309 timodprocessinfo(q
, tp
, &tca
->INFO_ack
);
1311 tim_send_reply(q
, mp
, tp
, T_CAPABILITY_REQ
);
1319 tilog("timodrproc: Got M_FLUSH\n", 0);
1321 if (*mp
->b_rptr
& FLUSHR
) {
1322 if (*mp
->b_rptr
& FLUSHBAND
)
1323 flushband(q
, *(mp
->b_rptr
+ 1), FLUSHDATA
);
1325 flushq(q
, FLUSHDATA
);
1331 iocbp
= (struct iocblk
*)mp
->b_rptr
;
1333 tilog("timodrproc: Got M_IOCACK\n", 0);
1335 if (iocbp
->ioc_cmd
== TI_GETMYNAME
) {
1338 * Transport provider supports this ioctl,
1339 * so I don't have to.
1341 if ((tp
->tim_flags
& DO_MYNAME
) != 0) {
1342 tp
->tim_flags
&= ~DO_MYNAME
;
1343 PI_PROVLOCK(tp
->tim_provinfo
);
1344 tp
->tim_provinfo
->tpi_myname
= PI_YES
;
1345 PI_PROVUNLOCK(tp
->tim_provinfo
);
1348 ASSERT(tp
->tim_mymaxlen
>= 0);
1349 if (tp
->tim_mymaxlen
!= 0) {
1350 kmem_free(tp
->tim_myname
, (size_t)tp
->tim_mymaxlen
);
1351 tp
->tim_myname
= NULL
;
1352 tp
->tim_mymaxlen
= 0;
1354 /* tim_iocsave may already be overwritten. */
1355 if (tp
->tim_saved_prim
== -1) {
1356 freemsg(tp
->tim_iocsave
);
1357 tp
->tim_iocsave
= NULL
;
1359 } else if (iocbp
->ioc_cmd
== TI_GETPEERNAME
) {
1363 * Transport provider supports this ioctl,
1364 * so I don't have to.
1366 if ((tp
->tim_flags
& DO_PEERNAME
) != 0) {
1367 tp
->tim_flags
&= ~DO_PEERNAME
;
1368 PI_PROVLOCK(tp
->tim_provinfo
);
1369 tp
->tim_provinfo
->tpi_peername
= PI_YES
;
1370 PI_PROVUNLOCK(tp
->tim_provinfo
);
1373 mutex_enter(&tp
->tim_mutex
);
1374 ASSERT(tp
->tim_peermaxlen
>= 0);
1375 clearit
= tp
->tim_peermaxlen
!= 0;
1377 kmem_free(tp
->tim_peername
, tp
->tim_peermaxlen
);
1378 tp
->tim_peername
= NULL
;
1379 tp
->tim_peermaxlen
= 0;
1380 tp
->tim_peerlen
= 0;
1382 mutex_exit(&tp
->tim_mutex
);
1386 bp
= tp
->tim_consave
;
1387 while (bp
!= NULL
) {
1393 tp
->tim_consave
= NULL
;
1395 /* tim_iocsave may already be overwritten. */
1396 if (tp
->tim_saved_prim
== -1) {
1397 freemsg(tp
->tim_iocsave
);
1398 tp
->tim_iocsave
= NULL
;
1406 tilog("timodrproc: Got M_IOCNAK\n", 0);
1408 iocbp
= (struct iocblk
*)mp
->b_rptr
;
1409 if (((iocbp
->ioc_cmd
== TI_GETMYNAME
) ||
1410 (iocbp
->ioc_cmd
== TI_GETPEERNAME
)) &&
1411 ((iocbp
->ioc_error
== EINVAL
) || (iocbp
->ioc_error
== 0))) {
1412 PI_PROVLOCK(tp
->tim_provinfo
);
1413 if (iocbp
->ioc_cmd
== TI_GETMYNAME
) {
1414 if (tp
->tim_provinfo
->tpi_myname
== PI_DONTKNOW
)
1415 tp
->tim_provinfo
->tpi_myname
= PI_NO
;
1416 } else if (iocbp
->ioc_cmd
== TI_GETPEERNAME
) {
1417 if (tp
->tim_provinfo
->tpi_peername
== PI_DONTKNOW
)
1418 tp
->tim_provinfo
->tpi_peername
= PI_NO
;
1420 PI_PROVUNLOCK(tp
->tim_provinfo
);
1421 /* tim_iocsave may already be overwritten. */
1422 if ((tp
->tim_iocsave
!= NULL
) &&
1423 (tp
->tim_saved_prim
== -1)) {
1425 mp
= tp
->tim_iocsave
;
1426 tp
->tim_iocsave
= NULL
;
1427 tp
->tim_flags
|= NAMEPROC
;
1428 if (ti_doname(WR(q
), mp
) != DONAME_CONT
) {
1429 tp
->tim_flags
&= ~NAMEPROC
;
1442 * timodwput - Module write put procedure. This is called from
1443 * the module, driver, or stream head upstream/downstream.
1444 * Handles M_FLUSH, M_DATA and some M_PROTO (T_DATA_REQ,
1445 * and T_UNITDATA_REQ) messages. All others are queued to
1446 * be handled by the service procedures.
1450 timodwput(queue_t
*q
, mblk_t
*mp
)
1452 union T_primitives
*pptr
;
1454 struct iocblk
*iocbp
;
1457 * Enqueue normal-priority messages if our queue already
1458 * holds some messages for deferred processing but don't
1459 * enqueue those M_IOCTLs which will result in an
1460 * M_PCPROTO (ie, high priority) message being created.
1462 if (q
->q_first
!= 0 && mp
->b_datap
->db_type
< QPCTL
) {
1463 if (mp
->b_datap
->db_type
== M_IOCTL
) {
1464 iocbp
= (struct iocblk
*)mp
->b_rptr
;
1465 switch (iocbp
->ioc_cmd
) {
1481 * Inline processing of data (to avoid additional procedure call).
1482 * Rest is handled in timodwproc.
1485 switch (mp
->b_datap
->db_type
) {
1487 tp
= (struct tim_tim
*)q
->q_ptr
;
1489 if (tp
->tim_flags
& CLTS
) {
1492 if ((tmp
= tim_filladdr(q
, mp
, B_FALSE
)) == NULL
) {
1499 if (bcanputnext(q
, mp
->b_band
))
1506 pptr
= (union T_primitives
*)mp
->b_rptr
;
1507 switch (pptr
->type
) {
1508 case T_UNITDATA_REQ
:
1509 tp
= (struct tim_tim
*)q
->q_ptr
;
1511 if (tp
->tim_flags
& CLTS
) {
1514 tmp
= tim_filladdr(q
, mp
, B_FALSE
);
1522 if (bcanputnext(q
, mp
->b_band
))
1530 if (bcanputnext(q
, mp
->b_band
))
1536 (void) timodwproc(q
, mp
);
1541 (void) timodwproc(q
, mp
);
1546 * timodwsrv - Module write queue service procedure.
1547 * This is called when messages are placed on an empty queue,
1548 * when high priority messages are placed on the queue, and
1549 * when flow control restrictions subside. This code used to
1550 * be included in a put procedure, but it was moved to a
1551 * service procedure because several points were added where
1552 * memory allocation could fail, and there is no reasonable
1553 * recovery mechanism from the put procedure.
1556 timodwsrv(queue_t
*q
)
1561 if (q
->q_ptr
== NULL
)
1564 while ((mp
= getq(q
)) != NULL
) {
1565 if (timodwproc(q
, mp
)) {
1567 * timodwproc did a putbq - stop processing
1576 * Common routine to process write side messages
1580 timodwproc(queue_t
*q
, mblk_t
*mp
)
1582 union T_primitives
*pptr
;
1584 uint32_t auditing
= AU_AUDITING();
1586 struct iocblk
*iocbp
;
1589 tp
= (struct tim_tim
*)q
->q_ptr
;
1591 switch (mp
->b_datap
->db_type
) {
1597 if (tp
->tim_flags
& CLTS
) {
1598 if ((tmp
= tim_filladdr(q
, mp
, B_TRUE
)) == NULL
) {
1604 if (!bcanputnext(q
, mp
->b_band
)) {
1605 (void) putbq(q
, mp
);
1613 iocbp
= (struct iocblk
*)mp
->b_rptr
;
1614 TILOG("timodwproc: Got M_IOCTL(%d)\n", iocbp
->ioc_cmd
);
1616 ASSERT(MBLKL(mp
) == sizeof (struct iocblk
));
1619 * TPI requires we await response to a previously sent message
1620 * before handling another, put it back on the head of queue.
1621 * Since putbq() may see QWANTR unset when called from the
1622 * service procedure, the queue must be explicitly scheduled
1623 * for service, as no backenable will occur for this case.
1624 * tim_ioctl_retry() sets a timer to handle the qenable.
1626 if (tp
->tim_flags
& WAITIOCACK
) {
1627 TILOG("timodwproc: putbq M_IOCTL(%d)\n",
1629 (void) putbq(q
, mp
);
1630 /* Called from timodwsrv() and messages on queue */
1631 if (!(q
->q_flag
& QWANTR
))
1636 switch (iocbp
->ioc_cmd
) {
1641 case _I_GETPEERCRED
:
1642 if ((tp
->tim_flags
& COTS
) == 0) {
1643 miocnak(q
, mp
, 0, ENOTSUP
);
1645 mblk_t
*cmp
= mp
->b_cont
;
1646 k_peercred_t
*kp
= NULL
;
1648 mutex_enter(&tp
->tim_mutex
);
1650 iocbp
->ioc_flag
== IOC_NATIVE
&&
1652 (CONNWAIT
|LOCORDREL
|REMORDREL
)) == 0 &&
1653 tp
->tim_peercred
!= NULL
&&
1654 DB_TYPE(cmp
) == M_DATA
&&
1655 MBLKL(cmp
) == sizeof (k_peercred_t
)) {
1656 kp
= (k_peercred_t
*)cmp
->b_rptr
;
1657 crhold(kp
->pc_cr
= tp
->tim_peercred
);
1658 kp
->pc_cpid
= tp
->tim_cpid
;
1660 mutex_exit(&tp
->tim_mutex
);
1662 miocack(q
, mp
, sizeof (*kp
), 0);
1664 miocnak(q
, mp
, 0, ENOTCONN
);
1671 TILOG("timodwproc: TI_{BIND|UNBIND|OPTMGMT|GETADDRS}"
1675 * We know that tim_send_ioctl_tpi_msg() is only
1676 * going to examine the `type' field, so we only
1677 * check that we can access that much data.
1679 error
= miocpullup(mp
, sizeof (t_scalar_t
));
1681 miocnak(q
, mp
, 0, error
);
1684 tim_send_ioctl_tpi_msg(q
, mp
, tp
, iocbp
);
1688 TILOG("timodwproc: TI_GETINFO\n", 0);
1689 error
= miocpullup(mp
, sizeof (struct T_info_req
));
1691 miocnak(q
, mp
, 0, error
);
1694 tp
->tim_flags
|= WAIT_IOCINFOACK
;
1695 tim_send_ioctl_tpi_msg(q
, mp
, tp
, iocbp
);
1700 struct ti_sync_req
*tsr
;
1703 error
= miocpullup(mp
, sizeof (struct ti_sync_req
));
1705 miocnak(q
, mp
, 0, error
);
1709 tsr_mp
= mp
->b_cont
;
1710 tsr
= (struct ti_sync_req
*)tsr_mp
->b_rptr
;
1711 TILOG("timodwproc: TI_SYNC(%x)\n", tsr
->tsr_flags
);
1714 * Save out the value of tsr_flags, in case we
1715 * reallocb() tsr_mp (below).
1717 tsr_flags
= tsr
->tsr_flags
;
1718 if ((tsr_flags
& TSRF_INFO_REQ
) == 0) {
1719 mblk_t
*ack_mp
= reallocb(tsr_mp
,
1720 sizeof (struct ti_sync_ack
), 0);
1722 /* Can reply immediately. */
1724 if (ack_mp
== NULL
) {
1725 tilog("timodwproc: allocb failed no "
1726 "recovery attempt\n", 0);
1728 miocnak(q
, mp
, 0, ENOMEM
);
1730 tim_answer_ti_sync(q
, mp
, tp
,
1737 * This code is retained for compatibility with
1738 * old statically linked applications. New code
1739 * should use TI_CAPABILITY for all TPI
1740 * information and should not use TSRF_INFO_REQ
1743 * defer processsing necessary to rput procedure
1744 * as we need to get information from transport
1745 * driver. Set flags that will tell the read
1746 * side the work needed on this request.
1749 if (tsr_flags
& TSRF_IS_EXP_IN_RCVBUF
)
1750 tp
->tim_flags
|= PEEK_RDQ_EXPIND
;
1753 * Convert message to a T_INFO_REQ message; relies
1754 * on sizeof (struct ti_sync_req) >= sizeof (struct
1757 ASSERT(MBLKL(tsr_mp
) >= sizeof (struct T_info_req
));
1759 ((struct T_info_req
*)tsr_mp
->b_rptr
)->PRIM_type
=
1761 tsr_mp
->b_wptr
= tsr_mp
->b_rptr
+
1762 sizeof (struct T_info_req
);
1763 tp
->tim_flags
|= WAIT_IOCINFOACK
;
1764 tim_send_ioctl_tpi_msg(q
, mp
, tp
, iocbp
);
1768 case TI_CAPABILITY
: {
1770 struct T_capability_req
*tcr
;
1772 error
= miocpullup(mp
, sizeof (*tcr
));
1774 miocnak(q
, mp
, 0, error
);
1778 tcsr_mp
= mp
->b_cont
;
1779 tcr
= (struct T_capability_req
*)tcsr_mp
->b_rptr
;
1780 TILOG("timodwproc: TI_CAPABILITY(CAP_bits1 = %x)\n",
1783 if (tcr
->PRIM_type
!= T_CAPABILITY_REQ
) {
1784 TILOG("timodwproc: invalid msg type %d\n",
1786 miocnak(q
, mp
, 0, EPROTO
);
1790 switch (tp
->tim_provinfo
->tpi_capability
) {
1792 /* Just send T_CAPABILITY_REQ down */
1793 tim_send_ioctl_tpi_msg(q
, mp
, tp
, iocbp
);
1798 * It is unknown yet whether transport provides
1799 * T_CAPABILITY_REQ or not. Send message down
1800 * and wait for reply.
1803 ASSERT(tp
->tim_tcap_timoutid
== 0);
1804 if ((tcr
->CAP_bits1
& TC1_INFO
) == 0) {
1805 tp
->tim_flags
|= TI_CAP_RECVD
;
1807 tp
->tim_flags
|= (TI_CAP_RECVD
|
1811 tp
->tim_tcap_timoutid
= qtimeout(q
,
1812 tim_tcap_timer
, q
, tim_tcap_wait
* hz
);
1813 tim_send_ioctl_tpi_msg(q
, mp
, tp
, iocbp
);
1818 * Transport doesn't support T_CAPABILITY_REQ.
1819 * Either reply immediately or send T_INFO_REQ
1822 if ((tcr
->CAP_bits1
& TC1_INFO
) != 0) {
1823 tp
->tim_flags
|= (TI_CAP_RECVD
|
1824 CAP_WANTS_INFO
| WAIT_IOCINFOACK
);
1825 TILOG("timodwproc: sending down "
1826 "T_INFO_REQ, flags = %x\n",
1830 * Generate T_INFO_REQ message and send
1833 ((struct T_info_req
*)tcsr_mp
->b_rptr
)->
1834 PRIM_type
= T_INFO_REQ
;
1835 tcsr_mp
->b_wptr
= tcsr_mp
->b_rptr
+
1836 sizeof (struct T_info_req
);
1837 tim_send_ioctl_tpi_msg(q
, mp
, tp
,
1844 * Can reply immediately. Just send back
1845 * T_CAPABILITY_ACK with CAP_bits1 set to 0.
1847 mp
->b_cont
= tcsr_mp
= tpi_ack_alloc(mp
->b_cont
,
1848 sizeof (struct T_capability_ack
), M_PCPROTO
,
1851 if (tcsr_mp
== NULL
) {
1852 tilog("timodwproc: allocb failed no "
1853 "recovery attempt\n", 0);
1854 miocnak(q
, mp
, 0, ENOMEM
);
1858 tp
->tim_flags
&= ~(WAITIOCACK
| TI_CAP_RECVD
|
1859 WAIT_IOCINFOACK
| CAP_WANTS_INFO
);
1860 ((struct T_capability_ack
*)
1861 tcsr_mp
->b_rptr
)->CAP_bits1
= 0;
1862 tim_ioctl_send_reply(q
, mp
, tcsr_mp
);
1865 * It could happen when timod is awaiting ack
1866 * for TI_GETPEERNAME/TI_GETMYNAME.
1868 if (tp
->tim_iocsave
!= NULL
) {
1869 freemsg(tp
->tim_iocsave
);
1870 tp
->tim_iocsave
= NULL
;
1871 tp
->tim_saved_prim
= -1;
1877 "timodwproc: unknown tpi_capability value "
1878 "%d\n", tp
->tim_provinfo
->tpi_capability
);
1886 tilog("timodwproc: Got TI_GETMYNAME\n", 0);
1888 if (tp
->tim_provinfo
->tpi_myname
== PI_YES
) {
1894 case TI_GETPEERNAME
:
1896 tilog("timodwproc: Got TI_GETPEERNAME\n", 0);
1898 if (tp
->tim_provinfo
->tpi_peername
== PI_YES
) {
1903 if ((tmp
= copymsg(mp
)) == NULL
) {
1904 tim_recover(q
, mp
, msgsize(mp
));
1908 * tim_iocsave may be non-NULL when timod is awaiting
1909 * ack for another TI_GETPEERNAME/TI_GETMYNAME.
1911 freemsg(tp
->tim_iocsave
);
1912 tp
->tim_iocsave
= mp
;
1913 tp
->tim_saved_prim
= -1;
1921 if (tp
->tim_flags
& NAMEPROC
) {
1922 if (ti_doname(q
, mp
) != DONAME_CONT
) {
1923 tp
->tim_flags
&= ~NAMEPROC
;
1931 if (MBLKL(mp
) < sizeof (t_scalar_t
)) {
1932 merror(q
, mp
, EPROTO
);
1936 pptr
= (union T_primitives
*)mp
->b_rptr
;
1937 switch (pptr
->type
) {
1944 if (pptr
->type
== T_EXDATA_REQ
)
1945 tilog("timodwproc: Got T_EXDATA_REQ\n", 0);
1947 if (!bcanputnext(q
, mp
->b_band
)) {
1948 (void) putbq(q
, mp
);
1954 case T_UNITDATA_REQ
:
1955 if (tp
->tim_flags
& CLTS
) {
1956 tmp
= tim_filladdr(q
, mp
, B_TRUE
);
1964 audit_sock(T_UNITDATA_REQ
, q
, mp
, TIMOD_ID
);
1965 if (!bcanputnext(q
, mp
->b_band
)) {
1966 (void) putbq(q
, mp
);
1973 struct T_conn_req
*reqp
= (struct T_conn_req
*)
1977 tilog("timodwproc: Got T_CONN_REQ\n", 0);
1979 if (MBLKL(mp
) < sizeof (struct T_conn_req
)) {
1980 merror(q
, mp
, EPROTO
);
1984 if (tp
->tim_flags
& DO_PEERNAME
) {
1985 if (!MBLKIN(mp
, reqp
->DEST_offset
,
1986 reqp
->DEST_length
)) {
1987 merror(q
, mp
, EPROTO
);
1990 ASSERT(reqp
->DEST_length
>= 0);
1991 mutex_enter(&tp
->tim_mutex
);
1992 if (reqp
->DEST_length
> tp
->tim_peermaxlen
) {
1993 p
= kmem_alloc(reqp
->DEST_length
,
1996 mutex_exit(&tp
->tim_mutex
);
1997 tilog("timodwproc: kmem_alloc "
1998 "failed, attempting "
2004 if (tp
->tim_peermaxlen
)
2005 kmem_free(tp
->tim_peername
,
2006 tp
->tim_peermaxlen
);
2007 tp
->tim_peername
= p
;
2008 tp
->tim_peermaxlen
= reqp
->DEST_length
;
2010 tp
->tim_peerlen
= reqp
->DEST_length
;
2011 p
= mp
->b_rptr
+ reqp
->DEST_offset
;
2012 bcopy(p
, tp
->tim_peername
, tp
->tim_peerlen
);
2013 mutex_exit(&tp
->tim_mutex
);
2015 if (tp
->tim_flags
& COTS
)
2016 tp
->tim_flags
|= CONNWAIT
;
2018 audit_sock(T_CONN_REQ
, q
, mp
, TIMOD_ID
);
2025 struct T_conn_res
*resp
;
2026 struct T_conn_ind
*indp
;
2030 if (MBLKL(mp
) < sizeof (struct T_conn_res
) ||
2031 (tp
->tim_flags
& WAITIOCACK
)) {
2032 merror(q
, mp
, EPROTO
);
2036 resp
= (struct T_conn_res
*)mp
->b_rptr
;
2037 for (tmp
= tp
->tim_consave
; tmp
!= NULL
;
2038 tmp
= tmp
->b_next
) {
2039 indp
= (struct T_conn_ind
*)tmp
->b_rptr
;
2040 if (indp
->SEQ_number
== resp
->SEQ_number
)
2047 if ((nbp
= dupb(mp
)) == NULL
&&
2048 (nbp
= copyb(mp
)) == NULL
) {
2049 tim_recover(q
, mp
, msgsize(mp
));
2054 pmp
->b_next
= tmp
->b_next
;
2056 tp
->tim_consave
= tmp
->b_next
;
2060 * Construct a list with:
2061 * nbp - copy of user's original request
2062 * tmp - the extracted T_conn_ind
2066 * tim_iocsave may be non-NULL when timod is awaiting
2067 * ack for TI_GETPEERNAME/TI_GETMYNAME.
2069 freemsg(tp
->tim_iocsave
);
2070 tp
->tim_iocsave
= nbp
;
2071 tp
->tim_saved_prim
= pptr
->type
;
2072 tp
->tim_flags
|= WAIT_CONNRESACK
| WAITIOCACK
;
2079 case T_DISCON_REQ
: {
2080 struct T_discon_req
*disp
;
2081 struct T_conn_ind
*conp
;
2084 if (MBLKL(mp
) < sizeof (struct T_discon_req
)) {
2085 merror(q
, mp
, EPROTO
);
2089 disp
= (struct T_discon_req
*)mp
->b_rptr
;
2090 tp
->tim_flags
&= ~(CONNWAIT
|LOCORDREL
|REMORDREL
);
2094 * If we are already connected, there won't
2095 * be any messages on tim_consave.
2097 for (tmp
= tp
->tim_consave
; tmp
; tmp
= tmp
->b_next
) {
2098 conp
= (struct T_conn_ind
*)tmp
->b_rptr
;
2099 if (conp
->SEQ_number
== disp
->SEQ_number
)
2105 pmp
->b_next
= tmp
->b_next
;
2107 tp
->tim_consave
= tmp
->b_next
;
2116 if (tp
->tim_flags
& REMORDREL
) {
2117 tp
->tim_flags
&= ~(LOCORDREL
|REMORDREL
);
2120 tp
->tim_flags
|= LOCORDREL
;
2125 case T_CAPABILITY_REQ
:
2126 tilog("timodwproc: Got T_CAPABILITY_REQ\n", 0);
2128 * XXX: We may know at this point whether transport
2129 * provides T_CAPABILITY_REQ or not and we may utilise
2130 * this knowledge here.
2138 tilog("timodwproc: Got M_FLUSH\n", 0);
2140 if (*mp
->b_rptr
& FLUSHW
) {
2141 if (*mp
->b_rptr
& FLUSHBAND
)
2142 flushband(q
, *(mp
->b_rptr
+ 1), FLUSHDATA
);
2144 flushq(q
, FLUSHDATA
);
2154 tilog(char *str
, t_scalar_t arg
)
2158 cmn_err(CE_CONT
, str
, arg
);
2160 (void) strlog(TIMOD_ID
, -1, 0, SL_TRACE
| SL_ERROR
,
2163 (void) strlog(TIMOD_ID
, -1, 0, SL_TRACE
, str
, arg
);
2168 tilogp(char *str
, uintptr_t arg
)
2172 cmn_err(CE_CONT
, str
, arg
);
2174 (void) strlog(TIMOD_ID
, -1, 0, SL_TRACE
| SL_ERROR
,
2177 (void) strlog(TIMOD_ID
, -1, 0, SL_TRACE
, str
, arg
);
2183 * Process the TI_GETNAME ioctl. If no name exists, return len = 0
2184 * in strbuf structures. The state transitions are determined by what
2185 * is hung of cq_private (cp_private) in the copyresp (copyreq) structure.
2186 * The high-level steps in the ioctl processing are as follows:
2188 * 1) we recieve an transparent M_IOCTL with the arg in the second message
2189 * block of the message.
2190 * 2) we send up an M_COPYIN request for the strbuf structure pointed to
2191 * by arg. The block containing arg is hung off cq_private.
2192 * 3) we receive an M_IOCDATA response with cp->cp_private->b_cont == NULL.
2193 * This means that the strbuf structure is found in the message block
2195 * 4) we send up an M_COPYOUT request with the strbuf message hung off
2196 * cq_private->b_cont. The address we are copying to is strbuf.buf.
2197 * we set strbuf.len to 0 to indicate that we should copy the strbuf
2198 * structure the next time. The message mp->b_cont contains the
2200 * 5) we receive an M_IOCDATA with cp_private->b_cont != NULL and
2201 * strbuf.len == 0. Restore strbuf.len to either tp->tim_mylen or
2203 * 6) we send up an M_COPYOUT request with a copy of the strbuf message
2204 * hung off mp->b_cont. In the strbuf structure in the message hung
2205 * off cq_private->b_cont, we set strbuf.len to 0 and strbuf.maxlen
2206 * to 0. This means that the next step is to ACK the ioctl.
2207 * 7) we receive an M_IOCDATA message with cp_private->b_cont != NULL and
2208 * strbuf.len == 0 and strbuf.maxlen == 0. Free up cp->private and
2209 * send an M_IOCACK upstream, and we are done.
2214 queue_t
*q
, /* queue message arrived at */
2215 mblk_t
*mp
) /* M_IOCTL or M_IOCDATA message only */
2217 struct iocblk
*iocp
;
2218 struct copyreq
*cqp
;
2219 STRUCT_HANDLE(strbuf
, sb
);
2220 struct copyresp
*csp
;
2223 struct tim_tim
*tp
= q
->q_ptr
;
2226 switch (mp
->b_datap
->db_type
) {
2228 iocp
= (struct iocblk
*)mp
->b_rptr
;
2229 if ((iocp
->ioc_cmd
!= TI_GETMYNAME
) &&
2230 (iocp
->ioc_cmd
!= TI_GETPEERNAME
)) {
2231 tilog("ti_doname: bad M_IOCTL command\n", 0);
2232 miocnak(q
, mp
, 0, EINVAL
);
2236 if ((iocp
->ioc_count
!= TRANSPARENT
)) {
2237 miocnak(q
, mp
, 0, EINVAL
);
2242 cqp
= (struct copyreq
*)mp
->b_rptr
;
2243 cqp
->cq_private
= mp
->b_cont
;
2244 cqp
->cq_addr
= (caddr_t
)*(intptr_t *)mp
->b_cont
->b_rptr
;
2246 cqp
->cq_size
= SIZEOF_STRUCT(strbuf
, iocp
->ioc_flag
);
2248 mp
->b_datap
->db_type
= M_COPYIN
;
2249 mp
->b_wptr
= mp
->b_rptr
+ sizeof (struct copyreq
);
2255 csp
= (struct copyresp
*)mp
->b_rptr
;
2256 iocp
= (struct iocblk
*)mp
->b_rptr
;
2257 cqp
= (struct copyreq
*)mp
->b_rptr
;
2258 if ((csp
->cp_cmd
!= TI_GETMYNAME
) &&
2259 (csp
->cp_cmd
!= TI_GETPEERNAME
)) {
2260 cmn_err(CE_WARN
, "ti_doname: bad M_IOCDATA command\n");
2261 miocnak(q
, mp
, 0, EINVAL
);
2265 if (csp
->cp_rval
) { /* error */
2266 freemsg(csp
->cp_private
);
2271 ASSERT(csp
->cp_private
!= NULL
);
2272 getpeer
= csp
->cp_cmd
== TI_GETPEERNAME
;
2274 mutex_enter(&tp
->tim_mutex
);
2275 if (csp
->cp_private
->b_cont
== NULL
) { /* got strbuf */
2277 STRUCT_SET_HANDLE(sb
, iocp
->ioc_flag
,
2278 (void *)mp
->b_cont
->b_rptr
);
2280 if (tp
->tim_peerlen
== 0) {
2281 /* copy just strbuf */
2282 STRUCT_FSET(sb
, len
, 0);
2283 } else if (tp
->tim_peerlen
>
2284 STRUCT_FGET(sb
, maxlen
)) {
2285 mutex_exit(&tp
->tim_mutex
);
2286 miocnak(q
, mp
, 0, ENAMETOOLONG
);
2291 STRUCT_FSET(sb
, len
, tp
->tim_peerlen
);
2294 if (tp
->tim_mylen
== 0) {
2295 /* copy just strbuf */
2296 STRUCT_FSET(sb
, len
, 0);
2297 } else if (tp
->tim_mylen
>
2298 STRUCT_FGET(sb
, maxlen
)) {
2299 freemsg(csp
->cp_private
);
2300 miocnak(q
, mp
, 0, ENAMETOOLONG
);
2305 STRUCT_FSET(sb
, len
, tp
->tim_mylen
);
2308 csp
->cp_private
->b_cont
= mp
->b_cont
;
2311 STRUCT_SET_HANDLE(sb
, iocp
->ioc_flag
,
2312 (void *)csp
->cp_private
->b_cont
->b_rptr
);
2313 if (STRUCT_FGET(sb
, len
) == 0) {
2315 * restore strbuf.len
2318 STRUCT_FSET(sb
, len
, tp
->tim_peerlen
);
2320 STRUCT_FSET(sb
, len
, tp
->tim_mylen
);
2323 mutex_exit(&tp
->tim_mutex
);
2324 if (STRUCT_FGET(sb
, maxlen
) == 0) {
2329 freemsg(csp
->cp_private
);
2330 tim_ioctl_send_reply(q
, mp
, NULL
);
2335 if ((bp
= allocb(STRUCT_SIZE(sb
), BPRI_MED
)) == NULL
) {
2338 "ti_doname: allocb failed no recovery attempt\n", 0);
2340 freemsg(csp
->cp_private
);
2341 miocnak(q
, mp
, 0, EAGAIN
);
2345 bp
->b_wptr
+= STRUCT_SIZE(sb
);
2346 bcopy(STRUCT_BUF(sb
), bp
->b_rptr
, STRUCT_SIZE(sb
));
2348 (caddr_t
)*(intptr_t *)csp
->cp_private
->b_rptr
;
2349 cqp
->cq_size
= STRUCT_SIZE(sb
);
2351 mp
->b_datap
->db_type
= M_COPYOUT
;
2353 STRUCT_FSET(sb
, len
, 0);
2354 STRUCT_FSET(sb
, maxlen
, 0); /* ack next time around */
2361 * copy the address to the user
2363 if ((bp
= allocb((size_t)STRUCT_FGET(sb
, len
), BPRI_MED
))
2366 mutex_exit(&tp
->tim_mutex
);
2368 tilog("ti_doname: allocb failed no recovery attempt\n",
2371 freemsg(csp
->cp_private
);
2372 miocnak(q
, mp
, 0, EAGAIN
);
2376 bp
->b_wptr
+= STRUCT_FGET(sb
, len
);
2378 bcopy(tp
->tim_peername
, bp
->b_rptr
,
2379 STRUCT_FGET(sb
, len
));
2380 mutex_exit(&tp
->tim_mutex
);
2382 bcopy(tp
->tim_myname
, bp
->b_rptr
, STRUCT_FGET(sb
, len
));
2384 cqp
->cq_addr
= (caddr_t
)STRUCT_FGETP(sb
, buf
);
2385 cqp
->cq_size
= STRUCT_FGET(sb
, len
);
2387 mp
->b_datap
->db_type
= M_COPYOUT
;
2389 STRUCT_FSET(sb
, len
, 0); /* copy the strbuf next time around */
2395 tilog("ti_doname: freeing bad message type = %d\n",
2396 mp
->b_datap
->db_type
);
2406 * Fill in the address of a connectionless data packet if a connect
2407 * had been done on this endpoint.
2410 tim_filladdr(queue_t
*q
, mblk_t
*mp
, boolean_t dorecover
)
2414 struct T_unitdata_req
*up
;
2415 struct T_unitdata_req
*nup
;
2418 tp
= (struct tim_tim
*)q
->q_ptr
;
2419 if (mp
->b_datap
->db_type
== M_DATA
) {
2420 mutex_enter(&tp
->tim_mutex
);
2421 bp
= allocb(sizeof (struct T_unitdata_req
) + tp
->tim_peerlen
,
2424 bp
->b_datap
->db_type
= M_PROTO
;
2425 up
= (struct T_unitdata_req
*)bp
->b_rptr
;
2426 up
->PRIM_type
= T_UNITDATA_REQ
;
2427 up
->DEST_length
= tp
->tim_peerlen
;
2428 bp
->b_wptr
+= sizeof (struct T_unitdata_req
);
2429 up
->DEST_offset
= sizeof (struct T_unitdata_req
);
2432 if (tp
->tim_peerlen
> 0) {
2433 bcopy(tp
->tim_peername
, bp
->b_wptr
,
2435 bp
->b_wptr
+= tp
->tim_peerlen
;
2440 ASSERT(mp
->b_datap
->db_type
== M_PROTO
);
2441 up
= (struct T_unitdata_req
*)mp
->b_rptr
;
2442 ASSERT(up
->PRIM_type
== T_UNITDATA_REQ
);
2443 if (up
->DEST_length
!= 0)
2445 mutex_enter(&tp
->tim_mutex
);
2446 bp
= allocb(sizeof (struct T_unitdata_req
) + up
->OPT_length
+
2447 tp
->tim_peerlen
, BPRI_MED
);
2449 bp
->b_datap
->db_type
= M_PROTO
;
2450 nup
= (struct T_unitdata_req
*)bp
->b_rptr
;
2451 nup
->PRIM_type
= T_UNITDATA_REQ
;
2452 nup
->DEST_length
= plen
= tp
->tim_peerlen
;
2453 bp
->b_wptr
+= sizeof (struct T_unitdata_req
);
2454 nup
->DEST_offset
= sizeof (struct T_unitdata_req
);
2456 bcopy(tp
->tim_peername
, bp
->b_wptr
, plen
);
2459 mutex_exit(&tp
->tim_mutex
);
2460 if (up
->OPT_length
== 0) {
2461 nup
->OPT_length
= 0;
2462 nup
->OPT_offset
= 0;
2464 nup
->OPT_length
= up
->OPT_length
;
2466 sizeof (struct T_unitdata_req
) + plen
;
2467 bcopy((mp
->b_wptr
+ up
->OPT_offset
), bp
->b_wptr
,
2469 bp
->b_wptr
+= up
->OPT_length
;
2471 bp
->b_cont
= mp
->b_cont
;
2477 ASSERT(MUTEX_HELD(&tp
->tim_mutex
));
2478 if (bp
== NULL
&& dorecover
) {
2480 sizeof (struct T_unitdata_req
) + tp
->tim_peerlen
);
2482 mutex_exit(&tp
->tim_mutex
);
2487 tim_addlink(struct tim_tim
*tp
)
2489 struct tim_tim
**tpp
;
2490 struct tim_tim
*next
;
2492 tpp
= &tim_hash
[TIM_HASH(tp
->tim_acceptor
)];
2493 rw_enter(&tim_list_rwlock
, RW_WRITER
);
2495 if ((next
= *tpp
) != NULL
)
2496 next
->tim_ptpn
= &tp
->tim_next
;
2497 tp
->tim_next
= next
;
2503 rw_exit(&tim_list_rwlock
);
2507 tim_dellink(struct tim_tim
*tp
)
2509 struct tim_tim
*next
;
2511 rw_enter(&tim_list_rwlock
, RW_WRITER
);
2513 if ((next
= tp
->tim_next
) != NULL
)
2514 next
->tim_ptpn
= tp
->tim_ptpn
;
2515 *(tp
->tim_ptpn
) = next
;
2519 rw_exit(&tim_list_rwlock
);
2522 static struct tim_tim
*
2523 tim_findlink(t_uscalar_t id
)
2527 ASSERT(rw_lock_held(&tim_list_rwlock
));
2529 for (tp
= tim_hash
[TIM_HASH(id
)]; tp
!= NULL
; tp
= tp
->tim_next
) {
2530 if (tp
->tim_acceptor
== id
) {
2538 tim_recover(queue_t
*q
, mblk_t
*mp
, t_scalar_t size
)
2544 tp
= (struct tim_tim
*)q
->q_ptr
;
2547 * Avoid re-enabling the queue.
2549 if (mp
->b_datap
->db_type
== M_PCPROTO
)
2550 mp
->b_datap
->db_type
= M_PROTO
;
2552 (void) putbq(q
, mp
);
2555 * Make sure there is at most one outstanding request per queue.
2557 if (q
->q_flag
& QREADR
) {
2558 if (tp
->tim_rtimoutid
|| tp
->tim_rbufcid
)
2561 if (tp
->tim_wtimoutid
|| tp
->tim_wbufcid
)
2564 if (!(bid
= qbufcall(RD(q
), (size_t)size
, BPRI_MED
, tim_buffer
, q
))) {
2565 tid
= qtimeout(RD(q
), tim_timer
, q
, TIMWAIT
);
2566 if (q
->q_flag
& QREADR
)
2567 tp
->tim_rtimoutid
= tid
;
2569 tp
->tim_wtimoutid
= tid
;
2571 if (q
->q_flag
& QREADR
)
2572 tp
->tim_rbufcid
= bid
;
2574 tp
->tim_wbufcid
= bid
;
2579 * Timod is waiting on a downstream ioctl reply, come back soon
2580 * to reschedule the write side service routine, which will check
2581 * if the ioctl is done and another can proceed.
2584 tim_ioctl_retry(queue_t
*q
)
2588 tp
= (struct tim_tim
*)q
->q_ptr
;
2591 * Make sure there is at most one outstanding request per wqueue.
2593 if (tp
->tim_wtimoutid
|| tp
->tim_wbufcid
)
2596 tp
->tim_wtimoutid
= qtimeout(RD(q
), tim_timer
, q
, TIMIOCWAIT
);
2600 * Inspect the data on read queues starting from read queues passed as
2601 * paramter (timod read queue) and traverse until
2602 * q_next is NULL (stream head). Look for a TPI T_EXDATA_IND message
2603 * reutrn 1 if found, 0 if not found.
2606 ti_expind_on_rdqueues(queue_t
*rq
)
2613 * We are going to walk q_next, so protect stream from plumbing
2619 * Hold QLOCK while referencing data on queues
2621 mutex_enter(QLOCK(rq
));
2623 while (bp
!= NULL
) {
2625 * Walk the messages on the queue looking
2626 * for a possible T_EXDATA_IND
2628 if ((bp
->b_datap
->db_type
== M_PROTO
) &&
2629 ((bp
->b_wptr
- bp
->b_rptr
) >=
2630 sizeof (struct T_exdata_ind
)) &&
2631 (((struct T_exdata_ind
*)bp
->b_rptr
)->PRIM_type
2633 /* bp is T_EXDATA_IND */
2634 mutex_exit(QLOCK(rq
));
2635 releasestr(q
); /* decrement sd_refcnt */
2636 return (1); /* expdata is on a read queue */
2638 bp
= bp
->b_next
; /* next message */
2640 mutex_exit(QLOCK(rq
));
2641 rq
= rq
->q_next
; /* next upstream queue */
2642 } while (rq
!= NULL
);
2644 return (0); /* no expdata on read queues */
2648 tim_tcap_timer(void *q_ptr
)
2650 queue_t
*q
= (queue_t
*)q_ptr
;
2651 struct tim_tim
*tp
= (struct tim_tim
*)q
->q_ptr
;
2653 ASSERT(tp
!= NULL
&& tp
->tim_tcap_timoutid
!= 0);
2654 ASSERT((tp
->tim_flags
& TI_CAP_RECVD
) != 0);
2656 tp
->tim_tcap_timoutid
= 0;
2657 TILOG("tim_tcap_timer: fired\n", 0);
2658 tim_tcap_genreply(q
, tp
);
2662 * tim_tcap_genreply() is called either from timeout routine or when
2663 * T_ERROR_ACK is received. In both cases it means that underlying
2664 * transport doesn't provide T_CAPABILITY_REQ.
2667 tim_tcap_genreply(queue_t
*q
, struct tim_tim
*tp
)
2669 mblk_t
*mp
= tp
->tim_iocsave
;
2670 struct iocblk
*iocbp
;
2672 TILOG("timodrproc: tim_tcap_genreply\n", 0);
2674 ASSERT(tp
== (struct tim_tim
*)q
->q_ptr
);
2677 iocbp
= (struct iocblk
*)mp
->b_rptr
;
2678 ASSERT(iocbp
!= NULL
);
2679 ASSERT(MBLKL(mp
) == sizeof (struct iocblk
));
2680 ASSERT(iocbp
->ioc_cmd
== TI_CAPABILITY
);
2681 ASSERT(mp
->b_cont
== NULL
);
2683 /* Save this information permanently in the module */
2684 PI_PROVLOCK(tp
->tim_provinfo
);
2685 if (tp
->tim_provinfo
->tpi_capability
== PI_DONTKNOW
)
2686 tp
->tim_provinfo
->tpi_capability
= PI_NO
;
2687 PI_PROVUNLOCK(tp
->tim_provinfo
);
2689 if (tp
->tim_tcap_timoutid
!= 0) {
2690 (void) quntimeout(q
, tp
->tim_tcap_timoutid
);
2691 tp
->tim_tcap_timoutid
= 0;
2694 if ((tp
->tim_flags
& CAP_WANTS_INFO
) != 0) {
2695 /* Send T_INFO_REQ down */
2696 mblk_t
*tirmp
= tpi_ack_alloc(NULL
,
2697 sizeof (struct T_info_req
), M_PCPROTO
, T_INFO_REQ
);
2699 if (tirmp
!= NULL
) {
2700 /* Emulate TC1_INFO */
2701 TILOG("emulate_tcap_ioc_req: sending T_INFO_REQ\n", 0);
2702 tp
->tim_flags
|= WAIT_IOCINFOACK
;
2703 putnext(WR(q
), tirmp
);
2705 tilog("emulate_tcap_req: allocb fail, "
2706 "no recovery attmpt\n", 0);
2707 tp
->tim_iocsave
= NULL
;
2708 tp
->tim_saved_prim
= -1;
2709 tp
->tim_flags
&= ~(TI_CAP_RECVD
| WAITIOCACK
|
2710 CAP_WANTS_INFO
| WAIT_IOCINFOACK
);
2711 miocnak(q
, mp
, 0, ENOMEM
);
2714 /* Reply immediately */
2715 mblk_t
*ackmp
= tpi_ack_alloc(NULL
,
2716 sizeof (struct T_capability_ack
), M_PCPROTO
,
2721 if (ackmp
!= NULL
) {
2722 ((struct T_capability_ack
*)
2723 ackmp
->b_rptr
)->CAP_bits1
= 0;
2724 tim_ioctl_send_reply(q
, mp
, ackmp
);
2725 tp
->tim_iocsave
= NULL
;
2726 tp
->tim_saved_prim
= -1;
2727 tp
->tim_flags
&= ~(WAITIOCACK
| WAIT_IOCINFOACK
|
2728 TI_CAP_RECVD
| CAP_WANTS_INFO
);
2730 tilog("timodwproc:allocb failed no "
2731 "recovery attempt\n", 0);
2732 tp
->tim_iocsave
= NULL
;
2733 tp
->tim_saved_prim
= -1;
2734 tp
->tim_flags
&= ~(TI_CAP_RECVD
| WAITIOCACK
|
2735 CAP_WANTS_INFO
| WAIT_IOCINFOACK
);
2736 miocnak(q
, mp
, 0, ENOMEM
);
2743 tim_ioctl_send_reply(queue_t
*q
, mblk_t
*ioc_mp
, mblk_t
*mp
)
2745 struct iocblk
*iocbp
;
2747 ASSERT(q
!= NULL
&& ioc_mp
!= NULL
);
2749 ioc_mp
->b_datap
->db_type
= M_IOCACK
;
2751 mp
->b_datap
->db_type
= M_DATA
;
2753 if (ioc_mp
->b_cont
!= mp
) {
2754 /* It is safe to call freemsg for NULL pointers */
2755 freemsg(ioc_mp
->b_cont
);
2756 ioc_mp
->b_cont
= mp
;
2758 iocbp
= (struct iocblk
*)ioc_mp
->b_rptr
;
2759 iocbp
->ioc_error
= 0;
2760 iocbp
->ioc_rval
= 0;
2762 * All ioctl's may return more data than was specified by
2763 * count arg. For TI_CAPABILITY count is treated as maximum data size.
2766 iocbp
->ioc_count
= 0;
2767 else if (iocbp
->ioc_cmd
!= TI_CAPABILITY
)
2768 iocbp
->ioc_count
= msgsize(mp
);
2770 iocbp
->ioc_count
= MIN(MBLKL(mp
), iocbp
->ioc_count
);
2771 /* Truncate message if too large */
2772 mp
->b_wptr
= mp
->b_rptr
+ iocbp
->ioc_count
;
2775 TILOG("iosendreply: ioc_cmd = %d, ", iocbp
->ioc_cmd
);
2776 putnext(RD(q
), ioc_mp
);
2780 * Send M_IOCACK for errors.
2783 tim_send_ioc_error_ack(queue_t
*q
, struct tim_tim
*tp
, mblk_t
*mp
)
2785 struct T_error_ack
*tea
= (struct T_error_ack
*)mp
->b_rptr
;
2786 t_scalar_t error_prim
;
2788 mp
->b_wptr
= mp
->b_rptr
+ sizeof (struct T_error_ack
);
2789 ASSERT(mp
->b_wptr
<= mp
->b_datap
->db_lim
);
2790 error_prim
= tea
->ERROR_prim
;
2792 ASSERT(tp
->tim_iocsave
!= NULL
);
2793 ASSERT(tp
->tim_iocsave
->b_cont
!= mp
);
2795 /* Always send this to the read side of the queue */
2798 TILOG("tim_send_ioc_error_ack: prim = %d\n", tp
->tim_saved_prim
);
2800 if (tp
->tim_saved_prim
!= error_prim
) {
2802 } else if (error_prim
== T_CAPABILITY_REQ
) {
2803 TILOG("timodrproc: T_ERROR_ACK/T_CAPABILITY_REQ\n", 0);
2804 ASSERT(tp
->tim_iocsave
->b_cont
== NULL
);
2806 tim_tcap_genreply(q
, tp
);
2809 struct iocblk
*iocbp
= (struct iocblk
*)tp
->tim_iocsave
->b_rptr
;
2811 TILOG("tim_send_ioc_error_ack: T_ERROR_ACK: prim %d\n",
2813 ASSERT(tp
->tim_iocsave
->b_cont
== NULL
);
2815 switch (error_prim
) {
2817 TILOG("timodrproc: Unknown T_ERROR_ACK: tlierror %d\n",
2824 case T_SVR4_OPTMGMT_REQ
:
2830 case T_CAPABILITY_REQ
:
2832 TILOG("ioc_err_ack: T_ERROR_ACK: tlierror %x\n",
2835 /* get saved ioctl msg and set values */
2836 iocbp
->ioc_count
= 0;
2837 iocbp
->ioc_error
= 0;
2838 iocbp
->ioc_rval
= tea
->TLI_error
;
2839 if (iocbp
->ioc_rval
== TSYSERR
)
2840 iocbp
->ioc_rval
|= tea
->UNIX_error
<< 8;
2841 tp
->tim_iocsave
->b_datap
->db_type
= M_IOCACK
;
2843 putnext(q
, tp
->tim_iocsave
);
2844 tp
->tim_iocsave
= NULL
;
2845 tp
->tim_saved_prim
= -1;
2846 tp
->tim_flags
&= ~(WAITIOCACK
| TI_CAP_RECVD
|
2847 CAP_WANTS_INFO
| WAIT_IOCINFOACK
);
2854 * Send reply to a usual message or ioctl message upstream.
2855 * Should be called from the read side only.
2858 tim_send_reply(queue_t
*q
, mblk_t
*mp
, struct tim_tim
*tp
, t_scalar_t prim
)
2860 ASSERT(mp
!= NULL
&& q
!= NULL
&& tp
!= NULL
);
2863 /* Restore db_type - recover() might have changed it */
2864 mp
->b_datap
->db_type
= M_PCPROTO
;
2866 if (((tp
->tim_flags
& WAITIOCACK
) == 0) || (tp
->tim_saved_prim
!= prim
))
2869 ASSERT(tp
->tim_iocsave
!= NULL
);
2870 tim_ioctl_send_reply(q
, tp
->tim_iocsave
, mp
);
2871 tp
->tim_iocsave
= NULL
;
2872 tp
->tim_saved_prim
= -1;
2873 tp
->tim_flags
&= ~(WAITIOCACK
| WAIT_IOCINFOACK
|
2874 TI_CAP_RECVD
| CAP_WANTS_INFO
);
2879 * Reply to TI_SYNC reequest without sending anything downstream.
2882 tim_answer_ti_sync(queue_t
*q
, mblk_t
*mp
, struct tim_tim
*tp
,
2883 mblk_t
*ackmp
, uint32_t tsr_flags
)
2885 struct ti_sync_ack
*tsap
;
2887 ASSERT(q
!= NULL
&& q
== WR(q
) && ackmp
!= NULL
);
2889 tsap
= (struct ti_sync_ack
*)ackmp
->b_rptr
;
2890 bzero(tsap
, sizeof (struct ti_sync_ack
));
2891 ackmp
->b_wptr
= ackmp
->b_rptr
+ sizeof (struct ti_sync_ack
);
2893 if (tsr_flags
== 0 ||
2894 (tsr_flags
& ~(TSRF_QLEN_REQ
| TSRF_IS_EXP_IN_RCVBUF
)) != 0) {
2896 * unsupported/bad flag setting
2899 TILOG("timodwproc: unsupported/bad flag setting %x\n",
2902 miocnak(q
, mp
, 0, EINVAL
);
2906 if ((tsr_flags
& TSRF_QLEN_REQ
) != 0)
2907 tsap
->tsa_qlen
= tp
->tim_backlog
;
2909 if ((tsr_flags
& TSRF_IS_EXP_IN_RCVBUF
) != 0 &&
2910 ti_expind_on_rdqueues(RD(q
))) {
2912 * Expedited data is queued on
2913 * the stream read side
2915 tsap
->tsa_flags
|= TSAF_EXP_QUEUED
;
2918 tim_ioctl_send_reply(q
, mp
, ackmp
);
2919 tp
->tim_iocsave
= NULL
;
2920 tp
->tim_saved_prim
= -1;
2921 tp
->tim_flags
&= ~(WAITIOCACK
| WAIT_IOCINFOACK
|
2922 TI_CAP_RECVD
| CAP_WANTS_INFO
);
2926 * Send TPI message from IOCTL message, ssave original ioctl header and TPI
2927 * message type. Should be called from write side only.
2930 tim_send_ioctl_tpi_msg(queue_t
*q
, mblk_t
*mp
, struct tim_tim
*tp
,
2931 struct iocblk
*iocb
)
2934 int ioc_cmd
= iocb
->ioc_cmd
;
2936 ASSERT(q
!= NULL
&& mp
!= NULL
&& tp
!= NULL
);
2938 ASSERT(mp
->b_cont
!= NULL
);
2940 tp
->tim_iocsave
= mp
;
2944 tp
->tim_flags
|= WAITIOCACK
;
2945 tp
->tim_saved_prim
= ((union T_primitives
*)tmp
->b_rptr
)->type
;
2948 * For TI_GETINFO, the attached message is a T_INFO_REQ
2949 * For TI_SYNC, we generate the T_INFO_REQ message above
2950 * For TI_CAPABILITY the attached message is either
2951 * T_CAPABILITY_REQ or T_INFO_REQ.
2952 * Among TPI request messages possible,
2953 * T_INFO_REQ/T_CAPABILITY_ACK messages are a M_PCPROTO, rest
2956 if (ioc_cmd
== TI_GETINFO
|| ioc_cmd
== TI_SYNC
||
2957 ioc_cmd
== TI_CAPABILITY
) {
2958 tmp
->b_datap
->db_type
= M_PCPROTO
;
2960 tmp
->b_datap
->db_type
= M_PROTO
;
2963 /* Verify credentials in STREAM */
2964 ASSERT(iocb
->ioc_cr
== NULL
|| iocb
->ioc_cr
== DB_CRED(tmp
));
2966 ASSERT(DB_CRED(tmp
) != NULL
);
2968 TILOG("timodwproc: sending down %d\n", tp
->tim_saved_prim
);
2973 tim_clear_peer(struct tim_tim
*tp
)
2975 mutex_enter(&tp
->tim_mutex
);
2976 if (tp
->tim_peercred
!= NULL
) {
2977 crfree(tp
->tim_peercred
);
2978 tp
->tim_peercred
= NULL
;
2980 tp
->tim_peerlen
= 0;
2981 mutex_exit(&tp
->tim_mutex
);