2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
26 * Copyright (c) 1995 Apple Computer, Inc.
29 * Created February 20, 1995 by Tuyen Nguyen
30 * Modified for MP, 1996 by Tuyen Nguyen
31 * Modified, March 17, 1997 by Tuyen Nguyen for MacOSX.
34 #include <sys/errno.h>
35 #include <sys/types.h>
36 #include <sys/param.h>
37 #include <machine/spl.h>
38 #include <sys/systm.h>
39 #include <sys/kernel.h>
41 #include <sys/filedesc.h>
42 #include <sys/fcntl.h>
44 #include <sys/ioctl.h>
45 #include <sys/malloc.h>
46 #include <sys/socket.h>
47 #include <sys/socketvar.h>
51 #include <netat/appletalk.h>
52 #include <netat/sysglue.h>
53 #include <netat/at_pcb.h>
54 #include <netat/atp.h>
55 #include <netat/ddp.h>
56 #include <netat/asp.h>
57 #include <netat/at_var.h>
58 #include <netat/debug.h>
61 #define CHK_LOOP(str) { \
62 if (loop_cnt++ > 100) { \
68 #define atpBDSsize (sizeof(struct atpBDS)*ATP_TRESP_MAX)
69 #define aspCMDsize (atpBDSsize+sizeof(struct atp_set_default)+TOTAL_ATP_HDR_SIZE)
70 #define SCBS_PER_BLK 16
71 #define TICKS_PER_SEC HZ
72 #define SESS_TMO_RES 2
73 #define DEF_SESS_TMO 120
74 #define NEXT_SEQ_NUM(x) (x = (x == 65535) ? 0 : (x + 1))
76 #define BAD_REMADDR(addr) \
77 ( (*(long *)&scb->rem_addr != *(long *)&addr) \
78 && ((scb->rem_addr.net != addr.net) \
79 || (scb->rem_addr.node != addr.node)) )
87 void asp_clock_funnel();
92 StaticProc asp_scb_t
*asp_find_scb();
93 StaticProc asp_scb_t
*asp_scb_alloc();
95 StaticProc
void asp_putnext();
96 StaticProc
void asp_iocack();
97 StaticProc
void asp_iocnak();
98 StaticProc
void asp_dequeue_scb();
99 StaticProc
void asp_scb_free();
100 StaticProc
void asp_timout();
101 StaticProc
void asp_untimout();
102 StaticProc
void asp_hangup();
103 StaticProc
void asp_send_tickle();
104 StaticProc
void asp_send_tickle_funnel();
105 StaticProc
void asp_accept();
106 StaticProc
int asp_send_req();
108 extern at_ifaddr_t
*ifID_home
;
109 extern int atp_pidM
[];
110 extern gref_t
*atp_inputQ
[];
111 gbuf_t
*scb_resource_m
= 0;
112 unsigned char asp_inpC
[256];
113 asp_scb_t
*asp_scbQ
[256];
115 static at_retry_t asp_def_retry
= {2, -1, 1};
116 static unsigned char scb_tmo_cnt
;
117 asp_scb_t
*scb_used_list
;
118 static asp_scb_t
*scb_tmo_list
;
119 asp_scb_t
*scb_free_list
;
120 atlock_t aspall_lock
, asptmo_lock
;
126 return (((asp_scb_t
*)gref
->info
)->sess_ioc
? 1 : 0);
136 bzero(asp_inpC
, sizeof(asp_inpC
));
137 bzero(asp_scbQ
, sizeof(asp_scbQ
));
141 * the open routine allocates a state structure
150 * if no asp structure available, return failure
152 if ((scb
= asp_scb_alloc()) == 0)
156 * initialize the gref data structure
158 gref
->info
= (void *)scb
;
159 gref
->readable
= asp_readable
;
162 * initialize the scb data structure
165 scb
->magic_num
= 222;
166 scb
->state
= ASPSTATE_Idle
;
167 scb
->pid
= gref
->pid
;
169 scb
->session_timer
= DEF_SESS_TMO
;
170 scb
->cmd_retry
= asp_def_retry
;
171 ATDISABLE(s
, aspall_lock
);
172 if ((scb
->next_scb
= scb_used_list
) != 0)
173 scb
->next_scb
->prev_scb
= scb
;
175 ATENABLE(s
, aspall_lock
);
180 dPrintf(D_M_ASP
, D_L_INFO
, ("asp_open: pid=%d\n", scb
->pid
));
185 * the close routine frees all the data structures
192 unsigned char sock_num
;
193 asp_scb_t
*scb
, *new_scb
;
196 scb
= (asp_scb_t
*)gref
->info
;
197 dPrintf(D_M_ASP
, D_L_INFO
, ("asp_close: loc=%d\n",
198 scb
->loc_addr
.socket
));
200 if (scb
->pid
&& scb
->sess_ioc
&& (scb
->dflag
!= 1)) {
202 * send the CloseSess response to peer
204 if (gbuf_type(scb
->sess_ioc
) != MSG_PROTO
) {
205 ATDISABLE(s
, scb
->lock
);
207 scb
->sess_ioc
= gbuf_next(m
);
208 ATENABLE(s
, scb
->lock
);
209 atp_send_rsp(scb
->gref
, m
, TRUE
);
213 if (scb
->atp_state
) {
214 sock_num
= scb
->loc_addr
.socket
;
215 ATDISABLE(s
, aspall_lock
);
216 if ((scb
->dflag
!= 1) && scb
->stat_msg
) {
217 untimeout(atp_retry_req
, scb
->stat_msg
);
218 gbuf_freem(scb
->stat_msg
);
221 if (asp_scbQ
[sock_num
]->next_scb
== 0) {
222 asp_scbQ
[sock_num
] = 0;
223 asp_inpC
[sock_num
] = 0;
224 ATENABLE(s
, aspall_lock
);
225 dPrintf(D_M_ASP
, D_L_INFO
,
226 (" : atp_close(), loc=%d\n", scb
->loc_addr
.socket
));
229 asp_inpC
[sock_num
]--;
230 if (scb
== asp_scbQ
[sock_num
]) {
231 new_scb
= scb
->next_scb
;
232 new_scb
->prev_scb
= 0;
233 asp_scbQ
[sock_num
] = new_scb
;
234 new_scb
->atp_state
->atp_gref
= new_scb
->gref
;
235 new_scb
->atp_state
->pid
= new_scb
->pid
;
236 atp_inputQ
[sock_num
] = new_scb
->gref
;
238 if ((scb
->prev_scb
->next_scb
= scb
->next_scb
) != 0)
239 scb
->next_scb
->prev_scb
= scb
->prev_scb
;
242 ATENABLE(s
, aspall_lock
);
245 asp_dequeue_scb(scb
);
248 * free all allocated blocks if any
250 ATDISABLE(s
, scb
->lock
);
252 gbuf_freem(scb
->stat_msg
);
256 gbuf_freel(scb
->sess_ioc
);
260 gbuf_freel(scb
->req_msgq
);
264 scb
->rem_addr
.node
= 0;
265 ATENABLE(s
, scb
->lock
);
271 asp_untimout(asp_hangup
, scb
);
272 untimeout(asp_send_tickle_funnel
, (void *)scb
); /* added for 2225395 */
275 * free the asp session control block
277 scb
->state
= ASPSTATE_Close
;
282 static char *aspStateStr(state
)
285 return ((state
==ASPSTATE_Close
)? "Close":
286 (state
==ASPSTATE_Idle
)? "Idle":
287 (state
==ASPSTATE_WaitingForGetStatusRsp
)? "GetStatusRsp":
288 (state
==ASPSTATE_WaitingForOpenSessRsp
)? "OpenSessRsp":
289 (state
==ASPSTATE_WaitingForCommandRsp
)? "CmdRsp":
290 (state
==ASPSTATE_WaitingForWriteContinue
)? "WriteCont":
291 (state
==ASPSTATE_WaitingForWriteRsp
)? "WriteRsp":
292 (state
==ASPSTATE_WaitingForWriteContinueRsp
)? "WriteContRsp":
293 (state
==ASPSTATE_WaitingForCloseSessRsp
)? "CloseSessRsp":
297 static char *aspCmdStr(aspCmd
)
300 return ((aspCmd
==ASPFUNC_CloseSess
)? "CloseSess":
301 (aspCmd
==ASPFUNC_Command
)? "Command":
302 (aspCmd
==ASPFUNC_GetStatus
)? "GetStatus":
303 (aspCmd
==ASPFUNC_OpenSess
)? "OpenSess":
304 (aspCmd
==ASPFUNC_Tickle
)? "Tickle":
305 (aspCmd
==ASPFUNC_Write
)? "Write":
306 (aspCmd
==ASPFUNC_WriteContinue
)? "WriteContinue":
307 (aspCmd
==ASPFUNC_Attention
)? "Attention":
308 (aspCmd
==ASPFUNC_CmdReply
)? "CmdReply": "unknown");
311 static char *aspIOCStr(aspIOC
)
315 (aspIOC
==ASPIOC_ClientBind
)? "ClientBind":
316 (aspIOC
==ASPIOC_CloseSession
)? "CloseSession":
317 (aspIOC
==ASPIOC_GetLocEntity
)? "GetLocEntity":
318 (aspIOC
==ASPIOC_GetRemEntity
)? "GetRemEntity":
319 (aspIOC
==ASPIOC_GetSession
)? "GetSession":
320 (aspIOC
==ASPIOC_GetStatus
)? "GetStatus":
321 (aspIOC
==ASPIOC_ListenerBind
)? "ListenerBind":
322 (aspIOC
==ASPIOC_OpenSession
)? "OpenSession":
323 (aspIOC
==ASPIOC_StatusBlock
)? "StatusBlock":
324 (aspIOC
==ASPIOC_SetPid
)? "SetPid":
325 (aspIOC
==ASPIOC_GetSessId
)? "GetSessId":
326 (aspIOC
==ASPIOC_EnableSelect
)? "EnableSelect":
327 (aspIOC
==ASPIOC_Look
)? "Look":
334 static char mbuf_str
[100];
339 "dat = %d, prot = %d, ioc = %d, err = %d, hu = %d, ack = %d, nak = %d, ctl = %d",
341 "dat = %d, prot = %d, ioc = %d, ctl = %d",
342 mbstat
.m_mtypes
[MSG_DATA
], mbstat
.m_mtypes
[MSG_PROTO
], mbstat
.m_mtypes
[MSG_IOCTL
],
344 mbstat.m_mtypes[MSG_ERROR], mbstat.m_mtypes[MSG_HANGUP], mbstat.m_mtypes[MSG_IOCACK],
345 mbstat.m_mtypes[MSG_IOCNAK],
347 mbstat
.m_mtypes
[MSG_CTL
]);
348 return(&mbuf_str
[0]);
351 void trace_beg(str
, m
)
356 gbuf_t
*mdata
, *mchain
;
359 for (i
= 0, j
= 0, mdata
= m
, mchain
= m
; mdata
; i
++) {
360 mdata
= gbuf_cont(mdata
);
361 if (!mdata
&& mchain
) {
362 mdata
= gbuf_next(mchain
);
367 dPrintf(D_M_ASP
, D_L_TRACE
,
368 ("%s: %s, m# = %d, c# = %d\n", str
, mbuf_totals(), i
, j
));
374 dPrintf(D_M_ASP
, D_L_TRACE
,
375 (" %s: %s\n", str
, mbuf_totals()));
382 int asp_wput(gref
, m
)
387 unsigned char sockSav
, sock_num
;
388 gbuf_t
*mioc
, *mdata
;
390 asp_scb_t
*scb
, *server_scb
, *curr_scb
;
393 union asp_primitives
*primitives
;
394 asp_status_cmd_t
*status_cmd
;
395 asp_open_cmd_t
*open_cmd
;
398 scb
= (asp_scb_t
*)gref
->info
;
399 if (scb
->dflag
== 0) {
404 if (gbuf_type(m
) != MSG_IOCTL
) {
405 dPrintf(D_M_ASP
, D_L_WARNING
,
406 ("asp_wput: UNKNOWN message, type=%d\n",
413 iocbp
= (ioc_t
*)gbuf_rptr(mioc
);
415 dPrintf(D_M_ASP_LOW
, D_L_INFO
,
416 ("asp_wput: %s, loc=%d, state=%s\n",
417 aspIOCStr(iocbp
->ioc_cmd
), scb
->loc_addr
.socket
,
418 aspStateStr(scb
->state
)));
420 switch (iocbp
->ioc_cmd
) {
421 case ASPIOC_CloseSession
:
422 if ((scb
->state
== ASPSTATE_Close
) || (scb
->rem_addr
.node
== 0))
427 aw
.func
= ASPFUNC_CloseSess
;
428 aw
.param1
= scb
->sess_id
;
430 iocbp
->ioc_private
= (void *)scb
;
431 scb
->ioc_wait
= (unsigned char)(iocbp
->ioc_cmd
& 0xff);
432 iocbp
->ioc_cmd
= AT_ATP_ISSUE_REQUEST
;
433 asp_send_req(gref
, mioc
, &scb
->rem_addr
, &Retry
, &aw
,
434 0, ASPSTATE_WaitingForCloseSessRsp
, 0x01);
437 case ASPIOC_ClientBind
:
439 * open an ATP channel
441 if ((err
= atp_open(gref
, 0)) != 0) {
442 asp_iocnak(gref
, mioc
, err
);
445 scb
->atp_state
= (atp_state_t
*)gref
->info
;
446 scb
->atp_state
->pid
= scb
->pid
;
448 * bind to any available socket
451 sockSav
= scb
->dflag
;
452 if ((sock_num
= (at_socket
)atp_bind(gref
, 0, &sockSav
)) == 0) {
453 scb
->atp_state
= (atp_state_t
*)0;
455 gref
->info
= (void *)scb
;
456 asp_iocnak(gref
, mioc
, EINVAL
);
459 gref
->info
= (void *)scb
;
460 asp_dequeue_scb(scb
);
461 scb
->atp_state
->dflag
= scb
->dflag
;
462 scb
->loc_addr
.socket
= sock_num
;
463 asp_scbQ
[sock_num
] = scb
;
464 asp_inpC
[sock_num
]++;
465 atp_pidM
[sock_num
] = 0;
468 case ASPIOC_ListenerBind
:
470 * open an ATP channel
472 if ((err
= atp_open(gref
, 0)) != 0) {
473 asp_iocnak(gref
, mioc
, err
);
476 scb
->atp_state
= (atp_state_t
*)gref
->info
;
477 scb
->atp_state
->pid
= scb
->pid
;
479 * bind to any available socket
481 if ((sock_num
= (at_socket
)atp_bind(gref
, 0, 0)) == 0) {
482 scb
->atp_state
= (atp_state_t
*)0;
484 gref
->info
= (void *)scb
;
485 asp_iocnak(gref
, mioc
, EINVAL
);
488 gref
->info
= (void *)scb
;
489 asp_dequeue_scb(scb
);
490 scb
->atp_state
->dflag
= scb
->dflag
;
491 scb
->loc_addr
.socket
= sock_num
;
492 asp_scbQ
[sock_num
] = scb
;
493 asp_inpC
[sock_num
]++;
495 *(at_inet_t
*)gbuf_rptr(gbuf_cont(mioc
)) = scb
->loc_addr
;
498 case ASPIOC_GetLocEntity
:
499 if ((gbuf_cont(mioc
) == 0) || (scb
->atp_state
== 0)) {
500 asp_iocnak(gref
, mioc
, EPROTO
);
503 *(at_inet_t
*)gbuf_rptr(gbuf_cont(mioc
)) = scb
->loc_addr
;
506 case ASPIOC_GetRemEntity
:
507 if ((gbuf_cont(mioc
) == 0) || (scb
->atp_state
== 0)) {
508 asp_iocnak(gref
, mioc
, EPROTO
);
511 *(at_inet_t
*)gbuf_rptr(gbuf_cont(mioc
)) = scb
->rem_addr
;
514 case ASPIOC_GetSession
:
515 if ((mdata
= gbuf_cont(mioc
)) == 0) {
516 asp_iocnak(gref
, mioc
, EPROTO
);
519 addr
= (at_inet_t
*)gbuf_rptr(mdata
);
520 scb
->tickle_interval
= (unsigned short)addr
->node
;
521 scb
->session_timer
= addr
->net
;
522 server_scb
= asp_scbQ
[addr
->socket
];
523 /*### LD 10/28/97: changed to make sure we're not accessing a null server_scb */
524 if (server_scb
== 0) {
525 asp_iocnak(gref
, mioc
, EPROTO
);
528 if (server_scb
->sess_ioc
== 0) {
529 asp_iocnak(gref
, mioc
, EPROTO
);
534 * open an ATP channel
536 if ((err
= atp_open(gref
, 0)) != 0) {
537 gref
->info
= (void *)scb
;
538 asp_iocnak(gref
, mioc
, err
);
541 scb
->atp_state
= (atp_state_t
*)gref
->info
;
542 scb
->atp_state
->pid
= scb
->pid
;
544 * bind to any available socket
547 sockSav
= scb
->dflag
;
548 if ((sock_num
= (at_socket
)atp_bind(gref
, 0, &sockSav
)) == 0) {
550 asp_dequeue_scb(scb
);
551 ATDISABLE(s
, aspall_lock
);
553 scb
->loc_addr
.socket
= sock_num
;
554 for (curr_scb
= asp_scbQ
[sock_num
];
555 curr_scb
->next_scb
; curr_scb
= curr_scb
->next_scb
) ;
556 scb
->prev_scb
= curr_scb
;
557 curr_scb
->next_scb
= scb
;
558 scb
->atp_state
= curr_scb
->atp_state
;
559 ATENABLE(s
, aspall_lock
);
561 asp_dequeue_scb(scb
);
562 ATDISABLE(s
, aspall_lock
);
563 scb
->loc_addr
.socket
= sock_num
;
564 asp_scbQ
[sock_num
] = scb
;
565 scb
->atp_state
->dflag
= scb
->dflag
;
566 ATENABLE(s
, aspall_lock
);
568 gref
->info
= (void *)scb
;
569 asp_inpC
[sock_num
]++;
571 asp_accept(server_scb
, scb
, mdata
);
574 case ASPIOC_GetStatus
:
575 if ((mdata
= gbuf_cont(mioc
)) == 0) {
576 asp_iocnak(gref
, mioc
, EINVAL
);
580 status_cmd
= (asp_status_cmd_t
*)gbuf_rptr(mdata
);
581 aw
.func
= ASPFUNC_GetStatus
;
584 scb
->ioc_wait
= (unsigned char)(iocbp
->ioc_cmd
& 0xff);
585 iocbp
->ioc_cmd
= AT_ATP_ISSUE_REQUEST_DEF
;
586 /* bms: make sure this is an ALO request */
587 asp_send_req(gref
, mioc
, &status_cmd
->SLSEntityIdentifier
,
588 &status_cmd
->Retry
, &aw
, 0, ASPSTATE_WaitingForGetStatusRsp
, 0xff);
592 case ASPIOC_OpenSession
:
593 if ((mdata
= gbuf_cont(mioc
)) == 0) {
594 asp_iocnak(gref
, mioc
, EINVAL
);
598 open_cmd
= (asp_open_cmd_t
*)gbuf_rptr(mdata
);
599 scb
->svc_addr
= open_cmd
->SLSEntityIdentifier
;
600 scb
->rem_addr
= scb
->svc_addr
;
601 scb
->rem_node
= scb
->rem_addr
.node
;
602 scb
->rem_addr
.node
= 0;
603 scb
->tickle_interval
= open_cmd
->TickleInterval
;
604 scb
->session_timer
= open_cmd
->SessionTimer
;
605 aw
.func
= ASPFUNC_OpenSess
;
606 aw
.param1
= scb
->loc_addr
.socket
;
607 aw
.param2
= ASP_Version
;
608 scb
->ioc_wait
= (unsigned char)(iocbp
->ioc_cmd
& 0xff);
609 iocbp
->ioc_cmd
= AT_ATP_ISSUE_REQUEST_DEF
;
610 asp_send_req(gref
, mioc
, &open_cmd
->SLSEntityIdentifier
,
611 &open_cmd
->Retry
, &aw
, 1, ASPSTATE_WaitingForOpenSessRsp
, 0x01);
615 case ASPIOC_StatusBlock
:
617 * save the server status block
620 gbuf_freem(scb
->stat_msg
);
621 scb
->stat_msg
= gbuf_cont(mioc
);
625 /* *** Does scb->pid get used in a packet header,
626 and if so is it in ASP, or in ATP?
627 If not, do we need this call for anything?
628 (cap does currently use it in _ANS code.)
631 if (gbuf_cont(mioc
) == 0) {
632 asp_iocnak(gref
, mioc
, EINVAL
);
635 scb
->pid
= *(int *)gbuf_rptr(gbuf_cont(mioc
));
638 case ASPIOC_GetSessId
:
639 if (gbuf_cont(mioc
) == 0) {
640 asp_iocnak(gref
, mioc
, EINVAL
);
643 *(gref_t
**)gbuf_rptr(gbuf_cont(mioc
)) = gref
;
647 if (gbuf_cont(mioc
) == 0) {
648 asp_iocnak(gref
, mioc
, EINVAL
);
652 primitives
= (union asp_primitives
*)gbuf_rptr(scb
->sess_ioc
);
653 if (primitives
->Primitive
== ASPFUNC_CmdReply
)
654 *(int *)gbuf_rptr(gbuf_cont(mioc
)) = 0;
656 *(int *)gbuf_rptr(gbuf_cont(mioc
)) = 1;
658 *(int *)gbuf_rptr(gbuf_cont(mioc
)) = -1;
661 case DDP_IOC_GET_CFG
:
663 struct atp_state
*atp
= (struct atp_state
*)gref
->info
;
667 if (gbuf_cont(mioc
) == 0) {
668 asp_iocnak(gref
, mioc
, EINVAL
);
671 /* *** borrowed from ddp_proto.c to handle DDP_IOC_GET_CFG
673 scb
->state
= ASPSTATE_Idle
;
675 /* *** was ddp_get_cfg() *** */
677 (ddp_addr_t
*)gbuf_rptr(gbuf_cont(mioc
));
678 cfgp
->inet
.net
= ifID_home
->ifThisNode
.s_net
;
679 cfgp
->inet
.node
= ifID_home
->ifThisNode
.s_node
;
680 cfgp
->inet
.socket
= atp
->atp_socket_no
;
681 cfgp
->ddptype
= DDP_ATP
;
683 gbuf_wset(gbuf_cont(mioc
), sizeof(at_inet_t
));
688 asp_iocnak(gref
, mioc
, EINVAL
);
692 asp_iocack(gref
, mioc
);
697 * send request routine
700 asp_send_req(gref
, mioc
, dest
, retry
, awp
, xo
, state
, bitmap
)
708 unsigned char bitmap
;
713 struct atp_set_default
*sd
;
716 struct atpBDS
*atpBDS
;
717 asp_scb_t
*scb
= (asp_scb_t
*)gref
->info
;
720 * allocate an ATP buffer for the request
722 if ((gbuf_cont(mioc
) = gbuf_alloc(aspCMDsize
, PRI_MED
)) == 0) {
723 if (awp
->func
== ASPFUNC_Tickle
)
726 asp_iocnak(gref
, mioc
, ENOBUFS
);
727 dPrintf(D_M_ASP
, D_L_WARNING
,
728 ("asp_send_req: ENOBUFS, loc=%d\n", scb
->loc_addr
.socket
));
732 mdata
= gbuf_cont(mioc
);
733 iocbp
= (ioc_t
*)gbuf_rptr(mioc
);
738 atpBDS
= (struct atpBDS
*)gbuf_rptr(mdata
);
739 gbuf_wset(mdata
,atpBDSsize
);
740 for (i
=0; i
< ATP_TRESP_MAX
; i
++) {
741 *(unsigned long *)atpBDS
[i
].bdsBuffAddr
= 1;
742 *(unsigned short *)atpBDS
[i
].bdsBuffSz
= ATP_DATA_SIZE
;
744 sd
= (struct atp_set_default
*)gbuf_wptr(mdata
);
745 gbuf_winc(mdata
,sizeof(struct atp_set_default
));
746 sd
->def_retries
= (retry
->retries
== -1) ?
747 ATP_INFINITE_RETRIES
: retry
->retries
;
748 sd
->def_rate
= retry
->interval
*TICKS_PER_SEC
;
749 sd
->def_BDSlen
= atpBDSsize
;
750 ddp
= (at_ddp_t
*)gbuf_wptr(mdata
);
751 NET_ASSIGN(ddp
->src_net
, scb
->loc_addr
.net
);
752 ddp
->src_node
= scb
->loc_addr
.node
;
753 NET_ASSIGN(ddp
->dst_net
, dest
->net
);
754 ddp
->dst_node
= dest
->node
;
755 ddp
->dst_socket
= dest
->socket
;
756 UAS_ASSIGN(ddp
->checksum
, 0);
757 atp
= ATP_ATP_HDR(gbuf_wptr(mdata
));
760 atp
->bitmap
= bitmap
;
761 gbuf_winc(mdata
,TOTAL_ATP_HDR_SIZE
);
762 *(asp_word_t
*)atp
->user_bytes
= *awp
;
763 iocbp
->ioc_count
= gbuf_len(mdata
);
770 dPrintf(D_M_ASP
, D_L_INFO
,
771 ("asp_send_req: %s, loc=%d, rem= %d, len=%d, state=%s\n",
772 aspCmdStr(awp
->func
),
773 scb
->loc_addr
.socket
, ddp
->dst_socket
, iocbp
->ioc_count
,
774 aspStateStr(scb
->state
)));
776 atp_send_req(gref
, mioc
);
781 * send tickle routine - funnelled version
784 asp_send_tickle_funnel(scb
)
787 thread_funnel_set(network_flock
, TRUE
);
788 asp_send_tickle(scb
);
789 thread_funnel_set(network_flock
, FALSE
);
794 * send tickle routine
807 * make sure the connection is still there
809 if (scb
->rem_addr
.node
== 0) {
813 if ((mioc
= gbuf_alloc(sizeof(ioc_t
), PRI_HI
)) == 0) {
814 dPrintf(D_M_ASP
, D_L_WARNING
,
815 ("asp_send_tickle: ENOBUFS 0, loc=%d, rem=%d\n",
816 scb
->loc_addr
.socket
,scb
->rem_addr
.socket
));
817 timeout(asp_send_tickle_funnel
, (void *)scb
, 10);
820 gbuf_wset(mioc
,sizeof(ioc_t
));
821 gbuf_set_type(mioc
, MSG_IOCTL
);
823 dest
= scb
->svc_addr
.node
?
824 (at_inet_t
*)&scb
->svc_addr
: (at_inet_t
*)&scb
->rem_addr
;
825 retry
.interval
= scb
->tickle_interval
;
828 aw
.func
= ASPFUNC_Tickle
;
829 aw
.param1
= scb
->sess_id
;
831 ((ioc_t
*)gbuf_rptr(mioc
))->ioc_cr
= (void *)scb
;
832 ((ioc_t
*)gbuf_rptr(mioc
))->ioc_cmd
= AT_ATP_ISSUE_REQUEST_TICKLE
;
834 if (asp_send_req(scb
->gref
, mioc
, dest
, &retry
, &aw
, 0, scb
->state
, 0)) {
835 dPrintf(D_M_ASP
, D_L_WARNING
,
836 ("asp_send_tickle: ENOBUFS 1, loc=%d, rem=%d\n",
837 scb
->loc_addr
.socket
,scb
->rem_addr
.socket
));
839 timeout(asp_send_tickle_funnel
, (void *)scb
, 10);
845 * accept connection routine
848 asp_accept(scb
, sess_scb
, m
)
860 mdata
= scb
->sess_ioc
;
861 ddp
= (at_ddp_t
*)gbuf_rptr(mdata
);
862 atp
= (at_atp_t
*)(gbuf_rptr(mdata
) + DDP_X_HDR_SIZE
);
863 rem_addr
.net
= NET_VALUE(ddp
->src_net
);
864 rem_addr
.node
= ddp
->src_node
;
865 rem_addr
.socket
= ddp
->src_socket
;
866 awp
= (asp_word_t
*)atp
->user_bytes
;
868 sess_scb
->loc_addr
.net
= NET_VALUE(ddp
->dst_net
);
869 sess_scb
->loc_addr
.node
= ddp
->dst_node
;
870 NET_ASSIGN(ddp
->src_net
, sess_scb
->loc_addr
.net
);
871 ddp
->src_node
= sess_scb
->loc_addr
.node
;
872 NET_ASSIGN(ddp
->dst_net
, rem_addr
.net
);
873 ddp
->dst_node
= rem_addr
.node
;
874 ddp
->dst_socket
= rem_addr
.socket
;
876 sess_scb
->sess_id
= sess_scb
->loc_addr
.socket
;
877 sess_scb
->rem_socket
= rem_addr
.socket
;
878 sess_scb
->rem_addr
= rem_addr
;
879 sess_scb
->rem_addr
.socket
= awp
->param1
;
880 sess_scb
->reply_socket
= sess_scb
->rem_addr
.socket
;
881 awp
->func
= sess_scb
->loc_addr
.socket
;
882 awp
->param1
= sess_scb
->sess_id
;
885 ATDISABLE(s
, scb
->lock
);
886 scb
->sess_ioc
= gbuf_next(mdata
);
887 ATENABLE(s
, scb
->lock
);
888 gbuf_next(mdata
) = 0;
889 asp_timout(asp_hangup
, sess_scb
, sess_scb
->session_timer
);
890 atp_send_rsp(scb
->gref
, mdata
, TRUE
);
891 asp_send_tickle(sess_scb
);
892 dPrintf(D_M_ASP
, D_L_INFO
,
893 ("asp_accept: ACCEPT connect request, loc=%d, rem=%x.%x.%d\n",
894 sess_scb
->loc_addr
.socket
,
895 sess_scb
->rem_addr
.net
,
896 sess_scb
->rem_addr
.node
,sess_scb
->rem_addr
.socket
));
900 * timer routine - funneled version
902 void asp_clock_funnel(arg
)
905 thread_funnel_set(network_flock
, TRUE
);
907 thread_funnel_set(network_flock
, FALSE
);
920 ATDISABLE(s
, asptmo_lock
);
922 scb_tmo_list
->tmo_delta
--;
923 while (((scb
= scb_tmo_list
) != 0) && (scb_tmo_list
->tmo_delta
== 0)) {
924 if ((scb_tmo_list
= scb
->next_tmo
) != 0)
925 scb_tmo_list
->prev_tmo
= 0;
926 if ((tmo_func
= scb
->tmo_func
) != 0) {
928 ATENABLE(s
, asptmo_lock
);
930 ATDISABLE(s
, asptmo_lock
);
933 ATENABLE(s
, asptmo_lock
);
935 if (++scb_tmo_cnt
== 0) scb_tmo_cnt
++;
936 timeout(asp_clock_funnel
, (void *)arg
, (1<<SESS_TMO_RES
)*TICKS_PER_SEC
);
944 asp_ack_reply(gref
, mioc
)
945 register gref_t
*gref
;
946 register gbuf_t
*mioc
;
949 int len
, msize
, nbds
;
950 register gbuf_t
*mdata
, *m
, *mx
;
951 struct atpBDS
*atpBDS
;
954 register asp_scb_t
*scb
, *sess_scb
;
955 register ioc_t
*iocbp
;
956 register asp_word_t
*awp
;
957 register asp_command_ind_t
*command_ind
;
958 register asp_cmdreply_ind_t
*cmdreply_ind
;
961 iocbp
= (ioc_t
*)gbuf_rptr(mioc
);
963 if (iocbp
->ioc_cmd
== AT_ATP_ISSUE_REQUEST_TICKLE
) {
965 * ignore the ack for the tickle request
967 scb
= (asp_scb_t
*)iocbp
->ioc_cr
;
968 scb
->tickle_tid
= (unsigned short)iocbp
->ioc_rval
;
973 scb
= (asp_scb_t
*)gref
->info
;
979 if (iocbp
->ioc_cmd
== AT_ATP_GET_POLL
) {
981 * if no data, just drop the request
983 if ((mdata
= gbuf_cont(mioc
)) == 0) {
988 gbuf_set_type(mioc
, MSG_IOCTL
);
989 ddp
= (at_ddp_t
*)gbuf_rptr(mdata
);
990 gbuf_rinc(mdata
,DDP_X_HDR_SIZE
);
991 atp
= (at_atp_t
*)gbuf_rptr(mdata
);
992 gbuf_rinc(mdata
,ATP_HDR_SIZE
);
993 rem_addr
.net
= NET_VALUE(ddp
->src_net
);
994 rem_addr
.node
= ddp
->src_node
;
995 rem_addr
.socket
= ddp
->src_socket
;
996 awp
= (asp_word_t
*)atp
->user_bytes
;
1000 * find the responsible scb
1002 if ((scb
= asp_find_scb(scb
->loc_addr
.socket
, &rem_addr
)) == 0) {
1007 dPrintf(D_M_ASP
, D_L_INFO
,
1008 ("asp_ack_reply: %s, loc=%d, rem=%x.%x.%d\n",
1009 aspCmdStr(awp
->func
),scb
->loc_addr
.socket
,
1010 NET_VALUE(ddp
->src_net
) ,ddp
->src_node
,ddp
->src_socket
));
1012 if (scb
->rem_addr
.node
)
1013 asp_untimout(asp_hangup
, scb
);
1015 switch (awp
->func
) {
1016 case ASPFUNC_GetStatus
:
1018 * ignore if this is not a server socket
1021 if ((scb
->dflag
!= 1) || (scb
->stat_msg
1022 && ((mx
= gbuf_dupb(scb
->stat_msg
)) == 0)))
1027 * send the status block
1029 if (gbuf_cont(mdata
)) {
1030 gbuf_freem(gbuf_cont(mdata
));
1031 gbuf_cont(mdata
) = 0;
1033 gbuf_rdec(mdata
,TOTAL_ATP_HDR_SIZE
);
1034 if ((m
= gbuf_alloc( (TOTAL_ATP_HDR_SIZE
+atpBDSsize
), PRI_MED
)) == 0) {
1039 bcopy(gbuf_rptr(mdata
), gbuf_rptr(m
), TOTAL_ATP_HDR_SIZE
);
1042 ddp
= (at_ddp_t
*)gbuf_rptr(mdata
);
1043 gbuf_wset(mdata
,DDP_X_HDR_SIZE
);
1044 atp
= (at_atp_t
*)gbuf_wptr(mdata
);
1045 gbuf_winc(mdata
,ATP_HDR_SIZE
);
1046 awp
= (asp_word_t
*)atp
->user_bytes
;
1047 NET_NET(ddp
->src_net
, ddp
->dst_net
);
1048 ddp
->src_node
= ddp
->dst_node
;
1049 NET_ASSIGN(ddp
->dst_net
, rem_addr
.net
);
1050 ddp
->dst_node
= rem_addr
.node
;
1051 ddp
->dst_socket
= rem_addr
.socket
;
1052 UAS_ASSIGN(ddp
->checksum
, 0);
1053 atpBDS
= (struct atpBDS
*)gbuf_wptr(mdata
);
1054 msize
= mx
? gbuf_msgsize(mx
) : 0;
1055 for (nbds
=0; (nbds
< ATP_TRESP_MAX
) && (msize
> 0); nbds
++) {
1056 len
= msize
< ATP_DATA_SIZE
? msize
: ATP_DATA_SIZE
;
1057 msize
-= ATP_DATA_SIZE
;
1058 *(long *)atpBDS
[nbds
].bdsUserData
= 0;
1059 UAL_ASSIGN(atpBDS
[nbds
].bdsBuffAddr
, 1);
1060 UAS_ASSIGN(atpBDS
[nbds
].bdsBuffSz
, len
);
1062 UAS_ASSIGN(atpBDS
[0].bdsDataSz
, nbds
);
1063 gbuf_winc(mdata
,atpBDSsize
);
1064 gbuf_cont(mdata
) = mx
;
1065 atp_send_rsp(gref
, mdata
, FALSE
);
1068 case ASPFUNC_OpenSess
:
1070 * ignore if server is not ready
1072 if ((scb
->dflag
!= 1) || (scb
->stat_msg
== 0))
1076 if (gbuf_cont(mdata
)) {
1077 gbuf_freem(gbuf_cont(mdata
));
1078 gbuf_cont(mdata
) = 0;
1080 gbuf_rdec(mdata
,TOTAL_ATP_HDR_SIZE
);
1081 gbuf_wset(mdata
,TOTAL_ATP_HDR_SIZE
);
1082 if (awp
->param2
!= ASP_Version
) {
1084 * bad version number, send the OpenSession response
1088 awp
->param2
= (unsigned short)ASPERR_BadVersNum
;
1089 dPrintf(D_M_ASP
, D_L_INFO
,
1091 ASPERR_BadVersNum
));
1093 NET_NET(ddp
->src_net
, ddp
->dst_net
);
1094 ddp
->src_node
= ddp
->dst_node
;
1095 NET_ASSIGN(ddp
->dst_net
, rem_addr
.net
);
1096 ddp
->dst_node
= rem_addr
.node
;
1097 ddp
->dst_socket
= rem_addr
.socket
;
1098 atp_send_rsp(gref
, mdata
, FALSE
);
1103 * queue the connection request
1105 ATDISABLE(s
, scb
->lock
);
1106 gbuf_next(mdata
) = 0;
1107 if ((m
= scb
->sess_ioc
) == 0) {
1108 scb
->sess_ioc
= mdata
;
1110 wakeup(&scb
->event
);
1112 atalk_notify_sel(gref
);
1114 while (gbuf_next(m
))
1116 gbuf_next(m
) = mdata
;
1118 ATENABLE(s
, scb
->lock
);
1119 dPrintf(D_M_ASP
, D_L_INFO
,
1120 (" : QUEUE connect request\n"));
1124 case ASPFUNC_Command
:
1126 if ( (scb
->sess_id
!= awp
->param1
)
1127 || (scb
->rcv_seq_num
!= awp
->param2
)
1128 || BAD_REMADDR(rem_addr
) ) {
1130 sprintf(era
,"%d.%d", scb
->rem_addr
.node
,scb
->rem_addr
.socket
);
1131 sprintf(ra
,"%d.%d", rem_addr
.node
,rem_addr
.socket
);
1132 dPrintf(D_M_ASP
, D_L_WARNING
,
1133 (" : DROP, id=%d,esn=%d,sn=%d,erem=%s,rem=%s\n",
1134 scb
->sess_id
,scb
->rcv_seq_num
,awp
->param2
,era
,ra
));
1135 gbuf_cont(mioc
) = 0;
1136 gbuf_rdec(mdata
,TOTAL_ATP_HDR_SIZE
);
1137 atp_drop_req(gref
, mdata
);
1140 scb
->reply_socket
= rem_addr
.socket
;
1141 if (awp
->func
== ASPFUNC_Write
)
1142 scb
->wrt_seq_num
= scb
->rcv_seq_num
;
1143 NEXT_SEQ_NUM(scb
->rcv_seq_num
);
1144 gbuf_set_type(mioc
, MSG_PROTO
);
1145 gbuf_wset(mioc
,sizeof(asp_command_ind_t
));
1146 command_ind
= (asp_command_ind_t
*)gbuf_rptr(mioc
);
1147 command_ind
->Primitive
= (int)awp
->func
;
1148 command_ind
->ReqRefNum
=
1149 *(unsigned short *)atp
->tid
;
1150 command_ind
->ReqType
= awp
->func
;
1152 mdata
= gbuf_strip(mdata
);
1153 gbuf_cont(mioc
) = mdata
;
1154 ATDISABLE(s
, scb
->lock
);
1155 if (scb
->req_flag
) {
1156 if ((mx
= scb
->req_msgq
) != 0) {
1157 while (gbuf_next(mx
))
1159 gbuf_next(mx
) = mioc
;
1161 scb
->req_msgq
= mioc
;
1162 ATENABLE(s
, scb
->lock
);
1165 ATENABLE(s
, scb
->lock
);
1166 asp_putnext(scb
->gref
, mioc
);
1170 case ASPFUNC_WriteContinue
:
1171 if ( (scb
->sess_id
!= awp
->param1
)
1172 || (scb
->snd_seq_num
!= awp
->param2
)
1173 || BAD_REMADDR(rem_addr
) ) {
1176 scb
->reply_socket
= rem_addr
.socket
;
1177 gbuf_set_type(mioc
, MSG_PROTO
);
1178 gbuf_wset(mioc
,sizeof(asp_command_ind_t
));
1179 command_ind
= (asp_command_ind_t
*)gbuf_rptr(mioc
);
1180 command_ind
->Primitive
= (int)awp
->func
;
1181 command_ind
->ReqRefNum
=
1182 *(unsigned short *)atp
->tid
;
1183 command_ind
->ReqType
= awp
->func
;
1185 mdata
= gbuf_strip(mdata
);
1186 gbuf_cont(mioc
) = mdata
;
1187 asp_putnext(scb
->gref
, mioc
);
1190 case ASPFUNC_Tickle
:
1191 if (scb
->stat_msg
) {
1192 sess_scb
= asp_scbQ
[awp
->param1
];
1193 if (sess_scb
&& sess_scb
->next_scb
)
1194 sess_scb
= asp_find_scb(
1195 sess_scb
->loc_addr
.socket
, &rem_addr
);
1197 if (sess_scb
->rem_addr
.node
)
1198 asp_untimout(asp_hangup
, sess_scb
);
1199 if (sess_scb
->rem_addr
.node
)
1200 asp_timout(asp_hangup
, sess_scb
, sess_scb
->session_timer
);
1203 dPrintf(D_M_ASP
, D_L_INFO
,
1204 (" : Tickle, %d -> %d, id=%d\n",
1205 ddp
->src_socket
,ddp
->dst_socket
,awp
->param1
));
1208 case ASPFUNC_CloseSess
:
1209 if ( (scb
->sess_id
!= awp
->param1
)
1210 || (scb
->state
== ASPSTATE_Close
)
1211 || (scb
->state
== ASPSTATE_WaitingForCloseSessRsp
)
1212 || (scb
->rem_addr
.net
!= rem_addr
.net
)
1213 || (scb
->rem_addr
.node
!= rem_addr
.node
) ) {
1214 dPrintf(D_M_ASP
, D_L_INFO
,
1215 (" : CLOSE retry, loc=%d, rem=%x.%x.%d\n",
1216 scb
->loc_addr
.socket
,
1219 scb
->rem_addr
.socket
));
1226 * build the CloseSess response to be sent to peer
1227 * when the session is closed by the user.
1229 if (gbuf_cont(mdata
)) {
1230 gbuf_freem(gbuf_cont(mdata
));
1231 gbuf_cont(mdata
) = 0;
1233 gbuf_rdec(mdata
,TOTAL_ATP_HDR_SIZE
);
1234 gbuf_wset(mdata
,TOTAL_ATP_HDR_SIZE
);
1235 NET_NET(ddp
->src_net
, ddp
->dst_net
);
1236 ddp
->src_node
= ddp
->dst_node
;
1237 NET_ASSIGN(ddp
->dst_net
, rem_addr
.net
);
1238 ddp
->dst_node
= rem_addr
.node
;
1239 ddp
->dst_socket
= rem_addr
.socket
;
1243 dPrintf(D_M_ASP
,D_L_INFO
,
1244 (" : CLOSE, loc=%d, rem=%x.%x.%d\n",
1245 scb
->loc_addr
.socket
,
1248 scb
->rem_addr
.socket
));
1250 gbuf_next(mdata
) = 0;
1251 ATDISABLE(s
, scb
->lock
);
1253 gbuf_freel(scb
->sess_ioc
);
1254 scb
->sess_ioc
= mdata
;
1255 scb
->state
= ASPSTATE_Close
;
1256 ATENABLE(s
, scb
->lock
);
1259 * notify upstream of the CloseSess from peer
1264 case ASPFUNC_Attention
:
1265 if ( (scb
->sess_id
!= awp
->param1
)
1266 || (scb
->rem_addr
.net
!= rem_addr
.net
)
1267 || (scb
->rem_addr
.node
!= rem_addr
.node
) ) {
1270 gbuf_set_type(mioc
, MSG_PROTO
);
1271 gbuf_wset(mioc
,sizeof(asp_command_ind_t
));
1272 command_ind
= (asp_command_ind_t
*)gbuf_rptr(mioc
);
1273 command_ind
->Primitive
= (int)awp
->func
;
1274 command_ind
->ReqRefNum
=
1275 *(unsigned short *)atp
->tid
;
1276 command_ind
->ReqType
= awp
->func
;
1277 scb
->attn_tid
= *(unsigned short *)atp
->tid
;
1279 gbuf_rdec(mdata
,2); /* attention code */
1281 mdata
= gbuf_strip(mdata
);
1282 gbuf_cont(mioc
) = mdata
;
1283 asp_putnext(scb
->gref
, mioc
);
1287 dPrintf(D_M_ASP
, D_L_WARNING
,
1288 (" : UNKNOWN func, func=%d\n",
1295 else if (iocbp
->ioc_cmd
== AT_ATP_REQUEST_COMPLETE
) {
1296 if (scb
->next_scb
) {
1298 * find the responsible scb
1300 scb
= (asp_scb_t
*)iocbp
->ioc_private
;
1301 if ((scb
== 0) || (scb
->magic_num
!= 222)) {
1302 dPrintf(D_M_ASP
, D_L_ERROR
,
1303 ("asp_ack_reply: CAN'T find scb 1\n"));
1308 dPrintf(D_M_ASP
, D_L_INFO
,
1309 ("asp_ack_reply: RSP, loc=%d, rem=%x.%x.%d, state=%s\n",
1310 scb
->loc_addr
.socket
,
1313 scb
->rem_addr
.socket
,
1314 aspStateStr(scb
->state
)));
1316 switch (scb
->state
) {
1317 case ASPSTATE_Close
:
1319 scb
->rem_addr
.node
= 0;
1321 ATDISABLE(s
, scb
->lock
);
1323 wakeup(&scb
->event
);
1325 atalk_notify_sel(gref
);
1326 ATENABLE(s
, scb
->lock
);
1329 case ASPSTATE_WaitingForGetStatusRsp
:
1331 scb
->state
= ASPSTATE_Idle
;
1332 mx
= gbuf_cont(mioc
);
1333 gbuf_cont(mioc
) = 0;
1334 mdata
= gbuf_cont(mx
);
1336 iocbp
->ioc_cmd
= ASPIOC_GetStatus
;
1337 iocbp
->ioc_count
= 0;
1338 iocbp
->ioc_rval
= mdata
? gbuf_msgsize(mdata
) : 0;
1340 atalk_putnext(gref
, mioc
);
1341 atalk_putnext(gref
, mdata
);
1344 case ASPSTATE_WaitingForOpenSessRsp
:
1346 scb
->state
= ASPSTATE_Idle
;
1347 mx
= gbuf_cont(mioc
);
1348 gbuf_cont(mioc
) = 0;
1349 if (gbuf_cont(mx
)) {
1350 gbuf_freem(gbuf_cont(mx
));
1353 iocbp
->ioc_cmd
= ASPIOC_OpenSession
;
1354 iocbp
->ioc_rval
= 0;
1355 iocbp
->ioc_count
= 0;
1356 atpBDS
= (struct atpBDS
*)gbuf_rptr(mx
);
1357 awp
= (asp_word_t
*)atpBDS
->bdsUserData
;
1360 asp_iocnak(gref
, mioc
, ECONNREFUSED
);
1362 scb
->rem_addr
.node
= scb
->rem_node
;
1363 scb
->rem_addr
.socket
= awp
->func
;
1364 /* bms: need to set the reply_socket for client side too.
1365 This makes ALO atten replies sent by the client work. */
1366 scb
->reply_socket
= scb
->rem_addr
.socket
;
1367 scb
->sess_id
= awp
->param1
;
1369 atalk_putnext(gref
, mioc
);
1370 asp_timout(asp_hangup
, scb
, scb
->session_timer
);
1371 asp_send_tickle(scb
);
1372 dPrintf(D_M_ASP
, D_L_INFO
,
1373 ("asp_ack_reply: CONNECT, loc=%d, rem=%x.%x.%d\n",
1374 scb
->loc_addr
.socket
,
1377 scb
->rem_addr
.socket
));
1381 case ASPSTATE_WaitingForCommandRsp
:
1382 case ASPSTATE_WaitingForWriteRsp
:
1383 case ASPSTATE_WaitingForWriteContinueRsp
:
1384 if (scb
->rem_addr
.node
)
1385 asp_untimout(asp_hangup
, scb
);
1386 NEXT_SEQ_NUM(scb
->snd_seq_num
);
1387 scb
->state
= ASPSTATE_Idle
;
1388 gbuf_set_type(mioc
, MSG_PROTO
);
1389 mx
= gbuf_cont(mioc
);
1390 mdata
= gbuf_cont(mx
);
1391 gbuf_cont(mioc
) = mdata
;
1392 atpBDS
= (struct atpBDS
*)gbuf_rptr(mx
);
1393 cmdreply_ind
= (asp_cmdreply_ind_t
*)gbuf_rptr(mioc
);
1394 cmdreply_ind
->Primitive
= ASPFUNC_CmdReply
;
1395 cmdreply_ind
->CmdResult
= *(int *)atpBDS
->bdsUserData
;
1396 gbuf_wset(mioc
,sizeof(asp_cmdreply_ind_t
));
1398 asp_putnext(scb
->gref
, mioc
);
1401 case ASPSTATE_WaitingForCloseSessRsp
:
1403 scb
->state
= ASPSTATE_Close
;
1404 scb
->rem_addr
.node
= 0;
1405 iocbp
->ioc_cmd
= ASPIOC_CloseSession
;
1406 iocbp
->ioc_rval
= 0;
1407 if (gbuf_cont(mioc
)) {
1408 gbuf_freem(gbuf_cont(mioc
));
1409 gbuf_cont(mioc
) = 0;
1411 atalk_putnext(scb
->gref
, mioc
);
1412 atp_cancel_req(scb
->gref
, (unsigned int)scb
->tickle_tid
);
1413 scb
->tickle_tid
= 0;
1417 dPrintf(D_M_ASP
, D_L_WARNING
,
1418 (" : UNKNOWN state, state=%s\n",
1419 aspStateStr(scb
->state
)));
1425 if (scb
->next_scb
) {
1427 * find the responsible scb
1429 scb
= (asp_scb_t
*)iocbp
->ioc_cr
;
1430 if ((scb
== 0) || (scb
->magic_num
!= 222)) {
1431 dPrintf(D_M_ASP
, D_L_ERROR
,
1432 ("asp_ack_reply: CAN'T find scb 2\n"));
1438 switch (scb
->state
) {
1439 case ASPSTATE_Close
:
1440 scb
->rem_addr
.node
= 0;
1449 if (scb
->rem_addr
.node
)
1450 asp_timout(asp_hangup
, scb
, scb
->session_timer
);
1451 } /* asp_ack_reply */
1457 asp_nak_reply(gref
, mioc
)
1458 register gref_t
*gref
;
1459 register gbuf_t
*mioc
;
1461 register asp_scb_t
*scb
;
1462 register ioc_t
*iocbp
;
1464 iocbp
= (ioc_t
*)gbuf_rptr(mioc
);
1466 if (iocbp
->ioc_cmd
== AT_ATP_ISSUE_REQUEST_TICKLE
) {
1468 * no tickle, close session
1470 scb
= (asp_scb_t
*)iocbp
->ioc_cr
;
1473 dPrintf(D_M_ASP
, D_L_WARNING
,
1474 ("tickle_nak: loc=%d, rem=%x.%x.%d, state=%s\n",
1475 scb
->loc_addr
.socket
,
1478 scb
->rem_addr
.socket
,
1479 aspStateStr(scb
->state
)));
1484 scb
= (asp_scb_t
*)gref
->info
;
1490 if (iocbp
->ioc_cmd
== AT_ATP_REQUEST_COMPLETE
) {
1491 if (scb
->next_scb
) {
1493 * find the responsible scb
1495 scb
= (asp_scb_t
*)iocbp
->ioc_private
;
1496 if ((scb
== 0) || (scb
->magic_num
!= 222)) {
1497 dPrintf(D_M_ASP
, D_L_ERROR
,
1498 ("asp_nak_reply: CAN'T find scb 1\n"));
1503 dPrintf(D_M_ASP
, D_L_WARNING
,
1504 ("asp_nak_reply: RSP, loc=%d, rem=%x.%x.%d, state=%s\n",
1505 scb
->loc_addr
.socket
,
1508 scb
->rem_addr
.socket
,
1509 aspStateStr(scb
->state
)));
1511 switch (scb
->state
) {
1512 case ASPSTATE_WaitingForGetStatusRsp
:
1513 iocbp
->ioc_cmd
= ASPIOC_GetStatus
;
1516 case ASPSTATE_WaitingForOpenSessRsp
:
1517 iocbp
->ioc_cmd
= ASPIOC_OpenSession
;
1520 case ASPSTATE_WaitingForCommandRsp
:
1521 case ASPSTATE_WaitingForWriteRsp
:
1522 case ASPSTATE_WaitingForWriteContinueRsp
:
1523 scb
->state
= ASPSTATE_Idle
;
1525 /* last remaining use of MSG_ERROR */
1526 gbuf_set_type(mioc
, MSG_ERROR
);
1527 *gbuf_rptr(mioc
) = (u_char
)EPROTO
;
1529 if (gbuf_cont(mioc
)) {
1530 gbuf_freem(gbuf_cont(mioc
));
1531 gbuf_cont(mioc
) = 0;
1534 asp_putnext(scb
->gref
, mioc
);
1537 case ASPSTATE_WaitingForCloseSessRsp
:
1538 scb
->state
= ASPSTATE_Close
;
1540 case ASPSTATE_Close
: /* new for PR-2296832 */
1541 scb
->rem_addr
.node
= 0;
1542 iocbp
->ioc_cmd
= ASPIOC_CloseSession
;
1543 iocbp
->ioc_rval
= 0;
1544 if (gbuf_cont(mioc
)) {
1545 gbuf_freem(gbuf_cont(mioc
));
1546 gbuf_cont(mioc
) = 0;
1548 gbuf_set_type(mioc
, MSG_IOCACK
);
1549 atalk_putnext(scb
->gref
, mioc
);
1556 scb
->state
= ASPSTATE_Idle
;
1557 atalk_putnext(gref
, mioc
);
1561 if (scb
->next_scb
) {
1563 * find the responsible scb
1565 scb
= (asp_scb_t
*)iocbp
->ioc_cr
;
1566 if ((scb
== 0) || (scb
->magic_num
!= 222)) {
1567 dPrintf(D_M_ASP
, D_L_ERROR
,
1568 ("asp_nak_reply: CAN'T find scb 2\n"));
1574 switch (scb
->state
) {
1575 case ASPSTATE_Close
:
1576 scb
->rem_addr
.node
= 0;
1582 } /* asp_nak_reply */
1585 * delete scb from the use list
1588 asp_dequeue_scb(scb
)
1593 ATDISABLE(s
, aspall_lock
);
1594 if (scb
== scb_used_list
) {
1595 if ((scb_used_list
= scb
->next_scb
) != 0)
1596 scb
->next_scb
->prev_scb
= 0;
1598 if ((scb
->prev_scb
->next_scb
= scb
->next_scb
) != 0)
1599 scb
->next_scb
->prev_scb
= scb
->prev_scb
;
1601 ATENABLE(s
, aspall_lock
);
1610 StaticProc asp_scb_t
*
1611 asp_find_scb(sock_num
, rem_addr
)
1612 unsigned char sock_num
;
1613 at_inet_t
*rem_addr
;
1617 asp_scb_t
*alt_scb
= 0;
1619 ATDISABLE(s
, aspall_lock
);
1620 for (scb
= asp_scbQ
[sock_num
]; scb
; scb
= scb
->next_scb
) {
1621 if ((scb
->rem_addr
.net
== rem_addr
->net
)
1622 && (scb
->rem_addr
.node
== rem_addr
->node
)) {
1623 if ((scb
->rem_addr
.socket
== rem_addr
->socket
)
1624 || (scb
->rem_socket
== rem_addr
->socket
))
1626 else if (alt_scb
== 0)
1631 if ((scb
== 0) && ((scb
= alt_scb
) == 0)) {
1632 dPrintf(D_M_ASP
, D_L_ERROR
,
1633 ("asp_find_scb: CAN'T find scb, loc=%d, rem=%x.%x.%d\n",
1639 ATENABLE(s
, aspall_lock
);
1648 asp_timout(func
, scb
, seconds
)
1650 register asp_scb_t
*scb
;
1655 register asp_scb_t
*curr_scb
, *prev_scb
;
1660 scb
->tmo_func
= func
;
1661 scb
->tmo_delta
= (seconds
>>SESS_TMO_RES
);
1662 scb
->tmo_cnt
= scb_tmo_cnt
;
1664 ATDISABLE(s
, asptmo_lock
);
1665 if (scb_tmo_list
== 0) {
1666 scb
->next_tmo
= scb
->prev_tmo
= 0;
1668 ATENABLE(s
, asptmo_lock
);
1673 curr_scb
= scb_tmo_list
;
1677 sum
+= curr_scb
->tmo_delta
;
1678 if (sum
> scb
->tmo_delta
) {
1679 sum
-= curr_scb
->tmo_delta
;
1680 scb
->tmo_delta
-= sum
;
1681 curr_scb
->tmo_delta
-= scb
->tmo_delta
;
1684 prev_scb
= curr_scb
;
1685 if ((curr_scb
= curr_scb
->next_tmo
) == 0) {
1686 scb
->tmo_delta
-= sum
;
1692 scb
->prev_tmo
= prev_scb
;
1693 if ((scb
->next_tmo
= prev_scb
->next_tmo
) != 0)
1694 prev_scb
->next_tmo
->prev_tmo
= scb
;
1695 prev_scb
->next_tmo
= scb
;
1698 scb
->next_tmo
= scb_tmo_list
;
1699 scb_tmo_list
->prev_tmo
= scb
;
1702 ATENABLE(s
, asptmo_lock
);
1709 asp_untimout(func
, scb
)
1711 register asp_scb_t
*scb
;
1715 if ((scb
->tmo_cnt
== scb_tmo_cnt
) || (scb
->tmo_func
== 0))
1718 ATDISABLE(s
, asptmo_lock
);
1719 if (scb_tmo_list
== scb
) {
1720 if ((scb_tmo_list
= scb
->next_tmo
) != 0) {
1721 scb_tmo_list
->prev_tmo
= 0;
1722 scb
->next_tmo
->tmo_delta
+= scb
->tmo_delta
;
1724 } else if (scb
->prev_tmo
) {
1725 if ((scb
->prev_tmo
->next_tmo
= scb
->next_tmo
) != 0) {
1726 scb
->next_tmo
->prev_tmo
= scb
->prev_tmo
;
1727 scb
->next_tmo
->tmo_delta
+= scb
->tmo_delta
;
1732 ATENABLE(s
, asptmo_lock
);
1745 * set the state to Close
1747 ATDISABLE(s
, scb
->lock
);
1748 scb
->state
= ASPSTATE_Close
;
1749 if (scb
->tickle_tid
) {
1750 atp_cancel_req(scb
->gref
, (unsigned int)scb
->tickle_tid
);
1751 scb
->tickle_tid
= 0;
1755 * notify upstream of the hangup
1757 if (scb
->rem_addr
.node
) {
1758 if (scb
->get_wait
) {
1759 wakeup(&scb
->event
);
1760 ATENABLE(s
, scb
->lock
);
1762 ATENABLE(s
, scb
->lock
);
1763 atalk_notify_sel(scb
->gref
);
1766 ATENABLE(s
, scb
->lock
);
1770 asp_iocack(gref
, mioc
)
1774 if (gbuf_cont(mioc
))
1775 ((ioc_t
*)gbuf_rptr(mioc
))->ioc_count
= gbuf_msgsize(gbuf_cont(mioc
));
1777 ((ioc_t
*)gbuf_rptr(mioc
))->ioc_count
= 0;
1779 gbuf_set_type(mioc
, MSG_IOCACK
);
1780 atalk_putnext(gref
, mioc
);
1784 asp_iocnak(gref
, mioc
, err
)
1789 ((ioc_t
*)gbuf_rptr(mioc
))->ioc_count
= 0;
1792 ((ioc_t
*)gbuf_rptr(mioc
))->ioc_error
= err
;
1793 ((ioc_t
*)gbuf_rptr(mioc
))->ioc_rval
= -1;
1794 if (gbuf_cont(mioc
)) {
1795 gbuf_freem(gbuf_cont(mioc
));
1796 gbuf_cont(mioc
) = 0;
1799 gbuf_set_type(mioc
, MSG_IOCNAK
);
1800 atalk_putnext(gref
, mioc
);
1804 * the alloc scb routine
1806 StaticProc asp_scb_t
*
1811 asp_scb_t
*scb
, *scb_array
;
1813 ATDISABLE(s
, aspall_lock
);
1814 if (scb_free_list
== 0) {
1815 if ((m
= gbuf_alloc(SCBS_PER_BLK
*sizeof(asp_scb_t
), PRI_MED
)) == 0)
1817 ATENABLE(s
, aspall_lock
);
1818 return (asp_scb_t
*)0;
1820 bzero((char *)gbuf_rptr(m
), SCBS_PER_BLK
*sizeof(asp_scb_t
));
1821 gbuf_cont(m
) = scb_resource_m
;
1823 scb_array
= (asp_scb_t
*)gbuf_rptr(m
);
1824 for (i
=0; i
< SCBS_PER_BLK
-1; i
++)
1825 scb_array
[i
].next_scb
= (asp_scb_t
*)&scb_array
[i
+1];
1826 scb_array
[i
].next_scb
= 0;
1827 scb_free_list
= (asp_scb_t
*)&scb_array
[0];
1830 scb
= scb_free_list
;
1831 scb_free_list
= scb
->next_scb
;
1832 ATENABLE(s
, aspall_lock
);
1833 ATLOCKINIT(scb
->lock
);
1834 ATLOCKINIT(scb
->delay_lock
);
1835 ATEVENTINIT(scb
->event
);
1836 ATEVENTINIT(scb
->delay_event
);
1842 * the free scb routine
1850 bzero((char *)scb
, sizeof(asp_scb_t
));
1851 ATDISABLE(s
, aspall_lock
);
1852 scb
->next_scb
= scb_free_list
;
1853 scb_free_list
= scb
;
1854 ATENABLE(s
, aspall_lock
);
1858 * routine to pass up receive data
1861 asp_putnext(gref
, mproto
)
1869 scb
= (asp_scb_t
*)gref
->info
;
1872 * queue the message.
1874 ATDISABLE(s
, scb
->lock
);
1875 gbuf_next(mproto
) = 0;
1876 if ((m
= scb
->sess_ioc
) == 0)
1877 scb
->sess_ioc
= mproto
;
1879 while (gbuf_next(m
))
1881 gbuf_next(m
) = mproto
;
1884 if (scb
->rcv_cnt
>= MAX_RCV_CNT
)
1887 if (scb
->get_wait
) {
1888 wakeup(&scb
->event
);
1889 ATENABLE(s
, scb
->lock
);
1890 } else if (mproto
== scb
->sess_ioc
) {
1891 ATENABLE(s
, scb
->lock
);
1892 atalk_notify_sel(gref
);
1894 ATENABLE(s
, scb
->lock
);
1898 * The following two routines are direct entries from system
1899 * calls to allow fast sending and recving of ASP data.
1902 /* in ASPputmsg we expect:
1908 ASPFUNC_WriteContinue
1910 bms: Make this callable from the kernel.
1911 If mreq != NULL, then must be called from kernel space and the following apply:
1912 1) *mreq is data to be sent already in mbuf chains.
1913 2) datptr->len = size of data
1916 int ASPputmsg(gref_t
*gref
, strbuf_t
*ctlptr
, strbuf_t
*datptr
, gbuf_t
*mreq
, int flags
, int *errp
)
1919 gbuf_t
*mioc
, *mdata
, *mx
;
1924 int nbds
, result
, msize
, Primitive
;
1925 unsigned char *wptr
;
1926 struct atp_set_default
*sd
;
1929 struct atpBDS
*atpBDS
;
1931 union asp_primitives
*primitives
;
1934 if ((scb
= (asp_scb_t
*)gref
->info
) == 0) {
1935 dPrintf(D_M_ASP
, D_L_ERROR
,
1936 ("ASPputmsg: stale handle=0x%x, pid=%d\n",
1937 (u_int
) gref
, gref
->pid
));
1943 if (scb
->state
== ASPSTATE_Close
)
1945 if (scb
->snd_stop
) {
1951 * copy in the control and data info
1954 /* being called from kernel space */
1955 bcopy (ctlptr
, &ctlbuf
, sizeof (strbuf_t
));
1956 bcopy (datptr
, &datbuf
, sizeof (strbuf_t
));
1958 /* being called from user space */
1959 if ((err
= copyin((caddr_t
)ctlptr
, (caddr_t
)&ctlbuf
, sizeof(ctlbuf
))) != 0)
1961 if ((err
= copyin((caddr_t
)datptr
, (caddr_t
)&datbuf
, sizeof(datbuf
))) != 0)
1966 * allocate buffer and copy in the control content
1968 if (!(mioc
= gbuf_alloc_wait(ctlbuf
.len
, TRUE
))) {
1969 /* error return should not be possible */
1973 gbuf_set_type(mioc
, MSG_IOCTL
); /* for later, in ATP */
1974 gbuf_wset(mioc
, ctlbuf
.len
);
1977 /* being called from kernel space */
1978 bcopy (ctlbuf
.buf
, gbuf_rptr(mioc
), ctlbuf
.len
);
1980 /* being called from user space */
1981 if ((err
= copyin((caddr_t
)ctlbuf
.buf
, (caddr_t
)gbuf_rptr(mioc
), ctlbuf
.len
)) != 0) {
1987 iocbp
= (ioc_t
*)gbuf_rptr(mioc
);
1988 primitives
= (union asp_primitives
*)gbuf_rptr(mioc
);
1989 Primitive
= primitives
->Primitive
;
1990 dPrintf(D_M_ASP
, D_L_INFO
,
1991 ("ASPputmsg: %s\n", aspCmdStr(Primitive
)));
1994 * allocate buffer and copy in the data content
1996 len
= (Primitive
== ASPFUNC_CmdReply
) ? 0 : aspCMDsize
;
1998 if (!(mdata
= gbuf_alloc_wait(datbuf
.len
+len
, TRUE
))) {
1999 /* error return should not be possible */
2004 gbuf_wset(mdata
, (datbuf
.len
+len
));
2005 gbuf_cont(mioc
) = mdata
;
2008 /* being called from kernel space */
2010 unsigned long offset
= 0;
2012 /* copy afp cmd data from the passed in mbufs to mdata. I cant
2013 chain mreq to mdata since the rest of this code assumes
2014 just one big mbuf with space in front for the BDS */
2016 while (tmp
!= NULL
) {
2017 bcopy (gbuf_rptr(tmp
), (gbuf_rptr(mdata
) + offset
), gbuf_len(tmp
));
2018 offset
+= gbuf_len(tmp
);
2019 tmp
= gbuf_cont(tmp
); /* on to next mbuf in chain */
2022 /* all data copied out of mreq so free it */
2025 /* being called from user space */
2026 if ((err
= copyin((caddr_t
)datbuf
.buf
,
2027 (caddr_t
)(gbuf_rptr(mdata
)+len
), datbuf
.len
)) != 0) {
2033 switch (Primitive
) {
2035 case ASPFUNC_Command
:
2037 case ASPFUNC_WriteContinue
:
2038 case ASPFUNC_Attention
:
2040 * build the command/write/write_continue request
2042 wptr
= gbuf_rptr(mdata
);
2043 atpBDS
= (struct atpBDS
*)wptr
;
2045 for (i
=0; i
< ATP_TRESP_MAX
; i
++) {
2046 *(unsigned long *)atpBDS
[i
].bdsBuffAddr
= 1;
2047 *(unsigned short *)atpBDS
[i
].bdsBuffSz
= ATP_DATA_SIZE
;
2049 sd
= (struct atp_set_default
*)wptr
;
2050 wptr
+= sizeof(struct atp_set_default
);
2051 sd
->def_retries
= (scb
->cmd_retry
.retries
== -1) ?
2052 ATP_INFINITE_RETRIES
: scb
->cmd_retry
.retries
;
2053 sd
->def_rate
= scb
->cmd_retry
.interval
*TICKS_PER_SEC
;
2054 sd
->def_BDSlen
= atpBDSsize
;
2055 ddp
= (at_ddp_t
*)wptr
;
2056 NET_ASSIGN(ddp
->src_net
, scb
->loc_addr
.net
);
2057 ddp
->src_node
= scb
->loc_addr
.node
;
2058 NET_ASSIGN(ddp
->dst_net
, scb
->rem_addr
.net
);
2059 ddp
->dst_node
= scb
->rem_addr
.node
;
2060 ddp
->dst_socket
= scb
->rem_addr
.socket
;
2061 UAS_ASSIGN(ddp
->checksum
, 0);
2062 atp
= ATP_ATP_HDR(wptr
);
2063 wptr
+= TOTAL_ATP_HDR_SIZE
;
2067 awp
= (asp_word_t
*)atp
->user_bytes
;
2068 awp
->func
= (unsigned char)Primitive
;
2069 awp
->param1
= scb
->sess_id
;
2070 awp
->param2
= scb
->snd_seq_num
;
2071 iocbp
->ioc_private
= (void *)scb
;
2072 iocbp
->ioc_count
= gbuf_len(mdata
);
2073 iocbp
->ioc_rval
= 0;
2074 iocbp
->ioc_cmd
= AT_ATP_ISSUE_REQUEST_DEF
;
2077 * send the command/write/write_continue/attention request
2079 ATDISABLE(s
, scb
->lock
);
2080 switch (awp
->func
) {
2081 case ASPFUNC_Command
:
2082 scb
->state
= ASPSTATE_WaitingForCommandRsp
;
2085 scb
->state
= ASPSTATE_WaitingForWriteRsp
;
2087 case ASPFUNC_WriteContinue
:
2088 scb
->state
= ASPSTATE_WaitingForWriteContinueRsp
;
2089 awp
->param2
= scb
->wrt_seq_num
;
2091 case ASPFUNC_Attention
:
2092 scb
->state
= ASPSTATE_WaitingForCommandRsp
;
2097 awp
->param2
= *(unsigned short *)gbuf_wptr(mdata
);
2100 ATENABLE(s
, scb
->lock
);
2101 dPrintf(D_M_ASP
,D_L_INFO
,
2102 ("ASPputmsg: %s, loc=%d, rem=%x.%x.%d\n",
2103 (awp
->func
== ASPFUNC_Command
? "CommandReq" :
2104 awp
->func
== ASPFUNC_Write
? "WriteReq" :
2105 awp
->func
== ASPFUNC_WriteContinue
? "WriteContinue" :
2106 "AttentionReq"),scb
->loc_addr
.socket
,
2107 NET_VALUE(ddp
->dst_net
),ddp
->dst_node
,ddp
->dst_socket
));
2108 atp_send_req(gref
, mioc
);
2111 case ASPFUNC_CmdReply
:
2113 ATDISABLE(s
, scb
->lock
);
2114 if (scb
->req_msgq
) {
2116 scb
->req_msgq
= gbuf_next(mx
);
2118 ATENABLE(s
, scb
->lock
);
2119 asp_putnext(scb
->gref
, mx
);
2122 ATENABLE(s
, scb
->lock
);
2124 result
= primitives
->CmdReplyReq
.CmdResult
;
2125 tid
= primitives
->CmdReplyReq
.ReqRefNum
;
2127 /* Re-use the original mioc mbuf to send the response. */
2128 gbuf_rinc(mioc
,sizeof(void *));
2130 ddp
= (at_ddp_t
*)gbuf_wptr(mioc
);
2131 gbuf_winc(mioc
,DDP_X_HDR_SIZE
);
2132 atp
= (at_atp_t
*)gbuf_wptr(mioc
);
2133 gbuf_winc(mioc
,ATP_HDR_SIZE
);
2134 NET_ASSIGN(ddp
->src_net
, scb
->loc_addr
.net
);
2135 ddp
->src_node
= scb
->loc_addr
.node
;
2136 NET_ASSIGN(ddp
->dst_net
, scb
->rem_addr
.net
);
2137 ddp
->dst_node
= scb
->rem_addr
.node
;
2138 ddp
->dst_socket
= scb
->reply_socket
;
2139 ddp
->type
= DDP_ATP
;
2140 UAS_ASSIGN(ddp
->checksum
, 0);
2141 UAS_ASSIGN(atp
->tid
, tid
);
2142 if (scb
->attn_flag
&& (tid
== scb
->attn_tid
)) {
2150 atpBDS
= (struct atpBDS
*)gbuf_wptr(mioc
);
2151 msize
= mdata
? gbuf_msgsize(mdata
) : 0;
2152 for (nbds
=0; (nbds
< ATP_TRESP_MAX
) && (msize
> 0); nbds
++) {
2153 len
= msize
< ATP_DATA_SIZE
? msize
: ATP_DATA_SIZE
;
2154 msize
-= ATP_DATA_SIZE
;
2155 *(long *)atpBDS
[nbds
].bdsUserData
= 0;
2156 UAL_ASSIGN(atpBDS
[nbds
].bdsBuffAddr
, 1);
2157 UAS_ASSIGN(atpBDS
[nbds
].bdsBuffSz
, len
);
2159 UAS_ASSIGN(atpBDS
[0].bdsDataSz
, nbds
);
2160 *(long *)atpBDS
[0].bdsUserData
= (long)result
;
2161 *(long *)atp
->user_bytes
= (long)result
;
2162 gbuf_winc(mioc
,atpBDSsize
);
2163 dPrintf(D_M_ASP
, D_L_INFO
,
2164 ("ASPputmsg: ATP CmdReplyReq, loc=%d, state=%s, msgsize = %d, result = %d, tid = %d\n",
2165 scb
->loc_addr
.socket
, aspStateStr(scb
->state
),
2166 (mdata
? gbuf_msgsize(mdata
) : 0), result
, tid
));
2167 atp_send_rsp(gref
, mioc
, TRUE
);
2171 /* Not an expected ASPFUNC */
2181 /* bms: make this callable from kernel. reply date is passed back as a mbuf chain in *mreply */
2182 int ASPgetmsg(gref_t
*gref
, strbuf_t
*ctlptr
, strbuf_t
*datptr
, gbuf_t
**mreply
, int *flags
, int *errp
)
2184 int err
, s
, len
, sum
, rval
;
2185 gbuf_t
*mproto
, *mdata
;
2189 unsigned char get_wait
;
2191 if ((scb
= (asp_scb_t
*)gref
->info
) == 0) {
2192 dPrintf(D_M_ASP
, D_L_ERROR
,
2193 ("ASPgetmsg: stale handle=0x%x, pid=%d\n",
2194 (u_int
) gref
, gref
->pid
));
2200 ATDISABLE(s
, scb
->lock
);
2201 if (scb
->state
== ASPSTATE_Close
) {
2202 ATENABLE(s
, scb
->lock
);
2209 while ((mproto
= scb
->sess_ioc
) == 0) {
2211 err
= tsleep(&scb
->event
, PSOCK
| PCATCH
, "aspgetmsg", 0);
2214 ATENABLE(s
, scb
->lock
);
2218 if (scb
->state
== ASPSTATE_Close
) {
2220 ATENABLE(s
, scb
->lock
);
2224 get_wait
= scb
->get_wait
;
2226 if ((ctlptr
== 0) && (datptr
== 0)) {
2227 ATENABLE(s
, scb
->lock
);
2230 scb
->sess_ioc
= gbuf_next(mproto
);
2231 mdata
= gbuf_cont(mproto
);
2232 ATENABLE(s
, scb
->lock
);
2234 /* last remaining use of MSG_ERROR */
2235 if (gbuf_type(mproto
) == MSG_ERROR
) {
2236 err
= (int)gbuf_rptr(mproto
)[0];
2241 * copy in the control and data info
2243 if (mreply
!= NULL
) {
2244 /* called from kernel space */
2245 bcopy (ctlptr
, &ctlbuf
, sizeof(ctlbuf
));
2246 bcopy (datptr
, &datbuf
, sizeof(datbuf
));
2248 /* called from user space */
2249 if ((err
= copyin((caddr_t
)ctlptr
,
2250 (caddr_t
)&ctlbuf
, sizeof(ctlbuf
))) != 0)
2252 if ((err
= copyin((caddr_t
)datptr
,
2253 (caddr_t
)&datbuf
, sizeof(datbuf
))) != 0)
2256 if ((datbuf
.maxlen
< 0) || (datbuf
.maxlen
< gbuf_msgsize(mdata
))) {
2257 ATDISABLE(s
, scb
->lock
);
2258 gbuf_next(mproto
) = scb
->sess_ioc
;
2259 scb
->sess_ioc
= mproto
;
2260 ATENABLE(s
, scb
->lock
);
2264 if (get_wait
== 0) {
2266 * this is a hack to support the select() call.
2267 * we're not supposed to dequeue messages in the Streams
2268 * head's read queue this way; but there is no better way.
2270 ATDISABLE(s
, scb
->lock
);
2271 if (scb
->sess_ioc
== 0) {
2272 ATENABLE(s
, scb
->lock
);
2274 ATENABLE(s
, scb
->lock
);
2275 atalk_notify_sel(gref
);
2280 * copy out the control content and info
2282 ctlbuf
.len
= gbuf_len(mproto
);
2284 if (mreply
!= NULL
) {
2285 /* called from kernel space */
2286 bcopy (gbuf_rptr(mproto
), ctlbuf
.buf
, ctlbuf
.len
);
2287 bcopy (&ctlbuf
, ctlptr
, sizeof(ctlbuf
));
2289 /* called from user space */
2290 if ((err
= copyout((caddr_t
)gbuf_rptr(mproto
),
2291 (caddr_t
)ctlbuf
.buf
, ctlbuf
.len
)) != 0)
2293 if ((err
= copyout((caddr_t
)&ctlbuf
,
2294 (caddr_t
)ctlptr
, sizeof(ctlbuf
))) != 0)
2299 * copy out the data content and info
2301 for (rval
= 0, sum
= 0; mdata
&& (rval
== 0); mdata
= gbuf_cont(mdata
))
2303 len
= gbuf_len(mdata
);
2305 if ((len
+ sum
) > datbuf
.maxlen
) {
2306 len
= datbuf
.maxlen
- sum
;
2310 if (mreply
== NULL
) {
2311 /* called from user space */
2312 if ((err
= copyout((caddr_t
)gbuf_rptr(mdata
), (caddr_t
)&datbuf
.buf
[sum
], len
)) != 0)
2319 if (mreply
!= NULL
) {
2320 /* called from kernel space */
2321 bcopy (&datbuf
, datptr
, sizeof(datbuf
));
2323 /* called from user space */
2324 if ((err
= copyout((caddr_t
)&datbuf
, (caddr_t
)datptr
, sizeof(datbuf
))) != 0)
2328 if (mreply
!= NULL
) {
2329 /* called from kernel space */
2330 /* return the reply data in mbufs, so dont free them.
2331 Just free the proto info */
2332 mdata
= gbuf_cont(mproto
);
2334 gbuf_cont(mproto
) = NULL
;
2337 /* called from user space */
2341 ATDISABLE(s
, scb
->lock
);
2348 ATENABLE(s
, scb
->lock
);
2352 ATDISABLE(s
, scb
->lock
);
2353 gbuf_next(mproto
) = scb
->sess_ioc
;
2354 scb
->sess_ioc
= mproto
;
2355 ATENABLE(s
, scb
->lock
);