2  * Copyright (c) 1995-2007 Apple Inc. All rights reserved. 
   4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 
   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. 
  15  * Please obtain a copy of the License at 
  16  * http://www.opensource.apple.com/apsl/ and read it before using this file. 
  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. 
  26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 
  30  *    Created February 20, 1995 by Tuyen Nguyen 
  31  *    Modified for MP, 1996 by Tuyen Nguyen 
  32  *   Modified, March 17, 1997 by Tuyen Nguyen for MacOSX. 
  35 #include <sys/errno.h> 
  36 #include <sys/types.h> 
  37 #include <sys/param.h> 
  38 #include <machine/spl.h> 
  39 #include <sys/systm.h> 
  40 #include <sys/kernel.h> 
  42 #include <sys/filedesc.h> 
  43 #include <sys/fcntl.h> 
  45 #include <sys/ioctl.h> 
  46 #include <sys/malloc.h> 
  47 #include <kern/locks.h> 
  48 #include <sys/socket.h> 
  49 #include <sys/socketvar.h> 
  53 #include <netat/sysglue.h> 
  54 #include <netat/appletalk.h> 
  55 #include <netat/at_pcb.h> 
  56 #include <netat/atp.h> 
  57 #include <netat/ddp.h> 
  58 #include <netat/asp.h> 
  59 #include <netat/at_var.h> 
  60 #include <netat/debug.h> 
  63 #define atpBDSsize    (sizeof(struct atpBDS)*ATP_TRESP_MAX) 
  64 #define aspCMDsize    (atpBDSsize+sizeof(struct atp_set_default)+TOTAL_ATP_HDR_SIZE) 
  65 #define SCBS_PER_BLK  16 
  66 #define TICKS_PER_SEC HZ 
  67 #define SESS_TMO_RES  2 
  68 #define DEF_SESS_TMO  120 
  69 #define NEXT_SEQ_NUM(x) (x = (x == 65535) ? 0 : (x + 1)) 
  71 #define BAD_REMADDR(addr) \ 
  72         ( (*(long *)&scb->rem_addr != *(long *)&addr) \ 
  73         && ((scb->rem_addr.net != addr.net) \ 
  74                 || (scb->rem_addr.node != addr.node)) ) 
  76 StaticProc asp_scb_t 
*asp_find_scb(unsigned char, at_inet_t 
*); 
  77 StaticProc asp_scb_t 
*asp_scb_alloc(void); 
  79 StaticProc 
void asp_putnext(gref_t 
*, gbuf_t 
*); 
  80 StaticProc 
void asp_iocack(gref_t 
*, gbuf_t 
*); 
  81 StaticProc 
void asp_iocnak(gref_t 
*, gbuf_t 
*, int); 
  82 StaticProc 
void asp_dequeue_scb(asp_scb_t 
*); 
  83 StaticProc 
void asp_scb_free(asp_scb_t 
*); 
  84 StaticProc 
void asp_timout(asp_tmo_func
,  asp_scb_t 
*, int); 
  85 StaticProc 
void asp_untimout(asp_tmo_func
,  asp_scb_t 
*); 
  86 StaticProc 
void asp_hangup(asp_scb_t 
*); 
  87 StaticProc 
void asp_send_tickle(asp_scb_t 
*); 
  88 StaticProc 
void asp_send_tickle_locked(void *); 
  89 StaticProc 
void asp_accept(asp_scb_t 
*scb
, asp_scb_t 
*sess_scb
, gbuf_t 
*m
); 
  90 StaticProc 
int  asp_send_req(gref_t 
*, gbuf_t 
*, at_inet_t 
*, at_retry_t 
*, asp_word_t 
*,  
  91                                                         unsigned char , unsigned char, unsigned char); 
  93 extern at_ifaddr_t 
*ifID_home
; 
  94 extern int atp_pidM
[]; 
  95 extern gref_t 
*atp_inputQ
[]; 
  96 extern lck_mtx_t 
*atalk_mutex
; 
  97 gbuf_t 
*scb_resource_m 
= 0; 
  98 unsigned char asp_inpC
[256]; 
  99 asp_scb_t 
*asp_scbQ
[256]; 
 101 static at_retry_t asp_def_retry 
= {2, -1, 1}; 
 102 static unsigned char scb_tmo_cnt
; 
 103 asp_scb_t 
*scb_used_list
; 
 104 static asp_scb_t 
*scb_tmo_list
; 
 105 asp_scb_t 
*scb_free_list
; 
 107 int asp_readable(gref_t 
*); 
 113         return (((asp_scb_t 
*)gref
->info
)->sess_ioc 
? 1 : 0); 
 123         bzero(asp_inpC
, sizeof(asp_inpC
)); 
 124         bzero(asp_scbQ
, sizeof(asp_scbQ
)); 
 128  * the open routine allocates a state structure 
 136          * if no asp structure available, return failure 
 138         if ((scb 
= asp_scb_alloc()) == 0) 
 142          * initialize the gref data structure 
 144         gref
->info 
= (void *)scb
; 
 145         gref
->readable 
= asp_readable
; 
 148          * initialize the scb data structure 
 151         scb
->magic_num 
= 222; 
 152         scb
->state 
= ASPSTATE_Idle
; 
 153         scb
->pid 
= gref
->pid
; 
 155         scb
->session_timer 
= DEF_SESS_TMO
; 
 156         scb
->cmd_retry 
= asp_def_retry
; 
 157         if ((scb
->next_scb 
= scb_used_list
) != 0) 
 158                 scb
->next_scb
->prev_scb 
= scb
; 
 164         dPrintf(D_M_ASP
, D_L_INFO
, ("asp_open: pid=%d\n", scb
->pid
)); 
 169  * the close routine frees all the data structures 
 175         unsigned char sock_num
; 
 176         asp_scb_t 
*scb
, *new_scb
; 
 179         scb 
= (asp_scb_t 
*)gref
->info
; 
 180         dPrintf(D_M_ASP
, D_L_INFO
, ("asp_close: loc=%d\n", 
 181                 scb
->loc_addr
.socket
)); 
 183         if (scb
->pid 
&& scb
->sess_ioc 
&& (scb
->dflag 
!= 1)) { 
 185                  * send the CloseSess response to peer 
 187                 if (gbuf_type(scb
->sess_ioc
) != MSG_PROTO
) { 
 189                         scb
->sess_ioc 
= gbuf_next(m
); 
 190                         atp_send_rsp(scb
->gref
, m
, TRUE
); 
 194         if (scb
->atp_state
) { 
 195                 sock_num 
= scb
->loc_addr
.socket
; 
 196                 if ((scb
->dflag 
!= 1) && scb
->stat_msg
) { 
 197                         untimeout(atp_retry_req
, scb
->stat_msg
); 
 198                         gbuf_freem(scb
->stat_msg
); 
 201                 if (asp_scbQ
[sock_num
]->next_scb 
== 0) { 
 202                         asp_scbQ
[sock_num
] = 0; 
 203                         asp_inpC
[sock_num
] = 0; 
 204                         dPrintf(D_M_ASP
, D_L_INFO
, 
 205                         ("         : atp_close(), loc=%d\n", scb
->loc_addr
.socket
)); 
 208                         asp_inpC
[sock_num
]--; 
 209                         if (scb 
== asp_scbQ
[sock_num
]) { 
 210                                 new_scb 
= scb
->next_scb
; 
 211                                 new_scb
->prev_scb 
= 0; 
 212                                 asp_scbQ
[sock_num
] = new_scb
; 
 213                                 new_scb
->atp_state
->atp_gref 
= new_scb
->gref
; 
 214                                 new_scb
->atp_state
->pid 
= new_scb
->pid
; 
 215                                 atp_inputQ
[sock_num
] = new_scb
->gref
; 
 217                                 if ((scb
->prev_scb
->next_scb 
= scb
->next_scb
) != 0) 
 218                                         scb
->next_scb
->prev_scb 
= scb
->prev_scb
; 
 223                 asp_dequeue_scb(scb
); 
 226          * free all allocated blocks if any 
 229                 gbuf_freem(scb
->stat_msg
); 
 233                 gbuf_freel(scb
->sess_ioc
); 
 237                 gbuf_freel(scb
->req_msgq
); 
 241         scb
->rem_addr
.node 
= 0; 
 247         asp_untimout(asp_hangup
, scb
); 
 248         untimeout(asp_send_tickle_locked
, (void *)scb
); /* added for 2225395 */ 
 251          * free the asp session control block 
 253         scb
->state 
= ASPSTATE_Close
; 
 260 static const char *aspStateStr(int); 
 262 static const char *aspStateStr(state
) 
 265   return ((state
==ASPSTATE_Close
)? "Close": 
 266           (state
==ASPSTATE_Idle
)? "Idle": 
 267           (state
==ASPSTATE_WaitingForGetStatusRsp
)? "GetStatusRsp": 
 268           (state
==ASPSTATE_WaitingForOpenSessRsp
)? "OpenSessRsp": 
 269           (state
==ASPSTATE_WaitingForCommandRsp
)? "CmdRsp": 
 270           (state
==ASPSTATE_WaitingForWriteContinue
)? "WriteCont": 
 271           (state
==ASPSTATE_WaitingForWriteRsp
)? "WriteRsp": 
 272           (state
==ASPSTATE_WaitingForWriteContinueRsp
)? "WriteContRsp": 
 273           (state
==ASPSTATE_WaitingForCloseSessRsp
)? "CloseSessRsp": 
 277 static const char *aspCmdStr(int); 
 279 static const char *aspCmdStr(aspCmd
) 
 282 return ((aspCmd
==ASPFUNC_CloseSess
)? "CloseSess": 
 283         (aspCmd
==ASPFUNC_Command
)? "Command": 
 284         (aspCmd
==ASPFUNC_GetStatus
)? "GetStatus": 
 285         (aspCmd
==ASPFUNC_OpenSess
)? "OpenSess": 
 286         (aspCmd
==ASPFUNC_Tickle
)? "Tickle": 
 287         (aspCmd
==ASPFUNC_Write
)? "Write": 
 288         (aspCmd
==ASPFUNC_WriteContinue
)? "WriteContinue": 
 289         (aspCmd
==ASPFUNC_Attention
)? "Attention": 
 290         (aspCmd
==ASPFUNC_CmdReply
)? "CmdReply": "unknown"); 
 293 static const char *aspIOCStr(int); 
 295 static const char *aspIOCStr(aspIOC
) 
 299         (aspIOC
==ASPIOC_ClientBind
)? "ClientBind": 
 300         (aspIOC
==ASPIOC_CloseSession
)? "CloseSession": 
 301         (aspIOC
==ASPIOC_GetLocEntity
)? "GetLocEntity": 
 302         (aspIOC
==ASPIOC_GetRemEntity
)? "GetRemEntity": 
 303         (aspIOC
==ASPIOC_GetSession
)? "GetSession": 
 304         (aspIOC
==ASPIOC_GetStatus
)? "GetStatus": 
 305         (aspIOC
==ASPIOC_ListenerBind
)? "ListenerBind": 
 306         (aspIOC
==ASPIOC_OpenSession
)? "OpenSession": 
 307         (aspIOC
==ASPIOC_StatusBlock
)? "StatusBlock": 
 308         (aspIOC
==ASPIOC_SetPid
)? "SetPid": 
 309         (aspIOC
==ASPIOC_GetSessId
)? "GetSessId": 
 310         (aspIOC
==ASPIOC_EnableSelect
)? "EnableSelect": 
 311         (aspIOC
==ASPIOC_Look
)? "Look": 
 319 static char mbuf_str
[100]; 
 324           "dat = %d, prot = %d, ioc = %d, err = %d, hu = %d, ack = %d, nak = %d, ctl = %d", 
 326           "dat = %d, prot = %d, ioc = %d, ctl = %d", 
 327           mbstat
.m_mtypes
[MSG_DATA
], mbstat
.m_mtypes
[MSG_PROTO
], mbstat
.m_mtypes
[MSG_IOCTL
], 
 329           mbstat.m_mtypes[MSG_ERROR], mbstat.m_mtypes[MSG_HANGUP], mbstat.m_mtypes[MSG_IOCACK], 
 330           mbstat.m_mtypes[MSG_IOCNAK],  
 332           mbstat
.m_mtypes
[MSG_CTL
]); 
 333   return(&mbuf_str
[0]); 
 336 void trace_beg(str
, m
) 
 341         gbuf_t 
*mdata
, *mchain
; 
 344           for (i 
= 0, j 
= 0, mdata 
= m
, mchain 
= m
; mdata
; i
++) { 
 345             mdata 
= gbuf_cont(mdata
); 
 346             if (!mdata 
&& mchain
) { 
 347               mdata 
= gbuf_next(mchain
); 
 352         dPrintf(D_M_ASP
, D_L_TRACE
, 
 353                 ("%s: %s, m# = %d, c# = %d\n", str
, mbuf_totals(), i
, j
)); 
 359         dPrintf(D_M_ASP
, D_L_TRACE
, 
 360                 ("  %s: %s\n", str
, mbuf_totals())); 
 362 #endif /* AT_MBUF_TRACE */ 
 367 int asp_wput(gref
, m
) 
 372         unsigned char sockSav
, sock_num
; 
 373         gbuf_t 
*mioc
, *mdata
; 
 375         asp_scb_t 
*scb
, *server_scb
, *curr_scb
; 
 378         union asp_primitives 
*primitives
; 
 379         asp_status_cmd_t 
*status_cmd
; 
 380         asp_open_cmd_t 
*open_cmd
; 
 383         scb 
= (asp_scb_t 
*)gref
->info
; 
 384         if (scb
->dflag 
== 0) { 
 389         if (gbuf_type(m
) != MSG_IOCTL
) { 
 390                 dPrintf(D_M_ASP
, D_L_WARNING
, 
 391                         ("asp_wput: UNKNOWN message, type=%d\n",  
 398         iocbp 
= (ioc_t 
*)gbuf_rptr(mioc
); 
 400         dPrintf(D_M_ASP_LOW
, D_L_INFO
, 
 401                 ("asp_wput: %s, loc=%d, state=%s\n",  
 402                  aspIOCStr(iocbp
->ioc_cmd
), scb
->loc_addr
.socket
,  
 403                  aspStateStr(scb
->state
))); 
 405         switch (iocbp
->ioc_cmd
) { 
 406         case ASPIOC_CloseSession
: 
 407                 if ((scb
->state 
== ASPSTATE_Close
) || (scb
->rem_addr
.node 
== 0)) 
 412                 aw
.func 
= ASPFUNC_CloseSess
; 
 413                 aw
.param1 
= scb
->sess_id
; 
 415                 iocbp
->ioc_private 
= (void *)scb
; 
 416                 scb
->ioc_wait 
= (unsigned char)(iocbp
->ioc_cmd 
& 0xff); 
 417                 iocbp
->ioc_cmd 
= AT_ATP_ISSUE_REQUEST
; 
 418                 asp_send_req(gref
, mioc
, &scb
->rem_addr
, &Retry
, &aw
,  
 419                              0, ASPSTATE_WaitingForCloseSessRsp
, 0x01); 
 422         case ASPIOC_ClientBind
: 
 424                  * open an ATP channel 
 426                 if ((err 
= atp_open(gref
, 0)) != 0) { 
 427                         asp_iocnak(gref
, mioc
, err
); 
 430                 scb
->atp_state 
= (atp_state_t 
*)gref
->info
; 
 431                 scb
->atp_state
->pid 
= scb
->pid
; 
 433                  * bind to any available socket 
 436                 sockSav 
= scb
->dflag
; 
 437                 if ((sock_num 
= (at_socket
)atp_bind(gref
, 0, &sockSav
)) == 0) { 
 438                         scb
->atp_state 
= (atp_state_t 
*)0; 
 440                         gref
->info 
= (void *)scb
; 
 441                         asp_iocnak(gref
, mioc
, EINVAL
); 
 444                 gref
->info 
= (void *)scb
; 
 445                 asp_dequeue_scb(scb
); 
 446                 scb
->atp_state
->dflag 
= scb
->dflag
; 
 447                 scb
->loc_addr
.socket 
= sock_num
; 
 448                 asp_scbQ
[sock_num
] = scb
; 
 449                 asp_inpC
[sock_num
]++; 
 450                 atp_pidM
[sock_num
] = 0; 
 453         case ASPIOC_ListenerBind
: 
 455                  * open an ATP channel 
 457                 if ((err 
= atp_open(gref
, 0)) != 0) { 
 458                         asp_iocnak(gref
, mioc
, err
); 
 461                 scb
->atp_state 
= (atp_state_t 
*)gref
->info
; 
 462                 scb
->atp_state
->pid 
= scb
->pid
; 
 464                  * bind to any available socket 
 466                 if ((sock_num 
= (at_socket
)atp_bind(gref
, 0, 0)) == 0) { 
 467                         scb
->atp_state 
= (atp_state_t 
*)0; 
 469                         gref
->info 
= (void *)scb
; 
 470                         asp_iocnak(gref
, mioc
, EINVAL
); 
 473                 gref
->info 
= (void *)scb
; 
 474                 asp_dequeue_scb(scb
); 
 475                 scb
->atp_state
->dflag 
= scb
->dflag
; 
 476                 scb
->loc_addr
.socket 
= sock_num
; 
 477                 asp_scbQ
[sock_num
] = scb
; 
 478                 asp_inpC
[sock_num
]++; 
 480                         *(at_inet_t 
*)gbuf_rptr(gbuf_cont(mioc
)) = scb
->loc_addr
; 
 483         case ASPIOC_GetLocEntity
: 
 484                 if ((gbuf_cont(mioc
) == 0) || (scb
->atp_state 
== 0)) { 
 485                         asp_iocnak(gref
, mioc
, EPROTOTYPE
); 
 488                 *(at_inet_t 
*)gbuf_rptr(gbuf_cont(mioc
)) = scb
->loc_addr
; 
 491         case ASPIOC_GetRemEntity
: 
 492                 if ((gbuf_cont(mioc
) == 0) || (scb
->atp_state 
== 0)) { 
 493                         asp_iocnak(gref
, mioc
, EPROTOTYPE
); 
 496                 *(at_inet_t 
*)gbuf_rptr(gbuf_cont(mioc
)) = scb
->rem_addr
; 
 499         case ASPIOC_GetSession
: 
 500                 if ((mdata 
= gbuf_cont(mioc
)) == 0) { 
 501                         asp_iocnak(gref
, mioc
, EPROTOTYPE
); 
 504                 addr 
= (at_inet_t 
*)gbuf_rptr(mdata
); 
 505                 scb
->tickle_interval 
= (unsigned short)addr
->node
; 
 506                 scb
->session_timer 
= addr
->net
; 
 507                 server_scb 
= asp_scbQ
[addr
->socket
]; 
 508 /*### LD 10/28/97: changed to make sure we're not accessing a null server_scb */ 
 509                 if (server_scb 
== 0) { 
 510                         asp_iocnak(gref
, mioc
, EPROTOTYPE
); 
 513                 if (server_scb
->sess_ioc 
== 0) { 
 514                         asp_iocnak(gref
, mioc
, EPROTOTYPE
); 
 519                  * open an ATP channel 
 521                 if ((err 
= atp_open(gref
, 0)) != 0) { 
 522                         gref
->info 
= (void *)scb
; 
 523                         asp_iocnak(gref
, mioc
, err
); 
 526                 scb
->atp_state 
= (atp_state_t 
*)gref
->info
; 
 527                 scb
->atp_state
->pid 
= scb
->pid
; 
 529                  * bind to any available socket 
 532                 sockSav 
= scb
->dflag
; 
 533                 if ((sock_num 
= (at_socket
)atp_bind(gref
, 0, &sockSav
)) == 0) { 
 535                         asp_dequeue_scb(scb
); 
 537                         scb
->loc_addr
.socket 
= sock_num
; 
 538                         for (curr_scb 
= asp_scbQ
[sock_num
]; 
 539                                 curr_scb
->next_scb
; curr_scb 
= curr_scb
->next_scb
) ; 
 540                         scb
->prev_scb 
= curr_scb
; 
 541                         curr_scb
->next_scb 
= scb
; 
 542                         scb
->atp_state 
= curr_scb
->atp_state
; 
 544                         asp_dequeue_scb(scb
); 
 545                         scb
->loc_addr
.socket 
= sock_num
; 
 546                         asp_scbQ
[sock_num
] = scb
; 
 547                         scb
->atp_state
->dflag 
= scb
->dflag
; 
 549                 gref
->info 
= (void *)scb
; 
 550                 asp_inpC
[sock_num
]++; 
 552                 asp_accept(server_scb
, scb
, mdata
); 
 555         case ASPIOC_GetStatus
: 
 556                 if ((mdata 
= gbuf_cont(mioc
)) == 0) { 
 557                         asp_iocnak(gref
, mioc
, EINVAL
); 
 561                 status_cmd 
= (asp_status_cmd_t 
*)gbuf_rptr(mdata
); 
 562                 aw
.func 
= ASPFUNC_GetStatus
; 
 565                 scb
->ioc_wait 
= (unsigned char)(iocbp
->ioc_cmd 
& 0xff); 
 566                 iocbp
->ioc_cmd 
= AT_ATP_ISSUE_REQUEST_DEF
; 
 567                 /* bms:  make sure this is an ALO request */ 
 568                 asp_send_req(gref
, mioc
, &status_cmd
->SLSEntityIdentifier
, 
 569                              &status_cmd
->Retry
, &aw
, 0, ASPSTATE_WaitingForGetStatusRsp
, 0xff); 
 573         case ASPIOC_OpenSession
: 
 574                 if ((mdata 
= gbuf_cont(mioc
)) == 0) { 
 575                         asp_iocnak(gref
, mioc
, EINVAL
); 
 579                 open_cmd 
= (asp_open_cmd_t 
*)gbuf_rptr(mdata
); 
 580                 scb
->svc_addr 
= open_cmd
->SLSEntityIdentifier
; 
 581                 scb
->rem_addr 
= scb
->svc_addr
; 
 582                 scb
->rem_node 
= scb
->rem_addr
.node
; 
 583                 scb
->rem_addr
.node 
= 0; 
 584                 scb
->tickle_interval 
= open_cmd
->TickleInterval
; 
 585                 scb
->session_timer 
= open_cmd
->SessionTimer
; 
 586                 aw
.func 
= ASPFUNC_OpenSess
; 
 587                 aw
.param1 
= scb
->loc_addr
.socket
; 
 588                 aw
.param2 
= htons(ASP_Version
); 
 589                 scb
->ioc_wait 
= (unsigned char)(iocbp
->ioc_cmd 
& 0xff); 
 590                 iocbp
->ioc_cmd 
= AT_ATP_ISSUE_REQUEST_DEF
; 
 591                 asp_send_req(gref
, mioc
, &open_cmd
->SLSEntityIdentifier
, 
 592                              &open_cmd
->Retry
, &aw
, 1, ASPSTATE_WaitingForOpenSessRsp
, 0x01); 
 596         case ASPIOC_StatusBlock
: 
 598                  * save the server status block 
 601                         gbuf_freem(scb
->stat_msg
); 
 602           scb
->stat_msg 
= gbuf_cont(mioc
); 
 606           /* *** Does scb->pid get used in a packet header, 
 607                  and if so is it in ASP, or in ATP?  
 608                  If not, do we need this call for anything? 
 609                  (cap does currently use it in _ANS code.) 
 612                 if (gbuf_cont(mioc
) == 0) { 
 613                         asp_iocnak(gref
, mioc
, EINVAL
); 
 616                 scb
->pid 
= *(int *)gbuf_rptr(gbuf_cont(mioc
)); 
 619         case ASPIOC_GetSessId
: 
 620                 if (gbuf_cont(mioc
) == 0) { 
 621                         asp_iocnak(gref
, mioc
, EINVAL
); 
 624                 *(gref_t 
**)gbuf_rptr(gbuf_cont(mioc
)) = gref
; 
 628                 if (gbuf_cont(mioc
) == 0) { 
 629                         asp_iocnak(gref
, mioc
, EINVAL
); 
 633                         primitives 
= (union asp_primitives 
*)gbuf_rptr(scb
->sess_ioc
); 
 634                         if (primitives
->Primitive 
== ASPFUNC_CmdReply
) 
 635                                 *(int *)gbuf_rptr(gbuf_cont(mioc
)) = 0; 
 637                                 *(int *)gbuf_rptr(gbuf_cont(mioc
)) = 1; 
 639                         *(int *)gbuf_rptr(gbuf_cont(mioc
)) = -1; 
 642         case DDP_IOC_GET_CFG
: 
 644                 struct atp_state 
*atp 
= (struct atp_state 
*)gref
->info
; 
 646                         atp 
= (struct atp_state 
*)atp
->atp_msgq
; 
 648                 if (gbuf_cont(mioc
) == 0) { 
 649                         asp_iocnak(gref
, mioc
, EINVAL
); 
 652                 /* *** borrowed from ddp_proto.c to handle DDP_IOC_GET_CFG 
 654                 scb
->state 
= ASPSTATE_Idle
; 
 656                 /* *** was ddp_get_cfg() *** */ 
 658                     (ddp_addr_t 
*)gbuf_rptr(gbuf_cont(mioc
)); 
 659                   cfgp
->inet
.net 
= ifID_home
->ifThisNode
.s_net
; 
 660                   cfgp
->inet
.node 
= ifID_home
->ifThisNode
.s_node
; 
 661                   cfgp
->inet
.socket 
= atp
->atp_socket_no
; 
 662                   cfgp
->ddptype 
= DDP_ATP
; 
 664                 gbuf_wset(gbuf_cont(mioc
), sizeof(at_inet_t
)); 
 669                 asp_iocnak(gref
, mioc
, EINVAL
); 
 673         asp_iocack(gref
, mioc
); 
 678  * send request routine 
 681 asp_send_req(gref
, mioc
, dest
, retry
, awp
, xo
, state
, bitmap
) 
 689         unsigned char bitmap
; 
 694         struct atp_set_default 
*sd
; 
 697         struct atpBDS 
*atpBDS
; 
 698         asp_scb_t 
*scb 
= (asp_scb_t 
*)gref
->info
; 
 701          * allocate an ATP buffer for the request 
 703         if ((gbuf_cont(mioc
) = gbuf_alloc(aspCMDsize
, PRI_MED
)) == 0) { 
 704                 if (awp
->func 
== ASPFUNC_Tickle
) 
 707                         asp_iocnak(gref
, mioc
, ENOBUFS
); 
 708                 dPrintf(D_M_ASP
, D_L_WARNING
, 
 709                 ("asp_send_req: ENOBUFS, loc=%d\n", scb
->loc_addr
.socket
)); 
 713         mdata 
= gbuf_cont(mioc
); 
 714         iocbp 
= (ioc_t 
*)gbuf_rptr(mioc
); 
 719         atpBDS 
= (struct atpBDS 
*)gbuf_rptr(mdata
); 
 720         gbuf_wset(mdata
,atpBDSsize
); 
 721         for (i
=0; i 
< ATP_TRESP_MAX
; i
++) { 
 722                 *(unsigned long  *)atpBDS
[i
].bdsBuffAddr 
= 1; 
 723                 *(unsigned short *)atpBDS
[i
].bdsBuffSz 
= ATP_DATA_SIZE
; 
 725         sd 
= (struct atp_set_default 
*)gbuf_wptr(mdata
); 
 726         gbuf_winc(mdata
,sizeof(struct atp_set_default
)); 
 727         sd
->def_retries 
= (retry
->retries 
== -1) ? 
 728                 ATP_INFINITE_RETRIES 
: retry
->retries
; 
 729         sd
->def_rate 
= retry
->interval
*TICKS_PER_SEC
; 
 730         sd
->def_BDSlen 
= atpBDSsize
; 
 731         ddp 
= (at_ddp_t 
*)gbuf_wptr(mdata
); 
 732         NET_ASSIGN(ddp
->src_net
, scb
->loc_addr
.net
); 
 733         ddp
->src_node 
= scb
->loc_addr
.node
; 
 734         NET_ASSIGN(ddp
->dst_net
, dest
->net
); 
 735         ddp
->dst_node 
= dest
->node
; 
 736         ddp
->dst_socket 
= dest
->socket
; 
 737         UAS_ASSIGN(ddp
->checksum
, 0); 
 738         atp 
= ATP_ATP_HDR(gbuf_wptr(mdata
)); 
 741         atp
->bitmap 
= bitmap
; 
 742         gbuf_winc(mdata
,TOTAL_ATP_HDR_SIZE
); 
 743         *(asp_word_t 
*)atp
->user_bytes 
= *awp
; 
 744         iocbp
->ioc_count 
= gbuf_len(mdata
); 
 751         dPrintf(D_M_ASP
, D_L_INFO
, 
 752                 ("asp_send_req: %s, loc=%d, rem= %d, len=%d, state=%s\n", 
 753                  aspCmdStr(awp
->func
), 
 754                  scb
->loc_addr
.socket
, ddp
->dst_socket
, iocbp
->ioc_count
, 
 755                  aspStateStr(scb
->state
))); 
 757         atp_send_req(gref
, mioc
); 
 762  * send tickle routine - locked version 
 765 asp_send_tickle_locked(scb
) 
 769         asp_send_tickle((asp_scb_t 
*)scb
); 
 775  * send tickle routine 
 788          * make sure the connection is still there 
 790         if (scb
->rem_addr
.node 
== 0) { 
 794         if ((mioc 
= gbuf_alloc(sizeof(ioc_t
), PRI_HI
)) == 0) { 
 795                 dPrintf(D_M_ASP
, D_L_WARNING
, 
 796                 ("asp_send_tickle: ENOBUFS 0, loc=%d, rem=%d\n", 
 797                         scb
->loc_addr
.socket
,scb
->rem_addr
.socket
)); 
 798                 timeout(asp_send_tickle_locked
, (void *)scb
, 10); 
 801         gbuf_wset(mioc
,sizeof(ioc_t
)); 
 802         gbuf_set_type(mioc
, MSG_IOCTL
); 
 804         dest 
= scb
->svc_addr
.node 
? 
 805                 (at_inet_t 
*)&scb
->svc_addr 
: (at_inet_t 
*)&scb
->rem_addr
; 
 806         retry
.interval 
= scb
->tickle_interval
; 
 809         aw
.func 
= ASPFUNC_Tickle
; 
 810         aw
.param1 
= scb
->sess_id
; 
 812         ((ioc_t 
*)gbuf_rptr(mioc
))->ioc_cr 
= (void *)scb
; 
 813         ((ioc_t 
*)gbuf_rptr(mioc
))->ioc_cmd 
= AT_ATP_ISSUE_REQUEST_TICKLE
; 
 815         if (asp_send_req(scb
->gref
, mioc
, dest
, &retry
, &aw
, 0, scb
->state
, 0)) { 
 816                 dPrintf(D_M_ASP
, D_L_WARNING
, 
 817                         ("asp_send_tickle: ENOBUFS 1, loc=%d, rem=%d\n", 
 818                          scb
->loc_addr
.socket
,scb
->rem_addr
.socket
)); 
 820                 timeout(asp_send_tickle_locked
, (void *)scb
, 10); 
 826  * accept connection routine 
 829 asp_accept(scb
, sess_scb
, m
) 
 840         mdata 
= scb
->sess_ioc
; 
 841         ddp 
= (at_ddp_t 
*)gbuf_rptr(mdata
); 
 842         atp 
= (at_atp_t 
*)(gbuf_rptr(mdata
) + DDP_X_HDR_SIZE
); 
 843         rem_addr
.net 
= NET_VALUE(ddp
->src_net
); 
 844         rem_addr
.node 
= ddp
->src_node
; 
 845         rem_addr
.socket 
= ddp
->src_socket
; 
 846         awp 
= (asp_word_t 
*)atp
->user_bytes
; 
 848         sess_scb
->loc_addr
.net 
= NET_VALUE(ddp
->dst_net
); 
 849         sess_scb
->loc_addr
.node 
= ddp
->dst_node
; 
 850         NET_ASSIGN(ddp
->src_net
, sess_scb
->loc_addr
.net
); 
 851         ddp
->src_node 
= sess_scb
->loc_addr
.node
; 
 852         NET_ASSIGN(ddp
->dst_net
, rem_addr
.net
); 
 853         ddp
->dst_node 
= rem_addr
.node
; 
 854         ddp
->dst_socket 
= rem_addr
.socket
; 
 856         sess_scb
->sess_id 
= sess_scb
->loc_addr
.socket
; 
 857         sess_scb
->rem_socket 
= rem_addr
.socket
; 
 858         sess_scb
->rem_addr 
= rem_addr
; 
 859         sess_scb
->rem_addr
.socket 
= awp
->param1
; 
 860         sess_scb
->reply_socket 
= sess_scb
->rem_addr
.socket
; 
 861         awp
->func 
= sess_scb
->loc_addr
.socket
; 
 862         awp
->param1 
= sess_scb
->sess_id
; 
 865         scb
->sess_ioc 
= gbuf_next(mdata
); 
 866         gbuf_next(mdata
) = 0; 
 867         asp_timout(asp_hangup
, sess_scb
, sess_scb
->session_timer
); 
 868         atp_send_rsp(scb
->gref
, mdata
, TRUE
); 
 869         asp_send_tickle(sess_scb
); 
 870         dPrintf(D_M_ASP
, D_L_INFO
, 
 871                 ("asp_accept: ACCEPT connect request, loc=%d, rem=%x.%x.%d\n", 
 872                 sess_scb
->loc_addr
.socket
, 
 873                 sess_scb
->rem_addr
.net
, 
 874                 sess_scb
->rem_addr
.node
,sess_scb
->rem_addr
.socket
)); 
 878  * timer routine - locked version 
 880 void asp_clock_locked(arg
) 
 895         asp_tmo_func tmo_func
; 
 898                 scb_tmo_list
->tmo_delta
--; 
 899         while (((scb 
= scb_tmo_list
) != 0) && (scb_tmo_list
->tmo_delta 
== 0)) { 
 900                 if ((scb_tmo_list 
= scb
->next_tmo
) != 0) 
 901                         scb_tmo_list
->prev_tmo 
= 0; 
 902                 if ((tmo_func 
= scb
->tmo_func
) != 0) { 
 908         if (++scb_tmo_cnt 
== 0) scb_tmo_cnt
++; 
 909         timeout(asp_clock_locked
, (void *)arg
, (1<<SESS_TMO_RES
)*TICKS_PER_SEC
); 
 917 asp_ack_reply(gref
, mioc
) 
 918         register gref_t 
*gref
; 
 919         register gbuf_t 
*mioc
; 
 921         int len
, msize
, nbds
; 
 922         register gbuf_t 
*mdata
, *m
, *mx
; 
 923         struct atpBDS 
*atpBDS
; 
 926         register asp_scb_t 
*scb
, *sess_scb
; 
 927         register ioc_t 
*iocbp
; 
 928         register asp_word_t 
*awp
; 
 929         register asp_command_ind_t 
*command_ind
; 
 930         register asp_cmdreply_ind_t 
*cmdreply_ind
; 
 933         iocbp 
= (ioc_t 
*)gbuf_rptr(mioc
); 
 935         if (iocbp
->ioc_cmd 
== AT_ATP_ISSUE_REQUEST_TICKLE
) { 
 937                  * ignore the ack for the tickle request 
 939                 scb 
= (asp_scb_t 
*)iocbp
->ioc_cr
; 
 940                 scb
->tickle_tid 
= (unsigned short)iocbp
->ioc_rval
; 
 945         scb 
= (asp_scb_t 
*)gref
->info
; 
 951         if (iocbp
->ioc_cmd 
== AT_ATP_GET_POLL
) { 
 953                  * if no data, just drop the request 
 955                 if ((mdata 
= gbuf_cont(mioc
)) == 0) { 
 960                 gbuf_set_type(mioc
, MSG_IOCTL
); 
 961                 ddp 
= (at_ddp_t 
*)gbuf_rptr(mdata
); 
 962                 gbuf_rinc(mdata
,DDP_X_HDR_SIZE
); 
 963                 atp 
= (at_atp_t 
*)gbuf_rptr(mdata
); 
 964                 gbuf_rinc(mdata
,ATP_HDR_SIZE
); 
 965                 rem_addr
.net 
= NET_VALUE(ddp
->src_net
); 
 966                 rem_addr
.node 
= ddp
->src_node
; 
 967                 rem_addr
.socket 
= ddp
->src_socket
; 
 968                 awp 
= (asp_word_t 
*)atp
->user_bytes
; 
 972                          * find the responsible scb 
 974                         if ((scb 
= asp_find_scb(scb
->loc_addr
.socket
, &rem_addr
)) == 0) { 
 979                 dPrintf(D_M_ASP
, D_L_INFO
, 
 980                         ("asp_ack_reply: %s, loc=%d, rem=%x.%x.%d\n", 
 981                         aspCmdStr(awp
->func
),scb
->loc_addr
.socket
, 
 982                         NET_VALUE(ddp
->src_net
) ,ddp
->src_node
,ddp
->src_socket
)); 
 984                 if (scb
->rem_addr
.node
) 
 985                         asp_untimout(asp_hangup
, scb
); 
 988                 case ASPFUNC_GetStatus
: 
 990                          * ignore if this is not a server socket 
 993                         if ((scb
->dflag 
!= 1) || (scb
->stat_msg
 
 994                                         && ((mx 
= gbuf_dupb(scb
->stat_msg
)) == 0))) 
 999                          * send the status block 
1001                         if (gbuf_cont(mdata
)) { 
1002                                 gbuf_freem(gbuf_cont(mdata
)); 
1003                                 gbuf_cont(mdata
) = 0; 
1005                         gbuf_rdec(mdata
,TOTAL_ATP_HDR_SIZE
); 
1006                         if ((m 
= gbuf_alloc( (TOTAL_ATP_HDR_SIZE
+atpBDSsize
), PRI_MED
)) == 0) { 
1011                         bcopy(gbuf_rptr(mdata
), gbuf_rptr(m
), TOTAL_ATP_HDR_SIZE
); 
1014                         ddp 
= (at_ddp_t 
*)gbuf_rptr(mdata
); 
1015                         gbuf_wset(mdata
,DDP_X_HDR_SIZE
); 
1016                         atp 
= (at_atp_t 
*)gbuf_wptr(mdata
); 
1017                         gbuf_winc(mdata
,ATP_HDR_SIZE
); 
1018                         awp 
= (asp_word_t 
*)atp
->user_bytes
; 
1019                         NET_NET(ddp
->src_net
, ddp
->dst_net
); 
1020                         ddp
->src_node 
= ddp
->dst_node
; 
1021                         NET_ASSIGN(ddp
->dst_net
, rem_addr
.net
); 
1022                         ddp
->dst_node 
= rem_addr
.node
; 
1023                         ddp
->dst_socket 
= rem_addr
.socket
; 
1024                         UAS_ASSIGN(ddp
->checksum
, 0); 
1025                         atpBDS 
= (struct atpBDS 
*)gbuf_wptr(mdata
); 
1026                         msize 
= mx 
? gbuf_msgsize(mx
) : 0; 
1027                         for (nbds
=0; (nbds 
< ATP_TRESP_MAX
) && (msize 
> 0); nbds
++) { 
1028                                 len 
= msize 
< ATP_DATA_SIZE 
? msize 
: ATP_DATA_SIZE
; 
1029                                 msize 
-= ATP_DATA_SIZE
; 
1030                                 *(long *)atpBDS
[nbds
].bdsUserData 
= 0; 
1031                                 UAL_ASSIGN(atpBDS
[nbds
].bdsBuffAddr
, 1); 
1032                                 UAS_ASSIGN(atpBDS
[nbds
].bdsBuffSz
, len
); 
1034                         UAS_ASSIGN(atpBDS
[0].bdsDataSz
, nbds
); 
1035                         gbuf_winc(mdata
,atpBDSsize
); 
1036                         gbuf_cont(mdata
) = mx
; 
1037                         atp_send_rsp(gref
, mdata
, FALSE
); 
1040                 case ASPFUNC_OpenSess
: 
1042                          * ignore if server is not ready 
1044                         if ((scb
->dflag 
!= 1) || (scb
->stat_msg 
== 0)) 
1048                         if (gbuf_cont(mdata
)) { 
1049                                 gbuf_freem(gbuf_cont(mdata
)); 
1050                                 gbuf_cont(mdata
) = 0; 
1052                         gbuf_rdec(mdata
,TOTAL_ATP_HDR_SIZE
); 
1053                         gbuf_wset(mdata
,TOTAL_ATP_HDR_SIZE
); 
1054                         if (awp
->param2 
!= ASP_Version
) { 
1056                                  * bad version number, send the OpenSession response 
1060                                 awp
->param2 
= htons((unsigned short)ASPERR_BadVersNum
); 
1061                                 dPrintf(D_M_ASP
, D_L_INFO
, 
1063                                         ASPERR_BadVersNum
)); 
1065                                 NET_NET(ddp
->src_net
, ddp
->dst_net
); 
1066                                 ddp
->src_node 
= ddp
->dst_node
; 
1067                                 NET_ASSIGN(ddp
->dst_net
, rem_addr
.net
); 
1068                                 ddp
->dst_node 
= rem_addr
.node
; 
1069                                 ddp
->dst_socket 
= rem_addr
.socket
; 
1070                                 atp_send_rsp(gref
, mdata
, FALSE
); 
1075                          * queue the connection request 
1077                         gbuf_next(mdata
) = 0; 
1078                         if ((m 
= scb
->sess_ioc
) == 0) { 
1079                                 scb
->sess_ioc 
= mdata
; 
1081                                         wakeup(&scb
->event
); 
1083                                         atalk_notify_sel(gref
); 
1085                                 while (gbuf_next(m
)) 
1087                                 gbuf_next(m
) = mdata
; 
1089                         dPrintf(D_M_ASP
, D_L_INFO
, 
1090                                 ("             : QUEUE connect request\n")); 
1094                 case ASPFUNC_Command
: 
1096                         if ( (scb
->sess_id 
!= awp
->param1
) 
1097                              || (scb
->rcv_seq_num 
!= ntohs(awp
->param2
)) 
1098                              || BAD_REMADDR(rem_addr
) ) { 
1100                                 snprintf(era
, sizeof(era
), "%d.%d", scb
->rem_addr
.node
,scb
->rem_addr
.socket
); 
1101                                 snprintf(ra
, sizeof(ra
), "%d.%d", rem_addr
.node
,rem_addr
.socket
); 
1102                                 dPrintf(D_M_ASP
, D_L_WARNING
, 
1103                                         ("             : DROP, id=%d,esn=%d,sn=%d,erem=%s,rem=%s\n", 
1104                                         scb
->sess_id
,scb
->rcv_seq_num
,awp
->param2
,era
,ra
)); 
1105                                 gbuf_cont(mioc
) = 0; 
1106                                 gbuf_rdec(mdata
,TOTAL_ATP_HDR_SIZE
); 
1107                                 atp_drop_req(gref
, mdata
); 
1110                         scb
->reply_socket 
= rem_addr
.socket
; 
1111                         if (awp
->func 
== ASPFUNC_Write
) 
1112                                 scb
->wrt_seq_num 
= scb
->rcv_seq_num
; 
1113                         NEXT_SEQ_NUM(scb
->rcv_seq_num
); 
1114                         gbuf_set_type(mioc
, MSG_PROTO
); 
1115                         gbuf_wset(mioc
,sizeof(asp_command_ind_t
)); 
1116                         command_ind 
= (asp_command_ind_t 
*)gbuf_rptr(mioc
); 
1117                         command_ind
->Primitive 
= (int)awp
->func
; 
1118                         command_ind
->ReqRefNum 
= 
1119                                 ntohs(*(unsigned short *)atp
->tid
); 
1120                         command_ind
->ReqType 
= awp
->func
; 
1122                         mdata 
= gbuf_strip(mdata
); 
1123                         gbuf_cont(mioc
) = mdata
; 
1124                         if (scb
->req_flag
) { 
1125                                 if ((mx 
= scb
->req_msgq
) != 0) { 
1126                                         while (gbuf_next(mx
)) 
1128                                         gbuf_next(mx
) = mioc
; 
1130                                         scb
->req_msgq 
= mioc
; 
1133                                 asp_putnext(scb
->gref
, mioc
); 
1137                 case ASPFUNC_WriteContinue
: 
1138                         if ( (scb
->sess_id 
!= awp
->param1
) 
1139                              || (scb
->snd_seq_num 
!= awp
->param2
) 
1140                              || BAD_REMADDR(rem_addr
) ) { 
1143                         scb
->reply_socket 
= rem_addr
.socket
; 
1144                         gbuf_set_type(mioc
, MSG_PROTO
); 
1145                         gbuf_wset(mioc
,sizeof(asp_command_ind_t
)); 
1146                         command_ind 
= (asp_command_ind_t 
*)gbuf_rptr(mioc
); 
1147                         command_ind
->Primitive 
= (int)awp
->func
; 
1148                         command_ind
->ReqRefNum 
= 
1149                                 ntohs(*(unsigned short *)atp
->tid
); 
1150                         command_ind
->ReqType 
= awp
->func
; 
1152                         mdata 
= gbuf_strip(mdata
); 
1153                         gbuf_cont(mioc
) = mdata
; 
1154                         asp_putnext(scb
->gref
, mioc
); 
1157                 case ASPFUNC_Tickle
: 
1158                         if (scb
->stat_msg
) { 
1159                                 sess_scb 
= asp_scbQ
[awp
->param1
]; 
1160                                 if (sess_scb 
&& sess_scb
->next_scb
) 
1161                                         sess_scb 
= asp_find_scb( 
1162                                                 sess_scb
->loc_addr
.socket
, &rem_addr
); 
1164                                 if (sess_scb
->rem_addr
.node
) 
1165                                         asp_untimout(asp_hangup
, sess_scb
); 
1166                                 if (sess_scb
->rem_addr
.node
) 
1167                                         asp_timout(asp_hangup
, sess_scb
, sess_scb
->session_timer
); 
1170                         dPrintf(D_M_ASP
, D_L_INFO
, 
1171                                 ("             : Tickle, %d -> %d, id=%d\n", 
1172                                 ddp
->src_socket
,ddp
->dst_socket
,awp
->param1
)); 
1175                 case ASPFUNC_CloseSess
: 
1176                         if ( (scb
->sess_id 
!= awp
->param1
) 
1177                              || (scb
->state 
== ASPSTATE_Close
) 
1178                              || (scb
->state 
== ASPSTATE_WaitingForCloseSessRsp
) 
1179                              || (scb
->rem_addr
.net 
!= rem_addr
.net
) 
1180                              || (scb
->rem_addr
.node 
!= rem_addr
.node
) ) { 
1181                                 dPrintf(D_M_ASP
, D_L_INFO
, 
1182                                         ("             : CLOSE retry, loc=%d, rem=%x.%x.%d\n", 
1183                                         scb
->loc_addr
.socket
, 
1186                                         scb
->rem_addr
.socket
)); 
1193                          * build the CloseSess response to be sent to peer 
1194                          * when the session is closed by the user. 
1196                         if (gbuf_cont(mdata
)) { 
1197                                 gbuf_freem(gbuf_cont(mdata
)); 
1198                                 gbuf_cont(mdata
) = 0; 
1200                         gbuf_rdec(mdata
,TOTAL_ATP_HDR_SIZE
); 
1201                         gbuf_wset(mdata
,TOTAL_ATP_HDR_SIZE
); 
1202                         NET_NET(ddp
->src_net
, ddp
->dst_net
); 
1203                         ddp
->src_node 
= ddp
->dst_node
; 
1204                         NET_ASSIGN(ddp
->dst_net
, rem_addr
.net
); 
1205                         ddp
->dst_node 
= rem_addr
.node
; 
1206                         ddp
->dst_socket 
= rem_addr
.socket
; 
1210                         dPrintf(D_M_ASP
,D_L_INFO
, 
1211                                 ("             : CLOSE, loc=%d, rem=%x.%x.%d\n", 
1212                                 scb
->loc_addr
.socket
, 
1215                                 scb
->rem_addr
.socket
)); 
1217                         gbuf_next(mdata
) = 0; 
1219                                 gbuf_freel(scb
->sess_ioc
); 
1220                         scb
->sess_ioc 
= mdata
; 
1221                         scb
->state 
= ASPSTATE_Close
; 
1224                          * notify upstream of the CloseSess from peer 
1229                 case ASPFUNC_Attention
: 
1230                         if ( (scb
->sess_id 
!= awp
->param1
) 
1231                              || (scb
->rem_addr
.net 
!= rem_addr
.net
) 
1232                              || (scb
->rem_addr
.node 
!= rem_addr
.node
) ) { 
1235                         gbuf_set_type(mioc
, MSG_PROTO
); 
1236                         gbuf_wset(mioc
,sizeof(asp_command_ind_t
)); 
1237                         command_ind 
= (asp_command_ind_t 
*)gbuf_rptr(mioc
); 
1238                         command_ind
->Primitive 
= (int)awp
->func
; 
1239                         command_ind
->ReqRefNum 
= 
1240                                 ntohs(*(unsigned short *)atp
->tid
); 
1241                         command_ind
->ReqType 
= awp
->func
; 
1242                         scb
->attn_tid 
= *(unsigned short *)atp
->tid
; 
1244                         gbuf_rdec(mdata
,2); /* attention code */ 
1246                         mdata 
= gbuf_strip(mdata
); 
1247                         gbuf_cont(mioc
) = mdata
; 
1248                         asp_putnext(scb
->gref
, mioc
); 
1252                         dPrintf(D_M_ASP
, D_L_WARNING
, 
1253                                 ("             : UNKNOWN func, func=%d\n", 
1260         else if (iocbp
->ioc_cmd 
== AT_ATP_REQUEST_COMPLETE
) { 
1261                 if (scb
->next_scb
) { 
1263                          * find the responsible scb 
1265                         scb 
= (asp_scb_t 
*)iocbp
->ioc_private
; 
1266                         if ((scb 
== 0) || (scb
->magic_num 
!= 222)) { 
1267                                 dPrintf(D_M_ASP
, D_L_ERROR
, 
1268                                         ("asp_ack_reply: CAN'T find scb 1\n")); 
1273                 dPrintf(D_M_ASP
, D_L_INFO
, 
1274                         ("asp_ack_reply: RSP, loc=%d, rem=%x.%x.%d, state=%s\n", 
1275                         scb
->loc_addr
.socket
, 
1278                         scb
->rem_addr
.socket
, 
1279                         aspStateStr(scb
->state
))); 
1281                 switch (scb
->state
) { 
1282                 case ASPSTATE_Close
: 
1284                         scb
->rem_addr
.node 
= 0; 
1287                                 wakeup(&scb
->event
); 
1289                                 atalk_notify_sel(gref
); 
1292                 case ASPSTATE_WaitingForGetStatusRsp
: 
1294                         scb
->state 
= ASPSTATE_Idle
; 
1295                         mx 
= gbuf_cont(mioc
); 
1296                         gbuf_cont(mioc
) = 0; 
1297                         mdata 
= gbuf_cont(mx
); 
1299                         iocbp
->ioc_cmd 
= ASPIOC_GetStatus
; 
1300                         iocbp
->ioc_count 
= 0; 
1301                         iocbp
->ioc_rval 
= mdata 
? gbuf_msgsize(mdata
) : 0; 
1303                         atalk_putnext(gref
, mioc
); 
1304                         atalk_putnext(gref
, mdata
); 
1307                 case ASPSTATE_WaitingForOpenSessRsp
: 
1309                         scb
->state 
= ASPSTATE_Idle
; 
1310                         mx 
= gbuf_cont(mioc
); 
1311                         gbuf_cont(mioc
) = 0; 
1312                         if (gbuf_cont(mx
)) { 
1313                                 gbuf_freem(gbuf_cont(mx
)); 
1316                         iocbp
->ioc_cmd 
= ASPIOC_OpenSession
; 
1317                         iocbp
->ioc_rval 
= 0; 
1318                         iocbp
->ioc_count 
= 0; 
1319                         atpBDS 
= (struct atpBDS 
*)gbuf_rptr(mx
); 
1320                         awp 
= (asp_word_t 
*)atpBDS
->bdsUserData
; 
1323                                 asp_iocnak(gref
, mioc
, ECONNREFUSED
); 
1325                                 scb
->rem_addr
.node 
= scb
->rem_node
; 
1326                                 scb
->rem_addr
.socket 
= awp
->func
; 
1327                                 /* bms:  need to set the reply_socket for client side too. 
1328                                 This makes ALO atten replies sent by the client work. */ 
1329                                 scb
->reply_socket 
= scb
->rem_addr
.socket
; 
1330                                 scb
->sess_id 
= awp
->param1
; 
1332                                 atalk_putnext(gref
, mioc
); 
1333                                 asp_timout(asp_hangup
, scb
, scb
->session_timer
); 
1334                                 asp_send_tickle(scb
); 
1335                                 dPrintf(D_M_ASP
, D_L_INFO
, 
1336                                         ("asp_ack_reply: CONNECT, loc=%d, rem=%x.%x.%d\n", 
1337                                         scb
->loc_addr
.socket
, 
1340                                         scb
->rem_addr
.socket
)); 
1344                 case ASPSTATE_WaitingForCommandRsp
: 
1345                 case ASPSTATE_WaitingForWriteRsp
: 
1346                 case ASPSTATE_WaitingForWriteContinueRsp
: 
1347                         if (scb
->rem_addr
.node
) 
1348                                 asp_untimout(asp_hangup
, scb
); 
1349                         NEXT_SEQ_NUM(scb
->snd_seq_num
); 
1350                         scb
->state 
= ASPSTATE_Idle
; 
1351                         gbuf_set_type(mioc
, MSG_PROTO
); 
1352                         mx 
= gbuf_cont(mioc
); 
1353                         mdata 
= gbuf_cont(mx
); 
1354                         gbuf_cont(mioc
) = mdata
; 
1355                         atpBDS 
= (struct atpBDS 
*)gbuf_rptr(mx
); 
1356                         cmdreply_ind 
= (asp_cmdreply_ind_t 
*)gbuf_rptr(mioc
); 
1357                         cmdreply_ind
->Primitive 
= ASPFUNC_CmdReply
; 
1358                         cmdreply_ind
->CmdResult 
= ntohl(*(int *)atpBDS
->bdsUserData
); 
1359                         gbuf_wset(mioc
,sizeof(asp_cmdreply_ind_t
)); 
1361                         asp_putnext(scb
->gref
, mioc
); 
1364                 case ASPSTATE_WaitingForCloseSessRsp
: 
1366                         scb
->state 
= ASPSTATE_Close
; 
1367                         scb
->rem_addr
.node 
= 0; 
1368                         iocbp
->ioc_cmd 
= ASPIOC_CloseSession
; 
1369                         iocbp
->ioc_rval 
= 0; 
1370                         if (gbuf_cont(mioc
)) { 
1371                                 gbuf_freem(gbuf_cont(mioc
)); 
1372                                 gbuf_cont(mioc
) = 0; 
1374                         atalk_putnext(scb
->gref
, mioc
); 
1375                         atp_cancel_req(scb
->gref
, (unsigned int)scb
->tickle_tid
); 
1376                         scb
->tickle_tid 
= 0; 
1380                         dPrintf(D_M_ASP
, D_L_WARNING
, 
1381                         ("             : UNKNOWN state, state=%s\n",  
1382                          aspStateStr(scb
->state
))); 
1388                 if (scb
->next_scb
) { 
1390                          * find the responsible scb 
1392                         scb 
= (asp_scb_t 
*)iocbp
->ioc_cr
; 
1393                         if ((scb 
== 0) || (scb
->magic_num 
!= 222)) { 
1394                                 dPrintf(D_M_ASP
, D_L_ERROR
, 
1395                                         ("asp_ack_reply: CAN'T find scb 2\n")); 
1401                 switch (scb
->state
) { 
1402                 case ASPSTATE_Close
: 
1403                         scb
->rem_addr
.node 
= 0; 
1412         if (scb
->rem_addr
.node
) 
1413                 asp_timout(asp_hangup
, scb
, scb
->session_timer
); 
1414 } /* asp_ack_reply */ 
1420 asp_nak_reply(gref
, mioc
) 
1421         register gref_t 
*gref
; 
1422         register gbuf_t 
*mioc
; 
1424         register asp_scb_t 
*scb
; 
1425         register ioc_t 
*iocbp
; 
1427         iocbp 
= (ioc_t 
*)gbuf_rptr(mioc
); 
1429         if (iocbp
->ioc_cmd 
== AT_ATP_ISSUE_REQUEST_TICKLE
) { 
1431                  * no tickle, close session 
1433                 scb 
= (asp_scb_t 
*)iocbp
->ioc_cr
; 
1436                 dPrintf(D_M_ASP
, D_L_WARNING
, 
1437                         ("tickle_nak: loc=%d, rem=%x.%x.%d, state=%s\n", 
1438                         scb
->loc_addr
.socket
, 
1441                         scb
->rem_addr
.socket
, 
1442                         aspStateStr(scb
->state
))); 
1447         scb 
= (asp_scb_t 
*)gref
->info
; 
1453         if (iocbp
->ioc_cmd 
== AT_ATP_REQUEST_COMPLETE
) { 
1454                 if (scb
->next_scb
) { 
1456                          * find the responsible scb 
1458                         scb 
= (asp_scb_t 
*)iocbp
->ioc_private
; 
1459                         if ((scb 
== 0) || (scb
->magic_num 
!= 222)) { 
1460                                 dPrintf(D_M_ASP
, D_L_ERROR
, 
1461                                         ("asp_nak_reply: CAN'T find scb 1\n")); 
1466                 dPrintf(D_M_ASP
, D_L_WARNING
, 
1467                         ("asp_nak_reply: RSP, loc=%d, rem=%x.%x.%d, state=%s\n", 
1468                         scb
->loc_addr
.socket
, 
1471                         scb
->rem_addr
.socket
, 
1472                         aspStateStr(scb
->state
))); 
1474                 switch (scb
->state
) { 
1475                 case ASPSTATE_WaitingForGetStatusRsp
: 
1476                         iocbp
->ioc_cmd 
= ASPIOC_GetStatus
; 
1479                 case ASPSTATE_WaitingForOpenSessRsp
: 
1480                         iocbp
->ioc_cmd 
= ASPIOC_OpenSession
; 
1483                 case ASPSTATE_WaitingForCommandRsp
: 
1484                 case ASPSTATE_WaitingForWriteRsp
: 
1485                 case ASPSTATE_WaitingForWriteContinueRsp
: 
1486                         scb
->state 
= ASPSTATE_Idle
; 
1488                         /* last remaining use of MSG_ERROR */ 
1489                         gbuf_set_type(mioc
, MSG_ERROR
); 
1490                         *gbuf_rptr(mioc
) = (u_char
)EPROTOTYPE
; 
1492                         if (gbuf_cont(mioc
)) { 
1493                                 gbuf_freem(gbuf_cont(mioc
)); 
1494                                 gbuf_cont(mioc
) = 0; 
1497                         asp_putnext(scb
->gref
, mioc
); 
1500                 case ASPSTATE_WaitingForCloseSessRsp
: 
1501                         scb
->state 
= ASPSTATE_Close
; 
1503                 case ASPSTATE_Close
: /* new for PR-2296832 */ 
1504                         scb
->rem_addr
.node 
= 0; 
1505                         iocbp
->ioc_cmd 
= ASPIOC_CloseSession
; 
1506                         iocbp
->ioc_rval 
= 0; 
1507                         if (gbuf_cont(mioc
)) { 
1508                                 gbuf_freem(gbuf_cont(mioc
)); 
1509                                 gbuf_cont(mioc
) = 0; 
1511                         gbuf_set_type(mioc
, MSG_IOCACK
); 
1512                         atalk_putnext(scb
->gref
, mioc
); 
1519                 scb
->state 
= ASPSTATE_Idle
; 
1520                 atalk_putnext(gref
, mioc
); 
1524                 if (scb
->next_scb
) { 
1526                          * find the responsible scb 
1528                         scb 
= (asp_scb_t 
*)iocbp
->ioc_cr
; 
1529                         if ((scb 
== 0) || (scb
->magic_num 
!= 222)) { 
1530                                 dPrintf(D_M_ASP
, D_L_ERROR
, 
1531                                         ("asp_nak_reply: CAN'T find scb 2\n")); 
1537                 switch (scb
->state
) { 
1538                 case ASPSTATE_Close
: 
1539                         scb
->rem_addr
.node 
= 0; 
1545 } /* asp_nak_reply */ 
1548  * delete scb from the use list 
1551 asp_dequeue_scb(scb
) 
1555         if (scb 
== scb_used_list
) { 
1556                 if ((scb_used_list 
= scb
->next_scb
) != 0) 
1557                         scb
->next_scb
->prev_scb 
= 0; 
1559                 if ((scb
->prev_scb
->next_scb 
= scb
->next_scb
) != 0) 
1560                         scb
->next_scb
->prev_scb 
= scb
->prev_scb
; 
1570 StaticProc asp_scb_t 
* 
1571 asp_find_scb(sock_num
, rem_addr
) 
1572         unsigned char sock_num
; 
1573         at_inet_t 
*rem_addr
; 
1576         asp_scb_t 
*alt_scb 
= 0; 
1578         for (scb 
= asp_scbQ
[sock_num
]; scb
; scb 
= scb
->next_scb
) { 
1579                 if ((scb
->rem_addr
.net 
== rem_addr
->net
) 
1580                         && (scb
->rem_addr
.node 
== rem_addr
->node
)) { 
1581                         if ((scb
->rem_addr
.socket 
== rem_addr
->socket
) 
1582                                         || (scb
->rem_socket 
== rem_addr
->socket
)) 
1584                         else if (alt_scb 
== 0) 
1589         if ((scb 
== 0) && ((scb 
= alt_scb
) == 0)) { 
1590                 dPrintf(D_M_ASP
, D_L_ERROR
, 
1591                         ("asp_find_scb: CAN'T find scb, loc=%d, rem=%x.%x.%d\n", 
1605 asp_timout(func
, scb
, seconds
) 
1607         register asp_scb_t 
*scb
; 
1611         register asp_scb_t 
*curr_scb
, *prev_scb
; 
1616         scb
->tmo_func 
= func
; 
1617         scb
->tmo_delta 
= (seconds
>>SESS_TMO_RES
); 
1618         scb
->tmo_cnt 
= scb_tmo_cnt
; 
1620         if (scb_tmo_list 
== 0) { 
1621                 scb
->next_tmo 
= scb
->prev_tmo 
= 0; 
1627         curr_scb 
= scb_tmo_list
; 
1631                 sum 
+= curr_scb
->tmo_delta
; 
1632                 if (sum 
> scb
->tmo_delta
) { 
1633                         sum 
-= curr_scb
->tmo_delta
; 
1634                         scb
->tmo_delta 
-= sum
; 
1635                         curr_scb
->tmo_delta 
-= scb
->tmo_delta
; 
1638                 prev_scb 
= curr_scb
; 
1639                 if ((curr_scb 
= curr_scb
->next_tmo
) == 0) { 
1640                         scb
->tmo_delta 
-= sum
; 
1646                 scb
->prev_tmo 
= prev_scb
; 
1647                 if ((scb
->next_tmo 
= prev_scb
->next_tmo
) != 0) 
1648                         prev_scb
->next_tmo
->prev_tmo 
= scb
; 
1649                 prev_scb
->next_tmo 
= scb
; 
1652                 scb
->next_tmo 
= scb_tmo_list
; 
1653                 scb_tmo_list
->prev_tmo 
= scb
; 
1663         __unused asp_tmo_func tmo_func
, 
1664         register asp_scb_t 
*scb
) 
1667         if ((scb
->tmo_cnt 
== scb_tmo_cnt
) || (scb
->tmo_func 
== 0)) 
1670         if (scb_tmo_list 
== scb
) { 
1671                 if ((scb_tmo_list 
= scb
->next_tmo
) != 0) { 
1672                         scb_tmo_list
->prev_tmo 
= 0; 
1673                         scb
->next_tmo
->tmo_delta 
+= scb
->tmo_delta
; 
1675         } else if (scb
->prev_tmo
) { 
1676                 if ((scb
->prev_tmo
->next_tmo 
= scb
->next_tmo
) != 0) { 
1677                         scb
->next_tmo
->prev_tmo 
= scb
->prev_tmo
; 
1678                         scb
->next_tmo
->tmo_delta 
+= scb
->tmo_delta
; 
1693          * set the state to Close 
1695         scb
->state 
= ASPSTATE_Close
; 
1696         if (scb
->tickle_tid
) { 
1697                 atp_cancel_req(scb
->gref
, (unsigned int)scb
->tickle_tid
); 
1698                 scb
->tickle_tid 
= 0; 
1702          * notify upstream of the hangup 
1704         if (scb
->rem_addr
.node
) { 
1706                         wakeup(&scb
->event
); 
1708                         atalk_notify_sel(scb
->gref
); 
1713 asp_iocack(gref
, mioc
) 
1717         if (gbuf_cont(mioc
)) 
1718                 ((ioc_t 
*)gbuf_rptr(mioc
))->ioc_count 
= gbuf_msgsize(gbuf_cont(mioc
)); 
1720                 ((ioc_t 
*)gbuf_rptr(mioc
))->ioc_count 
= 0; 
1722         gbuf_set_type(mioc
, MSG_IOCACK
); 
1723         atalk_putnext(gref
, mioc
); 
1727 asp_iocnak(gref
, mioc
, err
) 
1732         ((ioc_t 
*)gbuf_rptr(mioc
))->ioc_count 
= 0; 
1735         ((ioc_t 
*)gbuf_rptr(mioc
))->ioc_error 
= err
; 
1736         ((ioc_t 
*)gbuf_rptr(mioc
))->ioc_rval 
= -1; 
1737         if (gbuf_cont(mioc
)) { 
1738                 gbuf_freem(gbuf_cont(mioc
)); 
1739                 gbuf_cont(mioc
) = 0; 
1742         gbuf_set_type(mioc
, MSG_IOCNAK
); 
1743         atalk_putnext(gref
, mioc
); 
1747  * the alloc scb routine 
1749 StaticProc asp_scb_t 
* 
1754         asp_scb_t 
*scb
, *scb_array
; 
1756         if (scb_free_list 
== 0) { 
1757                 if ((m 
= gbuf_alloc(SCBS_PER_BLK
*sizeof(asp_scb_t
), PRI_MED
)) == 0) 
1758                         return (asp_scb_t 
*)0; 
1759                 bzero((char *)gbuf_rptr(m
), SCBS_PER_BLK
*sizeof(asp_scb_t
)); 
1760                 gbuf_cont(m
) = scb_resource_m
; 
1762                 scb_array 
= (asp_scb_t 
*)gbuf_rptr(m
); 
1763                 for (i
=0; i 
< SCBS_PER_BLK
-1; i
++) 
1764                         scb_array
[i
].next_scb 
= (asp_scb_t 
*)&scb_array
[i
+1]; 
1765                 scb_array
[i
].next_scb 
= 0; 
1766                 scb_free_list 
= (asp_scb_t 
*)&scb_array
[0]; 
1769         scb 
= scb_free_list
; 
1770         scb_free_list 
= scb
->next_scb
; 
1771         ATEVENTINIT(scb
->event
); 
1772         ATEVENTINIT(scb
->delay_event
); 
1778  * the free scb routine 
1785         bzero((char *)scb
, sizeof(asp_scb_t
)); 
1786         scb
->next_scb 
= scb_free_list
; 
1787         scb_free_list 
= scb
; 
1791  * routine to pass up receive data 
1794 asp_putnext(gref
, mproto
) 
1801         scb 
= (asp_scb_t 
*)gref
->info
; 
1804          * queue the message. 
1806         gbuf_next(mproto
) = 0; 
1807         if ((m 
= scb
->sess_ioc
) == 0) 
1808                 scb
->sess_ioc 
= mproto
; 
1810                 while (gbuf_next(m
)) 
1812                 gbuf_next(m
) = mproto
; 
1815         if (scb
->rcv_cnt 
>= MAX_RCV_CNT
) 
1819                 wakeup(&scb
->event
); 
1820         else if (mproto 
== scb
->sess_ioc
) 
1821                 atalk_notify_sel(gref
); 
1826  * The following two routines are direct entries from system 
1827  * calls to allow fast sending and recving of ASP data. 
1830 /* in ASPputmsg we expect: 
1836     ASPFUNC_WriteContinue 
1838     bms:  Make this callable from the kernel. 
1839     If mreq != NULL, then must be called from kernel space and the following apply: 
1840     1)  *mreq is data to be sent already in mbuf chains. 
1841     2)  datptr->len = size of data 
1844 int ASPputmsg(gref_t 
*gref
, strbuf_t 
*ctlptr
, strbuf_t 
*datptr
, gbuf_t 
*mreq
, __unused 
int flags
, int *errp
) 
1846     int i
, err
, len
, offset
, remain
, size
, copy_len
; 
1847     gbuf_t 
*mioc
, *mdata
, *mx
; 
1852     int nbds
, result
, msize
, Primitive
; 
1853     unsigned char *wptr
; 
1854     struct atp_set_default 
*sd
; 
1857     struct atpBDS 
*atpBDS
; 
1859     union asp_primitives 
*primitives
; 
1863     if ((scb 
= (asp_scb_t 
*)gref
->info
) == 0) { 
1864                 dPrintf(D_M_ASP
, D_L_ERROR
, 
1865                         ("ASPputmsg: stale handle=0x%x, pid=%d\n", 
1866                         (u_int
) gref
, gref
->pid
)); 
1872     if (scb
->state 
== ASPSTATE_Close
) 
1874     if (scb
->snd_stop
) { 
1880      * copy in the control and data info 
1883         /* being called from kernel space */ 
1884         bcopy (ctlptr
, &ctlbuf
, sizeof (strbuf_t
)); 
1885         bcopy (datptr
, &datbuf
, sizeof (strbuf_t
)); 
1887         /* being called from user space */ 
1888         if ((err 
= copyin(CAST_USER_ADDR_T(ctlptr
), (caddr_t
)&ctlbuf
, sizeof(ctlbuf
))) != 0) 
1890         if ((err 
= copyin(CAST_USER_ADDR_T(datptr
), (caddr_t
)&datbuf
, sizeof(datbuf
))) != 0) 
1894      /* Radar 5398072: check for bogus length 
1895       *                Max ASP data is 8 ATP packets 
1898      if ((ctlbuf
.len 
< 0) || (ctlbuf
.len 
> (ATP_DATA_SIZE 
* 8))) { 
1902      if ((datbuf
.len 
< 0) || (datbuf
.len 
> (ATP_DATA_SIZE 
* 8))) { 
1908      * allocate buffer and copy in the control content 
1910     if (!(mioc 
= gbuf_alloc_wait(ctlbuf
.len
, TRUE
))) { 
1911         /* error return should not be possible */ 
1915     gbuf_set_type(mioc
, MSG_IOCTL
); /* for later, in ATP */ 
1916     gbuf_wset(mioc
, ctlbuf
.len
); 
1919         /* being called from kernel space */ 
1920         bcopy (ctlbuf
.buf
, gbuf_rptr(mioc
), ctlbuf
.len
); 
1922         /* being called from user space */ 
1923         if ((err 
= copyin(CAST_USER_ADDR_T(ctlbuf
.buf
), (caddr_t
)gbuf_rptr(mioc
), ctlbuf
.len
)) != 0) { 
1929     iocbp 
= (ioc_t 
*)gbuf_rptr(mioc
); 
1930     primitives 
= (union asp_primitives 
*)gbuf_rptr(mioc
); 
1931     Primitive 
= primitives
->Primitive
; 
1932         dPrintf(D_M_ASP
, D_L_INFO
, 
1933                 ("ASPputmsg: %s\n", aspCmdStr(Primitive
))); 
1936      * copy in the data content into multiple mbuf clusters if 
1937      * required.  ATP now expects reply data to be placed in 
1938      * standard clusters, not the large external clusters that 
1939      * were used previously. 
1942     /* set offset for use by some commands */ 
1943     offset 
= (Primitive 
== ASPFUNC_CmdReply
) ? 0 : aspCMDsize
; 
1946         /* The data from the in-kernel call for use by AFP is passed 
1947          * in as one large external cluster.  This needs to be copied 
1948          * to a chain of standard clusters. 
1950         remain 
= gbuf_len(mreq
); 
1951         dataptr 
= mtod(mreq
, caddr_t
); 
1953         /* copyin from user space */ 
1954         remain 
= datbuf
.len
;  
1955         dataptr 
= (caddr_t
)datbuf
.buf
;   
1958     /* allocate first buffer */ 
1959     if (!(mdata 
= gbuf_alloc_wait((remain 
+ offset 
> MCLBYTES 
? MCLBYTES 
: remain 
+ offset
), TRUE
))) { 
1960         /* error return should not be possible */ 
1965     gbuf_wset(mdata
, 0);                /* init length to zero */ 
1966     gbuf_cont(mioc
) = mdata
; 
1969                 if (remain 
+ offset 
> MCLBYTES
) 
1970                         copy_len 
= MCLBYTES 
- offset
; 
1975                         bcopy (dataptr
, (gbuf_rptr(mdata
) + offset
), copy_len
); 
1976                 else if ((err 
= copyin(CAST_USER_ADDR_T(dataptr
), (caddr_t
)(gbuf_rptr(mdata
) + offset
), copy_len
)) != 0) { 
1980                 gbuf_wset(mdata
, (copy_len 
+ offset
)); 
1981                 size 
+= copy_len 
+ offset
; 
1982                 dataptr 
+= copy_len
; 
1985                         /* allocate the next mbuf */ 
1986                         if ((gbuf_cont(mdata
) = m_get((M_WAIT
), MSG_DATA
)) == 0) { 
1991                         mdata 
= gbuf_cont(mdata
); 
1992                         MCLGET(mdata
, M_WAIT
); 
1993                         if (!(mdata
->m_flags 
& M_EXT
)) { 
2000         mdata 
= gbuf_cont(mioc
);                        /* code further on down expects this to b e set */ 
2001         mdata
->m_pkthdr
.len 
= size
;                     /* set packet hdr len */ 
2006         switch (Primitive
) { 
2008     case ASPFUNC_Command
: 
2010     case ASPFUNC_WriteContinue
: 
2011     case ASPFUNC_Attention
: 
2013          * build the command/write/write_continue request 
2015         wptr 
= (unsigned char *)gbuf_rptr(mdata
); 
2016         atpBDS 
= (struct atpBDS 
*)wptr
; 
2018         for (i
=0; i 
< ATP_TRESP_MAX
; i
++) { 
2019             *(unsigned long  *)atpBDS
[i
].bdsBuffAddr 
= 1; 
2020             *(unsigned short *)atpBDS
[i
].bdsBuffSz 
= ATP_DATA_SIZE
; 
2022         sd 
= (struct atp_set_default 
*)wptr
; 
2023         wptr 
+= sizeof(struct atp_set_default
); 
2024         sd
->def_retries 
= (scb
->cmd_retry
.retries 
== -1) ? 
2025           ATP_INFINITE_RETRIES 
: scb
->cmd_retry
.retries
; 
2026         sd
->def_rate 
= scb
->cmd_retry
.interval
*TICKS_PER_SEC
; 
2027         sd
->def_BDSlen 
= atpBDSsize
; 
2028         ddp 
= (at_ddp_t 
*)wptr
; 
2029         NET_ASSIGN(ddp
->src_net
, scb
->loc_addr
.net
); 
2030         ddp
->src_node 
= scb
->loc_addr
.node
; 
2031         NET_ASSIGN(ddp
->dst_net
, scb
->rem_addr
.net
); 
2032         ddp
->dst_node 
= scb
->rem_addr
.node
; 
2033         ddp
->dst_socket 
= scb
->rem_addr
.socket
; 
2034         UAS_ASSIGN(ddp
->checksum
, 0); 
2035         atp 
= ATP_ATP_HDR(wptr
); 
2036         wptr 
+= TOTAL_ATP_HDR_SIZE
; 
2040         awp 
= (asp_word_t 
*)atp
->user_bytes
; 
2041         awp
->func 
= (unsigned char)Primitive
; 
2042         awp
->param1 
= scb
->sess_id
; 
2043         awp
->param2 
= htons(scb
->snd_seq_num
); 
2044         iocbp
->ioc_private 
= (void *)scb
; 
2045         iocbp
->ioc_count 
= gbuf_len(mdata
); 
2046         iocbp
->ioc_rval 
= 0; 
2047         iocbp
->ioc_cmd 
= AT_ATP_ISSUE_REQUEST_DEF
; 
2050          * send the command/write/write_continue/attention request 
2052         switch (awp
->func
) { 
2053         case ASPFUNC_Command
: 
2054             scb
->state 
= ASPSTATE_WaitingForCommandRsp
; 
2057             scb
->state 
= ASPSTATE_WaitingForWriteRsp
; 
2059         case ASPFUNC_WriteContinue
: 
2060             scb
->state 
= ASPSTATE_WaitingForWriteContinueRsp
; 
2061             awp
->param2 
= htons(scb
->wrt_seq_num
); 
2063         case ASPFUNC_Attention
: 
2064             scb
->state 
= ASPSTATE_WaitingForCommandRsp
; 
2069             awp
->param2 
= htons(*(unsigned short *)gbuf_wptr(mdata
)); 
2072         dPrintf(D_M_ASP
,D_L_INFO
, 
2073             ("ASPputmsg: %s, loc=%d, rem=%x.%x.%d\n", 
2074              (awp
->func 
== ASPFUNC_Command 
? "CommandReq" : 
2075               awp
->func 
== ASPFUNC_Write 
? "WriteReq" : 
2076               awp
->func 
== ASPFUNC_WriteContinue 
? "WriteContinue" : 
2077               "AttentionReq"),scb
->loc_addr
.socket
, 
2078              NET_VALUE(ddp
->dst_net
),ddp
->dst_node
,ddp
->dst_socket
)); 
2079         atp_send_req(gref
, mioc
); 
2082     case ASPFUNC_CmdReply
: 
2084         if (scb
->req_msgq
) { 
2086             scb
->req_msgq 
= gbuf_next(mx
); 
2088             asp_putnext(scb
->gref
, mx
); 
2092         result 
= primitives
->CmdReplyReq
.CmdResult
; 
2093         tid 
= primitives
->CmdReplyReq
.ReqRefNum
; 
2095         /* Re-use the original mioc mbuf to send the response. */ 
2096         gbuf_rinc(mioc
,sizeof(void *)); 
2098         ddp 
= (at_ddp_t 
*)gbuf_wptr(mioc
); 
2099         gbuf_winc(mioc
,DDP_X_HDR_SIZE
); 
2100         atp 
= (at_atp_t 
*)gbuf_wptr(mioc
); 
2101         gbuf_winc(mioc
,ATP_HDR_SIZE
); 
2102         NET_ASSIGN(ddp
->src_net
, scb
->loc_addr
.net
); 
2103         ddp
->src_node 
= scb
->loc_addr
.node
; 
2104         NET_ASSIGN(ddp
->dst_net
, scb
->rem_addr
.net
); 
2105         ddp
->dst_node 
= scb
->rem_addr
.node
; 
2106         ddp
->dst_socket 
= scb
->reply_socket
; 
2107         ddp
->type 
= DDP_ATP
; 
2108         UAS_ASSIGN(ddp
->checksum
, 0); 
2109         UAS_ASSIGN(atp
->tid
, htons(tid
)); 
2110         if (scb
->attn_flag 
&& (tid 
== scb
->attn_tid
)) { 
2118         /* setup the atpBDS struct - only the length field is used, 
2119          * except for the first one which contains the bds count in 
2122         atpBDS 
= (struct atpBDS 
*)gbuf_wptr(mioc
); 
2123         msize 
= mdata 
? gbuf_msgsize(mdata
) : 0; 
2124         for (nbds
=0; (nbds 
< ATP_TRESP_MAX
) && (msize 
> 0); nbds
++) { 
2125             len 
= msize 
< ATP_DATA_SIZE 
? msize 
: ATP_DATA_SIZE
; 
2126             msize 
-= ATP_DATA_SIZE
; 
2127             *(long *)atpBDS
[nbds
].bdsUserData 
= 0; 
2128             UAL_ASSIGN(atpBDS
[nbds
].bdsBuffAddr
, 1); 
2129             UAS_ASSIGN(atpBDS
[nbds
].bdsBuffSz
, len
); 
2131         UAS_ASSIGN(atpBDS
[0].bdsDataSz
, nbds
); 
2132         *(long *)atpBDS
[0].bdsUserData 
= (long)result
; 
2133         *(long *)atp
->user_bytes 
= (long)result
; 
2134         gbuf_winc(mioc
,atpBDSsize
); 
2135                 dPrintf(D_M_ASP
, D_L_INFO
, 
2136                         ("ASPputmsg: ATP CmdReplyReq, loc=%d, state=%s, msgsize = %d, result = %d, tid = %d\n", 
2137                          scb
->loc_addr
.socket
, aspStateStr(scb
->state
),  
2138                          (mdata 
? gbuf_msgsize(mdata
) : 0), result
, tid
)); 
2139         atp_send_rsp(gref
, mioc
, TRUE
); 
2143     /* Not an expected ASPFUNC */ 
2153 /* bms:  make this callable from kernel.  reply date is passed back as a mbuf chain in *mreply  */ 
2154 int ASPgetmsg(gref_t 
*gref
, strbuf_t 
*ctlptr
, strbuf_t 
*datptr
, gbuf_t 
**mreply
, __unused 
int *flags
, int *errp
) 
2156     int err
, len
, sum
, rval
; 
2157     gbuf_t 
*mproto
, *mdata
; 
2161     unsigned char get_wait
; 
2163     if ((scb 
= (asp_scb_t 
*)gref
->info
) == 0) { 
2164                 dPrintf(D_M_ASP
, D_L_ERROR
, 
2165                         ("ASPgetmsg: stale handle=0x%x, pid=%d\n", 
2166                         (u_int
) gref
, gref
->pid
)); 
2172     if (scb
->state 
== ASPSTATE_Close
) 
2178     while ((mproto 
= scb
->sess_ioc
) == 0) { 
2180            lck_mtx_assert(atalk_mutex
, LCK_MTX_ASSERT_OWNED
); 
2181         err 
= msleep(&scb
->event
, atalk_mutex
, PSOCK 
| PCATCH
, "aspgetmsg", 0); 
2187         if (scb
->state 
== ASPSTATE_Close
) { 
2192     get_wait 
= scb
->get_wait
; 
2194     if ((ctlptr 
== 0) && (datptr 
== 0)) 
2196     scb
->sess_ioc 
= gbuf_next(mproto
); 
2197     mdata 
= gbuf_cont(mproto
); 
2199     /* last remaining use of MSG_ERROR */ 
2200     if (gbuf_type(mproto
) == MSG_ERROR
) { 
2201         err 
= (int)gbuf_rptr(mproto
)[0]; 
2206      * copy in the control and data info 
2208     if (mreply 
!= NULL
) { 
2209         /* called from kernel space */ 
2210         bcopy (ctlptr
, &ctlbuf
, sizeof(ctlbuf
)); 
2211         bcopy (datptr
, &datbuf
, sizeof(datbuf
)); 
2213         /* called from user space */ 
2214         if ((err 
= copyin(CAST_USER_ADDR_T(ctlptr
), 
2215                 (caddr_t
)&ctlbuf
, sizeof(ctlbuf
))) != 0) 
2217         if ((err 
= copyin(CAST_USER_ADDR_T(datptr
), 
2218                 (caddr_t
)&datbuf
, sizeof(datbuf
))) != 0) 
2221     if ((datbuf
.maxlen 
< 0) || (datbuf
.maxlen 
< gbuf_msgsize(mdata
))) { 
2222         gbuf_next(mproto
) = scb
->sess_ioc
; 
2223         scb
->sess_ioc 
= mproto
; 
2227     if (get_wait 
== 0) { 
2229          * this is a hack to support the select() call. 
2230          * we're not supposed to dequeue messages in the Streams  
2231          * head's read queue this way; but there is no better way. 
2233         if (scb
->sess_ioc 
!= 0) 
2234             atalk_notify_sel(gref
);  
2239      * copy out the control content and info 
2241     ctlbuf
.len 
= gbuf_len(mproto
); 
2243     if (mreply 
!= NULL
) { 
2244         /* called from kernel space */ 
2245         bcopy (gbuf_rptr(mproto
), ctlbuf
.buf
, ctlbuf
.len
); 
2246         bcopy (&ctlbuf
, ctlptr
, sizeof(ctlbuf
)); 
2248         /* called from user space */ 
2249         if ((err 
= copyout((caddr_t
)gbuf_rptr(mproto
), 
2250                 CAST_USER_ADDR_T(ctlbuf
.buf
), ctlbuf
.len
)) != 0) 
2252         if ((err 
= copyout((caddr_t
)&ctlbuf
, 
2253                 CAST_USER_ADDR_T(ctlptr
), sizeof(ctlbuf
))) != 0) 
2258      * copy out the data content and info 
2260     for (rval 
= 0, sum 
= 0; mdata 
&& (rval 
== 0); mdata 
= gbuf_cont(mdata
))  
2262         len 
= gbuf_len(mdata
); 
2264             if ((len 
+ sum
) > datbuf
.maxlen
) { 
2265                 len 
= datbuf
.maxlen 
- sum
; 
2269             if (mreply 
== NULL
) { 
2270                 /* called from user space */ 
2271                 if ((err 
= copyout((caddr_t
)gbuf_rptr(mdata
), CAST_USER_ADDR_T(&datbuf
.buf
[sum
]), len
)) != 0) 
2278     if (mreply 
!= NULL
) { 
2279         /* called from kernel space */ 
2280         bcopy (&datbuf
, datptr
, sizeof(datbuf
)); 
2282         /* called from user space */ 
2283         if ((err 
= copyout((caddr_t
)&datbuf
, CAST_USER_ADDR_T(datptr
), sizeof(datbuf
))) != 0) 
2287     if (mreply 
!= NULL
) { 
2288         /* called from kernel space */ 
2289         /* return the reply data in mbufs, so dont free them.   
2290         Just free the proto info */ 
2291         mdata 
= gbuf_cont(mproto
); 
2293         gbuf_cont(mproto
) = NULL
; 
2296         /* called from user space */ 
2309     gbuf_next(mproto
) = scb
->sess_ioc
; 
2310     scb
->sess_ioc 
= mproto
;