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>
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
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
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) {
471 }
472
473 static void
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
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;
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
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
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
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
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);
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 }
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 }
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
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);
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
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
1591 timodwsrv(queue_t *q)
1592 {
1593 mblk_t *mp;
1594
1610 /*
1611 * Common routine to process write side messages
1612 */
1613
1614 static int
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 &&
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) {
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);
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) {
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;
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
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 *
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) {
2563 tim_cnt--;
2564
2565 rw_exit(&tim_list_rwlock);
2566 }
2567
2568 static struct tim_tim *
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
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 */
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
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
|
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 /*
22 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
26 /* All Rights Reserved */
27
28
29 /*
30 * Transport Interface Library cooperating module - issue 2
31 */
32
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>
45 #include <sys/cred.h>
46 #include <sys/cmn_err.h>
47 #include <sys/kmem.h>
48 #include <sys/sysmacros.h>
49 #include <sys/ddi.h>
50 #include <sys/sunddi.h>
51 #include <sys/strsun.h>
52 #include <c2/audit.h>
176 *
177 * There may be 3 states for transport:
178 *
179 * 1) It provides T_CAPABILITY_REQ
180 * 2) It does not provide T_CAPABILITY_REQ
181 * 3) It is not known yet whether transport provides T_CAPABILITY_REQ or not.
182 *
183 * It is assumed that the underlying transport either provides
184 * T_CAPABILITY_REQ or not and this does not changes during the
185 * system lifetime.
186 *
187 */
188 #define PEEK_RDQ_EXPIND 0x0001 /* look for expinds on stream rd queues */
189 #define WAITIOCACK 0x0002 /* waiting for info for ioctl act */
190 #define CLTS 0x0004 /* connectionless transport */
191 #define COTS 0x0008 /* connection-oriented transport */
192 #define CONNWAIT 0x0010 /* waiting for connect confirmation */
193 #define LOCORDREL 0x0020 /* local end has orderly released */
194 #define REMORDREL 0x0040 /* remote end had orderly released */
195 #define NAMEPROC 0x0080 /* processing a NAME ioctl */
196 #define DO_MYNAME 0x0100 /* timod handles TI_GETMYNAME */
197 #define DO_PEERNAME 0x0200 /* timod handles TI_GETPEERNAME */
198 #define TI_CAP_RECVD 0x0400 /* TI_CAPABILITY received */
199 #define CAP_WANTS_INFO 0x0800 /* TI_CAPABILITY has TC1_INFO set */
200 #define WAIT_IOCINFOACK 0x1000 /* T_INFO_REQ generated from ioctl */
201 #define WAIT_CONNRESACK 0x2000 /* waiting for T_OK_ACK to T_CONN_RES */
202
203
204 /* Debugging facilities */
205 /*
206 * Logging needed for debugging timod should only appear in DEBUG kernel.
207 */
208 #ifdef DEBUG
209 #define TILOG(msg, arg) tilog((msg), (arg))
210 #define TILOGP(msg, arg) tilogp((msg), (arg))
211 #else
212 #define TILOG(msg, arg)
213 #define TILOGP(msg, arg)
214 #endif
215
216
292 #define TIM_HASH(id) (((uintptr_t)(id) >> 8) % TIM_HASH_SIZE)
293 #else
294 #define TIM_HASH(id) ((uintptr_t)(id) % TIM_HASH_SIZE)
295 #endif /* _ILP32 */
296 static struct tim_tim *tim_hash[TIM_HASH_SIZE];
297 int tim_cnt = 0;
298
299 static void tilog(char *, t_scalar_t);
300 static void tilogp(char *, uintptr_t);
301 static mblk_t *tim_filladdr(queue_t *, mblk_t *, boolean_t);
302 static void tim_addlink(struct tim_tim *);
303 static void tim_dellink(struct tim_tim *);
304 static struct tim_tim *tim_findlink(t_uscalar_t);
305 static void tim_recover(queue_t *, mblk_t *, t_scalar_t);
306 static void tim_ioctl_retry(queue_t *);
307
308 int dotilog = 0;
309
310 #define TIMOD_ID 3
311
312 static int timodopen(queue_t *, dev_t *, int, int, cred_t *);
313 static int timodclose(queue_t *, int, cred_t *);
314 static void timodwput(queue_t *, mblk_t *);
315 static void timodrput(queue_t *, mblk_t *);
316 static void timodrsrv(queue_t *);
317 static void timodwsrv(queue_t *);
318 static int timodrproc(queue_t *, mblk_t *);
319 static int timodwproc(queue_t *, mblk_t *);
320
321 /* stream data structure definitions */
322
323 static struct module_info timod_info =
324 {TIMOD_ID, "timod", 0, INFPSZ, 512, 128};
325 static struct qinit timodrinit = {
326 (int (*)())timodrput,
327 (int (*)())timodrsrv,
328 timodopen,
329 timodclose,
330 nulldev,
331 &timod_info,
332 NULL
333 };
334 static struct qinit timodwinit = {
335 (int (*)())timodwput,
336 (int (*)())timodwsrv,
337 timodopen,
338 timodclose,
339 nulldev,
340 &timod_info,
341 NULL
342 };
343 static struct streamtab timinfo = { &timodrinit, &timodwinit, NULL, NULL };
344
345 /*
346 * timodopen - open routine gets called when the module gets pushed
347 * onto the stream.
348 */
349 /*ARGSUSED*/
350 static int
351 timodopen(
352 queue_t *q,
353 dev_t *devp,
354 int flag,
355 int sflag,
356 cred_t *crp)
357 {
358 struct tim_tim *tp;
359 struct stroptions *sop;
360 mblk_t *bp;
361
362 ASSERT(q != NULL);
363
364 if (q->q_ptr) {
460 }
461
462 static void
463 tim_buffer(void *arg)
464 {
465 queue_t *q = arg;
466 struct tim_tim *tp = (struct tim_tim *)q->q_ptr;
467
468 ASSERT(tp);
469
470 if (q->q_flag & QREADR) {
471 ASSERT(tp->tim_rbufcid);
472 tp->tim_rbufcid = 0;
473 } else {
474 ASSERT(tp->tim_wbufcid);
475 tp->tim_wbufcid = 0;
476 }
477 enableok(q);
478 qenable(q);
479 }
480
481 /*
482 * timodclose - This routine gets called when the module gets popped
483 * off of the stream.
484 */
485 /*ARGSUSED*/
486 static int
487 timodclose(
488 queue_t *q,
489 int flag,
490 cred_t *crp)
491 {
492 struct tim_tim *tp;
493 mblk_t *mp;
494 mblk_t *nmp;
495
496 ASSERT(q != NULL);
497
498 tp = (struct tim_tim *)q->q_ptr;
499 q->q_ptr = NULL;
608 switch (pptr->type) {
609 case T_EXDATA_IND:
610 case T_DATA_IND:
611 case T_UNITDATA_IND:
612 if (bcanputnext(q, mp->b_band))
613 putnext(q, mp);
614 else
615 (void) putq(q, mp);
616 break;
617 default:
618 (void) timodrproc(q, mp);
619 break;
620 }
621 break;
622 default:
623 (void) timodrproc(q, mp);
624 break;
625 }
626 }
627
628 /*
629 * timodrsrv - Module read queue service procedure. This is called when
630 * messages are placed on an empty queue, when high priority
631 * messages are placed on the queue, and when flow control
632 * restrictions subside. This code used to be included in a
633 * put procedure, but it was moved to a service procedure
634 * because several points were added where memory allocation
635 * could fail, and there is no reasonable recovery mechanism
636 * from the put procedure.
637 */
638 /*ARGSUSED*/
639 static void
640 timodrsrv(queue_t *q)
641 {
642 mblk_t *mp;
643 struct tim_tim *tp;
644
645 ASSERT(q != NULL);
646
647 tp = (struct tim_tim *)q->q_ptr;
648 if (!tp)
649 return;
650
651 while ((mp = getq(q)) != NULL) {
652 if (timodrproc(q, mp)) {
653 /*
654 * timodrproc did a putbq - stop processing
655 * messages.
656 */
657 return;
658 }
659 }
660 }
661
662 /*
663 * Perform common processing when a T_CAPABILITY_ACK or T_INFO_ACK
664 * arrive. Set the queue properties and adjust the tim_flags according
665 * to the service type.
666 */
667 static void
668 timodprocessinfo(queue_t *q, struct tim_tim *tp, struct T_info_ack *tia)
669 {
670 TILOG("timodprocessinfo: strqset(%d)\n", tia->TIDU_size);
671 (void) strqset(q, QMAXPSZ, 0, tia->TIDU_size);
672 (void) strqset(OTHERQ(q), QMAXPSZ, 0, tia->TIDU_size);
673
674 if ((tia->SERV_type == T_COTS) || (tia->SERV_type == T_COTS_ORD))
675 tp->tim_flags = (tp->tim_flags & ~CLTS) | COTS;
676 else if (tia->SERV_type == T_CLTS)
677 tp->tim_flags = (tp->tim_flags & ~COTS) | CLTS;
678 }
679
680 static int
681 timodrproc(queue_t *q, mblk_t *mp)
682 {
683 uint32_t auditing = AU_AUDITING();
684 union T_primitives *pptr;
685 struct tim_tim *tp;
686 struct iocblk *iocbp;
687 mblk_t *nbp;
688 size_t blen;
689
690 tp = (struct tim_tim *)q->q_ptr;
691
692 switch (mp->b_datap->db_type) {
693 default:
694 putnext(q, mp);
695 break;
696
697 case M_ERROR:
698 TILOG("timodrproc: Got M_ERROR, flags = %x\n", tp->tim_flags);
699 /*
700 * There is no specified standard response for driver when it
701 * receives unknown message type and M_ERROR is one
702 * possibility. If we send T_CAPABILITY_REQ down and transport
703 * provider responds with M_ERROR we assume that it doesn't
704 * understand this message type. This assumption may be
705 * sometimes incorrect (transport may reply with M_ERROR for
706 * some other reason) but there is no way for us to distinguish
707 * between different cases. In the worst case timod and everyone
708 * else sharing global transport description with it may end up
709 * emulating T_CAPABILITY_REQ.
710 */
711
752 * was too short, then the message would have
753 * already been putnext'd, and would thus
754 * never appear here. Just the same, the code
755 * below handles the impossible case since
756 * it's easy to do and saves future
757 * maintainers from unfortunate accidents.
758 */
759 ASSERT(mp->b_datap->db_type == M_PROTO);
760 if (mp->b_datap->db_type == M_PROTO &&
761 !bcanputnext(q, mp->b_band)) {
762 (void) putbq(q, mp);
763 return (1);
764 }
765 putnext(q, mp);
766 break;
767 }
768
769 pptr = (union T_primitives *)mp->b_rptr;
770 switch (pptr->type) {
771 default:
772
773 if (auditing)
774 audit_sock(T_UNITDATA_IND, q, mp, TIMOD_ID);
775 putnext(q, mp);
776 break;
777
778 case T_ERROR_ACK:
779 /* Restore db_type - recover() might have changed it */
780 mp->b_datap->db_type = M_PCPROTO;
781 if (blen < sizeof (struct T_error_ack)) {
782 putnext(q, mp);
783 break;
784 }
785
786 tilog("timodrproc: Got T_ERROR_ACK, flags = %x\n",
787 tp->tim_flags);
788
789 if ((tp->tim_flags & WAIT_CONNRESACK) &&
790 tp->tim_saved_prim == pptr->error_ack.ERROR_prim) {
791 tp->tim_flags &=
792 ~(WAIT_CONNRESACK | WAITIOCACK);
793 freemsg(tp->tim_iocsave);
794 tp->tim_iocsave = NULL;
795 tp->tim_saved_prim = -1;
796 putnext(q, mp);
866 ntp->tim_peermaxlen = indp->SRC_length;
867 }
868 ntp->tim_peerlen = indp->SRC_length;
869 ptr = (caddr_t)indp + indp->SRC_offset;
870 bcopy(ptr, ntp->tim_peername, ntp->tim_peerlen);
871
872 mutex_exit(&ntp->tim_mutex);
873
874 cresackout:
875 rw_exit(&tim_list_rwlock);
876 tp->tim_flags &=
877 ~(WAIT_CONNRESACK | WAITIOCACK);
878 freemsg(tp->tim_iocsave);
879 tp->tim_iocsave = NULL;
880 tp->tim_saved_prim = -1;
881 }
882
883 tim_send_reply(q, mp, tp, pptr->ok_ack.CORRECT_prim);
884 break;
885
886 case T_BIND_ACK: {
887 struct T_bind_ack *ackp =
888 (struct T_bind_ack *)mp->b_rptr;
889
890 /* Restore db_type - recover() might have changed it */
891 mp->b_datap->db_type = M_PCPROTO;
892 if (blen < sizeof (*ackp)) {
893 putnext(q, mp);
894 break;
895 }
896
897 /* save negotiated backlog */
898 tp->tim_backlog = ackp->CONIND_number;
899
900 if (((tp->tim_flags & WAITIOCACK) == 0) ||
901 ((tp->tim_saved_prim != O_T_BIND_REQ) &&
902 (tp->tim_saved_prim != T_BIND_REQ))) {
903 putnext(q, mp);
904 break;
905 }
929 ASSERT(tp->tim_mymaxlen >= 0);
930 if (tp->tim_mymaxlen != NULL) {
931 kmem_free(tp->tim_myname,
932 tp->tim_mymaxlen);
933 }
934 tp->tim_myname = p;
935 tp->tim_mymaxlen = ackp->ADDR_length;
936 }
937 tp->tim_mylen = ackp->ADDR_length;
938 bcopy(mp->b_rptr + ackp->ADDR_offset,
939 tp->tim_myname, tp->tim_mylen);
940 }
941 tim_ioctl_send_reply(q, tp->tim_iocsave, mp);
942 tp->tim_iocsave = NULL;
943 tp->tim_saved_prim = -1;
944 tp->tim_flags &= ~(WAITIOCACK | WAIT_IOCINFOACK |
945 TI_CAP_RECVD | CAP_WANTS_INFO);
946 break;
947 }
948
949 case T_OPTMGMT_ACK:
950
951 tilog("timodrproc: Got T_OPTMGMT_ACK\n", 0);
952
953 /* Restore db_type - recover() might have change it */
954 mp->b_datap->db_type = M_PCPROTO;
955
956 if (((tp->tim_flags & WAITIOCACK) == 0) ||
957 ((tp->tim_saved_prim != T_SVR4_OPTMGMT_REQ) &&
958 (tp->tim_saved_prim != T_OPTMGMT_REQ))) {
959 putnext(q, mp);
960 } else {
961 ASSERT(tp->tim_iocsave != NULL);
962 tim_ioctl_send_reply(q, tp->tim_iocsave, mp);
963 tp->tim_iocsave = NULL;
964 tp->tim_saved_prim = -1;
965 tp->tim_flags &= ~(WAITIOCACK |
966 WAIT_IOCINFOACK | TI_CAP_RECVD |
967 CAP_WANTS_INFO);
968 }
1161 }
1162 mp->b_wptr += 2*sizeof (uint32_t);
1163 }
1164 tim_ioctl_send_reply(q, tp->tim_iocsave, mp);
1165 tp->tim_iocsave = NULL;
1166 tp->tim_saved_prim = -1;
1167 tp->tim_flags &= ~(WAITIOCACK | WAIT_IOCINFOACK |
1168 TI_CAP_RECVD | CAP_WANTS_INFO);
1169 break;
1170 }
1171 }
1172
1173 putnext(q, mp);
1174 break;
1175
1176 case T_ADDR_ACK:
1177 tilog("timodrproc: Got T_ADDR_ACK\n", 0);
1178 tim_send_reply(q, mp, tp, T_ADDR_REQ);
1179 break;
1180
1181 case T_CONN_IND: {
1182 struct T_conn_ind *tcip =
1183 (struct T_conn_ind *)mp->b_rptr;
1184
1185 tilog("timodrproc: Got T_CONN_IND\n", 0);
1186
1187 if (blen >= sizeof (*tcip) &&
1188 MBLKIN(mp, tcip->SRC_offset, tcip->SRC_length)) {
1189 if (((nbp = dupmsg(mp)) != NULL) ||
1190 ((nbp = copymsg(mp)) != NULL)) {
1191 nbp->b_next = tp->tim_consave;
1192 tp->tim_consave = nbp;
1193 } else {
1194 tim_recover(q, mp,
1195 (t_scalar_t)sizeof (mblk_t));
1196 return (1);
1197 }
1198 }
1199 if (auditing)
1200 audit_sock(T_CONN_IND, q, mp, TIMOD_ID);
1201 putnext(q, mp);
1202 break;
1203 }
1204
1205 case T_CONN_CON:
1206 mutex_enter(&tp->tim_mutex);
1207 if (tp->tim_peercred != NULL)
1208 crfree(tp->tim_peercred);
1209 tp->tim_peercred = msg_getcred(mp, &tp->tim_cpid);
1210 if (tp->tim_peercred != NULL)
1211 crhold(tp->tim_peercred);
1212 mutex_exit(&tp->tim_mutex);
1213
1214 tilog("timodrproc: Got T_CONN_CON\n", 0);
1215
1216 tp->tim_flags &= ~CONNWAIT;
1217 putnext(q, mp);
1218 break;
1219
1220 case T_DISCON_IND: {
1221 struct T_discon_ind *disp;
1222 struct T_conn_ind *conp;
1223 mblk_t *pbp = NULL;
1224
1297 tp->tim_provinfo->tpi_capability = PI_YES;
1298 PI_PROVUNLOCK(tp->tim_provinfo);
1299
1300 /* Reset possible pending timeout */
1301 if (tp->tim_tcap_timoutid != 0) {
1302 (void) quntimeout(q, tp->tim_tcap_timoutid);
1303 tp->tim_tcap_timoutid = 0;
1304 }
1305
1306 tca = (struct T_capability_ack *)mp->b_rptr;
1307
1308 if (tca->CAP_bits1 & TC1_INFO)
1309 timodprocessinfo(q, tp, &tca->INFO_ack);
1310
1311 tim_send_reply(q, mp, tp, T_CAPABILITY_REQ);
1312 }
1313 break;
1314 }
1315 break;
1316
1317 case M_FLUSH:
1318
1319 tilog("timodrproc: Got M_FLUSH\n", 0);
1320
1321 if (*mp->b_rptr & FLUSHR) {
1322 if (*mp->b_rptr & FLUSHBAND)
1323 flushband(q, *(mp->b_rptr + 1), FLUSHDATA);
1324 else
1325 flushq(q, FLUSHDATA);
1326 }
1327 putnext(q, mp);
1328 break;
1329
1330 case M_IOCACK:
1331 iocbp = (struct iocblk *)mp->b_rptr;
1332
1333 tilog("timodrproc: Got M_IOCACK\n", 0);
1334
1335 if (iocbp->ioc_cmd == TI_GETMYNAME) {
1336
1337 /*
1338 * Transport provider supports this ioctl,
1339 * so I don't have to.
1340 */
1341 if ((tp->tim_flags & DO_MYNAME) != 0) {
1342 tp->tim_flags &= ~DO_MYNAME;
1343 PI_PROVLOCK(tp->tim_provinfo);
1344 tp->tim_provinfo->tpi_myname = PI_YES;
1345 PI_PROVUNLOCK(tp->tim_provinfo);
1346 }
1347
1348 ASSERT(tp->tim_mymaxlen >= 0);
1384 mblk_t *bp;
1385
1386 bp = tp->tim_consave;
1387 while (bp != NULL) {
1388 nbp = bp->b_next;
1389 bp->b_next = NULL;
1390 freemsg(bp);
1391 bp = nbp;
1392 }
1393 tp->tim_consave = NULL;
1394 }
1395 /* tim_iocsave may already be overwritten. */
1396 if (tp->tim_saved_prim == -1) {
1397 freemsg(tp->tim_iocsave);
1398 tp->tim_iocsave = NULL;
1399 }
1400 }
1401 putnext(q, mp);
1402 break;
1403
1404 case M_IOCNAK:
1405
1406 tilog("timodrproc: Got M_IOCNAK\n", 0);
1407
1408 iocbp = (struct iocblk *)mp->b_rptr;
1409 if (((iocbp->ioc_cmd == TI_GETMYNAME) ||
1410 (iocbp->ioc_cmd == TI_GETPEERNAME)) &&
1411 ((iocbp->ioc_error == EINVAL) || (iocbp->ioc_error == 0))) {
1412 PI_PROVLOCK(tp->tim_provinfo);
1413 if (iocbp->ioc_cmd == TI_GETMYNAME) {
1414 if (tp->tim_provinfo->tpi_myname == PI_DONTKNOW)
1415 tp->tim_provinfo->tpi_myname = PI_NO;
1416 } else if (iocbp->ioc_cmd == TI_GETPEERNAME) {
1417 if (tp->tim_provinfo->tpi_peername == PI_DONTKNOW)
1418 tp->tim_provinfo->tpi_peername = PI_NO;
1419 }
1420 PI_PROVUNLOCK(tp->tim_provinfo);
1421 /* tim_iocsave may already be overwritten. */
1422 if ((tp->tim_iocsave != NULL) &&
1423 (tp->tim_saved_prim == -1)) {
1424 freemsg(mp);
1425 mp = tp->tim_iocsave;
1426 tp->tim_iocsave = NULL;
1427 tp->tim_flags |= NAMEPROC;
1428 if (ti_doname(WR(q), mp) != DONAME_CONT) {
1429 tp->tim_flags &= ~NAMEPROC;
1430 }
1431 break;
1432 }
1433 }
1434 putnext(q, mp);
1435 break;
1436 }
1437
1438 return (0);
1439 }
1440
1441 /*
1442 * timodwput - Module write put procedure. This is called from
1443 * the module, driver, or stream head upstream/downstream.
1444 * Handles M_FLUSH, M_DATA and some M_PROTO (T_DATA_REQ,
1445 * and T_UNITDATA_REQ) messages. All others are queued to
1446 * be handled by the service procedures.
1447 */
1448
1449 static void
1450 timodwput(queue_t *q, mblk_t *mp)
1451 {
1452 union T_primitives *pptr;
1453 struct tim_tim *tp;
1454 struct iocblk *iocbp;
1455
1456 /*
1457 * Enqueue normal-priority messages if our queue already
1458 * holds some messages for deferred processing but don't
1459 * enqueue those M_IOCTLs which will result in an
1460 * M_PCPROTO (ie, high priority) message being created.
1461 */
1462 if (q->q_first != 0 && mp->b_datap->db_type < QPCTL) {
1463 if (mp->b_datap->db_type == M_IOCTL) {
1464 iocbp = (struct iocblk *)mp->b_rptr;
1465 switch (iocbp->ioc_cmd) {
1466 default:
1467 (void) putq(q, mp);
1468 return;
1469
1470 case TI_GETINFO:
1471 case TI_SYNC:
1472 case TI_CAPABILITY:
1473 break;
1474 }
1475 } else {
1476 (void) putq(q, mp);
1477 return;
1478 }
1479 }
1480 /*
1481 * Inline processing of data (to avoid additional procedure call).
1482 * Rest is handled in timodwproc.
1483 */
1484
1485 switch (mp->b_datap->db_type) {
1486 case M_DATA:
1487 tp = (struct tim_tim *)q->q_ptr;
1488 ASSERT(tp);
1489 if (tp->tim_flags & CLTS) {
1490 mblk_t *tmp;
1491
1492 if ((tmp = tim_filladdr(q, mp, B_FALSE)) == NULL) {
1493 (void) putq(q, mp);
1494 break;
1495 } else {
1496 mp = tmp;
1497 }
1498 }
1499 if (bcanputnext(q, mp->b_band))
1500 putnext(q, mp);
1501 else
1502 (void) putq(q, mp);
1503 break;
1504 case M_PROTO:
1505 case M_PCPROTO:
1506 pptr = (union T_primitives *)mp->b_rptr;
1507 switch (pptr->type) {
1508 case T_UNITDATA_REQ:
1509 tp = (struct tim_tim *)q->q_ptr;
1510 ASSERT(tp);
1511 if (tp->tim_flags & CLTS) {
1512 mblk_t *tmp;
1513
1514 tmp = tim_filladdr(q, mp, B_FALSE);
1515 if (tmp == NULL) {
1516 (void) putq(q, mp);
1517 break;
1518 } else {
1519 mp = tmp;
1520 }
1521 }
1522 if (bcanputnext(q, mp->b_band))
1523 putnext(q, mp);
1524 else
1525 (void) putq(q, mp);
1526 break;
1527
1528 case T_DATA_REQ:
1529 case T_EXDATA_REQ:
1530 if (bcanputnext(q, mp->b_band))
1531 putnext(q, mp);
1532 else
1533 (void) putq(q, mp);
1534 break;
1535 default:
1536 (void) timodwproc(q, mp);
1537 break;
1538 }
1539 break;
1540 default:
1541 (void) timodwproc(q, mp);
1542 break;
1543 }
1544 }
1545 /*
1546 * timodwsrv - Module write queue service procedure.
1547 * This is called when messages are placed on an empty queue,
1548 * when high priority messages are placed on the queue, and
1549 * when flow control restrictions subside. This code used to
1550 * be included in a put procedure, but it was moved to a
1551 * service procedure because several points were added where
1552 * memory allocation could fail, and there is no reasonable
1553 * recovery mechanism from the put procedure.
1554 */
1555 static void
1556 timodwsrv(queue_t *q)
1557 {
1558 mblk_t *mp;
1559
1575 /*
1576 * Common routine to process write side messages
1577 */
1578
1579 static int
1580 timodwproc(queue_t *q, mblk_t *mp)
1581 {
1582 union T_primitives *pptr;
1583 struct tim_tim *tp;
1584 uint32_t auditing = AU_AUDITING();
1585 mblk_t *tmp;
1586 struct iocblk *iocbp;
1587 int error;
1588
1589 tp = (struct tim_tim *)q->q_ptr;
1590
1591 switch (mp->b_datap->db_type) {
1592 default:
1593 putnext(q, mp);
1594 break;
1595
1596 case M_DATA:
1597 if (tp->tim_flags & CLTS) {
1598 if ((tmp = tim_filladdr(q, mp, B_TRUE)) == NULL) {
1599 return (1);
1600 } else {
1601 mp = tmp;
1602 }
1603 }
1604 if (!bcanputnext(q, mp->b_band)) {
1605 (void) putbq(q, mp);
1606 return (1);
1607 }
1608 putnext(q, mp);
1609 break;
1610
1611 case M_IOCTL:
1612
1613 iocbp = (struct iocblk *)mp->b_rptr;
1614 TILOG("timodwproc: Got M_IOCTL(%d)\n", iocbp->ioc_cmd);
1615
1616 ASSERT(MBLKL(mp) == sizeof (struct iocblk));
1617
1618 /*
1619 * TPI requires we await response to a previously sent message
1620 * before handling another, put it back on the head of queue.
1621 * Since putbq() may see QWANTR unset when called from the
1622 * service procedure, the queue must be explicitly scheduled
1623 * for service, as no backenable will occur for this case.
1624 * tim_ioctl_retry() sets a timer to handle the qenable.
1625 */
1626 if (tp->tim_flags & WAITIOCACK) {
1627 TILOG("timodwproc: putbq M_IOCTL(%d)\n",
1628 iocbp->ioc_cmd);
1629 (void) putbq(q, mp);
1630 /* Called from timodwsrv() and messages on queue */
1631 if (!(q->q_flag & QWANTR))
1632 tim_ioctl_retry(q);
1633 return (1);
1634 }
1635
1636 switch (iocbp->ioc_cmd) {
1637 default:
1638 putnext(q, mp);
1639 break;
1640
1641 case _I_GETPEERCRED:
1642 if ((tp->tim_flags & COTS) == 0) {
1643 miocnak(q, mp, 0, ENOTSUP);
1644 } else {
1645 mblk_t *cmp = mp->b_cont;
1646 k_peercred_t *kp = NULL;
1647
1648 mutex_enter(&tp->tim_mutex);
1649 if (cmp != NULL &&
1650 iocbp->ioc_flag == IOC_NATIVE &&
1651 (tp->tim_flags &
1652 (CONNWAIT|LOCORDREL|REMORDREL)) == 0 &&
1653 tp->tim_peercred != NULL &&
1654 DB_TYPE(cmp) == M_DATA &&
1864 /*
1865 * It could happen when timod is awaiting ack
1866 * for TI_GETPEERNAME/TI_GETMYNAME.
1867 */
1868 if (tp->tim_iocsave != NULL) {
1869 freemsg(tp->tim_iocsave);
1870 tp->tim_iocsave = NULL;
1871 tp->tim_saved_prim = -1;
1872 }
1873 break;
1874
1875 default:
1876 cmn_err(CE_PANIC,
1877 "timodwproc: unknown tpi_capability value "
1878 "%d\n", tp->tim_provinfo->tpi_capability);
1879 break;
1880 }
1881 }
1882 break;
1883
1884 case TI_GETMYNAME:
1885
1886 tilog("timodwproc: Got TI_GETMYNAME\n", 0);
1887
1888 if (tp->tim_provinfo->tpi_myname == PI_YES) {
1889 putnext(q, mp);
1890 break;
1891 }
1892 goto getname;
1893
1894 case TI_GETPEERNAME:
1895
1896 tilog("timodwproc: Got TI_GETPEERNAME\n", 0);
1897
1898 if (tp->tim_provinfo->tpi_peername == PI_YES) {
1899 putnext(q, mp);
1900 break;
1901 }
1902 getname:
1903 if ((tmp = copymsg(mp)) == NULL) {
1933 return (1);
1934 }
1935
1936 pptr = (union T_primitives *)mp->b_rptr;
1937 switch (pptr->type) {
1938 default:
1939 putnext(q, mp);
1940 break;
1941
1942 case T_EXDATA_REQ:
1943 case T_DATA_REQ:
1944 if (pptr->type == T_EXDATA_REQ)
1945 tilog("timodwproc: Got T_EXDATA_REQ\n", 0);
1946
1947 if (!bcanputnext(q, mp->b_band)) {
1948 (void) putbq(q, mp);
1949 return (1);
1950 }
1951 putnext(q, mp);
1952 break;
1953
1954 case T_UNITDATA_REQ:
1955 if (tp->tim_flags & CLTS) {
1956 tmp = tim_filladdr(q, mp, B_TRUE);
1957 if (tmp == NULL) {
1958 return (1);
1959 } else {
1960 mp = tmp;
1961 }
1962 }
1963 if (auditing)
1964 audit_sock(T_UNITDATA_REQ, q, mp, TIMOD_ID);
1965 if (!bcanputnext(q, mp->b_band)) {
1966 (void) putbq(q, mp);
1967 return (1);
1968 }
1969 putnext(q, mp);
1970 break;
1971
1972 case T_CONN_REQ: {
1973 struct T_conn_req *reqp = (struct T_conn_req *)
1974 mp->b_rptr;
1975 void *p;
1976
1977 tilog("timodwproc: Got T_CONN_REQ\n", 0);
1978
1979 if (MBLKL(mp) < sizeof (struct T_conn_req)) {
1980 merror(q, mp, EPROTO);
1981 return (1);
1982 }
1983
1984 if (tp->tim_flags & DO_PEERNAME) {
1985 if (!MBLKIN(mp, reqp->DEST_offset,
1986 reqp->DEST_length)) {
1987 merror(q, mp, EPROTO);
1988 return (1);
1989 }
1990 ASSERT(reqp->DEST_length >= 0);
1991 mutex_enter(&tp->tim_mutex);
1997 tilog("timodwproc: kmem_alloc "
1998 "failed, attempting "
1999 "recovery\n", 0);
2000 tim_recover(q, mp,
2001 reqp->DEST_length);
2002 return (1);
2003 }
2004 if (tp->tim_peermaxlen)
2005 kmem_free(tp->tim_peername,
2006 tp->tim_peermaxlen);
2007 tp->tim_peername = p;
2008 tp->tim_peermaxlen = reqp->DEST_length;
2009 }
2010 tp->tim_peerlen = reqp->DEST_length;
2011 p = mp->b_rptr + reqp->DEST_offset;
2012 bcopy(p, tp->tim_peername, tp->tim_peerlen);
2013 mutex_exit(&tp->tim_mutex);
2014 }
2015 if (tp->tim_flags & COTS)
2016 tp->tim_flags |= CONNWAIT;
2017 if (auditing)
2018 audit_sock(T_CONN_REQ, q, mp, TIMOD_ID);
2019 putnext(q, mp);
2020 break;
2021 }
2022
2023 case O_T_CONN_RES:
2024 case T_CONN_RES: {
2025 struct T_conn_res *resp;
2026 struct T_conn_ind *indp;
2027 mblk_t *pmp = NULL;
2028 mblk_t *nbp;
2029
2030 if (MBLKL(mp) < sizeof (struct T_conn_res) ||
2031 (tp->tim_flags & WAITIOCACK)) {
2032 merror(q, mp, EPROTO);
2033 return (1);
2034 }
2035
2036 resp = (struct T_conn_res *)mp->b_rptr;
2037 for (tmp = tp->tim_consave; tmp != NULL;
2038 tmp = tmp->b_next) {
2059 /*
2060 * Construct a list with:
2061 * nbp - copy of user's original request
2062 * tmp - the extracted T_conn_ind
2063 */
2064 nbp->b_cont = tmp;
2065 /*
2066 * tim_iocsave may be non-NULL when timod is awaiting
2067 * ack for TI_GETPEERNAME/TI_GETMYNAME.
2068 */
2069 freemsg(tp->tim_iocsave);
2070 tp->tim_iocsave = nbp;
2071 tp->tim_saved_prim = pptr->type;
2072 tp->tim_flags |= WAIT_CONNRESACK | WAITIOCACK;
2073
2074 cresout:
2075 putnext(q, mp);
2076 break;
2077 }
2078
2079 case T_DISCON_REQ: {
2080 struct T_discon_req *disp;
2081 struct T_conn_ind *conp;
2082 mblk_t *pmp = NULL;
2083
2084 if (MBLKL(mp) < sizeof (struct T_discon_req)) {
2085 merror(q, mp, EPROTO);
2086 return (1);
2087 }
2088
2089 disp = (struct T_discon_req *)mp->b_rptr;
2090 tp->tim_flags &= ~(CONNWAIT|LOCORDREL|REMORDREL);
2091 tim_clear_peer(tp);
2092
2093 /*
2094 * If we are already connected, there won't
2095 * be any messages on tim_consave.
2096 */
2097 for (tmp = tp->tim_consave; tmp; tmp = tmp->b_next) {
2098 conp = (struct T_conn_ind *)tmp->b_rptr;
2114
2115 case T_ORDREL_REQ:
2116 if (tp->tim_flags & REMORDREL) {
2117 tp->tim_flags &= ~(LOCORDREL|REMORDREL);
2118 tim_clear_peer(tp);
2119 } else {
2120 tp->tim_flags |= LOCORDREL;
2121 }
2122 putnext(q, mp);
2123 break;
2124
2125 case T_CAPABILITY_REQ:
2126 tilog("timodwproc: Got T_CAPABILITY_REQ\n", 0);
2127 /*
2128 * XXX: We may know at this point whether transport
2129 * provides T_CAPABILITY_REQ or not and we may utilise
2130 * this knowledge here.
2131 */
2132 putnext(q, mp);
2133 break;
2134 }
2135 break;
2136 case M_FLUSH:
2137
2138 tilog("timodwproc: Got M_FLUSH\n", 0);
2139
2140 if (*mp->b_rptr & FLUSHW) {
2141 if (*mp->b_rptr & FLUSHBAND)
2142 flushband(q, *(mp->b_rptr + 1), FLUSHDATA);
2143 else
2144 flushq(q, FLUSHDATA);
2145 }
2146 putnext(q, mp);
2147 break;
2148 }
2149
2150 return (0);
2151 }
2152
2153 static void
2384 cqp->cq_addr = (caddr_t)STRUCT_FGETP(sb, buf);
2385 cqp->cq_size = STRUCT_FGET(sb, len);
2386 cqp->cq_flag = 0;
2387 mp->b_datap->db_type = M_COPYOUT;
2388 mp->b_cont = bp;
2389 STRUCT_FSET(sb, len, 0); /* copy the strbuf next time around */
2390 qreply(q, mp);
2391 ret = DONAME_CONT;
2392 break;
2393
2394 default:
2395 tilog("ti_doname: freeing bad message type = %d\n",
2396 mp->b_datap->db_type);
2397 freemsg(mp);
2398 ret = DONAME_FAIL;
2399 break;
2400 }
2401 return (ret);
2402 }
2403
2404
2405 /*
2406 * Fill in the address of a connectionless data packet if a connect
2407 * had been done on this endpoint.
2408 */
2409 static mblk_t *
2410 tim_filladdr(queue_t *q, mblk_t *mp, boolean_t dorecover)
2411 {
2412 mblk_t *bp;
2413 struct tim_tim *tp;
2414 struct T_unitdata_req *up;
2415 struct T_unitdata_req *nup;
2416 size_t plen;
2417
2418 tp = (struct tim_tim *)q->q_ptr;
2419 if (mp->b_datap->db_type == M_DATA) {
2420 mutex_enter(&tp->tim_mutex);
2421 bp = allocb(sizeof (struct T_unitdata_req) + tp->tim_peerlen,
2422 BPRI_MED);
2423 if (bp != NULL) {
2517 tim_cnt--;
2518
2519 rw_exit(&tim_list_rwlock);
2520 }
2521
2522 static struct tim_tim *
2523 tim_findlink(t_uscalar_t id)
2524 {
2525 struct tim_tim *tp;
2526
2527 ASSERT(rw_lock_held(&tim_list_rwlock));
2528
2529 for (tp = tim_hash[TIM_HASH(id)]; tp != NULL; tp = tp->tim_next) {
2530 if (tp->tim_acceptor == id) {
2531 break;
2532 }
2533 }
2534 return (tp);
2535 }
2536
2537 static void
2538 tim_recover(queue_t *q, mblk_t *mp, t_scalar_t size)
2539 {
2540 struct tim_tim *tp;
2541 bufcall_id_t bid;
2542 timeout_id_t tid;
2543
2544 tp = (struct tim_tim *)q->q_ptr;
2545
2546 /*
2547 * Avoid re-enabling the queue.
2548 */
2549 if (mp->b_datap->db_type == M_PCPROTO)
2550 mp->b_datap->db_type = M_PROTO;
2551 noenable(q);
2552 (void) putbq(q, mp);
2553
2554 /*
2555 * Make sure there is at most one outstanding request per queue.
2556 */
2627 */
2628 if ((bp->b_datap->db_type == M_PROTO) &&
2629 ((bp->b_wptr - bp->b_rptr) >=
2630 sizeof (struct T_exdata_ind)) &&
2631 (((struct T_exdata_ind *)bp->b_rptr)->PRIM_type
2632 == T_EXDATA_IND)) {
2633 /* bp is T_EXDATA_IND */
2634 mutex_exit(QLOCK(rq));
2635 releasestr(q); /* decrement sd_refcnt */
2636 return (1); /* expdata is on a read queue */
2637 }
2638 bp = bp->b_next; /* next message */
2639 }
2640 mutex_exit(QLOCK(rq));
2641 rq = rq->q_next; /* next upstream queue */
2642 } while (rq != NULL);
2643 releasestr(q);
2644 return (0); /* no expdata on read queues */
2645 }
2646
2647 static void
2648 tim_tcap_timer(void *q_ptr)
2649 {
2650 queue_t *q = (queue_t *)q_ptr;
2651 struct tim_tim *tp = (struct tim_tim *)q->q_ptr;
2652
2653 ASSERT(tp != NULL && tp->tim_tcap_timoutid != 0);
2654 ASSERT((tp->tim_flags & TI_CAP_RECVD) != 0);
2655
2656 tp->tim_tcap_timoutid = 0;
2657 TILOG("tim_tcap_timer: fired\n", 0);
2658 tim_tcap_genreply(q, tp);
2659 }
2660
2661 /*
2662 * tim_tcap_genreply() is called either from timeout routine or when
2663 * T_ERROR_ACK is received. In both cases it means that underlying
2664 * transport doesn't provide T_CAPABILITY_REQ.
2665 */
2666 static void
|