2 * Copyright (c) 2006 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
;
126 atlock_t aspall_lock
, asptmo_lock
;
132 return (((asp_scb_t
*)gref
->info
)->sess_ioc
? 1 : 0);
142 bzero(asp_inpC
, sizeof(asp_inpC
));
143 bzero(asp_scbQ
, sizeof(asp_scbQ
));
147 * the open routine allocates a state structure
156 * if no asp structure available, return failure
158 if ((scb
= asp_scb_alloc()) == 0)
162 * initialize the gref data structure
164 gref
->info
= (void *)scb
;
165 gref
->readable
= asp_readable
;
168 * initialize the scb data structure
171 scb
->magic_num
= 222;
172 scb
->state
= ASPSTATE_Idle
;
173 scb
->pid
= gref
->pid
;
175 scb
->session_timer
= DEF_SESS_TMO
;
176 scb
->cmd_retry
= asp_def_retry
;
177 ATDISABLE(s
, aspall_lock
);
178 if ((scb
->next_scb
= scb_used_list
) != 0)
179 scb
->next_scb
->prev_scb
= scb
;
181 ATENABLE(s
, aspall_lock
);
186 dPrintf(D_M_ASP
, D_L_INFO
, ("asp_open: pid=%d\n", scb
->pid
));
191 * the close routine frees all the data structures
198 unsigned char sock_num
;
199 asp_scb_t
*scb
, *new_scb
;
202 scb
= (asp_scb_t
*)gref
->info
;
203 dPrintf(D_M_ASP
, D_L_INFO
, ("asp_close: loc=%d\n",
204 scb
->loc_addr
.socket
));
206 if (scb
->pid
&& scb
->sess_ioc
&& (scb
->dflag
!= 1)) {
208 * send the CloseSess response to peer
210 if (gbuf_type(scb
->sess_ioc
) != MSG_PROTO
) {
211 ATDISABLE(s
, scb
->lock
);
213 scb
->sess_ioc
= gbuf_next(m
);
214 ATENABLE(s
, scb
->lock
);
215 atp_send_rsp(scb
->gref
, m
, TRUE
);
219 if (scb
->atp_state
) {
220 sock_num
= scb
->loc_addr
.socket
;
221 ATDISABLE(s
, aspall_lock
);
222 if ((scb
->dflag
!= 1) && scb
->stat_msg
) {
223 untimeout(atp_retry_req
, scb
->stat_msg
);
224 gbuf_freem(scb
->stat_msg
);
227 if (asp_scbQ
[sock_num
]->next_scb
== 0) {
228 asp_scbQ
[sock_num
] = 0;
229 asp_inpC
[sock_num
] = 0;
230 ATENABLE(s
, aspall_lock
);
231 dPrintf(D_M_ASP
, D_L_INFO
,
232 (" : atp_close(), loc=%d\n", scb
->loc_addr
.socket
));
235 asp_inpC
[sock_num
]--;
236 if (scb
== asp_scbQ
[sock_num
]) {
237 new_scb
= scb
->next_scb
;
238 new_scb
->prev_scb
= 0;
239 asp_scbQ
[sock_num
] = new_scb
;
240 new_scb
->atp_state
->atp_gref
= new_scb
->gref
;
241 new_scb
->atp_state
->pid
= new_scb
->pid
;
242 atp_inputQ
[sock_num
] = new_scb
->gref
;
244 if ((scb
->prev_scb
->next_scb
= scb
->next_scb
) != 0)
245 scb
->next_scb
->prev_scb
= scb
->prev_scb
;
248 ATENABLE(s
, aspall_lock
);
251 asp_dequeue_scb(scb
);
254 * free all allocated blocks if any
256 ATDISABLE(s
, scb
->lock
);
258 gbuf_freem(scb
->stat_msg
);
262 gbuf_freel(scb
->sess_ioc
);
266 gbuf_freel(scb
->req_msgq
);
270 scb
->rem_addr
.node
= 0;
271 ATENABLE(s
, scb
->lock
);
277 asp_untimout(asp_hangup
, scb
);
278 untimeout(asp_send_tickle_locked
, (void *)scb
); /* added for 2225395 */
281 * free the asp session control block
283 scb
->state
= ASPSTATE_Close
;
288 static char *aspStateStr(state
)
291 return ((state
==ASPSTATE_Close
)? "Close":
292 (state
==ASPSTATE_Idle
)? "Idle":
293 (state
==ASPSTATE_WaitingForGetStatusRsp
)? "GetStatusRsp":
294 (state
==ASPSTATE_WaitingForOpenSessRsp
)? "OpenSessRsp":
295 (state
==ASPSTATE_WaitingForCommandRsp
)? "CmdRsp":
296 (state
==ASPSTATE_WaitingForWriteContinue
)? "WriteCont":
297 (state
==ASPSTATE_WaitingForWriteRsp
)? "WriteRsp":
298 (state
==ASPSTATE_WaitingForWriteContinueRsp
)? "WriteContRsp":
299 (state
==ASPSTATE_WaitingForCloseSessRsp
)? "CloseSessRsp":
303 static char *aspCmdStr(aspCmd
)
306 return ((aspCmd
==ASPFUNC_CloseSess
)? "CloseSess":
307 (aspCmd
==ASPFUNC_Command
)? "Command":
308 (aspCmd
==ASPFUNC_GetStatus
)? "GetStatus":
309 (aspCmd
==ASPFUNC_OpenSess
)? "OpenSess":
310 (aspCmd
==ASPFUNC_Tickle
)? "Tickle":
311 (aspCmd
==ASPFUNC_Write
)? "Write":
312 (aspCmd
==ASPFUNC_WriteContinue
)? "WriteContinue":
313 (aspCmd
==ASPFUNC_Attention
)? "Attention":
314 (aspCmd
==ASPFUNC_CmdReply
)? "CmdReply": "unknown");
317 static char *aspIOCStr(aspIOC
)
321 (aspIOC
==ASPIOC_ClientBind
)? "ClientBind":
322 (aspIOC
==ASPIOC_CloseSession
)? "CloseSession":
323 (aspIOC
==ASPIOC_GetLocEntity
)? "GetLocEntity":
324 (aspIOC
==ASPIOC_GetRemEntity
)? "GetRemEntity":
325 (aspIOC
==ASPIOC_GetSession
)? "GetSession":
326 (aspIOC
==ASPIOC_GetStatus
)? "GetStatus":
327 (aspIOC
==ASPIOC_ListenerBind
)? "ListenerBind":
328 (aspIOC
==ASPIOC_OpenSession
)? "OpenSession":
329 (aspIOC
==ASPIOC_StatusBlock
)? "StatusBlock":
330 (aspIOC
==ASPIOC_SetPid
)? "SetPid":
331 (aspIOC
==ASPIOC_GetSessId
)? "GetSessId":
332 (aspIOC
==ASPIOC_EnableSelect
)? "EnableSelect":
333 (aspIOC
==ASPIOC_Look
)? "Look":
340 static char mbuf_str
[100];
345 "dat = %d, prot = %d, ioc = %d, err = %d, hu = %d, ack = %d, nak = %d, ctl = %d",
347 "dat = %d, prot = %d, ioc = %d, ctl = %d",
348 mbstat
.m_mtypes
[MSG_DATA
], mbstat
.m_mtypes
[MSG_PROTO
], mbstat
.m_mtypes
[MSG_IOCTL
],
350 mbstat.m_mtypes[MSG_ERROR], mbstat.m_mtypes[MSG_HANGUP], mbstat.m_mtypes[MSG_IOCACK],
351 mbstat.m_mtypes[MSG_IOCNAK],
353 mbstat
.m_mtypes
[MSG_CTL
]);
354 return(&mbuf_str
[0]);
357 void trace_beg(str
, m
)
362 gbuf_t
*mdata
, *mchain
;
365 for (i
= 0, j
= 0, mdata
= m
, mchain
= m
; mdata
; i
++) {
366 mdata
= gbuf_cont(mdata
);
367 if (!mdata
&& mchain
) {
368 mdata
= gbuf_next(mchain
);
373 dPrintf(D_M_ASP
, D_L_TRACE
,
374 ("%s: %s, m# = %d, c# = %d\n", str
, mbuf_totals(), i
, j
));
380 dPrintf(D_M_ASP
, D_L_TRACE
,
381 (" %s: %s\n", str
, mbuf_totals()));
383 #endif /* AT_MBUF_TRACE */
388 int asp_wput(gref
, m
)
393 unsigned char sockSav
, sock_num
;
394 gbuf_t
*mioc
, *mdata
;
396 asp_scb_t
*scb
, *server_scb
, *curr_scb
;
399 union asp_primitives
*primitives
;
400 asp_status_cmd_t
*status_cmd
;
401 asp_open_cmd_t
*open_cmd
;
404 scb
= (asp_scb_t
*)gref
->info
;
405 if (scb
->dflag
== 0) {
410 if (gbuf_type(m
) != MSG_IOCTL
) {
411 dPrintf(D_M_ASP
, D_L_WARNING
,
412 ("asp_wput: UNKNOWN message, type=%d\n",
419 iocbp
= (ioc_t
*)gbuf_rptr(mioc
);
421 dPrintf(D_M_ASP_LOW
, D_L_INFO
,
422 ("asp_wput: %s, loc=%d, state=%s\n",
423 aspIOCStr(iocbp
->ioc_cmd
), scb
->loc_addr
.socket
,
424 aspStateStr(scb
->state
)));
426 switch (iocbp
->ioc_cmd
) {
427 case ASPIOC_CloseSession
:
428 if ((scb
->state
== ASPSTATE_Close
) || (scb
->rem_addr
.node
== 0))
433 aw
.func
= ASPFUNC_CloseSess
;
434 aw
.param1
= scb
->sess_id
;
436 iocbp
->ioc_private
= (void *)scb
;
437 scb
->ioc_wait
= (unsigned char)(iocbp
->ioc_cmd
& 0xff);
438 iocbp
->ioc_cmd
= AT_ATP_ISSUE_REQUEST
;
439 asp_send_req(gref
, mioc
, &scb
->rem_addr
, &Retry
, &aw
,
440 0, ASPSTATE_WaitingForCloseSessRsp
, 0x01);
443 case ASPIOC_ClientBind
:
445 * open an ATP channel
447 if ((err
= atp_open(gref
, 0)) != 0) {
448 asp_iocnak(gref
, mioc
, err
);
451 scb
->atp_state
= (atp_state_t
*)gref
->info
;
452 scb
->atp_state
->pid
= scb
->pid
;
454 * bind to any available socket
457 sockSav
= scb
->dflag
;
458 if ((sock_num
= (at_socket
)atp_bind(gref
, 0, &sockSav
)) == 0) {
459 scb
->atp_state
= (atp_state_t
*)0;
461 gref
->info
= (void *)scb
;
462 asp_iocnak(gref
, mioc
, EINVAL
);
465 gref
->info
= (void *)scb
;
466 asp_dequeue_scb(scb
);
467 scb
->atp_state
->dflag
= scb
->dflag
;
468 scb
->loc_addr
.socket
= sock_num
;
469 asp_scbQ
[sock_num
] = scb
;
470 asp_inpC
[sock_num
]++;
471 atp_pidM
[sock_num
] = 0;
474 case ASPIOC_ListenerBind
:
476 * open an ATP channel
478 if ((err
= atp_open(gref
, 0)) != 0) {
479 asp_iocnak(gref
, mioc
, err
);
482 scb
->atp_state
= (atp_state_t
*)gref
->info
;
483 scb
->atp_state
->pid
= scb
->pid
;
485 * bind to any available socket
487 if ((sock_num
= (at_socket
)atp_bind(gref
, 0, 0)) == 0) {
488 scb
->atp_state
= (atp_state_t
*)0;
490 gref
->info
= (void *)scb
;
491 asp_iocnak(gref
, mioc
, EINVAL
);
494 gref
->info
= (void *)scb
;
495 asp_dequeue_scb(scb
);
496 scb
->atp_state
->dflag
= scb
->dflag
;
497 scb
->loc_addr
.socket
= sock_num
;
498 asp_scbQ
[sock_num
] = scb
;
499 asp_inpC
[sock_num
]++;
501 *(at_inet_t
*)gbuf_rptr(gbuf_cont(mioc
)) = scb
->loc_addr
;
504 case ASPIOC_GetLocEntity
:
505 if ((gbuf_cont(mioc
) == 0) || (scb
->atp_state
== 0)) {
506 asp_iocnak(gref
, mioc
, EPROTOTYPE
);
509 *(at_inet_t
*)gbuf_rptr(gbuf_cont(mioc
)) = scb
->loc_addr
;
512 case ASPIOC_GetRemEntity
:
513 if ((gbuf_cont(mioc
) == 0) || (scb
->atp_state
== 0)) {
514 asp_iocnak(gref
, mioc
, EPROTOTYPE
);
517 *(at_inet_t
*)gbuf_rptr(gbuf_cont(mioc
)) = scb
->rem_addr
;
520 case ASPIOC_GetSession
:
521 if ((mdata
= gbuf_cont(mioc
)) == 0) {
522 asp_iocnak(gref
, mioc
, EPROTOTYPE
);
525 addr
= (at_inet_t
*)gbuf_rptr(mdata
);
526 scb
->tickle_interval
= (unsigned short)addr
->node
;
527 scb
->session_timer
= addr
->net
;
528 server_scb
= asp_scbQ
[addr
->socket
];
529 /*### LD 10/28/97: changed to make sure we're not accessing a null server_scb */
530 if (server_scb
== 0) {
531 asp_iocnak(gref
, mioc
, EPROTOTYPE
);
534 if (server_scb
->sess_ioc
== 0) {
535 asp_iocnak(gref
, mioc
, EPROTOTYPE
);
540 * open an ATP channel
542 if ((err
= atp_open(gref
, 0)) != 0) {
543 gref
->info
= (void *)scb
;
544 asp_iocnak(gref
, mioc
, err
);
547 scb
->atp_state
= (atp_state_t
*)gref
->info
;
548 scb
->atp_state
->pid
= scb
->pid
;
550 * bind to any available socket
553 sockSav
= scb
->dflag
;
554 if ((sock_num
= (at_socket
)atp_bind(gref
, 0, &sockSav
)) == 0) {
556 asp_dequeue_scb(scb
);
557 ATDISABLE(s
, aspall_lock
);
559 scb
->loc_addr
.socket
= sock_num
;
560 for (curr_scb
= asp_scbQ
[sock_num
];
561 curr_scb
->next_scb
; curr_scb
= curr_scb
->next_scb
) ;
562 scb
->prev_scb
= curr_scb
;
563 curr_scb
->next_scb
= scb
;
564 scb
->atp_state
= curr_scb
->atp_state
;
565 ATENABLE(s
, aspall_lock
);
567 asp_dequeue_scb(scb
);
568 ATDISABLE(s
, aspall_lock
);
569 scb
->loc_addr
.socket
= sock_num
;
570 asp_scbQ
[sock_num
] = scb
;
571 scb
->atp_state
->dflag
= scb
->dflag
;
572 ATENABLE(s
, aspall_lock
);
574 gref
->info
= (void *)scb
;
575 asp_inpC
[sock_num
]++;
577 asp_accept(server_scb
, scb
, mdata
);
580 case ASPIOC_GetStatus
:
581 if ((mdata
= gbuf_cont(mioc
)) == 0) {
582 asp_iocnak(gref
, mioc
, EINVAL
);
586 status_cmd
= (asp_status_cmd_t
*)gbuf_rptr(mdata
);
587 aw
.func
= ASPFUNC_GetStatus
;
590 scb
->ioc_wait
= (unsigned char)(iocbp
->ioc_cmd
& 0xff);
591 iocbp
->ioc_cmd
= AT_ATP_ISSUE_REQUEST_DEF
;
592 /* bms: make sure this is an ALO request */
593 asp_send_req(gref
, mioc
, &status_cmd
->SLSEntityIdentifier
,
594 &status_cmd
->Retry
, &aw
, 0, ASPSTATE_WaitingForGetStatusRsp
, 0xff);
598 case ASPIOC_OpenSession
:
599 if ((mdata
= gbuf_cont(mioc
)) == 0) {
600 asp_iocnak(gref
, mioc
, EINVAL
);
604 open_cmd
= (asp_open_cmd_t
*)gbuf_rptr(mdata
);
605 scb
->svc_addr
= open_cmd
->SLSEntityIdentifier
;
606 scb
->rem_addr
= scb
->svc_addr
;
607 scb
->rem_node
= scb
->rem_addr
.node
;
608 scb
->rem_addr
.node
= 0;
609 scb
->tickle_interval
= open_cmd
->TickleInterval
;
610 scb
->session_timer
= open_cmd
->SessionTimer
;
611 aw
.func
= ASPFUNC_OpenSess
;
612 aw
.param1
= scb
->loc_addr
.socket
;
613 aw
.param2
= ASP_Version
;
614 scb
->ioc_wait
= (unsigned char)(iocbp
->ioc_cmd
& 0xff);
615 iocbp
->ioc_cmd
= AT_ATP_ISSUE_REQUEST_DEF
;
616 asp_send_req(gref
, mioc
, &open_cmd
->SLSEntityIdentifier
,
617 &open_cmd
->Retry
, &aw
, 1, ASPSTATE_WaitingForOpenSessRsp
, 0x01);
621 case ASPIOC_StatusBlock
:
623 * save the server status block
626 gbuf_freem(scb
->stat_msg
);
627 scb
->stat_msg
= gbuf_cont(mioc
);
631 /* *** Does scb->pid get used in a packet header,
632 and if so is it in ASP, or in ATP?
633 If not, do we need this call for anything?
634 (cap does currently use it in _ANS code.)
637 if (gbuf_cont(mioc
) == 0) {
638 asp_iocnak(gref
, mioc
, EINVAL
);
641 scb
->pid
= *(int *)gbuf_rptr(gbuf_cont(mioc
));
644 case ASPIOC_GetSessId
:
645 if (gbuf_cont(mioc
) == 0) {
646 asp_iocnak(gref
, mioc
, EINVAL
);
649 *(gref_t
**)gbuf_rptr(gbuf_cont(mioc
)) = gref
;
653 if (gbuf_cont(mioc
) == 0) {
654 asp_iocnak(gref
, mioc
, EINVAL
);
658 primitives
= (union asp_primitives
*)gbuf_rptr(scb
->sess_ioc
);
659 if (primitives
->Primitive
== ASPFUNC_CmdReply
)
660 *(int *)gbuf_rptr(gbuf_cont(mioc
)) = 0;
662 *(int *)gbuf_rptr(gbuf_cont(mioc
)) = 1;
664 *(int *)gbuf_rptr(gbuf_cont(mioc
)) = -1;
667 case DDP_IOC_GET_CFG
:
669 struct atp_state
*atp
= (struct atp_state
*)gref
->info
;
671 atp
= (struct atp_state
*)atp
->atp_msgq
;
673 if (gbuf_cont(mioc
) == 0) {
674 asp_iocnak(gref
, mioc
, EINVAL
);
677 /* *** borrowed from ddp_proto.c to handle DDP_IOC_GET_CFG
679 scb
->state
= ASPSTATE_Idle
;
681 /* *** was ddp_get_cfg() *** */
683 (ddp_addr_t
*)gbuf_rptr(gbuf_cont(mioc
));
684 cfgp
->inet
.net
= ifID_home
->ifThisNode
.s_net
;
685 cfgp
->inet
.node
= ifID_home
->ifThisNode
.s_node
;
686 cfgp
->inet
.socket
= atp
->atp_socket_no
;
687 cfgp
->ddptype
= DDP_ATP
;
689 gbuf_wset(gbuf_cont(mioc
), sizeof(at_inet_t
));
694 asp_iocnak(gref
, mioc
, EINVAL
);
698 asp_iocack(gref
, mioc
);
703 * send request routine
706 asp_send_req(gref
, mioc
, dest
, retry
, awp
, xo
, state
, bitmap
)
714 unsigned char bitmap
;
719 struct atp_set_default
*sd
;
722 struct atpBDS
*atpBDS
;
723 asp_scb_t
*scb
= (asp_scb_t
*)gref
->info
;
726 * allocate an ATP buffer for the request
728 if ((gbuf_cont(mioc
) = gbuf_alloc(aspCMDsize
, PRI_MED
)) == 0) {
729 if (awp
->func
== ASPFUNC_Tickle
)
732 asp_iocnak(gref
, mioc
, ENOBUFS
);
733 dPrintf(D_M_ASP
, D_L_WARNING
,
734 ("asp_send_req: ENOBUFS, loc=%d\n", scb
->loc_addr
.socket
));
738 mdata
= gbuf_cont(mioc
);
739 iocbp
= (ioc_t
*)gbuf_rptr(mioc
);
744 atpBDS
= (struct atpBDS
*)gbuf_rptr(mdata
);
745 gbuf_wset(mdata
,atpBDSsize
);
746 for (i
=0; i
< ATP_TRESP_MAX
; i
++) {
747 *(unsigned long *)atpBDS
[i
].bdsBuffAddr
= 1;
748 *(unsigned short *)atpBDS
[i
].bdsBuffSz
= ATP_DATA_SIZE
;
750 sd
= (struct atp_set_default
*)gbuf_wptr(mdata
);
751 gbuf_winc(mdata
,sizeof(struct atp_set_default
));
752 sd
->def_retries
= (retry
->retries
== -1) ?
753 ATP_INFINITE_RETRIES
: retry
->retries
;
754 sd
->def_rate
= retry
->interval
*TICKS_PER_SEC
;
755 sd
->def_BDSlen
= atpBDSsize
;
756 ddp
= (at_ddp_t
*)gbuf_wptr(mdata
);
757 NET_ASSIGN(ddp
->src_net
, scb
->loc_addr
.net
);
758 ddp
->src_node
= scb
->loc_addr
.node
;
759 NET_ASSIGN(ddp
->dst_net
, dest
->net
);
760 ddp
->dst_node
= dest
->node
;
761 ddp
->dst_socket
= dest
->socket
;
762 UAS_ASSIGN(ddp
->checksum
, 0);
763 atp
= ATP_ATP_HDR(gbuf_wptr(mdata
));
766 atp
->bitmap
= bitmap
;
767 gbuf_winc(mdata
,TOTAL_ATP_HDR_SIZE
);
768 *(asp_word_t
*)atp
->user_bytes
= *awp
;
769 iocbp
->ioc_count
= gbuf_len(mdata
);
776 dPrintf(D_M_ASP
, D_L_INFO
,
777 ("asp_send_req: %s, loc=%d, rem= %d, len=%d, state=%s\n",
778 aspCmdStr(awp
->func
),
779 scb
->loc_addr
.socket
, ddp
->dst_socket
, iocbp
->ioc_count
,
780 aspStateStr(scb
->state
)));
782 atp_send_req(gref
, mioc
);
787 * send tickle routine - locked version
790 asp_send_tickle_locked(scb
)
794 asp_send_tickle((asp_scb_t
*)scb
);
800 * send tickle routine
813 * make sure the connection is still there
815 if (scb
->rem_addr
.node
== 0) {
819 if ((mioc
= gbuf_alloc(sizeof(ioc_t
), PRI_HI
)) == 0) {
820 dPrintf(D_M_ASP
, D_L_WARNING
,
821 ("asp_send_tickle: ENOBUFS 0, loc=%d, rem=%d\n",
822 scb
->loc_addr
.socket
,scb
->rem_addr
.socket
));
823 timeout(asp_send_tickle_locked
, (void *)scb
, 10);
826 gbuf_wset(mioc
,sizeof(ioc_t
));
827 gbuf_set_type(mioc
, MSG_IOCTL
);
829 dest
= scb
->svc_addr
.node
?
830 (at_inet_t
*)&scb
->svc_addr
: (at_inet_t
*)&scb
->rem_addr
;
831 retry
.interval
= scb
->tickle_interval
;
834 aw
.func
= ASPFUNC_Tickle
;
835 aw
.param1
= scb
->sess_id
;
837 ((ioc_t
*)gbuf_rptr(mioc
))->ioc_cr
= (void *)scb
;
838 ((ioc_t
*)gbuf_rptr(mioc
))->ioc_cmd
= AT_ATP_ISSUE_REQUEST_TICKLE
;
840 if (asp_send_req(scb
->gref
, mioc
, dest
, &retry
, &aw
, 0, scb
->state
, 0)) {
841 dPrintf(D_M_ASP
, D_L_WARNING
,
842 ("asp_send_tickle: ENOBUFS 1, loc=%d, rem=%d\n",
843 scb
->loc_addr
.socket
,scb
->rem_addr
.socket
));
845 timeout(asp_send_tickle_locked
, (void *)scb
, 10);
851 * accept connection routine
854 asp_accept(scb
, sess_scb
, m
)
866 mdata
= scb
->sess_ioc
;
867 ddp
= (at_ddp_t
*)gbuf_rptr(mdata
);
868 atp
= (at_atp_t
*)(gbuf_rptr(mdata
) + DDP_X_HDR_SIZE
);
869 rem_addr
.net
= NET_VALUE(ddp
->src_net
);
870 rem_addr
.node
= ddp
->src_node
;
871 rem_addr
.socket
= ddp
->src_socket
;
872 awp
= (asp_word_t
*)atp
->user_bytes
;
874 sess_scb
->loc_addr
.net
= NET_VALUE(ddp
->dst_net
);
875 sess_scb
->loc_addr
.node
= ddp
->dst_node
;
876 NET_ASSIGN(ddp
->src_net
, sess_scb
->loc_addr
.net
);
877 ddp
->src_node
= sess_scb
->loc_addr
.node
;
878 NET_ASSIGN(ddp
->dst_net
, rem_addr
.net
);
879 ddp
->dst_node
= rem_addr
.node
;
880 ddp
->dst_socket
= rem_addr
.socket
;
882 sess_scb
->sess_id
= sess_scb
->loc_addr
.socket
;
883 sess_scb
->rem_socket
= rem_addr
.socket
;
884 sess_scb
->rem_addr
= rem_addr
;
885 sess_scb
->rem_addr
.socket
= awp
->param1
;
886 sess_scb
->reply_socket
= sess_scb
->rem_addr
.socket
;
887 awp
->func
= sess_scb
->loc_addr
.socket
;
888 awp
->param1
= sess_scb
->sess_id
;
891 ATDISABLE(s
, scb
->lock
);
892 scb
->sess_ioc
= gbuf_next(mdata
);
893 ATENABLE(s
, scb
->lock
);
894 gbuf_next(mdata
) = 0;
895 asp_timout(asp_hangup
, sess_scb
, sess_scb
->session_timer
);
896 atp_send_rsp(scb
->gref
, mdata
, TRUE
);
897 asp_send_tickle(sess_scb
);
898 dPrintf(D_M_ASP
, D_L_INFO
,
899 ("asp_accept: ACCEPT connect request, loc=%d, rem=%x.%x.%d\n",
900 sess_scb
->loc_addr
.socket
,
901 sess_scb
->rem_addr
.net
,
902 sess_scb
->rem_addr
.node
,sess_scb
->rem_addr
.socket
));
906 * timer routine - locked version
908 void asp_clock_locked(arg
)
926 ATDISABLE(s
, asptmo_lock
);
928 scb_tmo_list
->tmo_delta
--;
929 while (((scb
= scb_tmo_list
) != 0) && (scb_tmo_list
->tmo_delta
== 0)) {
930 if ((scb_tmo_list
= scb
->next_tmo
) != 0)
931 scb_tmo_list
->prev_tmo
= 0;
932 if ((tmo_func
= scb
->tmo_func
) != 0) {
934 ATENABLE(s
, asptmo_lock
);
936 ATDISABLE(s
, asptmo_lock
);
939 ATENABLE(s
, asptmo_lock
);
941 if (++scb_tmo_cnt
== 0) scb_tmo_cnt
++;
942 timeout(asp_clock_locked
, (void *)arg
, (1<<SESS_TMO_RES
)*TICKS_PER_SEC
);
950 asp_ack_reply(gref
, mioc
)
951 register gref_t
*gref
;
952 register gbuf_t
*mioc
;
955 int len
, msize
, nbds
;
956 register gbuf_t
*mdata
, *m
, *mx
;
957 struct atpBDS
*atpBDS
;
960 register asp_scb_t
*scb
, *sess_scb
;
961 register ioc_t
*iocbp
;
962 register asp_word_t
*awp
;
963 register asp_command_ind_t
*command_ind
;
964 register asp_cmdreply_ind_t
*cmdreply_ind
;
967 iocbp
= (ioc_t
*)gbuf_rptr(mioc
);
969 if (iocbp
->ioc_cmd
== AT_ATP_ISSUE_REQUEST_TICKLE
) {
971 * ignore the ack for the tickle request
973 scb
= (asp_scb_t
*)iocbp
->ioc_cr
;
974 scb
->tickle_tid
= (unsigned short)iocbp
->ioc_rval
;
979 scb
= (asp_scb_t
*)gref
->info
;
985 if (iocbp
->ioc_cmd
== AT_ATP_GET_POLL
) {
987 * if no data, just drop the request
989 if ((mdata
= gbuf_cont(mioc
)) == 0) {
994 gbuf_set_type(mioc
, MSG_IOCTL
);
995 ddp
= (at_ddp_t
*)gbuf_rptr(mdata
);
996 gbuf_rinc(mdata
,DDP_X_HDR_SIZE
);
997 atp
= (at_atp_t
*)gbuf_rptr(mdata
);
998 gbuf_rinc(mdata
,ATP_HDR_SIZE
);
999 rem_addr
.net
= NET_VALUE(ddp
->src_net
);
1000 rem_addr
.node
= ddp
->src_node
;
1001 rem_addr
.socket
= ddp
->src_socket
;
1002 awp
= (asp_word_t
*)atp
->user_bytes
;
1004 if (scb
->next_scb
) {
1006 * find the responsible scb
1008 if ((scb
= asp_find_scb(scb
->loc_addr
.socket
, &rem_addr
)) == 0) {
1013 dPrintf(D_M_ASP
, D_L_INFO
,
1014 ("asp_ack_reply: %s, loc=%d, rem=%x.%x.%d\n",
1015 aspCmdStr(awp
->func
),scb
->loc_addr
.socket
,
1016 NET_VALUE(ddp
->src_net
) ,ddp
->src_node
,ddp
->src_socket
));
1018 if (scb
->rem_addr
.node
)
1019 asp_untimout(asp_hangup
, scb
);
1021 switch (awp
->func
) {
1022 case ASPFUNC_GetStatus
:
1024 * ignore if this is not a server socket
1027 if ((scb
->dflag
!= 1) || (scb
->stat_msg
1028 && ((mx
= gbuf_dupb(scb
->stat_msg
)) == 0)))
1033 * send the status block
1035 if (gbuf_cont(mdata
)) {
1036 gbuf_freem(gbuf_cont(mdata
));
1037 gbuf_cont(mdata
) = 0;
1039 gbuf_rdec(mdata
,TOTAL_ATP_HDR_SIZE
);
1040 if ((m
= gbuf_alloc( (TOTAL_ATP_HDR_SIZE
+atpBDSsize
), PRI_MED
)) == 0) {
1045 bcopy(gbuf_rptr(mdata
), gbuf_rptr(m
), TOTAL_ATP_HDR_SIZE
);
1048 ddp
= (at_ddp_t
*)gbuf_rptr(mdata
);
1049 gbuf_wset(mdata
,DDP_X_HDR_SIZE
);
1050 atp
= (at_atp_t
*)gbuf_wptr(mdata
);
1051 gbuf_winc(mdata
,ATP_HDR_SIZE
);
1052 awp
= (asp_word_t
*)atp
->user_bytes
;
1053 NET_NET(ddp
->src_net
, ddp
->dst_net
);
1054 ddp
->src_node
= ddp
->dst_node
;
1055 NET_ASSIGN(ddp
->dst_net
, rem_addr
.net
);
1056 ddp
->dst_node
= rem_addr
.node
;
1057 ddp
->dst_socket
= rem_addr
.socket
;
1058 UAS_ASSIGN(ddp
->checksum
, 0);
1059 atpBDS
= (struct atpBDS
*)gbuf_wptr(mdata
);
1060 msize
= mx
? gbuf_msgsize(mx
) : 0;
1061 for (nbds
=0; (nbds
< ATP_TRESP_MAX
) && (msize
> 0); nbds
++) {
1062 len
= msize
< ATP_DATA_SIZE
? msize
: ATP_DATA_SIZE
;
1063 msize
-= ATP_DATA_SIZE
;
1064 *(long *)atpBDS
[nbds
].bdsUserData
= 0;
1065 UAL_ASSIGN(atpBDS
[nbds
].bdsBuffAddr
, 1);
1066 UAS_ASSIGN(atpBDS
[nbds
].bdsBuffSz
, len
);
1068 UAS_ASSIGN(atpBDS
[0].bdsDataSz
, nbds
);
1069 gbuf_winc(mdata
,atpBDSsize
);
1070 gbuf_cont(mdata
) = mx
;
1071 atp_send_rsp(gref
, mdata
, FALSE
);
1074 case ASPFUNC_OpenSess
:
1076 * ignore if server is not ready
1078 if ((scb
->dflag
!= 1) || (scb
->stat_msg
== 0))
1082 if (gbuf_cont(mdata
)) {
1083 gbuf_freem(gbuf_cont(mdata
));
1084 gbuf_cont(mdata
) = 0;
1086 gbuf_rdec(mdata
,TOTAL_ATP_HDR_SIZE
);
1087 gbuf_wset(mdata
,TOTAL_ATP_HDR_SIZE
);
1088 if (awp
->param2
!= ASP_Version
) {
1090 * bad version number, send the OpenSession response
1094 awp
->param2
= (unsigned short)ASPERR_BadVersNum
;
1095 dPrintf(D_M_ASP
, D_L_INFO
,
1097 ASPERR_BadVersNum
));
1099 NET_NET(ddp
->src_net
, ddp
->dst_net
);
1100 ddp
->src_node
= ddp
->dst_node
;
1101 NET_ASSIGN(ddp
->dst_net
, rem_addr
.net
);
1102 ddp
->dst_node
= rem_addr
.node
;
1103 ddp
->dst_socket
= rem_addr
.socket
;
1104 atp_send_rsp(gref
, mdata
, FALSE
);
1109 * queue the connection request
1111 ATDISABLE(s
, scb
->lock
);
1112 gbuf_next(mdata
) = 0;
1113 if ((m
= scb
->sess_ioc
) == 0) {
1114 scb
->sess_ioc
= mdata
;
1116 wakeup(&scb
->event
);
1118 atalk_notify_sel(gref
);
1120 while (gbuf_next(m
))
1122 gbuf_next(m
) = mdata
;
1124 ATENABLE(s
, scb
->lock
);
1125 dPrintf(D_M_ASP
, D_L_INFO
,
1126 (" : QUEUE connect request\n"));
1130 case ASPFUNC_Command
:
1132 if ( (scb
->sess_id
!= awp
->param1
)
1133 || (scb
->rcv_seq_num
!= awp
->param2
)
1134 || BAD_REMADDR(rem_addr
) ) {
1136 sprintf(era
,"%d.%d", scb
->rem_addr
.node
,scb
->rem_addr
.socket
);
1137 sprintf(ra
,"%d.%d", rem_addr
.node
,rem_addr
.socket
);
1138 dPrintf(D_M_ASP
, D_L_WARNING
,
1139 (" : DROP, id=%d,esn=%d,sn=%d,erem=%s,rem=%s\n",
1140 scb
->sess_id
,scb
->rcv_seq_num
,awp
->param2
,era
,ra
));
1141 gbuf_cont(mioc
) = 0;
1142 gbuf_rdec(mdata
,TOTAL_ATP_HDR_SIZE
);
1143 atp_drop_req(gref
, mdata
);
1146 scb
->reply_socket
= rem_addr
.socket
;
1147 if (awp
->func
== ASPFUNC_Write
)
1148 scb
->wrt_seq_num
= scb
->rcv_seq_num
;
1149 NEXT_SEQ_NUM(scb
->rcv_seq_num
);
1150 gbuf_set_type(mioc
, MSG_PROTO
);
1151 gbuf_wset(mioc
,sizeof(asp_command_ind_t
));
1152 command_ind
= (asp_command_ind_t
*)gbuf_rptr(mioc
);
1153 command_ind
->Primitive
= (int)awp
->func
;
1154 command_ind
->ReqRefNum
=
1155 *(unsigned short *)atp
->tid
;
1156 command_ind
->ReqType
= awp
->func
;
1158 mdata
= gbuf_strip(mdata
);
1159 gbuf_cont(mioc
) = mdata
;
1160 ATDISABLE(s
, scb
->lock
);
1161 if (scb
->req_flag
) {
1162 if ((mx
= scb
->req_msgq
) != 0) {
1163 while (gbuf_next(mx
))
1165 gbuf_next(mx
) = mioc
;
1167 scb
->req_msgq
= mioc
;
1168 ATENABLE(s
, scb
->lock
);
1171 ATENABLE(s
, scb
->lock
);
1172 asp_putnext(scb
->gref
, mioc
);
1176 case ASPFUNC_WriteContinue
:
1177 if ( (scb
->sess_id
!= awp
->param1
)
1178 || (scb
->snd_seq_num
!= awp
->param2
)
1179 || BAD_REMADDR(rem_addr
) ) {
1182 scb
->reply_socket
= rem_addr
.socket
;
1183 gbuf_set_type(mioc
, MSG_PROTO
);
1184 gbuf_wset(mioc
,sizeof(asp_command_ind_t
));
1185 command_ind
= (asp_command_ind_t
*)gbuf_rptr(mioc
);
1186 command_ind
->Primitive
= (int)awp
->func
;
1187 command_ind
->ReqRefNum
=
1188 *(unsigned short *)atp
->tid
;
1189 command_ind
->ReqType
= awp
->func
;
1191 mdata
= gbuf_strip(mdata
);
1192 gbuf_cont(mioc
) = mdata
;
1193 asp_putnext(scb
->gref
, mioc
);
1196 case ASPFUNC_Tickle
:
1197 if (scb
->stat_msg
) {
1198 sess_scb
= asp_scbQ
[awp
->param1
];
1199 if (sess_scb
&& sess_scb
->next_scb
)
1200 sess_scb
= asp_find_scb(
1201 sess_scb
->loc_addr
.socket
, &rem_addr
);
1203 if (sess_scb
->rem_addr
.node
)
1204 asp_untimout(asp_hangup
, sess_scb
);
1205 if (sess_scb
->rem_addr
.node
)
1206 asp_timout(asp_hangup
, sess_scb
, sess_scb
->session_timer
);
1209 dPrintf(D_M_ASP
, D_L_INFO
,
1210 (" : Tickle, %d -> %d, id=%d\n",
1211 ddp
->src_socket
,ddp
->dst_socket
,awp
->param1
));
1214 case ASPFUNC_CloseSess
:
1215 if ( (scb
->sess_id
!= awp
->param1
)
1216 || (scb
->state
== ASPSTATE_Close
)
1217 || (scb
->state
== ASPSTATE_WaitingForCloseSessRsp
)
1218 || (scb
->rem_addr
.net
!= rem_addr
.net
)
1219 || (scb
->rem_addr
.node
!= rem_addr
.node
) ) {
1220 dPrintf(D_M_ASP
, D_L_INFO
,
1221 (" : CLOSE retry, loc=%d, rem=%x.%x.%d\n",
1222 scb
->loc_addr
.socket
,
1225 scb
->rem_addr
.socket
));
1232 * build the CloseSess response to be sent to peer
1233 * when the session is closed by the user.
1235 if (gbuf_cont(mdata
)) {
1236 gbuf_freem(gbuf_cont(mdata
));
1237 gbuf_cont(mdata
) = 0;
1239 gbuf_rdec(mdata
,TOTAL_ATP_HDR_SIZE
);
1240 gbuf_wset(mdata
,TOTAL_ATP_HDR_SIZE
);
1241 NET_NET(ddp
->src_net
, ddp
->dst_net
);
1242 ddp
->src_node
= ddp
->dst_node
;
1243 NET_ASSIGN(ddp
->dst_net
, rem_addr
.net
);
1244 ddp
->dst_node
= rem_addr
.node
;
1245 ddp
->dst_socket
= rem_addr
.socket
;
1249 dPrintf(D_M_ASP
,D_L_INFO
,
1250 (" : CLOSE, loc=%d, rem=%x.%x.%d\n",
1251 scb
->loc_addr
.socket
,
1254 scb
->rem_addr
.socket
));
1256 gbuf_next(mdata
) = 0;
1257 ATDISABLE(s
, scb
->lock
);
1259 gbuf_freel(scb
->sess_ioc
);
1260 scb
->sess_ioc
= mdata
;
1261 scb
->state
= ASPSTATE_Close
;
1262 ATENABLE(s
, scb
->lock
);
1265 * notify upstream of the CloseSess from peer
1270 case ASPFUNC_Attention
:
1271 if ( (scb
->sess_id
!= awp
->param1
)
1272 || (scb
->rem_addr
.net
!= rem_addr
.net
)
1273 || (scb
->rem_addr
.node
!= rem_addr
.node
) ) {
1276 gbuf_set_type(mioc
, MSG_PROTO
);
1277 gbuf_wset(mioc
,sizeof(asp_command_ind_t
));
1278 command_ind
= (asp_command_ind_t
*)gbuf_rptr(mioc
);
1279 command_ind
->Primitive
= (int)awp
->func
;
1280 command_ind
->ReqRefNum
=
1281 *(unsigned short *)atp
->tid
;
1282 command_ind
->ReqType
= awp
->func
;
1283 scb
->attn_tid
= *(unsigned short *)atp
->tid
;
1285 gbuf_rdec(mdata
,2); /* attention code */
1287 mdata
= gbuf_strip(mdata
);
1288 gbuf_cont(mioc
) = mdata
;
1289 asp_putnext(scb
->gref
, mioc
);
1293 dPrintf(D_M_ASP
, D_L_WARNING
,
1294 (" : UNKNOWN func, func=%d\n",
1301 else if (iocbp
->ioc_cmd
== AT_ATP_REQUEST_COMPLETE
) {
1302 if (scb
->next_scb
) {
1304 * find the responsible scb
1306 scb
= (asp_scb_t
*)iocbp
->ioc_private
;
1307 if ((scb
== 0) || (scb
->magic_num
!= 222)) {
1308 dPrintf(D_M_ASP
, D_L_ERROR
,
1309 ("asp_ack_reply: CAN'T find scb 1\n"));
1314 dPrintf(D_M_ASP
, D_L_INFO
,
1315 ("asp_ack_reply: RSP, loc=%d, rem=%x.%x.%d, state=%s\n",
1316 scb
->loc_addr
.socket
,
1319 scb
->rem_addr
.socket
,
1320 aspStateStr(scb
->state
)));
1322 switch (scb
->state
) {
1323 case ASPSTATE_Close
:
1325 scb
->rem_addr
.node
= 0;
1327 ATDISABLE(s
, scb
->lock
);
1329 wakeup(&scb
->event
);
1331 atalk_notify_sel(gref
);
1332 ATENABLE(s
, scb
->lock
);
1335 case ASPSTATE_WaitingForGetStatusRsp
:
1337 scb
->state
= ASPSTATE_Idle
;
1338 mx
= gbuf_cont(mioc
);
1339 gbuf_cont(mioc
) = 0;
1340 mdata
= gbuf_cont(mx
);
1342 iocbp
->ioc_cmd
= ASPIOC_GetStatus
;
1343 iocbp
->ioc_count
= 0;
1344 iocbp
->ioc_rval
= mdata
? gbuf_msgsize(mdata
) : 0;
1346 atalk_putnext(gref
, mioc
);
1347 atalk_putnext(gref
, mdata
);
1350 case ASPSTATE_WaitingForOpenSessRsp
:
1352 scb
->state
= ASPSTATE_Idle
;
1353 mx
= gbuf_cont(mioc
);
1354 gbuf_cont(mioc
) = 0;
1355 if (gbuf_cont(mx
)) {
1356 gbuf_freem(gbuf_cont(mx
));
1359 iocbp
->ioc_cmd
= ASPIOC_OpenSession
;
1360 iocbp
->ioc_rval
= 0;
1361 iocbp
->ioc_count
= 0;
1362 atpBDS
= (struct atpBDS
*)gbuf_rptr(mx
);
1363 awp
= (asp_word_t
*)atpBDS
->bdsUserData
;
1366 asp_iocnak(gref
, mioc
, ECONNREFUSED
);
1368 scb
->rem_addr
.node
= scb
->rem_node
;
1369 scb
->rem_addr
.socket
= awp
->func
;
1370 /* bms: need to set the reply_socket for client side too.
1371 This makes ALO atten replies sent by the client work. */
1372 scb
->reply_socket
= scb
->rem_addr
.socket
;
1373 scb
->sess_id
= awp
->param1
;
1375 atalk_putnext(gref
, mioc
);
1376 asp_timout(asp_hangup
, scb
, scb
->session_timer
);
1377 asp_send_tickle(scb
);
1378 dPrintf(D_M_ASP
, D_L_INFO
,
1379 ("asp_ack_reply: CONNECT, loc=%d, rem=%x.%x.%d\n",
1380 scb
->loc_addr
.socket
,
1383 scb
->rem_addr
.socket
));
1387 case ASPSTATE_WaitingForCommandRsp
:
1388 case ASPSTATE_WaitingForWriteRsp
:
1389 case ASPSTATE_WaitingForWriteContinueRsp
:
1390 if (scb
->rem_addr
.node
)
1391 asp_untimout(asp_hangup
, scb
);
1392 NEXT_SEQ_NUM(scb
->snd_seq_num
);
1393 scb
->state
= ASPSTATE_Idle
;
1394 gbuf_set_type(mioc
, MSG_PROTO
);
1395 mx
= gbuf_cont(mioc
);
1396 mdata
= gbuf_cont(mx
);
1397 gbuf_cont(mioc
) = mdata
;
1398 atpBDS
= (struct atpBDS
*)gbuf_rptr(mx
);
1399 cmdreply_ind
= (asp_cmdreply_ind_t
*)gbuf_rptr(mioc
);
1400 cmdreply_ind
->Primitive
= ASPFUNC_CmdReply
;
1401 cmdreply_ind
->CmdResult
= *(int *)atpBDS
->bdsUserData
;
1402 gbuf_wset(mioc
,sizeof(asp_cmdreply_ind_t
));
1404 asp_putnext(scb
->gref
, mioc
);
1407 case ASPSTATE_WaitingForCloseSessRsp
:
1409 scb
->state
= ASPSTATE_Close
;
1410 scb
->rem_addr
.node
= 0;
1411 iocbp
->ioc_cmd
= ASPIOC_CloseSession
;
1412 iocbp
->ioc_rval
= 0;
1413 if (gbuf_cont(mioc
)) {
1414 gbuf_freem(gbuf_cont(mioc
));
1415 gbuf_cont(mioc
) = 0;
1417 atalk_putnext(scb
->gref
, mioc
);
1418 atp_cancel_req(scb
->gref
, (unsigned int)scb
->tickle_tid
);
1419 scb
->tickle_tid
= 0;
1423 dPrintf(D_M_ASP
, D_L_WARNING
,
1424 (" : UNKNOWN state, state=%s\n",
1425 aspStateStr(scb
->state
)));
1431 if (scb
->next_scb
) {
1433 * find the responsible scb
1435 scb
= (asp_scb_t
*)iocbp
->ioc_cr
;
1436 if ((scb
== 0) || (scb
->magic_num
!= 222)) {
1437 dPrintf(D_M_ASP
, D_L_ERROR
,
1438 ("asp_ack_reply: CAN'T find scb 2\n"));
1444 switch (scb
->state
) {
1445 case ASPSTATE_Close
:
1446 scb
->rem_addr
.node
= 0;
1455 if (scb
->rem_addr
.node
)
1456 asp_timout(asp_hangup
, scb
, scb
->session_timer
);
1457 } /* asp_ack_reply */
1463 asp_nak_reply(gref
, mioc
)
1464 register gref_t
*gref
;
1465 register gbuf_t
*mioc
;
1467 register asp_scb_t
*scb
;
1468 register ioc_t
*iocbp
;
1470 iocbp
= (ioc_t
*)gbuf_rptr(mioc
);
1472 if (iocbp
->ioc_cmd
== AT_ATP_ISSUE_REQUEST_TICKLE
) {
1474 * no tickle, close session
1476 scb
= (asp_scb_t
*)iocbp
->ioc_cr
;
1479 dPrintf(D_M_ASP
, D_L_WARNING
,
1480 ("tickle_nak: loc=%d, rem=%x.%x.%d, state=%s\n",
1481 scb
->loc_addr
.socket
,
1484 scb
->rem_addr
.socket
,
1485 aspStateStr(scb
->state
)));
1490 scb
= (asp_scb_t
*)gref
->info
;
1496 if (iocbp
->ioc_cmd
== AT_ATP_REQUEST_COMPLETE
) {
1497 if (scb
->next_scb
) {
1499 * find the responsible scb
1501 scb
= (asp_scb_t
*)iocbp
->ioc_private
;
1502 if ((scb
== 0) || (scb
->magic_num
!= 222)) {
1503 dPrintf(D_M_ASP
, D_L_ERROR
,
1504 ("asp_nak_reply: CAN'T find scb 1\n"));
1509 dPrintf(D_M_ASP
, D_L_WARNING
,
1510 ("asp_nak_reply: RSP, loc=%d, rem=%x.%x.%d, state=%s\n",
1511 scb
->loc_addr
.socket
,
1514 scb
->rem_addr
.socket
,
1515 aspStateStr(scb
->state
)));
1517 switch (scb
->state
) {
1518 case ASPSTATE_WaitingForGetStatusRsp
:
1519 iocbp
->ioc_cmd
= ASPIOC_GetStatus
;
1522 case ASPSTATE_WaitingForOpenSessRsp
:
1523 iocbp
->ioc_cmd
= ASPIOC_OpenSession
;
1526 case ASPSTATE_WaitingForCommandRsp
:
1527 case ASPSTATE_WaitingForWriteRsp
:
1528 case ASPSTATE_WaitingForWriteContinueRsp
:
1529 scb
->state
= ASPSTATE_Idle
;
1531 /* last remaining use of MSG_ERROR */
1532 gbuf_set_type(mioc
, MSG_ERROR
);
1533 *gbuf_rptr(mioc
) = (u_char
)EPROTOTYPE
;
1535 if (gbuf_cont(mioc
)) {
1536 gbuf_freem(gbuf_cont(mioc
));
1537 gbuf_cont(mioc
) = 0;
1540 asp_putnext(scb
->gref
, mioc
);
1543 case ASPSTATE_WaitingForCloseSessRsp
:
1544 scb
->state
= ASPSTATE_Close
;
1546 case ASPSTATE_Close
: /* new for PR-2296832 */
1547 scb
->rem_addr
.node
= 0;
1548 iocbp
->ioc_cmd
= ASPIOC_CloseSession
;
1549 iocbp
->ioc_rval
= 0;
1550 if (gbuf_cont(mioc
)) {
1551 gbuf_freem(gbuf_cont(mioc
));
1552 gbuf_cont(mioc
) = 0;
1554 gbuf_set_type(mioc
, MSG_IOCACK
);
1555 atalk_putnext(scb
->gref
, mioc
);
1562 scb
->state
= ASPSTATE_Idle
;
1563 atalk_putnext(gref
, mioc
);
1567 if (scb
->next_scb
) {
1569 * find the responsible scb
1571 scb
= (asp_scb_t
*)iocbp
->ioc_cr
;
1572 if ((scb
== 0) || (scb
->magic_num
!= 222)) {
1573 dPrintf(D_M_ASP
, D_L_ERROR
,
1574 ("asp_nak_reply: CAN'T find scb 2\n"));
1580 switch (scb
->state
) {
1581 case ASPSTATE_Close
:
1582 scb
->rem_addr
.node
= 0;
1588 } /* asp_nak_reply */
1591 * delete scb from the use list
1594 asp_dequeue_scb(scb
)
1599 ATDISABLE(s
, aspall_lock
);
1600 if (scb
== scb_used_list
) {
1601 if ((scb_used_list
= scb
->next_scb
) != 0)
1602 scb
->next_scb
->prev_scb
= 0;
1604 if ((scb
->prev_scb
->next_scb
= scb
->next_scb
) != 0)
1605 scb
->next_scb
->prev_scb
= scb
->prev_scb
;
1607 ATENABLE(s
, aspall_lock
);
1616 StaticProc asp_scb_t
*
1617 asp_find_scb(sock_num
, rem_addr
)
1618 unsigned char sock_num
;
1619 at_inet_t
*rem_addr
;
1623 asp_scb_t
*alt_scb
= 0;
1625 ATDISABLE(s
, aspall_lock
);
1626 for (scb
= asp_scbQ
[sock_num
]; scb
; scb
= scb
->next_scb
) {
1627 if ((scb
->rem_addr
.net
== rem_addr
->net
)
1628 && (scb
->rem_addr
.node
== rem_addr
->node
)) {
1629 if ((scb
->rem_addr
.socket
== rem_addr
->socket
)
1630 || (scb
->rem_socket
== rem_addr
->socket
))
1632 else if (alt_scb
== 0)
1637 if ((scb
== 0) && ((scb
= alt_scb
) == 0)) {
1638 dPrintf(D_M_ASP
, D_L_ERROR
,
1639 ("asp_find_scb: CAN'T find scb, loc=%d, rem=%x.%x.%d\n",
1645 ATENABLE(s
, aspall_lock
);
1654 asp_timout(func
, scb
, seconds
)
1656 register asp_scb_t
*scb
;
1661 register asp_scb_t
*curr_scb
, *prev_scb
;
1666 scb
->tmo_func
= func
;
1667 scb
->tmo_delta
= (seconds
>>SESS_TMO_RES
);
1668 scb
->tmo_cnt
= scb_tmo_cnt
;
1670 ATDISABLE(s
, asptmo_lock
);
1671 if (scb_tmo_list
== 0) {
1672 scb
->next_tmo
= scb
->prev_tmo
= 0;
1674 ATENABLE(s
, asptmo_lock
);
1679 curr_scb
= scb_tmo_list
;
1683 sum
+= curr_scb
->tmo_delta
;
1684 if (sum
> scb
->tmo_delta
) {
1685 sum
-= curr_scb
->tmo_delta
;
1686 scb
->tmo_delta
-= sum
;
1687 curr_scb
->tmo_delta
-= scb
->tmo_delta
;
1690 prev_scb
= curr_scb
;
1691 if ((curr_scb
= curr_scb
->next_tmo
) == 0) {
1692 scb
->tmo_delta
-= sum
;
1698 scb
->prev_tmo
= prev_scb
;
1699 if ((scb
->next_tmo
= prev_scb
->next_tmo
) != 0)
1700 prev_scb
->next_tmo
->prev_tmo
= scb
;
1701 prev_scb
->next_tmo
= scb
;
1704 scb
->next_tmo
= scb_tmo_list
;
1705 scb_tmo_list
->prev_tmo
= scb
;
1708 ATENABLE(s
, asptmo_lock
);
1715 asp_untimout(func
, scb
)
1717 register asp_scb_t
*scb
;
1721 if ((scb
->tmo_cnt
== scb_tmo_cnt
) || (scb
->tmo_func
== 0))
1724 ATDISABLE(s
, asptmo_lock
);
1725 if (scb_tmo_list
== scb
) {
1726 if ((scb_tmo_list
= scb
->next_tmo
) != 0) {
1727 scb_tmo_list
->prev_tmo
= 0;
1728 scb
->next_tmo
->tmo_delta
+= scb
->tmo_delta
;
1730 } else if (scb
->prev_tmo
) {
1731 if ((scb
->prev_tmo
->next_tmo
= scb
->next_tmo
) != 0) {
1732 scb
->next_tmo
->prev_tmo
= scb
->prev_tmo
;
1733 scb
->next_tmo
->tmo_delta
+= scb
->tmo_delta
;
1738 ATENABLE(s
, asptmo_lock
);
1751 * set the state to Close
1753 ATDISABLE(s
, scb
->lock
);
1754 scb
->state
= ASPSTATE_Close
;
1755 if (scb
->tickle_tid
) {
1756 atp_cancel_req(scb
->gref
, (unsigned int)scb
->tickle_tid
);
1757 scb
->tickle_tid
= 0;
1761 * notify upstream of the hangup
1763 if (scb
->rem_addr
.node
) {
1764 if (scb
->get_wait
) {
1765 wakeup(&scb
->event
);
1766 ATENABLE(s
, scb
->lock
);
1768 ATENABLE(s
, scb
->lock
);
1769 atalk_notify_sel(scb
->gref
);
1772 ATENABLE(s
, scb
->lock
);
1776 asp_iocack(gref
, mioc
)
1780 if (gbuf_cont(mioc
))
1781 ((ioc_t
*)gbuf_rptr(mioc
))->ioc_count
= gbuf_msgsize(gbuf_cont(mioc
));
1783 ((ioc_t
*)gbuf_rptr(mioc
))->ioc_count
= 0;
1785 gbuf_set_type(mioc
, MSG_IOCACK
);
1786 atalk_putnext(gref
, mioc
);
1790 asp_iocnak(gref
, mioc
, err
)
1795 ((ioc_t
*)gbuf_rptr(mioc
))->ioc_count
= 0;
1798 ((ioc_t
*)gbuf_rptr(mioc
))->ioc_error
= err
;
1799 ((ioc_t
*)gbuf_rptr(mioc
))->ioc_rval
= -1;
1800 if (gbuf_cont(mioc
)) {
1801 gbuf_freem(gbuf_cont(mioc
));
1802 gbuf_cont(mioc
) = 0;
1805 gbuf_set_type(mioc
, MSG_IOCNAK
);
1806 atalk_putnext(gref
, mioc
);
1810 * the alloc scb routine
1812 StaticProc asp_scb_t
*
1817 asp_scb_t
*scb
, *scb_array
;
1819 ATDISABLE(s
, aspall_lock
);
1820 if (scb_free_list
== 0) {
1821 if ((m
= gbuf_alloc(SCBS_PER_BLK
*sizeof(asp_scb_t
), PRI_MED
)) == 0)
1823 ATENABLE(s
, aspall_lock
);
1824 return (asp_scb_t
*)0;
1826 bzero((char *)gbuf_rptr(m
), SCBS_PER_BLK
*sizeof(asp_scb_t
));
1827 gbuf_cont(m
) = scb_resource_m
;
1829 scb_array
= (asp_scb_t
*)gbuf_rptr(m
);
1830 for (i
=0; i
< SCBS_PER_BLK
-1; i
++)
1831 scb_array
[i
].next_scb
= (asp_scb_t
*)&scb_array
[i
+1];
1832 scb_array
[i
].next_scb
= 0;
1833 scb_free_list
= (asp_scb_t
*)&scb_array
[0];
1836 scb
= scb_free_list
;
1837 scb_free_list
= scb
->next_scb
;
1838 ATENABLE(s
, aspall_lock
);
1839 ATLOCKINIT(scb
->lock
);
1840 ATLOCKINIT(scb
->delay_lock
);
1841 ATEVENTINIT(scb
->event
);
1842 ATEVENTINIT(scb
->delay_event
);
1848 * the free scb routine
1856 bzero((char *)scb
, sizeof(asp_scb_t
));
1857 ATDISABLE(s
, aspall_lock
);
1858 scb
->next_scb
= scb_free_list
;
1859 scb_free_list
= scb
;
1860 ATENABLE(s
, aspall_lock
);
1864 * routine to pass up receive data
1867 asp_putnext(gref
, mproto
)
1875 scb
= (asp_scb_t
*)gref
->info
;
1878 * queue the message.
1880 ATDISABLE(s
, scb
->lock
);
1881 gbuf_next(mproto
) = 0;
1882 if ((m
= scb
->sess_ioc
) == 0)
1883 scb
->sess_ioc
= mproto
;
1885 while (gbuf_next(m
))
1887 gbuf_next(m
) = mproto
;
1890 if (scb
->rcv_cnt
>= MAX_RCV_CNT
)
1893 if (scb
->get_wait
) {
1894 wakeup(&scb
->event
);
1895 ATENABLE(s
, scb
->lock
);
1896 } else if (mproto
== scb
->sess_ioc
) {
1897 ATENABLE(s
, scb
->lock
);
1898 atalk_notify_sel(gref
);
1900 ATENABLE(s
, scb
->lock
);
1904 * The following two routines are direct entries from system
1905 * calls to allow fast sending and recving of ASP data.
1908 /* in ASPputmsg we expect:
1914 ASPFUNC_WriteContinue
1916 bms: Make this callable from the kernel.
1917 If mreq != NULL, then must be called from kernel space and the following apply:
1918 1) *mreq is data to be sent already in mbuf chains.
1919 2) datptr->len = size of data
1922 int ASPputmsg(gref_t
*gref
, strbuf_t
*ctlptr
, strbuf_t
*datptr
, gbuf_t
*mreq
, int flags
, int *errp
)
1924 int s
, i
, err
, len
, offset
, remain
, size
, copy_len
;
1925 gbuf_t
*mioc
, *mdata
, *mx
, *m0
;
1930 int nbds
, result
, msize
, Primitive
;
1931 unsigned char *wptr
;
1932 struct atp_set_default
*sd
;
1935 struct atpBDS
*atpBDS
;
1937 union asp_primitives
*primitives
;
1941 if ((scb
= (asp_scb_t
*)gref
->info
) == 0) {
1942 dPrintf(D_M_ASP
, D_L_ERROR
,
1943 ("ASPputmsg: stale handle=0x%x, pid=%d\n",
1944 (u_int
) gref
, gref
->pid
));
1950 if (scb
->state
== ASPSTATE_Close
)
1952 if (scb
->snd_stop
) {
1958 * copy in the control and data info
1961 /* being called from kernel space */
1962 bcopy (ctlptr
, &ctlbuf
, sizeof (strbuf_t
));
1963 bcopy (datptr
, &datbuf
, sizeof (strbuf_t
));
1965 /* being called from user space */
1966 if ((err
= copyin(CAST_USER_ADDR_T(ctlptr
), (caddr_t
)&ctlbuf
, sizeof(ctlbuf
))) != 0)
1968 if ((err
= copyin(CAST_USER_ADDR_T(datptr
), (caddr_t
)&datbuf
, sizeof(datbuf
))) != 0)
1973 * allocate buffer and copy in the control content
1975 if (!(mioc
= gbuf_alloc_wait(ctlbuf
.len
, TRUE
))) {
1976 /* error return should not be possible */
1980 gbuf_set_type(mioc
, MSG_IOCTL
); /* for later, in ATP */
1981 gbuf_wset(mioc
, ctlbuf
.len
);
1984 /* being called from kernel space */
1985 bcopy (ctlbuf
.buf
, gbuf_rptr(mioc
), ctlbuf
.len
);
1987 /* being called from user space */
1988 if ((err
= copyin(CAST_USER_ADDR_T(ctlbuf
.buf
), (caddr_t
)gbuf_rptr(mioc
), ctlbuf
.len
)) != 0) {
1994 iocbp
= (ioc_t
*)gbuf_rptr(mioc
);
1995 primitives
= (union asp_primitives
*)gbuf_rptr(mioc
);
1996 Primitive
= primitives
->Primitive
;
1997 dPrintf(D_M_ASP
, D_L_INFO
,
1998 ("ASPputmsg: %s\n", aspCmdStr(Primitive
)));
2001 * copy in the data content into multiple mbuf clusters if
2002 * required. ATP now expects reply data to be placed in
2003 * standard clusters, not the large external clusters that
2004 * were used previously.
2007 /* set offset for use by some commands */
2008 offset
= (Primitive
== ASPFUNC_CmdReply
) ? 0 : aspCMDsize
;
2011 /* The data from the in-kernel call for use by AFP is passed
2012 * in as one large external cluster. This needs to be copied
2013 * to a chain of standard clusters.
2015 remain
= gbuf_len(mreq
);
2016 dataptr
= mtod(mreq
, caddr_t
);
2018 /* copyin from user space */
2019 remain
= datbuf
.len
;
2020 dataptr
= (caddr_t
)datbuf
.buf
;
2023 /* allocate first buffer */
2024 if (!(mdata
= gbuf_alloc_wait((remain
+ offset
> MCLBYTES
? MCLBYTES
: remain
+ offset
), TRUE
))) {
2025 /* error return should not be possible */
2030 gbuf_wset(mdata
, 0); /* init length to zero */
2031 gbuf_cont(mioc
) = mdata
;
2034 if (remain
+ offset
> MCLBYTES
)
2035 copy_len
= MCLBYTES
- offset
;
2040 bcopy (dataptr
, (gbuf_rptr(mdata
) + offset
), copy_len
);
2041 else if ((err
= copyin(CAST_USER_ADDR_T(dataptr
), (caddr_t
)(gbuf_rptr(mdata
) + offset
), copy_len
)) != 0) {
2045 gbuf_wset(mdata
, (copy_len
+ offset
));
2046 size
+= copy_len
+ offset
;
2047 dataptr
+= copy_len
;
2050 /* allocate the next mbuf */
2051 if ((gbuf_cont(mdata
) = m_get((M_WAIT
), MSG_DATA
)) == 0) {
2056 mdata
= gbuf_cont(mdata
);
2057 MCLGET(mdata
, M_WAIT
);
2058 if (!(mdata
->m_flags
& M_EXT
)) {
2065 mdata
= gbuf_cont(mioc
); /* code further on down expects this to b e set */
2066 mdata
->m_pkthdr
.len
= size
; /* set packet hdr len */
2071 switch (Primitive
) {
2073 case ASPFUNC_Command
:
2075 case ASPFUNC_WriteContinue
:
2076 case ASPFUNC_Attention
:
2078 * build the command/write/write_continue request
2080 wptr
= gbuf_rptr(mdata
);
2081 atpBDS
= (struct atpBDS
*)wptr
;
2083 for (i
=0; i
< ATP_TRESP_MAX
; i
++) {
2084 *(unsigned long *)atpBDS
[i
].bdsBuffAddr
= 1;
2085 *(unsigned short *)atpBDS
[i
].bdsBuffSz
= ATP_DATA_SIZE
;
2087 sd
= (struct atp_set_default
*)wptr
;
2088 wptr
+= sizeof(struct atp_set_default
);
2089 sd
->def_retries
= (scb
->cmd_retry
.retries
== -1) ?
2090 ATP_INFINITE_RETRIES
: scb
->cmd_retry
.retries
;
2091 sd
->def_rate
= scb
->cmd_retry
.interval
*TICKS_PER_SEC
;
2092 sd
->def_BDSlen
= atpBDSsize
;
2093 ddp
= (at_ddp_t
*)wptr
;
2094 NET_ASSIGN(ddp
->src_net
, scb
->loc_addr
.net
);
2095 ddp
->src_node
= scb
->loc_addr
.node
;
2096 NET_ASSIGN(ddp
->dst_net
, scb
->rem_addr
.net
);
2097 ddp
->dst_node
= scb
->rem_addr
.node
;
2098 ddp
->dst_socket
= scb
->rem_addr
.socket
;
2099 UAS_ASSIGN(ddp
->checksum
, 0);
2100 atp
= ATP_ATP_HDR(wptr
);
2101 wptr
+= TOTAL_ATP_HDR_SIZE
;
2105 awp
= (asp_word_t
*)atp
->user_bytes
;
2106 awp
->func
= (unsigned char)Primitive
;
2107 awp
->param1
= scb
->sess_id
;
2108 awp
->param2
= scb
->snd_seq_num
;
2109 iocbp
->ioc_private
= (void *)scb
;
2110 iocbp
->ioc_count
= gbuf_len(mdata
);
2111 iocbp
->ioc_rval
= 0;
2112 iocbp
->ioc_cmd
= AT_ATP_ISSUE_REQUEST_DEF
;
2115 * send the command/write/write_continue/attention request
2117 ATDISABLE(s
, scb
->lock
);
2118 switch (awp
->func
) {
2119 case ASPFUNC_Command
:
2120 scb
->state
= ASPSTATE_WaitingForCommandRsp
;
2123 scb
->state
= ASPSTATE_WaitingForWriteRsp
;
2125 case ASPFUNC_WriteContinue
:
2126 scb
->state
= ASPSTATE_WaitingForWriteContinueRsp
;
2127 awp
->param2
= scb
->wrt_seq_num
;
2129 case ASPFUNC_Attention
:
2130 scb
->state
= ASPSTATE_WaitingForCommandRsp
;
2135 awp
->param2
= *(unsigned short *)gbuf_wptr(mdata
);
2138 ATENABLE(s
, scb
->lock
);
2139 dPrintf(D_M_ASP
,D_L_INFO
,
2140 ("ASPputmsg: %s, loc=%d, rem=%x.%x.%d\n",
2141 (awp
->func
== ASPFUNC_Command
? "CommandReq" :
2142 awp
->func
== ASPFUNC_Write
? "WriteReq" :
2143 awp
->func
== ASPFUNC_WriteContinue
? "WriteContinue" :
2144 "AttentionReq"),scb
->loc_addr
.socket
,
2145 NET_VALUE(ddp
->dst_net
),ddp
->dst_node
,ddp
->dst_socket
));
2146 atp_send_req(gref
, mioc
);
2149 case ASPFUNC_CmdReply
:
2151 ATDISABLE(s
, scb
->lock
);
2152 if (scb
->req_msgq
) {
2154 scb
->req_msgq
= gbuf_next(mx
);
2156 ATENABLE(s
, scb
->lock
);
2157 asp_putnext(scb
->gref
, mx
);
2160 ATENABLE(s
, scb
->lock
);
2162 result
= primitives
->CmdReplyReq
.CmdResult
;
2163 tid
= primitives
->CmdReplyReq
.ReqRefNum
;
2165 /* Re-use the original mioc mbuf to send the response. */
2166 gbuf_rinc(mioc
,sizeof(void *));
2168 ddp
= (at_ddp_t
*)gbuf_wptr(mioc
);
2169 gbuf_winc(mioc
,DDP_X_HDR_SIZE
);
2170 atp
= (at_atp_t
*)gbuf_wptr(mioc
);
2171 gbuf_winc(mioc
,ATP_HDR_SIZE
);
2172 NET_ASSIGN(ddp
->src_net
, scb
->loc_addr
.net
);
2173 ddp
->src_node
= scb
->loc_addr
.node
;
2174 NET_ASSIGN(ddp
->dst_net
, scb
->rem_addr
.net
);
2175 ddp
->dst_node
= scb
->rem_addr
.node
;
2176 ddp
->dst_socket
= scb
->reply_socket
;
2177 ddp
->type
= DDP_ATP
;
2178 UAS_ASSIGN(ddp
->checksum
, 0);
2179 UAS_ASSIGN(atp
->tid
, tid
);
2180 if (scb
->attn_flag
&& (tid
== scb
->attn_tid
)) {
2188 /* setup the atpBDS struct - only the length field is used,
2189 * except for the first one which contains the bds count in
2192 atpBDS
= (struct atpBDS
*)gbuf_wptr(mioc
);
2193 msize
= mdata
? gbuf_msgsize(mdata
) : 0;
2194 for (nbds
=0; (nbds
< ATP_TRESP_MAX
) && (msize
> 0); nbds
++) {
2195 len
= msize
< ATP_DATA_SIZE
? msize
: ATP_DATA_SIZE
;
2196 msize
-= ATP_DATA_SIZE
;
2197 *(long *)atpBDS
[nbds
].bdsUserData
= 0;
2198 UAL_ASSIGN(atpBDS
[nbds
].bdsBuffAddr
, 1);
2199 UAS_ASSIGN(atpBDS
[nbds
].bdsBuffSz
, len
);
2201 UAS_ASSIGN(atpBDS
[0].bdsDataSz
, nbds
);
2202 *(long *)atpBDS
[0].bdsUserData
= (long)result
;
2203 *(long *)atp
->user_bytes
= (long)result
;
2204 gbuf_winc(mioc
,atpBDSsize
);
2205 dPrintf(D_M_ASP
, D_L_INFO
,
2206 ("ASPputmsg: ATP CmdReplyReq, loc=%d, state=%s, msgsize = %d, result = %d, tid = %d\n",
2207 scb
->loc_addr
.socket
, aspStateStr(scb
->state
),
2208 (mdata
? gbuf_msgsize(mdata
) : 0), result
, tid
));
2209 atp_send_rsp(gref
, mioc
, TRUE
);
2213 /* Not an expected ASPFUNC */
2223 /* bms: make this callable from kernel. reply date is passed back as a mbuf chain in *mreply */
2224 int ASPgetmsg(gref_t
*gref
, strbuf_t
*ctlptr
, strbuf_t
*datptr
, gbuf_t
**mreply
, int *flags
, int *errp
)
2226 int err
, s
, len
, sum
, rval
;
2227 gbuf_t
*mproto
, *mdata
;
2231 unsigned char get_wait
;
2233 if ((scb
= (asp_scb_t
*)gref
->info
) == 0) {
2234 dPrintf(D_M_ASP
, D_L_ERROR
,
2235 ("ASPgetmsg: stale handle=0x%x, pid=%d\n",
2236 (u_int
) gref
, gref
->pid
));
2242 ATDISABLE(s
, scb
->lock
);
2243 if (scb
->state
== ASPSTATE_Close
) {
2244 ATENABLE(s
, scb
->lock
);
2251 while ((mproto
= scb
->sess_ioc
) == 0) {
2253 lck_mtx_assert(atalk_mutex
, LCK_MTX_ASSERT_OWNED
);
2254 err
= msleep(&scb
->event
, atalk_mutex
, PSOCK
| PCATCH
, "aspgetmsg", 0);
2257 ATENABLE(s
, scb
->lock
);
2261 if (scb
->state
== ASPSTATE_Close
) {
2263 ATENABLE(s
, scb
->lock
);
2267 get_wait
= scb
->get_wait
;
2269 if ((ctlptr
== 0) && (datptr
== 0)) {
2270 ATENABLE(s
, scb
->lock
);
2273 scb
->sess_ioc
= gbuf_next(mproto
);
2274 mdata
= gbuf_cont(mproto
);
2275 ATENABLE(s
, scb
->lock
);
2277 /* last remaining use of MSG_ERROR */
2278 if (gbuf_type(mproto
) == MSG_ERROR
) {
2279 err
= (int)gbuf_rptr(mproto
)[0];
2284 * copy in the control and data info
2286 if (mreply
!= NULL
) {
2287 /* called from kernel space */
2288 bcopy (ctlptr
, &ctlbuf
, sizeof(ctlbuf
));
2289 bcopy (datptr
, &datbuf
, sizeof(datbuf
));
2291 /* called from user space */
2292 if ((err
= copyin(CAST_USER_ADDR_T(ctlptr
),
2293 (caddr_t
)&ctlbuf
, sizeof(ctlbuf
))) != 0)
2295 if ((err
= copyin(CAST_USER_ADDR_T(datptr
),
2296 (caddr_t
)&datbuf
, sizeof(datbuf
))) != 0)
2299 if ((datbuf
.maxlen
< 0) || (datbuf
.maxlen
< gbuf_msgsize(mdata
))) {
2300 ATDISABLE(s
, scb
->lock
);
2301 gbuf_next(mproto
) = scb
->sess_ioc
;
2302 scb
->sess_ioc
= mproto
;
2303 ATENABLE(s
, scb
->lock
);
2307 if (get_wait
== 0) {
2309 * this is a hack to support the select() call.
2310 * we're not supposed to dequeue messages in the Streams
2311 * head's read queue this way; but there is no better way.
2313 ATDISABLE(s
, scb
->lock
);
2314 if (scb
->sess_ioc
== 0) {
2315 ATENABLE(s
, scb
->lock
);
2317 ATENABLE(s
, scb
->lock
);
2318 atalk_notify_sel(gref
);
2323 * copy out the control content and info
2325 ctlbuf
.len
= gbuf_len(mproto
);
2327 if (mreply
!= NULL
) {
2328 /* called from kernel space */
2329 bcopy (gbuf_rptr(mproto
), ctlbuf
.buf
, ctlbuf
.len
);
2330 bcopy (&ctlbuf
, ctlptr
, sizeof(ctlbuf
));
2332 /* called from user space */
2333 if ((err
= copyout((caddr_t
)gbuf_rptr(mproto
),
2334 CAST_USER_ADDR_T(ctlbuf
.buf
), ctlbuf
.len
)) != 0)
2336 if ((err
= copyout((caddr_t
)&ctlbuf
,
2337 CAST_USER_ADDR_T(ctlptr
), sizeof(ctlbuf
))) != 0)
2342 * copy out the data content and info
2344 for (rval
= 0, sum
= 0; mdata
&& (rval
== 0); mdata
= gbuf_cont(mdata
))
2346 len
= gbuf_len(mdata
);
2348 if ((len
+ sum
) > datbuf
.maxlen
) {
2349 len
= datbuf
.maxlen
- sum
;
2353 if (mreply
== NULL
) {
2354 /* called from user space */
2355 if ((err
= copyout((caddr_t
)gbuf_rptr(mdata
), CAST_USER_ADDR_T(&datbuf
.buf
[sum
]), len
)) != 0)
2362 if (mreply
!= NULL
) {
2363 /* called from kernel space */
2364 bcopy (&datbuf
, datptr
, sizeof(datbuf
));
2366 /* called from user space */
2367 if ((err
= copyout((caddr_t
)&datbuf
, CAST_USER_ADDR_T(datptr
), sizeof(datbuf
))) != 0)
2371 if (mreply
!= NULL
) {
2372 /* called from kernel space */
2373 /* return the reply data in mbufs, so dont free them.
2374 Just free the proto info */
2375 mdata
= gbuf_cont(mproto
);
2377 gbuf_cont(mproto
) = NULL
;
2380 /* called from user space */
2384 ATDISABLE(s
, scb
->lock
);
2391 ATENABLE(s
, scb
->lock
);
2395 ATDISABLE(s
, scb
->lock
);
2396 gbuf_next(mproto
) = scb
->sess_ioc
;
2397 scb
->sess_ioc
= mproto
;
2398 ATENABLE(s
, scb
->lock
);