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>
54 * This is the loadable module wrapper.
57 #include <sys/modctl.h>
59 static struct streamtab timinfo
;
61 static struct fmodsw fsw
= {
68 * Module linkage information for the kernel.
71 static struct modlstrmod modlstrmod
= {
72 &mod_strmodops
, "transport interface str mod", &fsw
75 static struct modlinkage modlinkage
= {
76 MODREV_1
, &modlstrmod
, NULL
79 static krwlock_t tim_list_rwlock
;
82 * This module keeps track of capabilities of underlying transport. Information
83 * is persistent through module invocations (open/close). Currently it remembers
84 * whether underlying transport supports TI_GET{MY,PEER}NAME ioctls and
85 * T_CAPABILITY_REQ message. This module either passes ioctl/messages to the
86 * transport or emulates it when transport doesn't understand these
89 * It is assumed that transport supports T_CAPABILITY_REQ when timod receives
90 * T_CAPABILITY_ACK from the transport. There is no current standard describing
91 * transport behaviour when it receives unknown message type, so following
92 * reactions are expected and handled:
94 * 1) Transport drops unknown T_CAPABILITY_REQ message type. In this case timod
95 * will wait for tcap_wait time and assume that transport doesn't provide
96 * this message type. T_CAPABILITY_REQ should never travel over the wire, so
97 * timeout value should only take into consideration internal processing time
98 * for the message. From user standpoint it may mean that an application will
99 * hang for TCAP_WAIT time in the kernel the first time this message is used
100 * with some particular transport (e.g. TCP/IP) during system uptime.
102 * 2) Transport responds with T_ERROR_ACK specifying T_CAPABILITY_REQ as
103 * original message type. In this case it is assumed that transport doesn't
104 * support it (which may not always be true - some transports return
105 * T_ERROR_ACK in other cases like lack of system memory).
107 * 3) Transport responds with M_ERROR, effectively shutting down the
108 * stream. Unfortunately there is no standard way to pass the reason of
109 * M_ERROR message back to the caller, so it is assumed that if M_ERROR was
110 * sent in response to T_CAPABILITY_REQ message, transport doesn't support
113 * It is possible under certain circumstances that timod will incorrectly assume
114 * that underlying transport doesn't provide T_CAPABILITY_REQ message type. In
115 * this "worst-case" scenario timod will emulate its functionality by itself and
116 * will provide only TC1_INFO capability. All other bits in CAP_bits1 field are
117 * cleaned. TC1_INFO is emulated by sending T_INFO_REQ down to transport
122 * Notes about locking:
124 * tim_list_rwlock protects the list of tim_tim structures itself. When this
125 * lock is held, the list itself is stable, but the contents of the entries
126 * themselves might not be.
128 * The rest of the members are generally protected by D_MTQPAIR, which
129 * specifies a default exclusive inner perimeter. If you're looking at
130 * q->q_ptr, then it's stable.
132 * There's one exception to this rule: tim_peer{maxlen,len,name}. These members
133 * are touched without entering the associated STREAMS perimeter because we
134 * get the pointer via tim_findlink() rather than q_ptr. These are protected
135 * by tim_mutex instead. If you don't hold that lock, don't look at them.
137 * (It would be possible to separate out the 'set by T_CONN_RES' cases from the
138 * others, but there appears to be no reason to do so.)
142 t_uscalar_t tim_backlog
;
144 t_scalar_t tim_mymaxlen
;
145 t_scalar_t tim_mylen
;
147 t_scalar_t tim_peermaxlen
;
148 t_scalar_t tim_peerlen
;
149 caddr_t tim_peername
;
150 cred_t
*tim_peercred
;
152 bufcall_id_t tim_wbufcid
;
153 bufcall_id_t tim_rbufcid
;
154 timeout_id_t tim_wtimoutid
;
155 timeout_id_t tim_rtimoutid
;
156 /* Protected by the global tim_list_rwlock for all instances */
157 struct tim_tim
*tim_next
;
158 struct tim_tim
**tim_ptpn
;
159 t_uscalar_t tim_acceptor
;
160 t_scalar_t tim_saved_prim
; /* Primitive from message */
162 timeout_id_t tim_tcap_timoutid
; /* For T_CAP_REQ timeout */
163 tpi_provinfo_t
*tim_provinfo
; /* Transport description */
164 kmutex_t tim_mutex
; /* protect tim_peer* */
170 * Local flags used with tim_flags field in instance structure of
171 * type 'struct _ti_user' declared above.
173 * This namespace constants were previously declared in a
174 * a very messed up namespace in timod.h
176 * There may be 3 states for transport:
178 * 1) It provides T_CAPABILITY_REQ
179 * 2) It does not provide T_CAPABILITY_REQ
180 * 3) It is not known yet whether transport provides T_CAPABILITY_REQ or not.
182 * It is assumed that the underlying transport either provides
183 * T_CAPABILITY_REQ or not and this does not changes during the
187 #define PEEK_RDQ_EXPIND 0x0001 /* look for expinds on stream rd queues */
188 #define WAITIOCACK 0x0002 /* waiting for info for ioctl act */
189 #define CLTS 0x0004 /* connectionless transport */
190 #define COTS 0x0008 /* connection-oriented transport */
191 #define CONNWAIT 0x0010 /* waiting for connect confirmation */
192 #define LOCORDREL 0x0020 /* local end has orderly released */
193 #define REMORDREL 0x0040 /* remote end had orderly released */
194 #define NAMEPROC 0x0080 /* processing a NAME ioctl */
195 #define DO_MYNAME 0x0100 /* timod handles TI_GETMYNAME */
196 #define DO_PEERNAME 0x0200 /* timod handles TI_GETPEERNAME */
197 #define TI_CAP_RECVD 0x0400 /* TI_CAPABILITY received */
198 #define CAP_WANTS_INFO 0x0800 /* TI_CAPABILITY has TC1_INFO set */
199 #define WAIT_IOCINFOACK 0x1000 /* T_INFO_REQ generated from ioctl */
200 #define WAIT_CONNRESACK 0x2000 /* waiting for T_OK_ACK to T_CONN_RES */
203 /* Debugging facilities */
205 * Logging needed for debugging timod should only appear in DEBUG kernel.
208 #define TILOG(msg, arg) tilog((msg), (arg))
209 #define TILOGP(msg, arg) tilogp((msg), (arg))
211 #define TILOG(msg, arg)
212 #define TILOGP(msg, arg)
217 * Sleep timeout for T_CAPABILITY_REQ. This message never travels across
218 * network, so timeout value should be enough to cover all internal processing
221 clock_t tim_tcap_wait
= 2;
223 /* Sleep timeout in tim_recover() */
224 #define TIMWAIT (1*hz)
225 /* Sleep timeout in tim_ioctl_retry() 0.2 seconds */
226 #define TIMIOCWAIT (200*hz/1000)
229 * Return values for ti_doname().
231 #define DONAME_FAIL 0 /* failing ioctl (done) */
232 #define DONAME_DONE 1 /* done processing */
233 #define DONAME_CONT 2 /* continue proceesing (not done yet) */
236 * Function prototypes
238 static int ti_doname(queue_t
*, mblk_t
*);
239 static int ti_expind_on_rdqueues(queue_t
*);
240 static void tim_ioctl_send_reply(queue_t
*, mblk_t
*, mblk_t
*);
241 static void tim_send_ioc_error_ack(queue_t
*, struct tim_tim
*, mblk_t
*);
242 static void tim_tcap_timer(void *);
243 static void tim_tcap_genreply(queue_t
*, struct tim_tim
*);
244 static void tim_send_reply(queue_t
*, mblk_t
*, struct tim_tim
*, t_scalar_t
);
245 static void tim_answer_ti_sync(queue_t
*, mblk_t
*, struct tim_tim
*,
247 static void tim_send_ioctl_tpi_msg(queue_t
*, mblk_t
*, struct tim_tim
*,
249 static void tim_clear_peer(struct tim_tim
*);
256 rw_init(&tim_list_rwlock
, NULL
, RW_DRIVER
, NULL
);
257 error
= mod_install(&modlinkage
);
259 rw_destroy(&tim_list_rwlock
);
271 error
= mod_remove(&modlinkage
);
274 rw_destroy(&tim_list_rwlock
);
279 _info(struct modinfo
*modinfop
)
281 return (mod_info(&modlinkage
, modinfop
));
286 * Hash list for all instances. Used to find tim_tim structure based on
287 * ACCEPTOR_id in T_CONN_RES. Protected by tim_list_rwlock.
289 #define TIM_HASH_SIZE 256
291 #define TIM_HASH(id) (((uintptr_t)(id) >> 8) % TIM_HASH_SIZE)
293 #define TIM_HASH(id) ((uintptr_t)(id) % TIM_HASH_SIZE)
295 static struct tim_tim
*tim_hash
[TIM_HASH_SIZE
];
298 static void tilog(char *, t_scalar_t
);
299 static void tilogp(char *, uintptr_t);
300 static mblk_t
*tim_filladdr(queue_t
*, mblk_t
*, boolean_t
);
301 static void tim_addlink(struct tim_tim
*);
302 static void tim_dellink(struct tim_tim
*);
303 static struct tim_tim
*tim_findlink(t_uscalar_t
);
304 static void tim_recover(queue_t
*, mblk_t
*, t_scalar_t
);
305 static void tim_ioctl_retry(queue_t
*);
311 static int timodopen(queue_t
*, dev_t
*, int, int, cred_t
*);
312 static int timodclose(queue_t
*, int, cred_t
*);
313 static void timodwput(queue_t
*, mblk_t
*);
314 static void timodrput(queue_t
*, mblk_t
*);
315 static void timodrsrv(queue_t
*);
316 static void timodwsrv(queue_t
*);
317 static int timodrproc(queue_t
*, mblk_t
*);
318 static int timodwproc(queue_t
*, mblk_t
*);
320 /* stream data structure definitions */
322 static struct module_info timod_info
=
323 {TIMOD_ID
, "timod", 0, INFPSZ
, 512, 128};
324 static struct qinit timodrinit
= {
325 (int (*)())timodrput
,
326 (int (*)())timodrsrv
,
333 static struct qinit timodwinit
= {
334 (int (*)())timodwput
,
335 (int (*)())timodwsrv
,
342 static struct streamtab timinfo
= { &timodrinit
, &timodwinit
, NULL
, NULL
};
345 * timodopen - open routine gets called when the module gets pushed
358 struct stroptions
*sop
;
367 if ((bp
= allocb(sizeof (struct stroptions
), BPRI_MED
)) == 0)
370 tp
= kmem_zalloc(sizeof (struct tim_tim
), KM_SLEEP
);
373 tp
->tim_saved_prim
= -1;
375 mutex_init(&tp
->tim_mutex
, NULL
, MUTEX_DEFAULT
, NULL
);
377 q
->q_ptr
= (caddr_t
)tp
;
378 WR(q
)->q_ptr
= (caddr_t
)tp
;
380 tilogp("timodopen: Allocated for tp %lx\n", (uintptr_t)tp
);
381 tilogp("timodopen: Allocated for q %lx\n", (uintptr_t)q
);
383 /* Must be done before tpi_findprov and _ILP32 q_next walk below */
386 tp
->tim_provinfo
= tpi_findprov(q
);
389 * Defer allocation of the buffers for the local address and
390 * the peer's address until we need them.
391 * Assume that timod has to handle getname until we here
392 * an iocack from the transport provider or we know that
393 * transport provider doesn't understand it.
395 if (tp
->tim_provinfo
->tpi_myname
!= PI_YES
) {
396 TILOG("timodopen: setting DO_MYNAME\n", 0);
397 tp
->tim_flags
|= DO_MYNAME
;
400 if (tp
->tim_provinfo
->tpi_peername
!= PI_YES
) {
401 TILOG("timodopen: setting DO_PEERNAME\n", 0);
402 tp
->tim_flags
|= DO_PEERNAME
;
410 * Find my driver's read queue (for T_CONN_RES handling)
413 while (SAMESTR(driverq
))
414 driverq
= driverq
->q_next
;
416 tp
->tim_acceptor
= (t_uscalar_t
)RD(driverq
);
419 tp
->tim_acceptor
= (t_uscalar_t
)getminor(*devp
);
423 * Add this one to the list.
428 * Send M_SETOPTS to stream head to make sure M_PCPROTO messages
429 * are not flushed. This prevents application deadlocks.
431 bp
->b_datap
->db_type
= M_SETOPTS
;
432 bp
->b_wptr
+= sizeof (struct stroptions
);
433 sop
= (struct stroptions
*)bp
->b_rptr
;
434 sop
->so_flags
= SO_READOPT
;
435 sop
->so_readopt
= RFLUSHPCPROT
;
446 struct tim_tim
*tp
= (struct tim_tim
*)q
->q_ptr
;
450 if (q
->q_flag
& QREADR
) {
451 ASSERT(tp
->tim_rtimoutid
);
452 tp
->tim_rtimoutid
= 0;
454 ASSERT(tp
->tim_wtimoutid
);
455 tp
->tim_wtimoutid
= 0;
462 tim_buffer(void *arg
)
465 struct tim_tim
*tp
= (struct tim_tim
*)q
->q_ptr
;
469 if (q
->q_flag
& QREADR
) {
470 ASSERT(tp
->tim_rbufcid
);
473 ASSERT(tp
->tim_wbufcid
);
481 * timodclose - This routine gets called when the module gets popped
497 tp
= (struct tim_tim
*)q
->q_ptr
;
502 tilogp("timodclose: Entered for tp %lx\n", (uintptr_t)tp
);
503 tilogp("timodclose: Entered for q %lx\n", (uintptr_t)q
);
509 * Cancel any outstanding bufcall
510 * or timeout requests.
512 if (tp
->tim_wbufcid
) {
513 qunbufcall(q
, tp
->tim_wbufcid
);
516 if (tp
->tim_rbufcid
) {
517 qunbufcall(q
, tp
->tim_rbufcid
);
520 if (tp
->tim_wtimoutid
) {
521 (void) quntimeout(q
, tp
->tim_wtimoutid
);
522 tp
->tim_wtimoutid
= 0;
524 if (tp
->tim_rtimoutid
) {
525 (void) quntimeout(q
, tp
->tim_rtimoutid
);
526 tp
->tim_rtimoutid
= 0;
529 if (tp
->tim_tcap_timoutid
!= 0) {
530 (void) quntimeout(q
, tp
->tim_tcap_timoutid
);
531 tp
->tim_tcap_timoutid
= 0;
534 if (tp
->tim_iocsave
!= NULL
)
535 freemsg(tp
->tim_iocsave
);
536 mp
= tp
->tim_consave
;
543 ASSERT(tp
->tim_mymaxlen
>= 0);
544 if (tp
->tim_mymaxlen
!= 0)
545 kmem_free(tp
->tim_myname
, (size_t)tp
->tim_mymaxlen
);
546 ASSERT(tp
->tim_peermaxlen
>= 0);
547 if (tp
->tim_peermaxlen
!= 0)
548 kmem_free(tp
->tim_peername
, (size_t)tp
->tim_peermaxlen
);
550 q
->q_ptr
= WR(q
)->q_ptr
= NULL
;
552 mutex_destroy(&tp
->tim_mutex
);
554 if (tp
->tim_peercred
!= NULL
)
555 crfree(tp
->tim_peercred
);
557 kmem_free(tp
, sizeof (struct tim_tim
));
563 * timodrput - Module read put procedure. This is called from
564 * the module, driver, or stream head upstream/downstream.
565 * Handles M_FLUSH, M_DATA and some M_PROTO (T_DATA_IND,
566 * and T_UNITDATA_IND) messages. All others are queued to
567 * be handled by the service procedures.
570 timodrput(queue_t
*q
, mblk_t
*mp
)
572 union T_primitives
*pptr
;
575 * During flow control and other instances when messages
576 * are on queue, queue up a non high priority message
578 if (q
->q_first
!= 0 && mp
->b_datap
->db_type
< QPCTL
) {
584 * Inline processing of data (to avoid additional procedure call).
585 * Rest is handled in timodrproc.
588 switch (mp
->b_datap
->db_type
) {
590 if (bcanputnext(q
, mp
->b_band
))
597 if (MBLKL(mp
) < sizeof (t_scalar_t
)) {
598 if (mp
->b_datap
->db_type
== M_PCPROTO
||
599 bcanputnext(q
, mp
->b_band
)) {
606 pptr
= (union T_primitives
*)mp
->b_rptr
;
607 switch (pptr
->type
) {
611 if (bcanputnext(q
, mp
->b_band
))
617 (void) timodrproc(q
, mp
);
622 (void) timodrproc(q
, mp
);
628 * timodrsrv - Module read queue service procedure. This is called when
629 * messages are placed on an empty queue, when high priority
630 * messages are placed on the queue, and when flow control
631 * restrictions subside. This code used to be included in a
632 * put procedure, but it was moved to a service procedure
633 * because several points were added where memory allocation
634 * could fail, and there is no reasonable recovery mechanism
635 * from the put procedure.
639 timodrsrv(queue_t
*q
)
646 tp
= (struct tim_tim
*)q
->q_ptr
;
650 while ((mp
= getq(q
)) != NULL
) {
651 if (timodrproc(q
, mp
)) {
653 * timodrproc did a putbq - stop processing
662 * Perform common processing when a T_CAPABILITY_ACK or T_INFO_ACK
663 * arrive. Set the queue properties and adjust the tim_flags according
664 * to the service type.
667 timodprocessinfo(queue_t
*q
, struct tim_tim
*tp
, struct T_info_ack
*tia
)
669 TILOG("timodprocessinfo: strqset(%d)\n", tia
->TIDU_size
);
670 (void) strqset(q
, QMAXPSZ
, 0, tia
->TIDU_size
);
671 (void) strqset(OTHERQ(q
), QMAXPSZ
, 0, tia
->TIDU_size
);
673 if ((tia
->SERV_type
== T_COTS
) || (tia
->SERV_type
== T_COTS_ORD
))
674 tp
->tim_flags
= (tp
->tim_flags
& ~CLTS
) | COTS
;
675 else if (tia
->SERV_type
== T_CLTS
)
676 tp
->tim_flags
= (tp
->tim_flags
& ~COTS
) | CLTS
;
680 timodrproc(queue_t
*q
, mblk_t
*mp
)
682 union T_primitives
*pptr
;
684 struct iocblk
*iocbp
;
688 tp
= (struct tim_tim
*)q
->q_ptr
;
690 switch (mp
->b_datap
->db_type
) {
696 TILOG("timodrproc: Got M_ERROR, flags = %x\n", tp
->tim_flags
);
698 * There is no specified standard response for driver when it
699 * receives unknown message type and M_ERROR is one
700 * possibility. If we send T_CAPABILITY_REQ down and transport
701 * provider responds with M_ERROR we assume that it doesn't
702 * understand this message type. This assumption may be
703 * sometimes incorrect (transport may reply with M_ERROR for
704 * some other reason) but there is no way for us to distinguish
705 * between different cases. In the worst case timod and everyone
706 * else sharing global transport description with it may end up
707 * emulating T_CAPABILITY_REQ.
711 * Check that we are waiting for T_CAPABILITY_ACK and
712 * T_CAPABILITY_REQ is not implemented by transport or emulated
715 if ((tp
->tim_provinfo
->tpi_capability
== PI_DONTKNOW
) &&
716 ((tp
->tim_flags
& TI_CAP_RECVD
) != 0)) {
718 * Good chances that this transport doesn't provide
719 * T_CAPABILITY_REQ. Mark this information permanently
720 * for the module + transport combination.
722 PI_PROVLOCK(tp
->tim_provinfo
);
723 if (tp
->tim_provinfo
->tpi_capability
== PI_DONTKNOW
)
724 tp
->tim_provinfo
->tpi_capability
= PI_NO
;
725 PI_PROVUNLOCK(tp
->tim_provinfo
);
726 if (tp
->tim_tcap_timoutid
!= 0) {
727 (void) quntimeout(q
, tp
->tim_tcap_timoutid
);
728 tp
->tim_tcap_timoutid
= 0;
734 if (!bcanputnext(q
, mp
->b_band
)) {
744 if (blen
< sizeof (t_scalar_t
)) {
746 * Note: it's not actually possible to get
747 * here with db_type M_PCPROTO, because
748 * timodrput has already checked MBLKL, and
749 * thus the assertion below. If the length
750 * was too short, then the message would have
751 * already been putnext'd, and would thus
752 * never appear here. Just the same, the code
753 * below handles the impossible case since
754 * it's easy to do and saves future
755 * maintainers from unfortunate accidents.
757 ASSERT(mp
->b_datap
->db_type
== M_PROTO
);
758 if (mp
->b_datap
->db_type
== M_PROTO
&&
759 !bcanputnext(q
, mp
->b_band
)) {
767 pptr
= (union T_primitives
*)mp
->b_rptr
;
768 switch (pptr
->type
) {
775 /* Restore db_type - recover() might have changed it */
776 mp
->b_datap
->db_type
= M_PCPROTO
;
777 if (blen
< sizeof (struct T_error_ack
)) {
782 tilog("timodrproc: Got T_ERROR_ACK, flags = %x\n",
785 if ((tp
->tim_flags
& WAIT_CONNRESACK
) &&
786 tp
->tim_saved_prim
== pptr
->error_ack
.ERROR_prim
) {
788 ~(WAIT_CONNRESACK
| WAITIOCACK
);
789 freemsg(tp
->tim_iocsave
);
790 tp
->tim_iocsave
= NULL
;
791 tp
->tim_saved_prim
= -1;
793 } else if (tp
->tim_flags
& WAITIOCACK
) {
794 tim_send_ioc_error_ack(q
, tp
, mp
);
801 if (blen
< sizeof (pptr
->ok_ack
)) {
802 mp
->b_datap
->db_type
= M_PCPROTO
;
807 tilog("timodrproc: Got T_OK_ACK\n", 0);
809 if (pptr
->ok_ack
.CORRECT_prim
== T_UNBIND_REQ
)
812 if ((tp
->tim_flags
& WAIT_CONNRESACK
) &&
813 tp
->tim_saved_prim
== pptr
->ok_ack
.CORRECT_prim
) {
814 struct T_conn_res
*resp
;
815 struct T_conn_ind
*indp
;
819 rw_enter(&tim_list_rwlock
, RW_READER
);
820 resp
= (struct T_conn_res
*)
821 tp
->tim_iocsave
->b_rptr
;
822 ntp
= tim_findlink(resp
->ACCEPTOR_id
);
826 mutex_enter(&ntp
->tim_mutex
);
827 if (ntp
->tim_peercred
!= NULL
)
828 crfree(ntp
->tim_peercred
);
830 msg_getcred(tp
->tim_iocsave
->b_cont
,
832 if (ntp
->tim_peercred
!= NULL
)
833 crhold(ntp
->tim_peercred
);
835 if (!(ntp
->tim_flags
& DO_PEERNAME
)) {
836 mutex_exit(&ntp
->tim_mutex
);
840 indp
= (struct T_conn_ind
*)
841 tp
->tim_iocsave
->b_cont
->b_rptr
;
842 /* true as message is put on list */
843 ASSERT(indp
->SRC_length
>= 0);
845 if (indp
->SRC_length
> ntp
->tim_peermaxlen
) {
846 ptr
= kmem_alloc(indp
->SRC_length
,
849 mutex_exit(&ntp
->tim_mutex
);
850 rw_exit(&tim_list_rwlock
);
851 tilog("timodwproc: kmem_alloc "
852 "failed, attempting "
858 if (ntp
->tim_peermaxlen
> 0)
859 kmem_free(ntp
->tim_peername
,
860 ntp
->tim_peermaxlen
);
861 ntp
->tim_peername
= ptr
;
862 ntp
->tim_peermaxlen
= indp
->SRC_length
;
864 ntp
->tim_peerlen
= indp
->SRC_length
;
865 ptr
= (caddr_t
)indp
+ indp
->SRC_offset
;
866 bcopy(ptr
, ntp
->tim_peername
, ntp
->tim_peerlen
);
868 mutex_exit(&ntp
->tim_mutex
);
871 rw_exit(&tim_list_rwlock
);
873 ~(WAIT_CONNRESACK
| WAITIOCACK
);
874 freemsg(tp
->tim_iocsave
);
875 tp
->tim_iocsave
= NULL
;
876 tp
->tim_saved_prim
= -1;
879 tim_send_reply(q
, mp
, tp
, pptr
->ok_ack
.CORRECT_prim
);
883 struct T_bind_ack
*ackp
=
884 (struct T_bind_ack
*)mp
->b_rptr
;
886 /* Restore db_type - recover() might have changed it */
887 mp
->b_datap
->db_type
= M_PCPROTO
;
888 if (blen
< sizeof (*ackp
)) {
893 /* save negotiated backlog */
894 tp
->tim_backlog
= ackp
->CONIND_number
;
896 if (((tp
->tim_flags
& WAITIOCACK
) == 0) ||
897 ((tp
->tim_saved_prim
!= O_T_BIND_REQ
) &&
898 (tp
->tim_saved_prim
!= T_BIND_REQ
))) {
902 ASSERT(tp
->tim_iocsave
!= NULL
);
904 if (tp
->tim_flags
& DO_MYNAME
) {
907 if (ackp
->ADDR_length
< 0 ||
908 mp
->b_rptr
+ ackp
->ADDR_offset
+
909 ackp
->ADDR_length
> mp
->b_wptr
) {
913 if (ackp
->ADDR_length
> tp
->tim_mymaxlen
) {
914 p
= kmem_alloc(ackp
->ADDR_length
,
917 tilog("timodrproc: kmem_alloc "
918 "failed attempt recovery",
925 ASSERT(tp
->tim_mymaxlen
>= 0);
926 if (tp
->tim_mymaxlen
!= 0) {
927 kmem_free(tp
->tim_myname
,
931 tp
->tim_mymaxlen
= ackp
->ADDR_length
;
933 tp
->tim_mylen
= ackp
->ADDR_length
;
934 bcopy(mp
->b_rptr
+ ackp
->ADDR_offset
,
935 tp
->tim_myname
, tp
->tim_mylen
);
937 tim_ioctl_send_reply(q
, tp
->tim_iocsave
, mp
);
938 tp
->tim_iocsave
= NULL
;
939 tp
->tim_saved_prim
= -1;
940 tp
->tim_flags
&= ~(WAITIOCACK
| WAIT_IOCINFOACK
|
941 TI_CAP_RECVD
| CAP_WANTS_INFO
);
947 tilog("timodrproc: Got T_OPTMGMT_ACK\n", 0);
949 /* Restore db_type - recover() might have change it */
950 mp
->b_datap
->db_type
= M_PCPROTO
;
952 if (((tp
->tim_flags
& WAITIOCACK
) == 0) ||
953 ((tp
->tim_saved_prim
!= T_SVR4_OPTMGMT_REQ
) &&
954 (tp
->tim_saved_prim
!= T_OPTMGMT_REQ
))) {
957 ASSERT(tp
->tim_iocsave
!= NULL
);
958 tim_ioctl_send_reply(q
, tp
->tim_iocsave
, mp
);
959 tp
->tim_iocsave
= NULL
;
960 tp
->tim_saved_prim
= -1;
961 tp
->tim_flags
&= ~(WAITIOCACK
|
962 WAIT_IOCINFOACK
| TI_CAP_RECVD
|
968 struct T_info_ack
*tia
= (struct T_info_ack
*)pptr
;
970 /* Restore db_type - recover() might have changed it */
971 mp
->b_datap
->db_type
= M_PCPROTO
;
973 if (blen
< sizeof (*tia
)) {
978 tilog("timodrproc: Got T_INFO_ACK, flags = %x\n",
981 timodprocessinfo(q
, tp
, tia
);
983 TILOG("timodrproc: flags = %x\n", tp
->tim_flags
);
984 if ((tp
->tim_flags
& WAITIOCACK
) != 0) {
985 size_t expected_ack_size
;
988 struct T_capability_ack
*tcap
;
991 * The only case when T_INFO_ACK may be received back
992 * when we are waiting for ioctl to complete is when
993 * this ioctl sent T_INFO_REQ down.
995 if (!(tp
->tim_flags
& WAIT_IOCINFOACK
)) {
999 ASSERT(tp
->tim_iocsave
!= NULL
);
1001 iocbp
= (struct iocblk
*)
1002 tp
->tim_iocsave
->b_rptr
;
1003 ioc_cmd
= iocbp
->ioc_cmd
;
1006 * Was it sent from TI_CAPABILITY emulation?
1008 if (ioc_cmd
== TI_CAPABILITY
) {
1009 struct T_info_ack saved_info
;
1012 * Perform sanity checks. The only case when we
1013 * send T_INFO_REQ from TI_CAPABILITY is when
1014 * timod emulates T_CAPABILITY_REQ and
1015 * CAP_bits1 has TC1_INFO set.
1017 if ((tp
->tim_flags
&
1018 (TI_CAP_RECVD
| CAP_WANTS_INFO
)) !=
1019 (TI_CAP_RECVD
| CAP_WANTS_INFO
)) {
1025 " emulating TI_CAPABILITY/"
1028 /* Save info & reuse mp for T_CAPABILITY_ACK */
1031 mp
= tpi_ack_alloc(mp
,
1032 sizeof (struct T_capability_ack
),
1033 M_PCPROTO
, T_CAPABILITY_ACK
);
1037 " realloc failed, no "
1038 "recovery attempted\n", 0);
1043 * Copy T_INFO information into T_CAPABILITY_ACK
1045 tcap
= (struct T_capability_ack
*)
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
,
1053 tp
->tim_iocsave
, mp
);
1054 tp
->tim_iocsave
= NULL
;
1055 tp
->tim_saved_prim
= -1;
1060 * The code for TI_SYNC/TI_GETINFO is left here only for
1061 * backward compatibility with staticaly linked old
1062 * applications. New TLI/XTI code should use
1063 * TI_CAPABILITY for getting transport info and should
1064 * not use TI_GETINFO/TI_SYNC for this purpose.
1068 * make sure the message sent back is the size of
1069 * the "expected ack"
1070 * For TI_GETINFO, expected ack size is
1071 * sizeof (T_info_ack)
1072 * For TI_SYNC, expected ack size is
1073 * sizeof (struct ti_sync_ack);
1075 if (ioc_cmd
!= TI_GETINFO
&&
1076 ioc_cmd
!= TI_SYNC
) {
1082 sizeof (struct T_info_ack
); /* TI_GETINFO */
1083 if (iocbp
->ioc_cmd
== TI_SYNC
) {
1084 expected_ack_size
= 2 *
1086 sizeof (struct ti_sync_ack
);
1088 deficit
= expected_ack_size
- blen
;
1091 if (mp
->b_datap
->db_lim
- mp
->b_wptr
<
1092 deficit
) { /* BEGIN CSTYLED */
1093 mblk_t
*tmp
= allocb(expected_ack_size
,
1096 ASSERT(MBLKSIZE(mp
) >=
1097 sizeof (struct T_error_ack
));
1099 tilog("timodrproc: allocb failed no "
1100 "recovery attempt\n", 0);
1102 mp
->b_rptr
= mp
->b_datap
->db_base
;
1103 pptr
= (union T_primitives
*)
1105 pptr
->error_ack
.ERROR_prim
= T_INFO_REQ
;
1106 pptr
->error_ack
.TLI_error
= TSYSERR
;
1107 pptr
->error_ack
.UNIX_error
= EAGAIN
;
1108 pptr
->error_ack
.PRIM_type
= T_ERROR_ACK
;
1109 mp
->b_datap
->db_type
= M_PCPROTO
;
1110 tim_send_ioc_error_ack(q
, tp
, mp
);
1113 bcopy(mp
->b_rptr
, tmp
->b_rptr
,
1115 tmp
->b_wptr
+= blen
;
1116 pptr
= (union T_primitives
*)
1125 * We now have "mp" which has enough space for an
1126 * appropriate ack and contains struct T_info_ack
1127 * that the transport provider returned. We now
1128 * stuff it with more stuff to fullfill
1129 * TI_SYNC ioctl needs, as necessary
1131 if (iocbp
->ioc_cmd
== TI_SYNC
) {
1133 * Assumes struct T_info_ack is first embedded
1134 * type in struct ti_sync_ack so it is
1135 * automatically there.
1137 struct ti_sync_ack
*tsap
=
1138 (struct ti_sync_ack
*)mp
->b_rptr
;
1141 * tsap->tsa_qlen needs to be set only if
1142 * TSRF_QLEN_REQ flag is set, but for
1143 * compatibility with statically linked
1144 * applications it is set here regardless of the
1145 * flag since old XTI library expected it to be
1148 tsap
->tsa_qlen
= tp
->tim_backlog
;
1149 /* intialize clear */
1150 tsap
->tsa_flags
= 0x0;
1151 if (tp
->tim_flags
& PEEK_RDQ_EXPIND
) {
1153 * Request to peek for EXPIND in
1156 if (ti_expind_on_rdqueues(q
)) {
1159 * queued on the stream
1168 mp
->b_wptr
+= 2*sizeof (uint32_t);
1170 tim_ioctl_send_reply(q
, tp
->tim_iocsave
, mp
);
1171 tp
->tim_iocsave
= NULL
;
1172 tp
->tim_saved_prim
= -1;
1174 ~(WAITIOCACK
| WAIT_IOCINFOACK
|
1175 TI_CAP_RECVD
| CAP_WANTS_INFO
);
1184 tilog("timodrproc: Got T_ADDR_ACK\n", 0);
1185 tim_send_reply(q
, mp
, tp
, T_ADDR_REQ
);
1189 struct T_conn_ind
*tcip
=
1190 (struct T_conn_ind
*)mp
->b_rptr
;
1192 tilog("timodrproc: Got T_CONN_IND\n", 0);
1194 if (blen
>= sizeof (*tcip
) &&
1195 MBLKIN(mp
, tcip
->SRC_offset
, tcip
->SRC_length
)) {
1196 if (((nbp
= dupmsg(mp
)) != NULL
) ||
1197 ((nbp
= copymsg(mp
)) != NULL
)) {
1198 nbp
->b_next
= tp
->tim_consave
;
1199 tp
->tim_consave
= nbp
;
1202 (t_scalar_t
)sizeof (mblk_t
));
1211 mutex_enter(&tp
->tim_mutex
);
1212 if (tp
->tim_peercred
!= NULL
)
1213 crfree(tp
->tim_peercred
);
1214 tp
->tim_peercred
= msg_getcred(mp
, &tp
->tim_cpid
);
1215 if (tp
->tim_peercred
!= NULL
)
1216 crhold(tp
->tim_peercred
);
1217 mutex_exit(&tp
->tim_mutex
);
1219 tilog("timodrproc: Got T_CONN_CON\n", 0);
1221 tp
->tim_flags
&= ~CONNWAIT
;
1225 case T_DISCON_IND
: {
1226 struct T_discon_ind
*disp
;
1227 struct T_conn_ind
*conp
;
1230 if (q
->q_first
!= 0)
1231 tilog("timodrput: T_DISCON_IND -"
1232 " flow control\n", 0);
1234 if (blen
< sizeof (*disp
)) {
1239 disp
= (struct T_discon_ind
*)mp
->b_rptr
;
1241 tilog("timodrproc: Got T_DISCON_IND Reason: %d\n",
1242 disp
->DISCON_reason
);
1244 tp
->tim_flags
&= ~(CONNWAIT
|LOCORDREL
|REMORDREL
);
1246 for (nbp
= tp
->tim_consave
; nbp
; nbp
= nbp
->b_next
) {
1247 conp
= (struct T_conn_ind
*)nbp
->b_rptr
;
1248 if (conp
->SEQ_number
== disp
->SEQ_number
)
1254 pbp
->b_next
= nbp
->b_next
;
1256 tp
->tim_consave
= nbp
->b_next
;
1266 tilog("timodrproc: Got T_ORDREL_IND\n", 0);
1268 if (tp
->tim_flags
& LOCORDREL
) {
1269 tp
->tim_flags
&= ~(LOCORDREL
|REMORDREL
);
1272 tp
->tim_flags
|= REMORDREL
;
1279 case T_UNITDATA_IND
:
1280 if (pptr
->type
== T_EXDATA_IND
)
1281 tilog("timodrproc: Got T_EXDATA_IND\n", 0);
1283 if (!bcanputnext(q
, mp
->b_band
)) {
1284 (void) putbq(q
, mp
);
1290 case T_CAPABILITY_ACK
: {
1291 struct T_capability_ack
*tca
;
1293 if (blen
< sizeof (*tca
)) {
1298 /* This transport supports T_CAPABILITY_REQ */
1299 tilog("timodrproc: Got T_CAPABILITY_ACK\n", 0);
1301 PI_PROVLOCK(tp
->tim_provinfo
);
1302 if (tp
->tim_provinfo
->tpi_capability
!= PI_YES
)
1303 tp
->tim_provinfo
->tpi_capability
= PI_YES
;
1304 PI_PROVUNLOCK(tp
->tim_provinfo
);
1306 /* Reset possible pending timeout */
1307 if (tp
->tim_tcap_timoutid
!= 0) {
1308 (void) quntimeout(q
, tp
->tim_tcap_timoutid
);
1309 tp
->tim_tcap_timoutid
= 0;
1312 tca
= (struct T_capability_ack
*)mp
->b_rptr
;
1314 if (tca
->CAP_bits1
& TC1_INFO
)
1315 timodprocessinfo(q
, tp
, &tca
->INFO_ack
);
1317 tim_send_reply(q
, mp
, tp
, T_CAPABILITY_REQ
);
1325 tilog("timodrproc: Got M_FLUSH\n", 0);
1327 if (*mp
->b_rptr
& FLUSHR
) {
1328 if (*mp
->b_rptr
& FLUSHBAND
)
1329 flushband(q
, *(mp
->b_rptr
+ 1), FLUSHDATA
);
1331 flushq(q
, FLUSHDATA
);
1337 iocbp
= (struct iocblk
*)mp
->b_rptr
;
1339 tilog("timodrproc: Got M_IOCACK\n", 0);
1341 if (iocbp
->ioc_cmd
== TI_GETMYNAME
) {
1344 * Transport provider supports this ioctl,
1345 * so I don't have to.
1347 if ((tp
->tim_flags
& DO_MYNAME
) != 0) {
1348 tp
->tim_flags
&= ~DO_MYNAME
;
1349 PI_PROVLOCK(tp
->tim_provinfo
);
1350 tp
->tim_provinfo
->tpi_myname
= PI_YES
;
1351 PI_PROVUNLOCK(tp
->tim_provinfo
);
1354 ASSERT(tp
->tim_mymaxlen
>= 0);
1355 if (tp
->tim_mymaxlen
!= 0) {
1356 kmem_free(tp
->tim_myname
,
1357 (size_t)tp
->tim_mymaxlen
);
1358 tp
->tim_myname
= NULL
;
1359 tp
->tim_mymaxlen
= 0;
1361 /* tim_iocsave may already be overwritten. */
1362 if (tp
->tim_saved_prim
== -1) {
1363 freemsg(tp
->tim_iocsave
);
1364 tp
->tim_iocsave
= NULL
;
1366 } else if (iocbp
->ioc_cmd
== TI_GETPEERNAME
) {
1370 * Transport provider supports this ioctl,
1371 * so I don't have to.
1373 if ((tp
->tim_flags
& DO_PEERNAME
) != 0) {
1374 tp
->tim_flags
&= ~DO_PEERNAME
;
1375 PI_PROVLOCK(tp
->tim_provinfo
);
1376 tp
->tim_provinfo
->tpi_peername
= PI_YES
;
1377 PI_PROVUNLOCK(tp
->tim_provinfo
);
1380 mutex_enter(&tp
->tim_mutex
);
1381 ASSERT(tp
->tim_peermaxlen
>= 0);
1382 clearit
= tp
->tim_peermaxlen
!= 0;
1384 kmem_free(tp
->tim_peername
, tp
->tim_peermaxlen
);
1385 tp
->tim_peername
= NULL
;
1386 tp
->tim_peermaxlen
= 0;
1387 tp
->tim_peerlen
= 0;
1389 mutex_exit(&tp
->tim_mutex
);
1393 bp
= tp
->tim_consave
;
1394 while (bp
!= NULL
) {
1400 tp
->tim_consave
= NULL
;
1402 /* tim_iocsave may already be overwritten. */
1403 if (tp
->tim_saved_prim
== -1) {
1404 freemsg(tp
->tim_iocsave
);
1405 tp
->tim_iocsave
= NULL
;
1413 tilog("timodrproc: Got M_IOCNAK\n", 0);
1415 iocbp
= (struct iocblk
*)mp
->b_rptr
;
1416 if (((iocbp
->ioc_cmd
== TI_GETMYNAME
) ||
1417 (iocbp
->ioc_cmd
== TI_GETPEERNAME
)) &&
1418 ((iocbp
->ioc_error
== EINVAL
) || (iocbp
->ioc_error
== 0))) {
1419 PI_PROVLOCK(tp
->tim_provinfo
);
1420 if (iocbp
->ioc_cmd
== TI_GETMYNAME
) {
1421 if (tp
->tim_provinfo
->tpi_myname
== PI_DONTKNOW
)
1422 tp
->tim_provinfo
->tpi_myname
= PI_NO
;
1423 } else if (iocbp
->ioc_cmd
== TI_GETPEERNAME
) {
1424 if (tp
->tim_provinfo
->tpi_peername
==
1426 tp
->tim_provinfo
->tpi_peername
= PI_NO
;
1428 PI_PROVUNLOCK(tp
->tim_provinfo
);
1429 /* tim_iocsave may already be overwritten. */
1430 if ((tp
->tim_iocsave
!= NULL
) &&
1431 (tp
->tim_saved_prim
== -1)) {
1433 mp
= tp
->tim_iocsave
;
1434 tp
->tim_iocsave
= NULL
;
1435 tp
->tim_flags
|= NAMEPROC
;
1436 if (ti_doname(WR(q
), mp
) != DONAME_CONT
) {
1437 tp
->tim_flags
&= ~NAMEPROC
;
1450 * timodwput - Module write put procedure. This is called from
1451 * the module, driver, or stream head upstream/downstream.
1452 * Handles M_FLUSH, M_DATA and some M_PROTO (T_DATA_REQ,
1453 * and T_UNITDATA_REQ) messages. All others are queued to
1454 * be handled by the service procedures.
1458 timodwput(queue_t
*q
, mblk_t
*mp
)
1460 union T_primitives
*pptr
;
1462 struct iocblk
*iocbp
;
1465 * Enqueue normal-priority messages if our queue already
1466 * holds some messages for deferred processing but don't
1467 * enqueue those M_IOCTLs which will result in an
1468 * M_PCPROTO (ie, high priority) message being created.
1470 if (q
->q_first
!= 0 && mp
->b_datap
->db_type
< QPCTL
) {
1471 if (mp
->b_datap
->db_type
== M_IOCTL
) {
1472 iocbp
= (struct iocblk
*)mp
->b_rptr
;
1473 switch (iocbp
->ioc_cmd
) {
1489 * Inline processing of data (to avoid additional procedure call).
1490 * Rest is handled in timodwproc.
1493 switch (mp
->b_datap
->db_type
) {
1495 tp
= (struct tim_tim
*)q
->q_ptr
;
1497 if (tp
->tim_flags
& CLTS
) {
1500 if ((tmp
= tim_filladdr(q
, mp
, B_FALSE
)) == NULL
) {
1507 if (bcanputnext(q
, mp
->b_band
))
1514 pptr
= (union T_primitives
*)mp
->b_rptr
;
1515 switch (pptr
->type
) {
1516 case T_UNITDATA_REQ
:
1517 tp
= (struct tim_tim
*)q
->q_ptr
;
1519 if (tp
->tim_flags
& CLTS
) {
1522 tmp
= tim_filladdr(q
, mp
, B_FALSE
);
1530 if (bcanputnext(q
, mp
->b_band
))
1538 if (bcanputnext(q
, mp
->b_band
))
1544 (void) timodwproc(q
, mp
);
1549 (void) timodwproc(q
, mp
);
1554 * timodwsrv - Module write queue service procedure.
1555 * This is called when messages are placed on an empty queue,
1556 * when high priority messages are placed on the queue, and
1557 * when flow control restrictions subside. This code used to
1558 * be included in a put procedure, but it was moved to a
1559 * service procedure because several points were added where
1560 * memory allocation could fail, and there is no reasonable
1561 * recovery mechanism from the put procedure.
1564 timodwsrv(queue_t
*q
)
1569 if (q
->q_ptr
== NULL
)
1572 while ((mp
= getq(q
)) != NULL
) {
1573 if (timodwproc(q
, mp
)) {
1575 * timodwproc did a putbq - stop processing
1584 * Common routine to process write side messages
1588 timodwproc(queue_t
*q
, mblk_t
*mp
)
1590 union T_primitives
*pptr
;
1593 struct iocblk
*iocbp
;
1596 tp
= (struct tim_tim
*)q
->q_ptr
;
1598 switch (mp
->b_datap
->db_type
) {
1604 if (tp
->tim_flags
& CLTS
) {
1605 if ((tmp
= tim_filladdr(q
, mp
, B_TRUE
)) == NULL
) {
1611 if (!bcanputnext(q
, mp
->b_band
)) {
1612 (void) putbq(q
, mp
);
1620 iocbp
= (struct iocblk
*)mp
->b_rptr
;
1621 TILOG("timodwproc: Got M_IOCTL(%d)\n", iocbp
->ioc_cmd
);
1623 ASSERT(MBLKL(mp
) == sizeof (struct iocblk
));
1626 * TPI requires we await response to a previously sent message
1627 * before handling another, put it back on the head of queue.
1628 * Since putbq() may see QWANTR unset when called from the
1629 * service procedure, the queue must be explicitly scheduled
1630 * for service, as no backenable will occur for this case.
1631 * tim_ioctl_retry() sets a timer to handle the qenable.
1633 if (tp
->tim_flags
& WAITIOCACK
) {
1634 TILOG("timodwproc: putbq M_IOCTL(%d)\n",
1636 (void) putbq(q
, mp
);
1637 /* Called from timodwsrv() and messages on queue */
1638 if (!(q
->q_flag
& QWANTR
))
1643 switch (iocbp
->ioc_cmd
) {
1648 case _I_GETPEERCRED
:
1649 if ((tp
->tim_flags
& COTS
) == 0) {
1650 miocnak(q
, mp
, 0, ENOTSUP
);
1652 mblk_t
*cmp
= mp
->b_cont
;
1653 k_peercred_t
*kp
= NULL
;
1655 mutex_enter(&tp
->tim_mutex
);
1657 iocbp
->ioc_flag
== IOC_NATIVE
&&
1659 (CONNWAIT
|LOCORDREL
|REMORDREL
)) == 0 &&
1660 tp
->tim_peercred
!= NULL
&&
1661 DB_TYPE(cmp
) == M_DATA
&&
1662 MBLKL(cmp
) == sizeof (k_peercred_t
)) {
1663 kp
= (k_peercred_t
*)cmp
->b_rptr
;
1664 crhold(kp
->pc_cr
= tp
->tim_peercred
);
1665 kp
->pc_cpid
= tp
->tim_cpid
;
1667 mutex_exit(&tp
->tim_mutex
);
1669 miocack(q
, mp
, sizeof (*kp
), 0);
1671 miocnak(q
, mp
, 0, ENOTCONN
);
1678 TILOG("timodwproc: TI_{BIND|UNBIND|OPTMGMT|GETADDRS}"
1682 * We know that tim_send_ioctl_tpi_msg() is only
1683 * going to examine the `type' field, so we only
1684 * check that we can access that much data.
1686 error
= miocpullup(mp
, sizeof (t_scalar_t
));
1688 miocnak(q
, mp
, 0, error
);
1691 tim_send_ioctl_tpi_msg(q
, mp
, tp
, iocbp
);
1695 TILOG("timodwproc: TI_GETINFO\n", 0);
1696 error
= miocpullup(mp
, sizeof (struct T_info_req
));
1698 miocnak(q
, mp
, 0, error
);
1701 tp
->tim_flags
|= WAIT_IOCINFOACK
;
1702 tim_send_ioctl_tpi_msg(q
, mp
, tp
, iocbp
);
1707 struct ti_sync_req
*tsr
;
1710 error
= miocpullup(mp
, sizeof (struct ti_sync_req
));
1712 miocnak(q
, mp
, 0, error
);
1716 tsr_mp
= mp
->b_cont
;
1717 tsr
= (struct ti_sync_req
*)tsr_mp
->b_rptr
;
1718 TILOG("timodwproc: TI_SYNC(%x)\n", tsr
->tsr_flags
);
1721 * Save out the value of tsr_flags, in case we
1722 * reallocb() tsr_mp (below).
1724 tsr_flags
= tsr
->tsr_flags
;
1725 if ((tsr_flags
& TSRF_INFO_REQ
) == 0) {
1726 mblk_t
*ack_mp
= reallocb(tsr_mp
,
1727 sizeof (struct ti_sync_ack
), 0);
1729 /* Can reply immediately. */
1731 if (ack_mp
== NULL
) {
1732 tilog("timodwproc: allocb failed no "
1733 "recovery attempt\n", 0);
1735 miocnak(q
, mp
, 0, ENOMEM
);
1737 tim_answer_ti_sync(q
, mp
, tp
,
1744 * This code is retained for compatibility with
1745 * old statically linked applications. New code
1746 * should use TI_CAPABILITY for all TPI
1747 * information and should not use TSRF_INFO_REQ
1750 * defer processsing necessary to rput procedure
1751 * as we need to get information from transport
1752 * driver. Set flags that will tell the read
1753 * side the work needed on this request.
1756 if (tsr_flags
& TSRF_IS_EXP_IN_RCVBUF
)
1757 tp
->tim_flags
|= PEEK_RDQ_EXPIND
;
1760 * Convert message to a T_INFO_REQ message; relies
1761 * on sizeof (struct ti_sync_req) >= sizeof (struct
1764 ASSERT(MBLKL(tsr_mp
) >= sizeof (struct T_info_req
));
1766 ((struct T_info_req
*)tsr_mp
->b_rptr
)->PRIM_type
=
1768 tsr_mp
->b_wptr
= tsr_mp
->b_rptr
+
1769 sizeof (struct T_info_req
);
1770 tp
->tim_flags
|= WAIT_IOCINFOACK
;
1771 tim_send_ioctl_tpi_msg(q
, mp
, tp
, iocbp
);
1775 case TI_CAPABILITY
: {
1777 struct T_capability_req
*tcr
;
1779 error
= miocpullup(mp
, sizeof (*tcr
));
1781 miocnak(q
, mp
, 0, error
);
1785 tcsr_mp
= mp
->b_cont
;
1786 tcr
= (struct T_capability_req
*)tcsr_mp
->b_rptr
;
1787 TILOG("timodwproc: TI_CAPABILITY(CAP_bits1 = %x)\n",
1790 if (tcr
->PRIM_type
!= T_CAPABILITY_REQ
) {
1791 TILOG("timodwproc: invalid msg type %d\n",
1793 miocnak(q
, mp
, 0, EPROTO
);
1797 switch (tp
->tim_provinfo
->tpi_capability
) {
1799 /* Just send T_CAPABILITY_REQ down */
1800 tim_send_ioctl_tpi_msg(q
, mp
, tp
, iocbp
);
1805 * It is unknown yet whether transport provides
1806 * T_CAPABILITY_REQ or not. Send message down
1807 * and wait for reply.
1810 ASSERT(tp
->tim_tcap_timoutid
== 0);
1811 if ((tcr
->CAP_bits1
& TC1_INFO
) == 0) {
1812 tp
->tim_flags
|= TI_CAP_RECVD
;
1814 tp
->tim_flags
|= (TI_CAP_RECVD
|
1818 tp
->tim_tcap_timoutid
= qtimeout(q
,
1819 tim_tcap_timer
, q
, tim_tcap_wait
* hz
);
1820 tim_send_ioctl_tpi_msg(q
, mp
, tp
, iocbp
);
1825 * Transport doesn't support T_CAPABILITY_REQ.
1826 * Either reply immediately or send T_INFO_REQ
1829 if ((tcr
->CAP_bits1
& TC1_INFO
) != 0) {
1830 tp
->tim_flags
|= (TI_CAP_RECVD
|
1831 CAP_WANTS_INFO
| WAIT_IOCINFOACK
);
1832 TILOG("timodwproc: sending down "
1833 "T_INFO_REQ, flags = %x\n",
1837 * Generate T_INFO_REQ message and send
1840 ((struct T_info_req
*)tcsr_mp
->b_rptr
)->
1841 PRIM_type
= T_INFO_REQ
;
1842 tcsr_mp
->b_wptr
= tcsr_mp
->b_rptr
+
1843 sizeof (struct T_info_req
);
1844 tim_send_ioctl_tpi_msg(q
, mp
, tp
,
1851 * Can reply immediately. Just send back
1852 * T_CAPABILITY_ACK with CAP_bits1 set to 0.
1854 mp
->b_cont
= tcsr_mp
= tpi_ack_alloc(mp
->b_cont
,
1855 sizeof (struct T_capability_ack
), M_PCPROTO
,
1858 if (tcsr_mp
== NULL
) {
1859 tilog("timodwproc: allocb failed no "
1860 "recovery attempt\n", 0);
1861 miocnak(q
, mp
, 0, ENOMEM
);
1865 tp
->tim_flags
&= ~(WAITIOCACK
| TI_CAP_RECVD
|
1866 WAIT_IOCINFOACK
| CAP_WANTS_INFO
);
1867 ((struct T_capability_ack
*)
1868 tcsr_mp
->b_rptr
)->CAP_bits1
= 0;
1869 tim_ioctl_send_reply(q
, mp
, tcsr_mp
);
1872 * It could happen when timod is awaiting ack
1873 * for TI_GETPEERNAME/TI_GETMYNAME.
1875 if (tp
->tim_iocsave
!= NULL
) {
1876 freemsg(tp
->tim_iocsave
);
1877 tp
->tim_iocsave
= NULL
;
1878 tp
->tim_saved_prim
= -1;
1884 "timodwproc: unknown tpi_capability value "
1885 "%d\n", tp
->tim_provinfo
->tpi_capability
);
1893 tilog("timodwproc: Got TI_GETMYNAME\n", 0);
1895 if (tp
->tim_provinfo
->tpi_myname
== PI_YES
) {
1901 case TI_GETPEERNAME
:
1903 tilog("timodwproc: Got TI_GETPEERNAME\n", 0);
1905 if (tp
->tim_provinfo
->tpi_peername
== PI_YES
) {
1910 if ((tmp
= copymsg(mp
)) == NULL
) {
1911 tim_recover(q
, mp
, msgsize(mp
));
1915 * tim_iocsave may be non-NULL when timod is awaiting
1916 * ack for another TI_GETPEERNAME/TI_GETMYNAME.
1918 freemsg(tp
->tim_iocsave
);
1919 tp
->tim_iocsave
= mp
;
1920 tp
->tim_saved_prim
= -1;
1928 if (tp
->tim_flags
& NAMEPROC
) {
1929 if (ti_doname(q
, mp
) != DONAME_CONT
) {
1930 tp
->tim_flags
&= ~NAMEPROC
;
1938 if (MBLKL(mp
) < sizeof (t_scalar_t
)) {
1939 merror(q
, mp
, EPROTO
);
1943 pptr
= (union T_primitives
*)mp
->b_rptr
;
1944 switch (pptr
->type
) {
1951 if (pptr
->type
== T_EXDATA_REQ
)
1952 tilog("timodwproc: Got T_EXDATA_REQ\n", 0);
1954 if (!bcanputnext(q
, mp
->b_band
)) {
1955 (void) putbq(q
, mp
);
1961 case T_UNITDATA_REQ
:
1962 if (tp
->tim_flags
& CLTS
) {
1963 tmp
= tim_filladdr(q
, mp
, B_TRUE
);
1970 if (!bcanputnext(q
, mp
->b_band
)) {
1971 (void) putbq(q
, mp
);
1978 struct T_conn_req
*reqp
= (struct T_conn_req
*)
1982 tilog("timodwproc: Got T_CONN_REQ\n", 0);
1984 if (MBLKL(mp
) < sizeof (struct T_conn_req
)) {
1985 merror(q
, mp
, EPROTO
);
1989 if (tp
->tim_flags
& DO_PEERNAME
) {
1990 if (!MBLKIN(mp
, reqp
->DEST_offset
,
1991 reqp
->DEST_length
)) {
1992 merror(q
, mp
, EPROTO
);
1995 ASSERT(reqp
->DEST_length
>= 0);
1996 mutex_enter(&tp
->tim_mutex
);
1997 if (reqp
->DEST_length
> tp
->tim_peermaxlen
) {
1998 p
= kmem_alloc(reqp
->DEST_length
,
2001 mutex_exit(&tp
->tim_mutex
);
2002 tilog("timodwproc: kmem_alloc "
2003 "failed, attempting "
2009 if (tp
->tim_peermaxlen
)
2010 kmem_free(tp
->tim_peername
,
2011 tp
->tim_peermaxlen
);
2012 tp
->tim_peername
= p
;
2013 tp
->tim_peermaxlen
= reqp
->DEST_length
;
2015 tp
->tim_peerlen
= reqp
->DEST_length
;
2016 p
= mp
->b_rptr
+ reqp
->DEST_offset
;
2017 bcopy(p
, tp
->tim_peername
, tp
->tim_peerlen
);
2018 mutex_exit(&tp
->tim_mutex
);
2020 if (tp
->tim_flags
& COTS
)
2021 tp
->tim_flags
|= CONNWAIT
;
2028 struct T_conn_res
*resp
;
2029 struct T_conn_ind
*indp
;
2033 if (MBLKL(mp
) < sizeof (struct T_conn_res
) ||
2034 (tp
->tim_flags
& WAITIOCACK
)) {
2035 merror(q
, mp
, EPROTO
);
2039 resp
= (struct T_conn_res
*)mp
->b_rptr
;
2040 for (tmp
= tp
->tim_consave
; tmp
!= NULL
;
2041 tmp
= tmp
->b_next
) {
2042 indp
= (struct T_conn_ind
*)tmp
->b_rptr
;
2043 if (indp
->SEQ_number
== resp
->SEQ_number
)
2050 if ((nbp
= dupb(mp
)) == NULL
&&
2051 (nbp
= copyb(mp
)) == NULL
) {
2052 tim_recover(q
, mp
, msgsize(mp
));
2057 pmp
->b_next
= tmp
->b_next
;
2059 tp
->tim_consave
= tmp
->b_next
;
2063 * Construct a list with:
2064 * nbp - copy of user's original request
2065 * tmp - the extracted T_conn_ind
2069 * tim_iocsave may be non-NULL when timod is awaiting
2070 * ack for TI_GETPEERNAME/TI_GETMYNAME.
2072 freemsg(tp
->tim_iocsave
);
2073 tp
->tim_iocsave
= nbp
;
2074 tp
->tim_saved_prim
= pptr
->type
;
2075 tp
->tim_flags
|= WAIT_CONNRESACK
| WAITIOCACK
;
2082 case T_DISCON_REQ
: {
2083 struct T_discon_req
*disp
;
2084 struct T_conn_ind
*conp
;
2087 if (MBLKL(mp
) < sizeof (struct T_discon_req
)) {
2088 merror(q
, mp
, EPROTO
);
2092 disp
= (struct T_discon_req
*)mp
->b_rptr
;
2093 tp
->tim_flags
&= ~(CONNWAIT
|LOCORDREL
|REMORDREL
);
2097 * If we are already connected, there won't
2098 * be any messages on tim_consave.
2100 for (tmp
= tp
->tim_consave
; tmp
; tmp
= tmp
->b_next
) {
2101 conp
= (struct T_conn_ind
*)tmp
->b_rptr
;
2102 if (conp
->SEQ_number
== disp
->SEQ_number
)
2108 pmp
->b_next
= tmp
->b_next
;
2110 tp
->tim_consave
= tmp
->b_next
;
2119 if (tp
->tim_flags
& REMORDREL
) {
2120 tp
->tim_flags
&= ~(LOCORDREL
|REMORDREL
);
2123 tp
->tim_flags
|= LOCORDREL
;
2128 case T_CAPABILITY_REQ
:
2129 tilog("timodwproc: Got T_CAPABILITY_REQ\n", 0);
2131 * XXX: We may know at this point whether transport
2132 * provides T_CAPABILITY_REQ or not and we may utilise
2133 * this knowledge here.
2141 tilog("timodwproc: Got M_FLUSH\n", 0);
2143 if (*mp
->b_rptr
& FLUSHW
) {
2144 if (*mp
->b_rptr
& FLUSHBAND
)
2145 flushband(q
, *(mp
->b_rptr
+ 1), FLUSHDATA
);
2147 flushq(q
, FLUSHDATA
);
2157 tilog(char *str
, t_scalar_t arg
)
2161 cmn_err(CE_CONT
, str
, arg
);
2163 (void) strlog(TIMOD_ID
, -1, 0, SL_TRACE
| SL_ERROR
,
2166 (void) strlog(TIMOD_ID
, -1, 0, SL_TRACE
, str
, arg
);
2171 tilogp(char *str
, uintptr_t arg
)
2175 cmn_err(CE_CONT
, str
, arg
);
2177 (void) strlog(TIMOD_ID
, -1, 0, SL_TRACE
| SL_ERROR
,
2180 (void) strlog(TIMOD_ID
, -1, 0, SL_TRACE
, str
, arg
);
2186 * Process the TI_GETNAME ioctl. If no name exists, return len = 0
2187 * in strbuf structures. The state transitions are determined by what
2188 * is hung of cq_private (cp_private) in the copyresp (copyreq) structure.
2189 * The high-level steps in the ioctl processing are as follows:
2191 * 1) we recieve an transparent M_IOCTL with the arg in the second message
2192 * block of the message.
2193 * 2) we send up an M_COPYIN request for the strbuf structure pointed to
2194 * by arg. The block containing arg is hung off cq_private.
2195 * 3) we receive an M_IOCDATA response with cp->cp_private->b_cont == NULL.
2196 * This means that the strbuf structure is found in the message block
2198 * 4) we send up an M_COPYOUT request with the strbuf message hung off
2199 * cq_private->b_cont. The address we are copying to is strbuf.buf.
2200 * we set strbuf.len to 0 to indicate that we should copy the strbuf
2201 * structure the next time. The message mp->b_cont contains the
2203 * 5) we receive an M_IOCDATA with cp_private->b_cont != NULL and
2204 * strbuf.len == 0. Restore strbuf.len to either tp->tim_mylen or
2206 * 6) we send up an M_COPYOUT request with a copy of the strbuf message
2207 * hung off mp->b_cont. In the strbuf structure in the message hung
2208 * off cq_private->b_cont, we set strbuf.len to 0 and strbuf.maxlen
2209 * to 0. This means that the next step is to ACK the ioctl.
2210 * 7) we receive an M_IOCDATA message with cp_private->b_cont != NULL and
2211 * strbuf.len == 0 and strbuf.maxlen == 0. Free up cp->private and
2212 * send an M_IOCACK upstream, and we are done.
2217 queue_t
*q
, /* queue message arrived at */
2218 mblk_t
*mp
) /* M_IOCTL or M_IOCDATA message only */
2220 struct iocblk
*iocp
;
2221 struct copyreq
*cqp
;
2222 STRUCT_HANDLE(strbuf
, sb
);
2223 struct copyresp
*csp
;
2226 struct tim_tim
*tp
= q
->q_ptr
;
2229 switch (mp
->b_datap
->db_type
) {
2231 iocp
= (struct iocblk
*)mp
->b_rptr
;
2232 if ((iocp
->ioc_cmd
!= TI_GETMYNAME
) &&
2233 (iocp
->ioc_cmd
!= TI_GETPEERNAME
)) {
2234 tilog("ti_doname: bad M_IOCTL command\n", 0);
2235 miocnak(q
, mp
, 0, EINVAL
);
2239 if ((iocp
->ioc_count
!= TRANSPARENT
)) {
2240 miocnak(q
, mp
, 0, EINVAL
);
2245 cqp
= (struct copyreq
*)mp
->b_rptr
;
2246 cqp
->cq_private
= mp
->b_cont
;
2247 cqp
->cq_addr
= (caddr_t
)*(intptr_t *)mp
->b_cont
->b_rptr
;
2249 cqp
->cq_size
= SIZEOF_STRUCT(strbuf
, iocp
->ioc_flag
);
2251 mp
->b_datap
->db_type
= M_COPYIN
;
2252 mp
->b_wptr
= mp
->b_rptr
+ sizeof (struct copyreq
);
2258 csp
= (struct copyresp
*)mp
->b_rptr
;
2259 iocp
= (struct iocblk
*)mp
->b_rptr
;
2260 cqp
= (struct copyreq
*)mp
->b_rptr
;
2261 if ((csp
->cp_cmd
!= TI_GETMYNAME
) &&
2262 (csp
->cp_cmd
!= TI_GETPEERNAME
)) {
2263 cmn_err(CE_WARN
, "ti_doname: bad M_IOCDATA command\n");
2264 miocnak(q
, mp
, 0, EINVAL
);
2268 if (csp
->cp_rval
) { /* error */
2269 freemsg(csp
->cp_private
);
2274 ASSERT(csp
->cp_private
!= NULL
);
2275 getpeer
= csp
->cp_cmd
== TI_GETPEERNAME
;
2277 mutex_enter(&tp
->tim_mutex
);
2278 if (csp
->cp_private
->b_cont
== NULL
) { /* got strbuf */
2280 STRUCT_SET_HANDLE(sb
, iocp
->ioc_flag
,
2281 (void *)mp
->b_cont
->b_rptr
);
2283 if (tp
->tim_peerlen
== 0) {
2284 /* copy just strbuf */
2285 STRUCT_FSET(sb
, len
, 0);
2286 } else if (tp
->tim_peerlen
>
2287 STRUCT_FGET(sb
, maxlen
)) {
2288 mutex_exit(&tp
->tim_mutex
);
2289 miocnak(q
, mp
, 0, ENAMETOOLONG
);
2294 STRUCT_FSET(sb
, len
, tp
->tim_peerlen
);
2297 if (tp
->tim_mylen
== 0) {
2298 /* copy just strbuf */
2299 STRUCT_FSET(sb
, len
, 0);
2300 } else if (tp
->tim_mylen
>
2301 STRUCT_FGET(sb
, maxlen
)) {
2302 freemsg(csp
->cp_private
);
2303 miocnak(q
, mp
, 0, ENAMETOOLONG
);
2308 STRUCT_FSET(sb
, len
, tp
->tim_mylen
);
2311 csp
->cp_private
->b_cont
= mp
->b_cont
;
2314 STRUCT_SET_HANDLE(sb
, iocp
->ioc_flag
,
2315 (void *)csp
->cp_private
->b_cont
->b_rptr
);
2316 if (STRUCT_FGET(sb
, len
) == 0) {
2318 * restore strbuf.len
2321 STRUCT_FSET(sb
, len
, tp
->tim_peerlen
);
2323 STRUCT_FSET(sb
, len
, tp
->tim_mylen
);
2326 mutex_exit(&tp
->tim_mutex
);
2327 if (STRUCT_FGET(sb
, maxlen
) == 0) {
2332 freemsg(csp
->cp_private
);
2333 tim_ioctl_send_reply(q
, mp
, NULL
);
2338 if ((bp
= allocb(STRUCT_SIZE(sb
), BPRI_MED
)) == NULL
) {
2341 "ti_doname: allocb failed no recovery attempt\n", 0);
2343 freemsg(csp
->cp_private
);
2344 miocnak(q
, mp
, 0, EAGAIN
);
2348 bp
->b_wptr
+= STRUCT_SIZE(sb
);
2349 bcopy(STRUCT_BUF(sb
), bp
->b_rptr
, STRUCT_SIZE(sb
));
2351 (caddr_t
)*(intptr_t *)csp
->cp_private
->b_rptr
;
2352 cqp
->cq_size
= STRUCT_SIZE(sb
);
2354 mp
->b_datap
->db_type
= M_COPYOUT
;
2356 STRUCT_FSET(sb
, len
, 0);
2357 STRUCT_FSET(sb
, maxlen
, 0); /* ack next time around */
2364 * copy the address to the user
2366 if ((bp
= allocb((size_t)STRUCT_FGET(sb
, len
), BPRI_MED
))
2369 mutex_exit(&tp
->tim_mutex
);
2371 tilog("ti_doname: allocb failed no recovery attempt\n",
2374 freemsg(csp
->cp_private
);
2375 miocnak(q
, mp
, 0, EAGAIN
);
2379 bp
->b_wptr
+= STRUCT_FGET(sb
, len
);
2381 bcopy(tp
->tim_peername
, bp
->b_rptr
,
2382 STRUCT_FGET(sb
, len
));
2383 mutex_exit(&tp
->tim_mutex
);
2385 bcopy(tp
->tim_myname
, bp
->b_rptr
, STRUCT_FGET(sb
, len
));
2387 cqp
->cq_addr
= (caddr_t
)STRUCT_FGETP(sb
, buf
);
2388 cqp
->cq_size
= STRUCT_FGET(sb
, len
);
2390 mp
->b_datap
->db_type
= M_COPYOUT
;
2392 STRUCT_FSET(sb
, len
, 0); /* copy the strbuf next time around */
2398 tilog("ti_doname: freeing bad message type = %d\n",
2399 mp
->b_datap
->db_type
);
2409 * Fill in the address of a connectionless data packet if a connect
2410 * had been done on this endpoint.
2413 tim_filladdr(queue_t
*q
, mblk_t
*mp
, boolean_t dorecover
)
2417 struct T_unitdata_req
*up
;
2418 struct T_unitdata_req
*nup
;
2421 tp
= (struct tim_tim
*)q
->q_ptr
;
2422 if (mp
->b_datap
->db_type
== M_DATA
) {
2423 mutex_enter(&tp
->tim_mutex
);
2424 bp
= allocb(sizeof (struct T_unitdata_req
) + tp
->tim_peerlen
,
2427 bp
->b_datap
->db_type
= M_PROTO
;
2428 up
= (struct T_unitdata_req
*)bp
->b_rptr
;
2429 up
->PRIM_type
= T_UNITDATA_REQ
;
2430 up
->DEST_length
= tp
->tim_peerlen
;
2431 bp
->b_wptr
+= sizeof (struct T_unitdata_req
);
2432 up
->DEST_offset
= sizeof (struct T_unitdata_req
);
2435 if (tp
->tim_peerlen
> 0) {
2436 bcopy(tp
->tim_peername
, bp
->b_wptr
,
2438 bp
->b_wptr
+= tp
->tim_peerlen
;
2443 ASSERT(mp
->b_datap
->db_type
== M_PROTO
);
2444 up
= (struct T_unitdata_req
*)mp
->b_rptr
;
2445 ASSERT(up
->PRIM_type
== T_UNITDATA_REQ
);
2446 if (up
->DEST_length
!= 0)
2448 mutex_enter(&tp
->tim_mutex
);
2449 bp
= allocb(sizeof (struct T_unitdata_req
) + up
->OPT_length
+
2450 tp
->tim_peerlen
, BPRI_MED
);
2452 bp
->b_datap
->db_type
= M_PROTO
;
2453 nup
= (struct T_unitdata_req
*)bp
->b_rptr
;
2454 nup
->PRIM_type
= T_UNITDATA_REQ
;
2455 nup
->DEST_length
= plen
= tp
->tim_peerlen
;
2456 bp
->b_wptr
+= sizeof (struct T_unitdata_req
);
2457 nup
->DEST_offset
= sizeof (struct T_unitdata_req
);
2459 bcopy(tp
->tim_peername
, bp
->b_wptr
, plen
);
2462 mutex_exit(&tp
->tim_mutex
);
2463 if (up
->OPT_length
== 0) {
2464 nup
->OPT_length
= 0;
2465 nup
->OPT_offset
= 0;
2467 nup
->OPT_length
= up
->OPT_length
;
2469 sizeof (struct T_unitdata_req
) + plen
;
2470 bcopy((mp
->b_wptr
+ up
->OPT_offset
), bp
->b_wptr
,
2472 bp
->b_wptr
+= up
->OPT_length
;
2474 bp
->b_cont
= mp
->b_cont
;
2480 ASSERT(MUTEX_HELD(&tp
->tim_mutex
));
2481 if (bp
== NULL
&& dorecover
) {
2483 sizeof (struct T_unitdata_req
) + tp
->tim_peerlen
);
2485 mutex_exit(&tp
->tim_mutex
);
2490 tim_addlink(struct tim_tim
*tp
)
2492 struct tim_tim
**tpp
;
2493 struct tim_tim
*next
;
2495 tpp
= &tim_hash
[TIM_HASH(tp
->tim_acceptor
)];
2496 rw_enter(&tim_list_rwlock
, RW_WRITER
);
2498 if ((next
= *tpp
) != NULL
)
2499 next
->tim_ptpn
= &tp
->tim_next
;
2500 tp
->tim_next
= next
;
2506 rw_exit(&tim_list_rwlock
);
2510 tim_dellink(struct tim_tim
*tp
)
2512 struct tim_tim
*next
;
2514 rw_enter(&tim_list_rwlock
, RW_WRITER
);
2516 if ((next
= tp
->tim_next
) != NULL
)
2517 next
->tim_ptpn
= tp
->tim_ptpn
;
2518 *(tp
->tim_ptpn
) = next
;
2522 rw_exit(&tim_list_rwlock
);
2525 static struct tim_tim
*
2526 tim_findlink(t_uscalar_t id
)
2530 ASSERT(rw_lock_held(&tim_list_rwlock
));
2532 for (tp
= tim_hash
[TIM_HASH(id
)]; tp
!= NULL
; tp
= tp
->tim_next
) {
2533 if (tp
->tim_acceptor
== id
) {
2541 tim_recover(queue_t
*q
, mblk_t
*mp
, t_scalar_t size
)
2547 tp
= (struct tim_tim
*)q
->q_ptr
;
2550 * Avoid re-enabling the queue.
2552 if (mp
->b_datap
->db_type
== M_PCPROTO
)
2553 mp
->b_datap
->db_type
= M_PROTO
;
2555 (void) putbq(q
, mp
);
2558 * Make sure there is at most one outstanding request per queue.
2560 if (q
->q_flag
& QREADR
) {
2561 if (tp
->tim_rtimoutid
|| tp
->tim_rbufcid
)
2564 if (tp
->tim_wtimoutid
|| tp
->tim_wbufcid
)
2567 if (!(bid
= qbufcall(RD(q
), (size_t)size
, BPRI_MED
, tim_buffer
, q
))) {
2568 tid
= qtimeout(RD(q
), tim_timer
, q
, TIMWAIT
);
2569 if (q
->q_flag
& QREADR
)
2570 tp
->tim_rtimoutid
= tid
;
2572 tp
->tim_wtimoutid
= tid
;
2574 if (q
->q_flag
& QREADR
)
2575 tp
->tim_rbufcid
= bid
;
2577 tp
->tim_wbufcid
= bid
;
2582 * Timod is waiting on a downstream ioctl reply, come back soon
2583 * to reschedule the write side service routine, which will check
2584 * if the ioctl is done and another can proceed.
2587 tim_ioctl_retry(queue_t
*q
)
2591 tp
= (struct tim_tim
*)q
->q_ptr
;
2594 * Make sure there is at most one outstanding request per wqueue.
2596 if (tp
->tim_wtimoutid
|| tp
->tim_wbufcid
)
2599 tp
->tim_wtimoutid
= qtimeout(RD(q
), tim_timer
, q
, TIMIOCWAIT
);
2603 * Inspect the data on read queues starting from read queues passed as
2604 * paramter (timod read queue) and traverse until
2605 * q_next is NULL (stream head). Look for a TPI T_EXDATA_IND message
2606 * reutrn 1 if found, 0 if not found.
2609 ti_expind_on_rdqueues(queue_t
*rq
)
2616 * We are going to walk q_next, so protect stream from plumbing
2622 * Hold QLOCK while referencing data on queues
2624 mutex_enter(QLOCK(rq
));
2626 while (bp
!= NULL
) {
2628 * Walk the messages on the queue looking
2629 * for a possible T_EXDATA_IND
2631 if ((bp
->b_datap
->db_type
== M_PROTO
) &&
2632 ((bp
->b_wptr
- bp
->b_rptr
) >=
2633 sizeof (struct T_exdata_ind
)) &&
2634 (((struct T_exdata_ind
*)bp
->b_rptr
)->PRIM_type
2636 /* bp is T_EXDATA_IND */
2637 mutex_exit(QLOCK(rq
));
2638 releasestr(q
); /* decrement sd_refcnt */
2639 return (1); /* expdata is on a read queue */
2641 bp
= bp
->b_next
; /* next message */
2643 mutex_exit(QLOCK(rq
));
2644 rq
= rq
->q_next
; /* next upstream queue */
2645 } while (rq
!= NULL
);
2647 return (0); /* no expdata on read queues */
2651 tim_tcap_timer(void *q_ptr
)
2653 queue_t
*q
= (queue_t
*)q_ptr
;
2654 struct tim_tim
*tp
= (struct tim_tim
*)q
->q_ptr
;
2656 ASSERT(tp
!= NULL
&& tp
->tim_tcap_timoutid
!= 0);
2657 ASSERT((tp
->tim_flags
& TI_CAP_RECVD
) != 0);
2659 tp
->tim_tcap_timoutid
= 0;
2660 TILOG("tim_tcap_timer: fired\n", 0);
2661 tim_tcap_genreply(q
, tp
);
2665 * tim_tcap_genreply() is called either from timeout routine or when
2666 * T_ERROR_ACK is received. In both cases it means that underlying
2667 * transport doesn't provide T_CAPABILITY_REQ.
2670 tim_tcap_genreply(queue_t
*q
, struct tim_tim
*tp
)
2672 mblk_t
*mp
= tp
->tim_iocsave
;
2673 struct iocblk
*iocbp
;
2675 TILOG("timodrproc: tim_tcap_genreply\n", 0);
2677 ASSERT(tp
== (struct tim_tim
*)q
->q_ptr
);
2680 iocbp
= (struct iocblk
*)mp
->b_rptr
;
2681 ASSERT(iocbp
!= NULL
);
2682 ASSERT(MBLKL(mp
) == sizeof (struct iocblk
));
2683 ASSERT(iocbp
->ioc_cmd
== TI_CAPABILITY
);
2684 ASSERT(mp
->b_cont
== NULL
);
2686 /* Save this information permanently in the module */
2687 PI_PROVLOCK(tp
->tim_provinfo
);
2688 if (tp
->tim_provinfo
->tpi_capability
== PI_DONTKNOW
)
2689 tp
->tim_provinfo
->tpi_capability
= PI_NO
;
2690 PI_PROVUNLOCK(tp
->tim_provinfo
);
2692 if (tp
->tim_tcap_timoutid
!= 0) {
2693 (void) quntimeout(q
, tp
->tim_tcap_timoutid
);
2694 tp
->tim_tcap_timoutid
= 0;
2697 if ((tp
->tim_flags
& CAP_WANTS_INFO
) != 0) {
2698 /* Send T_INFO_REQ down */
2699 mblk_t
*tirmp
= tpi_ack_alloc(NULL
,
2700 sizeof (struct T_info_req
), M_PCPROTO
, T_INFO_REQ
);
2702 if (tirmp
!= NULL
) {
2703 /* Emulate TC1_INFO */
2704 TILOG("emulate_tcap_ioc_req: sending T_INFO_REQ\n", 0);
2705 tp
->tim_flags
|= WAIT_IOCINFOACK
;
2706 putnext(WR(q
), tirmp
);
2708 tilog("emulate_tcap_req: allocb fail, "
2709 "no recovery attmpt\n", 0);
2710 tp
->tim_iocsave
= NULL
;
2711 tp
->tim_saved_prim
= -1;
2712 tp
->tim_flags
&= ~(TI_CAP_RECVD
| WAITIOCACK
|
2713 CAP_WANTS_INFO
| WAIT_IOCINFOACK
);
2714 miocnak(q
, mp
, 0, ENOMEM
);
2717 /* Reply immediately */
2718 mblk_t
*ackmp
= tpi_ack_alloc(NULL
,
2719 sizeof (struct T_capability_ack
), M_PCPROTO
,
2724 if (ackmp
!= NULL
) {
2725 ((struct T_capability_ack
*)
2726 ackmp
->b_rptr
)->CAP_bits1
= 0;
2727 tim_ioctl_send_reply(q
, mp
, ackmp
);
2728 tp
->tim_iocsave
= NULL
;
2729 tp
->tim_saved_prim
= -1;
2730 tp
->tim_flags
&= ~(WAITIOCACK
| WAIT_IOCINFOACK
|
2731 TI_CAP_RECVD
| CAP_WANTS_INFO
);
2733 tilog("timodwproc:allocb failed no "
2734 "recovery attempt\n", 0);
2735 tp
->tim_iocsave
= NULL
;
2736 tp
->tim_saved_prim
= -1;
2737 tp
->tim_flags
&= ~(TI_CAP_RECVD
| WAITIOCACK
|
2738 CAP_WANTS_INFO
| WAIT_IOCINFOACK
);
2739 miocnak(q
, mp
, 0, ENOMEM
);
2746 tim_ioctl_send_reply(queue_t
*q
, mblk_t
*ioc_mp
, mblk_t
*mp
)
2748 struct iocblk
*iocbp
;
2750 ASSERT(q
!= NULL
&& ioc_mp
!= NULL
);
2752 ioc_mp
->b_datap
->db_type
= M_IOCACK
;
2754 mp
->b_datap
->db_type
= M_DATA
;
2756 if (ioc_mp
->b_cont
!= mp
) {
2757 /* It is safe to call freemsg for NULL pointers */
2758 freemsg(ioc_mp
->b_cont
);
2759 ioc_mp
->b_cont
= mp
;
2761 iocbp
= (struct iocblk
*)ioc_mp
->b_rptr
;
2762 iocbp
->ioc_error
= 0;
2763 iocbp
->ioc_rval
= 0;
2765 * All ioctl's may return more data than was specified by
2766 * count arg. For TI_CAPABILITY count is treated as maximum data size.
2769 iocbp
->ioc_count
= 0;
2770 else if (iocbp
->ioc_cmd
!= TI_CAPABILITY
)
2771 iocbp
->ioc_count
= msgsize(mp
);
2773 iocbp
->ioc_count
= MIN(MBLKL(mp
), iocbp
->ioc_count
);
2774 /* Truncate message if too large */
2775 mp
->b_wptr
= mp
->b_rptr
+ iocbp
->ioc_count
;
2778 TILOG("iosendreply: ioc_cmd = %d, ", iocbp
->ioc_cmd
);
2779 putnext(RD(q
), ioc_mp
);
2783 * Send M_IOCACK for errors.
2786 tim_send_ioc_error_ack(queue_t
*q
, struct tim_tim
*tp
, mblk_t
*mp
)
2788 struct T_error_ack
*tea
= (struct T_error_ack
*)mp
->b_rptr
;
2789 t_scalar_t error_prim
;
2791 mp
->b_wptr
= mp
->b_rptr
+ sizeof (struct T_error_ack
);
2792 ASSERT(mp
->b_wptr
<= mp
->b_datap
->db_lim
);
2793 error_prim
= tea
->ERROR_prim
;
2795 ASSERT(tp
->tim_iocsave
!= NULL
);
2796 ASSERT(tp
->tim_iocsave
->b_cont
!= mp
);
2798 /* Always send this to the read side of the queue */
2801 TILOG("tim_send_ioc_error_ack: prim = %d\n", tp
->tim_saved_prim
);
2803 if (tp
->tim_saved_prim
!= error_prim
) {
2805 } else if (error_prim
== T_CAPABILITY_REQ
) {
2806 TILOG("timodrproc: T_ERROR_ACK/T_CAPABILITY_REQ\n", 0);
2807 ASSERT(tp
->tim_iocsave
->b_cont
== NULL
);
2809 tim_tcap_genreply(q
, tp
);
2812 struct iocblk
*iocbp
= (struct iocblk
*)tp
->tim_iocsave
->b_rptr
;
2814 TILOG("tim_send_ioc_error_ack: T_ERROR_ACK: prim %d\n",
2816 ASSERT(tp
->tim_iocsave
->b_cont
== NULL
);
2818 switch (error_prim
) {
2820 TILOG("timodrproc: Unknown T_ERROR_ACK: tlierror %d\n",
2827 case T_SVR4_OPTMGMT_REQ
:
2833 case T_CAPABILITY_REQ
:
2835 TILOG("ioc_err_ack: T_ERROR_ACK: tlierror %x\n",
2838 /* get saved ioctl msg and set values */
2839 iocbp
->ioc_count
= 0;
2840 iocbp
->ioc_error
= 0;
2841 iocbp
->ioc_rval
= tea
->TLI_error
;
2842 if (iocbp
->ioc_rval
== TSYSERR
)
2843 iocbp
->ioc_rval
|= tea
->UNIX_error
<< 8;
2844 tp
->tim_iocsave
->b_datap
->db_type
= M_IOCACK
;
2846 putnext(q
, tp
->tim_iocsave
);
2847 tp
->tim_iocsave
= NULL
;
2848 tp
->tim_saved_prim
= -1;
2849 tp
->tim_flags
&= ~(WAITIOCACK
| TI_CAP_RECVD
|
2850 CAP_WANTS_INFO
| WAIT_IOCINFOACK
);
2857 * Send reply to a usual message or ioctl message upstream.
2858 * Should be called from the read side only.
2861 tim_send_reply(queue_t
*q
, mblk_t
*mp
, struct tim_tim
*tp
, t_scalar_t prim
)
2863 ASSERT(mp
!= NULL
&& q
!= NULL
&& tp
!= NULL
);
2866 /* Restore db_type - recover() might have changed it */
2867 mp
->b_datap
->db_type
= M_PCPROTO
;
2869 if (((tp
->tim_flags
& WAITIOCACK
) == 0) || (tp
->tim_saved_prim
!= prim
))
2872 ASSERT(tp
->tim_iocsave
!= NULL
);
2873 tim_ioctl_send_reply(q
, tp
->tim_iocsave
, mp
);
2874 tp
->tim_iocsave
= NULL
;
2875 tp
->tim_saved_prim
= -1;
2876 tp
->tim_flags
&= ~(WAITIOCACK
| WAIT_IOCINFOACK
|
2877 TI_CAP_RECVD
| CAP_WANTS_INFO
);
2882 * Reply to TI_SYNC reequest without sending anything downstream.
2885 tim_answer_ti_sync(queue_t
*q
, mblk_t
*mp
, struct tim_tim
*tp
,
2886 mblk_t
*ackmp
, uint32_t tsr_flags
)
2888 struct ti_sync_ack
*tsap
;
2890 ASSERT(q
!= NULL
&& q
== WR(q
) && ackmp
!= NULL
);
2892 tsap
= (struct ti_sync_ack
*)ackmp
->b_rptr
;
2893 bzero(tsap
, sizeof (struct ti_sync_ack
));
2894 ackmp
->b_wptr
= ackmp
->b_rptr
+ sizeof (struct ti_sync_ack
);
2896 if (tsr_flags
== 0 ||
2897 (tsr_flags
& ~(TSRF_QLEN_REQ
| TSRF_IS_EXP_IN_RCVBUF
)) != 0) {
2899 * unsupported/bad flag setting
2902 TILOG("timodwproc: unsupported/bad flag setting %x\n",
2905 miocnak(q
, mp
, 0, EINVAL
);
2909 if ((tsr_flags
& TSRF_QLEN_REQ
) != 0)
2910 tsap
->tsa_qlen
= tp
->tim_backlog
;
2912 if ((tsr_flags
& TSRF_IS_EXP_IN_RCVBUF
) != 0 &&
2913 ti_expind_on_rdqueues(RD(q
))) {
2915 * Expedited data is queued on
2916 * the stream read side
2918 tsap
->tsa_flags
|= TSAF_EXP_QUEUED
;
2921 tim_ioctl_send_reply(q
, mp
, ackmp
);
2922 tp
->tim_iocsave
= NULL
;
2923 tp
->tim_saved_prim
= -1;
2924 tp
->tim_flags
&= ~(WAITIOCACK
| WAIT_IOCINFOACK
|
2925 TI_CAP_RECVD
| CAP_WANTS_INFO
);
2929 * Send TPI message from IOCTL message, ssave original ioctl header and TPI
2930 * message type. Should be called from write side only.
2933 tim_send_ioctl_tpi_msg(queue_t
*q
, mblk_t
*mp
, struct tim_tim
*tp
,
2934 struct iocblk
*iocb
)
2937 int ioc_cmd
= iocb
->ioc_cmd
;
2939 ASSERT(q
!= NULL
&& mp
!= NULL
&& tp
!= NULL
);
2941 ASSERT(mp
->b_cont
!= NULL
);
2943 tp
->tim_iocsave
= mp
;
2947 tp
->tim_flags
|= WAITIOCACK
;
2948 tp
->tim_saved_prim
= ((union T_primitives
*)tmp
->b_rptr
)->type
;
2951 * For TI_GETINFO, the attached message is a T_INFO_REQ
2952 * For TI_SYNC, we generate the T_INFO_REQ message above
2953 * For TI_CAPABILITY the attached message is either
2954 * T_CAPABILITY_REQ or T_INFO_REQ.
2955 * Among TPI request messages possible,
2956 * T_INFO_REQ/T_CAPABILITY_ACK messages are a M_PCPROTO, rest
2959 if (ioc_cmd
== TI_GETINFO
|| ioc_cmd
== TI_SYNC
||
2960 ioc_cmd
== TI_CAPABILITY
) {
2961 tmp
->b_datap
->db_type
= M_PCPROTO
;
2963 tmp
->b_datap
->db_type
= M_PROTO
;
2966 /* Verify credentials in STREAM */
2967 ASSERT(iocb
->ioc_cr
== NULL
|| iocb
->ioc_cr
== DB_CRED(tmp
));
2969 ASSERT(DB_CRED(tmp
) != NULL
);
2971 TILOG("timodwproc: sending down %d\n", tp
->tim_saved_prim
);
2976 tim_clear_peer(struct tim_tim
*tp
)
2978 mutex_enter(&tp
->tim_mutex
);
2979 if (tp
->tim_peercred
!= NULL
) {
2980 crfree(tp
->tim_peercred
);
2981 tp
->tim_peercred
= NULL
;
2983 tp
->tim_peerlen
= 0;
2984 mutex_exit(&tp
->tim_mutex
);