1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /* ONC_PLUS EXTRACT START */
22 /*
23 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
27 /* All Rights Reserved */
28
29
30 /*
31 * Transport Interface Library cooperating module - issue 2
32 */
33
34 /* ONC_PLUS EXTRACT END */
35 #include <sys/param.h>
36 #include <sys/types.h>
37 #include <sys/stream.h>
38 #include <sys/stropts.h>
39 #include <sys/strsubr.h>
40 #define _SUN_TPI_VERSION 2
41 #include <sys/tihdr.h>
42 #include <sys/timod.h>
43 #include <sys/suntpi.h>
44 #include <sys/debug.h>
45 #include <sys/strlog.h>
46 #include <sys/errno.h>
47 #include <sys/cred.h>
48 #include <sys/cmn_err.h>
49 #include <sys/kmem.h>
50 #include <sys/sysmacros.h>
51 #include <sys/ddi.h>
52 #include <sys/sunddi.h>
53 #include <sys/strsun.h>
54 #include <c2/audit.h>
55
56 /*
57 * This is the loadable module wrapper.
58 */
59 #include <sys/conf.h>
60 #include <sys/modctl.h>
61
62 static struct streamtab timinfo;
63
64 static struct fmodsw fsw = {
65 "timod",
66 &timinfo,
67 D_MTQPAIR | D_MP,
68 };
69
70 /*
71 * Module linkage information for the kernel.
72 */
73
74 static struct modlstrmod modlstrmod = {
75 &mod_strmodops, "transport interface str mod", &fsw
76 };
77
78 static struct modlinkage modlinkage = {
79 MODREV_1, &modlstrmod, NULL
80 };
81
82 static krwlock_t tim_list_rwlock;
83
84 /*
85 * This module keeps track of capabilities of underlying transport. Information
86 * is persistent through module invocations (open/close). Currently it remembers
87 * whether underlying transport supports TI_GET{MY,PEER}NAME ioctls and
88 * T_CAPABILITY_REQ message. This module either passes ioctl/messages to the
89 * transport or emulates it when transport doesn't understand these
90 * ioctl/messages.
91 *
92 * It is assumed that transport supports T_CAPABILITY_REQ when timod receives
93 * T_CAPABILITY_ACK from the transport. There is no current standard describing
94 * transport behaviour when it receives unknown message type, so following
95 * reactions are expected and handled:
96 *
97 * 1) Transport drops unknown T_CAPABILITY_REQ message type. In this case timod
98 * will wait for tcap_wait time and assume that transport doesn't provide
99 * this message type. T_CAPABILITY_REQ should never travel over the wire, so
100 * timeout value should only take into consideration internal processing time
101 * for the message. From user standpoint it may mean that an application will
102 * hang for TCAP_WAIT time in the kernel the first time this message is used
103 * with some particular transport (e.g. TCP/IP) during system uptime.
104 *
105 * 2) Transport responds with T_ERROR_ACK specifying T_CAPABILITY_REQ as
106 * original message type. In this case it is assumed that transport doesn't
107 * support it (which may not always be true - some transports return
108 * T_ERROR_ACK in other cases like lack of system memory).
109 *
110 * 3) Transport responds with M_ERROR, effectively shutting down the
111 * stream. Unfortunately there is no standard way to pass the reason of
112 * M_ERROR message back to the caller, so it is assumed that if M_ERROR was
113 * sent in response to T_CAPABILITY_REQ message, transport doesn't support
114 * it.
115 *
116 * It is possible under certain circumstances that timod will incorrectly assume
117 * that underlying transport doesn't provide T_CAPABILITY_REQ message type. In
118 * this "worst-case" scenario timod will emulate its functionality by itself and
119 * will provide only TC1_INFO capability. All other bits in CAP_bits1 field are
120 * cleaned. TC1_INFO is emulated by sending T_INFO_REQ down to transport
121 * provider.
122 */
123
124 /*
125 * Notes about locking:
126 *
127 * tim_list_rwlock protects the list of tim_tim structures itself. When this
128 * lock is held, the list itself is stable, but the contents of the entries
129 * themselves might not be.
130 *
131 * The rest of the members are generally protected by D_MTQPAIR, which
132 * specifies a default exclusive inner perimeter. If you're looking at
133 * q->q_ptr, then it's stable.
134 *
135 * There's one exception to this rule: tim_peer{maxlen,len,name}. These members
136 * are touched without entering the associated STREAMS perimeter because we
137 * get the pointer via tim_findlink() rather than q_ptr. These are protected
138 * by tim_mutex instead. If you don't hold that lock, don't look at them.
139 *
140 * (It would be possible to separate out the 'set by T_CONN_RES' cases from the
141 * others, but there appears to be no reason to do so.)
142 */
143 struct tim_tim {
144 uint32_t tim_flags;
145 t_uscalar_t tim_backlog;
146 mblk_t *tim_iocsave;
147 t_scalar_t tim_mymaxlen;
148 t_scalar_t tim_mylen;
149 caddr_t tim_myname;
150 t_scalar_t tim_peermaxlen;
151 t_scalar_t tim_peerlen;
152 caddr_t tim_peername;
153 cred_t *tim_peercred;
154 mblk_t *tim_consave;
155 bufcall_id_t tim_wbufcid;
156 bufcall_id_t tim_rbufcid;
157 timeout_id_t tim_wtimoutid;
158 timeout_id_t tim_rtimoutid;
159 /* Protected by the global tim_list_rwlock for all instances */
160 struct tim_tim *tim_next;
161 struct tim_tim **tim_ptpn;
162 t_uscalar_t tim_acceptor;
163 t_scalar_t tim_saved_prim; /* Primitive from message */
164 /* part of ioctl. */
165 timeout_id_t tim_tcap_timoutid; /* For T_CAP_REQ timeout */
166 tpi_provinfo_t *tim_provinfo; /* Transport description */
167 kmutex_t tim_mutex; /* protect tim_peer* */
168 pid_t tim_cpid;
169 };
170
171
172 /*
173 * Local flags used with tim_flags field in instance structure of
174 * type 'struct _ti_user' declared above.
175 * Historical note:
176 * This namespace constants were previously declared in a
177 * a very messed up namespace in timod.h
178 *
179 * There may be 3 states for transport:
180 *
181 * 1) It provides T_CAPABILITY_REQ
182 * 2) It does not provide T_CAPABILITY_REQ
183 * 3) It is not known yet whether transport provides T_CAPABILITY_REQ or not.
184 *
185 * It is assumed that the underlying transport either provides
186 * T_CAPABILITY_REQ or not and this does not changes during the
187 * system lifetime.
188 *
189 */
190 #define PEEK_RDQ_EXPIND 0x0001 /* look for expinds on stream rd queues */
191 #define WAITIOCACK 0x0002 /* waiting for info for ioctl act */
192 #define CLTS 0x0004 /* connectionless transport */
193 #define COTS 0x0008 /* connection-oriented transport */
194 #define CONNWAIT 0x0010 /* waiting for connect confirmation */
195 #define LOCORDREL 0x0020 /* local end has orderly released */
196 #define REMORDREL 0x0040 /* remote end had orderly released */
197 #define NAMEPROC 0x0080 /* processing a NAME ioctl */
198 /* ONC_PLUS EXTRACT START */
199 #define DO_MYNAME 0x0100 /* timod handles TI_GETMYNAME */
200 /* ONC_PLUS EXTRACT END */
201 #define DO_PEERNAME 0x0200 /* timod handles TI_GETPEERNAME */
202 #define TI_CAP_RECVD 0x0400 /* TI_CAPABILITY received */
203 #define CAP_WANTS_INFO 0x0800 /* TI_CAPABILITY has TC1_INFO set */
204 #define WAIT_IOCINFOACK 0x1000 /* T_INFO_REQ generated from ioctl */
205 #define WAIT_CONNRESACK 0x2000 /* waiting for T_OK_ACK to T_CONN_RES */
206
207
208 /* Debugging facilities */
209 /*
210 * Logging needed for debugging timod should only appear in DEBUG kernel.
211 */
212 #ifdef DEBUG
213 #define TILOG(msg, arg) tilog((msg), (arg))
214 #define TILOGP(msg, arg) tilogp((msg), (arg))
215 #else
216 #define TILOG(msg, arg)
217 #define TILOGP(msg, arg)
218 #endif
219
220
221 /*
222 * Sleep timeout for T_CAPABILITY_REQ. This message never travels across
223 * network, so timeout value should be enough to cover all internal processing
224 * time.
225 */
226 clock_t tim_tcap_wait = 2;
227
228 /* Sleep timeout in tim_recover() */
229 #define TIMWAIT (1*hz)
230 /* Sleep timeout in tim_ioctl_retry() 0.2 seconds */
231 #define TIMIOCWAIT (200*hz/1000)
232
233 /*
234 * Return values for ti_doname().
235 */
236 #define DONAME_FAIL 0 /* failing ioctl (done) */
237 #define DONAME_DONE 1 /* done processing */
238 #define DONAME_CONT 2 /* continue proceesing (not done yet) */
239
240 /*
241 * Function prototypes
242 */
243 static int ti_doname(queue_t *, mblk_t *);
244 static int ti_expind_on_rdqueues(queue_t *);
245 static void tim_ioctl_send_reply(queue_t *, mblk_t *, mblk_t *);
246 static void tim_send_ioc_error_ack(queue_t *, struct tim_tim *, mblk_t *);
247 static void tim_tcap_timer(void *);
248 static void tim_tcap_genreply(queue_t *, struct tim_tim *);
249 static void tim_send_reply(queue_t *, mblk_t *, struct tim_tim *, t_scalar_t);
250 static void tim_answer_ti_sync(queue_t *, mblk_t *, struct tim_tim *,
251 mblk_t *, uint32_t);
252 static void tim_send_ioctl_tpi_msg(queue_t *, mblk_t *, struct tim_tim *,
253 struct iocblk *);
254 static void tim_clear_peer(struct tim_tim *);
255
256 int
_init(void)257 _init(void)
258 {
259 int error;
260
261 rw_init(&tim_list_rwlock, NULL, RW_DRIVER, NULL);
262 error = mod_install(&modlinkage);
263 if (error != 0) {
264 rw_destroy(&tim_list_rwlock);
265 return (error);
266 }
267
268 return (0);
269 }
270
271 int
_fini(void)272 _fini(void)
273 {
274 int error;
275
276 error = mod_remove(&modlinkage);
277 if (error != 0)
278 return (error);
279 rw_destroy(&tim_list_rwlock);
280 return (0);
281 }
282
283 int
_info(struct modinfo * modinfop)284 _info(struct modinfo *modinfop)
285 {
286 return (mod_info(&modlinkage, modinfop));
287 }
288
289
290 /*
291 * Hash list for all instances. Used to find tim_tim structure based on
292 * ACCEPTOR_id in T_CONN_RES. Protected by tim_list_rwlock.
293 */
294 #define TIM_HASH_SIZE 256
295 #ifdef _ILP32
296 #define TIM_HASH(id) (((uintptr_t)(id) >> 8) % TIM_HASH_SIZE)
297 #else
298 #define TIM_HASH(id) ((uintptr_t)(id) % TIM_HASH_SIZE)
299 #endif /* _ILP32 */
300 static struct tim_tim *tim_hash[TIM_HASH_SIZE];
301 int tim_cnt = 0;
302
303 static void tilog(char *, t_scalar_t);
304 static void tilogp(char *, uintptr_t);
305 static mblk_t *tim_filladdr(queue_t *, mblk_t *, boolean_t);
306 static void tim_addlink(struct tim_tim *);
307 static void tim_dellink(struct tim_tim *);
308 static struct tim_tim *tim_findlink(t_uscalar_t);
309 static void tim_recover(queue_t *, mblk_t *, t_scalar_t);
310 static void tim_ioctl_retry(queue_t *);
311
312 int dotilog = 0;
313
314 #define TIMOD_ID 3
315
316 /* ONC_PLUS EXTRACT START */
317 static int timodopen(queue_t *, dev_t *, int, int, cred_t *);
318 /* ONC_PLUS EXTRACT END */
319 static int timodclose(queue_t *, int, cred_t *);
320 static void timodwput(queue_t *, mblk_t *);
321 static void timodrput(queue_t *, mblk_t *);
322 /* ONC_PLUS EXTRACT START */
323 static void timodrsrv(queue_t *);
324 /* ONC_PLUS EXTRACT END */
325 static void timodwsrv(queue_t *);
326 /* ONC_PLUS EXTRACT START */
327 static int timodrproc(queue_t *, mblk_t *);
328 static int timodwproc(queue_t *, mblk_t *);
329 /* ONC_PLUS EXTRACT END */
330
331 /* stream data structure definitions */
332
333 static struct module_info timod_info =
334 {TIMOD_ID, "timod", 0, INFPSZ, 512, 128};
335 static struct qinit timodrinit = {
336 (int (*)())timodrput,
337 (int (*)())timodrsrv,
338 timodopen,
339 timodclose,
340 nulldev,
341 &timod_info,
342 NULL
343 };
344 static struct qinit timodwinit = {
345 (int (*)())timodwput,
346 (int (*)())timodwsrv,
347 timodopen,
348 timodclose,
349 nulldev,
350 &timod_info,
351 NULL
352 };
353 static struct streamtab timinfo = { &timodrinit, &timodwinit, NULL, NULL };
354
355 /* ONC_PLUS EXTRACT START */
356 /*
357 * timodopen - open routine gets called when the module gets pushed
358 * onto the stream.
359 */
360 /*ARGSUSED*/
361 static int
timodopen(queue_t * q,dev_t * devp,int flag,int sflag,cred_t * crp)362 timodopen(
363 queue_t *q,
364 dev_t *devp,
365 int flag,
366 int sflag,
367 cred_t *crp)
368 {
369 struct tim_tim *tp;
370 struct stroptions *sop;
371 mblk_t *bp;
372
373 ASSERT(q != NULL);
374
375 if (q->q_ptr) {
376 return (0);
377 }
378
379 if ((bp = allocb(sizeof (struct stroptions), BPRI_MED)) == 0)
380 return (ENOMEM);
381
382 tp = kmem_zalloc(sizeof (struct tim_tim), KM_SLEEP);
383
384 tp->tim_cpid = -1;
385 tp->tim_saved_prim = -1;
386
387 mutex_init(&tp->tim_mutex, NULL, MUTEX_DEFAULT, NULL);
388
389 q->q_ptr = (caddr_t)tp;
390 WR(q)->q_ptr = (caddr_t)tp;
391
392 tilogp("timodopen: Allocated for tp %lx\n", (uintptr_t)tp);
393 tilogp("timodopen: Allocated for q %lx\n", (uintptr_t)q);
394
395 /* Must be done before tpi_findprov and _ILP32 q_next walk below */
396 qprocson(q);
397
398 tp->tim_provinfo = tpi_findprov(q);
399
400 /*
401 * Defer allocation of the buffers for the local address and
402 * the peer's address until we need them.
403 * Assume that timod has to handle getname until we here
404 * an iocack from the transport provider or we know that
405 * transport provider doesn't understand it.
406 */
407 if (tp->tim_provinfo->tpi_myname != PI_YES) {
408 TILOG("timodopen: setting DO_MYNAME\n", 0);
409 tp->tim_flags |= DO_MYNAME;
410 }
411
412 if (tp->tim_provinfo->tpi_peername != PI_YES) {
413 TILOG("timodopen: setting DO_PEERNAME\n", 0);
414 tp->tim_flags |= DO_PEERNAME;
415 }
416
417 #ifdef _ILP32
418 {
419 queue_t *driverq;
420
421 /*
422 * Find my driver's read queue (for T_CONN_RES handling)
423 */
424 driverq = WR(q);
425 while (SAMESTR(driverq))
426 driverq = driverq->q_next;
427
428 tp->tim_acceptor = (t_uscalar_t)RD(driverq);
429 }
430 #else
431 tp->tim_acceptor = (t_uscalar_t)getminor(*devp);
432 #endif /* _ILP32 */
433
434 /*
435 * Add this one to the list.
436 */
437 tim_addlink(tp);
438
439 /*
440 * Send M_SETOPTS to stream head to make sure M_PCPROTO messages
441 * are not flushed. This prevents application deadlocks.
442 */
443 bp->b_datap->db_type = M_SETOPTS;
444 bp->b_wptr += sizeof (struct stroptions);
445 sop = (struct stroptions *)bp->b_rptr;
446 sop->so_flags = SO_READOPT;
447 sop->so_readopt = RFLUSHPCPROT;
448
449 putnext(q, bp);
450
451 return (0);
452 }
453
454 static void
tim_timer(void * arg)455 tim_timer(void *arg)
456 {
457 queue_t *q = arg;
458 struct tim_tim *tp = (struct tim_tim *)q->q_ptr;
459
460 ASSERT(tp);
461
462 if (q->q_flag & QREADR) {
463 ASSERT(tp->tim_rtimoutid);
464 tp->tim_rtimoutid = 0;
465 } else {
466 ASSERT(tp->tim_wtimoutid);
467 tp->tim_wtimoutid = 0;
468 }
469 enableok(q);
470 qenable(q);
471 }
472
473 static void
tim_buffer(void * arg)474 tim_buffer(void *arg)
475 {
476 queue_t *q = arg;
477 struct tim_tim *tp = (struct tim_tim *)q->q_ptr;
478
479 ASSERT(tp);
480
481 if (q->q_flag & QREADR) {
482 ASSERT(tp->tim_rbufcid);
483 tp->tim_rbufcid = 0;
484 } else {
485 ASSERT(tp->tim_wbufcid);
486 tp->tim_wbufcid = 0;
487 }
488 enableok(q);
489 qenable(q);
490 }
491 /* ONC_PLUS EXTRACT END */
492
493 /*
494 * timodclose - This routine gets called when the module gets popped
495 * off of the stream.
496 */
497 /*ARGSUSED*/
498 static int
timodclose(queue_t * q,int flag,cred_t * crp)499 timodclose(
500 queue_t *q,
501 int flag,
502 cred_t *crp)
503 {
504 struct tim_tim *tp;
505 mblk_t *mp;
506 mblk_t *nmp;
507
508 ASSERT(q != NULL);
509
510 tp = (struct tim_tim *)q->q_ptr;
511 q->q_ptr = NULL;
512
513 ASSERT(tp != NULL);
514
515 tilogp("timodclose: Entered for tp %lx\n", (uintptr_t)tp);
516 tilogp("timodclose: Entered for q %lx\n", (uintptr_t)q);
517
518 qprocsoff(q);
519 tim_dellink(tp);
520
521 /*
522 * Cancel any outstanding bufcall
523 * or timeout requests.
524 */
525 if (tp->tim_wbufcid) {
526 qunbufcall(q, tp->tim_wbufcid);
527 tp->tim_wbufcid = 0;
528 }
529 if (tp->tim_rbufcid) {
530 qunbufcall(q, tp->tim_rbufcid);
531 tp->tim_rbufcid = 0;
532 }
533 if (tp->tim_wtimoutid) {
534 (void) quntimeout(q, tp->tim_wtimoutid);
535 tp->tim_wtimoutid = 0;
536 }
537 if (tp->tim_rtimoutid) {
538 (void) quntimeout(q, tp->tim_rtimoutid);
539 tp->tim_rtimoutid = 0;
540 }
541
542 if (tp->tim_tcap_timoutid != 0) {
543 (void) quntimeout(q, tp->tim_tcap_timoutid);
544 tp->tim_tcap_timoutid = 0;
545 }
546
547 if (tp->tim_iocsave != NULL)
548 freemsg(tp->tim_iocsave);
549 mp = tp->tim_consave;
550 while (mp) {
551 nmp = mp->b_next;
552 mp->b_next = NULL;
553 freemsg(mp);
554 mp = nmp;
555 }
556 ASSERT(tp->tim_mymaxlen >= 0);
557 if (tp->tim_mymaxlen != 0)
558 kmem_free(tp->tim_myname, (size_t)tp->tim_mymaxlen);
559 ASSERT(tp->tim_peermaxlen >= 0);
560 if (tp->tim_peermaxlen != 0)
561 kmem_free(tp->tim_peername, (size_t)tp->tim_peermaxlen);
562
563 q->q_ptr = WR(q)->q_ptr = NULL;
564
565 mutex_destroy(&tp->tim_mutex);
566
567 if (tp->tim_peercred != NULL)
568 crfree(tp->tim_peercred);
569
570 kmem_free(tp, sizeof (struct tim_tim));
571
572 return (0);
573 }
574
575 /*
576 * timodrput - Module read put procedure. This is called from
577 * the module, driver, or stream head upstream/downstream.
578 * Handles M_FLUSH, M_DATA and some M_PROTO (T_DATA_IND,
579 * and T_UNITDATA_IND) messages. All others are queued to
580 * be handled by the service procedures.
581 */
582 static void
timodrput(queue_t * q,mblk_t * mp)583 timodrput(queue_t *q, mblk_t *mp)
584 {
585 union T_primitives *pptr;
586
587 /*
588 * During flow control and other instances when messages
589 * are on queue, queue up a non high priority message
590 */
591 if (q->q_first != 0 && mp->b_datap->db_type < QPCTL) {
592 (void) putq(q, mp);
593 return;
594 }
595
596 /*
597 * Inline processing of data (to avoid additional procedure call).
598 * Rest is handled in timodrproc.
599 */
600
601 switch (mp->b_datap->db_type) {
602 case M_DATA:
603 if (bcanputnext(q, mp->b_band))
604 putnext(q, mp);
605 else
606 (void) putq(q, mp);
607 break;
608 case M_PROTO:
609 case M_PCPROTO:
610 if (MBLKL(mp) < sizeof (t_scalar_t)) {
611 if (mp->b_datap->db_type == M_PCPROTO ||
612 bcanputnext(q, mp->b_band)) {
613 putnext(q, mp);
614 } else {
615 (void) putq(q, mp);
616 }
617 break;
618 }
619 pptr = (union T_primitives *)mp->b_rptr;
620 switch (pptr->type) {
621 case T_EXDATA_IND:
622 case T_DATA_IND:
623 case T_UNITDATA_IND:
624 if (bcanputnext(q, mp->b_band))
625 putnext(q, mp);
626 else
627 (void) putq(q, mp);
628 break;
629 default:
630 (void) timodrproc(q, mp);
631 break;
632 }
633 break;
634 default:
635 (void) timodrproc(q, mp);
636 break;
637 }
638 }
639
640 /* ONC_PLUS EXTRACT START */
641 /*
642 * timodrsrv - Module read queue service procedure. This is called when
643 * messages are placed on an empty queue, when high priority
644 * messages are placed on the queue, and when flow control
645 * restrictions subside. This code used to be included in a
646 * put procedure, but it was moved to a service procedure
647 * because several points were added where memory allocation
648 * could fail, and there is no reasonable recovery mechanism
649 * from the put procedure.
650 */
651 /*ARGSUSED*/
652 static void
timodrsrv(queue_t * q)653 timodrsrv(queue_t *q)
654 {
655 /* ONC_PLUS EXTRACT END */
656 mblk_t *mp;
657 struct tim_tim *tp;
658
659 ASSERT(q != NULL);
660
661 tp = (struct tim_tim *)q->q_ptr;
662 if (!tp)
663 return;
664
665 while ((mp = getq(q)) != NULL) {
666 if (timodrproc(q, mp)) {
667 /*
668 * timodrproc did a putbq - stop processing
669 * messages.
670 */
671 return;
672 }
673 }
674 /* ONC_PLUS EXTRACT START */
675 }
676
677 /*
678 * Perform common processing when a T_CAPABILITY_ACK or T_INFO_ACK
679 * arrive. Set the queue properties and adjust the tim_flags according
680 * to the service type.
681 */
682 static void
timodprocessinfo(queue_t * q,struct tim_tim * tp,struct T_info_ack * tia)683 timodprocessinfo(queue_t *q, struct tim_tim *tp, struct T_info_ack *tia)
684 {
685 TILOG("timodprocessinfo: strqset(%d)\n", tia->TIDU_size);
686 (void) strqset(q, QMAXPSZ, 0, tia->TIDU_size);
687 (void) strqset(OTHERQ(q), QMAXPSZ, 0, tia->TIDU_size);
688
689 if ((tia->SERV_type == T_COTS) || (tia->SERV_type == T_COTS_ORD))
690 tp->tim_flags = (tp->tim_flags & ~CLTS) | COTS;
691 else if (tia->SERV_type == T_CLTS)
692 tp->tim_flags = (tp->tim_flags & ~COTS) | CLTS;
693 }
694
695 static int
timodrproc(queue_t * q,mblk_t * mp)696 timodrproc(queue_t *q, mblk_t *mp)
697 {
698 uint32_t auditing = AU_AUDITING();
699 union T_primitives *pptr;
700 struct tim_tim *tp;
701 struct iocblk *iocbp;
702 mblk_t *nbp;
703 size_t blen;
704 /* ONC_PLUS EXTRACT END */
705
706 tp = (struct tim_tim *)q->q_ptr;
707
708 /* ONC_PLUS EXTRACT START */
709 switch (mp->b_datap->db_type) {
710 default:
711 putnext(q, mp);
712 break;
713
714 case M_ERROR:
715 TILOG("timodrproc: Got M_ERROR, flags = %x\n", tp->tim_flags);
716 /*
717 * There is no specified standard response for driver when it
718 * receives unknown message type and M_ERROR is one
719 * possibility. If we send T_CAPABILITY_REQ down and transport
720 * provider responds with M_ERROR we assume that it doesn't
721 * understand this message type. This assumption may be
722 * sometimes incorrect (transport may reply with M_ERROR for
723 * some other reason) but there is no way for us to distinguish
724 * between different cases. In the worst case timod and everyone
725 * else sharing global transport description with it may end up
726 * emulating T_CAPABILITY_REQ.
727 */
728
729 /*
730 * Check that we are waiting for T_CAPABILITY_ACK and
731 * T_CAPABILITY_REQ is not implemented by transport or emulated
732 * by timod.
733 */
734 if ((tp->tim_provinfo->tpi_capability == PI_DONTKNOW) &&
735 ((tp->tim_flags & TI_CAP_RECVD) != 0)) {
736 /*
737 * Good chances that this transport doesn't provide
738 * T_CAPABILITY_REQ. Mark this information permanently
739 * for the module + transport combination.
740 */
741 PI_PROVLOCK(tp->tim_provinfo);
742 if (tp->tim_provinfo->tpi_capability == PI_DONTKNOW)
743 tp->tim_provinfo->tpi_capability = PI_NO;
744 PI_PROVUNLOCK(tp->tim_provinfo);
745 if (tp->tim_tcap_timoutid != 0) {
746 (void) quntimeout(q, tp->tim_tcap_timoutid);
747 tp->tim_tcap_timoutid = 0;
748 }
749 }
750 putnext(q, mp);
751 break;
752 case M_DATA:
753 if (!bcanputnext(q, mp->b_band)) {
754 (void) putbq(q, mp);
755 return (1);
756 }
757 putnext(q, mp);
758 break;
759
760 case M_PROTO:
761 case M_PCPROTO:
762 blen = MBLKL(mp);
763 if (blen < sizeof (t_scalar_t)) {
764 /*
765 * Note: it's not actually possible to get
766 * here with db_type M_PCPROTO, because
767 * timodrput has already checked MBLKL, and
768 * thus the assertion below. If the length
769 * was too short, then the message would have
770 * already been putnext'd, and would thus
771 * never appear here. Just the same, the code
772 * below handles the impossible case since
773 * it's easy to do and saves future
774 * maintainers from unfortunate accidents.
775 */
776 ASSERT(mp->b_datap->db_type == M_PROTO);
777 if (mp->b_datap->db_type == M_PROTO &&
778 !bcanputnext(q, mp->b_band)) {
779 (void) putbq(q, mp);
780 return (1);
781 }
782 putnext(q, mp);
783 break;
784 }
785
786 pptr = (union T_primitives *)mp->b_rptr;
787 switch (pptr->type) {
788 default:
789 /* ONC_PLUS EXTRACT END */
790
791 if (auditing)
792 audit_sock(T_UNITDATA_IND, q, mp, TIMOD_ID);
793 /* ONC_PLUS EXTRACT START */
794 putnext(q, mp);
795 break;
796 /* ONC_PLUS EXTRACT END */
797
798 case T_ERROR_ACK:
799 /* Restore db_type - recover() might have changed it */
800 mp->b_datap->db_type = M_PCPROTO;
801 if (blen < sizeof (struct T_error_ack)) {
802 putnext(q, mp);
803 break;
804 }
805
806 tilog("timodrproc: Got T_ERROR_ACK, flags = %x\n",
807 tp->tim_flags);
808
809 if ((tp->tim_flags & WAIT_CONNRESACK) &&
810 tp->tim_saved_prim == pptr->error_ack.ERROR_prim) {
811 tp->tim_flags &=
812 ~(WAIT_CONNRESACK | WAITIOCACK);
813 freemsg(tp->tim_iocsave);
814 tp->tim_iocsave = NULL;
815 tp->tim_saved_prim = -1;
816 putnext(q, mp);
817 } else if (tp->tim_flags & WAITIOCACK) {
818 tim_send_ioc_error_ack(q, tp, mp);
819 } else {
820 putnext(q, mp);
821 }
822 break;
823
824 case T_OK_ACK:
825 if (blen < sizeof (pptr->ok_ack)) {
826 mp->b_datap->db_type = M_PCPROTO;
827 putnext(q, mp);
828 break;
829 }
830
831 tilog("timodrproc: Got T_OK_ACK\n", 0);
832
833 if (pptr->ok_ack.CORRECT_prim == T_UNBIND_REQ)
834 tp->tim_mylen = 0;
835
836 if ((tp->tim_flags & WAIT_CONNRESACK) &&
837 tp->tim_saved_prim == pptr->ok_ack.CORRECT_prim) {
838 struct T_conn_res *resp;
839 struct T_conn_ind *indp;
840 struct tim_tim *ntp;
841 caddr_t ptr;
842
843 rw_enter(&tim_list_rwlock, RW_READER);
844 resp = (struct T_conn_res *)
845 tp->tim_iocsave->b_rptr;
846 ntp = tim_findlink(resp->ACCEPTOR_id);
847 if (ntp == NULL)
848 goto cresackout;
849
850 mutex_enter(&ntp->tim_mutex);
851 if (ntp->tim_peercred != NULL)
852 crfree(ntp->tim_peercred);
853 ntp->tim_peercred =
854 msg_getcred(tp->tim_iocsave->b_cont,
855 &ntp->tim_cpid);
856 if (ntp->tim_peercred != NULL)
857 crhold(ntp->tim_peercred);
858
859 if (!(ntp->tim_flags & DO_PEERNAME)) {
860 mutex_exit(&ntp->tim_mutex);
861 goto cresackout;
862 }
863
864 indp = (struct T_conn_ind *)
865 tp->tim_iocsave->b_cont->b_rptr;
866 /* true as message is put on list */
867 ASSERT(indp->SRC_length >= 0);
868
869 if (indp->SRC_length > ntp->tim_peermaxlen) {
870 ptr = kmem_alloc(indp->SRC_length,
871 KM_NOSLEEP);
872 if (ptr == NULL) {
873 mutex_exit(&ntp->tim_mutex);
874 rw_exit(&tim_list_rwlock);
875 tilog("timodwproc: kmem_alloc "
876 "failed, attempting "
877 "recovery\n", 0);
878 tim_recover(q, mp,
879 indp->SRC_length);
880 return (1);
881 }
882 if (ntp->tim_peermaxlen > 0)
883 kmem_free(ntp->tim_peername,
884 ntp->tim_peermaxlen);
885 ntp->tim_peername = ptr;
886 ntp->tim_peermaxlen = indp->SRC_length;
887 }
888 ntp->tim_peerlen = indp->SRC_length;
889 ptr = (caddr_t)indp + indp->SRC_offset;
890 bcopy(ptr, ntp->tim_peername, ntp->tim_peerlen);
891
892 mutex_exit(&ntp->tim_mutex);
893
894 cresackout:
895 rw_exit(&tim_list_rwlock);
896 tp->tim_flags &=
897 ~(WAIT_CONNRESACK | WAITIOCACK);
898 freemsg(tp->tim_iocsave);
899 tp->tim_iocsave = NULL;
900 tp->tim_saved_prim = -1;
901 }
902
903 tim_send_reply(q, mp, tp, pptr->ok_ack.CORRECT_prim);
904 break;
905
906 /* ONC_PLUS EXTRACT START */
907 case T_BIND_ACK: {
908 struct T_bind_ack *ackp =
909 (struct T_bind_ack *)mp->b_rptr;
910
911 /* Restore db_type - recover() might have changed it */
912 mp->b_datap->db_type = M_PCPROTO;
913 if (blen < sizeof (*ackp)) {
914 putnext(q, mp);
915 break;
916 }
917
918 /* save negotiated backlog */
919 tp->tim_backlog = ackp->CONIND_number;
920
921 if (((tp->tim_flags & WAITIOCACK) == 0) ||
922 ((tp->tim_saved_prim != O_T_BIND_REQ) &&
923 (tp->tim_saved_prim != T_BIND_REQ))) {
924 putnext(q, mp);
925 break;
926 }
927 ASSERT(tp->tim_iocsave != NULL);
928
929 if (tp->tim_flags & DO_MYNAME) {
930 caddr_t p;
931
932 if (ackp->ADDR_length < 0 ||
933 mp->b_rptr + ackp->ADDR_offset +
934 ackp->ADDR_length > mp->b_wptr) {
935 putnext(q, mp);
936 break;
937 }
938 if (ackp->ADDR_length > tp->tim_mymaxlen) {
939 p = kmem_alloc(ackp->ADDR_length,
940 KM_NOSLEEP);
941 if (p == NULL) {
942 tilog("timodrproc: kmem_alloc "
943 "failed attempt recovery",
944 0);
945
946 tim_recover(q, mp,
947 ackp->ADDR_length);
948 return (1);
949 }
950 ASSERT(tp->tim_mymaxlen >= 0);
951 if (tp->tim_mymaxlen != NULL) {
952 kmem_free(tp->tim_myname,
953 tp->tim_mymaxlen);
954 }
955 tp->tim_myname = p;
956 tp->tim_mymaxlen = ackp->ADDR_length;
957 }
958 tp->tim_mylen = ackp->ADDR_length;
959 bcopy(mp->b_rptr + ackp->ADDR_offset,
960 tp->tim_myname, tp->tim_mylen);
961 }
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 | WAIT_IOCINFOACK |
966 TI_CAP_RECVD | CAP_WANTS_INFO);
967 break;
968 }
969
970 /* ONC_PLUS EXTRACT END */
971 case T_OPTMGMT_ACK:
972
973 tilog("timodrproc: Got T_OPTMGMT_ACK\n", 0);
974
975 /* Restore db_type - recover() might have change it */
976 mp->b_datap->db_type = M_PCPROTO;
977
978 if (((tp->tim_flags & WAITIOCACK) == 0) ||
979 ((tp->tim_saved_prim != T_SVR4_OPTMGMT_REQ) &&
980 (tp->tim_saved_prim != T_OPTMGMT_REQ))) {
981 putnext(q, mp);
982 } else {
983 ASSERT(tp->tim_iocsave != NULL);
984 tim_ioctl_send_reply(q, tp->tim_iocsave, mp);
985 tp->tim_iocsave = NULL;
986 tp->tim_saved_prim = -1;
987 tp->tim_flags &= ~(WAITIOCACK |
988 WAIT_IOCINFOACK | TI_CAP_RECVD |
989 CAP_WANTS_INFO);
990 }
991 break;
992
993 case T_INFO_ACK: {
994 struct T_info_ack *tia = (struct T_info_ack *)pptr;
995
996 /* Restore db_type - recover() might have changed it */
997 mp->b_datap->db_type = M_PCPROTO;
998
999 if (blen < sizeof (*tia)) {
1000 putnext(q, mp);
1001 break;
1002 }
1003
1004 tilog("timodrproc: Got T_INFO_ACK, flags = %x\n",
1005 tp->tim_flags);
1006
1007 timodprocessinfo(q, tp, tia);
1008
1009 TILOG("timodrproc: flags = %x\n", tp->tim_flags);
1010 if ((tp->tim_flags & WAITIOCACK) != 0) {
1011 size_t expected_ack_size;
1012 ssize_t deficit;
1013 int ioc_cmd;
1014 struct T_capability_ack *tcap;
1015
1016 /*
1017 * The only case when T_INFO_ACK may be received back
1018 * when we are waiting for ioctl to complete is when
1019 * this ioctl sent T_INFO_REQ down.
1020 */
1021 if (!(tp->tim_flags & WAIT_IOCINFOACK)) {
1022 putnext(q, mp);
1023 break;
1024 }
1025 ASSERT(tp->tim_iocsave != NULL);
1026
1027 iocbp = (struct iocblk *)tp->tim_iocsave->b_rptr;
1028 ioc_cmd = iocbp->ioc_cmd;
1029
1030 /*
1031 * Was it sent from TI_CAPABILITY emulation?
1032 */
1033 if (ioc_cmd == TI_CAPABILITY) {
1034 struct T_info_ack saved_info;
1035
1036 /*
1037 * Perform sanity checks. The only case when we
1038 * send T_INFO_REQ from TI_CAPABILITY is when
1039 * timod emulates T_CAPABILITY_REQ and CAP_bits1
1040 * has TC1_INFO set.
1041 */
1042 if ((tp->tim_flags &
1043 (TI_CAP_RECVD | CAP_WANTS_INFO)) !=
1044 (TI_CAP_RECVD | CAP_WANTS_INFO)) {
1045 putnext(q, mp);
1046 break;
1047 }
1048
1049 TILOG("timodrproc: emulating TI_CAPABILITY/"
1050 "info\n", 0);
1051
1052 /* Save info & reuse mp for T_CAPABILITY_ACK */
1053 saved_info = *tia;
1054
1055 mp = tpi_ack_alloc(mp,
1056 sizeof (struct T_capability_ack),
1057 M_PCPROTO, T_CAPABILITY_ACK);
1058
1059 if (mp == NULL) {
1060 tilog("timodrproc: realloc failed, "
1061 "no recovery attempted\n", 0);
1062 return (1);
1063 }
1064
1065 /*
1066 * Copy T_INFO information into T_CAPABILITY_ACK
1067 */
1068 tcap = (struct T_capability_ack *)mp->b_rptr;
1069 tcap->CAP_bits1 = TC1_INFO;
1070 tcap->INFO_ack = saved_info;
1071 tp->tim_flags &= ~(WAITIOCACK |
1072 WAIT_IOCINFOACK | TI_CAP_RECVD |
1073 CAP_WANTS_INFO);
1074 tim_ioctl_send_reply(q, tp->tim_iocsave, mp);
1075 tp->tim_iocsave = NULL;
1076 tp->tim_saved_prim = -1;
1077 break;
1078 }
1079
1080 /*
1081 * The code for TI_SYNC/TI_GETINFO is left here only for
1082 * backward compatibility with staticaly linked old
1083 * applications. New TLI/XTI code should use
1084 * TI_CAPABILITY for getting transport info and should
1085 * not use TI_GETINFO/TI_SYNC for this purpose.
1086 */
1087
1088 /*
1089 * make sure the message sent back is the size of
1090 * the "expected ack"
1091 * For TI_GETINFO, expected ack size is
1092 * sizeof (T_info_ack)
1093 * For TI_SYNC, expected ack size is
1094 * sizeof (struct ti_sync_ack);
1095 */
1096 if (ioc_cmd != TI_GETINFO && ioc_cmd != TI_SYNC) {
1097 putnext(q, mp);
1098 break;
1099 }
1100
1101 expected_ack_size =
1102 sizeof (struct T_info_ack); /* TI_GETINFO */
1103 if (iocbp->ioc_cmd == TI_SYNC) {
1104 expected_ack_size = 2 * sizeof (uint32_t) +
1105 sizeof (struct ti_sync_ack);
1106 }
1107 deficit = expected_ack_size - blen;
1108
1109 if (deficit != 0) {
1110 if (mp->b_datap->db_lim - mp->b_wptr <
1111 deficit) {
1112 mblk_t *tmp = allocb(expected_ack_size,
1113 BPRI_HI);
1114 if (tmp == NULL) {
1115 ASSERT(MBLKSIZE(mp) >=
1116 sizeof (struct T_error_ack));
1117
1118 tilog("timodrproc: allocb failed no "
1119 "recovery attempt\n", 0);
1120
1121 mp->b_rptr = mp->b_datap->db_base;
1122 pptr = (union T_primitives *)
1123 mp->b_rptr;
1124 pptr->error_ack.ERROR_prim = T_INFO_REQ;
1125 pptr->error_ack.TLI_error = TSYSERR;
1126 pptr->error_ack.UNIX_error = EAGAIN;
1127 pptr->error_ack.PRIM_type = T_ERROR_ACK;
1128 mp->b_datap->db_type = M_PCPROTO;
1129 tim_send_ioc_error_ack(q, tp, mp);
1130 break;
1131 } else {
1132 bcopy(mp->b_rptr, tmp->b_rptr, blen);
1133 tmp->b_wptr += blen;
1134 pptr = (union T_primitives *)
1135 tmp->b_rptr;
1136 freemsg(mp);
1137 mp = tmp;
1138 }
1139 }
1140 }
1141 /*
1142 * We now have "mp" which has enough space for an
1143 * appropriate ack and contains struct T_info_ack
1144 * that the transport provider returned. We now
1145 * stuff it with more stuff to fullfill
1146 * TI_SYNC ioctl needs, as necessary
1147 */
1148 if (iocbp->ioc_cmd == TI_SYNC) {
1149 /*
1150 * Assumes struct T_info_ack is first embedded
1151 * type in struct ti_sync_ack so it is
1152 * automatically there.
1153 */
1154 struct ti_sync_ack *tsap =
1155 (struct ti_sync_ack *)mp->b_rptr;
1156
1157 /*
1158 * tsap->tsa_qlen needs to be set only if
1159 * TSRF_QLEN_REQ flag is set, but for
1160 * compatibility with statically linked
1161 * applications it is set here regardless of the
1162 * flag since old XTI library expected it to be
1163 * set.
1164 */
1165 tsap->tsa_qlen = tp->tim_backlog;
1166 tsap->tsa_flags = 0x0; /* intialize clear */
1167 if (tp->tim_flags & PEEK_RDQ_EXPIND) {
1168 /*
1169 * Request to peek for EXPIND in
1170 * rcvbuf.
1171 */
1172 if (ti_expind_on_rdqueues(q)) {
1173 /*
1174 * Expedited data is
1175 * queued on the stream
1176 * read side
1177 */
1178 tsap->tsa_flags |=
1179 TSAF_EXP_QUEUED;
1180 }
1181 tp->tim_flags &=
1182 ~PEEK_RDQ_EXPIND;
1183 }
1184 mp->b_wptr += 2*sizeof (uint32_t);
1185 }
1186 tim_ioctl_send_reply(q, tp->tim_iocsave, mp);
1187 tp->tim_iocsave = NULL;
1188 tp->tim_saved_prim = -1;
1189 tp->tim_flags &= ~(WAITIOCACK | WAIT_IOCINFOACK |
1190 TI_CAP_RECVD | CAP_WANTS_INFO);
1191 break;
1192 }
1193 }
1194
1195 putnext(q, mp);
1196 break;
1197
1198 case T_ADDR_ACK:
1199 tilog("timodrproc: Got T_ADDR_ACK\n", 0);
1200 tim_send_reply(q, mp, tp, T_ADDR_REQ);
1201 break;
1202
1203 /* ONC_PLUS EXTRACT START */
1204 case T_CONN_IND: {
1205 struct T_conn_ind *tcip =
1206 (struct T_conn_ind *)mp->b_rptr;
1207
1208 tilog("timodrproc: Got T_CONN_IND\n", 0);
1209
1210 if (blen >= sizeof (*tcip) &&
1211 MBLKIN(mp, tcip->SRC_offset, tcip->SRC_length)) {
1212 if (((nbp = dupmsg(mp)) != NULL) ||
1213 ((nbp = copymsg(mp)) != NULL)) {
1214 nbp->b_next = tp->tim_consave;
1215 tp->tim_consave = nbp;
1216 } else {
1217 tim_recover(q, mp,
1218 (t_scalar_t)sizeof (mblk_t));
1219 return (1);
1220 }
1221 }
1222 /* ONC_PLUS EXTRACT END */
1223 if (auditing)
1224 audit_sock(T_CONN_IND, q, mp, TIMOD_ID);
1225 /* ONC_PLUS EXTRACT START */
1226 putnext(q, mp);
1227 break;
1228 }
1229
1230 /* ONC_PLUS EXTRACT END */
1231 case T_CONN_CON:
1232 mutex_enter(&tp->tim_mutex);
1233 if (tp->tim_peercred != NULL)
1234 crfree(tp->tim_peercred);
1235 tp->tim_peercred = msg_getcred(mp, &tp->tim_cpid);
1236 if (tp->tim_peercred != NULL)
1237 crhold(tp->tim_peercred);
1238 mutex_exit(&tp->tim_mutex);
1239
1240 tilog("timodrproc: Got T_CONN_CON\n", 0);
1241
1242 tp->tim_flags &= ~CONNWAIT;
1243 putnext(q, mp);
1244 break;
1245
1246 case T_DISCON_IND: {
1247 struct T_discon_ind *disp;
1248 struct T_conn_ind *conp;
1249 mblk_t *pbp = NULL;
1250
1251 if (q->q_first != 0)
1252 tilog("timodrput: T_DISCON_IND - flow control\n", 0);
1253
1254 if (blen < sizeof (*disp)) {
1255 putnext(q, mp);
1256 break;
1257 }
1258
1259 disp = (struct T_discon_ind *)mp->b_rptr;
1260
1261 tilog("timodrproc: Got T_DISCON_IND Reason: %d\n",
1262 disp->DISCON_reason);
1263
1264 tp->tim_flags &= ~(CONNWAIT|LOCORDREL|REMORDREL);
1265 tim_clear_peer(tp);
1266 for (nbp = tp->tim_consave; nbp; nbp = nbp->b_next) {
1267 conp = (struct T_conn_ind *)nbp->b_rptr;
1268 if (conp->SEQ_number == disp->SEQ_number)
1269 break;
1270 pbp = nbp;
1271 }
1272 if (nbp) {
1273 if (pbp)
1274 pbp->b_next = nbp->b_next;
1275 else
1276 tp->tim_consave = nbp->b_next;
1277 nbp->b_next = NULL;
1278 freemsg(nbp);
1279 }
1280 putnext(q, mp);
1281 break;
1282 }
1283
1284 case T_ORDREL_IND:
1285
1286 tilog("timodrproc: Got T_ORDREL_IND\n", 0);
1287
1288 if (tp->tim_flags & LOCORDREL) {
1289 tp->tim_flags &= ~(LOCORDREL|REMORDREL);
1290 tim_clear_peer(tp);
1291 } else {
1292 tp->tim_flags |= REMORDREL;
1293 }
1294 putnext(q, mp);
1295 break;
1296
1297 case T_EXDATA_IND:
1298 case T_DATA_IND:
1299 case T_UNITDATA_IND:
1300 if (pptr->type == T_EXDATA_IND)
1301 tilog("timodrproc: Got T_EXDATA_IND\n", 0);
1302
1303 if (!bcanputnext(q, mp->b_band)) {
1304 (void) putbq(q, mp);
1305 return (1);
1306 }
1307 putnext(q, mp);
1308 break;
1309
1310 case T_CAPABILITY_ACK: {
1311 struct T_capability_ack *tca;
1312
1313 if (blen < sizeof (*tca)) {
1314 putnext(q, mp);
1315 break;
1316 }
1317
1318 /* This transport supports T_CAPABILITY_REQ */
1319 tilog("timodrproc: Got T_CAPABILITY_ACK\n", 0);
1320
1321 PI_PROVLOCK(tp->tim_provinfo);
1322 if (tp->tim_provinfo->tpi_capability != PI_YES)
1323 tp->tim_provinfo->tpi_capability = PI_YES;
1324 PI_PROVUNLOCK(tp->tim_provinfo);
1325
1326 /* Reset possible pending timeout */
1327 if (tp->tim_tcap_timoutid != 0) {
1328 (void) quntimeout(q, tp->tim_tcap_timoutid);
1329 tp->tim_tcap_timoutid = 0;
1330 }
1331
1332 tca = (struct T_capability_ack *)mp->b_rptr;
1333
1334 if (tca->CAP_bits1 & TC1_INFO)
1335 timodprocessinfo(q, tp, &tca->INFO_ack);
1336
1337 tim_send_reply(q, mp, tp, T_CAPABILITY_REQ);
1338 }
1339 break;
1340 }
1341 break;
1342
1343 /* ONC_PLUS EXTRACT START */
1344 case M_FLUSH:
1345
1346 tilog("timodrproc: Got M_FLUSH\n", 0);
1347
1348 if (*mp->b_rptr & FLUSHR) {
1349 if (*mp->b_rptr & FLUSHBAND)
1350 flushband(q, *(mp->b_rptr + 1), FLUSHDATA);
1351 else
1352 flushq(q, FLUSHDATA);
1353 }
1354 putnext(q, mp);
1355 break;
1356 /* ONC_PLUS EXTRACT END */
1357
1358 case M_IOCACK:
1359 iocbp = (struct iocblk *)mp->b_rptr;
1360
1361 tilog("timodrproc: Got M_IOCACK\n", 0);
1362
1363 if (iocbp->ioc_cmd == TI_GETMYNAME) {
1364
1365 /*
1366 * Transport provider supports this ioctl,
1367 * so I don't have to.
1368 */
1369 if ((tp->tim_flags & DO_MYNAME) != 0) {
1370 tp->tim_flags &= ~DO_MYNAME;
1371 PI_PROVLOCK(tp->tim_provinfo);
1372 tp->tim_provinfo->tpi_myname = PI_YES;
1373 PI_PROVUNLOCK(tp->tim_provinfo);
1374 }
1375
1376 ASSERT(tp->tim_mymaxlen >= 0);
1377 if (tp->tim_mymaxlen != 0) {
1378 kmem_free(tp->tim_myname, (size_t)tp->tim_mymaxlen);
1379 tp->tim_myname = NULL;
1380 tp->tim_mymaxlen = 0;
1381 }
1382 /* tim_iocsave may already be overwritten. */
1383 if (tp->tim_saved_prim == -1) {
1384 freemsg(tp->tim_iocsave);
1385 tp->tim_iocsave = NULL;
1386 }
1387 } else if (iocbp->ioc_cmd == TI_GETPEERNAME) {
1388 boolean_t clearit;
1389
1390 /*
1391 * Transport provider supports this ioctl,
1392 * so I don't have to.
1393 */
1394 if ((tp->tim_flags & DO_PEERNAME) != 0) {
1395 tp->tim_flags &= ~DO_PEERNAME;
1396 PI_PROVLOCK(tp->tim_provinfo);
1397 tp->tim_provinfo->tpi_peername = PI_YES;
1398 PI_PROVUNLOCK(tp->tim_provinfo);
1399 }
1400
1401 mutex_enter(&tp->tim_mutex);
1402 ASSERT(tp->tim_peermaxlen >= 0);
1403 clearit = tp->tim_peermaxlen != 0;
1404 if (clearit) {
1405 kmem_free(tp->tim_peername, tp->tim_peermaxlen);
1406 tp->tim_peername = NULL;
1407 tp->tim_peermaxlen = 0;
1408 tp->tim_peerlen = 0;
1409 }
1410 mutex_exit(&tp->tim_mutex);
1411 if (clearit) {
1412 mblk_t *bp;
1413
1414 bp = tp->tim_consave;
1415 while (bp != NULL) {
1416 nbp = bp->b_next;
1417 bp->b_next = NULL;
1418 freemsg(bp);
1419 bp = nbp;
1420 }
1421 tp->tim_consave = NULL;
1422 }
1423 /* tim_iocsave may already be overwritten. */
1424 if (tp->tim_saved_prim == -1) {
1425 freemsg(tp->tim_iocsave);
1426 tp->tim_iocsave = NULL;
1427 }
1428 }
1429 putnext(q, mp);
1430 break;
1431
1432 /* ONC_PLUS EXTRACT START */
1433 case M_IOCNAK:
1434
1435 tilog("timodrproc: Got M_IOCNAK\n", 0);
1436
1437 iocbp = (struct iocblk *)mp->b_rptr;
1438 if (((iocbp->ioc_cmd == TI_GETMYNAME) ||
1439 (iocbp->ioc_cmd == TI_GETPEERNAME)) &&
1440 ((iocbp->ioc_error == EINVAL) || (iocbp->ioc_error == 0))) {
1441 PI_PROVLOCK(tp->tim_provinfo);
1442 if (iocbp->ioc_cmd == TI_GETMYNAME) {
1443 if (tp->tim_provinfo->tpi_myname == PI_DONTKNOW)
1444 tp->tim_provinfo->tpi_myname = PI_NO;
1445 } else if (iocbp->ioc_cmd == TI_GETPEERNAME) {
1446 if (tp->tim_provinfo->tpi_peername == PI_DONTKNOW)
1447 tp->tim_provinfo->tpi_peername = PI_NO;
1448 }
1449 PI_PROVUNLOCK(tp->tim_provinfo);
1450 /* tim_iocsave may already be overwritten. */
1451 if ((tp->tim_iocsave != NULL) &&
1452 (tp->tim_saved_prim == -1)) {
1453 freemsg(mp);
1454 mp = tp->tim_iocsave;
1455 tp->tim_iocsave = NULL;
1456 tp->tim_flags |= NAMEPROC;
1457 if (ti_doname(WR(q), mp) != DONAME_CONT) {
1458 tp->tim_flags &= ~NAMEPROC;
1459 }
1460 break;
1461 }
1462 }
1463 putnext(q, mp);
1464 break;
1465 /* ONC_PLUS EXTRACT END */
1466 }
1467
1468 return (0);
1469 }
1470
1471 /* ONC_PLUS EXTRACT START */
1472 /*
1473 * timodwput - Module write put procedure. This is called from
1474 * the module, driver, or stream head upstream/downstream.
1475 * Handles M_FLUSH, M_DATA and some M_PROTO (T_DATA_REQ,
1476 * and T_UNITDATA_REQ) messages. All others are queued to
1477 * be handled by the service procedures.
1478 */
1479
1480 static void
timodwput(queue_t * q,mblk_t * mp)1481 timodwput(queue_t *q, mblk_t *mp)
1482 {
1483 union T_primitives *pptr;
1484 struct tim_tim *tp;
1485 struct iocblk *iocbp;
1486
1487 /*
1488 * Enqueue normal-priority messages if our queue already
1489 * holds some messages for deferred processing but don't
1490 * enqueue those M_IOCTLs which will result in an
1491 * M_PCPROTO (ie, high priority) message being created.
1492 */
1493 /* ONC_PLUS EXTRACT END */
1494 if (q->q_first != 0 && mp->b_datap->db_type < QPCTL) {
1495 if (mp->b_datap->db_type == M_IOCTL) {
1496 iocbp = (struct iocblk *)mp->b_rptr;
1497 switch (iocbp->ioc_cmd) {
1498 default:
1499 (void) putq(q, mp);
1500 return;
1501
1502 case TI_GETINFO:
1503 case TI_SYNC:
1504 case TI_CAPABILITY:
1505 break;
1506 }
1507 } else {
1508 (void) putq(q, mp);
1509 return;
1510 }
1511 }
1512 /* ONC_PLUS EXTRACT START */
1513 /*
1514 * Inline processing of data (to avoid additional procedure call).
1515 * Rest is handled in timodwproc.
1516 */
1517
1518 switch (mp->b_datap->db_type) {
1519 case M_DATA:
1520 tp = (struct tim_tim *)q->q_ptr;
1521 ASSERT(tp);
1522 if (tp->tim_flags & CLTS) {
1523 mblk_t *tmp;
1524
1525 if ((tmp = tim_filladdr(q, mp, B_FALSE)) == NULL) {
1526 (void) putq(q, mp);
1527 break;
1528 } else {
1529 mp = tmp;
1530 }
1531 }
1532 if (bcanputnext(q, mp->b_band))
1533 putnext(q, mp);
1534 else
1535 (void) putq(q, mp);
1536 break;
1537 case M_PROTO:
1538 case M_PCPROTO:
1539 pptr = (union T_primitives *)mp->b_rptr;
1540 switch (pptr->type) {
1541 /* ONC_PLUS EXTRACT END */
1542 case T_UNITDATA_REQ:
1543 tp = (struct tim_tim *)q->q_ptr;
1544 ASSERT(tp);
1545 if (tp->tim_flags & CLTS) {
1546 mblk_t *tmp;
1547
1548 tmp = tim_filladdr(q, mp, B_FALSE);
1549 if (tmp == NULL) {
1550 (void) putq(q, mp);
1551 break;
1552 } else {
1553 mp = tmp;
1554 }
1555 }
1556 if (bcanputnext(q, mp->b_band))
1557 putnext(q, mp);
1558 else
1559 (void) putq(q, mp);
1560 break;
1561
1562 case T_DATA_REQ:
1563 case T_EXDATA_REQ:
1564 if (bcanputnext(q, mp->b_band))
1565 putnext(q, mp);
1566 else
1567 (void) putq(q, mp);
1568 break;
1569 default:
1570 (void) timodwproc(q, mp);
1571 break;
1572 }
1573 break;
1574 /* ONC_PLUS EXTRACT START */
1575 default:
1576 (void) timodwproc(q, mp);
1577 break;
1578 }
1579 }
1580 /*
1581 * timodwsrv - Module write queue service procedure.
1582 * This is called when messages are placed on an empty queue,
1583 * when high priority messages are placed on the queue, and
1584 * when flow control restrictions subside. This code used to
1585 * be included in a put procedure, but it was moved to a
1586 * service procedure because several points were added where
1587 * memory allocation could fail, and there is no reasonable
1588 * recovery mechanism from the put procedure.
1589 */
1590 static void
timodwsrv(queue_t * q)1591 timodwsrv(queue_t *q)
1592 {
1593 mblk_t *mp;
1594
1595 ASSERT(q != NULL);
1596 if (q->q_ptr == NULL)
1597 return;
1598
1599 while ((mp = getq(q)) != NULL) {
1600 if (timodwproc(q, mp)) {
1601 /*
1602 * timodwproc did a putbq - stop processing
1603 * messages.
1604 */
1605 return;
1606 }
1607 }
1608 }
1609
1610 /*
1611 * Common routine to process write side messages
1612 */
1613
1614 static int
timodwproc(queue_t * q,mblk_t * mp)1615 timodwproc(queue_t *q, mblk_t *mp)
1616 {
1617 union T_primitives *pptr;
1618 struct tim_tim *tp;
1619 uint32_t auditing = AU_AUDITING();
1620 mblk_t *tmp;
1621 struct iocblk *iocbp;
1622 int error;
1623
1624 tp = (struct tim_tim *)q->q_ptr;
1625
1626 switch (mp->b_datap->db_type) {
1627 default:
1628 putnext(q, mp);
1629 break;
1630 /* ONC_PLUS EXTRACT END */
1631
1632 case M_DATA:
1633 if (tp->tim_flags & CLTS) {
1634 if ((tmp = tim_filladdr(q, mp, B_TRUE)) == NULL) {
1635 return (1);
1636 } else {
1637 mp = tmp;
1638 }
1639 }
1640 if (!bcanputnext(q, mp->b_band)) {
1641 (void) putbq(q, mp);
1642 return (1);
1643 }
1644 putnext(q, mp);
1645 break;
1646
1647 /* ONC_PLUS EXTRACT START */
1648 case M_IOCTL:
1649
1650 iocbp = (struct iocblk *)mp->b_rptr;
1651 TILOG("timodwproc: Got M_IOCTL(%d)\n", iocbp->ioc_cmd);
1652
1653 ASSERT(MBLKL(mp) == sizeof (struct iocblk));
1654
1655 /*
1656 * TPI requires we await response to a previously sent message
1657 * before handling another, put it back on the head of queue.
1658 * Since putbq() may see QWANTR unset when called from the
1659 * service procedure, the queue must be explicitly scheduled
1660 * for service, as no backenable will occur for this case.
1661 * tim_ioctl_retry() sets a timer to handle the qenable.
1662 */
1663 if (tp->tim_flags & WAITIOCACK) {
1664 TILOG("timodwproc: putbq M_IOCTL(%d)\n",
1665 iocbp->ioc_cmd);
1666 (void) putbq(q, mp);
1667 /* Called from timodwsrv() and messages on queue */
1668 if (!(q->q_flag & QWANTR))
1669 tim_ioctl_retry(q);
1670 return (1);
1671 }
1672 /* ONC_PLUS EXTRACT END */
1673
1674 switch (iocbp->ioc_cmd) {
1675 default:
1676 putnext(q, mp);
1677 break;
1678
1679 case _I_GETPEERCRED:
1680 if ((tp->tim_flags & COTS) == 0) {
1681 miocnak(q, mp, 0, ENOTSUP);
1682 } else {
1683 mblk_t *cmp = mp->b_cont;
1684 k_peercred_t *kp = NULL;
1685
1686 mutex_enter(&tp->tim_mutex);
1687 if (cmp != NULL &&
1688 iocbp->ioc_flag == IOC_NATIVE &&
1689 (tp->tim_flags &
1690 (CONNWAIT|LOCORDREL|REMORDREL)) == 0 &&
1691 tp->tim_peercred != NULL &&
1692 DB_TYPE(cmp) == M_DATA &&
1693 MBLKL(cmp) == sizeof (k_peercred_t)) {
1694 kp = (k_peercred_t *)cmp->b_rptr;
1695 crhold(kp->pc_cr = tp->tim_peercred);
1696 kp->pc_cpid = tp->tim_cpid;
1697 }
1698 mutex_exit(&tp->tim_mutex);
1699 if (kp != NULL)
1700 miocack(q, mp, sizeof (*kp), 0);
1701 else
1702 miocnak(q, mp, 0, ENOTCONN);
1703 }
1704 break;
1705 case TI_BIND:
1706 case TI_UNBIND:
1707 case TI_OPTMGMT:
1708 case TI_GETADDRS:
1709 TILOG("timodwproc: TI_{BIND|UNBIND|OPTMGMT|GETADDRS}"
1710 "\n", 0);
1711
1712 /*
1713 * We know that tim_send_ioctl_tpi_msg() is only
1714 * going to examine the `type' field, so we only
1715 * check that we can access that much data.
1716 */
1717 error = miocpullup(mp, sizeof (t_scalar_t));
1718 if (error != 0) {
1719 miocnak(q, mp, 0, error);
1720 break;
1721 }
1722 tim_send_ioctl_tpi_msg(q, mp, tp, iocbp);
1723 break;
1724
1725 case TI_GETINFO:
1726 TILOG("timodwproc: TI_GETINFO\n", 0);
1727 error = miocpullup(mp, sizeof (struct T_info_req));
1728 if (error != 0) {
1729 miocnak(q, mp, 0, error);
1730 break;
1731 }
1732 tp->tim_flags |= WAIT_IOCINFOACK;
1733 tim_send_ioctl_tpi_msg(q, mp, tp, iocbp);
1734 break;
1735
1736 case TI_SYNC: {
1737 mblk_t *tsr_mp;
1738 struct ti_sync_req *tsr;
1739 uint32_t tsr_flags;
1740
1741 error = miocpullup(mp, sizeof (struct ti_sync_req));
1742 if (error != 0) {
1743 miocnak(q, mp, 0, error);
1744 break;
1745 }
1746
1747 tsr_mp = mp->b_cont;
1748 tsr = (struct ti_sync_req *)tsr_mp->b_rptr;
1749 TILOG("timodwproc: TI_SYNC(%x)\n", tsr->tsr_flags);
1750
1751 /*
1752 * Save out the value of tsr_flags, in case we
1753 * reallocb() tsr_mp (below).
1754 */
1755 tsr_flags = tsr->tsr_flags;
1756 if ((tsr_flags & TSRF_INFO_REQ) == 0) {
1757 mblk_t *ack_mp = reallocb(tsr_mp,
1758 sizeof (struct ti_sync_ack), 0);
1759
1760 /* Can reply immediately. */
1761 mp->b_cont = NULL;
1762 if (ack_mp == NULL) {
1763 tilog("timodwproc: allocb failed no "
1764 "recovery attempt\n", 0);
1765 freemsg(tsr_mp);
1766 miocnak(q, mp, 0, ENOMEM);
1767 } else {
1768 tim_answer_ti_sync(q, mp, tp,
1769 ack_mp, tsr_flags);
1770 }
1771 break;
1772 }
1773
1774 /*
1775 * This code is retained for compatibility with
1776 * old statically linked applications. New code
1777 * should use TI_CAPABILITY for all TPI
1778 * information and should not use TSRF_INFO_REQ
1779 * flag.
1780 *
1781 * defer processsing necessary to rput procedure
1782 * as we need to get information from transport
1783 * driver. Set flags that will tell the read
1784 * side the work needed on this request.
1785 */
1786
1787 if (tsr_flags & TSRF_IS_EXP_IN_RCVBUF)
1788 tp->tim_flags |= PEEK_RDQ_EXPIND;
1789
1790 /*
1791 * Convert message to a T_INFO_REQ message; relies
1792 * on sizeof (struct ti_sync_req) >= sizeof (struct
1793 * T_info_req)).
1794 */
1795 ASSERT(MBLKL(tsr_mp) >= sizeof (struct T_info_req));
1796
1797 ((struct T_info_req *)tsr_mp->b_rptr)->PRIM_type =
1798 T_INFO_REQ;
1799 tsr_mp->b_wptr = tsr_mp->b_rptr +
1800 sizeof (struct T_info_req);
1801 tp->tim_flags |= WAIT_IOCINFOACK;
1802 tim_send_ioctl_tpi_msg(q, mp, tp, iocbp);
1803 }
1804 break;
1805
1806 case TI_CAPABILITY: {
1807 mblk_t *tcsr_mp;
1808 struct T_capability_req *tcr;
1809
1810 error = miocpullup(mp, sizeof (*tcr));
1811 if (error != 0) {
1812 miocnak(q, mp, 0, error);
1813 break;
1814 }
1815
1816 tcsr_mp = mp->b_cont;
1817 tcr = (struct T_capability_req *)tcsr_mp->b_rptr;
1818 TILOG("timodwproc: TI_CAPABILITY(CAP_bits1 = %x)\n",
1819 tcr->CAP_bits1);
1820
1821 if (tcr->PRIM_type != T_CAPABILITY_REQ) {
1822 TILOG("timodwproc: invalid msg type %d\n",
1823 tcr->PRIM_type);
1824 miocnak(q, mp, 0, EPROTO);
1825 break;
1826 }
1827
1828 switch (tp->tim_provinfo->tpi_capability) {
1829 case PI_YES:
1830 /* Just send T_CAPABILITY_REQ down */
1831 tim_send_ioctl_tpi_msg(q, mp, tp, iocbp);
1832 break;
1833
1834 case PI_DONTKNOW:
1835 /*
1836 * It is unknown yet whether transport provides
1837 * T_CAPABILITY_REQ or not. Send message down
1838 * and wait for reply.
1839 */
1840
1841 ASSERT(tp->tim_tcap_timoutid == 0);
1842 if ((tcr->CAP_bits1 & TC1_INFO) == 0) {
1843 tp->tim_flags |= TI_CAP_RECVD;
1844 } else {
1845 tp->tim_flags |= (TI_CAP_RECVD |
1846 CAP_WANTS_INFO);
1847 }
1848
1849 tp->tim_tcap_timoutid = qtimeout(q,
1850 tim_tcap_timer, q, tim_tcap_wait * hz);
1851 tim_send_ioctl_tpi_msg(q, mp, tp, iocbp);
1852 break;
1853
1854 case PI_NO:
1855 /*
1856 * Transport doesn't support T_CAPABILITY_REQ.
1857 * Either reply immediately or send T_INFO_REQ
1858 * if needed.
1859 */
1860 if ((tcr->CAP_bits1 & TC1_INFO) != 0) {
1861 tp->tim_flags |= (TI_CAP_RECVD |
1862 CAP_WANTS_INFO | WAIT_IOCINFOACK);
1863 TILOG("timodwproc: sending down "
1864 "T_INFO_REQ, flags = %x\n",
1865 tp->tim_flags);
1866
1867 /*
1868 * Generate T_INFO_REQ message and send
1869 * it down
1870 */
1871 ((struct T_info_req *)tcsr_mp->b_rptr)->
1872 PRIM_type = T_INFO_REQ;
1873 tcsr_mp->b_wptr = tcsr_mp->b_rptr +
1874 sizeof (struct T_info_req);
1875 tim_send_ioctl_tpi_msg(q, mp, tp,
1876 iocbp);
1877 break;
1878 }
1879
1880
1881 /*
1882 * Can reply immediately. Just send back
1883 * T_CAPABILITY_ACK with CAP_bits1 set to 0.
1884 */
1885 mp->b_cont = tcsr_mp = tpi_ack_alloc(mp->b_cont,
1886 sizeof (struct T_capability_ack), M_PCPROTO,
1887 T_CAPABILITY_ACK);
1888
1889 if (tcsr_mp == NULL) {
1890 tilog("timodwproc: allocb failed no "
1891 "recovery attempt\n", 0);
1892 miocnak(q, mp, 0, ENOMEM);
1893 break;
1894 }
1895
1896 tp->tim_flags &= ~(WAITIOCACK | TI_CAP_RECVD |
1897 WAIT_IOCINFOACK | CAP_WANTS_INFO);
1898 ((struct T_capability_ack *)
1899 tcsr_mp->b_rptr)->CAP_bits1 = 0;
1900 tim_ioctl_send_reply(q, mp, tcsr_mp);
1901
1902 /*
1903 * It could happen when timod is awaiting ack
1904 * for TI_GETPEERNAME/TI_GETMYNAME.
1905 */
1906 if (tp->tim_iocsave != NULL) {
1907 freemsg(tp->tim_iocsave);
1908 tp->tim_iocsave = NULL;
1909 tp->tim_saved_prim = -1;
1910 }
1911 break;
1912
1913 default:
1914 cmn_err(CE_PANIC,
1915 "timodwproc: unknown tpi_capability value "
1916 "%d\n", tp->tim_provinfo->tpi_capability);
1917 break;
1918 }
1919 }
1920 break;
1921
1922 /* ONC_PLUS EXTRACT START */
1923 case TI_GETMYNAME:
1924
1925 tilog("timodwproc: Got TI_GETMYNAME\n", 0);
1926
1927 if (tp->tim_provinfo->tpi_myname == PI_YES) {
1928 putnext(q, mp);
1929 break;
1930 }
1931 goto getname;
1932
1933 case TI_GETPEERNAME:
1934
1935 tilog("timodwproc: Got TI_GETPEERNAME\n", 0);
1936
1937 if (tp->tim_provinfo->tpi_peername == PI_YES) {
1938 putnext(q, mp);
1939 break;
1940 }
1941 getname:
1942 if ((tmp = copymsg(mp)) == NULL) {
1943 tim_recover(q, mp, msgsize(mp));
1944 return (1);
1945 }
1946 /*
1947 * tim_iocsave may be non-NULL when timod is awaiting
1948 * ack for another TI_GETPEERNAME/TI_GETMYNAME.
1949 */
1950 freemsg(tp->tim_iocsave);
1951 tp->tim_iocsave = mp;
1952 tp->tim_saved_prim = -1;
1953 putnext(q, tmp);
1954 break;
1955 }
1956 break;
1957
1958 case M_IOCDATA:
1959
1960 if (tp->tim_flags & NAMEPROC) {
1961 if (ti_doname(q, mp) != DONAME_CONT) {
1962 tp->tim_flags &= ~NAMEPROC;
1963 }
1964 } else
1965 putnext(q, mp);
1966 break;
1967
1968 case M_PROTO:
1969 case M_PCPROTO:
1970 if (MBLKL(mp) < sizeof (t_scalar_t)) {
1971 merror(q, mp, EPROTO);
1972 return (1);
1973 }
1974
1975 pptr = (union T_primitives *)mp->b_rptr;
1976 switch (pptr->type) {
1977 default:
1978 putnext(q, mp);
1979 break;
1980
1981 case T_EXDATA_REQ:
1982 case T_DATA_REQ:
1983 if (pptr->type == T_EXDATA_REQ)
1984 tilog("timodwproc: Got T_EXDATA_REQ\n", 0);
1985
1986 if (!bcanputnext(q, mp->b_band)) {
1987 (void) putbq(q, mp);
1988 return (1);
1989 }
1990 putnext(q, mp);
1991 break;
1992 /* ONC_PLUS EXTRACT END */
1993
1994 case T_UNITDATA_REQ:
1995 if (tp->tim_flags & CLTS) {
1996 tmp = tim_filladdr(q, mp, B_TRUE);
1997 if (tmp == NULL) {
1998 return (1);
1999 } else {
2000 mp = tmp;
2001 }
2002 }
2003 if (auditing)
2004 audit_sock(T_UNITDATA_REQ, q, mp, TIMOD_ID);
2005 if (!bcanputnext(q, mp->b_band)) {
2006 (void) putbq(q, mp);
2007 return (1);
2008 }
2009 putnext(q, mp);
2010 break;
2011
2012 /* ONC_PLUS EXTRACT START */
2013 case T_CONN_REQ: {
2014 struct T_conn_req *reqp = (struct T_conn_req *)
2015 mp->b_rptr;
2016 void *p;
2017
2018 tilog("timodwproc: Got T_CONN_REQ\n", 0);
2019
2020 if (MBLKL(mp) < sizeof (struct T_conn_req)) {
2021 merror(q, mp, EPROTO);
2022 return (1);
2023 }
2024
2025 if (tp->tim_flags & DO_PEERNAME) {
2026 if (!MBLKIN(mp, reqp->DEST_offset,
2027 reqp->DEST_length)) {
2028 merror(q, mp, EPROTO);
2029 return (1);
2030 }
2031 ASSERT(reqp->DEST_length >= 0);
2032 mutex_enter(&tp->tim_mutex);
2033 if (reqp->DEST_length > tp->tim_peermaxlen) {
2034 p = kmem_alloc(reqp->DEST_length,
2035 KM_NOSLEEP);
2036 if (p == NULL) {
2037 mutex_exit(&tp->tim_mutex);
2038 tilog("timodwproc: kmem_alloc "
2039 "failed, attempting "
2040 "recovery\n", 0);
2041 tim_recover(q, mp,
2042 reqp->DEST_length);
2043 return (1);
2044 }
2045 if (tp->tim_peermaxlen)
2046 kmem_free(tp->tim_peername,
2047 tp->tim_peermaxlen);
2048 tp->tim_peername = p;
2049 tp->tim_peermaxlen = reqp->DEST_length;
2050 }
2051 tp->tim_peerlen = reqp->DEST_length;
2052 p = mp->b_rptr + reqp->DEST_offset;
2053 bcopy(p, tp->tim_peername, tp->tim_peerlen);
2054 mutex_exit(&tp->tim_mutex);
2055 }
2056 if (tp->tim_flags & COTS)
2057 tp->tim_flags |= CONNWAIT;
2058 /* ONC_PLUS EXTRACT END */
2059 if (auditing)
2060 audit_sock(T_CONN_REQ, q, mp, TIMOD_ID);
2061 /* ONC_PLUS EXTRACT START */
2062 putnext(q, mp);
2063 break;
2064 }
2065
2066 case O_T_CONN_RES:
2067 case T_CONN_RES: {
2068 struct T_conn_res *resp;
2069 struct T_conn_ind *indp;
2070 mblk_t *pmp = NULL;
2071 mblk_t *nbp;
2072
2073 if (MBLKL(mp) < sizeof (struct T_conn_res) ||
2074 (tp->tim_flags & WAITIOCACK)) {
2075 merror(q, mp, EPROTO);
2076 return (1);
2077 }
2078
2079 resp = (struct T_conn_res *)mp->b_rptr;
2080 for (tmp = tp->tim_consave; tmp != NULL;
2081 tmp = tmp->b_next) {
2082 indp = (struct T_conn_ind *)tmp->b_rptr;
2083 if (indp->SEQ_number == resp->SEQ_number)
2084 break;
2085 pmp = tmp;
2086 }
2087 if (tmp == NULL)
2088 goto cresout;
2089
2090 if ((nbp = dupb(mp)) == NULL &&
2091 (nbp = copyb(mp)) == NULL) {
2092 tim_recover(q, mp, msgsize(mp));
2093 return (1);
2094 }
2095
2096 if (pmp != NULL)
2097 pmp->b_next = tmp->b_next;
2098 else
2099 tp->tim_consave = tmp->b_next;
2100 tmp->b_next = NULL;
2101
2102 /*
2103 * Construct a list with:
2104 * nbp - copy of user's original request
2105 * tmp - the extracted T_conn_ind
2106 */
2107 nbp->b_cont = tmp;
2108 /*
2109 * tim_iocsave may be non-NULL when timod is awaiting
2110 * ack for TI_GETPEERNAME/TI_GETMYNAME.
2111 */
2112 freemsg(tp->tim_iocsave);
2113 tp->tim_iocsave = nbp;
2114 tp->tim_saved_prim = pptr->type;
2115 tp->tim_flags |= WAIT_CONNRESACK | WAITIOCACK;
2116
2117 cresout:
2118 putnext(q, mp);
2119 break;
2120 }
2121
2122 /* ONC_PLUS EXTRACT END */
2123 case T_DISCON_REQ: {
2124 struct T_discon_req *disp;
2125 struct T_conn_ind *conp;
2126 mblk_t *pmp = NULL;
2127
2128 if (MBLKL(mp) < sizeof (struct T_discon_req)) {
2129 merror(q, mp, EPROTO);
2130 return (1);
2131 }
2132
2133 disp = (struct T_discon_req *)mp->b_rptr;
2134 tp->tim_flags &= ~(CONNWAIT|LOCORDREL|REMORDREL);
2135 tim_clear_peer(tp);
2136
2137 /*
2138 * If we are already connected, there won't
2139 * be any messages on tim_consave.
2140 */
2141 for (tmp = tp->tim_consave; tmp; tmp = tmp->b_next) {
2142 conp = (struct T_conn_ind *)tmp->b_rptr;
2143 if (conp->SEQ_number == disp->SEQ_number)
2144 break;
2145 pmp = tmp;
2146 }
2147 if (tmp) {
2148 if (pmp)
2149 pmp->b_next = tmp->b_next;
2150 else
2151 tp->tim_consave = tmp->b_next;
2152 tmp->b_next = NULL;
2153 freemsg(tmp);
2154 }
2155 putnext(q, mp);
2156 break;
2157 }
2158
2159 case T_ORDREL_REQ:
2160 if (tp->tim_flags & REMORDREL) {
2161 tp->tim_flags &= ~(LOCORDREL|REMORDREL);
2162 tim_clear_peer(tp);
2163 } else {
2164 tp->tim_flags |= LOCORDREL;
2165 }
2166 putnext(q, mp);
2167 break;
2168
2169 case T_CAPABILITY_REQ:
2170 tilog("timodwproc: Got T_CAPABILITY_REQ\n", 0);
2171 /*
2172 * XXX: We may know at this point whether transport
2173 * provides T_CAPABILITY_REQ or not and we may utilise
2174 * this knowledge here.
2175 */
2176 putnext(q, mp);
2177 break;
2178 /* ONC_PLUS EXTRACT START */
2179 }
2180 break;
2181 case M_FLUSH:
2182
2183 tilog("timodwproc: Got M_FLUSH\n", 0);
2184
2185 if (*mp->b_rptr & FLUSHW) {
2186 if (*mp->b_rptr & FLUSHBAND)
2187 flushband(q, *(mp->b_rptr + 1), FLUSHDATA);
2188 else
2189 flushq(q, FLUSHDATA);
2190 }
2191 putnext(q, mp);
2192 break;
2193 }
2194
2195 return (0);
2196 }
2197
2198 static void
tilog(char * str,t_scalar_t arg)2199 tilog(char *str, t_scalar_t arg)
2200 {
2201 if (dotilog) {
2202 if (dotilog & 2)
2203 cmn_err(CE_CONT, str, arg);
2204 if (dotilog & 4)
2205 (void) strlog(TIMOD_ID, -1, 0, SL_TRACE | SL_ERROR,
2206 str, arg);
2207 else
2208 (void) strlog(TIMOD_ID, -1, 0, SL_TRACE, str, arg);
2209 }
2210 }
2211
2212 static void
tilogp(char * str,uintptr_t arg)2213 tilogp(char *str, uintptr_t arg)
2214 {
2215 if (dotilog) {
2216 if (dotilog & 2)
2217 cmn_err(CE_CONT, str, arg);
2218 if (dotilog & 4)
2219 (void) strlog(TIMOD_ID, -1, 0, SL_TRACE | SL_ERROR,
2220 str, arg);
2221 else
2222 (void) strlog(TIMOD_ID, -1, 0, SL_TRACE, str, arg);
2223 }
2224 }
2225
2226
2227 /*
2228 * Process the TI_GETNAME ioctl. If no name exists, return len = 0
2229 * in strbuf structures. The state transitions are determined by what
2230 * is hung of cq_private (cp_private) in the copyresp (copyreq) structure.
2231 * The high-level steps in the ioctl processing are as follows:
2232 *
2233 * 1) we recieve an transparent M_IOCTL with the arg in the second message
2234 * block of the message.
2235 * 2) we send up an M_COPYIN request for the strbuf structure pointed to
2236 * by arg. The block containing arg is hung off cq_private.
2237 * 3) we receive an M_IOCDATA response with cp->cp_private->b_cont == NULL.
2238 * This means that the strbuf structure is found in the message block
2239 * mp->b_cont.
2240 * 4) we send up an M_COPYOUT request with the strbuf message hung off
2241 * cq_private->b_cont. The address we are copying to is strbuf.buf.
2242 * we set strbuf.len to 0 to indicate that we should copy the strbuf
2243 * structure the next time. The message mp->b_cont contains the
2244 * address info.
2245 * 5) we receive an M_IOCDATA with cp_private->b_cont != NULL and
2246 * strbuf.len == 0. Restore strbuf.len to either tp->tim_mylen or
2247 * tp->tim_peerlen.
2248 * 6) we send up an M_COPYOUT request with a copy of the strbuf message
2249 * hung off mp->b_cont. In the strbuf structure in the message hung
2250 * off cq_private->b_cont, we set strbuf.len to 0 and strbuf.maxlen
2251 * to 0. This means that the next step is to ACK the ioctl.
2252 * 7) we receive an M_IOCDATA message with cp_private->b_cont != NULL and
2253 * strbuf.len == 0 and strbuf.maxlen == 0. Free up cp->private and
2254 * send an M_IOCACK upstream, and we are done.
2255 *
2256 */
2257 static int
ti_doname(queue_t * q,mblk_t * mp)2258 ti_doname(
2259 queue_t *q, /* queue message arrived at */
2260 mblk_t *mp) /* M_IOCTL or M_IOCDATA message only */
2261 {
2262 struct iocblk *iocp;
2263 struct copyreq *cqp;
2264 STRUCT_HANDLE(strbuf, sb);
2265 struct copyresp *csp;
2266 int ret;
2267 mblk_t *bp;
2268 struct tim_tim *tp = q->q_ptr;
2269 boolean_t getpeer;
2270
2271 switch (mp->b_datap->db_type) {
2272 case M_IOCTL:
2273 iocp = (struct iocblk *)mp->b_rptr;
2274 if ((iocp->ioc_cmd != TI_GETMYNAME) &&
2275 (iocp->ioc_cmd != TI_GETPEERNAME)) {
2276 tilog("ti_doname: bad M_IOCTL command\n", 0);
2277 miocnak(q, mp, 0, EINVAL);
2278 ret = DONAME_FAIL;
2279 break;
2280 }
2281 if ((iocp->ioc_count != TRANSPARENT)) {
2282 miocnak(q, mp, 0, EINVAL);
2283 ret = DONAME_FAIL;
2284 break;
2285 }
2286
2287 cqp = (struct copyreq *)mp->b_rptr;
2288 cqp->cq_private = mp->b_cont;
2289 cqp->cq_addr = (caddr_t)*(intptr_t *)mp->b_cont->b_rptr;
2290 mp->b_cont = NULL;
2291 cqp->cq_size = SIZEOF_STRUCT(strbuf, iocp->ioc_flag);
2292 cqp->cq_flag = 0;
2293 mp->b_datap->db_type = M_COPYIN;
2294 mp->b_wptr = mp->b_rptr + sizeof (struct copyreq);
2295 qreply(q, mp);
2296 ret = DONAME_CONT;
2297 break;
2298
2299 case M_IOCDATA:
2300 csp = (struct copyresp *)mp->b_rptr;
2301 iocp = (struct iocblk *)mp->b_rptr;
2302 cqp = (struct copyreq *)mp->b_rptr;
2303 if ((csp->cp_cmd != TI_GETMYNAME) &&
2304 (csp->cp_cmd != TI_GETPEERNAME)) {
2305 cmn_err(CE_WARN, "ti_doname: bad M_IOCDATA command\n");
2306 miocnak(q, mp, 0, EINVAL);
2307 ret = DONAME_FAIL;
2308 break;
2309 }
2310 if (csp->cp_rval) { /* error */
2311 freemsg(csp->cp_private);
2312 freemsg(mp);
2313 ret = DONAME_FAIL;
2314 break;
2315 }
2316 ASSERT(csp->cp_private != NULL);
2317 getpeer = csp->cp_cmd == TI_GETPEERNAME;
2318 if (getpeer)
2319 mutex_enter(&tp->tim_mutex);
2320 if (csp->cp_private->b_cont == NULL) { /* got strbuf */
2321 ASSERT(mp->b_cont);
2322 STRUCT_SET_HANDLE(sb, iocp->ioc_flag,
2323 (void *)mp->b_cont->b_rptr);
2324 if (getpeer) {
2325 if (tp->tim_peerlen == 0) {
2326 /* copy just strbuf */
2327 STRUCT_FSET(sb, len, 0);
2328 } else if (tp->tim_peerlen >
2329 STRUCT_FGET(sb, maxlen)) {
2330 mutex_exit(&tp->tim_mutex);
2331 miocnak(q, mp, 0, ENAMETOOLONG);
2332 ret = DONAME_FAIL;
2333 break;
2334 } else {
2335 /* copy buffer */
2336 STRUCT_FSET(sb, len, tp->tim_peerlen);
2337 }
2338 } else {
2339 if (tp->tim_mylen == 0) {
2340 /* copy just strbuf */
2341 STRUCT_FSET(sb, len, 0);
2342 } else if (tp->tim_mylen >
2343 STRUCT_FGET(sb, maxlen)) {
2344 freemsg(csp->cp_private);
2345 miocnak(q, mp, 0, ENAMETOOLONG);
2346 ret = DONAME_FAIL;
2347 break;
2348 } else {
2349 /* copy buffer */
2350 STRUCT_FSET(sb, len, tp->tim_mylen);
2351 }
2352 }
2353 csp->cp_private->b_cont = mp->b_cont;
2354 mp->b_cont = NULL;
2355 }
2356 STRUCT_SET_HANDLE(sb, iocp->ioc_flag,
2357 (void *)csp->cp_private->b_cont->b_rptr);
2358 if (STRUCT_FGET(sb, len) == 0) {
2359 /*
2360 * restore strbuf.len
2361 */
2362 if (getpeer)
2363 STRUCT_FSET(sb, len, tp->tim_peerlen);
2364 else
2365 STRUCT_FSET(sb, len, tp->tim_mylen);
2366
2367 if (getpeer)
2368 mutex_exit(&tp->tim_mutex);
2369 if (STRUCT_FGET(sb, maxlen) == 0) {
2370
2371 /*
2372 * ack the ioctl
2373 */
2374 freemsg(csp->cp_private);
2375 tim_ioctl_send_reply(q, mp, NULL);
2376 ret = DONAME_DONE;
2377 break;
2378 }
2379
2380 if ((bp = allocb(STRUCT_SIZE(sb), BPRI_MED)) == NULL) {
2381
2382 tilog(
2383 "ti_doname: allocb failed no recovery attempt\n", 0);
2384
2385 freemsg(csp->cp_private);
2386 miocnak(q, mp, 0, EAGAIN);
2387 ret = DONAME_FAIL;
2388 break;
2389 }
2390 bp->b_wptr += STRUCT_SIZE(sb);
2391 bcopy(STRUCT_BUF(sb), bp->b_rptr, STRUCT_SIZE(sb));
2392 cqp->cq_addr =
2393 (caddr_t)*(intptr_t *)csp->cp_private->b_rptr;
2394 cqp->cq_size = STRUCT_SIZE(sb);
2395 cqp->cq_flag = 0;
2396 mp->b_datap->db_type = M_COPYOUT;
2397 mp->b_cont = bp;
2398 STRUCT_FSET(sb, len, 0);
2399 STRUCT_FSET(sb, maxlen, 0); /* ack next time around */
2400 qreply(q, mp);
2401 ret = DONAME_CONT;
2402 break;
2403 }
2404
2405 /*
2406 * copy the address to the user
2407 */
2408 if ((bp = allocb((size_t)STRUCT_FGET(sb, len), BPRI_MED))
2409 == NULL) {
2410 if (getpeer)
2411 mutex_exit(&tp->tim_mutex);
2412
2413 tilog("ti_doname: allocb failed no recovery attempt\n",
2414 0);
2415
2416 freemsg(csp->cp_private);
2417 miocnak(q, mp, 0, EAGAIN);
2418 ret = DONAME_FAIL;
2419 break;
2420 }
2421 bp->b_wptr += STRUCT_FGET(sb, len);
2422 if (getpeer) {
2423 bcopy(tp->tim_peername, bp->b_rptr,
2424 STRUCT_FGET(sb, len));
2425 mutex_exit(&tp->tim_mutex);
2426 } else {
2427 bcopy(tp->tim_myname, bp->b_rptr, STRUCT_FGET(sb, len));
2428 }
2429 cqp->cq_addr = (caddr_t)STRUCT_FGETP(sb, buf);
2430 cqp->cq_size = STRUCT_FGET(sb, len);
2431 cqp->cq_flag = 0;
2432 mp->b_datap->db_type = M_COPYOUT;
2433 mp->b_cont = bp;
2434 STRUCT_FSET(sb, len, 0); /* copy the strbuf next time around */
2435 qreply(q, mp);
2436 ret = DONAME_CONT;
2437 break;
2438
2439 default:
2440 tilog("ti_doname: freeing bad message type = %d\n",
2441 mp->b_datap->db_type);
2442 freemsg(mp);
2443 ret = DONAME_FAIL;
2444 break;
2445 }
2446 return (ret);
2447 }
2448
2449 /* ONC_PLUS EXTRACT END */
2450
2451 /*
2452 * Fill in the address of a connectionless data packet if a connect
2453 * had been done on this endpoint.
2454 */
2455 static mblk_t *
tim_filladdr(queue_t * q,mblk_t * mp,boolean_t dorecover)2456 tim_filladdr(queue_t *q, mblk_t *mp, boolean_t dorecover)
2457 {
2458 mblk_t *bp;
2459 struct tim_tim *tp;
2460 struct T_unitdata_req *up;
2461 struct T_unitdata_req *nup;
2462 size_t plen;
2463
2464 tp = (struct tim_tim *)q->q_ptr;
2465 if (mp->b_datap->db_type == M_DATA) {
2466 mutex_enter(&tp->tim_mutex);
2467 bp = allocb(sizeof (struct T_unitdata_req) + tp->tim_peerlen,
2468 BPRI_MED);
2469 if (bp != NULL) {
2470 bp->b_datap->db_type = M_PROTO;
2471 up = (struct T_unitdata_req *)bp->b_rptr;
2472 up->PRIM_type = T_UNITDATA_REQ;
2473 up->DEST_length = tp->tim_peerlen;
2474 bp->b_wptr += sizeof (struct T_unitdata_req);
2475 up->DEST_offset = sizeof (struct T_unitdata_req);
2476 up->OPT_length = 0;
2477 up->OPT_offset = 0;
2478 if (tp->tim_peerlen > 0) {
2479 bcopy(tp->tim_peername, bp->b_wptr,
2480 tp->tim_peerlen);
2481 bp->b_wptr += tp->tim_peerlen;
2482 }
2483 bp->b_cont = mp;
2484 }
2485 } else {
2486 ASSERT(mp->b_datap->db_type == M_PROTO);
2487 up = (struct T_unitdata_req *)mp->b_rptr;
2488 ASSERT(up->PRIM_type == T_UNITDATA_REQ);
2489 if (up->DEST_length != 0)
2490 return (mp);
2491 mutex_enter(&tp->tim_mutex);
2492 bp = allocb(sizeof (struct T_unitdata_req) + up->OPT_length +
2493 tp->tim_peerlen, BPRI_MED);
2494 if (bp != NULL) {
2495 bp->b_datap->db_type = M_PROTO;
2496 nup = (struct T_unitdata_req *)bp->b_rptr;
2497 nup->PRIM_type = T_UNITDATA_REQ;
2498 nup->DEST_length = plen = tp->tim_peerlen;
2499 bp->b_wptr += sizeof (struct T_unitdata_req);
2500 nup->DEST_offset = sizeof (struct T_unitdata_req);
2501 if (plen > 0) {
2502 bcopy(tp->tim_peername, bp->b_wptr, plen);
2503 bp->b_wptr += plen;
2504 }
2505 mutex_exit(&tp->tim_mutex);
2506 if (up->OPT_length == 0) {
2507 nup->OPT_length = 0;
2508 nup->OPT_offset = 0;
2509 } else {
2510 nup->OPT_length = up->OPT_length;
2511 nup->OPT_offset =
2512 sizeof (struct T_unitdata_req) + plen;
2513 bcopy((mp->b_wptr + up->OPT_offset), bp->b_wptr,
2514 up->OPT_length);
2515 bp->b_wptr += up->OPT_length;
2516 }
2517 bp->b_cont = mp->b_cont;
2518 mp->b_cont = NULL;
2519 freeb(mp);
2520 return (bp);
2521 }
2522 }
2523 ASSERT(MUTEX_HELD(&tp->tim_mutex));
2524 if (bp == NULL && dorecover) {
2525 tim_recover(q, mp,
2526 sizeof (struct T_unitdata_req) + tp->tim_peerlen);
2527 }
2528 mutex_exit(&tp->tim_mutex);
2529 return (bp);
2530 }
2531
2532 static void
tim_addlink(struct tim_tim * tp)2533 tim_addlink(struct tim_tim *tp)
2534 {
2535 struct tim_tim **tpp;
2536 struct tim_tim *next;
2537
2538 tpp = &tim_hash[TIM_HASH(tp->tim_acceptor)];
2539 rw_enter(&tim_list_rwlock, RW_WRITER);
2540
2541 if ((next = *tpp) != NULL)
2542 next->tim_ptpn = &tp->tim_next;
2543 tp->tim_next = next;
2544 tp->tim_ptpn = tpp;
2545 *tpp = tp;
2546
2547 tim_cnt++;
2548
2549 rw_exit(&tim_list_rwlock);
2550 }
2551
2552 static void
tim_dellink(struct tim_tim * tp)2553 tim_dellink(struct tim_tim *tp)
2554 {
2555 struct tim_tim *next;
2556
2557 rw_enter(&tim_list_rwlock, RW_WRITER);
2558
2559 if ((next = tp->tim_next) != NULL)
2560 next->tim_ptpn = tp->tim_ptpn;
2561 *(tp->tim_ptpn) = next;
2562
2563 tim_cnt--;
2564
2565 rw_exit(&tim_list_rwlock);
2566 }
2567
2568 static struct tim_tim *
tim_findlink(t_uscalar_t id)2569 tim_findlink(t_uscalar_t id)
2570 {
2571 struct tim_tim *tp;
2572
2573 ASSERT(rw_lock_held(&tim_list_rwlock));
2574
2575 for (tp = tim_hash[TIM_HASH(id)]; tp != NULL; tp = tp->tim_next) {
2576 if (tp->tim_acceptor == id) {
2577 break;
2578 }
2579 }
2580 return (tp);
2581 }
2582
2583 /* ONC_PLUS EXTRACT START */
2584 static void
tim_recover(queue_t * q,mblk_t * mp,t_scalar_t size)2585 tim_recover(queue_t *q, mblk_t *mp, t_scalar_t size)
2586 {
2587 struct tim_tim *tp;
2588 bufcall_id_t bid;
2589 timeout_id_t tid;
2590
2591 tp = (struct tim_tim *)q->q_ptr;
2592
2593 /*
2594 * Avoid re-enabling the queue.
2595 */
2596 if (mp->b_datap->db_type == M_PCPROTO)
2597 mp->b_datap->db_type = M_PROTO;
2598 noenable(q);
2599 (void) putbq(q, mp);
2600
2601 /*
2602 * Make sure there is at most one outstanding request per queue.
2603 */
2604 if (q->q_flag & QREADR) {
2605 if (tp->tim_rtimoutid || tp->tim_rbufcid)
2606 return;
2607 } else {
2608 if (tp->tim_wtimoutid || tp->tim_wbufcid)
2609 return;
2610 }
2611 if (!(bid = qbufcall(RD(q), (size_t)size, BPRI_MED, tim_buffer, q))) {
2612 tid = qtimeout(RD(q), tim_timer, q, TIMWAIT);
2613 if (q->q_flag & QREADR)
2614 tp->tim_rtimoutid = tid;
2615 else
2616 tp->tim_wtimoutid = tid;
2617 } else {
2618 if (q->q_flag & QREADR)
2619 tp->tim_rbufcid = bid;
2620 else
2621 tp->tim_wbufcid = bid;
2622 }
2623 }
2624
2625 /*
2626 * Timod is waiting on a downstream ioctl reply, come back soon
2627 * to reschedule the write side service routine, which will check
2628 * if the ioctl is done and another can proceed.
2629 */
2630 static void
tim_ioctl_retry(queue_t * q)2631 tim_ioctl_retry(queue_t *q)
2632 {
2633 struct tim_tim *tp;
2634
2635 tp = (struct tim_tim *)q->q_ptr;
2636
2637 /*
2638 * Make sure there is at most one outstanding request per wqueue.
2639 */
2640 if (tp->tim_wtimoutid || tp->tim_wbufcid)
2641 return;
2642
2643 tp->tim_wtimoutid = qtimeout(RD(q), tim_timer, q, TIMIOCWAIT);
2644 }
2645
2646 /*
2647 * Inspect the data on read queues starting from read queues passed as
2648 * paramter (timod read queue) and traverse until
2649 * q_next is NULL (stream head). Look for a TPI T_EXDATA_IND message
2650 * reutrn 1 if found, 0 if not found.
2651 */
2652 static int
ti_expind_on_rdqueues(queue_t * rq)2653 ti_expind_on_rdqueues(queue_t *rq)
2654 {
2655 mblk_t *bp;
2656 queue_t *q;
2657
2658 q = rq;
2659 /*
2660 * We are going to walk q_next, so protect stream from plumbing
2661 * changes.
2662 */
2663 claimstr(q);
2664 do {
2665 /*
2666 * Hold QLOCK while referencing data on queues
2667 */
2668 mutex_enter(QLOCK(rq));
2669 bp = rq->q_first;
2670 while (bp != NULL) {
2671 /*
2672 * Walk the messages on the queue looking
2673 * for a possible T_EXDATA_IND
2674 */
2675 if ((bp->b_datap->db_type == M_PROTO) &&
2676 ((bp->b_wptr - bp->b_rptr) >=
2677 sizeof (struct T_exdata_ind)) &&
2678 (((struct T_exdata_ind *)bp->b_rptr)->PRIM_type
2679 == T_EXDATA_IND)) {
2680 /* bp is T_EXDATA_IND */
2681 mutex_exit(QLOCK(rq));
2682 releasestr(q); /* decrement sd_refcnt */
2683 return (1); /* expdata is on a read queue */
2684 }
2685 bp = bp->b_next; /* next message */
2686 }
2687 mutex_exit(QLOCK(rq));
2688 rq = rq->q_next; /* next upstream queue */
2689 } while (rq != NULL);
2690 releasestr(q);
2691 return (0); /* no expdata on read queues */
2692 }
2693
2694 /* ONC_PLUS EXTRACT END */
2695 static void
tim_tcap_timer(void * q_ptr)2696 tim_tcap_timer(void *q_ptr)
2697 {
2698 queue_t *q = (queue_t *)q_ptr;
2699 struct tim_tim *tp = (struct tim_tim *)q->q_ptr;
2700
2701 ASSERT(tp != NULL && tp->tim_tcap_timoutid != 0);
2702 ASSERT((tp->tim_flags & TI_CAP_RECVD) != 0);
2703
2704 tp->tim_tcap_timoutid = 0;
2705 TILOG("tim_tcap_timer: fired\n", 0);
2706 tim_tcap_genreply(q, tp);
2707 }
2708
2709 /*
2710 * tim_tcap_genreply() is called either from timeout routine or when
2711 * T_ERROR_ACK is received. In both cases it means that underlying
2712 * transport doesn't provide T_CAPABILITY_REQ.
2713 */
2714 static void
tim_tcap_genreply(queue_t * q,struct tim_tim * tp)2715 tim_tcap_genreply(queue_t *q, struct tim_tim *tp)
2716 {
2717 mblk_t *mp = tp->tim_iocsave;
2718 struct iocblk *iocbp;
2719
2720 TILOG("timodrproc: tim_tcap_genreply\n", 0);
2721
2722 ASSERT(tp == (struct tim_tim *)q->q_ptr);
2723 ASSERT(mp != NULL);
2724
2725 iocbp = (struct iocblk *)mp->b_rptr;
2726 ASSERT(iocbp != NULL);
2727 ASSERT(MBLKL(mp) == sizeof (struct iocblk));
2728 ASSERT(iocbp->ioc_cmd == TI_CAPABILITY);
2729 ASSERT(mp->b_cont == NULL);
2730
2731 /* Save this information permanently in the module */
2732 PI_PROVLOCK(tp->tim_provinfo);
2733 if (tp->tim_provinfo->tpi_capability == PI_DONTKNOW)
2734 tp->tim_provinfo->tpi_capability = PI_NO;
2735 PI_PROVUNLOCK(tp->tim_provinfo);
2736
2737 if (tp->tim_tcap_timoutid != 0) {
2738 (void) quntimeout(q, tp->tim_tcap_timoutid);
2739 tp->tim_tcap_timoutid = 0;
2740 }
2741
2742 if ((tp->tim_flags & CAP_WANTS_INFO) != 0) {
2743 /* Send T_INFO_REQ down */
2744 mblk_t *tirmp = tpi_ack_alloc(NULL,
2745 sizeof (struct T_info_req), M_PCPROTO, T_INFO_REQ);
2746
2747 if (tirmp != NULL) {
2748 /* Emulate TC1_INFO */
2749 TILOG("emulate_tcap_ioc_req: sending T_INFO_REQ\n", 0);
2750 tp->tim_flags |= WAIT_IOCINFOACK;
2751 putnext(WR(q), tirmp);
2752 } else {
2753 tilog("emulate_tcap_req: allocb fail, "
2754 "no recovery attmpt\n", 0);
2755 tp->tim_iocsave = NULL;
2756 tp->tim_saved_prim = -1;
2757 tp->tim_flags &= ~(TI_CAP_RECVD | WAITIOCACK |
2758 CAP_WANTS_INFO | WAIT_IOCINFOACK);
2759 miocnak(q, mp, 0, ENOMEM);
2760 }
2761 } else {
2762 /* Reply immediately */
2763 mblk_t *ackmp = tpi_ack_alloc(NULL,
2764 sizeof (struct T_capability_ack), M_PCPROTO,
2765 T_CAPABILITY_ACK);
2766
2767 mp->b_cont = ackmp;
2768
2769 if (ackmp != NULL) {
2770 ((struct T_capability_ack *)
2771 ackmp->b_rptr)->CAP_bits1 = 0;
2772 tim_ioctl_send_reply(q, mp, ackmp);
2773 tp->tim_iocsave = NULL;
2774 tp->tim_saved_prim = -1;
2775 tp->tim_flags &= ~(WAITIOCACK | WAIT_IOCINFOACK |
2776 TI_CAP_RECVD | CAP_WANTS_INFO);
2777 } else {
2778 tilog("timodwproc:allocb failed no "
2779 "recovery attempt\n", 0);
2780 tp->tim_iocsave = NULL;
2781 tp->tim_saved_prim = -1;
2782 tp->tim_flags &= ~(TI_CAP_RECVD | WAITIOCACK |
2783 CAP_WANTS_INFO | WAIT_IOCINFOACK);
2784 miocnak(q, mp, 0, ENOMEM);
2785 }
2786 }
2787 }
2788
2789
2790 static void
tim_ioctl_send_reply(queue_t * q,mblk_t * ioc_mp,mblk_t * mp)2791 tim_ioctl_send_reply(queue_t *q, mblk_t *ioc_mp, mblk_t *mp)
2792 {
2793 struct iocblk *iocbp;
2794
2795 ASSERT(q != NULL && ioc_mp != NULL);
2796
2797 ioc_mp->b_datap->db_type = M_IOCACK;
2798 if (mp != NULL)
2799 mp->b_datap->db_type = M_DATA;
2800
2801 if (ioc_mp->b_cont != mp) {
2802 /* It is safe to call freemsg for NULL pointers */
2803 freemsg(ioc_mp->b_cont);
2804 ioc_mp->b_cont = mp;
2805 }
2806 iocbp = (struct iocblk *)ioc_mp->b_rptr;
2807 iocbp->ioc_error = 0;
2808 iocbp->ioc_rval = 0;
2809 /*
2810 * All ioctl's may return more data than was specified by
2811 * count arg. For TI_CAPABILITY count is treated as maximum data size.
2812 */
2813 if (mp == NULL)
2814 iocbp->ioc_count = 0;
2815 else if (iocbp->ioc_cmd != TI_CAPABILITY)
2816 iocbp->ioc_count = msgsize(mp);
2817 else {
2818 iocbp->ioc_count = MIN(MBLKL(mp), iocbp->ioc_count);
2819 /* Truncate message if too large */
2820 mp->b_wptr = mp->b_rptr + iocbp->ioc_count;
2821 }
2822
2823 TILOG("iosendreply: ioc_cmd = %d, ", iocbp->ioc_cmd);
2824 putnext(RD(q), ioc_mp);
2825 }
2826
2827 /*
2828 * Send M_IOCACK for errors.
2829 */
2830 static void
tim_send_ioc_error_ack(queue_t * q,struct tim_tim * tp,mblk_t * mp)2831 tim_send_ioc_error_ack(queue_t *q, struct tim_tim *tp, mblk_t *mp)
2832 {
2833 struct T_error_ack *tea = (struct T_error_ack *)mp->b_rptr;
2834 t_scalar_t error_prim;
2835
2836 mp->b_wptr = mp->b_rptr + sizeof (struct T_error_ack);
2837 ASSERT(mp->b_wptr <= mp->b_datap->db_lim);
2838 error_prim = tea->ERROR_prim;
2839
2840 ASSERT(tp->tim_iocsave != NULL);
2841 ASSERT(tp->tim_iocsave->b_cont != mp);
2842
2843 /* Always send this to the read side of the queue */
2844 q = RD(q);
2845
2846 TILOG("tim_send_ioc_error_ack: prim = %d\n", tp->tim_saved_prim);
2847
2848 if (tp->tim_saved_prim != error_prim) {
2849 putnext(q, mp);
2850 } else if (error_prim == T_CAPABILITY_REQ) {
2851 TILOG("timodrproc: T_ERROR_ACK/T_CAPABILITY_REQ\n", 0);
2852 ASSERT(tp->tim_iocsave->b_cont == NULL);
2853
2854 tim_tcap_genreply(q, tp);
2855 freemsg(mp);
2856 } else {
2857 struct iocblk *iocbp = (struct iocblk *)tp->tim_iocsave->b_rptr;
2858
2859 TILOG("tim_send_ioc_error_ack: T_ERROR_ACK: prim %d\n",
2860 error_prim);
2861 ASSERT(tp->tim_iocsave->b_cont == NULL);
2862
2863 switch (error_prim) {
2864 default:
2865 TILOG("timodrproc: Unknown T_ERROR_ACK: tlierror %d\n",
2866 tea->TLI_error);
2867
2868 putnext(q, mp);
2869 break;
2870
2871 case T_INFO_REQ:
2872 case T_SVR4_OPTMGMT_REQ:
2873 case T_OPTMGMT_REQ:
2874 case O_T_BIND_REQ:
2875 case T_BIND_REQ:
2876 case T_UNBIND_REQ:
2877 case T_ADDR_REQ:
2878 case T_CAPABILITY_REQ:
2879
2880 TILOG("ioc_err_ack: T_ERROR_ACK: tlierror %x\n",
2881 tea->TLI_error);
2882
2883 /* get saved ioctl msg and set values */
2884 iocbp->ioc_count = 0;
2885 iocbp->ioc_error = 0;
2886 iocbp->ioc_rval = tea->TLI_error;
2887 if (iocbp->ioc_rval == TSYSERR)
2888 iocbp->ioc_rval |= tea->UNIX_error << 8;
2889 tp->tim_iocsave->b_datap->db_type = M_IOCACK;
2890 freemsg(mp);
2891 putnext(q, tp->tim_iocsave);
2892 tp->tim_iocsave = NULL;
2893 tp->tim_saved_prim = -1;
2894 tp->tim_flags &= ~(WAITIOCACK | TI_CAP_RECVD |
2895 CAP_WANTS_INFO | WAIT_IOCINFOACK);
2896 break;
2897 }
2898 }
2899 }
2900
2901 /*
2902 * Send reply to a usual message or ioctl message upstream.
2903 * Should be called from the read side only.
2904 */
2905 static void
tim_send_reply(queue_t * q,mblk_t * mp,struct tim_tim * tp,t_scalar_t prim)2906 tim_send_reply(queue_t *q, mblk_t *mp, struct tim_tim *tp, t_scalar_t prim)
2907 {
2908 ASSERT(mp != NULL && q != NULL && tp != NULL);
2909 ASSERT(q == RD(q));
2910
2911 /* Restore db_type - recover() might have changed it */
2912 mp->b_datap->db_type = M_PCPROTO;
2913
2914 if (((tp->tim_flags & WAITIOCACK) == 0) || (tp->tim_saved_prim != prim))
2915 putnext(q, mp);
2916 else {
2917 ASSERT(tp->tim_iocsave != NULL);
2918 tim_ioctl_send_reply(q, tp->tim_iocsave, mp);
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);
2923 }
2924 }
2925
2926 /*
2927 * Reply to TI_SYNC reequest without sending anything downstream.
2928 */
2929 static void
tim_answer_ti_sync(queue_t * q,mblk_t * mp,struct tim_tim * tp,mblk_t * ackmp,uint32_t tsr_flags)2930 tim_answer_ti_sync(queue_t *q, mblk_t *mp, struct tim_tim *tp,
2931 mblk_t *ackmp, uint32_t tsr_flags)
2932 {
2933 struct ti_sync_ack *tsap;
2934
2935 ASSERT(q != NULL && q == WR(q) && ackmp != NULL);
2936
2937 tsap = (struct ti_sync_ack *)ackmp->b_rptr;
2938 bzero(tsap, sizeof (struct ti_sync_ack));
2939 ackmp->b_wptr = ackmp->b_rptr + sizeof (struct ti_sync_ack);
2940
2941 if (tsr_flags == 0 ||
2942 (tsr_flags & ~(TSRF_QLEN_REQ | TSRF_IS_EXP_IN_RCVBUF)) != 0) {
2943 /*
2944 * unsupported/bad flag setting
2945 * or no flag set.
2946 */
2947 TILOG("timodwproc: unsupported/bad flag setting %x\n",
2948 tsr_flags);
2949 freemsg(ackmp);
2950 miocnak(q, mp, 0, EINVAL);
2951 return;
2952 }
2953
2954 if ((tsr_flags & TSRF_QLEN_REQ) != 0)
2955 tsap->tsa_qlen = tp->tim_backlog;
2956
2957 if ((tsr_flags & TSRF_IS_EXP_IN_RCVBUF) != 0 &&
2958 ti_expind_on_rdqueues(RD(q))) {
2959 /*
2960 * Expedited data is queued on
2961 * the stream read side
2962 */
2963 tsap->tsa_flags |= TSAF_EXP_QUEUED;
2964 }
2965
2966 tim_ioctl_send_reply(q, mp, ackmp);
2967 tp->tim_iocsave = NULL;
2968 tp->tim_saved_prim = -1;
2969 tp->tim_flags &= ~(WAITIOCACK | WAIT_IOCINFOACK |
2970 TI_CAP_RECVD | CAP_WANTS_INFO);
2971 }
2972
2973 /*
2974 * Send TPI message from IOCTL message, ssave original ioctl header and TPI
2975 * message type. Should be called from write side only.
2976 */
2977 static void
tim_send_ioctl_tpi_msg(queue_t * q,mblk_t * mp,struct tim_tim * tp,struct iocblk * iocb)2978 tim_send_ioctl_tpi_msg(queue_t *q, mblk_t *mp, struct tim_tim *tp,
2979 struct iocblk *iocb)
2980 {
2981 mblk_t *tmp;
2982 int ioc_cmd = iocb->ioc_cmd;
2983
2984 ASSERT(q != NULL && mp != NULL && tp != NULL);
2985 ASSERT(q == WR(q));
2986 ASSERT(mp->b_cont != NULL);
2987
2988 tp->tim_iocsave = mp;
2989 tmp = mp->b_cont;
2990
2991 mp->b_cont = NULL;
2992 tp->tim_flags |= WAITIOCACK;
2993 tp->tim_saved_prim = ((union T_primitives *)tmp->b_rptr)->type;
2994
2995 /*
2996 * For TI_GETINFO, the attached message is a T_INFO_REQ
2997 * For TI_SYNC, we generate the T_INFO_REQ message above
2998 * For TI_CAPABILITY the attached message is either
2999 * T_CAPABILITY_REQ or T_INFO_REQ.
3000 * Among TPI request messages possible,
3001 * T_INFO_REQ/T_CAPABILITY_ACK messages are a M_PCPROTO, rest
3002 * are M_PROTO
3003 */
3004 if (ioc_cmd == TI_GETINFO || ioc_cmd == TI_SYNC ||
3005 ioc_cmd == TI_CAPABILITY) {
3006 tmp->b_datap->db_type = M_PCPROTO;
3007 } else {
3008 tmp->b_datap->db_type = M_PROTO;
3009 }
3010
3011 /* Verify credentials in STREAM */
3012 ASSERT(iocb->ioc_cr == NULL || iocb->ioc_cr == DB_CRED(tmp));
3013
3014 ASSERT(DB_CRED(tmp) != NULL);
3015
3016 TILOG("timodwproc: sending down %d\n", tp->tim_saved_prim);
3017 putnext(q, tmp);
3018 }
3019
3020 static void
tim_clear_peer(struct tim_tim * tp)3021 tim_clear_peer(struct tim_tim *tp)
3022 {
3023 mutex_enter(&tp->tim_mutex);
3024 if (tp->tim_peercred != NULL) {
3025 crfree(tp->tim_peercred);
3026 tp->tim_peercred = NULL;
3027 }
3028 tp->tim_peerlen = 0;
3029 mutex_exit(&tp->tim_mutex);
3030 }
3031