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