]> git.saurik.com Git - apple/xnu.git/blob - bsd/netat/atp_write.c
42a16a3977ab5a91b23f12ff4a93f820d74cb3d8
[apple/xnu.git] / bsd / netat / atp_write.c
1 /*
2 * Copyright (c) 2006 Apple Computer, Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_OSREFERENCE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the
10 * License may not be used to create, or enable the creation or
11 * redistribution of, unlawful or unlicensed copies of an Apple operating
12 * system, or to circumvent, violate, or enable the circumvention or
13 * violation of, any terms of an Apple operating system software license
14 * agreement.
15 *
16 * Please obtain a copy of the License at
17 * http://www.opensource.apple.com/apsl/ and read it before using this
18 * file.
19 *
20 * The Original Code and all software distributed under the License are
21 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
22 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
23 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
25 * Please see the License for the specific language governing rights and
26 * limitations under the License.
27 *
28 * @APPLE_LICENSE_OSREFERENCE_HEADER_END@
29 */
30 /*
31 * Copyright (c) 1996-1998 Apple Computer, Inc.
32 * All Rights Reserved.
33 */
34
35 /* Modified for MP, 1996 by Tuyen Nguyen
36 * Modified, March 17, 1997 by Tuyen Nguyen for MacOSX.
37 */
38 #define RESOLVE_DBG
39
40 #include <sys/errno.h>
41 #include <sys/types.h>
42 #include <sys/param.h>
43 #include <machine/spl.h>
44 #include <sys/systm.h>
45 #include <sys/kernel.h>
46 #include <sys/proc.h>
47 #include <sys/filedesc.h>
48 #include <sys/fcntl.h>
49 #include <kern/locks.h>
50 #include <sys/mbuf.h>
51 #include <sys/ioctl.h>
52 #include <sys/malloc.h>
53 #include <sys/socket.h>
54 #include <sys/socketvar.h>
55
56 #include <net/if.h>
57
58 #include <netat/sysglue.h>
59 #include <netat/appletalk.h>
60 #include <netat/ddp.h>
61 #include <netat/at_pcb.h>
62 #include <netat/atp.h>
63 #include <netat/at_var.h>
64 #include <netat/asp.h>
65 #include <netat/at_pat.h>
66 #include <netat/debug.h>
67
68 static int loop_cnt; /* for debugging loops */
69 #define CHK_LOOP(str) { \
70 if (loop_cnt++ > 100) { \
71 kprintf("%s", str); \
72 break; \
73 } \
74 }
75
76 static int atp_pack_bdsp(struct atp_trans *, struct atpBDS *);
77 static int atp_unpack_bdsp(struct atp_state *, gbuf_t *, struct atp_rcb *,
78 int, int);
79 void atp_trp_clock(), asp_clock(), asp_clock_locked(), atp_trp_clock_locked();;
80
81 extern struct atp_rcb_qhead atp_need_rel;
82 extern int atp_inited;
83 extern struct atp_state *atp_used_list;
84 extern asp_scb_t *scb_free_list;
85 extern atlock_t atpgen_lock;
86 extern atlock_t atpall_lock;
87 extern atlock_t atptmo_lock;
88
89 extern gbuf_t *scb_resource_m;
90 extern gbuf_t *atp_resource_m;
91 extern gref_t *atp_inputQ[];
92 extern int atp_pidM[];
93 extern at_ifaddr_t *ifID_home;
94 extern lck_mtx_t * atalk_mutex;
95
96 static struct atp_trans *trp_tmo_list;
97 struct atp_trans *trp_tmo_rcb;
98
99 /* first bds entry gives number of bds entries in total (hack) */
100 #define get_bds_entries(m) \
101 ((gbuf_len(m) > TOTAL_ATP_HDR_SIZE)? \
102 (UAS_VALUE(((struct atpBDS *)(AT_ATP_HDR(m)->data))->bdsDataSz)): 0)
103
104 #define atpBDSsize (sizeof(struct atpBDS)*ATP_TRESP_MAX)
105
106 void atp_link()
107 {
108 trp_tmo_list = 0;
109 trp_tmo_rcb = atp_trans_alloc(0);
110 atp_timout(atp_rcb_timer, trp_tmo_rcb, 10 * HZ);
111 atp_trp_clock((void *)&atp_inited);
112 asp_clock((void *)&atp_inited);
113 }
114
115 void atp_unlink()
116 {
117 untimeout(asp_clock_locked, (void *)&atp_inited);
118 untimeout(atp_trp_clock_locked, (void *)&atp_inited);
119 atp_untimout(atp_rcb_timer, trp_tmo_rcb);
120 trp_tmo_list = 0;
121
122 #ifdef BAD_IDEA
123 /* allocated in asp_scb_alloc(), which is called
124 by asp_open() */
125 if (scb_resource_m) {
126 gbuf_freem(scb_resource_m);
127 scb_resource_m = 0;
128 scb_free_list = 0;
129 }
130 /* allocated in atp_trans_alloc() */
131 if (atp_resource_m) {
132 gbuf_freem(atp_resource_m);
133 atp_resource_m = 0;
134 atp_trans_free_list = 0;
135 }
136 #endif
137 }
138
139 /*
140 * write queue put routine .... filter out other than IOCTLs
141 * Version 1.8 of atp_write.c on 89/02/09 17:53:26
142 */
143
144 void
145 atp_wput(gref, m)
146 register gref_t *gref;
147 register gbuf_t *m;
148 {
149 register ioc_t *iocbp;
150 int i, xcnt, s;
151 struct atp_state *atp;
152 struct atp_trans *trp;
153 struct atp_rcb *rcbp;
154 at_socket skt;
155
156 atp = (struct atp_state *)gref->info;
157 if (atp->dflag)
158 atp = (struct atp_state *)atp->atp_msgq;
159
160 switch(gbuf_type(m)) {
161 case MSG_DATA:
162 if (atp->atp_msgq) {
163 gbuf_freem(m);
164 dPrintf(D_M_ATP, D_L_WARNING,
165 ("atp_wput: atp_msgq discarded\n"));
166 } else
167 atp->atp_msgq = m;
168 break;
169
170 case MSG_IOCTL:
171 /* Need to ensure that all copyin/copyout calls are made at
172 * put routine time which should be in the user context. (true when
173 * we are the stream head). The service routine can be called on an
174 * unpredictable context and copyin/copyout calls will get wrong results
175 * or even panic the kernel.
176 */
177 iocbp = (ioc_t *)gbuf_rptr(m);
178
179 switch (iocbp->ioc_cmd) {
180 case AT_ATP_BIND_REQ:
181 if (gbuf_cont(m) == NULL) {
182 iocbp->ioc_rval = -1;
183 atp_iocnak(atp, m, EINVAL);
184 return;
185 }
186 skt = *(at_socket *)gbuf_rptr(gbuf_cont(m));
187 if ((skt = (at_socket)atp_bind(gref, (unsigned int)skt, 0)) == 0)
188 atp_iocnak(atp, m, EINVAL);
189 else {
190 *(at_socket *)gbuf_rptr(gbuf_cont(m)) = skt;
191 iocbp->ioc_rval = 0;
192 atp_iocack(atp, m);
193 atp_dequeue_atp(atp);
194 }
195 return;
196
197 case AT_ATP_GET_CHANID:
198 if (gbuf_cont(m) == NULL) {
199 iocbp->ioc_rval = -1;
200 atp_iocnak(atp, m, EINVAL);
201 return;
202 }
203 *(gref_t **)gbuf_rptr(gbuf_cont(m)) = gref;
204 atp_iocack(atp, m);
205 return;
206
207 /* not the close and not the tickle(?) */
208 case AT_ATP_ISSUE_REQUEST_DEF:
209 case AT_ATP_ISSUE_REQUEST_DEF_NOTE: {
210 gbuf_t *bds, *tmp, *m2;
211 struct atp_rcb *rcbp;
212 at_ddp_t *ddp;
213 at_atp_t *athp;
214
215 if ((tmp = gbuf_cont(m)) != 0) {
216 if ((bds = gbuf_dupb(tmp)) == NULL) {
217 atp_iocnak(atp, m, ENOBUFS);
218 return;
219 }
220 gbuf_rinc(tmp,atpBDSsize);
221 gbuf_wset(bds,atpBDSsize);
222 iocbp->ioc_count -= atpBDSsize;
223 gbuf_cont(tmp) = bds;
224 }
225
226 /*
227 * send a response to a transaction
228 * first check it out
229 */
230 if (iocbp->ioc_count < TOTAL_ATP_HDR_SIZE) {
231 atp_iocnak(atp, m, EINVAL);
232 break;
233 }
234
235 /*
236 * remove the response from the message
237 */
238 m2 = gbuf_cont(m);
239 gbuf_cont(m) = NULL;
240 iocbp->ioc_count = 0;
241 ddp = AT_DDP_HDR(m2);
242 athp = AT_ATP_HDR(m2);
243 if (atp->atp_msgq) {
244 gbuf_cont(m2) = atp->atp_msgq;
245 atp->atp_msgq = 0;
246 }
247
248 ATDISABLE(s, atp->atp_lock);
249 /*
250 * search for the corresponding rcb
251 */
252 for (rcbp = atp->atp_rcb.head; rcbp; rcbp = rcbp->rc_list.next) {
253 if (rcbp->rc_tid == UAS_VALUE(athp->tid) &&
254 rcbp->rc_socket.node == ddp->dst_node &&
255 rcbp->rc_socket.net == NET_VALUE(ddp->dst_net) &&
256 rcbp->rc_socket.socket == ddp->dst_socket)
257 break;
258 }
259 ATENABLE(s, atp->atp_lock);
260
261 /*
262 * If it has already been sent then return an error
263 */
264 if ((rcbp && rcbp->rc_state != RCB_NOTIFIED) ||
265 (rcbp == NULL && athp->xo)) {
266 atp_iocnak(atp, m, ENOENT);
267 gbuf_freem(m2);
268 return;
269 }
270 if (rcbp == NULL) { /* a response for an ALO transaction */
271 if ((rcbp = atp_rcb_alloc(atp)) == NULL) {
272 atp_iocnak(atp, m, ENOBUFS);
273 gbuf_freem(m2);
274 return;
275 }
276 rcbp->rc_ioctl = 0;
277 rcbp->rc_socket.socket = ddp->dst_socket;
278 rcbp->rc_socket.node = ddp->dst_node;
279 rcbp->rc_socket.net = NET_VALUE(ddp->dst_net);
280 rcbp->rc_tid = UAS_VALUE(athp->tid);
281 rcbp->rc_bitmap = 0xff;
282 rcbp->rc_xo = 0;
283 ATDISABLE(s, atp->atp_lock);
284 rcbp->rc_state = RCB_SENDING;
285 ATP_Q_APPEND(atp->atp_rcb, rcbp, rc_list);
286 ATENABLE(s, atp->atp_lock);
287 }
288 xcnt = get_bds_entries(m2);
289 if ((i = atp_unpack_bdsp(atp, m2, rcbp, xcnt, FALSE))) {
290 if ( !rcbp->rc_xo)
291 atp_rcb_free(rcbp);
292 atp_iocnak(atp, m, i);
293 return;
294 }
295 atp_send_replies(atp, rcbp);
296
297 /*
298 * send the ack back to the responder
299 */
300 atp_iocack(atp, m);
301 return;
302 }
303
304 case AT_ATP_GET_POLL: {
305 if (gbuf_cont(m)) {
306 gbuf_freem(gbuf_cont(m));
307 gbuf_cont(m) = NULL;
308 iocbp->ioc_count = 0;
309 }
310
311 /*
312 * search for a waiting request
313 */
314 ATDISABLE(s, atp->atp_lock);
315 if ((rcbp = atp->atp_attached.head)) {
316 /*
317 * Got one, move it to the active response Q
318 */
319 gbuf_cont(m) = rcbp->rc_ioctl;
320 rcbp->rc_ioctl = NULL;
321 if (rcbp->rc_xo) {
322 ATP_Q_REMOVE(atp->atp_attached, rcbp, rc_list);
323 rcbp->rc_state = RCB_NOTIFIED;
324 ATP_Q_APPEND(atp->atp_rcb, rcbp, rc_list);
325 } else {
326 /* detach rcbp from attached queue,
327 * and free any outstanding resources
328 */
329 atp_rcb_free(rcbp);
330 }
331 ATENABLE(s, atp->atp_lock);
332 atp_iocack(atp, m);
333 } else {
334 /*
335 * None available - can out
336 */
337 ATENABLE(s, atp->atp_lock);
338 atp_iocnak(atp, m, EAGAIN);
339 }
340 break;
341 }
342
343 case AT_ATP_CANCEL_REQUEST: {
344 /*
345 * Cancel a pending request
346 */
347 if (iocbp->ioc_count != sizeof(int)) {
348 atp_iocnak(atp, m, EINVAL);
349 break;
350 }
351 i = *(int *)gbuf_rptr(gbuf_cont(m));
352 gbuf_freem(gbuf_cont(m));
353 gbuf_cont(m) = NULL;
354 ATDISABLE(s, atp->atp_lock);
355 for (trp = atp->atp_trans_wait.head; trp; trp = trp->tr_list.next) {
356 if (trp->tr_tid == i)
357 break;
358 }
359 if (trp == NULL) {
360 ATENABLE(s, atp->atp_lock);
361 atp_iocnak(atp, m, ENOENT);
362 } else {
363 ATENABLE(s, atp->atp_lock);
364 atp_free(trp);
365 atp_iocack(atp, m);
366 }
367 break;
368 }
369
370 case AT_ATP_PEEK: {
371 unsigned char event;
372 if (atalk_peek(gref, &event) == -1)
373 atp_iocnak(atp, m, EAGAIN);
374 else {
375 *gbuf_rptr(gbuf_cont(m)) = event;
376 atp_iocack(atp, m);
377 }
378 break;
379 }
380
381 case DDP_IOC_GET_CFG:
382 #ifdef APPLETALK_DEBUG
383 kprintf("atp_wput: DDP_IOC_GET_CFG\n");
384 #endif
385 if (gbuf_cont(m) == 0) {
386 atp_iocnak(atp, m, EINVAL);
387 break;
388 }
389 {
390 /* *** was ddp_get_cfg() *** */
391 ddp_addr_t *cfgp =
392 (ddp_addr_t *)gbuf_rptr(gbuf_cont(m));
393 cfgp->inet.net = ifID_home->ifThisNode.s_net;
394 cfgp->inet.node = ifID_home->ifThisNode.s_node;
395 cfgp->inet.socket = atp->atp_socket_no;
396 cfgp->ddptype = DDP_ATP;
397 #ifdef NOT_YET
398 cfgp->inet.net = atp->atp_gref->laddr.s_net;
399 cfgp->inet.node = atp->atp_gref->laddr.s_node;
400 cfgp->inet.socket = atp->atp_gref->lport;
401 cfgp->ddptype = atp->atp_gref->ddptype;
402 #endif
403 }
404 gbuf_wset(gbuf_cont(m), sizeof(ddp_addr_t));
405 atp_iocack(atp, m);
406 break;
407
408 default:
409 /*
410 * Otherwise pass it on, if possible
411 */
412 iocbp->ioc_private = (void *)gref;
413 DDP_OUTPUT(m);
414 break;
415 }
416 break;
417
418 default:
419 gbuf_freem(m);
420 break;
421 }
422 } /* atp_wput */
423
424 gbuf_t *atp_build_release(trp)
425 register struct atp_trans *trp;
426 {
427 register gbuf_t *m;
428 register at_ddp_t *ddp;
429 register at_atp_t *athp;
430
431 /*
432 * Now try and allocate enough space to send the message
433 * if none is available the caller will schedule
434 * a timeout so we can retry for more space soon
435 */
436 if ((m = (gbuf_t *)gbuf_alloc(AT_WR_OFFSET+ATP_HDR_SIZE, PRI_HI)) != NULL) {
437 gbuf_rinc(m,AT_WR_OFFSET);
438 gbuf_wset(m,TOTAL_ATP_HDR_SIZE);
439 ddp = AT_DDP_HDR(m);
440 ddp->type = DDP_ATP;
441 UAS_ASSIGN(ddp->checksum, 0);
442 ddp->dst_socket = trp->tr_socket.socket;
443 ddp->dst_node = trp->tr_socket.node;
444 NET_ASSIGN(ddp->dst_net, trp->tr_socket.net);
445 ddp->src_node = trp->tr_local_node;
446 NET_NET(ddp->src_net, trp->tr_local_net);
447
448 /*
449 * clear the cmd/xo/eom/sts/unused fields
450 */
451 athp = AT_ATP_HDR(m);
452 ATP_CLEAR_CONTROL(athp);
453 athp->cmd = ATP_CMD_TREL;
454 UAS_ASSIGN(athp->tid, trp->tr_tid);
455 }
456
457 return (m);
458 }
459
460 void atp_send_replies(atp, rcbp)
461 register struct atp_state *atp;
462 register struct atp_rcb *rcbp;
463 { register gbuf_t *m;
464 register int i, len;
465 int s_gen, s, cnt, err, offset, space;
466 unsigned char *m0_rptr = NULL, *m0_wptr = NULL;
467 register at_atp_t *athp;
468 register struct atpBDS *bdsp;
469 register gbuf_t *m2, *m1, *m0, *mhdr;
470 caddr_t lastPage;
471 gbuf_t *mprev, *mlist = 0;
472 at_socket src_socket = (at_socket)atp->atp_socket_no;
473 gbuf_t *rc_xmt[ATP_TRESP_MAX];
474 struct ddp_atp {
475 char ddp_atp_hdr[TOTAL_ATP_HDR_SIZE];
476 };
477 struct timeval timenow;
478
479 ATDISABLE(s, atp->atp_lock);
480 if (rcbp->rc_queue != atp) {
481 ATENABLE(s, atp->atp_lock);
482 return;
483 }
484 if (rcbp->rc_not_sent_bitmap == 0)
485 goto nothing_to_send;
486
487 dPrintf(D_M_ATP_LOW, D_L_OUTPUT, ("atp_send_replies\n"));
488 /*
489 * Do this for each message that hasn't been sent
490 */
491 cnt = rcbp->rc_pktcnt;
492 for (i = 0; i < cnt; i++) {
493 rc_xmt[i] = 0;
494 if (rcbp->rc_snd[i]) {
495 if ((rc_xmt[i] =
496 gbuf_alloc(AT_WR_OFFSET+TOTAL_ATP_HDR_SIZE,PRI_MED))
497 == NULL) {
498 for (cnt = 0; cnt < i; cnt++)
499 if (rc_xmt[cnt])
500 gbuf_freeb(rc_xmt[cnt]);
501 goto nothing_to_send;
502 }
503 }
504 }
505
506 m = rcbp->rc_xmt;
507 m0 = gbuf_cont(m);
508 if (gbuf_len(m) > TOTAL_ATP_HDR_SIZE)
509 bdsp = (struct atpBDS *)(AT_ATP_HDR(m)->data);
510 else
511 bdsp = 0;
512 offset = 0;
513 if (m0)
514 space = gbuf_msgsize(m0);
515 else
516 space = 0;
517 for (i = 0; i < cnt; i++) {
518 if (rcbp->rc_snd[i] == 0) {
519 if ((len = UAS_VALUE(bdsp->bdsBuffSz))) {
520 offset += len;
521 space -= len;
522 }
523 } else {
524 mhdr = rc_xmt[i];
525 /* setup header fields */
526 gbuf_rinc(mhdr,AT_WR_OFFSET);
527 gbuf_wset(mhdr,TOTAL_ATP_HDR_SIZE);
528 *(struct ddp_atp *)(gbuf_rptr(mhdr))= *(struct ddp_atp *)(gbuf_rptr(m));
529 athp = AT_ATP_HDR(mhdr);
530 ATP_CLEAR_CONTROL(athp);
531 athp->cmd = ATP_CMD_TRESP;
532 athp->bitmap = i;
533 if (i == (cnt - 1))
534 athp->eom = 1; /* for the last fragment */
535 if (bdsp) {
536 UAL_UAL(athp->user_bytes, bdsp->bdsUserData);
537 if ((len = UAS_VALUE(bdsp->bdsBuffSz)) && m0 != 0 && space > 0) {
538 if ((m1 = m_copym(m0, offset, len, M_DONTWAIT)) == 0) {
539 for (i = 0; i < cnt; i++)
540 if (rc_xmt[i])
541 gbuf_freem(rc_xmt[i]);
542 goto nothing_to_send;
543 }
544 offset += len;
545 space -= len;
546 gbuf_cont(mhdr) = m1;
547 }
548 }
549
550 AT_DDP_HDR(mhdr)->src_socket = src_socket;
551 dPrintf(D_M_ATP_LOW, D_L_OUTPUT,
552 ("atp_send_replies: %d, socket=%d, size=%d\n",
553 i, atp->atp_socket_no, gbuf_msgsize(gbuf_cont(m2))));
554
555 if (mlist)
556 gbuf_next(mprev) = mhdr;
557 else
558 mlist = mhdr;
559 mprev = mhdr;
560
561 rcbp->rc_snd[i] = 0;
562 rcbp->rc_not_sent_bitmap &= ~atp_mask[i];
563 if (rcbp->rc_not_sent_bitmap == 0)
564 break;
565 }
566 /*
567 * on to the next frag
568 */
569 bdsp++;
570 }
571 if (mlist) {
572 ATENABLE(s, atp->atp_lock);
573 DDP_OUTPUT(mlist);
574 ATDISABLE(s, atp->atp_lock);
575 }
576
577 nothing_to_send:
578 /*
579 * If all replies from this reply block have been sent then
580 * remove it from the queue and mark it so
581 */
582 if (rcbp->rc_queue != atp) {
583 ATENABLE(s, atp->atp_lock);
584 return;
585 }
586 rcbp->rc_rep_waiting = 0;
587
588 /*
589 * If we are doing execute once re-set the rcb timeout
590 * each time we send back any part of the response. Note
591 * that this timer is started when an initial request is
592 * received. Each response reprimes the timer. Duplicate
593 * requests do not reprime the timer.
594 *
595 * We have sent all of a response so free the
596 * resources.
597 */
598 if (rcbp->rc_xo && rcbp->rc_state != RCB_RELEASED) {
599 getmicrouptime(&timenow);
600 ATDISABLE(s_gen, atpgen_lock);
601 if (rcbp->rc_timestamp == 0) {
602 rcbp->rc_timestamp = timenow.tv_sec;
603 if (rcbp->rc_timestamp == 0)
604 rcbp->rc_timestamp = 1;
605 ATP_Q_APPEND(atp_need_rel, rcbp, rc_tlist);
606 }
607 rcbp->rc_state = RCB_RESPONSE_FULL;
608 ATENABLE(s_gen, atpgen_lock);
609 } else
610 atp_rcb_free(rcbp);
611 ATENABLE(s, atp->atp_lock);
612 } /* atp_send_replies */
613
614
615 static int
616 atp_pack_bdsp(trp, bdsp)
617 register struct atp_trans *trp;
618 register struct atpBDS *bdsp;
619 {
620 register gbuf_t *m = NULL;
621 register int i, datsize = 0;
622 struct atpBDS *bdsbase = bdsp;
623 int error = 0;
624
625 dPrintf(D_M_ATP, D_L_INFO, ("atp_pack_bdsp: socket=%d\n",
626 trp->tr_queue->atp_socket_no));
627
628 for (i = 0; i < ATP_TRESP_MAX; i++, bdsp++) {
629 unsigned short bufsize = UAS_VALUE(bdsp->bdsBuffSz);
630 long bufaddr = UAL_VALUE(bdsp->bdsBuffAddr);
631
632 if ((m = trp->tr_rcv[i]) == NULL)
633 break;
634
635 /* discard ddp hdr on first packet */
636 if (i == 0)
637 gbuf_rinc(m,DDP_X_HDR_SIZE);
638
639 /* this field may contain control information even when
640 no data is present */
641 UAL_UAL(bdsp->bdsUserData,
642 (((at_atp_t *)(gbuf_rptr(m)))->user_bytes));
643 gbuf_rinc(m, ATP_HDR_SIZE);
644
645 if ((bufsize != 0) && (bufaddr != 0)) {
646 /* user expects data back */
647 short tmp = 0;
648 register char *buf = (char *)bufaddr;
649
650 while (m) {
651 unsigned short len = (unsigned short)(gbuf_len(m));
652 if (len) {
653 if (len > bufsize)
654 len = bufsize;
655 if ((error = copyout((caddr_t)gbuf_rptr(m),
656 CAST_USER_ADDR_T(&buf[tmp]),
657 len)) != 0) {
658 return error;
659 }
660 bufsize -= len;
661 tmp += len;
662 }
663 m = gbuf_cont(m);
664 }
665
666 UAS_ASSIGN(bdsp->bdsDataSz, tmp);
667 datsize += (int)tmp;
668 }
669 gbuf_freem(trp->tr_rcv[i]);
670 trp->tr_rcv[i] = NULL;
671 }
672
673 /* report the number of packets */
674 UAS_ASSIGN(((struct atpBDS *)bdsbase)->bdsBuffSz, i);
675
676 dPrintf(D_M_ATP, D_L_INFO, (" : size=%d\n",
677 datsize));
678
679 return 0;
680 } /* atp_pack_bdsp */
681
682
683 /* create an mbuf chain with mbuf packet headers for each ATP response packet
684 * to be sent. m contains the DDP hdr, ATP hdr, and and array of atpBDS structs.
685 * chained to m is an mbuf that contians the actual data pointed to by the atpBDS
686 * structs.
687 */
688 static int
689 atp_unpack_bdsp(atp, m, rcbp, cnt, wait)
690 struct atp_state *atp;
691 gbuf_t *m; /* ddp, atp and bdsp gbuf_t */
692 register struct atp_rcb *rcbp;
693 register int cnt, wait;
694 {
695 register struct atpBDS *bdsp;
696 register gbuf_t *m2, *m1, *m0, *mhdr;
697 caddr_t lastPage;
698 at_atp_t *athp;
699 int i, len, s_gen;
700 at_socket src_socket;
701
702 struct ddp_atp {
703 char ddp_atp_hdr[TOTAL_ATP_HDR_SIZE];
704 };
705 gbuf_t *mprev, *mlist = 0;
706 gbuf_t *rc_xmt[ATP_TRESP_MAX];
707 unsigned char *m0_rptr, *m0_wptr;
708 int err, offset, space;
709 struct timeval timenow;
710
711 /*
712 * get the user data structure pointer
713 */
714 bdsp = (struct atpBDS *)(AT_ATP_HDR(m)->data);
715
716 /*
717 * Guard against bogus count argument.
718 */
719 if ((unsigned) cnt > ATP_TRESP_MAX) {
720 dPrintf(D_M_ATP, D_L_ERROR,
721 ("atp_unpack_bdsp: bad bds count 0x%x\n", cnt));
722 gbuf_freem(m);
723 return(EINVAL);
724 }
725 if ((src_socket = (at_socket)atp->atp_socket_no) == 0xFF) {
726 /* comparison was to -1, however src_socket is a u_char */
727 gbuf_freem(m);
728 return EPIPE;
729 }
730
731 m0 = gbuf_cont(m);
732 rcbp->rc_xmt = m;
733 rcbp->rc_pktcnt = cnt;
734 rcbp->rc_state = RCB_SENDING;
735 rcbp->rc_not_sent_bitmap = 0;
736
737 if (cnt <= 1) {
738 /*
739 * special case this to
740 * improve AFP write transactions to the server
741 */
742 rcbp->rc_pktcnt = 1;
743 if ((m2 = gbuf_alloc_wait(AT_WR_OFFSET+TOTAL_ATP_HDR_SIZE,
744 wait)) == NULL)
745 return 0;
746 gbuf_rinc(m2,AT_WR_OFFSET);
747 gbuf_wset(m2,TOTAL_ATP_HDR_SIZE);
748 *(struct ddp_atp *)(gbuf_rptr(m2))= *(struct ddp_atp *)(gbuf_rptr(m));
749 athp = AT_ATP_HDR(m2);
750 ATP_CLEAR_CONTROL(athp);
751 athp->cmd = ATP_CMD_TRESP;
752 athp->bitmap = 0;
753 athp->eom = 1; /* there's only 1 fragment */
754
755 /* *** why only if cnt > 0? *** */
756 if (cnt > 0)
757 UAL_UAL(athp->user_bytes, bdsp->bdsUserData);
758 if (m0)
759 if (!append_copy((struct mbuf *)m2,
760 (struct mbuf *)m0, wait)) {
761 gbuf_freeb(m2);
762 return 0;
763 }
764 /*
765 * send the message and mark it as sent
766 */
767 AT_DDP_HDR(m2)->src_socket = src_socket;
768 dPrintf(D_M_ATP_LOW, D_L_INFO,
769 ("atp_unpack_bdsp %d, socket=%d, size=%d, cnt=%d\n",
770 0,atp->atp_socket_no,gbuf_msgsize(gbuf_cont(m2)),cnt));
771 mlist = m2;
772 goto l_send;
773 }
774
775 /* create an array of mbuf packet headers for the packets to be sent
776 * to contain the atp and ddp headers with room at the front for the
777 * datalink header.
778 */
779 for (i = 0; i < cnt; i++) {
780 /* all hdrs, packet data and dst addr storage */
781 if ((rc_xmt[i] =
782 gbuf_alloc_wait(AT_WR_OFFSET+TOTAL_ATP_HDR_SIZE, wait)) == NULL) {
783 for (cnt = 0; cnt < i; cnt++)
784 if (rc_xmt[cnt])
785 gbuf_freeb(rc_xmt[cnt]);
786 return 0;
787 }
788 }
789
790 /* run through the atpBDS structs and create an mbuf for the data
791 * portion of each packet to be sent. these get chained to the mbufs
792 * containing the ATP and DDP headers. this code assumes that no ATP
793 * packet is contained in more than 2 mbufs (e.i crosses mbuf boundary
794 * no more than one time).
795 */
796 offset = 0;
797 if (m0)
798 space = gbuf_msgsize(m0);
799 for (i = 0; i < cnt; i++) { /* for each hdr mbuf */
800 mhdr = rc_xmt[i];
801 /* setup header fields */
802 gbuf_rinc(mhdr,AT_WR_OFFSET);
803 gbuf_wset(mhdr,TOTAL_ATP_HDR_SIZE);
804 *(struct ddp_atp *)(gbuf_rptr(mhdr))= *(struct ddp_atp *)(gbuf_rptr(m));
805 athp = AT_ATP_HDR(mhdr);
806 ATP_CLEAR_CONTROL(athp);
807 athp->cmd = ATP_CMD_TRESP;
808 athp->bitmap = i;
809 if (i == (cnt - 1))
810 athp->eom = 1; /* for the last fragment */
811 UAL_UAL(athp->user_bytes, bdsp->bdsUserData);
812
813 if ((len = UAS_VALUE(bdsp->bdsBuffSz)) != 0 && m0 != 0 && space > 0) {
814 if ((m1 = m_copym(m0, offset, len, wait)) == 0) {
815 for (i = 0; i < cnt; i++)
816 if (rc_xmt[i])
817 gbuf_freem(rc_xmt[i]);
818 return 0;
819 }
820 gbuf_cont(mhdr) = m1;
821 space -= len;
822 offset += len;
823 }
824
825 AT_DDP_HDR(mhdr)->src_socket = src_socket;
826 dPrintf(D_M_ATP_LOW,D_L_INFO,
827 ("atp_unpack_bdsp %d, socket=%d, size=%d, cnt=%d\n",
828 i,atp->atp_socket_no,gbuf_msgsize(gbuf_cont(mhdr)),cnt));
829 if (mlist)
830 gbuf_next(mprev) = mhdr;
831 else
832 mlist = mhdr;
833 mprev = mhdr;
834 /*
835 * on to the next frag
836 */
837 bdsp++;
838 }
839 /*
840 * send the message
841 */
842 l_send:
843 if (rcbp->rc_xo) {
844 getmicrouptime(&timenow);
845 ATDISABLE(s_gen, atpgen_lock);
846 if (rcbp->rc_timestamp == 0) {
847 if ((rcbp->rc_timestamp = timenow.tv_sec) == 0)
848 rcbp->rc_timestamp = 1;
849 ATP_Q_APPEND(atp_need_rel, rcbp, rc_tlist);
850 }
851 ATENABLE(s_gen, atpgen_lock);
852 }
853
854 DDP_OUTPUT(mlist);
855 return 0;
856
857 } /* atp_unpack_bdsp */
858
859 #define ATP_SOCKET_LAST (DDP_SOCKET_LAST-6)
860 #define ATP_SOCKET_FIRST (DDP_SOCKET_1st_DYNAMIC)
861 static unsigned int sNext = 0;
862
863 int atp_bind(gref, sVal, flag)
864 gref_t *gref;
865 unsigned int sVal;
866 unsigned char *flag;
867 {
868 extern unsigned char asp_inpC[];
869 extern asp_scb_t *asp_scbQ[];
870 unsigned char inpC, sNextUsed = 0;
871 unsigned int sMin, sMax, sSav;
872 struct atp_state *atp;
873 int s;
874
875 atp = (struct atp_state *)gref->info;
876 if (atp->dflag)
877 atp = (struct atp_state *)atp->atp_msgq;
878
879 sMax = ATP_SOCKET_LAST;
880 sMin = ATP_SOCKET_FIRST;
881 ATDISABLE(s, atpgen_lock);
882 if (flag && (*flag == 3)) {
883 sMin += 40;
884 if (sMin < sNext) {
885 sMin = sNext;
886 sNextUsed = 1;
887 }
888 }
889
890 if ( (sVal != 0) &&
891 ((sVal > sMax) || (sVal < 2) || (sVal == 6) ||
892 (ddp_socket_inuse(sVal, DDP_ATP) &&
893 (atp_inputQ[sVal] != (gref_t *)1)))) {
894 ATENABLE(s, atpgen_lock);
895 return 0;
896 }
897
898 if (sVal == 0) {
899 inpC = 255;
900 again:
901 for (sVal=sMin; sVal <= sMax; sVal++) {
902 if (!ddp_socket_inuse(sVal, DDP_ATP) ||
903 atp_inputQ[sVal] == (gref_t *)1)
904 break;
905 else if (flag && (*flag == 3) && asp_scbQ[sVal]) {
906 if ((asp_scbQ[sVal]->dflag == *flag)
907 && (asp_inpC[sVal] < inpC) ) {
908 inpC = asp_inpC[sVal];
909 sSav = sVal;
910 }
911 }
912 }
913 if (sVal > sMax) {
914 if (flag && (*flag == 3)) {
915 if (sNextUsed) {
916 sNextUsed = 0;
917 sMax = sNext - 1;
918 sMin = ATP_SOCKET_FIRST+40;
919 goto again;
920 }
921 sNext = 0;
922 *flag = (unsigned char)sSav;
923 }
924 ATENABLE(s, atpgen_lock);
925 return 0;
926 }
927 }
928 atp->atp_socket_no = (short)sVal;
929 atp_inputQ[sVal] = gref;
930 if (flag == 0)
931 atp_pidM[sVal] = atp->atp_pid;
932 else if (*flag == 3) {
933 sNext = sVal + 1;
934 if (sNext > ATP_SOCKET_LAST)
935 sNext = 0;
936 }
937
938 ATENABLE(s, atpgen_lock);
939 return (int)sVal;
940 }
941
942 void atp_req_ind(atp, mioc)
943 register struct atp_state *atp;
944 register gbuf_t *mioc;
945 {
946 register struct atp_rcb *rcbp;
947 int s;
948
949 if ((rcbp = atp->atp_attached.head) != 0) {
950 gbuf_cont(mioc) = rcbp->rc_ioctl;
951 rcbp->rc_ioctl = NULL;
952 ATDISABLE(s, atp->atp_lock);
953 if (rcbp->rc_xo) {
954 ATP_Q_REMOVE(atp->atp_attached, rcbp, rc_list);
955 rcbp->rc_state = RCB_NOTIFIED;
956 ATP_Q_APPEND(atp->atp_rcb, rcbp, rc_list);
957 } else
958 atp_rcb_free(rcbp);
959 ATENABLE(s, atp->atp_lock);
960 if (gbuf_cont(mioc))
961 ((ioc_t *)gbuf_rptr(mioc))->ioc_count = gbuf_msgsize(gbuf_cont(mioc));
962 else
963 ((ioc_t *)gbuf_rptr(mioc))->ioc_count = 0;
964 asp_ack_reply(atp->atp_gref, mioc);
965 } else
966 gbuf_freeb(mioc);
967 }
968
969 void atp_rsp_ind(trp, mioc)
970 register struct atp_trans *trp;
971 register gbuf_t *mioc;
972 {
973 register struct atp_state *atp = trp->tr_queue;
974 register int err;
975 gbuf_t *xm = 0;
976
977 err = 0;
978 {
979 switch (trp->tr_state) {
980 case TRANS_DONE:
981 if (asp_pack_bdsp(trp, &xm) < 0)
982 err = EFAULT;
983 gbuf_cont(mioc) = trp->tr_xmt;
984 trp->tr_xmt = NULL;
985 break;
986
987 case TRANS_FAILED:
988 err = ETIMEDOUT;
989 break;
990
991 default:
992 err = ENOENT;
993 break;
994 }
995 atp_free(trp);
996
997 if (err) {
998 dPrintf(D_M_ATP, D_L_ERROR,
999 ("atp_rsp_ind: TRANSACTION error\n"));
1000 atp_iocnak(atp, mioc, err);
1001 } else {
1002 gbuf_cont(gbuf_cont(mioc)) = xm;
1003 atp_iocack(atp, mioc);
1004 }
1005 }
1006 }
1007
1008 void atp_cancel_req(gref, tid)
1009 gref_t *gref;
1010 unsigned short tid;
1011 {
1012 int s;
1013 struct atp_state *atp;
1014 struct atp_trans *trp;
1015
1016 atp = (struct atp_state *)gref->info;
1017 if (atp->dflag)
1018 atp = (struct atp_state *)atp->atp_msgq;
1019
1020 ATDISABLE(s, atp->atp_lock);
1021 for (trp = atp->atp_trans_wait.head; trp; trp = trp->tr_list.next) {
1022 if (trp->tr_tid == tid)
1023 break;
1024 }
1025 ATENABLE(s, atp->atp_lock);
1026 if (trp != NULL)
1027 atp_free(trp);
1028 }
1029
1030 /*
1031 * remove atp from the use list
1032 */
1033 void
1034 atp_dequeue_atp(atp)
1035 struct atp_state *atp;
1036 {
1037 int s;
1038
1039 ATDISABLE(s, atpall_lock);
1040 if (atp == atp_used_list) {
1041 if ((atp_used_list = atp->atp_trans_waiting) != 0)
1042 atp->atp_trans_waiting->atp_rcb_waiting = 0;
1043 } else if (atp->atp_rcb_waiting) {
1044 if ((atp->atp_rcb_waiting->atp_trans_waiting
1045 = atp->atp_trans_waiting) != 0)
1046 atp->atp_trans_waiting->atp_rcb_waiting = atp->atp_rcb_waiting;
1047 }
1048
1049 atp->atp_trans_waiting = 0;
1050 atp->atp_rcb_waiting = 0;
1051 ATENABLE(s, atpall_lock);
1052 }
1053
1054 void
1055 atp_timout(func, trp, ticks)
1056 void (*func)();
1057 struct atp_trans *trp;
1058 int ticks;
1059 {
1060 int s;
1061 unsigned int sum;
1062 struct atp_trans *curr_trp, *prev_trp;
1063
1064 ATDISABLE(s, atptmo_lock);
1065 if (trp->tr_tmo_func) {
1066 ATENABLE(s, atptmo_lock);
1067 return;
1068 }
1069
1070 trp->tr_tmo_func = func;
1071 trp->tr_tmo_delta = 1+(ticks>>5);
1072
1073 if (trp_tmo_list == 0) {
1074 trp->tr_tmo_next = trp->tr_tmo_prev = 0;
1075 trp_tmo_list = trp;
1076 ATENABLE(s, atptmo_lock);
1077 return;
1078 }
1079
1080 prev_trp = 0;
1081 curr_trp = trp_tmo_list;
1082 sum = 0;
1083
1084 while (1) {
1085 sum += curr_trp->tr_tmo_delta;
1086 if (sum > trp->tr_tmo_delta) {
1087 sum -= curr_trp->tr_tmo_delta;
1088 trp->tr_tmo_delta -= sum;
1089 curr_trp->tr_tmo_delta -= trp->tr_tmo_delta;
1090 break;
1091 }
1092 prev_trp = curr_trp;
1093 if ((curr_trp = curr_trp->tr_tmo_next) == 0) {
1094 trp->tr_tmo_delta -= sum;
1095 break;
1096 }
1097 }
1098
1099 if (prev_trp) {
1100 trp->tr_tmo_prev = prev_trp;
1101 if ((trp->tr_tmo_next = prev_trp->tr_tmo_next) != 0)
1102 prev_trp->tr_tmo_next->tr_tmo_prev = trp;
1103 prev_trp->tr_tmo_next = trp;
1104 } else {
1105 trp->tr_tmo_prev = 0;
1106 trp->tr_tmo_next = trp_tmo_list;
1107 trp_tmo_list->tr_tmo_prev = trp;
1108 trp_tmo_list = trp;
1109 }
1110 ATENABLE(s, atptmo_lock);
1111 }
1112
1113 void
1114 atp_untimout(func, trp)
1115 void (*func)();
1116 struct atp_trans *trp;
1117 {
1118 int s;
1119
1120 ATDISABLE(s, atptmo_lock);
1121 if (trp->tr_tmo_func == 0) {
1122 ATENABLE(s, atptmo_lock);
1123 return;
1124 }
1125
1126 if (trp_tmo_list == trp) {
1127 if ((trp_tmo_list = trp->tr_tmo_next) != 0) {
1128 trp_tmo_list->tr_tmo_prev = 0;
1129 trp->tr_tmo_next->tr_tmo_delta += trp->tr_tmo_delta;
1130 }
1131 } else {
1132 if ((trp->tr_tmo_prev->tr_tmo_next = trp->tr_tmo_next) != 0) {
1133 trp->tr_tmo_next->tr_tmo_prev = trp->tr_tmo_prev;
1134 trp->tr_tmo_next->tr_tmo_delta += trp->tr_tmo_delta;
1135 }
1136 }
1137 trp->tr_tmo_func = 0;
1138 ATENABLE(s, atptmo_lock);
1139 }
1140
1141 void
1142 atp_trp_clock_locked(arg)
1143 void *arg;
1144 {
1145 atalk_lock();
1146 atp_trp_clock(arg);
1147 atalk_unlock();
1148 }
1149
1150 void
1151 atp_trp_clock(arg)
1152 void *arg;
1153 {
1154 int s;
1155 struct atp_trans *trp;
1156 void (*tr_tmo_func)();
1157
1158 ATDISABLE(s, atptmo_lock);
1159 if (trp_tmo_list)
1160 trp_tmo_list->tr_tmo_delta--;
1161 while (((trp = trp_tmo_list) != 0) && (trp_tmo_list->tr_tmo_delta == 0)) {
1162 if ((trp_tmo_list = trp->tr_tmo_next) != 0)
1163 trp_tmo_list->tr_tmo_prev = 0;
1164 if ((tr_tmo_func = trp->tr_tmo_func) != 0) {
1165 trp->tr_tmo_func = 0;
1166 ATENABLE(s, atptmo_lock);
1167 (*tr_tmo_func)(trp);
1168 ATDISABLE(s, atptmo_lock);
1169 }
1170 }
1171 ATENABLE(s, atptmo_lock);
1172
1173 timeout(atp_trp_clock_locked, (void *)arg, (1<<5));
1174 }
1175
1176 void
1177 atp_send_req(gref, mioc)
1178 gref_t *gref;
1179 gbuf_t *mioc;
1180 {
1181 register struct atp_state *atp;
1182 register struct atp_trans *trp;
1183 register ioc_t *iocbp;
1184 register at_atp_t *athp;
1185 register at_ddp_t *ddp;
1186 gbuf_t *m, *m2, *bds;
1187 struct atp_set_default *sdb;
1188 int s, old;
1189 unsigned int timer;
1190
1191 atp = (struct atp_state *)((struct atp_state *)gref->info)->atp_msgq;
1192 iocbp = (ioc_t *)gbuf_rptr(mioc);
1193
1194 if ((trp = atp_trans_alloc(atp)) == NULL) {
1195 l_retry:
1196 ((asp_scb_t *)gref->info)->stat_msg = mioc;
1197 iocbp->ioc_private = (void *)gref;
1198 timeout(atp_retry_req, mioc, 10);
1199 return;
1200 }
1201
1202 m2 = gbuf_cont(mioc);
1203 if ((bds = gbuf_dupb(m2)) == NULL) {
1204 atp_trans_free(trp);
1205 goto l_retry;
1206 }
1207 gbuf_rinc(m2,atpBDSsize);
1208 gbuf_wset(bds,atpBDSsize);
1209 iocbp->ioc_count -= atpBDSsize;
1210 gbuf_cont(m2) = NULL;
1211
1212 old = iocbp->ioc_cmd;
1213 iocbp->ioc_cmd = AT_ATP_ISSUE_REQUEST;
1214 sdb = (struct atp_set_default *)gbuf_rptr(m2);
1215
1216 /*
1217 * The at_snd_req library routine multiplies seconds by 100.
1218 * We need to divide by 100 in order to obtain the timer.
1219 */
1220 if ((timer = (sdb->def_rate * HZ)/100) == 0)
1221 timer = HZ;
1222 iocbp->ioc_count -= sizeof(struct atp_set_default);
1223 gbuf_rinc(m2,sizeof(struct atp_set_default));
1224
1225 trp->tr_retry = sdb->def_retries;
1226 trp->tr_timeout = timer;
1227 trp->tr_bdsp = bds;
1228 trp->tr_tid = atp_tid(atp);
1229 trp->tr_xmt = mioc;
1230
1231 /*
1232 * Now fill in the header (and remember the bits
1233 * we need to know)
1234 */
1235 athp = AT_ATP_HDR(m2);
1236 athp->cmd = ATP_CMD_TREQ;
1237 UAS_ASSIGN(athp->tid, trp->tr_tid);
1238 athp->eom = 0;
1239 athp->sts = 0;
1240 trp->tr_xo = athp->xo;
1241 trp->tr_bitmap = athp->bitmap;
1242 ddp = AT_DDP_HDR(m2);
1243 ddp->type = DDP_ATP;
1244 ddp->src_socket = (at_socket)atp->atp_socket_no;
1245 trp->tr_socket.socket = ddp->dst_socket;
1246 trp->tr_socket.node = ddp->dst_node;
1247 trp->tr_socket.net = NET_VALUE(ddp->dst_net);
1248 trp->tr_local_socket = atp->atp_socket_no;
1249 trp->tr_local_node = ddp->src_node;
1250 NET_NET(trp->tr_local_net, ddp->src_net);
1251
1252 #ifdef NOT_YET
1253 /* save the local information in the gref */
1254 atp->atp_gref->laddr.s_net = NET_VALUE(ddp->src_net);
1255 atp->atp_gref->laddr.s_node = ddp->src_node;
1256 atp->atp_gref->lport = ddp->src_node;
1257 atp->atp_gref->ddptype = DDP_ATP;
1258 #endif
1259
1260 /*
1261 * Put us in the transaction waiting queue
1262 */
1263 ATDISABLE(s, atp->atp_lock);
1264 ATP_Q_APPEND(atp->atp_trans_wait, trp, tr_list);
1265 ATENABLE(s, atp->atp_lock);
1266
1267 /*
1268 * Send the message and set the timer
1269 */
1270 m = (gbuf_t *)copy_pkt(m2, sizeof(llc_header_t));
1271 if (!trp->tr_retry && !trp->tr_bitmap && !trp->tr_xo)
1272 atp_x_done(trp); /* no reason to tie up resources */
1273 else
1274 atp_timout(atp_req_timeout, trp, trp->tr_timeout);
1275 if (m) {
1276 trace_mbufs(D_M_ATP_LOW, " s", m);
1277 DDP_OUTPUT(m);
1278 }
1279 } /* atp_send_req */
1280
1281 void atp_retry_req(arg)
1282 void *arg;
1283 {
1284 gbuf_t *m = (gbuf_t *)arg;
1285 gref_t *gref;
1286
1287 atalk_lock();
1288
1289 gref = (gref_t *)((ioc_t *)gbuf_rptr(m))->ioc_private;
1290 if (gref->info) {
1291 ((asp_scb_t *)gref->info)->stat_msg = 0;
1292 atp_send_req(gref, m);
1293 }
1294 atalk_unlock();
1295 }
1296
1297 void atp_send_rsp(gref, m, wait)
1298 gref_t *gref;
1299 gbuf_t *m;
1300 int wait;
1301 {
1302 register struct atp_state *atp;
1303 register struct atp_rcb *rcbp;
1304 register at_atp_t *athp;
1305 register at_ddp_t *ddp;
1306 int s, xcnt;
1307
1308 atp = (struct atp_state *)gref->info;
1309 if (atp->dflag)
1310 atp = (struct atp_state *)atp->atp_msgq;
1311 ddp = AT_DDP_HDR(m);
1312 athp = AT_ATP_HDR(m);
1313
1314 /*
1315 * search for the corresponding rcb
1316 */
1317 ATDISABLE(s, atp->atp_lock);
1318 for (rcbp = atp->atp_rcb.head; rcbp; rcbp = rcbp->rc_list.next) {
1319 if ( (rcbp->rc_tid == UAS_VALUE(athp->tid)) &&
1320 (rcbp->rc_socket.node == ddp->dst_node) &&
1321 (rcbp->rc_socket.net == NET_VALUE(ddp->dst_net)) &&
1322 (rcbp->rc_socket.socket == ddp->dst_socket) )
1323 break;
1324 }
1325
1326 /*
1327 * If it has already been sent then drop the request
1328 */
1329 if ((rcbp && (rcbp->rc_state != RCB_NOTIFIED)) ||
1330 (rcbp == NULL && athp->xo) ) {
1331 ATENABLE(s, atp->atp_lock);
1332 gbuf_freem(m);
1333 return;
1334 }
1335 ATENABLE(s, atp->atp_lock);
1336
1337 if (rcbp == NULL) { /* a response is being sent for an ALO transaction */
1338 if ((rcbp = atp_rcb_alloc(atp)) == NULL) {
1339 gbuf_freem(m);
1340 return;
1341 }
1342 rcbp->rc_ioctl = 0;
1343 rcbp->rc_socket.socket = ddp->dst_socket;
1344 rcbp->rc_socket.node = ddp->dst_node;
1345 rcbp->rc_socket.net = NET_VALUE(ddp->dst_net);
1346 rcbp->rc_tid = UAS_VALUE(athp->tid);
1347 rcbp->rc_bitmap = 0xff;
1348 rcbp->rc_xo = 0;
1349 rcbp->rc_state = RCB_RESPONSE_FULL;
1350 ATDISABLE(s, atp->atp_lock);
1351 ATP_Q_APPEND(atp->atp_rcb, rcbp, rc_list);
1352 ATENABLE(s, atp->atp_lock);
1353 }
1354 else if (ddp->src_node == 0) {
1355 NET_NET(ddp->src_net, rcbp->rc_local_net);
1356 ddp->src_node = rcbp->rc_local_node;
1357 }
1358
1359 xcnt = get_bds_entries(m);
1360 s = atp_unpack_bdsp(atp, m, rcbp, xcnt, wait);
1361 if (s == 0)
1362 atp_send_replies(atp, rcbp);
1363 } /* atp_send_rsp */
1364
1365 int asp_pack_bdsp(trp, xm)
1366 register struct atp_trans *trp;
1367 gbuf_t **xm;
1368 {
1369 register struct atpBDS *bdsp;
1370 register gbuf_t *m, *m2;
1371 register int i;
1372 gbuf_t *m_prev, *m_head = 0;
1373
1374 dPrintf(D_M_ATP, D_L_INFO, ("asp_pack_bdsp: socket=%d\n",
1375 trp->tr_queue->atp_socket_no));
1376
1377 if ((m2 = trp->tr_bdsp) == NULL)
1378 return 0;
1379 trp->tr_bdsp = NULL;
1380 bdsp = (struct atpBDS *)gbuf_rptr(m2);
1381
1382 for (i = 0; (i < ATP_TRESP_MAX &&
1383 bdsp < (struct atpBDS *)(gbuf_wptr(m2))); i++) {
1384 if ((m = trp->tr_rcv[i]) == NULL)
1385 break;
1386 if (i == 0) {
1387 /* discard ddp hdr on first packet */
1388 gbuf_rinc(m,DDP_X_HDR_SIZE);
1389 }
1390
1391 UAL_UAL(bdsp->bdsUserData, (((at_atp_t *)(gbuf_rptr(m)))->user_bytes));
1392 gbuf_rinc(m, ATP_HDR_SIZE);
1393
1394 if (UAL_VALUE(bdsp->bdsBuffAddr)) {
1395 short tmp = 0;
1396
1397 /* user expects data back */
1398 m = gbuf_strip(m);
1399 if (m_head == 0)
1400 m_head = m;
1401 else
1402 gbuf_cont(m_prev) = m;
1403 if (m) {
1404 tmp = (short)gbuf_len(m);
1405 while (gbuf_cont(m)) {
1406 m = gbuf_cont(m);
1407 tmp += (short)(gbuf_len(m));
1408 }
1409 m_prev = m;
1410 }
1411 UAS_ASSIGN(bdsp->bdsDataSz, tmp);
1412 }
1413 trp->tr_rcv[i] = NULL;
1414 bdsp++;
1415
1416 }
1417 /*
1418 * report the number of packets
1419 */
1420 UAS_ASSIGN(((struct atpBDS *)gbuf_rptr(m2))->bdsBuffSz, i);
1421
1422 if (trp->tr_xmt) /* an ioctl block is still held? */
1423 gbuf_cont(trp->tr_xmt) = m2;
1424 else
1425 trp->tr_xmt = m2;
1426
1427 if (m_head)
1428 *xm = m_head;
1429 else
1430 *xm = 0;
1431
1432 dPrintf(D_M_ATP, D_L_INFO, (" : size=%d\n",
1433 gbuf_msgsize(*xm)));
1434
1435 return 0;
1436 }
1437
1438 /*
1439 * The following routines are direct entries from system
1440 * calls to allow fast sending and recving of ATP data.
1441 */
1442
1443 int
1444 _ATPsndreq(fd, buf, len, nowait, err, proc)
1445 int fd;
1446 unsigned char *buf;
1447 int len;
1448 int nowait;
1449 int *err;
1450 void *proc;
1451 {
1452 gref_t *gref;
1453 int s, rc;
1454 unsigned short tid;
1455 unsigned int timer;
1456 register struct atp_state *atp;
1457 register struct atp_trans *trp;
1458 register ioc_t *iocbp;
1459 register at_atp_t *athp;
1460 register at_ddp_t *ddp;
1461 struct atp_set_default *sdb;
1462 gbuf_t *m2, *m, *mioc;
1463 char bds[atpBDSsize];
1464
1465 if ((*err = atalk_getref(0, fd, &gref, proc, 1)) != 0)
1466 return -1;
1467
1468 if ((gref == 0) || ((atp = (struct atp_state *)gref->info) == 0)
1469 || (atp->atp_flags & ATP_CLOSING)) {
1470 dPrintf(D_M_ATP, D_L_ERROR, ("ATPsndreq: stale handle=0x%x, pid=%d\n",
1471 (u_int) gref, gref->pid));
1472 file_drop(fd);
1473 *err = EINVAL;
1474 return -1;
1475 }
1476
1477
1478 while ((mioc = gbuf_alloc(sizeof(ioc_t), PRI_MED)) == 0) {
1479 struct timespec ts;
1480 /* the vaue of 10n terms of hz is 100ms */
1481 ts.tv_sec = 0;
1482 ts.tv_nsec = 100 *1000 * NSEC_PER_USEC;
1483
1484 ATDISABLE(s, atp->atp_delay_lock);
1485 rc = msleep(&atp->atp_delay_event, atalk_mutex, PSOCK | PCATCH, "atpmioc", &ts);
1486 ATENABLE(s, atp->atp_delay_lock);
1487 if (rc != 0) {
1488 *err = rc;
1489 file_drop(fd);
1490 return -1;
1491 }
1492
1493 }
1494 gbuf_wset(mioc,sizeof(ioc_t));
1495 len -= atpBDSsize;
1496 while ((m2 = gbuf_alloc(len, PRI_MED)) == 0) {
1497 struct timespec ts;
1498 /* the vaue of 10n terms of hz is 100ms */
1499 ts.tv_sec = 0;
1500 ts.tv_nsec = 100 *1000 * NSEC_PER_USEC;
1501
1502 ATDISABLE(s, atp->atp_delay_lock);
1503 rc = msleep(&atp->atp_delay_event, atalk_mutex, PSOCK | PCATCH, "atpm2", &ts);
1504 ATENABLE(s, atp->atp_delay_lock);
1505 if (rc != 0) {
1506 gbuf_freeb(mioc);
1507 file_drop(fd);
1508 *err = rc;
1509 return -1;
1510 }
1511 }
1512 gbuf_wset(m2, len);
1513 gbuf_cont(mioc) = m2;
1514 if (((*err = copyin(CAST_USER_ADDR_T(buf), (caddr_t)bds, atpBDSsize)) != 0)
1515 || ((*err = copyin(CAST_USER_ADDR_T(&buf[atpBDSsize]),
1516 (caddr_t)gbuf_rptr(m2), len)) != 0)) {
1517 gbuf_freem(mioc);
1518 file_drop(fd);
1519 return -1;
1520 }
1521 gbuf_set_type(mioc, MSG_IOCTL);
1522 iocbp = (ioc_t *)gbuf_rptr(mioc);
1523 iocbp->ioc_count = len;
1524 iocbp->ioc_cmd = nowait ? AT_ATP_ISSUE_REQUEST_NOTE : AT_ATP_ISSUE_REQUEST;
1525 sdb = (struct atp_set_default *)gbuf_rptr(m2);
1526
1527 /*
1528 * The at_snd_req library routine multiplies seconds by 100.
1529 * We need to divide by 100 in order to obtain the timer.
1530 */
1531 if ((timer = (sdb->def_rate * HZ)/100) == 0)
1532 timer = HZ;
1533 iocbp->ioc_count -= sizeof(struct atp_set_default);
1534 gbuf_rinc(m2,sizeof(struct atp_set_default));
1535
1536 /*
1537 * allocate and set up the transaction record
1538 */
1539 while ((trp = atp_trans_alloc(atp)) == 0) {
1540 struct timespec ts;
1541 /* the vaue of 10n terms of hz is 100ms */
1542 ts.tv_sec = 0;
1543 ts.tv_nsec = 100 *1000 * NSEC_PER_USEC;
1544
1545 ATDISABLE(s, atp->atp_delay_lock);
1546 rc = msleep(&atp->atp_delay_event, atalk_mutex, PSOCK | PCATCH, "atptrp", &ts);
1547 ATENABLE(s, atp->atp_delay_lock);
1548 if (rc != 0) {
1549 gbuf_freem(mioc);
1550 file_drop(fd);
1551 *err = rc;
1552 return -1;
1553 }
1554 }
1555 trp->tr_retry = sdb->def_retries;
1556 trp->tr_timeout = timer;
1557 trp->tr_bdsp = NULL;
1558 trp->tr_tid = atp_tid(atp);
1559 tid = trp->tr_tid;
1560
1561 /*
1562 * remember the IOCTL packet so we can ack it
1563 * later
1564 */
1565 trp->tr_xmt = mioc;
1566
1567 /*
1568 * Now fill in the header (and remember the bits
1569 * we need to know)
1570 */
1571 athp = AT_ATP_HDR(m2);
1572 athp->cmd = ATP_CMD_TREQ;
1573 UAS_ASSIGN(athp->tid, trp->tr_tid);
1574 athp->eom = 0;
1575 athp->sts = 0;
1576 trp->tr_xo = athp->xo;
1577 trp->tr_bitmap = athp->bitmap;
1578 ddp = AT_DDP_HDR(m2);
1579 ddp->type = DDP_ATP;
1580 ddp->src_socket = (at_socket)atp->atp_socket_no;
1581 ddp->src_node = 0;
1582 trp->tr_socket.socket = ddp->dst_socket;
1583 trp->tr_socket.node = ddp->dst_node;
1584 trp->tr_socket.net = NET_VALUE(ddp->dst_net);
1585 trp->tr_local_socket = atp->atp_socket_no;
1586
1587 #ifdef NOT_YET
1588 /* save the local information in the gref */
1589 atp->atp_gref->laddr.s_net = NET_VALUE(ddp->src_net);
1590 atp->atp_gref->laddr.s_node = ddp->src_node;
1591 atp->atp_gref->lport = ddp->src_node;
1592 atp->atp_gref->ddptype = DDP_ATP;
1593 #endif
1594
1595 /*
1596 * Put us in the transaction waiting queue
1597 */
1598 ATDISABLE(s, atp->atp_lock);
1599 ATP_Q_APPEND(atp->atp_trans_wait, trp, tr_list);
1600 ATENABLE(s, atp->atp_lock);
1601
1602 /*
1603 * Send the message and set the timer
1604 */
1605 m = (gbuf_t *)copy_pkt(m2, sizeof(llc_header_t));
1606 if ( !trp->tr_retry && !trp->tr_bitmap && !trp->tr_xo)
1607 atp_x_done(trp); /* no reason to tie up resources */
1608 else
1609 atp_timout(atp_req_timeout, trp, trp->tr_timeout);
1610 if (m)
1611 DDP_OUTPUT(m);
1612
1613 if (nowait) {
1614 file_drop(fd);
1615 return (int)tid;
1616 }
1617
1618 /*
1619 * wait for the transaction to complete
1620 */
1621 ATDISABLE(s, trp->tr_lock);
1622 while ((trp->tr_state != TRANS_DONE) && (trp->tr_state != TRANS_FAILED) &&
1623 (trp->tr_state != TRANS_ABORTING)) {
1624 trp->tr_rsp_wait = 1;
1625 rc = msleep(&trp->tr_event, atalk_mutex, PSOCK | PCATCH, "atpsndreq", 0);
1626 if (rc != 0) {
1627 trp->tr_rsp_wait = 0;
1628 ATENABLE(s, trp->tr_lock);
1629 file_drop(fd);
1630 *err = rc;
1631 return -1;
1632 }
1633 }
1634 trp->tr_rsp_wait = 0;
1635 ATENABLE(s, trp->tr_lock);
1636
1637
1638 if (trp->tr_state == TRANS_FAILED || trp->tr_state == TRANS_ABORTING) {
1639 /*
1640 * transaction timed out, return error
1641 */
1642 atp_free(trp);
1643 file_drop(fd);
1644 *err = ETIMEDOUT;
1645 return -1;
1646 }
1647
1648 /*
1649 * copy out the recv data
1650 */
1651 if ((*err = atp_pack_bdsp(trp, (struct atpBDS *)bds)) != 0) {
1652 atp_free(trp);
1653 file_drop(fd);
1654 return -1;
1655 }
1656
1657 /*
1658 * copyout the result info
1659 */
1660 if ((*err = copyout((caddr_t)bds, CAST_USER_ADDR_T(buf), atpBDSsize)) != 0) {
1661 atp_free(trp);
1662 file_drop(fd);
1663 return -1;
1664 }
1665
1666 atp_free(trp);
1667 file_drop(fd);
1668
1669 return (int)tid;
1670 } /* _ATPsndreq */
1671
1672
1673 /* entry point for ATP send response. respbuf contains a DDP hdr,
1674 * ATP hdr, and atpBDS array. The bdsDataSz field of the first atpBDS
1675 * struct contains the number of atpBDS structs in the array. resplen
1676 * contains the len of the data in respbuf and datalen contains the
1677 * len of the data buffer holding the response packets which the atpBDS
1678 * struct entries point to.
1679 */
1680 int
1681 _ATPsndrsp(fd, respbuff, resplen, datalen, err, proc)
1682 int fd;
1683 unsigned char *respbuff;
1684 int resplen;
1685 int datalen;
1686 int *err;
1687 void *proc;
1688 {
1689 gref_t *gref;
1690 int s, rc;
1691 long bufaddr;
1692 gbuf_t *m, *mdata;
1693 short space;
1694 int size;
1695 struct atp_state *atp;
1696 struct atpBDS *bdsp;
1697 u_int16_t *bufsz;
1698 char *buf;
1699 int bds_cnt, count, len;
1700 caddr_t dataptr;
1701
1702 if ((*err = atalk_getref(0, fd, &gref, proc, 1)) != 0)
1703 return -1;
1704
1705 if ((gref == 0) || ((atp = (struct atp_state *)gref->info) == 0)
1706 || (atp->atp_flags & ATP_CLOSING)) {
1707 dPrintf(D_M_ATP, D_L_ERROR, ("ATPsndrsp: stale handle=0x%x, pid=%d\n",
1708 (u_int) gref, gref->pid));
1709
1710 file_drop(fd);
1711 *err = EINVAL;
1712 return -1;
1713 }
1714
1715 /*
1716 * allocate buffer and copy in the response info
1717 */
1718 if ((m = gbuf_alloc_wait(resplen, TRUE)) == 0) {
1719 *err = ENOMEM;
1720 file_drop(fd);
1721 return -1;
1722 }
1723 if ((*err = copyin(CAST_USER_ADDR_T(respbuff), (caddr_t)gbuf_rptr(m), resplen)) != 0) {
1724 gbuf_freeb(m);
1725 file_drop(fd);
1726 return -1;
1727 }
1728 gbuf_wset(m,resplen);
1729 ((at_ddp_t *)gbuf_rptr(m))->src_node = 0;
1730 bdsp = (struct atpBDS *)(gbuf_rptr(m) + TOTAL_ATP_HDR_SIZE);
1731
1732 /*
1733 * allocate buffers and copy in the response data.
1734 * note that only the size field of the atpBDS field
1735 * is used internally in the kernel.
1736 */
1737 bds_cnt = get_bds_entries(m); /* count of # entries */
1738 /* check correctness of parameters */
1739 if (bds_cnt > ATP_TRESP_MAX) {
1740 gbuf_freem(m);
1741 *err = EINVAL;
1742 file_drop(fd);
1743 return -1;
1744 }
1745
1746 for (size = 0, count = 0; count < bds_cnt; count++) {
1747 size += UAS_VALUE(bdsp[count].bdsBuffSz);
1748 }
1749 if (size > datalen) {
1750 gbuf_freem(m);
1751 *err = EINVAL;
1752 file_drop(fd);
1753 return -1;
1754 }
1755
1756 /* get the first mbuf */
1757 if ((mdata = gbuf_alloc_wait((space = (size > MCLBYTES ? MCLBYTES : size)), TRUE)) == 0) {
1758 gbuf_freem(m);
1759 file_drop(fd);
1760 *err = ENOMEM;
1761 return -1;
1762 }
1763 gbuf_cont(m) = mdata;
1764 dataptr = mtod(mdata, caddr_t);
1765 for (count = 0; count < bds_cnt; bdsp++, count++) {
1766 if ((bufaddr = UAL_VALUE(bdsp->bdsBuffAddr)) != 0 &&
1767 (len = UAS_VALUE(bdsp->bdsBuffSz)) != 0) {
1768 if (len > space) { /* enough room ? */
1769 gbuf_wset(mdata, dataptr - mtod(mdata, caddr_t)); /* set len of last mbuf */
1770 /* allocate the next mbuf */
1771 if ((gbuf_cont(mdata) = m_get((M_WAIT), MSG_DATA)) == 0) {
1772 gbuf_freem(m);
1773 file_drop(fd);
1774 *err = ENOMEM;
1775 return -1;
1776 }
1777 mdata = gbuf_cont(mdata);
1778 MCLGET(mdata, M_WAIT);
1779 if (!(mdata->m_flags & M_EXT)) {
1780 m_freem(m);
1781 file_drop(fd);
1782 return(NULL);
1783 }
1784 dataptr = mtod(mdata, caddr_t);
1785 space = MCLBYTES;
1786 }
1787 /* do the copyin */
1788 if ((*err = copyin(CAST_USER_ADDR_T(bufaddr), dataptr, len)) != 0) {
1789 gbuf_freem(m);
1790 file_drop(fd);
1791 return -1;
1792 }
1793 dataptr += len;
1794 space -= len;
1795 }
1796 }
1797 gbuf_wset(mdata, dataptr - mtod(mdata, caddr_t)); /* set len of last mbuf */
1798 gbuf_cont(m)->m_pkthdr.len = size; /* set packet hdr len */
1799
1800 atp_send_rsp(gref, m, TRUE);
1801 file_drop(fd);
1802 return 0;
1803 }
1804
1805 int
1806 _ATPgetreq(fd, buf, buflen, err, proc)
1807 int fd;
1808 unsigned char *buf;
1809 int buflen;
1810 int *err;
1811 void *proc;
1812 {
1813 gref_t *gref;
1814 register struct atp_state *atp;
1815 register struct atp_rcb *rcbp;
1816 register gbuf_t *m, *m_head;
1817 int s, size, len;
1818
1819 if ((*err = atalk_getref(0, fd, &gref, proc, 1)) != 0)
1820 return -1;
1821
1822 if ((gref == 0) || ((atp = (struct atp_state *)gref->info) == 0)
1823 || (atp->atp_flags & ATP_CLOSING)) {
1824 dPrintf(D_M_ATP, D_L_ERROR, ("ATPgetreq: stale handle=0x%x, pid=%d\n",
1825 (u_int) gref, gref->pid));
1826 file_drop(fd);
1827 *err = EINVAL;
1828 return -1;
1829 }
1830
1831 ATDISABLE(s, atp->atp_lock);
1832 if ((rcbp = atp->atp_attached.head) != NULL) {
1833 /*
1834 * Got one, move it to the active response Q
1835 */
1836 m_head = rcbp->rc_ioctl;
1837 rcbp->rc_ioctl = NULL;
1838
1839 if (rcbp->rc_xo) {
1840 ATP_Q_REMOVE(atp->atp_attached, rcbp, rc_list);
1841 rcbp->rc_state = RCB_NOTIFIED;
1842 ATP_Q_APPEND(atp->atp_rcb, rcbp, rc_list);
1843 } else {
1844 /* detach rcbp from attached queue,
1845 * and free any outstanding resources
1846 */
1847 atp_rcb_free(rcbp);
1848 }
1849 ATENABLE(s, atp->atp_lock);
1850
1851 /*
1852 * copyout the request data, including the protocol header
1853 */
1854 for (size=0, m=m_head; m; m = gbuf_cont(m)) {
1855 if ((len = gbuf_len(m)) > buflen)
1856 len = buflen;
1857 copyout((caddr_t)gbuf_rptr(m), CAST_USER_ADDR_T(&buf[size]), len);
1858 size += len;
1859 if ((buflen -= len) == 0)
1860 break;
1861 }
1862 gbuf_freem(m_head);
1863
1864 file_drop(fd);
1865 return size;
1866 }
1867 ATENABLE(s, atp->atp_lock);
1868
1869 file_drop(fd);
1870 return -1;
1871 }
1872
1873 int
1874 _ATPgetrsp(fd, bdsp, err, proc)
1875 int fd;
1876 struct atpBDS *bdsp;
1877 int *err;
1878 void *proc;
1879 {
1880 gref_t *gref;
1881 register struct atp_state *atp;
1882 register struct atp_trans *trp;
1883 int s, tid;
1884 char bds[atpBDSsize];
1885
1886 if ((*err = atalk_getref(0, fd, &gref, proc, 1)) != 0)
1887 return -1;
1888
1889 if ((gref == 0) || ((atp = (struct atp_state *)gref->info) == 0)
1890 || (atp->atp_flags & ATP_CLOSING)) {
1891 dPrintf(D_M_ATP, D_L_ERROR, ("ATPgetrsp: stale handle=0x%x, pid=%d\n",
1892 (u_int) gref, gref->pid));
1893 file_drop(fd);
1894 *err = EINVAL;
1895 return -1;
1896 }
1897
1898 ATDISABLE(s, atp->atp_lock);
1899 for (trp = atp->atp_trans_wait.head; trp; trp = trp->tr_list.next) {
1900 dPrintf(D_M_ATP, D_L_INFO,
1901 ("ATPgetrsp: atp:0x%x, trp:0x%x, state:%d\n",
1902 (u_int) atp, (u_int) trp, trp->tr_state));
1903
1904 switch (trp->tr_state) {
1905 case TRANS_DONE:
1906 ATENABLE(s, atp->atp_lock);
1907 if ((*err = copyin(CAST_USER_ADDR_T(bdsp),
1908 (caddr_t)bds, sizeof(bds))) != 0) {
1909 atp_free(trp);
1910 file_drop(fd);
1911 return -1;
1912 }
1913 if ((*err = atp_pack_bdsp(trp, (struct atpBDS *)bds)) != 0) {
1914 atp_free(trp);
1915 file_drop(fd);
1916 return -1;
1917 }
1918 tid = (int)trp->tr_tid;
1919 atp_free(trp);
1920 if ((*err = copyout((caddr_t)bds, CAST_USER_ADDR_T(bdsp), sizeof(bds))) != 0) {
1921 file_drop(fd);
1922 return -1;
1923 }
1924 file_drop(fd);
1925 return tid;
1926
1927 case TRANS_FAILED:
1928 /*
1929 * transaction timed out, return error
1930 */
1931 ATENABLE(s, atp->atp_lock);
1932 atp_free(trp);
1933 file_drop(fd);
1934 *err = ETIMEDOUT;
1935 return -1;
1936
1937 default:
1938 continue;
1939 }
1940 }
1941 ATENABLE(s, atp->atp_lock);
1942
1943 file_drop(fd);
1944 *err = EINVAL;
1945 return -1;
1946 }
1947
1948 void
1949 atp_drop_req(gref, m)
1950 gref_t *gref;
1951 gbuf_t *m;
1952 {
1953 int s;
1954 struct atp_state *atp;
1955 struct atp_rcb *rcbp;
1956 at_atp_t *athp;
1957 at_ddp_t *ddp;
1958
1959 atp = (struct atp_state *)gref->info;
1960 if (atp->dflag)
1961 atp = (struct atp_state *)atp->atp_msgq;
1962 ddp = AT_DDP_HDR(m);
1963 athp = AT_ATP_HDR(m);
1964
1965 /*
1966 * search for the corresponding rcb
1967 */
1968 ATDISABLE(s, atp->atp_lock);
1969 for (rcbp = atp->atp_rcb.head; rcbp; rcbp = rcbp->rc_list.next) {
1970 if ( (rcbp->rc_tid == UAS_VALUE(athp->tid)) &&
1971 (rcbp->rc_socket.node == ddp->src_node) &&
1972 (rcbp->rc_socket.net == NET_VALUE(ddp->src_net)) &&
1973 (rcbp->rc_socket.socket == ddp->src_socket) )
1974 break;
1975 }
1976
1977 /*
1978 * drop the request
1979 */
1980 if (rcbp)
1981 atp_rcb_free(rcbp);
1982 ATENABLE(s, atp->atp_lock);
1983
1984 gbuf_freem(m);
1985 }