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