1/* 2 * Copyright (c) 2000 Apple Computer, 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 * Copyright (c) 1996-1998 Apple Computer, Inc. 30 * All Rights Reserved. 31 */ 32 33/* Modified for MP, 1996 by Tuyen Nguyen 34 * Modified, March 17, 1997 by Tuyen Nguyen for MacOSX. 35 */ 36#include <sys/errno.h> 37#include <sys/types.h> 38#include <sys/param.h> 39#include <machine/spl.h> 40#include <sys/systm.h> 41#include <sys/kernel.h> 42#include <sys/proc.h> 43#include <sys/filedesc.h> 44#include <sys/fcntl.h> 45#include <sys/mbuf.h> 46#include <sys/ioctl.h> 47#include <sys/malloc.h> 48#include <sys/socket.h> 49 50#include <net/if.h> 51 52#include <netat/sysglue.h> 53#include <netat/appletalk.h> 54#include <netat/ddp.h> 55#include <netat/at_pcb.h> 56#include <netat/at_var.h> 57#include <netat/atp.h> 58#include <netat/asp.h> 59#include <netat/debug.h> 60 61__private_extern__ int atp_resp_seqno2big = 0; 62 63static void atp_trans_complete(struct atp_trans *); 64void atp_x_done_locked(void *); 65void atp_treq_event(void *); 66 67/* 68 * Decide what to do about received messages 69 * Version 1.7 of atp_read.c on 89/02/09 17:53:16 70 */ 71 72void atp_treq_event(void *arg) 73{ 74 register gref_t *gref = (gref_t *)arg; 75 register gbuf_t *m; 76 register struct atp_state *atp; 77 78 atalk_lock(); 79 atp = (struct atp_state *)gref->info; 80 if (atp->dflag) 81 atp = (struct atp_state *)atp->atp_msgq; 82 83 if (atp->dflag) { 84 if ((m = gbuf_alloc(sizeof(ioc_t), PRI_HI)) != NULL) { 85 gbuf_set_type(m, MSG_IOCTL); 86 gbuf_wset(m,sizeof(ioc_t)); 87 ((ioc_t *)gbuf_rptr(m))->ioc_cmd = AT_ATP_GET_POLL; 88 atp_wput(gref, m); 89 } 90 } 91 else if ((m = gbuf_alloc(1, PRI_HI)) != NULL) { 92 *gbuf_rptr(m) = 0; 93 gbuf_wset(m,1); 94 atalk_putnext(gref, m); 95 } 96 97 if (m == 0) 98 timeout(atp_treq_event, gref, 10); 99 atalk_unlock(); 100} 101 102void atp_rput(gref, m) 103gref_t *gref; 104gbuf_t *m; 105{ 106 register at_atp_t *athp; 107 register struct atp_state *atp; 108 gbuf_t *m_asp = NULL; 109 struct timeval timenow; 110 u_short temp_net; 111 112 atp = (struct atp_state *)gref->info; 113 if (atp->dflag) 114 atp = (struct atp_state *)atp->atp_msgq; 115 116 switch(gbuf_type(m)) { 117 case MSG_DATA: 118 /* 119 * Decode the message, make sure it is an atp 120 * message 121 */ 122 if (((AT_DDP_HDR(m))->type != DDP_ATP) || 123 (atp->atp_flags & ATP_CLOSING)) { 124 gbuf_freem(m); 125 dPrintf(D_M_ATP_LOW, (D_L_INPUT|D_L_ERROR), 126 ("atp_rput: dropping MSG, not atp\n")); 127 break; 128 } 129 130 athp = AT_ATP_HDR(m); 131 dPrintf(D_M_ATP_LOW, D_L_INPUT, 132 ("atp_rput MSG_DATA: %s (%d)\n", 133 (athp->cmd == ATP_CMD_TRESP)? "TRESP": 134 (athp->cmd == ATP_CMD_TREL)? "TREL": 135 (athp->cmd == ATP_CMD_TREQ)? "TREQ": "unknown", 136 athp->cmd)); 137 trace_mbufs(D_M_ATP_LOW, " r", m); 138 139 switch (athp->cmd) { 140 141 case ATP_CMD_TRESP: 142 { 143 register struct atp_trans *trp; 144 register unsigned int seqno; 145 register at_ddp_t *ddp; 146 147 /* 148 * we just got a response, find the trans record 149 */ 150 151 for (trp = atp->atp_trans_wait.head; trp; trp = trp->tr_list.next) { 152 if (trp->tr_tid == UAS_VALUE_NTOH(athp->tid)) 153 break; 154 } 155 156 /* 157 * If we can't find one then ignore the message 158 */ 159 seqno = athp->bitmap; 160 if (seqno > 7) { 161 atp_resp_seqno2big++; 162 ddp = AT_DDP_HDR(m); 163 dPrintf(D_M_ATP_LOW, (D_L_INPUT|D_L_ERROR), 164 ("atp_rput: dropping TRESP seqno too big, tid=%d,loc=%d,rem=%d.%d,seqno=%u\n", 165 UAS_VALUE_NTOH(athp->tid), 166 ddp->dst_socket, ddp->src_node, ddp->src_socket, seqno)); 167 gbuf_freem(m); 168 return; 169 } 170 if (trp == NULL) { 171 ddp = AT_DDP_HDR(m); 172 dPrintf(D_M_ATP_LOW, (D_L_INPUT|D_L_ERROR), 173 ("atp_rput: dropping TRESP, no trp,tid=%d,loc=%d,rem=%d.%d,seqno=%u\n", 174 UAS_VALUE_NTOH(athp->tid), 175 ddp->dst_socket, ddp->src_node, ddp->src_socket, seqno)); 176 gbuf_freem(m); 177 return; 178 } 179 180 /* 181 * If no longer valid, drop it 182 */ 183 if (trp->tr_state == TRANS_FAILED) { 184 ddp = AT_DDP_HDR(m); 185 dPrintf(D_M_ATP_LOW, (D_L_INPUT|D_L_ERROR), 186 ("atp_rput: dropping TRESP, failed trp,tid=%d,loc=%d,rem=%d.%d\n", 187 UAS_VALUE_NTOH(athp->tid), 188 ddp->dst_socket, ddp->src_node, ddp->src_socket)); 189 gbuf_freem(m); 190 return; 191 } 192 193 /* 194 * If we have already received it, ignore it 195 */ 196 if (!(trp->tr_bitmap&atp_mask[seqno]) || trp->tr_rcv[seqno]) { 197 ddp = AT_DDP_HDR(m); 198 dPrintf(D_M_ATP_LOW, (D_L_INPUT|D_L_ERROR), 199 ("atp_rput: dropping TRESP, duplicate,tid=%d,loc=%d,rem=%d.%d,seqno=%u\n", 200 UAS_VALUE_NTOH(athp->tid), 201 ddp->dst_socket, ddp->src_node, ddp->src_socket, seqno)); 202 gbuf_freem(m); 203 return; 204 } 205 206 /* 207 * Update the received packet bitmap 208 */ 209 if (athp->eom) 210 trp->tr_bitmap &= atp_lomask[seqno]; 211 else 212 trp->tr_bitmap &= ~atp_mask[seqno]; 213 214 /* 215 * Save the message in the trans record 216 */ 217 trp->tr_rcv[seqno] = m; 218 219 /* 220 * If it isn't the first message then 221 * can the header 222 */ 223 if (seqno) 224 gbuf_rinc(m,DDP_X_HDR_SIZE); 225 226 /* 227 * If we now have all the responses then return 228 * the message to the user 229 */ 230 if (trp->tr_bitmap == 0) { 231 232 /* 233 * Cancel the request timer and any 234 * pending transmits 235 */ 236 atp_untimout(atp_req_timeout, trp); 237 238 /* 239 * Send the results back to the user 240 */ 241 atp_x_done(trp); 242 return; 243 } 244 if (athp->sts) { 245 /* 246 * If they want treq again, send them 247 */ 248 atp_untimout(atp_req_timeout, trp); 249 atp_send(trp); 250 return; 251 } 252 return; 253 } 254 255 case ATP_CMD_TREL: 256 { register struct atp_rcb *rcbp; 257 register at_ddp_t *ddp; 258 259 /* 260 * Search for a matching transaction 261 */ 262 ddp = AT_DDP_HDR(m); 263 264 for (rcbp = atp->atp_rcb.head; rcbp; rcbp = rcbp->rc_list.next) { 265 if (rcbp->rc_tid == UAS_VALUE_NTOH(athp->tid) && 266 rcbp->rc_socket.node == ddp->src_node && 267 rcbp->rc_socket.net == NET_VALUE(ddp->src_net) && 268 rcbp->rc_socket.socket == ddp->src_socket) { 269 /* 270 * Mark the rcb released 271 */ 272 rcbp->rc_not_sent_bitmap = 0; 273 if (rcbp->rc_state == RCB_SENDING) 274 rcbp->rc_state = RCB_RELEASED; 275 else 276 { 277 ddp = 0; 278 atp_rcb_free(rcbp); 279 } 280 break; 281 } 282 } 283 284 gbuf_freem(m); 285 return; 286 } 287 288 289 case ATP_CMD_TREQ: 290 { register struct atp_rcb *rcbp; 291 register at_ddp_t *ddp; 292 gbuf_t *m2; 293 294 /* 295 * If it is a request message, first 296 * check to see 297 * if matches something in our active 298 * request queue 299 */ 300 ddp = AT_DDP_HDR(m); 301 302 for (rcbp = atp->atp_rcb.head; rcbp; rcbp = rcbp->rc_list.next) { 303 if (rcbp->rc_tid == UAS_VALUE_NTOH(athp->tid) && 304 rcbp->rc_socket.node == ddp->src_node && 305 rcbp->rc_socket.net == NET_VALUE(ddp->src_net) && 306 rcbp->rc_socket.socket == ddp->src_socket) 307 break; 308 } 309 /* 310 * If this is a new req then do 311 * something with it 312 */ 313 if (rcbp == NULL) { 314 /* 315 * see if it matches something in the 316 * attached request queue 317 * if it does, just release the message 318 * and go on about our buisness 319 */ 320 /* we just did this, why do again? -jjs 4-10-95 */ 321 for (rcbp = atp->atp_attached.head; rcbp; rcbp = rcbp->rc_list.next) { 322 if (rcbp->rc_tid == UAS_VALUE_NTOH(athp->tid) && 323 rcbp->rc_socket.node == ddp->src_node && 324 rcbp->rc_socket.net == NET_VALUE(ddp->src_net) && 325 rcbp->rc_socket.socket == ddp->src_socket) { 326 gbuf_freem(m); 327 dPrintf(D_M_ATP_LOW, D_L_INPUT, 328 ("atp_rput: dropping TREQ, matches req queue\n")); 329 return; 330 } 331 } 332 333 /* 334 * assume someone is interested in 335 * in an asynchronous incoming request 336 */ 337 if ((rcbp = atp_rcb_alloc(atp)) == NULL) { 338 gbuf_freem(m); 339 return; 340 } 341 rcbp->rc_state = RCB_UNQUEUED; 342 343 rcbp->rc_local_node = ddp->dst_node; 344 temp_net = NET_VALUE(ddp->dst_net); 345 NET_ASSIGN_NOSWAP(rcbp->rc_local_net, temp_net); 346 rcbp->rc_socket.socket = ddp->src_socket; 347 rcbp->rc_socket.node = ddp->src_node; 348 rcbp->rc_socket.net = NET_VALUE(ddp->src_net); 349 rcbp->rc_tid = UAS_VALUE_NTOH(athp->tid); 350 rcbp->rc_bitmap = athp->bitmap; 351 rcbp->rc_not_sent_bitmap = athp->bitmap; 352 rcbp->rc_xo = athp->xo; 353 /* 354 * if async then send it as 355 * data 356 * otherwise, it is a synchronous ioctl so 357 * complete it 358 */ 359 if (atp->dflag) { /* for ASP? */ 360 if ((m2 = gbuf_alloc(sizeof(ioc_t), PRI_HI))) { 361 gbuf_set_type(m2, MSG_DATA); 362 gbuf_wset(m2,sizeof(ioc_t)); 363 ((ioc_t *)gbuf_rptr(m2))->ioc_cmd = AT_ATP_GET_POLL; 364 m_asp = m2; 365 } 366 } else if ((m2 = gbuf_alloc(1, PRI_HI))) { 367 *gbuf_rptr(m2) = 0; 368 gbuf_wset(m2,1); 369 atalk_putnext(gref, m2); 370 } 371 if (m2 == 0) { 372 dPrintf(D_M_ATP,D_L_WARNING, 373 ("atp_rput: out of buffer for TREQ\n")); 374 timeout(atp_treq_event, gref, 10); 375 } 376 rcbp->rc_ioctl = m; 377 378 /* 379 * move it to the attached list 380 */ 381 dPrintf(D_M_ATP_LOW, D_L_INPUT, 382 ("atp_rput: moving to attached list\n")); 383 rcbp->rc_state = RCB_PENDING; 384 ATP_Q_APPEND(atp->atp_attached, rcbp, rc_list); 385 if (m_asp != NULL) { 386 atp_req_ind(atp, m_asp); 387 return; 388 } 389 } else { 390 dPrintf(D_M_ATP_LOW, D_L_INPUT, 391 ("atp_rput: found match, state:%d\n", 392 rcbp->rc_state)); 393 394 /* 395 * Otherwise we have found a matching request 396 * look for what to do 397 */ 398 switch (rcbp->rc_state) { 399 case RCB_RESPONDING: 400 case RCB_RESPONSE_FULL: 401 /* 402 * If it is one we have in progress 403 * (either have all the responses 404 * or are waiting for them) 405 * update the bitmap and resend 406 * the replies 407 */ 408 getmicrouptime(&timenow); 409 if (rcbp->rc_timestamp) { 410 rcbp->rc_timestamp = timenow.tv_sec; 411 if (rcbp->rc_timestamp == 0) 412 rcbp->rc_timestamp = 1; 413 } 414 rcbp->rc_bitmap = athp->bitmap; 415 rcbp->rc_not_sent_bitmap = athp->bitmap; 416 gbuf_freem(m); 417 atp_reply(rcbp); 418 return; 419 420 case RCB_RELEASED: 421 default: 422 /* 423 * If we have a release or 424 * we haven't sent any data yet 425 * ignore the request 426 */ 427 gbuf_freem(m); 428 return; 429 } 430 } 431 return; 432 } 433 434 default: 435 gbuf_freem(m); 436 break; 437 } 438 break; 439 440 case MSG_IOCACK: 441 if (atp->dflag) 442 asp_ack_reply(gref, m); 443 else 444 atalk_putnext(gref, m); 445 break; 446 447 case MSG_IOCNAK: 448 if (atp->dflag) 449 asp_nak_reply(gref, m); 450 else 451 atalk_putnext(gref, m); 452 break; 453 454 default: 455 gbuf_freem(m); 456 } 457} /* atp_rput */ 458 459void 460atp_x_done_locked(trp) 461void *trp; 462{ 463 atalk_lock(); 464 atp_x_done((struct atp_trans *)trp); 465 atalk_unlock(); 466 467} 468 469void 470atp_x_done(trp) 471register struct atp_trans *trp; 472{ 473 struct atp_state *atp; 474 gbuf_t *m; 475 476 477 if ( !trp->tr_xo) 478 atp_trans_complete(trp); 479 else { 480 /* 481 * If execute once send a release 482 */ 483 if ((m = (gbuf_t *)atp_build_release(trp)) != NULL) { 484 AT_DDP_HDR(m)->src_socket = ((struct atp_state *) 485 trp->tr_queue)->atp_socket_no; 486 DDP_OUTPUT(m); 487 /* 488 * Now send back the transaction reply to the process 489 * or notify the process if required 490 */ 491 atp_trans_complete(trp); 492 } else { 493 494 atp = trp->tr_queue; 495 trp->tr_state = TRANS_RELEASE; 496 timeout(atp_x_done_locked, trp, 10); 497 } 498 } 499} 500 501static void 502atp_trans_complete(trp) 503register struct atp_trans *trp; 504{ register gbuf_t *m; 505 register int type; 506 struct atp_state *atp; 507 508 /* we could gbuf_freem(trp->tr_xmt) here if were not planning to 509 re-use the mbuf later */ 510 m = trp->tr_xmt; 511 trp->tr_xmt = NULL; 512 trp->tr_state = TRANS_DONE; 513 514 if (gbuf_cont(m) == NULL) /* issued via the new interface */ 515 type = AT_ATP_ISSUE_REQUEST_NOTE; 516 else { 517 type = ((ioc_t *)(gbuf_rptr(m)))->ioc_cmd; 518 /* 519 * free any data following the ioctl blk 520 */ 521 gbuf_freem(gbuf_cont(m)); 522 gbuf_cont(m) = NULL; 523 } 524 dPrintf(D_M_ATP_LOW, D_L_INPUT, ("atp_trans_comp: trp=0x%x type = %s\n", 525 (u_int) trp, 526 (type==AT_ATP_ISSUE_REQUEST)? "AT_ATP_ISSUE_REQUEST": 527 (type==AT_ATP_ISSUE_REQUEST_NOTE)? "AT_ATP_ISSUE_REQUEST_NOTE" : 528 "unknown")); 529 530 switch(type) { 531 case AT_ATP_ISSUE_REQUEST: 532 atp = trp->tr_queue; 533 if (atp->dflag) { 534 ((ioc_t *)gbuf_rptr(m))->ioc_count = 0; 535 ((ioc_t *)gbuf_rptr(m))->ioc_error = 0; 536 ((ioc_t *)gbuf_rptr(m))->ioc_rval = trp->tr_tid; 537 ((ioc_t *)gbuf_rptr(m))->ioc_cmd = AT_ATP_REQUEST_COMPLETE; 538 gbuf_set_type(m, MSG_IOCTL); 539 atp_rsp_ind(trp, m); 540 } else { 541 if (trp->tr_bdsp == NULL) { 542 gbuf_freem(m); 543 if (trp->tr_rsp_wait) 544 wakeup(&trp->tr_event); 545 } else { 546 gbuf_set_type(m, MSG_IOCACK); 547 ((ioc_t *)gbuf_rptr(m))->ioc_count = 0; 548 ((ioc_t *)gbuf_rptr(m))->ioc_error = 0; 549 ((ioc_t *)gbuf_rptr(m))->ioc_rval = 0; 550 atalk_putnext(trp->tr_queue->atp_gref, m); 551 } 552 } 553 break; 554 555 case AT_ATP_ISSUE_REQUEST_NOTE: 556 gbuf_wset(m,1); 557 *gbuf_rptr(m) = 1; 558 gbuf_set_type(m, MSG_DATA); 559 atalk_putnext(trp->tr_queue->atp_gref, m); 560 break; 561 } 562} /* atp_trans_complete */ 563