2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
23 * Copyright (c) 1995 Apple Computer, Inc.
26 * Created February 20, 1995 by Tuyen Nguyen
27 * Modified for MP, 1996 by Tuyen Nguyen
28 * Modified, March 17, 1997 by Tuyen Nguyen for MacOSX.
31 #include <sys/errno.h>
32 #include <sys/types.h>
33 #include <sys/param.h>
34 #include <machine/spl.h>
35 #include <sys/systm.h>
36 #include <sys/kernel.h>
38 #include <sys/filedesc.h>
39 #include <sys/fcntl.h>
41 #include <sys/ioctl.h>
42 #include <sys/malloc.h>
43 #include <kern/locks.h>
44 #include <sys/socket.h>
45 #include <sys/socketvar.h>
49 #include <netat/appletalk.h>
50 #include <netat/sysglue.h>
51 #include <netat/at_pcb.h>
52 #include <netat/atp.h>
53 #include <netat/ddp.h>
54 #include <netat/asp.h>
55 #include <netat/at_var.h>
56 #include <netat/debug.h>
59 #define CHK_LOOP(str) { \
60 if (loop_cnt++ > 100) { \
66 #define atpBDSsize (sizeof(struct atpBDS)*ATP_TRESP_MAX)
67 #define aspCMDsize (atpBDSsize+sizeof(struct atp_set_default)+TOTAL_ATP_HDR_SIZE)
68 #define SCBS_PER_BLK 16
69 #define TICKS_PER_SEC HZ
70 #define SESS_TMO_RES 2
71 #define DEF_SESS_TMO 120
72 #define NEXT_SEQ_NUM(x) (x = (x == 65535) ? 0 : (x + 1))
74 #define BAD_REMADDR(addr) \
75 ( (*(long *)&scb->rem_addr != *(long *)&addr) \
76 && ((scb->rem_addr.net != addr.net) \
77 || (scb->rem_addr.node != addr.node)) )
85 void asp_clock_locked(void *);
89 StaticProc asp_scb_t
*asp_find_scb();
90 StaticProc asp_scb_t
*asp_scb_alloc();
92 StaticProc
void asp_putnext();
93 StaticProc
void asp_iocack();
94 StaticProc
void asp_iocnak();
95 StaticProc
void asp_dequeue_scb();
96 StaticProc
void asp_scb_free();
97 StaticProc
void asp_timout();
98 StaticProc
void asp_untimout();
99 StaticProc
void asp_hangup();
100 StaticProc
void asp_send_tickle();
101 StaticProc
void asp_send_tickle_locked(void *);
102 StaticProc
void asp_accept();
103 StaticProc
int asp_send_req();
105 extern at_ifaddr_t
*ifID_home
;
106 extern int atp_pidM
[];
107 extern gref_t
*atp_inputQ
[];
108 extern lck_mtx_t
*atalk_mutex
;
109 gbuf_t
*scb_resource_m
= 0;
110 unsigned char asp_inpC
[256];
111 asp_scb_t
*asp_scbQ
[256];
113 static at_retry_t asp_def_retry
= {2, -1, 1};
114 static unsigned char scb_tmo_cnt
;
115 asp_scb_t
*scb_used_list
;
116 static asp_scb_t
*scb_tmo_list
;
117 asp_scb_t
*scb_free_list
;
123 return (((asp_scb_t
*)gref
->info
)->sess_ioc
? 1 : 0);
133 bzero(asp_inpC
, sizeof(asp_inpC
));
134 bzero(asp_scbQ
, sizeof(asp_scbQ
));
138 * the open routine allocates a state structure
146 * if no asp structure available, return failure
148 if ((scb
= asp_scb_alloc()) == 0)
152 * initialize the gref data structure
154 gref
->info
= (void *)scb
;
155 gref
->readable
= asp_readable
;
158 * initialize the scb data structure
161 scb
->magic_num
= 222;
162 scb
->state
= ASPSTATE_Idle
;
163 scb
->pid
= gref
->pid
;
165 scb
->session_timer
= DEF_SESS_TMO
;
166 scb
->cmd_retry
= asp_def_retry
;
167 if ((scb
->next_scb
= scb_used_list
) != 0)
168 scb
->next_scb
->prev_scb
= scb
;
174 dPrintf(D_M_ASP
, D_L_INFO
, ("asp_open: pid=%d\n", scb
->pid
));
179 * the close routine frees all the data structures
185 unsigned char sock_num
;
186 asp_scb_t
*scb
, *new_scb
;
189 scb
= (asp_scb_t
*)gref
->info
;
190 dPrintf(D_M_ASP
, D_L_INFO
, ("asp_close: loc=%d\n",
191 scb
->loc_addr
.socket
));
193 if (scb
->pid
&& scb
->sess_ioc
&& (scb
->dflag
!= 1)) {
195 * send the CloseSess response to peer
197 if (gbuf_type(scb
->sess_ioc
) != MSG_PROTO
) {
199 scb
->sess_ioc
= gbuf_next(m
);
200 atp_send_rsp(scb
->gref
, m
, TRUE
);
204 if (scb
->atp_state
) {
205 sock_num
= scb
->loc_addr
.socket
;
206 if ((scb
->dflag
!= 1) && scb
->stat_msg
) {
207 untimeout(atp_retry_req
, scb
->stat_msg
);
208 gbuf_freem(scb
->stat_msg
);
211 if (asp_scbQ
[sock_num
]->next_scb
== 0) {
212 asp_scbQ
[sock_num
] = 0;
213 asp_inpC
[sock_num
] = 0;
214 dPrintf(D_M_ASP
, D_L_INFO
,
215 (" : atp_close(), loc=%d\n", scb
->loc_addr
.socket
));
218 asp_inpC
[sock_num
]--;
219 if (scb
== asp_scbQ
[sock_num
]) {
220 new_scb
= scb
->next_scb
;
221 new_scb
->prev_scb
= 0;
222 asp_scbQ
[sock_num
] = new_scb
;
223 new_scb
->atp_state
->atp_gref
= new_scb
->gref
;
224 new_scb
->atp_state
->pid
= new_scb
->pid
;
225 atp_inputQ
[sock_num
] = new_scb
->gref
;
227 if ((scb
->prev_scb
->next_scb
= scb
->next_scb
) != 0)
228 scb
->next_scb
->prev_scb
= scb
->prev_scb
;
233 asp_dequeue_scb(scb
);
236 * free all allocated blocks if any
239 gbuf_freem(scb
->stat_msg
);
243 gbuf_freel(scb
->sess_ioc
);
247 gbuf_freel(scb
->req_msgq
);
251 scb
->rem_addr
.node
= 0;
257 asp_untimout(asp_hangup
, scb
);
258 untimeout(asp_send_tickle_locked
, (void *)scb
); /* added for 2225395 */
261 * free the asp session control block
263 scb
->state
= ASPSTATE_Close
;
268 static char *aspStateStr(state
)
271 return ((state
==ASPSTATE_Close
)? "Close":
272 (state
==ASPSTATE_Idle
)? "Idle":
273 (state
==ASPSTATE_WaitingForGetStatusRsp
)? "GetStatusRsp":
274 (state
==ASPSTATE_WaitingForOpenSessRsp
)? "OpenSessRsp":
275 (state
==ASPSTATE_WaitingForCommandRsp
)? "CmdRsp":
276 (state
==ASPSTATE_WaitingForWriteContinue
)? "WriteCont":
277 (state
==ASPSTATE_WaitingForWriteRsp
)? "WriteRsp":
278 (state
==ASPSTATE_WaitingForWriteContinueRsp
)? "WriteContRsp":
279 (state
==ASPSTATE_WaitingForCloseSessRsp
)? "CloseSessRsp":
283 static char *aspCmdStr(aspCmd
)
286 return ((aspCmd
==ASPFUNC_CloseSess
)? "CloseSess":
287 (aspCmd
==ASPFUNC_Command
)? "Command":
288 (aspCmd
==ASPFUNC_GetStatus
)? "GetStatus":
289 (aspCmd
==ASPFUNC_OpenSess
)? "OpenSess":
290 (aspCmd
==ASPFUNC_Tickle
)? "Tickle":
291 (aspCmd
==ASPFUNC_Write
)? "Write":
292 (aspCmd
==ASPFUNC_WriteContinue
)? "WriteContinue":
293 (aspCmd
==ASPFUNC_Attention
)? "Attention":
294 (aspCmd
==ASPFUNC_CmdReply
)? "CmdReply": "unknown");
297 static char *aspIOCStr(aspIOC
)
301 (aspIOC
==ASPIOC_ClientBind
)? "ClientBind":
302 (aspIOC
==ASPIOC_CloseSession
)? "CloseSession":
303 (aspIOC
==ASPIOC_GetLocEntity
)? "GetLocEntity":
304 (aspIOC
==ASPIOC_GetRemEntity
)? "GetRemEntity":
305 (aspIOC
==ASPIOC_GetSession
)? "GetSession":
306 (aspIOC
==ASPIOC_GetStatus
)? "GetStatus":
307 (aspIOC
==ASPIOC_ListenerBind
)? "ListenerBind":
308 (aspIOC
==ASPIOC_OpenSession
)? "OpenSession":
309 (aspIOC
==ASPIOC_StatusBlock
)? "StatusBlock":
310 (aspIOC
==ASPIOC_SetPid
)? "SetPid":
311 (aspIOC
==ASPIOC_GetSessId
)? "GetSessId":
312 (aspIOC
==ASPIOC_EnableSelect
)? "EnableSelect":
313 (aspIOC
==ASPIOC_Look
)? "Look":
320 static char mbuf_str
[100];
325 "dat = %d, prot = %d, ioc = %d, err = %d, hu = %d, ack = %d, nak = %d, ctl = %d",
327 "dat = %d, prot = %d, ioc = %d, ctl = %d",
328 mbstat
.m_mtypes
[MSG_DATA
], mbstat
.m_mtypes
[MSG_PROTO
], mbstat
.m_mtypes
[MSG_IOCTL
],
330 mbstat.m_mtypes[MSG_ERROR], mbstat.m_mtypes[MSG_HANGUP], mbstat.m_mtypes[MSG_IOCACK],
331 mbstat.m_mtypes[MSG_IOCNAK],
333 mbstat
.m_mtypes
[MSG_CTL
]);
334 return(&mbuf_str
[0]);
337 void trace_beg(str
, m
)
342 gbuf_t
*mdata
, *mchain
;
345 for (i
= 0, j
= 0, mdata
= m
, mchain
= m
; mdata
; i
++) {
346 mdata
= gbuf_cont(mdata
);
347 if (!mdata
&& mchain
) {
348 mdata
= gbuf_next(mchain
);
353 dPrintf(D_M_ASP
, D_L_TRACE
,
354 ("%s: %s, m# = %d, c# = %d\n", str
, mbuf_totals(), i
, j
));
360 dPrintf(D_M_ASP
, D_L_TRACE
,
361 (" %s: %s\n", str
, mbuf_totals()));
363 #endif /* AT_MBUF_TRACE */
368 int asp_wput(gref
, m
)
373 unsigned char sockSav
, sock_num
;
374 gbuf_t
*mioc
, *mdata
;
376 asp_scb_t
*scb
, *server_scb
, *curr_scb
;
379 union asp_primitives
*primitives
;
380 asp_status_cmd_t
*status_cmd
;
381 asp_open_cmd_t
*open_cmd
;
384 scb
= (asp_scb_t
*)gref
->info
;
385 if (scb
->dflag
== 0) {
390 if (gbuf_type(m
) != MSG_IOCTL
) {
391 dPrintf(D_M_ASP
, D_L_WARNING
,
392 ("asp_wput: UNKNOWN message, type=%d\n",
399 iocbp
= (ioc_t
*)gbuf_rptr(mioc
);
401 dPrintf(D_M_ASP_LOW
, D_L_INFO
,
402 ("asp_wput: %s, loc=%d, state=%s\n",
403 aspIOCStr(iocbp
->ioc_cmd
), scb
->loc_addr
.socket
,
404 aspStateStr(scb
->state
)));
406 switch (iocbp
->ioc_cmd
) {
407 case ASPIOC_CloseSession
:
408 if ((scb
->state
== ASPSTATE_Close
) || (scb
->rem_addr
.node
== 0))
413 aw
.func
= ASPFUNC_CloseSess
;
414 aw
.param1
= scb
->sess_id
;
416 iocbp
->ioc_private
= (void *)scb
;
417 scb
->ioc_wait
= (unsigned char)(iocbp
->ioc_cmd
& 0xff);
418 iocbp
->ioc_cmd
= AT_ATP_ISSUE_REQUEST
;
419 asp_send_req(gref
, mioc
, &scb
->rem_addr
, &Retry
, &aw
,
420 0, ASPSTATE_WaitingForCloseSessRsp
, 0x01);
423 case ASPIOC_ClientBind
:
425 * open an ATP channel
427 if ((err
= atp_open(gref
, 0)) != 0) {
428 asp_iocnak(gref
, mioc
, err
);
431 scb
->atp_state
= (atp_state_t
*)gref
->info
;
432 scb
->atp_state
->pid
= scb
->pid
;
434 * bind to any available socket
437 sockSav
= scb
->dflag
;
438 if ((sock_num
= (at_socket
)atp_bind(gref
, 0, &sockSav
)) == 0) {
439 scb
->atp_state
= (atp_state_t
*)0;
441 gref
->info
= (void *)scb
;
442 asp_iocnak(gref
, mioc
, EINVAL
);
445 gref
->info
= (void *)scb
;
446 asp_dequeue_scb(scb
);
447 scb
->atp_state
->dflag
= scb
->dflag
;
448 scb
->loc_addr
.socket
= sock_num
;
449 asp_scbQ
[sock_num
] = scb
;
450 asp_inpC
[sock_num
]++;
451 atp_pidM
[sock_num
] = 0;
454 case ASPIOC_ListenerBind
:
456 * open an ATP channel
458 if ((err
= atp_open(gref
, 0)) != 0) {
459 asp_iocnak(gref
, mioc
, err
);
462 scb
->atp_state
= (atp_state_t
*)gref
->info
;
463 scb
->atp_state
->pid
= scb
->pid
;
465 * bind to any available socket
467 if ((sock_num
= (at_socket
)atp_bind(gref
, 0, 0)) == 0) {
468 scb
->atp_state
= (atp_state_t
*)0;
470 gref
->info
= (void *)scb
;
471 asp_iocnak(gref
, mioc
, EINVAL
);
474 gref
->info
= (void *)scb
;
475 asp_dequeue_scb(scb
);
476 scb
->atp_state
->dflag
= scb
->dflag
;
477 scb
->loc_addr
.socket
= sock_num
;
478 asp_scbQ
[sock_num
] = scb
;
479 asp_inpC
[sock_num
]++;
481 *(at_inet_t
*)gbuf_rptr(gbuf_cont(mioc
)) = scb
->loc_addr
;
484 case ASPIOC_GetLocEntity
:
485 if ((gbuf_cont(mioc
) == 0) || (scb
->atp_state
== 0)) {
486 asp_iocnak(gref
, mioc
, EPROTOTYPE
);
489 *(at_inet_t
*)gbuf_rptr(gbuf_cont(mioc
)) = scb
->loc_addr
;
492 case ASPIOC_GetRemEntity
:
493 if ((gbuf_cont(mioc
) == 0) || (scb
->atp_state
== 0)) {
494 asp_iocnak(gref
, mioc
, EPROTOTYPE
);
497 *(at_inet_t
*)gbuf_rptr(gbuf_cont(mioc
)) = scb
->rem_addr
;
500 case ASPIOC_GetSession
:
501 if ((mdata
= gbuf_cont(mioc
)) == 0) {
502 asp_iocnak(gref
, mioc
, EPROTOTYPE
);
505 addr
= (at_inet_t
*)gbuf_rptr(mdata
);
506 scb
->tickle_interval
= (unsigned short)addr
->node
;
507 scb
->session_timer
= addr
->net
;
508 server_scb
= asp_scbQ
[addr
->socket
];
509 /*### LD 10/28/97: changed to make sure we're not accessing a null server_scb */
510 if (server_scb
== 0) {
511 asp_iocnak(gref
, mioc
, EPROTOTYPE
);
514 if (server_scb
->sess_ioc
== 0) {
515 asp_iocnak(gref
, mioc
, EPROTOTYPE
);
520 * open an ATP channel
522 if ((err
= atp_open(gref
, 0)) != 0) {
523 gref
->info
= (void *)scb
;
524 asp_iocnak(gref
, mioc
, err
);
527 scb
->atp_state
= (atp_state_t
*)gref
->info
;
528 scb
->atp_state
->pid
= scb
->pid
;
530 * bind to any available socket
533 sockSav
= scb
->dflag
;
534 if ((sock_num
= (at_socket
)atp_bind(gref
, 0, &sockSav
)) == 0) {
536 asp_dequeue_scb(scb
);
538 scb
->loc_addr
.socket
= sock_num
;
539 for (curr_scb
= asp_scbQ
[sock_num
];
540 curr_scb
->next_scb
; curr_scb
= curr_scb
->next_scb
) ;
541 scb
->prev_scb
= curr_scb
;
542 curr_scb
->next_scb
= scb
;
543 scb
->atp_state
= curr_scb
->atp_state
;
545 asp_dequeue_scb(scb
);
546 scb
->loc_addr
.socket
= sock_num
;
547 asp_scbQ
[sock_num
] = scb
;
548 scb
->atp_state
->dflag
= scb
->dflag
;
550 gref
->info
= (void *)scb
;
551 asp_inpC
[sock_num
]++;
553 asp_accept(server_scb
, scb
, mdata
);
556 case ASPIOC_GetStatus
:
557 if ((mdata
= gbuf_cont(mioc
)) == 0) {
558 asp_iocnak(gref
, mioc
, EINVAL
);
562 status_cmd
= (asp_status_cmd_t
*)gbuf_rptr(mdata
);
563 aw
.func
= ASPFUNC_GetStatus
;
566 scb
->ioc_wait
= (unsigned char)(iocbp
->ioc_cmd
& 0xff);
567 iocbp
->ioc_cmd
= AT_ATP_ISSUE_REQUEST_DEF
;
568 /* bms: make sure this is an ALO request */
569 asp_send_req(gref
, mioc
, &status_cmd
->SLSEntityIdentifier
,
570 &status_cmd
->Retry
, &aw
, 0, ASPSTATE_WaitingForGetStatusRsp
, 0xff);
574 case ASPIOC_OpenSession
:
575 if ((mdata
= gbuf_cont(mioc
)) == 0) {
576 asp_iocnak(gref
, mioc
, EINVAL
);
580 open_cmd
= (asp_open_cmd_t
*)gbuf_rptr(mdata
);
581 scb
->svc_addr
= open_cmd
->SLSEntityIdentifier
;
582 scb
->rem_addr
= scb
->svc_addr
;
583 scb
->rem_node
= scb
->rem_addr
.node
;
584 scb
->rem_addr
.node
= 0;
585 scb
->tickle_interval
= open_cmd
->TickleInterval
;
586 scb
->session_timer
= open_cmd
->SessionTimer
;
587 aw
.func
= ASPFUNC_OpenSess
;
588 aw
.param1
= scb
->loc_addr
.socket
;
589 aw
.param2
= htons(ASP_Version
);
590 scb
->ioc_wait
= (unsigned char)(iocbp
->ioc_cmd
& 0xff);
591 iocbp
->ioc_cmd
= AT_ATP_ISSUE_REQUEST_DEF
;
592 asp_send_req(gref
, mioc
, &open_cmd
->SLSEntityIdentifier
,
593 &open_cmd
->Retry
, &aw
, 1, ASPSTATE_WaitingForOpenSessRsp
, 0x01);
597 case ASPIOC_StatusBlock
:
599 * save the server status block
602 gbuf_freem(scb
->stat_msg
);
603 scb
->stat_msg
= gbuf_cont(mioc
);
607 /* *** Does scb->pid get used in a packet header,
608 and if so is it in ASP, or in ATP?
609 If not, do we need this call for anything?
610 (cap does currently use it in _ANS code.)
613 if (gbuf_cont(mioc
) == 0) {
614 asp_iocnak(gref
, mioc
, EINVAL
);
617 scb
->pid
= *(int *)gbuf_rptr(gbuf_cont(mioc
));
620 case ASPIOC_GetSessId
:
621 if (gbuf_cont(mioc
) == 0) {
622 asp_iocnak(gref
, mioc
, EINVAL
);
625 *(gref_t
**)gbuf_rptr(gbuf_cont(mioc
)) = gref
;
629 if (gbuf_cont(mioc
) == 0) {
630 asp_iocnak(gref
, mioc
, EINVAL
);
634 primitives
= (union asp_primitives
*)gbuf_rptr(scb
->sess_ioc
);
635 if (primitives
->Primitive
== ASPFUNC_CmdReply
)
636 *(int *)gbuf_rptr(gbuf_cont(mioc
)) = 0;
638 *(int *)gbuf_rptr(gbuf_cont(mioc
)) = 1;
640 *(int *)gbuf_rptr(gbuf_cont(mioc
)) = -1;
643 case DDP_IOC_GET_CFG
:
645 struct atp_state
*atp
= (struct atp_state
*)gref
->info
;
647 atp
= (struct atp_state
*)atp
->atp_msgq
;
649 if (gbuf_cont(mioc
) == 0) {
650 asp_iocnak(gref
, mioc
, EINVAL
);
653 /* *** borrowed from ddp_proto.c to handle DDP_IOC_GET_CFG
655 scb
->state
= ASPSTATE_Idle
;
657 /* *** was ddp_get_cfg() *** */
659 (ddp_addr_t
*)gbuf_rptr(gbuf_cont(mioc
));
660 cfgp
->inet
.net
= ifID_home
->ifThisNode
.s_net
;
661 cfgp
->inet
.node
= ifID_home
->ifThisNode
.s_node
;
662 cfgp
->inet
.socket
= atp
->atp_socket_no
;
663 cfgp
->ddptype
= DDP_ATP
;
665 gbuf_wset(gbuf_cont(mioc
), sizeof(at_inet_t
));
670 asp_iocnak(gref
, mioc
, EINVAL
);
674 asp_iocack(gref
, mioc
);
679 * send request routine
682 asp_send_req(gref
, mioc
, dest
, retry
, awp
, xo
, state
, bitmap
)
690 unsigned char bitmap
;
695 struct atp_set_default
*sd
;
698 struct atpBDS
*atpBDS
;
699 asp_scb_t
*scb
= (asp_scb_t
*)gref
->info
;
702 * allocate an ATP buffer for the request
704 if ((gbuf_cont(mioc
) = gbuf_alloc(aspCMDsize
, PRI_MED
)) == 0) {
705 if (awp
->func
== ASPFUNC_Tickle
)
708 asp_iocnak(gref
, mioc
, ENOBUFS
);
709 dPrintf(D_M_ASP
, D_L_WARNING
,
710 ("asp_send_req: ENOBUFS, loc=%d\n", scb
->loc_addr
.socket
));
714 mdata
= gbuf_cont(mioc
);
715 iocbp
= (ioc_t
*)gbuf_rptr(mioc
);
720 atpBDS
= (struct atpBDS
*)gbuf_rptr(mdata
);
721 gbuf_wset(mdata
,atpBDSsize
);
722 for (i
=0; i
< ATP_TRESP_MAX
; i
++) {
723 *(unsigned long *)atpBDS
[i
].bdsBuffAddr
= 1;
724 *(unsigned short *)atpBDS
[i
].bdsBuffSz
= ATP_DATA_SIZE
;
726 sd
= (struct atp_set_default
*)gbuf_wptr(mdata
);
727 gbuf_winc(mdata
,sizeof(struct atp_set_default
));
728 sd
->def_retries
= (retry
->retries
== -1) ?
729 ATP_INFINITE_RETRIES
: retry
->retries
;
730 sd
->def_rate
= retry
->interval
*TICKS_PER_SEC
;
731 sd
->def_BDSlen
= atpBDSsize
;
732 ddp
= (at_ddp_t
*)gbuf_wptr(mdata
);
733 NET_ASSIGN(ddp
->src_net
, scb
->loc_addr
.net
);
734 ddp
->src_node
= scb
->loc_addr
.node
;
735 NET_ASSIGN(ddp
->dst_net
, dest
->net
);
736 ddp
->dst_node
= dest
->node
;
737 ddp
->dst_socket
= dest
->socket
;
738 UAS_ASSIGN(ddp
->checksum
, 0);
739 atp
= ATP_ATP_HDR(gbuf_wptr(mdata
));
742 atp
->bitmap
= bitmap
;
743 gbuf_winc(mdata
,TOTAL_ATP_HDR_SIZE
);
744 *(asp_word_t
*)atp
->user_bytes
= *awp
;
745 iocbp
->ioc_count
= gbuf_len(mdata
);
752 dPrintf(D_M_ASP
, D_L_INFO
,
753 ("asp_send_req: %s, loc=%d, rem= %d, len=%d, state=%s\n",
754 aspCmdStr(awp
->func
),
755 scb
->loc_addr
.socket
, ddp
->dst_socket
, iocbp
->ioc_count
,
756 aspStateStr(scb
->state
)));
758 atp_send_req(gref
, mioc
);
763 * send tickle routine - locked version
766 asp_send_tickle_locked(scb
)
770 asp_send_tickle((asp_scb_t
*)scb
);
776 * send tickle routine
789 * make sure the connection is still there
791 if (scb
->rem_addr
.node
== 0) {
795 if ((mioc
= gbuf_alloc(sizeof(ioc_t
), PRI_HI
)) == 0) {
796 dPrintf(D_M_ASP
, D_L_WARNING
,
797 ("asp_send_tickle: ENOBUFS 0, loc=%d, rem=%d\n",
798 scb
->loc_addr
.socket
,scb
->rem_addr
.socket
));
799 timeout(asp_send_tickle_locked
, (void *)scb
, 10);
802 gbuf_wset(mioc
,sizeof(ioc_t
));
803 gbuf_set_type(mioc
, MSG_IOCTL
);
805 dest
= scb
->svc_addr
.node
?
806 (at_inet_t
*)&scb
->svc_addr
: (at_inet_t
*)&scb
->rem_addr
;
807 retry
.interval
= scb
->tickle_interval
;
810 aw
.func
= ASPFUNC_Tickle
;
811 aw
.param1
= scb
->sess_id
;
813 ((ioc_t
*)gbuf_rptr(mioc
))->ioc_cr
= (void *)scb
;
814 ((ioc_t
*)gbuf_rptr(mioc
))->ioc_cmd
= AT_ATP_ISSUE_REQUEST_TICKLE
;
816 if (asp_send_req(scb
->gref
, mioc
, dest
, &retry
, &aw
, 0, scb
->state
, 0)) {
817 dPrintf(D_M_ASP
, D_L_WARNING
,
818 ("asp_send_tickle: ENOBUFS 1, loc=%d, rem=%d\n",
819 scb
->loc_addr
.socket
,scb
->rem_addr
.socket
));
821 timeout(asp_send_tickle_locked
, (void *)scb
, 10);
827 * accept connection routine
830 asp_accept(scb
, sess_scb
, m
)
841 mdata
= scb
->sess_ioc
;
842 ddp
= (at_ddp_t
*)gbuf_rptr(mdata
);
843 atp
= (at_atp_t
*)(gbuf_rptr(mdata
) + DDP_X_HDR_SIZE
);
844 rem_addr
.net
= NET_VALUE(ddp
->src_net
);
845 rem_addr
.node
= ddp
->src_node
;
846 rem_addr
.socket
= ddp
->src_socket
;
847 awp
= (asp_word_t
*)atp
->user_bytes
;
849 sess_scb
->loc_addr
.net
= NET_VALUE(ddp
->dst_net
);
850 sess_scb
->loc_addr
.node
= ddp
->dst_node
;
851 NET_ASSIGN(ddp
->src_net
, sess_scb
->loc_addr
.net
);
852 ddp
->src_node
= sess_scb
->loc_addr
.node
;
853 NET_ASSIGN(ddp
->dst_net
, rem_addr
.net
);
854 ddp
->dst_node
= rem_addr
.node
;
855 ddp
->dst_socket
= rem_addr
.socket
;
857 sess_scb
->sess_id
= sess_scb
->loc_addr
.socket
;
858 sess_scb
->rem_socket
= rem_addr
.socket
;
859 sess_scb
->rem_addr
= rem_addr
;
860 sess_scb
->rem_addr
.socket
= awp
->param1
;
861 sess_scb
->reply_socket
= sess_scb
->rem_addr
.socket
;
862 awp
->func
= sess_scb
->loc_addr
.socket
;
863 awp
->param1
= sess_scb
->sess_id
;
866 scb
->sess_ioc
= gbuf_next(mdata
);
867 gbuf_next(mdata
) = 0;
868 asp_timout(asp_hangup
, sess_scb
, sess_scb
->session_timer
);
869 atp_send_rsp(scb
->gref
, mdata
, TRUE
);
870 asp_send_tickle(sess_scb
);
871 dPrintf(D_M_ASP
, D_L_INFO
,
872 ("asp_accept: ACCEPT connect request, loc=%d, rem=%x.%x.%d\n",
873 sess_scb
->loc_addr
.socket
,
874 sess_scb
->rem_addr
.net
,
875 sess_scb
->rem_addr
.node
,sess_scb
->rem_addr
.socket
));
879 * timer routine - locked version
881 void asp_clock_locked(arg
)
899 scb_tmo_list
->tmo_delta
--;
900 while (((scb
= scb_tmo_list
) != 0) && (scb_tmo_list
->tmo_delta
== 0)) {
901 if ((scb_tmo_list
= scb
->next_tmo
) != 0)
902 scb_tmo_list
->prev_tmo
= 0;
903 if ((tmo_func
= scb
->tmo_func
) != 0) {
909 if (++scb_tmo_cnt
== 0) scb_tmo_cnt
++;
910 timeout(asp_clock_locked
, (void *)arg
, (1<<SESS_TMO_RES
)*TICKS_PER_SEC
);
918 asp_ack_reply(gref
, mioc
)
919 register gref_t
*gref
;
920 register gbuf_t
*mioc
;
922 int len
, msize
, nbds
;
923 register gbuf_t
*mdata
, *m
, *mx
;
924 struct atpBDS
*atpBDS
;
927 register asp_scb_t
*scb
, *sess_scb
;
928 register ioc_t
*iocbp
;
929 register asp_word_t
*awp
;
930 register asp_command_ind_t
*command_ind
;
931 register asp_cmdreply_ind_t
*cmdreply_ind
;
934 iocbp
= (ioc_t
*)gbuf_rptr(mioc
);
936 if (iocbp
->ioc_cmd
== AT_ATP_ISSUE_REQUEST_TICKLE
) {
938 * ignore the ack for the tickle request
940 scb
= (asp_scb_t
*)iocbp
->ioc_cr
;
941 scb
->tickle_tid
= (unsigned short)iocbp
->ioc_rval
;
946 scb
= (asp_scb_t
*)gref
->info
;
952 if (iocbp
->ioc_cmd
== AT_ATP_GET_POLL
) {
954 * if no data, just drop the request
956 if ((mdata
= gbuf_cont(mioc
)) == 0) {
961 gbuf_set_type(mioc
, MSG_IOCTL
);
962 ddp
= (at_ddp_t
*)gbuf_rptr(mdata
);
963 gbuf_rinc(mdata
,DDP_X_HDR_SIZE
);
964 atp
= (at_atp_t
*)gbuf_rptr(mdata
);
965 gbuf_rinc(mdata
,ATP_HDR_SIZE
);
966 rem_addr
.net
= NET_VALUE(ddp
->src_net
);
967 rem_addr
.node
= ddp
->src_node
;
968 rem_addr
.socket
= ddp
->src_socket
;
969 awp
= (asp_word_t
*)atp
->user_bytes
;
973 * find the responsible scb
975 if ((scb
= asp_find_scb(scb
->loc_addr
.socket
, &rem_addr
)) == 0) {
980 dPrintf(D_M_ASP
, D_L_INFO
,
981 ("asp_ack_reply: %s, loc=%d, rem=%x.%x.%d\n",
982 aspCmdStr(awp
->func
),scb
->loc_addr
.socket
,
983 NET_VALUE(ddp
->src_net
) ,ddp
->src_node
,ddp
->src_socket
));
985 if (scb
->rem_addr
.node
)
986 asp_untimout(asp_hangup
, scb
);
989 case ASPFUNC_GetStatus
:
991 * ignore if this is not a server socket
994 if ((scb
->dflag
!= 1) || (scb
->stat_msg
995 && ((mx
= gbuf_dupb(scb
->stat_msg
)) == 0)))
1000 * send the status block
1002 if (gbuf_cont(mdata
)) {
1003 gbuf_freem(gbuf_cont(mdata
));
1004 gbuf_cont(mdata
) = 0;
1006 gbuf_rdec(mdata
,TOTAL_ATP_HDR_SIZE
);
1007 if ((m
= gbuf_alloc( (TOTAL_ATP_HDR_SIZE
+atpBDSsize
), PRI_MED
)) == 0) {
1012 bcopy(gbuf_rptr(mdata
), gbuf_rptr(m
), TOTAL_ATP_HDR_SIZE
);
1015 ddp
= (at_ddp_t
*)gbuf_rptr(mdata
);
1016 gbuf_wset(mdata
,DDP_X_HDR_SIZE
);
1017 atp
= (at_atp_t
*)gbuf_wptr(mdata
);
1018 gbuf_winc(mdata
,ATP_HDR_SIZE
);
1019 awp
= (asp_word_t
*)atp
->user_bytes
;
1020 NET_NET(ddp
->src_net
, ddp
->dst_net
);
1021 ddp
->src_node
= ddp
->dst_node
;
1022 NET_ASSIGN(ddp
->dst_net
, rem_addr
.net
);
1023 ddp
->dst_node
= rem_addr
.node
;
1024 ddp
->dst_socket
= rem_addr
.socket
;
1025 UAS_ASSIGN(ddp
->checksum
, 0);
1026 atpBDS
= (struct atpBDS
*)gbuf_wptr(mdata
);
1027 msize
= mx
? gbuf_msgsize(mx
) : 0;
1028 for (nbds
=0; (nbds
< ATP_TRESP_MAX
) && (msize
> 0); nbds
++) {
1029 len
= msize
< ATP_DATA_SIZE
? msize
: ATP_DATA_SIZE
;
1030 msize
-= ATP_DATA_SIZE
;
1031 *(long *)atpBDS
[nbds
].bdsUserData
= 0;
1032 UAL_ASSIGN(atpBDS
[nbds
].bdsBuffAddr
, 1);
1033 UAS_ASSIGN(atpBDS
[nbds
].bdsBuffSz
, len
);
1035 UAS_ASSIGN(atpBDS
[0].bdsDataSz
, nbds
);
1036 gbuf_winc(mdata
,atpBDSsize
);
1037 gbuf_cont(mdata
) = mx
;
1038 atp_send_rsp(gref
, mdata
, FALSE
);
1041 case ASPFUNC_OpenSess
:
1043 * ignore if server is not ready
1045 if ((scb
->dflag
!= 1) || (scb
->stat_msg
== 0))
1049 if (gbuf_cont(mdata
)) {
1050 gbuf_freem(gbuf_cont(mdata
));
1051 gbuf_cont(mdata
) = 0;
1053 gbuf_rdec(mdata
,TOTAL_ATP_HDR_SIZE
);
1054 gbuf_wset(mdata
,TOTAL_ATP_HDR_SIZE
);
1055 if (awp
->param2
!= ASP_Version
) {
1057 * bad version number, send the OpenSession response
1061 awp
->param2
= htons((unsigned short)ASPERR_BadVersNum
);
1062 dPrintf(D_M_ASP
, D_L_INFO
,
1064 ASPERR_BadVersNum
));
1066 NET_NET(ddp
->src_net
, ddp
->dst_net
);
1067 ddp
->src_node
= ddp
->dst_node
;
1068 NET_ASSIGN(ddp
->dst_net
, rem_addr
.net
);
1069 ddp
->dst_node
= rem_addr
.node
;
1070 ddp
->dst_socket
= rem_addr
.socket
;
1071 atp_send_rsp(gref
, mdata
, FALSE
);
1076 * queue the connection request
1078 gbuf_next(mdata
) = 0;
1079 if ((m
= scb
->sess_ioc
) == 0) {
1080 scb
->sess_ioc
= mdata
;
1082 wakeup(&scb
->event
);
1084 atalk_notify_sel(gref
);
1086 while (gbuf_next(m
))
1088 gbuf_next(m
) = mdata
;
1090 dPrintf(D_M_ASP
, D_L_INFO
,
1091 (" : QUEUE connect request\n"));
1095 case ASPFUNC_Command
:
1097 if ( (scb
->sess_id
!= awp
->param1
)
1098 || (scb
->rcv_seq_num
!= ntohs(awp
->param2
))
1099 || BAD_REMADDR(rem_addr
) ) {
1101 sprintf(era
,"%d.%d", scb
->rem_addr
.node
,scb
->rem_addr
.socket
);
1102 sprintf(ra
,"%d.%d", rem_addr
.node
,rem_addr
.socket
);
1103 dPrintf(D_M_ASP
, D_L_WARNING
,
1104 (" : DROP, id=%d,esn=%d,sn=%d,erem=%s,rem=%s\n",
1105 scb
->sess_id
,scb
->rcv_seq_num
,awp
->param2
,era
,ra
));
1106 gbuf_cont(mioc
) = 0;
1107 gbuf_rdec(mdata
,TOTAL_ATP_HDR_SIZE
);
1108 atp_drop_req(gref
, mdata
);
1111 scb
->reply_socket
= rem_addr
.socket
;
1112 if (awp
->func
== ASPFUNC_Write
)
1113 scb
->wrt_seq_num
= scb
->rcv_seq_num
;
1114 NEXT_SEQ_NUM(scb
->rcv_seq_num
);
1115 gbuf_set_type(mioc
, MSG_PROTO
);
1116 gbuf_wset(mioc
,sizeof(asp_command_ind_t
));
1117 command_ind
= (asp_command_ind_t
*)gbuf_rptr(mioc
);
1118 command_ind
->Primitive
= (int)awp
->func
;
1119 command_ind
->ReqRefNum
=
1120 ntohs(*(unsigned short *)atp
->tid
);
1121 command_ind
->ReqType
= awp
->func
;
1123 mdata
= gbuf_strip(mdata
);
1124 gbuf_cont(mioc
) = mdata
;
1125 if (scb
->req_flag
) {
1126 if ((mx
= scb
->req_msgq
) != 0) {
1127 while (gbuf_next(mx
))
1129 gbuf_next(mx
) = mioc
;
1131 scb
->req_msgq
= mioc
;
1134 asp_putnext(scb
->gref
, mioc
);
1138 case ASPFUNC_WriteContinue
:
1139 if ( (scb
->sess_id
!= awp
->param1
)
1140 || (scb
->snd_seq_num
!= awp
->param2
)
1141 || BAD_REMADDR(rem_addr
) ) {
1144 scb
->reply_socket
= rem_addr
.socket
;
1145 gbuf_set_type(mioc
, MSG_PROTO
);
1146 gbuf_wset(mioc
,sizeof(asp_command_ind_t
));
1147 command_ind
= (asp_command_ind_t
*)gbuf_rptr(mioc
);
1148 command_ind
->Primitive
= (int)awp
->func
;
1149 command_ind
->ReqRefNum
=
1150 ntohs(*(unsigned short *)atp
->tid
);
1151 command_ind
->ReqType
= awp
->func
;
1153 mdata
= gbuf_strip(mdata
);
1154 gbuf_cont(mioc
) = mdata
;
1155 asp_putnext(scb
->gref
, mioc
);
1158 case ASPFUNC_Tickle
:
1159 if (scb
->stat_msg
) {
1160 sess_scb
= asp_scbQ
[awp
->param1
];
1161 if (sess_scb
&& sess_scb
->next_scb
)
1162 sess_scb
= asp_find_scb(
1163 sess_scb
->loc_addr
.socket
, &rem_addr
);
1165 if (sess_scb
->rem_addr
.node
)
1166 asp_untimout(asp_hangup
, sess_scb
);
1167 if (sess_scb
->rem_addr
.node
)
1168 asp_timout(asp_hangup
, sess_scb
, sess_scb
->session_timer
);
1171 dPrintf(D_M_ASP
, D_L_INFO
,
1172 (" : Tickle, %d -> %d, id=%d\n",
1173 ddp
->src_socket
,ddp
->dst_socket
,awp
->param1
));
1176 case ASPFUNC_CloseSess
:
1177 if ( (scb
->sess_id
!= awp
->param1
)
1178 || (scb
->state
== ASPSTATE_Close
)
1179 || (scb
->state
== ASPSTATE_WaitingForCloseSessRsp
)
1180 || (scb
->rem_addr
.net
!= rem_addr
.net
)
1181 || (scb
->rem_addr
.node
!= rem_addr
.node
) ) {
1182 dPrintf(D_M_ASP
, D_L_INFO
,
1183 (" : CLOSE retry, loc=%d, rem=%x.%x.%d\n",
1184 scb
->loc_addr
.socket
,
1187 scb
->rem_addr
.socket
));
1194 * build the CloseSess response to be sent to peer
1195 * when the session is closed by the user.
1197 if (gbuf_cont(mdata
)) {
1198 gbuf_freem(gbuf_cont(mdata
));
1199 gbuf_cont(mdata
) = 0;
1201 gbuf_rdec(mdata
,TOTAL_ATP_HDR_SIZE
);
1202 gbuf_wset(mdata
,TOTAL_ATP_HDR_SIZE
);
1203 NET_NET(ddp
->src_net
, ddp
->dst_net
);
1204 ddp
->src_node
= ddp
->dst_node
;
1205 NET_ASSIGN(ddp
->dst_net
, rem_addr
.net
);
1206 ddp
->dst_node
= rem_addr
.node
;
1207 ddp
->dst_socket
= rem_addr
.socket
;
1211 dPrintf(D_M_ASP
,D_L_INFO
,
1212 (" : CLOSE, loc=%d, rem=%x.%x.%d\n",
1213 scb
->loc_addr
.socket
,
1216 scb
->rem_addr
.socket
));
1218 gbuf_next(mdata
) = 0;
1220 gbuf_freel(scb
->sess_ioc
);
1221 scb
->sess_ioc
= mdata
;
1222 scb
->state
= ASPSTATE_Close
;
1225 * notify upstream of the CloseSess from peer
1230 case ASPFUNC_Attention
:
1231 if ( (scb
->sess_id
!= awp
->param1
)
1232 || (scb
->rem_addr
.net
!= rem_addr
.net
)
1233 || (scb
->rem_addr
.node
!= rem_addr
.node
) ) {
1236 gbuf_set_type(mioc
, MSG_PROTO
);
1237 gbuf_wset(mioc
,sizeof(asp_command_ind_t
));
1238 command_ind
= (asp_command_ind_t
*)gbuf_rptr(mioc
);
1239 command_ind
->Primitive
= (int)awp
->func
;
1240 command_ind
->ReqRefNum
=
1241 ntohs(*(unsigned short *)atp
->tid
);
1242 command_ind
->ReqType
= awp
->func
;
1243 scb
->attn_tid
= *(unsigned short *)atp
->tid
;
1245 gbuf_rdec(mdata
,2); /* attention code */
1247 mdata
= gbuf_strip(mdata
);
1248 gbuf_cont(mioc
) = mdata
;
1249 asp_putnext(scb
->gref
, mioc
);
1253 dPrintf(D_M_ASP
, D_L_WARNING
,
1254 (" : UNKNOWN func, func=%d\n",
1261 else if (iocbp
->ioc_cmd
== AT_ATP_REQUEST_COMPLETE
) {
1262 if (scb
->next_scb
) {
1264 * find the responsible scb
1266 scb
= (asp_scb_t
*)iocbp
->ioc_private
;
1267 if ((scb
== 0) || (scb
->magic_num
!= 222)) {
1268 dPrintf(D_M_ASP
, D_L_ERROR
,
1269 ("asp_ack_reply: CAN'T find scb 1\n"));
1274 dPrintf(D_M_ASP
, D_L_INFO
,
1275 ("asp_ack_reply: RSP, loc=%d, rem=%x.%x.%d, state=%s\n",
1276 scb
->loc_addr
.socket
,
1279 scb
->rem_addr
.socket
,
1280 aspStateStr(scb
->state
)));
1282 switch (scb
->state
) {
1283 case ASPSTATE_Close
:
1285 scb
->rem_addr
.node
= 0;
1288 wakeup(&scb
->event
);
1290 atalk_notify_sel(gref
);
1293 case ASPSTATE_WaitingForGetStatusRsp
:
1295 scb
->state
= ASPSTATE_Idle
;
1296 mx
= gbuf_cont(mioc
);
1297 gbuf_cont(mioc
) = 0;
1298 mdata
= gbuf_cont(mx
);
1300 iocbp
->ioc_cmd
= ASPIOC_GetStatus
;
1301 iocbp
->ioc_count
= 0;
1302 iocbp
->ioc_rval
= mdata
? gbuf_msgsize(mdata
) : 0;
1304 atalk_putnext(gref
, mioc
);
1305 atalk_putnext(gref
, mdata
);
1308 case ASPSTATE_WaitingForOpenSessRsp
:
1310 scb
->state
= ASPSTATE_Idle
;
1311 mx
= gbuf_cont(mioc
);
1312 gbuf_cont(mioc
) = 0;
1313 if (gbuf_cont(mx
)) {
1314 gbuf_freem(gbuf_cont(mx
));
1317 iocbp
->ioc_cmd
= ASPIOC_OpenSession
;
1318 iocbp
->ioc_rval
= 0;
1319 iocbp
->ioc_count
= 0;
1320 atpBDS
= (struct atpBDS
*)gbuf_rptr(mx
);
1321 awp
= (asp_word_t
*)atpBDS
->bdsUserData
;
1324 asp_iocnak(gref
, mioc
, ECONNREFUSED
);
1326 scb
->rem_addr
.node
= scb
->rem_node
;
1327 scb
->rem_addr
.socket
= awp
->func
;
1328 /* bms: need to set the reply_socket for client side too.
1329 This makes ALO atten replies sent by the client work. */
1330 scb
->reply_socket
= scb
->rem_addr
.socket
;
1331 scb
->sess_id
= awp
->param1
;
1333 atalk_putnext(gref
, mioc
);
1334 asp_timout(asp_hangup
, scb
, scb
->session_timer
);
1335 asp_send_tickle(scb
);
1336 dPrintf(D_M_ASP
, D_L_INFO
,
1337 ("asp_ack_reply: CONNECT, loc=%d, rem=%x.%x.%d\n",
1338 scb
->loc_addr
.socket
,
1341 scb
->rem_addr
.socket
));
1345 case ASPSTATE_WaitingForCommandRsp
:
1346 case ASPSTATE_WaitingForWriteRsp
:
1347 case ASPSTATE_WaitingForWriteContinueRsp
:
1348 if (scb
->rem_addr
.node
)
1349 asp_untimout(asp_hangup
, scb
);
1350 NEXT_SEQ_NUM(scb
->snd_seq_num
);
1351 scb
->state
= ASPSTATE_Idle
;
1352 gbuf_set_type(mioc
, MSG_PROTO
);
1353 mx
= gbuf_cont(mioc
);
1354 mdata
= gbuf_cont(mx
);
1355 gbuf_cont(mioc
) = mdata
;
1356 atpBDS
= (struct atpBDS
*)gbuf_rptr(mx
);
1357 cmdreply_ind
= (asp_cmdreply_ind_t
*)gbuf_rptr(mioc
);
1358 cmdreply_ind
->Primitive
= ASPFUNC_CmdReply
;
1359 cmdreply_ind
->CmdResult
= ntohl(*(int *)atpBDS
->bdsUserData
);
1360 gbuf_wset(mioc
,sizeof(asp_cmdreply_ind_t
));
1362 asp_putnext(scb
->gref
, mioc
);
1365 case ASPSTATE_WaitingForCloseSessRsp
:
1367 scb
->state
= ASPSTATE_Close
;
1368 scb
->rem_addr
.node
= 0;
1369 iocbp
->ioc_cmd
= ASPIOC_CloseSession
;
1370 iocbp
->ioc_rval
= 0;
1371 if (gbuf_cont(mioc
)) {
1372 gbuf_freem(gbuf_cont(mioc
));
1373 gbuf_cont(mioc
) = 0;
1375 atalk_putnext(scb
->gref
, mioc
);
1376 atp_cancel_req(scb
->gref
, (unsigned int)scb
->tickle_tid
);
1377 scb
->tickle_tid
= 0;
1381 dPrintf(D_M_ASP
, D_L_WARNING
,
1382 (" : UNKNOWN state, state=%s\n",
1383 aspStateStr(scb
->state
)));
1389 if (scb
->next_scb
) {
1391 * find the responsible scb
1393 scb
= (asp_scb_t
*)iocbp
->ioc_cr
;
1394 if ((scb
== 0) || (scb
->magic_num
!= 222)) {
1395 dPrintf(D_M_ASP
, D_L_ERROR
,
1396 ("asp_ack_reply: CAN'T find scb 2\n"));
1402 switch (scb
->state
) {
1403 case ASPSTATE_Close
:
1404 scb
->rem_addr
.node
= 0;
1413 if (scb
->rem_addr
.node
)
1414 asp_timout(asp_hangup
, scb
, scb
->session_timer
);
1415 } /* asp_ack_reply */
1421 asp_nak_reply(gref
, mioc
)
1422 register gref_t
*gref
;
1423 register gbuf_t
*mioc
;
1425 register asp_scb_t
*scb
;
1426 register ioc_t
*iocbp
;
1428 iocbp
= (ioc_t
*)gbuf_rptr(mioc
);
1430 if (iocbp
->ioc_cmd
== AT_ATP_ISSUE_REQUEST_TICKLE
) {
1432 * no tickle, close session
1434 scb
= (asp_scb_t
*)iocbp
->ioc_cr
;
1437 dPrintf(D_M_ASP
, D_L_WARNING
,
1438 ("tickle_nak: loc=%d, rem=%x.%x.%d, state=%s\n",
1439 scb
->loc_addr
.socket
,
1442 scb
->rem_addr
.socket
,
1443 aspStateStr(scb
->state
)));
1448 scb
= (asp_scb_t
*)gref
->info
;
1454 if (iocbp
->ioc_cmd
== AT_ATP_REQUEST_COMPLETE
) {
1455 if (scb
->next_scb
) {
1457 * find the responsible scb
1459 scb
= (asp_scb_t
*)iocbp
->ioc_private
;
1460 if ((scb
== 0) || (scb
->magic_num
!= 222)) {
1461 dPrintf(D_M_ASP
, D_L_ERROR
,
1462 ("asp_nak_reply: CAN'T find scb 1\n"));
1467 dPrintf(D_M_ASP
, D_L_WARNING
,
1468 ("asp_nak_reply: RSP, loc=%d, rem=%x.%x.%d, state=%s\n",
1469 scb
->loc_addr
.socket
,
1472 scb
->rem_addr
.socket
,
1473 aspStateStr(scb
->state
)));
1475 switch (scb
->state
) {
1476 case ASPSTATE_WaitingForGetStatusRsp
:
1477 iocbp
->ioc_cmd
= ASPIOC_GetStatus
;
1480 case ASPSTATE_WaitingForOpenSessRsp
:
1481 iocbp
->ioc_cmd
= ASPIOC_OpenSession
;
1484 case ASPSTATE_WaitingForCommandRsp
:
1485 case ASPSTATE_WaitingForWriteRsp
:
1486 case ASPSTATE_WaitingForWriteContinueRsp
:
1487 scb
->state
= ASPSTATE_Idle
;
1489 /* last remaining use of MSG_ERROR */
1490 gbuf_set_type(mioc
, MSG_ERROR
);
1491 *gbuf_rptr(mioc
) = (u_char
)EPROTOTYPE
;
1493 if (gbuf_cont(mioc
)) {
1494 gbuf_freem(gbuf_cont(mioc
));
1495 gbuf_cont(mioc
) = 0;
1498 asp_putnext(scb
->gref
, mioc
);
1501 case ASPSTATE_WaitingForCloseSessRsp
:
1502 scb
->state
= ASPSTATE_Close
;
1504 case ASPSTATE_Close
: /* new for PR-2296832 */
1505 scb
->rem_addr
.node
= 0;
1506 iocbp
->ioc_cmd
= ASPIOC_CloseSession
;
1507 iocbp
->ioc_rval
= 0;
1508 if (gbuf_cont(mioc
)) {
1509 gbuf_freem(gbuf_cont(mioc
));
1510 gbuf_cont(mioc
) = 0;
1512 gbuf_set_type(mioc
, MSG_IOCACK
);
1513 atalk_putnext(scb
->gref
, mioc
);
1520 scb
->state
= ASPSTATE_Idle
;
1521 atalk_putnext(gref
, mioc
);
1525 if (scb
->next_scb
) {
1527 * find the responsible scb
1529 scb
= (asp_scb_t
*)iocbp
->ioc_cr
;
1530 if ((scb
== 0) || (scb
->magic_num
!= 222)) {
1531 dPrintf(D_M_ASP
, D_L_ERROR
,
1532 ("asp_nak_reply: CAN'T find scb 2\n"));
1538 switch (scb
->state
) {
1539 case ASPSTATE_Close
:
1540 scb
->rem_addr
.node
= 0;
1546 } /* asp_nak_reply */
1549 * delete scb from the use list
1552 asp_dequeue_scb(scb
)
1556 if (scb
== scb_used_list
) {
1557 if ((scb_used_list
= scb
->next_scb
) != 0)
1558 scb
->next_scb
->prev_scb
= 0;
1560 if ((scb
->prev_scb
->next_scb
= scb
->next_scb
) != 0)
1561 scb
->next_scb
->prev_scb
= scb
->prev_scb
;
1571 StaticProc asp_scb_t
*
1572 asp_find_scb(sock_num
, rem_addr
)
1573 unsigned char sock_num
;
1574 at_inet_t
*rem_addr
;
1577 asp_scb_t
*alt_scb
= 0;
1579 for (scb
= asp_scbQ
[sock_num
]; scb
; scb
= scb
->next_scb
) {
1580 if ((scb
->rem_addr
.net
== rem_addr
->net
)
1581 && (scb
->rem_addr
.node
== rem_addr
->node
)) {
1582 if ((scb
->rem_addr
.socket
== rem_addr
->socket
)
1583 || (scb
->rem_socket
== rem_addr
->socket
))
1585 else if (alt_scb
== 0)
1590 if ((scb
== 0) && ((scb
= alt_scb
) == 0)) {
1591 dPrintf(D_M_ASP
, D_L_ERROR
,
1592 ("asp_find_scb: CAN'T find scb, loc=%d, rem=%x.%x.%d\n",
1606 asp_timout(func
, scb
, seconds
)
1608 register asp_scb_t
*scb
;
1612 register asp_scb_t
*curr_scb
, *prev_scb
;
1617 scb
->tmo_func
= func
;
1618 scb
->tmo_delta
= (seconds
>>SESS_TMO_RES
);
1619 scb
->tmo_cnt
= scb_tmo_cnt
;
1621 if (scb_tmo_list
== 0) {
1622 scb
->next_tmo
= scb
->prev_tmo
= 0;
1628 curr_scb
= scb_tmo_list
;
1632 sum
+= curr_scb
->tmo_delta
;
1633 if (sum
> scb
->tmo_delta
) {
1634 sum
-= curr_scb
->tmo_delta
;
1635 scb
->tmo_delta
-= sum
;
1636 curr_scb
->tmo_delta
-= scb
->tmo_delta
;
1639 prev_scb
= curr_scb
;
1640 if ((curr_scb
= curr_scb
->next_tmo
) == 0) {
1641 scb
->tmo_delta
-= sum
;
1647 scb
->prev_tmo
= prev_scb
;
1648 if ((scb
->next_tmo
= prev_scb
->next_tmo
) != 0)
1649 prev_scb
->next_tmo
->prev_tmo
= scb
;
1650 prev_scb
->next_tmo
= scb
;
1653 scb
->next_tmo
= scb_tmo_list
;
1654 scb_tmo_list
->prev_tmo
= scb
;
1663 asp_untimout(func
, scb
)
1665 register asp_scb_t
*scb
;
1668 if ((scb
->tmo_cnt
== scb_tmo_cnt
) || (scb
->tmo_func
== 0))
1671 if (scb_tmo_list
== scb
) {
1672 if ((scb_tmo_list
= scb
->next_tmo
) != 0) {
1673 scb_tmo_list
->prev_tmo
= 0;
1674 scb
->next_tmo
->tmo_delta
+= scb
->tmo_delta
;
1676 } else if (scb
->prev_tmo
) {
1677 if ((scb
->prev_tmo
->next_tmo
= scb
->next_tmo
) != 0) {
1678 scb
->next_tmo
->prev_tmo
= scb
->prev_tmo
;
1679 scb
->next_tmo
->tmo_delta
+= scb
->tmo_delta
;
1696 * set the state to Close
1698 scb
->state
= ASPSTATE_Close
;
1699 if (scb
->tickle_tid
) {
1700 atp_cancel_req(scb
->gref
, (unsigned int)scb
->tickle_tid
);
1701 scb
->tickle_tid
= 0;
1705 * notify upstream of the hangup
1707 if (scb
->rem_addr
.node
) {
1709 wakeup(&scb
->event
);
1711 atalk_notify_sel(scb
->gref
);
1716 asp_iocack(gref
, mioc
)
1720 if (gbuf_cont(mioc
))
1721 ((ioc_t
*)gbuf_rptr(mioc
))->ioc_count
= gbuf_msgsize(gbuf_cont(mioc
));
1723 ((ioc_t
*)gbuf_rptr(mioc
))->ioc_count
= 0;
1725 gbuf_set_type(mioc
, MSG_IOCACK
);
1726 atalk_putnext(gref
, mioc
);
1730 asp_iocnak(gref
, mioc
, err
)
1735 ((ioc_t
*)gbuf_rptr(mioc
))->ioc_count
= 0;
1738 ((ioc_t
*)gbuf_rptr(mioc
))->ioc_error
= err
;
1739 ((ioc_t
*)gbuf_rptr(mioc
))->ioc_rval
= -1;
1740 if (gbuf_cont(mioc
)) {
1741 gbuf_freem(gbuf_cont(mioc
));
1742 gbuf_cont(mioc
) = 0;
1745 gbuf_set_type(mioc
, MSG_IOCNAK
);
1746 atalk_putnext(gref
, mioc
);
1750 * the alloc scb routine
1752 StaticProc asp_scb_t
*
1757 asp_scb_t
*scb
, *scb_array
;
1759 if (scb_free_list
== 0) {
1760 if ((m
= gbuf_alloc(SCBS_PER_BLK
*sizeof(asp_scb_t
), PRI_MED
)) == 0)
1761 return (asp_scb_t
*)0;
1762 bzero((char *)gbuf_rptr(m
), SCBS_PER_BLK
*sizeof(asp_scb_t
));
1763 gbuf_cont(m
) = scb_resource_m
;
1765 scb_array
= (asp_scb_t
*)gbuf_rptr(m
);
1766 for (i
=0; i
< SCBS_PER_BLK
-1; i
++)
1767 scb_array
[i
].next_scb
= (asp_scb_t
*)&scb_array
[i
+1];
1768 scb_array
[i
].next_scb
= 0;
1769 scb_free_list
= (asp_scb_t
*)&scb_array
[0];
1772 scb
= scb_free_list
;
1773 scb_free_list
= scb
->next_scb
;
1774 ATEVENTINIT(scb
->event
);
1775 ATEVENTINIT(scb
->delay_event
);
1781 * the free scb routine
1788 bzero((char *)scb
, sizeof(asp_scb_t
));
1789 scb
->next_scb
= scb_free_list
;
1790 scb_free_list
= scb
;
1794 * routine to pass up receive data
1797 asp_putnext(gref
, mproto
)
1804 scb
= (asp_scb_t
*)gref
->info
;
1807 * queue the message.
1809 gbuf_next(mproto
) = 0;
1810 if ((m
= scb
->sess_ioc
) == 0)
1811 scb
->sess_ioc
= mproto
;
1813 while (gbuf_next(m
))
1815 gbuf_next(m
) = mproto
;
1818 if (scb
->rcv_cnt
>= MAX_RCV_CNT
)
1822 wakeup(&scb
->event
);
1823 else if (mproto
== scb
->sess_ioc
)
1824 atalk_notify_sel(gref
);
1829 * The following two routines are direct entries from system
1830 * calls to allow fast sending and recving of ASP data.
1833 /* in ASPputmsg we expect:
1839 ASPFUNC_WriteContinue
1841 bms: Make this callable from the kernel.
1842 If mreq != NULL, then must be called from kernel space and the following apply:
1843 1) *mreq is data to be sent already in mbuf chains.
1844 2) datptr->len = size of data
1847 int ASPputmsg(gref_t
*gref
, strbuf_t
*ctlptr
, strbuf_t
*datptr
, gbuf_t
*mreq
, int flags
, int *errp
)
1849 int i
, err
, len
, offset
, remain
, size
, copy_len
;
1850 gbuf_t
*mioc
, *mdata
, *mx
, *m0
;
1855 int nbds
, result
, msize
, Primitive
;
1856 unsigned char *wptr
;
1857 struct atp_set_default
*sd
;
1860 struct atpBDS
*atpBDS
;
1862 union asp_primitives
*primitives
;
1866 if ((scb
= (asp_scb_t
*)gref
->info
) == 0) {
1867 dPrintf(D_M_ASP
, D_L_ERROR
,
1868 ("ASPputmsg: stale handle=0x%x, pid=%d\n",
1869 (u_int
) gref
, gref
->pid
));
1875 if (scb
->state
== ASPSTATE_Close
)
1877 if (scb
->snd_stop
) {
1883 * copy in the control and data info
1886 /* being called from kernel space */
1887 bcopy (ctlptr
, &ctlbuf
, sizeof (strbuf_t
));
1888 bcopy (datptr
, &datbuf
, sizeof (strbuf_t
));
1890 /* being called from user space */
1891 if ((err
= copyin(CAST_USER_ADDR_T(ctlptr
), (caddr_t
)&ctlbuf
, sizeof(ctlbuf
))) != 0)
1893 if ((err
= copyin(CAST_USER_ADDR_T(datptr
), (caddr_t
)&datbuf
, sizeof(datbuf
))) != 0)
1897 /* Radar 5423396: check for bogus length
1898 * Max ASP data is 8 ATP packets
1901 if ((ctlbuf
.len
< 0) || (ctlbuf
.len
> (ATP_DATA_SIZE
* 8))) {
1905 if ((datbuf
.len
< 0) || (datbuf
.len
> (ATP_DATA_SIZE
* 8))) {
1911 * allocate buffer and copy in the control content
1913 if (!(mioc
= gbuf_alloc_wait(ctlbuf
.len
, TRUE
))) {
1914 /* error return should not be possible */
1918 gbuf_set_type(mioc
, MSG_IOCTL
); /* for later, in ATP */
1919 gbuf_wset(mioc
, ctlbuf
.len
);
1922 /* being called from kernel space */
1923 bcopy (ctlbuf
.buf
, gbuf_rptr(mioc
), ctlbuf
.len
);
1925 /* being called from user space */
1926 if ((err
= copyin(CAST_USER_ADDR_T(ctlbuf
.buf
), (caddr_t
)gbuf_rptr(mioc
), ctlbuf
.len
)) != 0) {
1932 iocbp
= (ioc_t
*)gbuf_rptr(mioc
);
1933 primitives
= (union asp_primitives
*)gbuf_rptr(mioc
);
1934 Primitive
= primitives
->Primitive
;
1935 dPrintf(D_M_ASP
, D_L_INFO
,
1936 ("ASPputmsg: %s\n", aspCmdStr(Primitive
)));
1939 * copy in the data content into multiple mbuf clusters if
1940 * required. ATP now expects reply data to be placed in
1941 * standard clusters, not the large external clusters that
1942 * were used previously.
1945 /* set offset for use by some commands */
1946 offset
= (Primitive
== ASPFUNC_CmdReply
) ? 0 : aspCMDsize
;
1949 /* The data from the in-kernel call for use by AFP is passed
1950 * in as one large external cluster. This needs to be copied
1951 * to a chain of standard clusters.
1953 remain
= gbuf_len(mreq
);
1954 dataptr
= mtod(mreq
, caddr_t
);
1956 /* copyin from user space */
1957 remain
= datbuf
.len
;
1958 dataptr
= (caddr_t
)datbuf
.buf
;
1961 /* allocate first buffer */
1962 if (!(mdata
= gbuf_alloc_wait((remain
+ offset
> MCLBYTES
? MCLBYTES
: remain
+ offset
), TRUE
))) {
1963 /* error return should not be possible */
1968 gbuf_wset(mdata
, 0); /* init length to zero */
1969 gbuf_cont(mioc
) = mdata
;
1972 if (remain
+ offset
> MCLBYTES
)
1973 copy_len
= MCLBYTES
- offset
;
1978 bcopy (dataptr
, (gbuf_rptr(mdata
) + offset
), copy_len
);
1979 else if ((err
= copyin(CAST_USER_ADDR_T(dataptr
), (caddr_t
)(gbuf_rptr(mdata
) + offset
), copy_len
)) != 0) {
1983 gbuf_wset(mdata
, (copy_len
+ offset
));
1984 size
+= copy_len
+ offset
;
1985 dataptr
+= copy_len
;
1988 /* allocate the next mbuf */
1989 if ((gbuf_cont(mdata
) = m_get((M_WAIT
), MSG_DATA
)) == 0) {
1994 mdata
= gbuf_cont(mdata
);
1995 MCLGET(mdata
, M_WAIT
);
1996 if (!(mdata
->m_flags
& M_EXT
)) {
2003 mdata
= gbuf_cont(mioc
); /* code further on down expects this to b e set */
2004 mdata
->m_pkthdr
.len
= size
; /* set packet hdr len */
2009 switch (Primitive
) {
2011 case ASPFUNC_Command
:
2013 case ASPFUNC_WriteContinue
:
2014 case ASPFUNC_Attention
:
2016 * build the command/write/write_continue request
2018 wptr
= gbuf_rptr(mdata
);
2019 atpBDS
= (struct atpBDS
*)wptr
;
2021 for (i
=0; i
< ATP_TRESP_MAX
; i
++) {
2022 *(unsigned long *)atpBDS
[i
].bdsBuffAddr
= 1;
2023 *(unsigned short *)atpBDS
[i
].bdsBuffSz
= ATP_DATA_SIZE
;
2025 sd
= (struct atp_set_default
*)wptr
;
2026 wptr
+= sizeof(struct atp_set_default
);
2027 sd
->def_retries
= (scb
->cmd_retry
.retries
== -1) ?
2028 ATP_INFINITE_RETRIES
: scb
->cmd_retry
.retries
;
2029 sd
->def_rate
= scb
->cmd_retry
.interval
*TICKS_PER_SEC
;
2030 sd
->def_BDSlen
= atpBDSsize
;
2031 ddp
= (at_ddp_t
*)wptr
;
2032 NET_ASSIGN(ddp
->src_net
, scb
->loc_addr
.net
);
2033 ddp
->src_node
= scb
->loc_addr
.node
;
2034 NET_ASSIGN(ddp
->dst_net
, scb
->rem_addr
.net
);
2035 ddp
->dst_node
= scb
->rem_addr
.node
;
2036 ddp
->dst_socket
= scb
->rem_addr
.socket
;
2037 UAS_ASSIGN(ddp
->checksum
, 0);
2038 atp
= ATP_ATP_HDR(wptr
);
2039 wptr
+= TOTAL_ATP_HDR_SIZE
;
2043 awp
= (asp_word_t
*)atp
->user_bytes
;
2044 awp
->func
= (unsigned char)Primitive
;
2045 awp
->param1
= scb
->sess_id
;
2046 awp
->param2
= htons(scb
->snd_seq_num
);
2047 iocbp
->ioc_private
= (void *)scb
;
2048 iocbp
->ioc_count
= gbuf_len(mdata
);
2049 iocbp
->ioc_rval
= 0;
2050 iocbp
->ioc_cmd
= AT_ATP_ISSUE_REQUEST_DEF
;
2053 * send the command/write/write_continue/attention request
2055 switch (awp
->func
) {
2056 case ASPFUNC_Command
:
2057 scb
->state
= ASPSTATE_WaitingForCommandRsp
;
2060 scb
->state
= ASPSTATE_WaitingForWriteRsp
;
2062 case ASPFUNC_WriteContinue
:
2063 scb
->state
= ASPSTATE_WaitingForWriteContinueRsp
;
2064 awp
->param2
= htons(scb
->wrt_seq_num
);
2066 case ASPFUNC_Attention
:
2067 scb
->state
= ASPSTATE_WaitingForCommandRsp
;
2072 awp
->param2
= htons(*(unsigned short *)gbuf_wptr(mdata
));
2075 dPrintf(D_M_ASP
,D_L_INFO
,
2076 ("ASPputmsg: %s, loc=%d, rem=%x.%x.%d\n",
2077 (awp
->func
== ASPFUNC_Command
? "CommandReq" :
2078 awp
->func
== ASPFUNC_Write
? "WriteReq" :
2079 awp
->func
== ASPFUNC_WriteContinue
? "WriteContinue" :
2080 "AttentionReq"),scb
->loc_addr
.socket
,
2081 NET_VALUE(ddp
->dst_net
),ddp
->dst_node
,ddp
->dst_socket
));
2082 atp_send_req(gref
, mioc
);
2085 case ASPFUNC_CmdReply
:
2087 if (scb
->req_msgq
) {
2089 scb
->req_msgq
= gbuf_next(mx
);
2091 asp_putnext(scb
->gref
, mx
);
2095 result
= primitives
->CmdReplyReq
.CmdResult
;
2096 tid
= primitives
->CmdReplyReq
.ReqRefNum
;
2098 /* Re-use the original mioc mbuf to send the response. */
2099 gbuf_rinc(mioc
,sizeof(void *));
2101 ddp
= (at_ddp_t
*)gbuf_wptr(mioc
);
2102 gbuf_winc(mioc
,DDP_X_HDR_SIZE
);
2103 atp
= (at_atp_t
*)gbuf_wptr(mioc
);
2104 gbuf_winc(mioc
,ATP_HDR_SIZE
);
2105 NET_ASSIGN(ddp
->src_net
, scb
->loc_addr
.net
);
2106 ddp
->src_node
= scb
->loc_addr
.node
;
2107 NET_ASSIGN(ddp
->dst_net
, scb
->rem_addr
.net
);
2108 ddp
->dst_node
= scb
->rem_addr
.node
;
2109 ddp
->dst_socket
= scb
->reply_socket
;
2110 ddp
->type
= DDP_ATP
;
2111 UAS_ASSIGN(ddp
->checksum
, 0);
2112 UAS_ASSIGN(atp
->tid
, htons(tid
));
2113 if (scb
->attn_flag
&& (tid
== scb
->attn_tid
)) {
2121 /* setup the atpBDS struct - only the length field is used,
2122 * except for the first one which contains the bds count in
2125 atpBDS
= (struct atpBDS
*)gbuf_wptr(mioc
);
2126 msize
= mdata
? gbuf_msgsize(mdata
) : 0;
2127 for (nbds
=0; (nbds
< ATP_TRESP_MAX
) && (msize
> 0); nbds
++) {
2128 len
= msize
< ATP_DATA_SIZE
? msize
: ATP_DATA_SIZE
;
2129 msize
-= ATP_DATA_SIZE
;
2130 *(long *)atpBDS
[nbds
].bdsUserData
= 0;
2131 UAL_ASSIGN(atpBDS
[nbds
].bdsBuffAddr
, 1);
2132 UAS_ASSIGN(atpBDS
[nbds
].bdsBuffSz
, len
);
2134 UAS_ASSIGN(atpBDS
[0].bdsDataSz
, nbds
);
2135 *(long *)atpBDS
[0].bdsUserData
= (long)result
;
2136 *(long *)atp
->user_bytes
= (long)result
;
2137 gbuf_winc(mioc
,atpBDSsize
);
2138 dPrintf(D_M_ASP
, D_L_INFO
,
2139 ("ASPputmsg: ATP CmdReplyReq, loc=%d, state=%s, msgsize = %d, result = %d, tid = %d\n",
2140 scb
->loc_addr
.socket
, aspStateStr(scb
->state
),
2141 (mdata
? gbuf_msgsize(mdata
) : 0), result
, tid
));
2142 atp_send_rsp(gref
, mioc
, TRUE
);
2146 /* Not an expected ASPFUNC */
2156 /* bms: make this callable from kernel. reply date is passed back as a mbuf chain in *mreply */
2157 int ASPgetmsg(gref_t
*gref
, strbuf_t
*ctlptr
, strbuf_t
*datptr
, gbuf_t
**mreply
, int *flags
, int *errp
)
2159 int err
, len
, sum
, rval
;
2160 gbuf_t
*mproto
, *mdata
;
2164 unsigned char get_wait
;
2166 if ((scb
= (asp_scb_t
*)gref
->info
) == 0) {
2167 dPrintf(D_M_ASP
, D_L_ERROR
,
2168 ("ASPgetmsg: stale handle=0x%x, pid=%d\n",
2169 (u_int
) gref
, gref
->pid
));
2175 if (scb
->state
== ASPSTATE_Close
)
2181 while ((mproto
= scb
->sess_ioc
) == 0) {
2183 lck_mtx_assert(atalk_mutex
, LCK_MTX_ASSERT_OWNED
);
2184 err
= msleep(&scb
->event
, atalk_mutex
, PSOCK
| PCATCH
, "aspgetmsg", 0);
2190 if (scb
->state
== ASPSTATE_Close
) {
2195 get_wait
= scb
->get_wait
;
2197 if ((ctlptr
== 0) && (datptr
== 0))
2199 scb
->sess_ioc
= gbuf_next(mproto
);
2200 mdata
= gbuf_cont(mproto
);
2202 /* last remaining use of MSG_ERROR */
2203 if (gbuf_type(mproto
) == MSG_ERROR
) {
2204 err
= (int)gbuf_rptr(mproto
)[0];
2209 * copy in the control and data info
2211 if (mreply
!= NULL
) {
2212 /* called from kernel space */
2213 bcopy (ctlptr
, &ctlbuf
, sizeof(ctlbuf
));
2214 bcopy (datptr
, &datbuf
, sizeof(datbuf
));
2216 /* called from user space */
2217 if ((err
= copyin(CAST_USER_ADDR_T(ctlptr
),
2218 (caddr_t
)&ctlbuf
, sizeof(ctlbuf
))) != 0)
2220 if ((err
= copyin(CAST_USER_ADDR_T(datptr
),
2221 (caddr_t
)&datbuf
, sizeof(datbuf
))) != 0)
2224 if ((datbuf
.maxlen
< 0) || (datbuf
.maxlen
< gbuf_msgsize(mdata
))) {
2225 gbuf_next(mproto
) = scb
->sess_ioc
;
2226 scb
->sess_ioc
= mproto
;
2230 if (get_wait
== 0) {
2232 * this is a hack to support the select() call.
2233 * we're not supposed to dequeue messages in the Streams
2234 * head's read queue this way; but there is no better way.
2236 if (scb
->sess_ioc
!= 0)
2237 atalk_notify_sel(gref
);
2242 * copy out the control content and info
2244 ctlbuf
.len
= gbuf_len(mproto
);
2246 if (mreply
!= NULL
) {
2247 /* called from kernel space */
2248 bcopy (gbuf_rptr(mproto
), ctlbuf
.buf
, ctlbuf
.len
);
2249 bcopy (&ctlbuf
, ctlptr
, sizeof(ctlbuf
));
2251 /* called from user space */
2252 if ((err
= copyout((caddr_t
)gbuf_rptr(mproto
),
2253 CAST_USER_ADDR_T(ctlbuf
.buf
), ctlbuf
.len
)) != 0)
2255 if ((err
= copyout((caddr_t
)&ctlbuf
,
2256 CAST_USER_ADDR_T(ctlptr
), sizeof(ctlbuf
))) != 0)
2261 * copy out the data content and info
2263 for (rval
= 0, sum
= 0; mdata
&& (rval
== 0); mdata
= gbuf_cont(mdata
))
2265 len
= gbuf_len(mdata
);
2267 if ((len
+ sum
) > datbuf
.maxlen
) {
2268 len
= datbuf
.maxlen
- sum
;
2272 if (mreply
== NULL
) {
2273 /* called from user space */
2274 if ((err
= copyout((caddr_t
)gbuf_rptr(mdata
), CAST_USER_ADDR_T(&datbuf
.buf
[sum
]), len
)) != 0)
2281 if (mreply
!= NULL
) {
2282 /* called from kernel space */
2283 bcopy (&datbuf
, datptr
, sizeof(datbuf
));
2285 /* called from user space */
2286 if ((err
= copyout((caddr_t
)&datbuf
, CAST_USER_ADDR_T(datptr
), sizeof(datbuf
))) != 0)
2290 if (mreply
!= NULL
) {
2291 /* called from kernel space */
2292 /* return the reply data in mbufs, so dont free them.
2293 Just free the proto info */
2294 mdata
= gbuf_cont(mproto
);
2296 gbuf_cont(mproto
) = NULL
;
2299 /* called from user space */
2312 gbuf_next(mproto
) = scb
->sess_ioc
;
2313 scb
->sess_ioc
= mproto
;