2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_OSREFERENCE_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
10 * License may not be used to create, or enable the creation or
11 * redistribution of, unlawful or unlicensed copies of an Apple operating
12 * system, or to circumvent, violate, or enable the circumvention or
13 * violation of, any terms of an Apple operating system software license
16 * Please obtain a copy of the License at
17 * http://www.opensource.apple.com/apsl/ and read it before using this
20 * The Original Code and all software distributed under the License are
21 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
22 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
23 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
25 * Please see the License for the specific language governing rights and
26 * limitations under the License.
28 * @APPLE_LICENSE_OSREFERENCE_HEADER_END@
31 * Copyright (c) 1995 Apple Computer, Inc.
34 * Created February 20, 1995 by Tuyen Nguyen
35 * Modified for MP, 1996 by Tuyen Nguyen
36 * Modified, March 17, 1997 by Tuyen Nguyen for MacOSX.
39 #include <sys/errno.h>
40 #include <sys/types.h>
41 #include <sys/param.h>
42 #include <machine/spl.h>
43 #include <sys/systm.h>
44 #include <sys/kernel.h>
46 #include <sys/filedesc.h>
47 #include <sys/fcntl.h>
49 #include <sys/ioctl.h>
50 #include <sys/malloc.h>
51 #include <kern/locks.h>
52 #include <sys/socket.h>
53 #include <sys/socketvar.h>
57 #include <netat/appletalk.h>
58 #include <netat/sysglue.h>
59 #include <netat/at_pcb.h>
60 #include <netat/atp.h>
61 #include <netat/ddp.h>
62 #include <netat/asp.h>
63 #include <netat/at_var.h>
64 #include <netat/debug.h>
67 #define CHK_LOOP(str) { \
68 if (loop_cnt++ > 100) { \
74 #define atpBDSsize (sizeof(struct atpBDS)*ATP_TRESP_MAX)
75 #define aspCMDsize (atpBDSsize+sizeof(struct atp_set_default)+TOTAL_ATP_HDR_SIZE)
76 #define SCBS_PER_BLK 16
77 #define TICKS_PER_SEC HZ
78 #define SESS_TMO_RES 2
79 #define DEF_SESS_TMO 120
80 #define NEXT_SEQ_NUM(x) (x = (x == 65535) ? 0 : (x + 1))
82 #define BAD_REMADDR(addr) \
83 ( (*(long *)&scb->rem_addr != *(long *)&addr) \
84 && ((scb->rem_addr.net != addr.net) \
85 || (scb->rem_addr.node != addr.node)) )
93 void asp_clock_locked(void *);
97 StaticProc asp_scb_t
*asp_find_scb();
98 StaticProc asp_scb_t
*asp_scb_alloc();
100 StaticProc
void asp_putnext();
101 StaticProc
void asp_iocack();
102 StaticProc
void asp_iocnak();
103 StaticProc
void asp_dequeue_scb();
104 StaticProc
void asp_scb_free();
105 StaticProc
void asp_timout();
106 StaticProc
void asp_untimout();
107 StaticProc
void asp_hangup();
108 StaticProc
void asp_send_tickle();
109 StaticProc
void asp_send_tickle_locked(void *);
110 StaticProc
void asp_accept();
111 StaticProc
int asp_send_req();
113 extern at_ifaddr_t
*ifID_home
;
114 extern int atp_pidM
[];
115 extern gref_t
*atp_inputQ
[];
116 extern lck_mtx_t
*atalk_mutex
;
117 gbuf_t
*scb_resource_m
= 0;
118 unsigned char asp_inpC
[256];
119 asp_scb_t
*asp_scbQ
[256];
121 static at_retry_t asp_def_retry
= {2, -1, 1};
122 static unsigned char scb_tmo_cnt
;
123 asp_scb_t
*scb_used_list
;
124 static asp_scb_t
*scb_tmo_list
;
125 asp_scb_t
*scb_free_list
;
131 return (((asp_scb_t
*)gref
->info
)->sess_ioc
? 1 : 0);
141 bzero(asp_inpC
, sizeof(asp_inpC
));
142 bzero(asp_scbQ
, sizeof(asp_scbQ
));
146 * the open routine allocates a state structure
154 * if no asp structure available, return failure
156 if ((scb
= asp_scb_alloc()) == 0)
160 * initialize the gref data structure
162 gref
->info
= (void *)scb
;
163 gref
->readable
= asp_readable
;
166 * initialize the scb data structure
169 scb
->magic_num
= 222;
170 scb
->state
= ASPSTATE_Idle
;
171 scb
->pid
= gref
->pid
;
173 scb
->session_timer
= DEF_SESS_TMO
;
174 scb
->cmd_retry
= asp_def_retry
;
175 if ((scb
->next_scb
= scb_used_list
) != 0)
176 scb
->next_scb
->prev_scb
= scb
;
182 dPrintf(D_M_ASP
, D_L_INFO
, ("asp_open: pid=%d\n", scb
->pid
));
187 * the close routine frees all the data structures
193 unsigned char sock_num
;
194 asp_scb_t
*scb
, *new_scb
;
197 scb
= (asp_scb_t
*)gref
->info
;
198 dPrintf(D_M_ASP
, D_L_INFO
, ("asp_close: loc=%d\n",
199 scb
->loc_addr
.socket
));
201 if (scb
->pid
&& scb
->sess_ioc
&& (scb
->dflag
!= 1)) {
203 * send the CloseSess response to peer
205 if (gbuf_type(scb
->sess_ioc
) != MSG_PROTO
) {
207 scb
->sess_ioc
= gbuf_next(m
);
208 atp_send_rsp(scb
->gref
, m
, TRUE
);
212 if (scb
->atp_state
) {
213 sock_num
= scb
->loc_addr
.socket
;
214 if ((scb
->dflag
!= 1) && scb
->stat_msg
) {
215 untimeout(atp_retry_req
, scb
->stat_msg
);
216 gbuf_freem(scb
->stat_msg
);
219 if (asp_scbQ
[sock_num
]->next_scb
== 0) {
220 asp_scbQ
[sock_num
] = 0;
221 asp_inpC
[sock_num
] = 0;
222 dPrintf(D_M_ASP
, D_L_INFO
,
223 (" : atp_close(), loc=%d\n", scb
->loc_addr
.socket
));
226 asp_inpC
[sock_num
]--;
227 if (scb
== asp_scbQ
[sock_num
]) {
228 new_scb
= scb
->next_scb
;
229 new_scb
->prev_scb
= 0;
230 asp_scbQ
[sock_num
] = new_scb
;
231 new_scb
->atp_state
->atp_gref
= new_scb
->gref
;
232 new_scb
->atp_state
->pid
= new_scb
->pid
;
233 atp_inputQ
[sock_num
] = new_scb
->gref
;
235 if ((scb
->prev_scb
->next_scb
= scb
->next_scb
) != 0)
236 scb
->next_scb
->prev_scb
= scb
->prev_scb
;
241 asp_dequeue_scb(scb
);
244 * free all allocated blocks if any
247 gbuf_freem(scb
->stat_msg
);
251 gbuf_freel(scb
->sess_ioc
);
255 gbuf_freel(scb
->req_msgq
);
259 scb
->rem_addr
.node
= 0;
265 asp_untimout(asp_hangup
, scb
);
266 untimeout(asp_send_tickle_locked
, (void *)scb
); /* added for 2225395 */
269 * free the asp session control block
271 scb
->state
= ASPSTATE_Close
;
276 static char *aspStateStr(state
)
279 return ((state
==ASPSTATE_Close
)? "Close":
280 (state
==ASPSTATE_Idle
)? "Idle":
281 (state
==ASPSTATE_WaitingForGetStatusRsp
)? "GetStatusRsp":
282 (state
==ASPSTATE_WaitingForOpenSessRsp
)? "OpenSessRsp":
283 (state
==ASPSTATE_WaitingForCommandRsp
)? "CmdRsp":
284 (state
==ASPSTATE_WaitingForWriteContinue
)? "WriteCont":
285 (state
==ASPSTATE_WaitingForWriteRsp
)? "WriteRsp":
286 (state
==ASPSTATE_WaitingForWriteContinueRsp
)? "WriteContRsp":
287 (state
==ASPSTATE_WaitingForCloseSessRsp
)? "CloseSessRsp":
291 static char *aspCmdStr(aspCmd
)
294 return ((aspCmd
==ASPFUNC_CloseSess
)? "CloseSess":
295 (aspCmd
==ASPFUNC_Command
)? "Command":
296 (aspCmd
==ASPFUNC_GetStatus
)? "GetStatus":
297 (aspCmd
==ASPFUNC_OpenSess
)? "OpenSess":
298 (aspCmd
==ASPFUNC_Tickle
)? "Tickle":
299 (aspCmd
==ASPFUNC_Write
)? "Write":
300 (aspCmd
==ASPFUNC_WriteContinue
)? "WriteContinue":
301 (aspCmd
==ASPFUNC_Attention
)? "Attention":
302 (aspCmd
==ASPFUNC_CmdReply
)? "CmdReply": "unknown");
305 static char *aspIOCStr(aspIOC
)
309 (aspIOC
==ASPIOC_ClientBind
)? "ClientBind":
310 (aspIOC
==ASPIOC_CloseSession
)? "CloseSession":
311 (aspIOC
==ASPIOC_GetLocEntity
)? "GetLocEntity":
312 (aspIOC
==ASPIOC_GetRemEntity
)? "GetRemEntity":
313 (aspIOC
==ASPIOC_GetSession
)? "GetSession":
314 (aspIOC
==ASPIOC_GetStatus
)? "GetStatus":
315 (aspIOC
==ASPIOC_ListenerBind
)? "ListenerBind":
316 (aspIOC
==ASPIOC_OpenSession
)? "OpenSession":
317 (aspIOC
==ASPIOC_StatusBlock
)? "StatusBlock":
318 (aspIOC
==ASPIOC_SetPid
)? "SetPid":
319 (aspIOC
==ASPIOC_GetSessId
)? "GetSessId":
320 (aspIOC
==ASPIOC_EnableSelect
)? "EnableSelect":
321 (aspIOC
==ASPIOC_Look
)? "Look":
328 static char mbuf_str
[100];
333 "dat = %d, prot = %d, ioc = %d, err = %d, hu = %d, ack = %d, nak = %d, ctl = %d",
335 "dat = %d, prot = %d, ioc = %d, ctl = %d",
336 mbstat
.m_mtypes
[MSG_DATA
], mbstat
.m_mtypes
[MSG_PROTO
], mbstat
.m_mtypes
[MSG_IOCTL
],
338 mbstat.m_mtypes[MSG_ERROR], mbstat.m_mtypes[MSG_HANGUP], mbstat.m_mtypes[MSG_IOCACK],
339 mbstat.m_mtypes[MSG_IOCNAK],
341 mbstat
.m_mtypes
[MSG_CTL
]);
342 return(&mbuf_str
[0]);
345 void trace_beg(str
, m
)
350 gbuf_t
*mdata
, *mchain
;
353 for (i
= 0, j
= 0, mdata
= m
, mchain
= m
; mdata
; i
++) {
354 mdata
= gbuf_cont(mdata
);
355 if (!mdata
&& mchain
) {
356 mdata
= gbuf_next(mchain
);
361 dPrintf(D_M_ASP
, D_L_TRACE
,
362 ("%s: %s, m# = %d, c# = %d\n", str
, mbuf_totals(), i
, j
));
368 dPrintf(D_M_ASP
, D_L_TRACE
,
369 (" %s: %s\n", str
, mbuf_totals()));
371 #endif /* AT_MBUF_TRACE */
376 int asp_wput(gref
, m
)
381 unsigned char sockSav
, sock_num
;
382 gbuf_t
*mioc
, *mdata
;
384 asp_scb_t
*scb
, *server_scb
, *curr_scb
;
387 union asp_primitives
*primitives
;
388 asp_status_cmd_t
*status_cmd
;
389 asp_open_cmd_t
*open_cmd
;
392 scb
= (asp_scb_t
*)gref
->info
;
393 if (scb
->dflag
== 0) {
398 if (gbuf_type(m
) != MSG_IOCTL
) {
399 dPrintf(D_M_ASP
, D_L_WARNING
,
400 ("asp_wput: UNKNOWN message, type=%d\n",
407 iocbp
= (ioc_t
*)gbuf_rptr(mioc
);
409 dPrintf(D_M_ASP_LOW
, D_L_INFO
,
410 ("asp_wput: %s, loc=%d, state=%s\n",
411 aspIOCStr(iocbp
->ioc_cmd
), scb
->loc_addr
.socket
,
412 aspStateStr(scb
->state
)));
414 switch (iocbp
->ioc_cmd
) {
415 case ASPIOC_CloseSession
:
416 if ((scb
->state
== ASPSTATE_Close
) || (scb
->rem_addr
.node
== 0))
421 aw
.func
= ASPFUNC_CloseSess
;
422 aw
.param1
= scb
->sess_id
;
424 iocbp
->ioc_private
= (void *)scb
;
425 scb
->ioc_wait
= (unsigned char)(iocbp
->ioc_cmd
& 0xff);
426 iocbp
->ioc_cmd
= AT_ATP_ISSUE_REQUEST
;
427 asp_send_req(gref
, mioc
, &scb
->rem_addr
, &Retry
, &aw
,
428 0, ASPSTATE_WaitingForCloseSessRsp
, 0x01);
431 case ASPIOC_ClientBind
:
433 * open an ATP channel
435 if ((err
= atp_open(gref
, 0)) != 0) {
436 asp_iocnak(gref
, mioc
, err
);
439 scb
->atp_state
= (atp_state_t
*)gref
->info
;
440 scb
->atp_state
->pid
= scb
->pid
;
442 * bind to any available socket
445 sockSav
= scb
->dflag
;
446 if ((sock_num
= (at_socket
)atp_bind(gref
, 0, &sockSav
)) == 0) {
447 scb
->atp_state
= (atp_state_t
*)0;
449 gref
->info
= (void *)scb
;
450 asp_iocnak(gref
, mioc
, EINVAL
);
453 gref
->info
= (void *)scb
;
454 asp_dequeue_scb(scb
);
455 scb
->atp_state
->dflag
= scb
->dflag
;
456 scb
->loc_addr
.socket
= sock_num
;
457 asp_scbQ
[sock_num
] = scb
;
458 asp_inpC
[sock_num
]++;
459 atp_pidM
[sock_num
] = 0;
462 case ASPIOC_ListenerBind
:
464 * open an ATP channel
466 if ((err
= atp_open(gref
, 0)) != 0) {
467 asp_iocnak(gref
, mioc
, err
);
470 scb
->atp_state
= (atp_state_t
*)gref
->info
;
471 scb
->atp_state
->pid
= scb
->pid
;
473 * bind to any available socket
475 if ((sock_num
= (at_socket
)atp_bind(gref
, 0, 0)) == 0) {
476 scb
->atp_state
= (atp_state_t
*)0;
478 gref
->info
= (void *)scb
;
479 asp_iocnak(gref
, mioc
, EINVAL
);
482 gref
->info
= (void *)scb
;
483 asp_dequeue_scb(scb
);
484 scb
->atp_state
->dflag
= scb
->dflag
;
485 scb
->loc_addr
.socket
= sock_num
;
486 asp_scbQ
[sock_num
] = scb
;
487 asp_inpC
[sock_num
]++;
489 *(at_inet_t
*)gbuf_rptr(gbuf_cont(mioc
)) = scb
->loc_addr
;
492 case ASPIOC_GetLocEntity
:
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
->loc_addr
;
500 case ASPIOC_GetRemEntity
:
501 if ((gbuf_cont(mioc
) == 0) || (scb
->atp_state
== 0)) {
502 asp_iocnak(gref
, mioc
, EPROTOTYPE
);
505 *(at_inet_t
*)gbuf_rptr(gbuf_cont(mioc
)) = scb
->rem_addr
;
508 case ASPIOC_GetSession
:
509 if ((mdata
= gbuf_cont(mioc
)) == 0) {
510 asp_iocnak(gref
, mioc
, EPROTOTYPE
);
513 addr
= (at_inet_t
*)gbuf_rptr(mdata
);
514 scb
->tickle_interval
= (unsigned short)addr
->node
;
515 scb
->session_timer
= addr
->net
;
516 server_scb
= asp_scbQ
[addr
->socket
];
517 /*### LD 10/28/97: changed to make sure we're not accessing a null server_scb */
518 if (server_scb
== 0) {
519 asp_iocnak(gref
, mioc
, EPROTOTYPE
);
522 if (server_scb
->sess_ioc
== 0) {
523 asp_iocnak(gref
, mioc
, EPROTOTYPE
);
528 * open an ATP channel
530 if ((err
= atp_open(gref
, 0)) != 0) {
531 gref
->info
= (void *)scb
;
532 asp_iocnak(gref
, mioc
, err
);
535 scb
->atp_state
= (atp_state_t
*)gref
->info
;
536 scb
->atp_state
->pid
= scb
->pid
;
538 * bind to any available socket
541 sockSav
= scb
->dflag
;
542 if ((sock_num
= (at_socket
)atp_bind(gref
, 0, &sockSav
)) == 0) {
544 asp_dequeue_scb(scb
);
546 scb
->loc_addr
.socket
= sock_num
;
547 for (curr_scb
= asp_scbQ
[sock_num
];
548 curr_scb
->next_scb
; curr_scb
= curr_scb
->next_scb
) ;
549 scb
->prev_scb
= curr_scb
;
550 curr_scb
->next_scb
= scb
;
551 scb
->atp_state
= curr_scb
->atp_state
;
553 asp_dequeue_scb(scb
);
554 scb
->loc_addr
.socket
= sock_num
;
555 asp_scbQ
[sock_num
] = scb
;
556 scb
->atp_state
->dflag
= scb
->dflag
;
558 gref
->info
= (void *)scb
;
559 asp_inpC
[sock_num
]++;
561 asp_accept(server_scb
, scb
, mdata
);
564 case ASPIOC_GetStatus
:
565 if ((mdata
= gbuf_cont(mioc
)) == 0) {
566 asp_iocnak(gref
, mioc
, EINVAL
);
570 status_cmd
= (asp_status_cmd_t
*)gbuf_rptr(mdata
);
571 aw
.func
= ASPFUNC_GetStatus
;
574 scb
->ioc_wait
= (unsigned char)(iocbp
->ioc_cmd
& 0xff);
575 iocbp
->ioc_cmd
= AT_ATP_ISSUE_REQUEST_DEF
;
576 /* bms: make sure this is an ALO request */
577 asp_send_req(gref
, mioc
, &status_cmd
->SLSEntityIdentifier
,
578 &status_cmd
->Retry
, &aw
, 0, ASPSTATE_WaitingForGetStatusRsp
, 0xff);
582 case ASPIOC_OpenSession
:
583 if ((mdata
= gbuf_cont(mioc
)) == 0) {
584 asp_iocnak(gref
, mioc
, EINVAL
);
588 open_cmd
= (asp_open_cmd_t
*)gbuf_rptr(mdata
);
589 scb
->svc_addr
= open_cmd
->SLSEntityIdentifier
;
590 scb
->rem_addr
= scb
->svc_addr
;
591 scb
->rem_node
= scb
->rem_addr
.node
;
592 scb
->rem_addr
.node
= 0;
593 scb
->tickle_interval
= open_cmd
->TickleInterval
;
594 scb
->session_timer
= open_cmd
->SessionTimer
;
595 aw
.func
= ASPFUNC_OpenSess
;
596 aw
.param1
= scb
->loc_addr
.socket
;
597 aw
.param2
= htons(ASP_Version
);
598 scb
->ioc_wait
= (unsigned char)(iocbp
->ioc_cmd
& 0xff);
599 iocbp
->ioc_cmd
= AT_ATP_ISSUE_REQUEST_DEF
;
600 asp_send_req(gref
, mioc
, &open_cmd
->SLSEntityIdentifier
,
601 &open_cmd
->Retry
, &aw
, 1, ASPSTATE_WaitingForOpenSessRsp
, 0x01);
605 case ASPIOC_StatusBlock
:
607 * save the server status block
610 gbuf_freem(scb
->stat_msg
);
611 scb
->stat_msg
= gbuf_cont(mioc
);
615 /* *** Does scb->pid get used in a packet header,
616 and if so is it in ASP, or in ATP?
617 If not, do we need this call for anything?
618 (cap does currently use it in _ANS code.)
621 if (gbuf_cont(mioc
) == 0) {
622 asp_iocnak(gref
, mioc
, EINVAL
);
625 scb
->pid
= *(int *)gbuf_rptr(gbuf_cont(mioc
));
628 case ASPIOC_GetSessId
:
629 if (gbuf_cont(mioc
) == 0) {
630 asp_iocnak(gref
, mioc
, EINVAL
);
633 *(gref_t
**)gbuf_rptr(gbuf_cont(mioc
)) = gref
;
637 if (gbuf_cont(mioc
) == 0) {
638 asp_iocnak(gref
, mioc
, EINVAL
);
642 primitives
= (union asp_primitives
*)gbuf_rptr(scb
->sess_ioc
);
643 if (primitives
->Primitive
== ASPFUNC_CmdReply
)
644 *(int *)gbuf_rptr(gbuf_cont(mioc
)) = 0;
646 *(int *)gbuf_rptr(gbuf_cont(mioc
)) = 1;
648 *(int *)gbuf_rptr(gbuf_cont(mioc
)) = -1;
651 case DDP_IOC_GET_CFG
:
653 struct atp_state
*atp
= (struct atp_state
*)gref
->info
;
655 atp
= (struct atp_state
*)atp
->atp_msgq
;
657 if (gbuf_cont(mioc
) == 0) {
658 asp_iocnak(gref
, mioc
, EINVAL
);
661 /* *** borrowed from ddp_proto.c to handle DDP_IOC_GET_CFG
663 scb
->state
= ASPSTATE_Idle
;
665 /* *** was ddp_get_cfg() *** */
667 (ddp_addr_t
*)gbuf_rptr(gbuf_cont(mioc
));
668 cfgp
->inet
.net
= ifID_home
->ifThisNode
.s_net
;
669 cfgp
->inet
.node
= ifID_home
->ifThisNode
.s_node
;
670 cfgp
->inet
.socket
= atp
->atp_socket_no
;
671 cfgp
->ddptype
= DDP_ATP
;
673 gbuf_wset(gbuf_cont(mioc
), sizeof(at_inet_t
));
678 asp_iocnak(gref
, mioc
, EINVAL
);
682 asp_iocack(gref
, mioc
);
687 * send request routine
690 asp_send_req(gref
, mioc
, dest
, retry
, awp
, xo
, state
, bitmap
)
698 unsigned char bitmap
;
703 struct atp_set_default
*sd
;
706 struct atpBDS
*atpBDS
;
707 asp_scb_t
*scb
= (asp_scb_t
*)gref
->info
;
710 * allocate an ATP buffer for the request
712 if ((gbuf_cont(mioc
) = gbuf_alloc(aspCMDsize
, PRI_MED
)) == 0) {
713 if (awp
->func
== ASPFUNC_Tickle
)
716 asp_iocnak(gref
, mioc
, ENOBUFS
);
717 dPrintf(D_M_ASP
, D_L_WARNING
,
718 ("asp_send_req: ENOBUFS, loc=%d\n", scb
->loc_addr
.socket
));
722 mdata
= gbuf_cont(mioc
);
723 iocbp
= (ioc_t
*)gbuf_rptr(mioc
);
728 atpBDS
= (struct atpBDS
*)gbuf_rptr(mdata
);
729 gbuf_wset(mdata
,atpBDSsize
);
730 for (i
=0; i
< ATP_TRESP_MAX
; i
++) {
731 *(unsigned long *)atpBDS
[i
].bdsBuffAddr
= 1;
732 *(unsigned short *)atpBDS
[i
].bdsBuffSz
= ATP_DATA_SIZE
;
734 sd
= (struct atp_set_default
*)gbuf_wptr(mdata
);
735 gbuf_winc(mdata
,sizeof(struct atp_set_default
));
736 sd
->def_retries
= (retry
->retries
== -1) ?
737 ATP_INFINITE_RETRIES
: retry
->retries
;
738 sd
->def_rate
= retry
->interval
*TICKS_PER_SEC
;
739 sd
->def_BDSlen
= atpBDSsize
;
740 ddp
= (at_ddp_t
*)gbuf_wptr(mdata
);
741 NET_ASSIGN(ddp
->src_net
, scb
->loc_addr
.net
);
742 ddp
->src_node
= scb
->loc_addr
.node
;
743 NET_ASSIGN(ddp
->dst_net
, dest
->net
);
744 ddp
->dst_node
= dest
->node
;
745 ddp
->dst_socket
= dest
->socket
;
746 UAS_ASSIGN(ddp
->checksum
, 0);
747 atp
= ATP_ATP_HDR(gbuf_wptr(mdata
));
750 atp
->bitmap
= bitmap
;
751 gbuf_winc(mdata
,TOTAL_ATP_HDR_SIZE
);
752 *(asp_word_t
*)atp
->user_bytes
= *awp
;
753 iocbp
->ioc_count
= gbuf_len(mdata
);
760 dPrintf(D_M_ASP
, D_L_INFO
,
761 ("asp_send_req: %s, loc=%d, rem= %d, len=%d, state=%s\n",
762 aspCmdStr(awp
->func
),
763 scb
->loc_addr
.socket
, ddp
->dst_socket
, iocbp
->ioc_count
,
764 aspStateStr(scb
->state
)));
766 atp_send_req(gref
, mioc
);
771 * send tickle routine - locked version
774 asp_send_tickle_locked(scb
)
778 asp_send_tickle((asp_scb_t
*)scb
);
784 * send tickle routine
797 * make sure the connection is still there
799 if (scb
->rem_addr
.node
== 0) {
803 if ((mioc
= gbuf_alloc(sizeof(ioc_t
), PRI_HI
)) == 0) {
804 dPrintf(D_M_ASP
, D_L_WARNING
,
805 ("asp_send_tickle: ENOBUFS 0, loc=%d, rem=%d\n",
806 scb
->loc_addr
.socket
,scb
->rem_addr
.socket
));
807 timeout(asp_send_tickle_locked
, (void *)scb
, 10);
810 gbuf_wset(mioc
,sizeof(ioc_t
));
811 gbuf_set_type(mioc
, MSG_IOCTL
);
813 dest
= scb
->svc_addr
.node
?
814 (at_inet_t
*)&scb
->svc_addr
: (at_inet_t
*)&scb
->rem_addr
;
815 retry
.interval
= scb
->tickle_interval
;
818 aw
.func
= ASPFUNC_Tickle
;
819 aw
.param1
= scb
->sess_id
;
821 ((ioc_t
*)gbuf_rptr(mioc
))->ioc_cr
= (void *)scb
;
822 ((ioc_t
*)gbuf_rptr(mioc
))->ioc_cmd
= AT_ATP_ISSUE_REQUEST_TICKLE
;
824 if (asp_send_req(scb
->gref
, mioc
, dest
, &retry
, &aw
, 0, scb
->state
, 0)) {
825 dPrintf(D_M_ASP
, D_L_WARNING
,
826 ("asp_send_tickle: ENOBUFS 1, loc=%d, rem=%d\n",
827 scb
->loc_addr
.socket
,scb
->rem_addr
.socket
));
829 timeout(asp_send_tickle_locked
, (void *)scb
, 10);
835 * accept connection routine
838 asp_accept(scb
, sess_scb
, m
)
849 mdata
= scb
->sess_ioc
;
850 ddp
= (at_ddp_t
*)gbuf_rptr(mdata
);
851 atp
= (at_atp_t
*)(gbuf_rptr(mdata
) + DDP_X_HDR_SIZE
);
852 rem_addr
.net
= NET_VALUE(ddp
->src_net
);
853 rem_addr
.node
= ddp
->src_node
;
854 rem_addr
.socket
= ddp
->src_socket
;
855 awp
= (asp_word_t
*)atp
->user_bytes
;
857 sess_scb
->loc_addr
.net
= NET_VALUE(ddp
->dst_net
);
858 sess_scb
->loc_addr
.node
= ddp
->dst_node
;
859 NET_ASSIGN(ddp
->src_net
, sess_scb
->loc_addr
.net
);
860 ddp
->src_node
= sess_scb
->loc_addr
.node
;
861 NET_ASSIGN(ddp
->dst_net
, rem_addr
.net
);
862 ddp
->dst_node
= rem_addr
.node
;
863 ddp
->dst_socket
= rem_addr
.socket
;
865 sess_scb
->sess_id
= sess_scb
->loc_addr
.socket
;
866 sess_scb
->rem_socket
= rem_addr
.socket
;
867 sess_scb
->rem_addr
= rem_addr
;
868 sess_scb
->rem_addr
.socket
= awp
->param1
;
869 sess_scb
->reply_socket
= sess_scb
->rem_addr
.socket
;
870 awp
->func
= sess_scb
->loc_addr
.socket
;
871 awp
->param1
= sess_scb
->sess_id
;
874 scb
->sess_ioc
= gbuf_next(mdata
);
875 gbuf_next(mdata
) = 0;
876 asp_timout(asp_hangup
, sess_scb
, sess_scb
->session_timer
);
877 atp_send_rsp(scb
->gref
, mdata
, TRUE
);
878 asp_send_tickle(sess_scb
);
879 dPrintf(D_M_ASP
, D_L_INFO
,
880 ("asp_accept: ACCEPT connect request, loc=%d, rem=%x.%x.%d\n",
881 sess_scb
->loc_addr
.socket
,
882 sess_scb
->rem_addr
.net
,
883 sess_scb
->rem_addr
.node
,sess_scb
->rem_addr
.socket
));
887 * timer routine - locked version
889 void asp_clock_locked(arg
)
907 scb_tmo_list
->tmo_delta
--;
908 while (((scb
= scb_tmo_list
) != 0) && (scb_tmo_list
->tmo_delta
== 0)) {
909 if ((scb_tmo_list
= scb
->next_tmo
) != 0)
910 scb_tmo_list
->prev_tmo
= 0;
911 if ((tmo_func
= scb
->tmo_func
) != 0) {
917 if (++scb_tmo_cnt
== 0) scb_tmo_cnt
++;
918 timeout(asp_clock_locked
, (void *)arg
, (1<<SESS_TMO_RES
)*TICKS_PER_SEC
);
926 asp_ack_reply(gref
, mioc
)
927 register gref_t
*gref
;
928 register gbuf_t
*mioc
;
930 int len
, msize
, nbds
;
931 register gbuf_t
*mdata
, *m
, *mx
;
932 struct atpBDS
*atpBDS
;
935 register asp_scb_t
*scb
, *sess_scb
;
936 register ioc_t
*iocbp
;
937 register asp_word_t
*awp
;
938 register asp_command_ind_t
*command_ind
;
939 register asp_cmdreply_ind_t
*cmdreply_ind
;
942 iocbp
= (ioc_t
*)gbuf_rptr(mioc
);
944 if (iocbp
->ioc_cmd
== AT_ATP_ISSUE_REQUEST_TICKLE
) {
946 * ignore the ack for the tickle request
948 scb
= (asp_scb_t
*)iocbp
->ioc_cr
;
949 scb
->tickle_tid
= (unsigned short)iocbp
->ioc_rval
;
954 scb
= (asp_scb_t
*)gref
->info
;
960 if (iocbp
->ioc_cmd
== AT_ATP_GET_POLL
) {
962 * if no data, just drop the request
964 if ((mdata
= gbuf_cont(mioc
)) == 0) {
969 gbuf_set_type(mioc
, MSG_IOCTL
);
970 ddp
= (at_ddp_t
*)gbuf_rptr(mdata
);
971 gbuf_rinc(mdata
,DDP_X_HDR_SIZE
);
972 atp
= (at_atp_t
*)gbuf_rptr(mdata
);
973 gbuf_rinc(mdata
,ATP_HDR_SIZE
);
974 rem_addr
.net
= NET_VALUE(ddp
->src_net
);
975 rem_addr
.node
= ddp
->src_node
;
976 rem_addr
.socket
= ddp
->src_socket
;
977 awp
= (asp_word_t
*)atp
->user_bytes
;
981 * find the responsible scb
983 if ((scb
= asp_find_scb(scb
->loc_addr
.socket
, &rem_addr
)) == 0) {
988 dPrintf(D_M_ASP
, D_L_INFO
,
989 ("asp_ack_reply: %s, loc=%d, rem=%x.%x.%d\n",
990 aspCmdStr(awp
->func
),scb
->loc_addr
.socket
,
991 NET_VALUE(ddp
->src_net
) ,ddp
->src_node
,ddp
->src_socket
));
993 if (scb
->rem_addr
.node
)
994 asp_untimout(asp_hangup
, scb
);
997 case ASPFUNC_GetStatus
:
999 * ignore if this is not a server socket
1002 if ((scb
->dflag
!= 1) || (scb
->stat_msg
1003 && ((mx
= gbuf_dupb(scb
->stat_msg
)) == 0)))
1008 * send the status block
1010 if (gbuf_cont(mdata
)) {
1011 gbuf_freem(gbuf_cont(mdata
));
1012 gbuf_cont(mdata
) = 0;
1014 gbuf_rdec(mdata
,TOTAL_ATP_HDR_SIZE
);
1015 if ((m
= gbuf_alloc( (TOTAL_ATP_HDR_SIZE
+atpBDSsize
), PRI_MED
)) == 0) {
1020 bcopy(gbuf_rptr(mdata
), gbuf_rptr(m
), TOTAL_ATP_HDR_SIZE
);
1023 ddp
= (at_ddp_t
*)gbuf_rptr(mdata
);
1024 gbuf_wset(mdata
,DDP_X_HDR_SIZE
);
1025 atp
= (at_atp_t
*)gbuf_wptr(mdata
);
1026 gbuf_winc(mdata
,ATP_HDR_SIZE
);
1027 awp
= (asp_word_t
*)atp
->user_bytes
;
1028 NET_NET(ddp
->src_net
, ddp
->dst_net
);
1029 ddp
->src_node
= ddp
->dst_node
;
1030 NET_ASSIGN(ddp
->dst_net
, rem_addr
.net
);
1031 ddp
->dst_node
= rem_addr
.node
;
1032 ddp
->dst_socket
= rem_addr
.socket
;
1033 UAS_ASSIGN(ddp
->checksum
, 0);
1034 atpBDS
= (struct atpBDS
*)gbuf_wptr(mdata
);
1035 msize
= mx
? gbuf_msgsize(mx
) : 0;
1036 for (nbds
=0; (nbds
< ATP_TRESP_MAX
) && (msize
> 0); nbds
++) {
1037 len
= msize
< ATP_DATA_SIZE
? msize
: ATP_DATA_SIZE
;
1038 msize
-= ATP_DATA_SIZE
;
1039 *(long *)atpBDS
[nbds
].bdsUserData
= 0;
1040 UAL_ASSIGN(atpBDS
[nbds
].bdsBuffAddr
, 1);
1041 UAS_ASSIGN(atpBDS
[nbds
].bdsBuffSz
, len
);
1043 UAS_ASSIGN(atpBDS
[0].bdsDataSz
, nbds
);
1044 gbuf_winc(mdata
,atpBDSsize
);
1045 gbuf_cont(mdata
) = mx
;
1046 atp_send_rsp(gref
, mdata
, FALSE
);
1049 case ASPFUNC_OpenSess
:
1051 * ignore if server is not ready
1053 if ((scb
->dflag
!= 1) || (scb
->stat_msg
== 0))
1057 if (gbuf_cont(mdata
)) {
1058 gbuf_freem(gbuf_cont(mdata
));
1059 gbuf_cont(mdata
) = 0;
1061 gbuf_rdec(mdata
,TOTAL_ATP_HDR_SIZE
);
1062 gbuf_wset(mdata
,TOTAL_ATP_HDR_SIZE
);
1063 if (awp
->param2
!= ASP_Version
) {
1065 * bad version number, send the OpenSession response
1069 awp
->param2
= htons((unsigned short)ASPERR_BadVersNum
);
1070 dPrintf(D_M_ASP
, D_L_INFO
,
1072 ASPERR_BadVersNum
));
1074 NET_NET(ddp
->src_net
, ddp
->dst_net
);
1075 ddp
->src_node
= ddp
->dst_node
;
1076 NET_ASSIGN(ddp
->dst_net
, rem_addr
.net
);
1077 ddp
->dst_node
= rem_addr
.node
;
1078 ddp
->dst_socket
= rem_addr
.socket
;
1079 atp_send_rsp(gref
, mdata
, FALSE
);
1084 * queue the connection request
1086 gbuf_next(mdata
) = 0;
1087 if ((m
= scb
->sess_ioc
) == 0) {
1088 scb
->sess_ioc
= mdata
;
1090 wakeup(&scb
->event
);
1092 atalk_notify_sel(gref
);
1094 while (gbuf_next(m
))
1096 gbuf_next(m
) = mdata
;
1098 dPrintf(D_M_ASP
, D_L_INFO
,
1099 (" : QUEUE connect request\n"));
1103 case ASPFUNC_Command
:
1105 if ( (scb
->sess_id
!= awp
->param1
)
1106 || (scb
->rcv_seq_num
!= ntohs(awp
->param2
))
1107 || BAD_REMADDR(rem_addr
) ) {
1109 sprintf(era
,"%d.%d", scb
->rem_addr
.node
,scb
->rem_addr
.socket
);
1110 sprintf(ra
,"%d.%d", rem_addr
.node
,rem_addr
.socket
);
1111 dPrintf(D_M_ASP
, D_L_WARNING
,
1112 (" : DROP, id=%d,esn=%d,sn=%d,erem=%s,rem=%s\n",
1113 scb
->sess_id
,scb
->rcv_seq_num
,awp
->param2
,era
,ra
));
1114 gbuf_cont(mioc
) = 0;
1115 gbuf_rdec(mdata
,TOTAL_ATP_HDR_SIZE
);
1116 atp_drop_req(gref
, mdata
);
1119 scb
->reply_socket
= rem_addr
.socket
;
1120 if (awp
->func
== ASPFUNC_Write
)
1121 scb
->wrt_seq_num
= scb
->rcv_seq_num
;
1122 NEXT_SEQ_NUM(scb
->rcv_seq_num
);
1123 gbuf_set_type(mioc
, MSG_PROTO
);
1124 gbuf_wset(mioc
,sizeof(asp_command_ind_t
));
1125 command_ind
= (asp_command_ind_t
*)gbuf_rptr(mioc
);
1126 command_ind
->Primitive
= (int)awp
->func
;
1127 command_ind
->ReqRefNum
=
1128 ntohs(*(unsigned short *)atp
->tid
);
1129 command_ind
->ReqType
= awp
->func
;
1131 mdata
= gbuf_strip(mdata
);
1132 gbuf_cont(mioc
) = mdata
;
1133 if (scb
->req_flag
) {
1134 if ((mx
= scb
->req_msgq
) != 0) {
1135 while (gbuf_next(mx
))
1137 gbuf_next(mx
) = mioc
;
1139 scb
->req_msgq
= mioc
;
1142 asp_putnext(scb
->gref
, mioc
);
1146 case ASPFUNC_WriteContinue
:
1147 if ( (scb
->sess_id
!= awp
->param1
)
1148 || (scb
->snd_seq_num
!= awp
->param2
)
1149 || BAD_REMADDR(rem_addr
) ) {
1152 scb
->reply_socket
= rem_addr
.socket
;
1153 gbuf_set_type(mioc
, MSG_PROTO
);
1154 gbuf_wset(mioc
,sizeof(asp_command_ind_t
));
1155 command_ind
= (asp_command_ind_t
*)gbuf_rptr(mioc
);
1156 command_ind
->Primitive
= (int)awp
->func
;
1157 command_ind
->ReqRefNum
=
1158 ntohs(*(unsigned short *)atp
->tid
);
1159 command_ind
->ReqType
= awp
->func
;
1161 mdata
= gbuf_strip(mdata
);
1162 gbuf_cont(mioc
) = mdata
;
1163 asp_putnext(scb
->gref
, mioc
);
1166 case ASPFUNC_Tickle
:
1167 if (scb
->stat_msg
) {
1168 sess_scb
= asp_scbQ
[awp
->param1
];
1169 if (sess_scb
&& sess_scb
->next_scb
)
1170 sess_scb
= asp_find_scb(
1171 sess_scb
->loc_addr
.socket
, &rem_addr
);
1173 if (sess_scb
->rem_addr
.node
)
1174 asp_untimout(asp_hangup
, sess_scb
);
1175 if (sess_scb
->rem_addr
.node
)
1176 asp_timout(asp_hangup
, sess_scb
, sess_scb
->session_timer
);
1179 dPrintf(D_M_ASP
, D_L_INFO
,
1180 (" : Tickle, %d -> %d, id=%d\n",
1181 ddp
->src_socket
,ddp
->dst_socket
,awp
->param1
));
1184 case ASPFUNC_CloseSess
:
1185 if ( (scb
->sess_id
!= awp
->param1
)
1186 || (scb
->state
== ASPSTATE_Close
)
1187 || (scb
->state
== ASPSTATE_WaitingForCloseSessRsp
)
1188 || (scb
->rem_addr
.net
!= rem_addr
.net
)
1189 || (scb
->rem_addr
.node
!= rem_addr
.node
) ) {
1190 dPrintf(D_M_ASP
, D_L_INFO
,
1191 (" : CLOSE retry, loc=%d, rem=%x.%x.%d\n",
1192 scb
->loc_addr
.socket
,
1195 scb
->rem_addr
.socket
));
1202 * build the CloseSess response to be sent to peer
1203 * when the session is closed by the user.
1205 if (gbuf_cont(mdata
)) {
1206 gbuf_freem(gbuf_cont(mdata
));
1207 gbuf_cont(mdata
) = 0;
1209 gbuf_rdec(mdata
,TOTAL_ATP_HDR_SIZE
);
1210 gbuf_wset(mdata
,TOTAL_ATP_HDR_SIZE
);
1211 NET_NET(ddp
->src_net
, ddp
->dst_net
);
1212 ddp
->src_node
= ddp
->dst_node
;
1213 NET_ASSIGN(ddp
->dst_net
, rem_addr
.net
);
1214 ddp
->dst_node
= rem_addr
.node
;
1215 ddp
->dst_socket
= rem_addr
.socket
;
1219 dPrintf(D_M_ASP
,D_L_INFO
,
1220 (" : CLOSE, loc=%d, rem=%x.%x.%d\n",
1221 scb
->loc_addr
.socket
,
1224 scb
->rem_addr
.socket
));
1226 gbuf_next(mdata
) = 0;
1228 gbuf_freel(scb
->sess_ioc
);
1229 scb
->sess_ioc
= mdata
;
1230 scb
->state
= ASPSTATE_Close
;
1233 * notify upstream of the CloseSess from peer
1238 case ASPFUNC_Attention
:
1239 if ( (scb
->sess_id
!= awp
->param1
)
1240 || (scb
->rem_addr
.net
!= rem_addr
.net
)
1241 || (scb
->rem_addr
.node
!= rem_addr
.node
) ) {
1244 gbuf_set_type(mioc
, MSG_PROTO
);
1245 gbuf_wset(mioc
,sizeof(asp_command_ind_t
));
1246 command_ind
= (asp_command_ind_t
*)gbuf_rptr(mioc
);
1247 command_ind
->Primitive
= (int)awp
->func
;
1248 command_ind
->ReqRefNum
=
1249 ntohs(*(unsigned short *)atp
->tid
);
1250 command_ind
->ReqType
= awp
->func
;
1251 scb
->attn_tid
= *(unsigned short *)atp
->tid
;
1253 gbuf_rdec(mdata
,2); /* attention code */
1255 mdata
= gbuf_strip(mdata
);
1256 gbuf_cont(mioc
) = mdata
;
1257 asp_putnext(scb
->gref
, mioc
);
1261 dPrintf(D_M_ASP
, D_L_WARNING
,
1262 (" : UNKNOWN func, func=%d\n",
1269 else if (iocbp
->ioc_cmd
== AT_ATP_REQUEST_COMPLETE
) {
1270 if (scb
->next_scb
) {
1272 * find the responsible scb
1274 scb
= (asp_scb_t
*)iocbp
->ioc_private
;
1275 if ((scb
== 0) || (scb
->magic_num
!= 222)) {
1276 dPrintf(D_M_ASP
, D_L_ERROR
,
1277 ("asp_ack_reply: CAN'T find scb 1\n"));
1282 dPrintf(D_M_ASP
, D_L_INFO
,
1283 ("asp_ack_reply: RSP, loc=%d, rem=%x.%x.%d, state=%s\n",
1284 scb
->loc_addr
.socket
,
1287 scb
->rem_addr
.socket
,
1288 aspStateStr(scb
->state
)));
1290 switch (scb
->state
) {
1291 case ASPSTATE_Close
:
1293 scb
->rem_addr
.node
= 0;
1296 wakeup(&scb
->event
);
1298 atalk_notify_sel(gref
);
1301 case ASPSTATE_WaitingForGetStatusRsp
:
1303 scb
->state
= ASPSTATE_Idle
;
1304 mx
= gbuf_cont(mioc
);
1305 gbuf_cont(mioc
) = 0;
1306 mdata
= gbuf_cont(mx
);
1308 iocbp
->ioc_cmd
= ASPIOC_GetStatus
;
1309 iocbp
->ioc_count
= 0;
1310 iocbp
->ioc_rval
= mdata
? gbuf_msgsize(mdata
) : 0;
1312 atalk_putnext(gref
, mioc
);
1313 atalk_putnext(gref
, mdata
);
1316 case ASPSTATE_WaitingForOpenSessRsp
:
1318 scb
->state
= ASPSTATE_Idle
;
1319 mx
= gbuf_cont(mioc
);
1320 gbuf_cont(mioc
) = 0;
1321 if (gbuf_cont(mx
)) {
1322 gbuf_freem(gbuf_cont(mx
));
1325 iocbp
->ioc_cmd
= ASPIOC_OpenSession
;
1326 iocbp
->ioc_rval
= 0;
1327 iocbp
->ioc_count
= 0;
1328 atpBDS
= (struct atpBDS
*)gbuf_rptr(mx
);
1329 awp
= (asp_word_t
*)atpBDS
->bdsUserData
;
1332 asp_iocnak(gref
, mioc
, ECONNREFUSED
);
1334 scb
->rem_addr
.node
= scb
->rem_node
;
1335 scb
->rem_addr
.socket
= awp
->func
;
1336 /* bms: need to set the reply_socket for client side too.
1337 This makes ALO atten replies sent by the client work. */
1338 scb
->reply_socket
= scb
->rem_addr
.socket
;
1339 scb
->sess_id
= awp
->param1
;
1341 atalk_putnext(gref
, mioc
);
1342 asp_timout(asp_hangup
, scb
, scb
->session_timer
);
1343 asp_send_tickle(scb
);
1344 dPrintf(D_M_ASP
, D_L_INFO
,
1345 ("asp_ack_reply: CONNECT, loc=%d, rem=%x.%x.%d\n",
1346 scb
->loc_addr
.socket
,
1349 scb
->rem_addr
.socket
));
1353 case ASPSTATE_WaitingForCommandRsp
:
1354 case ASPSTATE_WaitingForWriteRsp
:
1355 case ASPSTATE_WaitingForWriteContinueRsp
:
1356 if (scb
->rem_addr
.node
)
1357 asp_untimout(asp_hangup
, scb
);
1358 NEXT_SEQ_NUM(scb
->snd_seq_num
);
1359 scb
->state
= ASPSTATE_Idle
;
1360 gbuf_set_type(mioc
, MSG_PROTO
);
1361 mx
= gbuf_cont(mioc
);
1362 mdata
= gbuf_cont(mx
);
1363 gbuf_cont(mioc
) = mdata
;
1364 atpBDS
= (struct atpBDS
*)gbuf_rptr(mx
);
1365 cmdreply_ind
= (asp_cmdreply_ind_t
*)gbuf_rptr(mioc
);
1366 cmdreply_ind
->Primitive
= ASPFUNC_CmdReply
;
1367 cmdreply_ind
->CmdResult
= ntohl(*(int *)atpBDS
->bdsUserData
);
1368 gbuf_wset(mioc
,sizeof(asp_cmdreply_ind_t
));
1370 asp_putnext(scb
->gref
, mioc
);
1373 case ASPSTATE_WaitingForCloseSessRsp
:
1375 scb
->state
= ASPSTATE_Close
;
1376 scb
->rem_addr
.node
= 0;
1377 iocbp
->ioc_cmd
= ASPIOC_CloseSession
;
1378 iocbp
->ioc_rval
= 0;
1379 if (gbuf_cont(mioc
)) {
1380 gbuf_freem(gbuf_cont(mioc
));
1381 gbuf_cont(mioc
) = 0;
1383 atalk_putnext(scb
->gref
, mioc
);
1384 atp_cancel_req(scb
->gref
, (unsigned int)scb
->tickle_tid
);
1385 scb
->tickle_tid
= 0;
1389 dPrintf(D_M_ASP
, D_L_WARNING
,
1390 (" : UNKNOWN state, state=%s\n",
1391 aspStateStr(scb
->state
)));
1397 if (scb
->next_scb
) {
1399 * find the responsible scb
1401 scb
= (asp_scb_t
*)iocbp
->ioc_cr
;
1402 if ((scb
== 0) || (scb
->magic_num
!= 222)) {
1403 dPrintf(D_M_ASP
, D_L_ERROR
,
1404 ("asp_ack_reply: CAN'T find scb 2\n"));
1410 switch (scb
->state
) {
1411 case ASPSTATE_Close
:
1412 scb
->rem_addr
.node
= 0;
1421 if (scb
->rem_addr
.node
)
1422 asp_timout(asp_hangup
, scb
, scb
->session_timer
);
1423 } /* asp_ack_reply */
1429 asp_nak_reply(gref
, mioc
)
1430 register gref_t
*gref
;
1431 register gbuf_t
*mioc
;
1433 register asp_scb_t
*scb
;
1434 register ioc_t
*iocbp
;
1436 iocbp
= (ioc_t
*)gbuf_rptr(mioc
);
1438 if (iocbp
->ioc_cmd
== AT_ATP_ISSUE_REQUEST_TICKLE
) {
1440 * no tickle, close session
1442 scb
= (asp_scb_t
*)iocbp
->ioc_cr
;
1445 dPrintf(D_M_ASP
, D_L_WARNING
,
1446 ("tickle_nak: loc=%d, rem=%x.%x.%d, state=%s\n",
1447 scb
->loc_addr
.socket
,
1450 scb
->rem_addr
.socket
,
1451 aspStateStr(scb
->state
)));
1456 scb
= (asp_scb_t
*)gref
->info
;
1462 if (iocbp
->ioc_cmd
== AT_ATP_REQUEST_COMPLETE
) {
1463 if (scb
->next_scb
) {
1465 * find the responsible scb
1467 scb
= (asp_scb_t
*)iocbp
->ioc_private
;
1468 if ((scb
== 0) || (scb
->magic_num
!= 222)) {
1469 dPrintf(D_M_ASP
, D_L_ERROR
,
1470 ("asp_nak_reply: CAN'T find scb 1\n"));
1475 dPrintf(D_M_ASP
, D_L_WARNING
,
1476 ("asp_nak_reply: RSP, loc=%d, rem=%x.%x.%d, state=%s\n",
1477 scb
->loc_addr
.socket
,
1480 scb
->rem_addr
.socket
,
1481 aspStateStr(scb
->state
)));
1483 switch (scb
->state
) {
1484 case ASPSTATE_WaitingForGetStatusRsp
:
1485 iocbp
->ioc_cmd
= ASPIOC_GetStatus
;
1488 case ASPSTATE_WaitingForOpenSessRsp
:
1489 iocbp
->ioc_cmd
= ASPIOC_OpenSession
;
1492 case ASPSTATE_WaitingForCommandRsp
:
1493 case ASPSTATE_WaitingForWriteRsp
:
1494 case ASPSTATE_WaitingForWriteContinueRsp
:
1495 scb
->state
= ASPSTATE_Idle
;
1497 /* last remaining use of MSG_ERROR */
1498 gbuf_set_type(mioc
, MSG_ERROR
);
1499 *gbuf_rptr(mioc
) = (u_char
)EPROTOTYPE
;
1501 if (gbuf_cont(mioc
)) {
1502 gbuf_freem(gbuf_cont(mioc
));
1503 gbuf_cont(mioc
) = 0;
1506 asp_putnext(scb
->gref
, mioc
);
1509 case ASPSTATE_WaitingForCloseSessRsp
:
1510 scb
->state
= ASPSTATE_Close
;
1512 case ASPSTATE_Close
: /* new for PR-2296832 */
1513 scb
->rem_addr
.node
= 0;
1514 iocbp
->ioc_cmd
= ASPIOC_CloseSession
;
1515 iocbp
->ioc_rval
= 0;
1516 if (gbuf_cont(mioc
)) {
1517 gbuf_freem(gbuf_cont(mioc
));
1518 gbuf_cont(mioc
) = 0;
1520 gbuf_set_type(mioc
, MSG_IOCACK
);
1521 atalk_putnext(scb
->gref
, mioc
);
1528 scb
->state
= ASPSTATE_Idle
;
1529 atalk_putnext(gref
, mioc
);
1533 if (scb
->next_scb
) {
1535 * find the responsible scb
1537 scb
= (asp_scb_t
*)iocbp
->ioc_cr
;
1538 if ((scb
== 0) || (scb
->magic_num
!= 222)) {
1539 dPrintf(D_M_ASP
, D_L_ERROR
,
1540 ("asp_nak_reply: CAN'T find scb 2\n"));
1546 switch (scb
->state
) {
1547 case ASPSTATE_Close
:
1548 scb
->rem_addr
.node
= 0;
1554 } /* asp_nak_reply */
1557 * delete scb from the use list
1560 asp_dequeue_scb(scb
)
1564 if (scb
== scb_used_list
) {
1565 if ((scb_used_list
= scb
->next_scb
) != 0)
1566 scb
->next_scb
->prev_scb
= 0;
1568 if ((scb
->prev_scb
->next_scb
= scb
->next_scb
) != 0)
1569 scb
->next_scb
->prev_scb
= scb
->prev_scb
;
1579 StaticProc asp_scb_t
*
1580 asp_find_scb(sock_num
, rem_addr
)
1581 unsigned char sock_num
;
1582 at_inet_t
*rem_addr
;
1585 asp_scb_t
*alt_scb
= 0;
1587 for (scb
= asp_scbQ
[sock_num
]; scb
; scb
= scb
->next_scb
) {
1588 if ((scb
->rem_addr
.net
== rem_addr
->net
)
1589 && (scb
->rem_addr
.node
== rem_addr
->node
)) {
1590 if ((scb
->rem_addr
.socket
== rem_addr
->socket
)
1591 || (scb
->rem_socket
== rem_addr
->socket
))
1593 else if (alt_scb
== 0)
1598 if ((scb
== 0) && ((scb
= alt_scb
) == 0)) {
1599 dPrintf(D_M_ASP
, D_L_ERROR
,
1600 ("asp_find_scb: CAN'T find scb, loc=%d, rem=%x.%x.%d\n",
1614 asp_timout(func
, scb
, seconds
)
1616 register asp_scb_t
*scb
;
1620 register asp_scb_t
*curr_scb
, *prev_scb
;
1625 scb
->tmo_func
= func
;
1626 scb
->tmo_delta
= (seconds
>>SESS_TMO_RES
);
1627 scb
->tmo_cnt
= scb_tmo_cnt
;
1629 if (scb_tmo_list
== 0) {
1630 scb
->next_tmo
= scb
->prev_tmo
= 0;
1636 curr_scb
= scb_tmo_list
;
1640 sum
+= curr_scb
->tmo_delta
;
1641 if (sum
> scb
->tmo_delta
) {
1642 sum
-= curr_scb
->tmo_delta
;
1643 scb
->tmo_delta
-= sum
;
1644 curr_scb
->tmo_delta
-= scb
->tmo_delta
;
1647 prev_scb
= curr_scb
;
1648 if ((curr_scb
= curr_scb
->next_tmo
) == 0) {
1649 scb
->tmo_delta
-= sum
;
1655 scb
->prev_tmo
= prev_scb
;
1656 if ((scb
->next_tmo
= prev_scb
->next_tmo
) != 0)
1657 prev_scb
->next_tmo
->prev_tmo
= scb
;
1658 prev_scb
->next_tmo
= scb
;
1661 scb
->next_tmo
= scb_tmo_list
;
1662 scb_tmo_list
->prev_tmo
= scb
;
1671 asp_untimout(func
, scb
)
1673 register asp_scb_t
*scb
;
1676 if ((scb
->tmo_cnt
== scb_tmo_cnt
) || (scb
->tmo_func
== 0))
1679 if (scb_tmo_list
== scb
) {
1680 if ((scb_tmo_list
= scb
->next_tmo
) != 0) {
1681 scb_tmo_list
->prev_tmo
= 0;
1682 scb
->next_tmo
->tmo_delta
+= scb
->tmo_delta
;
1684 } else if (scb
->prev_tmo
) {
1685 if ((scb
->prev_tmo
->next_tmo
= scb
->next_tmo
) != 0) {
1686 scb
->next_tmo
->prev_tmo
= scb
->prev_tmo
;
1687 scb
->next_tmo
->tmo_delta
+= scb
->tmo_delta
;
1704 * set the state to Close
1706 scb
->state
= ASPSTATE_Close
;
1707 if (scb
->tickle_tid
) {
1708 atp_cancel_req(scb
->gref
, (unsigned int)scb
->tickle_tid
);
1709 scb
->tickle_tid
= 0;
1713 * notify upstream of the hangup
1715 if (scb
->rem_addr
.node
) {
1717 wakeup(&scb
->event
);
1719 atalk_notify_sel(scb
->gref
);
1724 asp_iocack(gref
, mioc
)
1728 if (gbuf_cont(mioc
))
1729 ((ioc_t
*)gbuf_rptr(mioc
))->ioc_count
= gbuf_msgsize(gbuf_cont(mioc
));
1731 ((ioc_t
*)gbuf_rptr(mioc
))->ioc_count
= 0;
1733 gbuf_set_type(mioc
, MSG_IOCACK
);
1734 atalk_putnext(gref
, mioc
);
1738 asp_iocnak(gref
, mioc
, err
)
1743 ((ioc_t
*)gbuf_rptr(mioc
))->ioc_count
= 0;
1746 ((ioc_t
*)gbuf_rptr(mioc
))->ioc_error
= err
;
1747 ((ioc_t
*)gbuf_rptr(mioc
))->ioc_rval
= -1;
1748 if (gbuf_cont(mioc
)) {
1749 gbuf_freem(gbuf_cont(mioc
));
1750 gbuf_cont(mioc
) = 0;
1753 gbuf_set_type(mioc
, MSG_IOCNAK
);
1754 atalk_putnext(gref
, mioc
);
1758 * the alloc scb routine
1760 StaticProc asp_scb_t
*
1765 asp_scb_t
*scb
, *scb_array
;
1767 if (scb_free_list
== 0) {
1768 if ((m
= gbuf_alloc(SCBS_PER_BLK
*sizeof(asp_scb_t
), PRI_MED
)) == 0)
1769 return (asp_scb_t
*)0;
1770 bzero((char *)gbuf_rptr(m
), SCBS_PER_BLK
*sizeof(asp_scb_t
));
1771 gbuf_cont(m
) = scb_resource_m
;
1773 scb_array
= (asp_scb_t
*)gbuf_rptr(m
);
1774 for (i
=0; i
< SCBS_PER_BLK
-1; i
++)
1775 scb_array
[i
].next_scb
= (asp_scb_t
*)&scb_array
[i
+1];
1776 scb_array
[i
].next_scb
= 0;
1777 scb_free_list
= (asp_scb_t
*)&scb_array
[0];
1780 scb
= scb_free_list
;
1781 scb_free_list
= scb
->next_scb
;
1782 ATEVENTINIT(scb
->event
);
1783 ATEVENTINIT(scb
->delay_event
);
1789 * the free scb routine
1796 bzero((char *)scb
, sizeof(asp_scb_t
));
1797 scb
->next_scb
= scb_free_list
;
1798 scb_free_list
= scb
;
1802 * routine to pass up receive data
1805 asp_putnext(gref
, mproto
)
1812 scb
= (asp_scb_t
*)gref
->info
;
1815 * queue the message.
1817 gbuf_next(mproto
) = 0;
1818 if ((m
= scb
->sess_ioc
) == 0)
1819 scb
->sess_ioc
= mproto
;
1821 while (gbuf_next(m
))
1823 gbuf_next(m
) = mproto
;
1826 if (scb
->rcv_cnt
>= MAX_RCV_CNT
)
1830 wakeup(&scb
->event
);
1831 else if (mproto
== scb
->sess_ioc
)
1832 atalk_notify_sel(gref
);
1837 * The following two routines are direct entries from system
1838 * calls to allow fast sending and recving of ASP data.
1841 /* in ASPputmsg we expect:
1847 ASPFUNC_WriteContinue
1849 bms: Make this callable from the kernel.
1850 If mreq != NULL, then must be called from kernel space and the following apply:
1851 1) *mreq is data to be sent already in mbuf chains.
1852 2) datptr->len = size of data
1855 int ASPputmsg(gref_t
*gref
, strbuf_t
*ctlptr
, strbuf_t
*datptr
, gbuf_t
*mreq
, int flags
, int *errp
)
1857 int i
, err
, len
, offset
, remain
, size
, copy_len
;
1858 gbuf_t
*mioc
, *mdata
, *mx
, *m0
;
1863 int nbds
, result
, msize
, Primitive
;
1864 unsigned char *wptr
;
1865 struct atp_set_default
*sd
;
1868 struct atpBDS
*atpBDS
;
1870 union asp_primitives
*primitives
;
1874 if ((scb
= (asp_scb_t
*)gref
->info
) == 0) {
1875 dPrintf(D_M_ASP
, D_L_ERROR
,
1876 ("ASPputmsg: stale handle=0x%x, pid=%d\n",
1877 (u_int
) gref
, gref
->pid
));
1883 if (scb
->state
== ASPSTATE_Close
)
1885 if (scb
->snd_stop
) {
1891 * copy in the control and data info
1894 /* being called from kernel space */
1895 bcopy (ctlptr
, &ctlbuf
, sizeof (strbuf_t
));
1896 bcopy (datptr
, &datbuf
, sizeof (strbuf_t
));
1898 /* being called from user space */
1899 if ((err
= copyin(CAST_USER_ADDR_T(ctlptr
), (caddr_t
)&ctlbuf
, sizeof(ctlbuf
))) != 0)
1901 if ((err
= copyin(CAST_USER_ADDR_T(datptr
), (caddr_t
)&datbuf
, sizeof(datbuf
))) != 0)
1906 * allocate buffer and copy in the control content
1908 if (!(mioc
= gbuf_alloc_wait(ctlbuf
.len
, TRUE
))) {
1909 /* error return should not be possible */
1913 gbuf_set_type(mioc
, MSG_IOCTL
); /* for later, in ATP */
1914 gbuf_wset(mioc
, ctlbuf
.len
);
1917 /* being called from kernel space */
1918 bcopy (ctlbuf
.buf
, gbuf_rptr(mioc
), ctlbuf
.len
);
1920 /* being called from user space */
1921 if ((err
= copyin(CAST_USER_ADDR_T(ctlbuf
.buf
), (caddr_t
)gbuf_rptr(mioc
), ctlbuf
.len
)) != 0) {
1927 iocbp
= (ioc_t
*)gbuf_rptr(mioc
);
1928 primitives
= (union asp_primitives
*)gbuf_rptr(mioc
);
1929 Primitive
= primitives
->Primitive
;
1930 dPrintf(D_M_ASP
, D_L_INFO
,
1931 ("ASPputmsg: %s\n", aspCmdStr(Primitive
)));
1934 * copy in the data content into multiple mbuf clusters if
1935 * required. ATP now expects reply data to be placed in
1936 * standard clusters, not the large external clusters that
1937 * were used previously.
1940 /* set offset for use by some commands */
1941 offset
= (Primitive
== ASPFUNC_CmdReply
) ? 0 : aspCMDsize
;
1944 /* The data from the in-kernel call for use by AFP is passed
1945 * in as one large external cluster. This needs to be copied
1946 * to a chain of standard clusters.
1948 remain
= gbuf_len(mreq
);
1949 dataptr
= mtod(mreq
, caddr_t
);
1951 /* copyin from user space */
1952 remain
= datbuf
.len
;
1953 dataptr
= (caddr_t
)datbuf
.buf
;
1956 /* allocate first buffer */
1957 if (!(mdata
= gbuf_alloc_wait((remain
+ offset
> MCLBYTES
? MCLBYTES
: remain
+ offset
), TRUE
))) {
1958 /* error return should not be possible */
1963 gbuf_wset(mdata
, 0); /* init length to zero */
1964 gbuf_cont(mioc
) = mdata
;
1967 if (remain
+ offset
> MCLBYTES
)
1968 copy_len
= MCLBYTES
- offset
;
1973 bcopy (dataptr
, (gbuf_rptr(mdata
) + offset
), copy_len
);
1974 else if ((err
= copyin(CAST_USER_ADDR_T(dataptr
), (caddr_t
)(gbuf_rptr(mdata
) + offset
), copy_len
)) != 0) {
1978 gbuf_wset(mdata
, (copy_len
+ offset
));
1979 size
+= copy_len
+ offset
;
1980 dataptr
+= copy_len
;
1983 /* allocate the next mbuf */
1984 if ((gbuf_cont(mdata
) = m_get((M_WAIT
), MSG_DATA
)) == 0) {
1989 mdata
= gbuf_cont(mdata
);
1990 MCLGET(mdata
, M_WAIT
);
1991 if (!(mdata
->m_flags
& M_EXT
)) {
1998 mdata
= gbuf_cont(mioc
); /* code further on down expects this to b e set */
1999 mdata
->m_pkthdr
.len
= size
; /* set packet hdr len */
2004 switch (Primitive
) {
2006 case ASPFUNC_Command
:
2008 case ASPFUNC_WriteContinue
:
2009 case ASPFUNC_Attention
:
2011 * build the command/write/write_continue request
2013 wptr
= gbuf_rptr(mdata
);
2014 atpBDS
= (struct atpBDS
*)wptr
;
2016 for (i
=0; i
< ATP_TRESP_MAX
; i
++) {
2017 *(unsigned long *)atpBDS
[i
].bdsBuffAddr
= 1;
2018 *(unsigned short *)atpBDS
[i
].bdsBuffSz
= ATP_DATA_SIZE
;
2020 sd
= (struct atp_set_default
*)wptr
;
2021 wptr
+= sizeof(struct atp_set_default
);
2022 sd
->def_retries
= (scb
->cmd_retry
.retries
== -1) ?
2023 ATP_INFINITE_RETRIES
: scb
->cmd_retry
.retries
;
2024 sd
->def_rate
= scb
->cmd_retry
.interval
*TICKS_PER_SEC
;
2025 sd
->def_BDSlen
= atpBDSsize
;
2026 ddp
= (at_ddp_t
*)wptr
;
2027 NET_ASSIGN(ddp
->src_net
, scb
->loc_addr
.net
);
2028 ddp
->src_node
= scb
->loc_addr
.node
;
2029 NET_ASSIGN(ddp
->dst_net
, scb
->rem_addr
.net
);
2030 ddp
->dst_node
= scb
->rem_addr
.node
;
2031 ddp
->dst_socket
= scb
->rem_addr
.socket
;
2032 UAS_ASSIGN(ddp
->checksum
, 0);
2033 atp
= ATP_ATP_HDR(wptr
);
2034 wptr
+= TOTAL_ATP_HDR_SIZE
;
2038 awp
= (asp_word_t
*)atp
->user_bytes
;
2039 awp
->func
= (unsigned char)Primitive
;
2040 awp
->param1
= scb
->sess_id
;
2041 awp
->param2
= htons(scb
->snd_seq_num
);
2042 iocbp
->ioc_private
= (void *)scb
;
2043 iocbp
->ioc_count
= gbuf_len(mdata
);
2044 iocbp
->ioc_rval
= 0;
2045 iocbp
->ioc_cmd
= AT_ATP_ISSUE_REQUEST_DEF
;
2048 * send the command/write/write_continue/attention request
2050 switch (awp
->func
) {
2051 case ASPFUNC_Command
:
2052 scb
->state
= ASPSTATE_WaitingForCommandRsp
;
2055 scb
->state
= ASPSTATE_WaitingForWriteRsp
;
2057 case ASPFUNC_WriteContinue
:
2058 scb
->state
= ASPSTATE_WaitingForWriteContinueRsp
;
2059 awp
->param2
= htons(scb
->wrt_seq_num
);
2061 case ASPFUNC_Attention
:
2062 scb
->state
= ASPSTATE_WaitingForCommandRsp
;
2067 awp
->param2
= htons(*(unsigned short *)gbuf_wptr(mdata
));
2070 dPrintf(D_M_ASP
,D_L_INFO
,
2071 ("ASPputmsg: %s, loc=%d, rem=%x.%x.%d\n",
2072 (awp
->func
== ASPFUNC_Command
? "CommandReq" :
2073 awp
->func
== ASPFUNC_Write
? "WriteReq" :
2074 awp
->func
== ASPFUNC_WriteContinue
? "WriteContinue" :
2075 "AttentionReq"),scb
->loc_addr
.socket
,
2076 NET_VALUE(ddp
->dst_net
),ddp
->dst_node
,ddp
->dst_socket
));
2077 atp_send_req(gref
, mioc
);
2080 case ASPFUNC_CmdReply
:
2082 if (scb
->req_msgq
) {
2084 scb
->req_msgq
= gbuf_next(mx
);
2086 asp_putnext(scb
->gref
, mx
);
2090 result
= primitives
->CmdReplyReq
.CmdResult
;
2091 tid
= primitives
->CmdReplyReq
.ReqRefNum
;
2093 /* Re-use the original mioc mbuf to send the response. */
2094 gbuf_rinc(mioc
,sizeof(void *));
2096 ddp
= (at_ddp_t
*)gbuf_wptr(mioc
);
2097 gbuf_winc(mioc
,DDP_X_HDR_SIZE
);
2098 atp
= (at_atp_t
*)gbuf_wptr(mioc
);
2099 gbuf_winc(mioc
,ATP_HDR_SIZE
);
2100 NET_ASSIGN(ddp
->src_net
, scb
->loc_addr
.net
);
2101 ddp
->src_node
= scb
->loc_addr
.node
;
2102 NET_ASSIGN(ddp
->dst_net
, scb
->rem_addr
.net
);
2103 ddp
->dst_node
= scb
->rem_addr
.node
;
2104 ddp
->dst_socket
= scb
->reply_socket
;
2105 ddp
->type
= DDP_ATP
;
2106 UAS_ASSIGN(ddp
->checksum
, 0);
2107 UAS_ASSIGN(atp
->tid
, htons(tid
));
2108 if (scb
->attn_flag
&& (tid
== scb
->attn_tid
)) {
2116 /* setup the atpBDS struct - only the length field is used,
2117 * except for the first one which contains the bds count in
2120 atpBDS
= (struct atpBDS
*)gbuf_wptr(mioc
);
2121 msize
= mdata
? gbuf_msgsize(mdata
) : 0;
2122 for (nbds
=0; (nbds
< ATP_TRESP_MAX
) && (msize
> 0); nbds
++) {
2123 len
= msize
< ATP_DATA_SIZE
? msize
: ATP_DATA_SIZE
;
2124 msize
-= ATP_DATA_SIZE
;
2125 *(long *)atpBDS
[nbds
].bdsUserData
= 0;
2126 UAL_ASSIGN(atpBDS
[nbds
].bdsBuffAddr
, 1);
2127 UAS_ASSIGN(atpBDS
[nbds
].bdsBuffSz
, len
);
2129 UAS_ASSIGN(atpBDS
[0].bdsDataSz
, nbds
);
2130 *(long *)atpBDS
[0].bdsUserData
= (long)result
;
2131 *(long *)atp
->user_bytes
= (long)result
;
2132 gbuf_winc(mioc
,atpBDSsize
);
2133 dPrintf(D_M_ASP
, D_L_INFO
,
2134 ("ASPputmsg: ATP CmdReplyReq, loc=%d, state=%s, msgsize = %d, result = %d, tid = %d\n",
2135 scb
->loc_addr
.socket
, aspStateStr(scb
->state
),
2136 (mdata
? gbuf_msgsize(mdata
) : 0), result
, tid
));
2137 atp_send_rsp(gref
, mioc
, TRUE
);
2141 /* Not an expected ASPFUNC */
2151 /* bms: make this callable from kernel. reply date is passed back as a mbuf chain in *mreply */
2152 int ASPgetmsg(gref_t
*gref
, strbuf_t
*ctlptr
, strbuf_t
*datptr
, gbuf_t
**mreply
, int *flags
, int *errp
)
2154 int err
, len
, sum
, rval
;
2155 gbuf_t
*mproto
, *mdata
;
2159 unsigned char get_wait
;
2161 if ((scb
= (asp_scb_t
*)gref
->info
) == 0) {
2162 dPrintf(D_M_ASP
, D_L_ERROR
,
2163 ("ASPgetmsg: stale handle=0x%x, pid=%d\n",
2164 (u_int
) gref
, gref
->pid
));
2170 if (scb
->state
== ASPSTATE_Close
)
2176 while ((mproto
= scb
->sess_ioc
) == 0) {
2178 lck_mtx_assert(atalk_mutex
, LCK_MTX_ASSERT_OWNED
);
2179 err
= msleep(&scb
->event
, atalk_mutex
, PSOCK
| PCATCH
, "aspgetmsg", 0);
2185 if (scb
->state
== ASPSTATE_Close
) {
2190 get_wait
= scb
->get_wait
;
2192 if ((ctlptr
== 0) && (datptr
== 0))
2194 scb
->sess_ioc
= gbuf_next(mproto
);
2195 mdata
= gbuf_cont(mproto
);
2197 /* last remaining use of MSG_ERROR */
2198 if (gbuf_type(mproto
) == MSG_ERROR
) {
2199 err
= (int)gbuf_rptr(mproto
)[0];
2204 * copy in the control and data info
2206 if (mreply
!= NULL
) {
2207 /* called from kernel space */
2208 bcopy (ctlptr
, &ctlbuf
, sizeof(ctlbuf
));
2209 bcopy (datptr
, &datbuf
, sizeof(datbuf
));
2211 /* called from user space */
2212 if ((err
= copyin(CAST_USER_ADDR_T(ctlptr
),
2213 (caddr_t
)&ctlbuf
, sizeof(ctlbuf
))) != 0)
2215 if ((err
= copyin(CAST_USER_ADDR_T(datptr
),
2216 (caddr_t
)&datbuf
, sizeof(datbuf
))) != 0)
2219 if ((datbuf
.maxlen
< 0) || (datbuf
.maxlen
< gbuf_msgsize(mdata
))) {
2220 gbuf_next(mproto
) = scb
->sess_ioc
;
2221 scb
->sess_ioc
= mproto
;
2225 if (get_wait
== 0) {
2227 * this is a hack to support the select() call.
2228 * we're not supposed to dequeue messages in the Streams
2229 * head's read queue this way; but there is no better way.
2231 if (scb
->sess_ioc
!= 0)
2232 atalk_notify_sel(gref
);
2237 * copy out the control content and info
2239 ctlbuf
.len
= gbuf_len(mproto
);
2241 if (mreply
!= NULL
) {
2242 /* called from kernel space */
2243 bcopy (gbuf_rptr(mproto
), ctlbuf
.buf
, ctlbuf
.len
);
2244 bcopy (&ctlbuf
, ctlptr
, sizeof(ctlbuf
));
2246 /* called from user space */
2247 if ((err
= copyout((caddr_t
)gbuf_rptr(mproto
),
2248 CAST_USER_ADDR_T(ctlbuf
.buf
), ctlbuf
.len
)) != 0)
2250 if ((err
= copyout((caddr_t
)&ctlbuf
,
2251 CAST_USER_ADDR_T(ctlptr
), sizeof(ctlbuf
))) != 0)
2256 * copy out the data content and info
2258 for (rval
= 0, sum
= 0; mdata
&& (rval
== 0); mdata
= gbuf_cont(mdata
))
2260 len
= gbuf_len(mdata
);
2262 if ((len
+ sum
) > datbuf
.maxlen
) {
2263 len
= datbuf
.maxlen
- sum
;
2267 if (mreply
== NULL
) {
2268 /* called from user space */
2269 if ((err
= copyout((caddr_t
)gbuf_rptr(mdata
), CAST_USER_ADDR_T(&datbuf
.buf
[sum
]), len
)) != 0)
2276 if (mreply
!= NULL
) {
2277 /* called from kernel space */
2278 bcopy (&datbuf
, datptr
, sizeof(datbuf
));
2280 /* called from user space */
2281 if ((err
= copyout((caddr_t
)&datbuf
, CAST_USER_ADDR_T(datptr
), sizeof(datbuf
))) != 0)
2285 if (mreply
!= NULL
) {
2286 /* called from kernel space */
2287 /* return the reply data in mbufs, so dont free them.
2288 Just free the proto info */
2289 mdata
= gbuf_cont(mproto
);
2291 gbuf_cont(mproto
) = NULL
;
2294 /* called from user space */
2307 gbuf_next(mproto
) = scb
->sess_ioc
;
2308 scb
->sess_ioc
= mproto
;