2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 * Copyright (c) 1995 Apple Computer, Inc.
32 * Created February 20, 1995 by Tuyen Nguyen
33 * Modified for MP, 1996 by Tuyen Nguyen
34 * Modified, March 17, 1997 by Tuyen Nguyen for MacOSX.
37 #include <sys/errno.h>
38 #include <sys/types.h>
39 #include <sys/param.h>
40 #include <machine/spl.h>
41 #include <sys/systm.h>
42 #include <sys/kernel.h>
44 #include <sys/filedesc.h>
45 #include <sys/fcntl.h>
47 #include <sys/ioctl.h>
48 #include <sys/malloc.h>
49 #include <kern/locks.h>
50 #include <sys/socket.h>
51 #include <sys/socketvar.h>
55 #include <netat/appletalk.h>
56 #include <netat/sysglue.h>
57 #include <netat/at_pcb.h>
58 #include <netat/atp.h>
59 #include <netat/ddp.h>
60 #include <netat/asp.h>
61 #include <netat/at_var.h>
62 #include <netat/debug.h>
65 #define CHK_LOOP(str) { \
66 if (loop_cnt++ > 100) { \
72 #define atpBDSsize (sizeof(struct atpBDS)*ATP_TRESP_MAX)
73 #define aspCMDsize (atpBDSsize+sizeof(struct atp_set_default)+TOTAL_ATP_HDR_SIZE)
74 #define SCBS_PER_BLK 16
75 #define TICKS_PER_SEC HZ
76 #define SESS_TMO_RES 2
77 #define DEF_SESS_TMO 120
78 #define NEXT_SEQ_NUM(x) (x = (x == 65535) ? 0 : (x + 1))
80 #define BAD_REMADDR(addr) \
81 ( (*(long *)&scb->rem_addr != *(long *)&addr) \
82 && ((scb->rem_addr.net != addr.net) \
83 || (scb->rem_addr.node != addr.node)) )
91 void asp_clock_locked(void *);
95 StaticProc asp_scb_t
*asp_find_scb();
96 StaticProc asp_scb_t
*asp_scb_alloc();
98 StaticProc
void asp_putnext();
99 StaticProc
void asp_iocack();
100 StaticProc
void asp_iocnak();
101 StaticProc
void asp_dequeue_scb();
102 StaticProc
void asp_scb_free();
103 StaticProc
void asp_timout();
104 StaticProc
void asp_untimout();
105 StaticProc
void asp_hangup();
106 StaticProc
void asp_send_tickle();
107 StaticProc
void asp_send_tickle_locked(void *);
108 StaticProc
void asp_accept();
109 StaticProc
int asp_send_req();
111 extern at_ifaddr_t
*ifID_home
;
112 extern int atp_pidM
[];
113 extern gref_t
*atp_inputQ
[];
114 extern lck_mtx_t
*atalk_mutex
;
115 gbuf_t
*scb_resource_m
= 0;
116 unsigned char asp_inpC
[256];
117 asp_scb_t
*asp_scbQ
[256];
119 static at_retry_t asp_def_retry
= {2, -1, 1};
120 static unsigned char scb_tmo_cnt
;
121 asp_scb_t
*scb_used_list
;
122 static asp_scb_t
*scb_tmo_list
;
123 asp_scb_t
*scb_free_list
;
124 atlock_t aspall_lock
, asptmo_lock
;
130 return (((asp_scb_t
*)gref
->info
)->sess_ioc
? 1 : 0);
140 bzero(asp_inpC
, sizeof(asp_inpC
));
141 bzero(asp_scbQ
, sizeof(asp_scbQ
));
145 * the open routine allocates a state structure
154 * if no asp structure available, return failure
156 if ((scb
= asp_scb_alloc()) == 0)
160 * initialize the gref data structure
162 gref
->info
= (void *)scb
;
163 gref
->readable
= asp_readable
;
166 * initialize the scb data structure
169 scb
->magic_num
= 222;
170 scb
->state
= ASPSTATE_Idle
;
171 scb
->pid
= gref
->pid
;
173 scb
->session_timer
= DEF_SESS_TMO
;
174 scb
->cmd_retry
= asp_def_retry
;
175 ATDISABLE(s
, aspall_lock
);
176 if ((scb
->next_scb
= scb_used_list
) != 0)
177 scb
->next_scb
->prev_scb
= scb
;
179 ATENABLE(s
, aspall_lock
);
184 dPrintf(D_M_ASP
, D_L_INFO
, ("asp_open: pid=%d\n", scb
->pid
));
189 * the close routine frees all the data structures
196 unsigned char sock_num
;
197 asp_scb_t
*scb
, *new_scb
;
200 scb
= (asp_scb_t
*)gref
->info
;
201 dPrintf(D_M_ASP
, D_L_INFO
, ("asp_close: loc=%d\n",
202 scb
->loc_addr
.socket
));
204 if (scb
->pid
&& scb
->sess_ioc
&& (scb
->dflag
!= 1)) {
206 * send the CloseSess response to peer
208 if (gbuf_type(scb
->sess_ioc
) != MSG_PROTO
) {
209 ATDISABLE(s
, scb
->lock
);
211 scb
->sess_ioc
= gbuf_next(m
);
212 ATENABLE(s
, scb
->lock
);
213 atp_send_rsp(scb
->gref
, m
, TRUE
);
217 if (scb
->atp_state
) {
218 sock_num
= scb
->loc_addr
.socket
;
219 ATDISABLE(s
, aspall_lock
);
220 if ((scb
->dflag
!= 1) && scb
->stat_msg
) {
221 untimeout(atp_retry_req
, scb
->stat_msg
);
222 gbuf_freem(scb
->stat_msg
);
225 if (asp_scbQ
[sock_num
]->next_scb
== 0) {
226 asp_scbQ
[sock_num
] = 0;
227 asp_inpC
[sock_num
] = 0;
228 ATENABLE(s
, aspall_lock
);
229 dPrintf(D_M_ASP
, D_L_INFO
,
230 (" : atp_close(), loc=%d\n", scb
->loc_addr
.socket
));
233 asp_inpC
[sock_num
]--;
234 if (scb
== asp_scbQ
[sock_num
]) {
235 new_scb
= scb
->next_scb
;
236 new_scb
->prev_scb
= 0;
237 asp_scbQ
[sock_num
] = new_scb
;
238 new_scb
->atp_state
->atp_gref
= new_scb
->gref
;
239 new_scb
->atp_state
->pid
= new_scb
->pid
;
240 atp_inputQ
[sock_num
] = new_scb
->gref
;
242 if ((scb
->prev_scb
->next_scb
= scb
->next_scb
) != 0)
243 scb
->next_scb
->prev_scb
= scb
->prev_scb
;
246 ATENABLE(s
, aspall_lock
);
249 asp_dequeue_scb(scb
);
252 * free all allocated blocks if any
254 ATDISABLE(s
, scb
->lock
);
256 gbuf_freem(scb
->stat_msg
);
260 gbuf_freel(scb
->sess_ioc
);
264 gbuf_freel(scb
->req_msgq
);
268 scb
->rem_addr
.node
= 0;
269 ATENABLE(s
, scb
->lock
);
275 asp_untimout(asp_hangup
, scb
);
276 untimeout(asp_send_tickle_locked
, (void *)scb
); /* added for 2225395 */
279 * free the asp session control block
281 scb
->state
= ASPSTATE_Close
;
286 static char *aspStateStr(state
)
289 return ((state
==ASPSTATE_Close
)? "Close":
290 (state
==ASPSTATE_Idle
)? "Idle":
291 (state
==ASPSTATE_WaitingForGetStatusRsp
)? "GetStatusRsp":
292 (state
==ASPSTATE_WaitingForOpenSessRsp
)? "OpenSessRsp":
293 (state
==ASPSTATE_WaitingForCommandRsp
)? "CmdRsp":
294 (state
==ASPSTATE_WaitingForWriteContinue
)? "WriteCont":
295 (state
==ASPSTATE_WaitingForWriteRsp
)? "WriteRsp":
296 (state
==ASPSTATE_WaitingForWriteContinueRsp
)? "WriteContRsp":
297 (state
==ASPSTATE_WaitingForCloseSessRsp
)? "CloseSessRsp":
301 static char *aspCmdStr(aspCmd
)
304 return ((aspCmd
==ASPFUNC_CloseSess
)? "CloseSess":
305 (aspCmd
==ASPFUNC_Command
)? "Command":
306 (aspCmd
==ASPFUNC_GetStatus
)? "GetStatus":
307 (aspCmd
==ASPFUNC_OpenSess
)? "OpenSess":
308 (aspCmd
==ASPFUNC_Tickle
)? "Tickle":
309 (aspCmd
==ASPFUNC_Write
)? "Write":
310 (aspCmd
==ASPFUNC_WriteContinue
)? "WriteContinue":
311 (aspCmd
==ASPFUNC_Attention
)? "Attention":
312 (aspCmd
==ASPFUNC_CmdReply
)? "CmdReply": "unknown");
315 static char *aspIOCStr(aspIOC
)
319 (aspIOC
==ASPIOC_ClientBind
)? "ClientBind":
320 (aspIOC
==ASPIOC_CloseSession
)? "CloseSession":
321 (aspIOC
==ASPIOC_GetLocEntity
)? "GetLocEntity":
322 (aspIOC
==ASPIOC_GetRemEntity
)? "GetRemEntity":
323 (aspIOC
==ASPIOC_GetSession
)? "GetSession":
324 (aspIOC
==ASPIOC_GetStatus
)? "GetStatus":
325 (aspIOC
==ASPIOC_ListenerBind
)? "ListenerBind":
326 (aspIOC
==ASPIOC_OpenSession
)? "OpenSession":
327 (aspIOC
==ASPIOC_StatusBlock
)? "StatusBlock":
328 (aspIOC
==ASPIOC_SetPid
)? "SetPid":
329 (aspIOC
==ASPIOC_GetSessId
)? "GetSessId":
330 (aspIOC
==ASPIOC_EnableSelect
)? "EnableSelect":
331 (aspIOC
==ASPIOC_Look
)? "Look":
338 static char mbuf_str
[100];
343 "dat = %d, prot = %d, ioc = %d, err = %d, hu = %d, ack = %d, nak = %d, ctl = %d",
345 "dat = %d, prot = %d, ioc = %d, ctl = %d",
346 mbstat
.m_mtypes
[MSG_DATA
], mbstat
.m_mtypes
[MSG_PROTO
], mbstat
.m_mtypes
[MSG_IOCTL
],
348 mbstat.m_mtypes[MSG_ERROR], mbstat.m_mtypes[MSG_HANGUP], mbstat.m_mtypes[MSG_IOCACK],
349 mbstat.m_mtypes[MSG_IOCNAK],
351 mbstat
.m_mtypes
[MSG_CTL
]);
352 return(&mbuf_str
[0]);
355 void trace_beg(str
, m
)
360 gbuf_t
*mdata
, *mchain
;
363 for (i
= 0, j
= 0, mdata
= m
, mchain
= m
; mdata
; i
++) {
364 mdata
= gbuf_cont(mdata
);
365 if (!mdata
&& mchain
) {
366 mdata
= gbuf_next(mchain
);
371 dPrintf(D_M_ASP
, D_L_TRACE
,
372 ("%s: %s, m# = %d, c# = %d\n", str
, mbuf_totals(), i
, j
));
378 dPrintf(D_M_ASP
, D_L_TRACE
,
379 (" %s: %s\n", str
, mbuf_totals()));
381 #endif /* AT_MBUF_TRACE */
386 int asp_wput(gref
, m
)
391 unsigned char sockSav
, sock_num
;
392 gbuf_t
*mioc
, *mdata
;
394 asp_scb_t
*scb
, *server_scb
, *curr_scb
;
397 union asp_primitives
*primitives
;
398 asp_status_cmd_t
*status_cmd
;
399 asp_open_cmd_t
*open_cmd
;
402 scb
= (asp_scb_t
*)gref
->info
;
403 if (scb
->dflag
== 0) {
408 if (gbuf_type(m
) != MSG_IOCTL
) {
409 dPrintf(D_M_ASP
, D_L_WARNING
,
410 ("asp_wput: UNKNOWN message, type=%d\n",
417 iocbp
= (ioc_t
*)gbuf_rptr(mioc
);
419 dPrintf(D_M_ASP_LOW
, D_L_INFO
,
420 ("asp_wput: %s, loc=%d, state=%s\n",
421 aspIOCStr(iocbp
->ioc_cmd
), scb
->loc_addr
.socket
,
422 aspStateStr(scb
->state
)));
424 switch (iocbp
->ioc_cmd
) {
425 case ASPIOC_CloseSession
:
426 if ((scb
->state
== ASPSTATE_Close
) || (scb
->rem_addr
.node
== 0))
431 aw
.func
= ASPFUNC_CloseSess
;
432 aw
.param1
= scb
->sess_id
;
434 iocbp
->ioc_private
= (void *)scb
;
435 scb
->ioc_wait
= (unsigned char)(iocbp
->ioc_cmd
& 0xff);
436 iocbp
->ioc_cmd
= AT_ATP_ISSUE_REQUEST
;
437 asp_send_req(gref
, mioc
, &scb
->rem_addr
, &Retry
, &aw
,
438 0, ASPSTATE_WaitingForCloseSessRsp
, 0x01);
441 case ASPIOC_ClientBind
:
443 * open an ATP channel
445 if ((err
= atp_open(gref
, 0)) != 0) {
446 asp_iocnak(gref
, mioc
, err
);
449 scb
->atp_state
= (atp_state_t
*)gref
->info
;
450 scb
->atp_state
->pid
= scb
->pid
;
452 * bind to any available socket
455 sockSav
= scb
->dflag
;
456 if ((sock_num
= (at_socket
)atp_bind(gref
, 0, &sockSav
)) == 0) {
457 scb
->atp_state
= (atp_state_t
*)0;
459 gref
->info
= (void *)scb
;
460 asp_iocnak(gref
, mioc
, EINVAL
);
463 gref
->info
= (void *)scb
;
464 asp_dequeue_scb(scb
);
465 scb
->atp_state
->dflag
= scb
->dflag
;
466 scb
->loc_addr
.socket
= sock_num
;
467 asp_scbQ
[sock_num
] = scb
;
468 asp_inpC
[sock_num
]++;
469 atp_pidM
[sock_num
] = 0;
472 case ASPIOC_ListenerBind
:
474 * open an ATP channel
476 if ((err
= atp_open(gref
, 0)) != 0) {
477 asp_iocnak(gref
, mioc
, err
);
480 scb
->atp_state
= (atp_state_t
*)gref
->info
;
481 scb
->atp_state
->pid
= scb
->pid
;
483 * bind to any available socket
485 if ((sock_num
= (at_socket
)atp_bind(gref
, 0, 0)) == 0) {
486 scb
->atp_state
= (atp_state_t
*)0;
488 gref
->info
= (void *)scb
;
489 asp_iocnak(gref
, mioc
, EINVAL
);
492 gref
->info
= (void *)scb
;
493 asp_dequeue_scb(scb
);
494 scb
->atp_state
->dflag
= scb
->dflag
;
495 scb
->loc_addr
.socket
= sock_num
;
496 asp_scbQ
[sock_num
] = scb
;
497 asp_inpC
[sock_num
]++;
499 *(at_inet_t
*)gbuf_rptr(gbuf_cont(mioc
)) = scb
->loc_addr
;
502 case ASPIOC_GetLocEntity
:
503 if ((gbuf_cont(mioc
) == 0) || (scb
->atp_state
== 0)) {
504 asp_iocnak(gref
, mioc
, EPROTOTYPE
);
507 *(at_inet_t
*)gbuf_rptr(gbuf_cont(mioc
)) = scb
->loc_addr
;
510 case ASPIOC_GetRemEntity
:
511 if ((gbuf_cont(mioc
) == 0) || (scb
->atp_state
== 0)) {
512 asp_iocnak(gref
, mioc
, EPROTOTYPE
);
515 *(at_inet_t
*)gbuf_rptr(gbuf_cont(mioc
)) = scb
->rem_addr
;
518 case ASPIOC_GetSession
:
519 if ((mdata
= gbuf_cont(mioc
)) == 0) {
520 asp_iocnak(gref
, mioc
, EPROTOTYPE
);
523 addr
= (at_inet_t
*)gbuf_rptr(mdata
);
524 scb
->tickle_interval
= (unsigned short)addr
->node
;
525 scb
->session_timer
= addr
->net
;
526 server_scb
= asp_scbQ
[addr
->socket
];
527 /*### LD 10/28/97: changed to make sure we're not accessing a null server_scb */
528 if (server_scb
== 0) {
529 asp_iocnak(gref
, mioc
, EPROTOTYPE
);
532 if (server_scb
->sess_ioc
== 0) {
533 asp_iocnak(gref
, mioc
, EPROTOTYPE
);
538 * open an ATP channel
540 if ((err
= atp_open(gref
, 0)) != 0) {
541 gref
->info
= (void *)scb
;
542 asp_iocnak(gref
, mioc
, err
);
545 scb
->atp_state
= (atp_state_t
*)gref
->info
;
546 scb
->atp_state
->pid
= scb
->pid
;
548 * bind to any available socket
551 sockSav
= scb
->dflag
;
552 if ((sock_num
= (at_socket
)atp_bind(gref
, 0, &sockSav
)) == 0) {
554 asp_dequeue_scb(scb
);
555 ATDISABLE(s
, aspall_lock
);
557 scb
->loc_addr
.socket
= sock_num
;
558 for (curr_scb
= asp_scbQ
[sock_num
];
559 curr_scb
->next_scb
; curr_scb
= curr_scb
->next_scb
) ;
560 scb
->prev_scb
= curr_scb
;
561 curr_scb
->next_scb
= scb
;
562 scb
->atp_state
= curr_scb
->atp_state
;
563 ATENABLE(s
, aspall_lock
);
565 asp_dequeue_scb(scb
);
566 ATDISABLE(s
, aspall_lock
);
567 scb
->loc_addr
.socket
= sock_num
;
568 asp_scbQ
[sock_num
] = scb
;
569 scb
->atp_state
->dflag
= scb
->dflag
;
570 ATENABLE(s
, aspall_lock
);
572 gref
->info
= (void *)scb
;
573 asp_inpC
[sock_num
]++;
575 asp_accept(server_scb
, scb
, mdata
);
578 case ASPIOC_GetStatus
:
579 if ((mdata
= gbuf_cont(mioc
)) == 0) {
580 asp_iocnak(gref
, mioc
, EINVAL
);
584 status_cmd
= (asp_status_cmd_t
*)gbuf_rptr(mdata
);
585 aw
.func
= ASPFUNC_GetStatus
;
588 scb
->ioc_wait
= (unsigned char)(iocbp
->ioc_cmd
& 0xff);
589 iocbp
->ioc_cmd
= AT_ATP_ISSUE_REQUEST_DEF
;
590 /* bms: make sure this is an ALO request */
591 asp_send_req(gref
, mioc
, &status_cmd
->SLSEntityIdentifier
,
592 &status_cmd
->Retry
, &aw
, 0, ASPSTATE_WaitingForGetStatusRsp
, 0xff);
596 case ASPIOC_OpenSession
:
597 if ((mdata
= gbuf_cont(mioc
)) == 0) {
598 asp_iocnak(gref
, mioc
, EINVAL
);
602 open_cmd
= (asp_open_cmd_t
*)gbuf_rptr(mdata
);
603 scb
->svc_addr
= open_cmd
->SLSEntityIdentifier
;
604 scb
->rem_addr
= scb
->svc_addr
;
605 scb
->rem_node
= scb
->rem_addr
.node
;
606 scb
->rem_addr
.node
= 0;
607 scb
->tickle_interval
= open_cmd
->TickleInterval
;
608 scb
->session_timer
= open_cmd
->SessionTimer
;
609 aw
.func
= ASPFUNC_OpenSess
;
610 aw
.param1
= scb
->loc_addr
.socket
;
611 aw
.param2
= ASP_Version
;
612 scb
->ioc_wait
= (unsigned char)(iocbp
->ioc_cmd
& 0xff);
613 iocbp
->ioc_cmd
= AT_ATP_ISSUE_REQUEST_DEF
;
614 asp_send_req(gref
, mioc
, &open_cmd
->SLSEntityIdentifier
,
615 &open_cmd
->Retry
, &aw
, 1, ASPSTATE_WaitingForOpenSessRsp
, 0x01);
619 case ASPIOC_StatusBlock
:
621 * save the server status block
624 gbuf_freem(scb
->stat_msg
);
625 scb
->stat_msg
= gbuf_cont(mioc
);
629 /* *** Does scb->pid get used in a packet header,
630 and if so is it in ASP, or in ATP?
631 If not, do we need this call for anything?
632 (cap does currently use it in _ANS code.)
635 if (gbuf_cont(mioc
) == 0) {
636 asp_iocnak(gref
, mioc
, EINVAL
);
639 scb
->pid
= *(int *)gbuf_rptr(gbuf_cont(mioc
));
642 case ASPIOC_GetSessId
:
643 if (gbuf_cont(mioc
) == 0) {
644 asp_iocnak(gref
, mioc
, EINVAL
);
647 *(gref_t
**)gbuf_rptr(gbuf_cont(mioc
)) = gref
;
651 if (gbuf_cont(mioc
) == 0) {
652 asp_iocnak(gref
, mioc
, EINVAL
);
656 primitives
= (union asp_primitives
*)gbuf_rptr(scb
->sess_ioc
);
657 if (primitives
->Primitive
== ASPFUNC_CmdReply
)
658 *(int *)gbuf_rptr(gbuf_cont(mioc
)) = 0;
660 *(int *)gbuf_rptr(gbuf_cont(mioc
)) = 1;
662 *(int *)gbuf_rptr(gbuf_cont(mioc
)) = -1;
665 case DDP_IOC_GET_CFG
:
667 struct atp_state
*atp
= (struct atp_state
*)gref
->info
;
669 atp
= (struct atp_state
*)atp
->atp_msgq
;
671 if (gbuf_cont(mioc
) == 0) {
672 asp_iocnak(gref
, mioc
, EINVAL
);
675 /* *** borrowed from ddp_proto.c to handle DDP_IOC_GET_CFG
677 scb
->state
= ASPSTATE_Idle
;
679 /* *** was ddp_get_cfg() *** */
681 (ddp_addr_t
*)gbuf_rptr(gbuf_cont(mioc
));
682 cfgp
->inet
.net
= ifID_home
->ifThisNode
.s_net
;
683 cfgp
->inet
.node
= ifID_home
->ifThisNode
.s_node
;
684 cfgp
->inet
.socket
= atp
->atp_socket_no
;
685 cfgp
->ddptype
= DDP_ATP
;
687 gbuf_wset(gbuf_cont(mioc
), sizeof(at_inet_t
));
692 asp_iocnak(gref
, mioc
, EINVAL
);
696 asp_iocack(gref
, mioc
);
701 * send request routine
704 asp_send_req(gref
, mioc
, dest
, retry
, awp
, xo
, state
, bitmap
)
712 unsigned char bitmap
;
717 struct atp_set_default
*sd
;
720 struct atpBDS
*atpBDS
;
721 asp_scb_t
*scb
= (asp_scb_t
*)gref
->info
;
724 * allocate an ATP buffer for the request
726 if ((gbuf_cont(mioc
) = gbuf_alloc(aspCMDsize
, PRI_MED
)) == 0) {
727 if (awp
->func
== ASPFUNC_Tickle
)
730 asp_iocnak(gref
, mioc
, ENOBUFS
);
731 dPrintf(D_M_ASP
, D_L_WARNING
,
732 ("asp_send_req: ENOBUFS, loc=%d\n", scb
->loc_addr
.socket
));
736 mdata
= gbuf_cont(mioc
);
737 iocbp
= (ioc_t
*)gbuf_rptr(mioc
);
742 atpBDS
= (struct atpBDS
*)gbuf_rptr(mdata
);
743 gbuf_wset(mdata
,atpBDSsize
);
744 for (i
=0; i
< ATP_TRESP_MAX
; i
++) {
745 *(unsigned long *)atpBDS
[i
].bdsBuffAddr
= 1;
746 *(unsigned short *)atpBDS
[i
].bdsBuffSz
= ATP_DATA_SIZE
;
748 sd
= (struct atp_set_default
*)gbuf_wptr(mdata
);
749 gbuf_winc(mdata
,sizeof(struct atp_set_default
));
750 sd
->def_retries
= (retry
->retries
== -1) ?
751 ATP_INFINITE_RETRIES
: retry
->retries
;
752 sd
->def_rate
= retry
->interval
*TICKS_PER_SEC
;
753 sd
->def_BDSlen
= atpBDSsize
;
754 ddp
= (at_ddp_t
*)gbuf_wptr(mdata
);
755 NET_ASSIGN(ddp
->src_net
, scb
->loc_addr
.net
);
756 ddp
->src_node
= scb
->loc_addr
.node
;
757 NET_ASSIGN(ddp
->dst_net
, dest
->net
);
758 ddp
->dst_node
= dest
->node
;
759 ddp
->dst_socket
= dest
->socket
;
760 UAS_ASSIGN(ddp
->checksum
, 0);
761 atp
= ATP_ATP_HDR(gbuf_wptr(mdata
));
764 atp
->bitmap
= bitmap
;
765 gbuf_winc(mdata
,TOTAL_ATP_HDR_SIZE
);
766 *(asp_word_t
*)atp
->user_bytes
= *awp
;
767 iocbp
->ioc_count
= gbuf_len(mdata
);
774 dPrintf(D_M_ASP
, D_L_INFO
,
775 ("asp_send_req: %s, loc=%d, rem= %d, len=%d, state=%s\n",
776 aspCmdStr(awp
->func
),
777 scb
->loc_addr
.socket
, ddp
->dst_socket
, iocbp
->ioc_count
,
778 aspStateStr(scb
->state
)));
780 atp_send_req(gref
, mioc
);
785 * send tickle routine - locked version
788 asp_send_tickle_locked(scb
)
792 asp_send_tickle((asp_scb_t
*)scb
);
798 * send tickle routine
811 * make sure the connection is still there
813 if (scb
->rem_addr
.node
== 0) {
817 if ((mioc
= gbuf_alloc(sizeof(ioc_t
), PRI_HI
)) == 0) {
818 dPrintf(D_M_ASP
, D_L_WARNING
,
819 ("asp_send_tickle: ENOBUFS 0, loc=%d, rem=%d\n",
820 scb
->loc_addr
.socket
,scb
->rem_addr
.socket
));
821 timeout(asp_send_tickle_locked
, (void *)scb
, 10);
824 gbuf_wset(mioc
,sizeof(ioc_t
));
825 gbuf_set_type(mioc
, MSG_IOCTL
);
827 dest
= scb
->svc_addr
.node
?
828 (at_inet_t
*)&scb
->svc_addr
: (at_inet_t
*)&scb
->rem_addr
;
829 retry
.interval
= scb
->tickle_interval
;
832 aw
.func
= ASPFUNC_Tickle
;
833 aw
.param1
= scb
->sess_id
;
835 ((ioc_t
*)gbuf_rptr(mioc
))->ioc_cr
= (void *)scb
;
836 ((ioc_t
*)gbuf_rptr(mioc
))->ioc_cmd
= AT_ATP_ISSUE_REQUEST_TICKLE
;
838 if (asp_send_req(scb
->gref
, mioc
, dest
, &retry
, &aw
, 0, scb
->state
, 0)) {
839 dPrintf(D_M_ASP
, D_L_WARNING
,
840 ("asp_send_tickle: ENOBUFS 1, loc=%d, rem=%d\n",
841 scb
->loc_addr
.socket
,scb
->rem_addr
.socket
));
843 timeout(asp_send_tickle_locked
, (void *)scb
, 10);
849 * accept connection routine
852 asp_accept(scb
, sess_scb
, m
)
864 mdata
= scb
->sess_ioc
;
865 ddp
= (at_ddp_t
*)gbuf_rptr(mdata
);
866 atp
= (at_atp_t
*)(gbuf_rptr(mdata
) + DDP_X_HDR_SIZE
);
867 rem_addr
.net
= NET_VALUE(ddp
->src_net
);
868 rem_addr
.node
= ddp
->src_node
;
869 rem_addr
.socket
= ddp
->src_socket
;
870 awp
= (asp_word_t
*)atp
->user_bytes
;
872 sess_scb
->loc_addr
.net
= NET_VALUE(ddp
->dst_net
);
873 sess_scb
->loc_addr
.node
= ddp
->dst_node
;
874 NET_ASSIGN(ddp
->src_net
, sess_scb
->loc_addr
.net
);
875 ddp
->src_node
= sess_scb
->loc_addr
.node
;
876 NET_ASSIGN(ddp
->dst_net
, rem_addr
.net
);
877 ddp
->dst_node
= rem_addr
.node
;
878 ddp
->dst_socket
= rem_addr
.socket
;
880 sess_scb
->sess_id
= sess_scb
->loc_addr
.socket
;
881 sess_scb
->rem_socket
= rem_addr
.socket
;
882 sess_scb
->rem_addr
= rem_addr
;
883 sess_scb
->rem_addr
.socket
= awp
->param1
;
884 sess_scb
->reply_socket
= sess_scb
->rem_addr
.socket
;
885 awp
->func
= sess_scb
->loc_addr
.socket
;
886 awp
->param1
= sess_scb
->sess_id
;
889 ATDISABLE(s
, scb
->lock
);
890 scb
->sess_ioc
= gbuf_next(mdata
);
891 ATENABLE(s
, scb
->lock
);
892 gbuf_next(mdata
) = 0;
893 asp_timout(asp_hangup
, sess_scb
, sess_scb
->session_timer
);
894 atp_send_rsp(scb
->gref
, mdata
, TRUE
);
895 asp_send_tickle(sess_scb
);
896 dPrintf(D_M_ASP
, D_L_INFO
,
897 ("asp_accept: ACCEPT connect request, loc=%d, rem=%x.%x.%d\n",
898 sess_scb
->loc_addr
.socket
,
899 sess_scb
->rem_addr
.net
,
900 sess_scb
->rem_addr
.node
,sess_scb
->rem_addr
.socket
));
904 * timer routine - locked version
906 void asp_clock_locked(arg
)
924 ATDISABLE(s
, asptmo_lock
);
926 scb_tmo_list
->tmo_delta
--;
927 while (((scb
= scb_tmo_list
) != 0) && (scb_tmo_list
->tmo_delta
== 0)) {
928 if ((scb_tmo_list
= scb
->next_tmo
) != 0)
929 scb_tmo_list
->prev_tmo
= 0;
930 if ((tmo_func
= scb
->tmo_func
) != 0) {
932 ATENABLE(s
, asptmo_lock
);
934 ATDISABLE(s
, asptmo_lock
);
937 ATENABLE(s
, asptmo_lock
);
939 if (++scb_tmo_cnt
== 0) scb_tmo_cnt
++;
940 timeout(asp_clock_locked
, (void *)arg
, (1<<SESS_TMO_RES
)*TICKS_PER_SEC
);
948 asp_ack_reply(gref
, mioc
)
949 register gref_t
*gref
;
950 register gbuf_t
*mioc
;
953 int len
, msize
, nbds
;
954 register gbuf_t
*mdata
, *m
, *mx
;
955 struct atpBDS
*atpBDS
;
958 register asp_scb_t
*scb
, *sess_scb
;
959 register ioc_t
*iocbp
;
960 register asp_word_t
*awp
;
961 register asp_command_ind_t
*command_ind
;
962 register asp_cmdreply_ind_t
*cmdreply_ind
;
965 iocbp
= (ioc_t
*)gbuf_rptr(mioc
);
967 if (iocbp
->ioc_cmd
== AT_ATP_ISSUE_REQUEST_TICKLE
) {
969 * ignore the ack for the tickle request
971 scb
= (asp_scb_t
*)iocbp
->ioc_cr
;
972 scb
->tickle_tid
= (unsigned short)iocbp
->ioc_rval
;
977 scb
= (asp_scb_t
*)gref
->info
;
983 if (iocbp
->ioc_cmd
== AT_ATP_GET_POLL
) {
985 * if no data, just drop the request
987 if ((mdata
= gbuf_cont(mioc
)) == 0) {
992 gbuf_set_type(mioc
, MSG_IOCTL
);
993 ddp
= (at_ddp_t
*)gbuf_rptr(mdata
);
994 gbuf_rinc(mdata
,DDP_X_HDR_SIZE
);
995 atp
= (at_atp_t
*)gbuf_rptr(mdata
);
996 gbuf_rinc(mdata
,ATP_HDR_SIZE
);
997 rem_addr
.net
= NET_VALUE(ddp
->src_net
);
998 rem_addr
.node
= ddp
->src_node
;
999 rem_addr
.socket
= ddp
->src_socket
;
1000 awp
= (asp_word_t
*)atp
->user_bytes
;
1002 if (scb
->next_scb
) {
1004 * find the responsible scb
1006 if ((scb
= asp_find_scb(scb
->loc_addr
.socket
, &rem_addr
)) == 0) {
1011 dPrintf(D_M_ASP
, D_L_INFO
,
1012 ("asp_ack_reply: %s, loc=%d, rem=%x.%x.%d\n",
1013 aspCmdStr(awp
->func
),scb
->loc_addr
.socket
,
1014 NET_VALUE(ddp
->src_net
) ,ddp
->src_node
,ddp
->src_socket
));
1016 if (scb
->rem_addr
.node
)
1017 asp_untimout(asp_hangup
, scb
);
1019 switch (awp
->func
) {
1020 case ASPFUNC_GetStatus
:
1022 * ignore if this is not a server socket
1025 if ((scb
->dflag
!= 1) || (scb
->stat_msg
1026 && ((mx
= gbuf_dupb(scb
->stat_msg
)) == 0)))
1031 * send the status block
1033 if (gbuf_cont(mdata
)) {
1034 gbuf_freem(gbuf_cont(mdata
));
1035 gbuf_cont(mdata
) = 0;
1037 gbuf_rdec(mdata
,TOTAL_ATP_HDR_SIZE
);
1038 if ((m
= gbuf_alloc( (TOTAL_ATP_HDR_SIZE
+atpBDSsize
), PRI_MED
)) == 0) {
1043 bcopy(gbuf_rptr(mdata
), gbuf_rptr(m
), TOTAL_ATP_HDR_SIZE
);
1046 ddp
= (at_ddp_t
*)gbuf_rptr(mdata
);
1047 gbuf_wset(mdata
,DDP_X_HDR_SIZE
);
1048 atp
= (at_atp_t
*)gbuf_wptr(mdata
);
1049 gbuf_winc(mdata
,ATP_HDR_SIZE
);
1050 awp
= (asp_word_t
*)atp
->user_bytes
;
1051 NET_NET(ddp
->src_net
, ddp
->dst_net
);
1052 ddp
->src_node
= ddp
->dst_node
;
1053 NET_ASSIGN(ddp
->dst_net
, rem_addr
.net
);
1054 ddp
->dst_node
= rem_addr
.node
;
1055 ddp
->dst_socket
= rem_addr
.socket
;
1056 UAS_ASSIGN(ddp
->checksum
, 0);
1057 atpBDS
= (struct atpBDS
*)gbuf_wptr(mdata
);
1058 msize
= mx
? gbuf_msgsize(mx
) : 0;
1059 for (nbds
=0; (nbds
< ATP_TRESP_MAX
) && (msize
> 0); nbds
++) {
1060 len
= msize
< ATP_DATA_SIZE
? msize
: ATP_DATA_SIZE
;
1061 msize
-= ATP_DATA_SIZE
;
1062 *(long *)atpBDS
[nbds
].bdsUserData
= 0;
1063 UAL_ASSIGN(atpBDS
[nbds
].bdsBuffAddr
, 1);
1064 UAS_ASSIGN(atpBDS
[nbds
].bdsBuffSz
, len
);
1066 UAS_ASSIGN(atpBDS
[0].bdsDataSz
, nbds
);
1067 gbuf_winc(mdata
,atpBDSsize
);
1068 gbuf_cont(mdata
) = mx
;
1069 atp_send_rsp(gref
, mdata
, FALSE
);
1072 case ASPFUNC_OpenSess
:
1074 * ignore if server is not ready
1076 if ((scb
->dflag
!= 1) || (scb
->stat_msg
== 0))
1080 if (gbuf_cont(mdata
)) {
1081 gbuf_freem(gbuf_cont(mdata
));
1082 gbuf_cont(mdata
) = 0;
1084 gbuf_rdec(mdata
,TOTAL_ATP_HDR_SIZE
);
1085 gbuf_wset(mdata
,TOTAL_ATP_HDR_SIZE
);
1086 if (awp
->param2
!= ASP_Version
) {
1088 * bad version number, send the OpenSession response
1092 awp
->param2
= (unsigned short)ASPERR_BadVersNum
;
1093 dPrintf(D_M_ASP
, D_L_INFO
,
1095 ASPERR_BadVersNum
));
1097 NET_NET(ddp
->src_net
, ddp
->dst_net
);
1098 ddp
->src_node
= ddp
->dst_node
;
1099 NET_ASSIGN(ddp
->dst_net
, rem_addr
.net
);
1100 ddp
->dst_node
= rem_addr
.node
;
1101 ddp
->dst_socket
= rem_addr
.socket
;
1102 atp_send_rsp(gref
, mdata
, FALSE
);
1107 * queue the connection request
1109 ATDISABLE(s
, scb
->lock
);
1110 gbuf_next(mdata
) = 0;
1111 if ((m
= scb
->sess_ioc
) == 0) {
1112 scb
->sess_ioc
= mdata
;
1114 wakeup(&scb
->event
);
1116 atalk_notify_sel(gref
);
1118 while (gbuf_next(m
))
1120 gbuf_next(m
) = mdata
;
1122 ATENABLE(s
, scb
->lock
);
1123 dPrintf(D_M_ASP
, D_L_INFO
,
1124 (" : QUEUE connect request\n"));
1128 case ASPFUNC_Command
:
1130 if ( (scb
->sess_id
!= awp
->param1
)
1131 || (scb
->rcv_seq_num
!= awp
->param2
)
1132 || BAD_REMADDR(rem_addr
) ) {
1134 sprintf(era
,"%d.%d", scb
->rem_addr
.node
,scb
->rem_addr
.socket
);
1135 sprintf(ra
,"%d.%d", rem_addr
.node
,rem_addr
.socket
);
1136 dPrintf(D_M_ASP
, D_L_WARNING
,
1137 (" : DROP, id=%d,esn=%d,sn=%d,erem=%s,rem=%s\n",
1138 scb
->sess_id
,scb
->rcv_seq_num
,awp
->param2
,era
,ra
));
1139 gbuf_cont(mioc
) = 0;
1140 gbuf_rdec(mdata
,TOTAL_ATP_HDR_SIZE
);
1141 atp_drop_req(gref
, mdata
);
1144 scb
->reply_socket
= rem_addr
.socket
;
1145 if (awp
->func
== ASPFUNC_Write
)
1146 scb
->wrt_seq_num
= scb
->rcv_seq_num
;
1147 NEXT_SEQ_NUM(scb
->rcv_seq_num
);
1148 gbuf_set_type(mioc
, MSG_PROTO
);
1149 gbuf_wset(mioc
,sizeof(asp_command_ind_t
));
1150 command_ind
= (asp_command_ind_t
*)gbuf_rptr(mioc
);
1151 command_ind
->Primitive
= (int)awp
->func
;
1152 command_ind
->ReqRefNum
=
1153 *(unsigned short *)atp
->tid
;
1154 command_ind
->ReqType
= awp
->func
;
1156 mdata
= gbuf_strip(mdata
);
1157 gbuf_cont(mioc
) = mdata
;
1158 ATDISABLE(s
, scb
->lock
);
1159 if (scb
->req_flag
) {
1160 if ((mx
= scb
->req_msgq
) != 0) {
1161 while (gbuf_next(mx
))
1163 gbuf_next(mx
) = mioc
;
1165 scb
->req_msgq
= mioc
;
1166 ATENABLE(s
, scb
->lock
);
1169 ATENABLE(s
, scb
->lock
);
1170 asp_putnext(scb
->gref
, mioc
);
1174 case ASPFUNC_WriteContinue
:
1175 if ( (scb
->sess_id
!= awp
->param1
)
1176 || (scb
->snd_seq_num
!= awp
->param2
)
1177 || BAD_REMADDR(rem_addr
) ) {
1180 scb
->reply_socket
= rem_addr
.socket
;
1181 gbuf_set_type(mioc
, MSG_PROTO
);
1182 gbuf_wset(mioc
,sizeof(asp_command_ind_t
));
1183 command_ind
= (asp_command_ind_t
*)gbuf_rptr(mioc
);
1184 command_ind
->Primitive
= (int)awp
->func
;
1185 command_ind
->ReqRefNum
=
1186 *(unsigned short *)atp
->tid
;
1187 command_ind
->ReqType
= awp
->func
;
1189 mdata
= gbuf_strip(mdata
);
1190 gbuf_cont(mioc
) = mdata
;
1191 asp_putnext(scb
->gref
, mioc
);
1194 case ASPFUNC_Tickle
:
1195 if (scb
->stat_msg
) {
1196 sess_scb
= asp_scbQ
[awp
->param1
];
1197 if (sess_scb
&& sess_scb
->next_scb
)
1198 sess_scb
= asp_find_scb(
1199 sess_scb
->loc_addr
.socket
, &rem_addr
);
1201 if (sess_scb
->rem_addr
.node
)
1202 asp_untimout(asp_hangup
, sess_scb
);
1203 if (sess_scb
->rem_addr
.node
)
1204 asp_timout(asp_hangup
, sess_scb
, sess_scb
->session_timer
);
1207 dPrintf(D_M_ASP
, D_L_INFO
,
1208 (" : Tickle, %d -> %d, id=%d\n",
1209 ddp
->src_socket
,ddp
->dst_socket
,awp
->param1
));
1212 case ASPFUNC_CloseSess
:
1213 if ( (scb
->sess_id
!= awp
->param1
)
1214 || (scb
->state
== ASPSTATE_Close
)
1215 || (scb
->state
== ASPSTATE_WaitingForCloseSessRsp
)
1216 || (scb
->rem_addr
.net
!= rem_addr
.net
)
1217 || (scb
->rem_addr
.node
!= rem_addr
.node
) ) {
1218 dPrintf(D_M_ASP
, D_L_INFO
,
1219 (" : CLOSE retry, loc=%d, rem=%x.%x.%d\n",
1220 scb
->loc_addr
.socket
,
1223 scb
->rem_addr
.socket
));
1230 * build the CloseSess response to be sent to peer
1231 * when the session is closed by the user.
1233 if (gbuf_cont(mdata
)) {
1234 gbuf_freem(gbuf_cont(mdata
));
1235 gbuf_cont(mdata
) = 0;
1237 gbuf_rdec(mdata
,TOTAL_ATP_HDR_SIZE
);
1238 gbuf_wset(mdata
,TOTAL_ATP_HDR_SIZE
);
1239 NET_NET(ddp
->src_net
, ddp
->dst_net
);
1240 ddp
->src_node
= ddp
->dst_node
;
1241 NET_ASSIGN(ddp
->dst_net
, rem_addr
.net
);
1242 ddp
->dst_node
= rem_addr
.node
;
1243 ddp
->dst_socket
= rem_addr
.socket
;
1247 dPrintf(D_M_ASP
,D_L_INFO
,
1248 (" : CLOSE, loc=%d, rem=%x.%x.%d\n",
1249 scb
->loc_addr
.socket
,
1252 scb
->rem_addr
.socket
));
1254 gbuf_next(mdata
) = 0;
1255 ATDISABLE(s
, scb
->lock
);
1257 gbuf_freel(scb
->sess_ioc
);
1258 scb
->sess_ioc
= mdata
;
1259 scb
->state
= ASPSTATE_Close
;
1260 ATENABLE(s
, scb
->lock
);
1263 * notify upstream of the CloseSess from peer
1268 case ASPFUNC_Attention
:
1269 if ( (scb
->sess_id
!= awp
->param1
)
1270 || (scb
->rem_addr
.net
!= rem_addr
.net
)
1271 || (scb
->rem_addr
.node
!= rem_addr
.node
) ) {
1274 gbuf_set_type(mioc
, MSG_PROTO
);
1275 gbuf_wset(mioc
,sizeof(asp_command_ind_t
));
1276 command_ind
= (asp_command_ind_t
*)gbuf_rptr(mioc
);
1277 command_ind
->Primitive
= (int)awp
->func
;
1278 command_ind
->ReqRefNum
=
1279 *(unsigned short *)atp
->tid
;
1280 command_ind
->ReqType
= awp
->func
;
1281 scb
->attn_tid
= *(unsigned short *)atp
->tid
;
1283 gbuf_rdec(mdata
,2); /* attention code */
1285 mdata
= gbuf_strip(mdata
);
1286 gbuf_cont(mioc
) = mdata
;
1287 asp_putnext(scb
->gref
, mioc
);
1291 dPrintf(D_M_ASP
, D_L_WARNING
,
1292 (" : UNKNOWN func, func=%d\n",
1299 else if (iocbp
->ioc_cmd
== AT_ATP_REQUEST_COMPLETE
) {
1300 if (scb
->next_scb
) {
1302 * find the responsible scb
1304 scb
= (asp_scb_t
*)iocbp
->ioc_private
;
1305 if ((scb
== 0) || (scb
->magic_num
!= 222)) {
1306 dPrintf(D_M_ASP
, D_L_ERROR
,
1307 ("asp_ack_reply: CAN'T find scb 1\n"));
1312 dPrintf(D_M_ASP
, D_L_INFO
,
1313 ("asp_ack_reply: RSP, loc=%d, rem=%x.%x.%d, state=%s\n",
1314 scb
->loc_addr
.socket
,
1317 scb
->rem_addr
.socket
,
1318 aspStateStr(scb
->state
)));
1320 switch (scb
->state
) {
1321 case ASPSTATE_Close
:
1323 scb
->rem_addr
.node
= 0;
1325 ATDISABLE(s
, scb
->lock
);
1327 wakeup(&scb
->event
);
1329 atalk_notify_sel(gref
);
1330 ATENABLE(s
, scb
->lock
);
1333 case ASPSTATE_WaitingForGetStatusRsp
:
1335 scb
->state
= ASPSTATE_Idle
;
1336 mx
= gbuf_cont(mioc
);
1337 gbuf_cont(mioc
) = 0;
1338 mdata
= gbuf_cont(mx
);
1340 iocbp
->ioc_cmd
= ASPIOC_GetStatus
;
1341 iocbp
->ioc_count
= 0;
1342 iocbp
->ioc_rval
= mdata
? gbuf_msgsize(mdata
) : 0;
1344 atalk_putnext(gref
, mioc
);
1345 atalk_putnext(gref
, mdata
);
1348 case ASPSTATE_WaitingForOpenSessRsp
:
1350 scb
->state
= ASPSTATE_Idle
;
1351 mx
= gbuf_cont(mioc
);
1352 gbuf_cont(mioc
) = 0;
1353 if (gbuf_cont(mx
)) {
1354 gbuf_freem(gbuf_cont(mx
));
1357 iocbp
->ioc_cmd
= ASPIOC_OpenSession
;
1358 iocbp
->ioc_rval
= 0;
1359 iocbp
->ioc_count
= 0;
1360 atpBDS
= (struct atpBDS
*)gbuf_rptr(mx
);
1361 awp
= (asp_word_t
*)atpBDS
->bdsUserData
;
1364 asp_iocnak(gref
, mioc
, ECONNREFUSED
);
1366 scb
->rem_addr
.node
= scb
->rem_node
;
1367 scb
->rem_addr
.socket
= awp
->func
;
1368 /* bms: need to set the reply_socket for client side too.
1369 This makes ALO atten replies sent by the client work. */
1370 scb
->reply_socket
= scb
->rem_addr
.socket
;
1371 scb
->sess_id
= awp
->param1
;
1373 atalk_putnext(gref
, mioc
);
1374 asp_timout(asp_hangup
, scb
, scb
->session_timer
);
1375 asp_send_tickle(scb
);
1376 dPrintf(D_M_ASP
, D_L_INFO
,
1377 ("asp_ack_reply: CONNECT, loc=%d, rem=%x.%x.%d\n",
1378 scb
->loc_addr
.socket
,
1381 scb
->rem_addr
.socket
));
1385 case ASPSTATE_WaitingForCommandRsp
:
1386 case ASPSTATE_WaitingForWriteRsp
:
1387 case ASPSTATE_WaitingForWriteContinueRsp
:
1388 if (scb
->rem_addr
.node
)
1389 asp_untimout(asp_hangup
, scb
);
1390 NEXT_SEQ_NUM(scb
->snd_seq_num
);
1391 scb
->state
= ASPSTATE_Idle
;
1392 gbuf_set_type(mioc
, MSG_PROTO
);
1393 mx
= gbuf_cont(mioc
);
1394 mdata
= gbuf_cont(mx
);
1395 gbuf_cont(mioc
) = mdata
;
1396 atpBDS
= (struct atpBDS
*)gbuf_rptr(mx
);
1397 cmdreply_ind
= (asp_cmdreply_ind_t
*)gbuf_rptr(mioc
);
1398 cmdreply_ind
->Primitive
= ASPFUNC_CmdReply
;
1399 cmdreply_ind
->CmdResult
= *(int *)atpBDS
->bdsUserData
;
1400 gbuf_wset(mioc
,sizeof(asp_cmdreply_ind_t
));
1402 asp_putnext(scb
->gref
, mioc
);
1405 case ASPSTATE_WaitingForCloseSessRsp
:
1407 scb
->state
= ASPSTATE_Close
;
1408 scb
->rem_addr
.node
= 0;
1409 iocbp
->ioc_cmd
= ASPIOC_CloseSession
;
1410 iocbp
->ioc_rval
= 0;
1411 if (gbuf_cont(mioc
)) {
1412 gbuf_freem(gbuf_cont(mioc
));
1413 gbuf_cont(mioc
) = 0;
1415 atalk_putnext(scb
->gref
, mioc
);
1416 atp_cancel_req(scb
->gref
, (unsigned int)scb
->tickle_tid
);
1417 scb
->tickle_tid
= 0;
1421 dPrintf(D_M_ASP
, D_L_WARNING
,
1422 (" : UNKNOWN state, state=%s\n",
1423 aspStateStr(scb
->state
)));
1429 if (scb
->next_scb
) {
1431 * find the responsible scb
1433 scb
= (asp_scb_t
*)iocbp
->ioc_cr
;
1434 if ((scb
== 0) || (scb
->magic_num
!= 222)) {
1435 dPrintf(D_M_ASP
, D_L_ERROR
,
1436 ("asp_ack_reply: CAN'T find scb 2\n"));
1442 switch (scb
->state
) {
1443 case ASPSTATE_Close
:
1444 scb
->rem_addr
.node
= 0;
1453 if (scb
->rem_addr
.node
)
1454 asp_timout(asp_hangup
, scb
, scb
->session_timer
);
1455 } /* asp_ack_reply */
1461 asp_nak_reply(gref
, mioc
)
1462 register gref_t
*gref
;
1463 register gbuf_t
*mioc
;
1465 register asp_scb_t
*scb
;
1466 register ioc_t
*iocbp
;
1468 iocbp
= (ioc_t
*)gbuf_rptr(mioc
);
1470 if (iocbp
->ioc_cmd
== AT_ATP_ISSUE_REQUEST_TICKLE
) {
1472 * no tickle, close session
1474 scb
= (asp_scb_t
*)iocbp
->ioc_cr
;
1477 dPrintf(D_M_ASP
, D_L_WARNING
,
1478 ("tickle_nak: loc=%d, rem=%x.%x.%d, state=%s\n",
1479 scb
->loc_addr
.socket
,
1482 scb
->rem_addr
.socket
,
1483 aspStateStr(scb
->state
)));
1488 scb
= (asp_scb_t
*)gref
->info
;
1494 if (iocbp
->ioc_cmd
== AT_ATP_REQUEST_COMPLETE
) {
1495 if (scb
->next_scb
) {
1497 * find the responsible scb
1499 scb
= (asp_scb_t
*)iocbp
->ioc_private
;
1500 if ((scb
== 0) || (scb
->magic_num
!= 222)) {
1501 dPrintf(D_M_ASP
, D_L_ERROR
,
1502 ("asp_nak_reply: CAN'T find scb 1\n"));
1507 dPrintf(D_M_ASP
, D_L_WARNING
,
1508 ("asp_nak_reply: RSP, loc=%d, rem=%x.%x.%d, state=%s\n",
1509 scb
->loc_addr
.socket
,
1512 scb
->rem_addr
.socket
,
1513 aspStateStr(scb
->state
)));
1515 switch (scb
->state
) {
1516 case ASPSTATE_WaitingForGetStatusRsp
:
1517 iocbp
->ioc_cmd
= ASPIOC_GetStatus
;
1520 case ASPSTATE_WaitingForOpenSessRsp
:
1521 iocbp
->ioc_cmd
= ASPIOC_OpenSession
;
1524 case ASPSTATE_WaitingForCommandRsp
:
1525 case ASPSTATE_WaitingForWriteRsp
:
1526 case ASPSTATE_WaitingForWriteContinueRsp
:
1527 scb
->state
= ASPSTATE_Idle
;
1529 /* last remaining use of MSG_ERROR */
1530 gbuf_set_type(mioc
, MSG_ERROR
);
1531 *gbuf_rptr(mioc
) = (u_char
)EPROTOTYPE
;
1533 if (gbuf_cont(mioc
)) {
1534 gbuf_freem(gbuf_cont(mioc
));
1535 gbuf_cont(mioc
) = 0;
1538 asp_putnext(scb
->gref
, mioc
);
1541 case ASPSTATE_WaitingForCloseSessRsp
:
1542 scb
->state
= ASPSTATE_Close
;
1544 case ASPSTATE_Close
: /* new for PR-2296832 */
1545 scb
->rem_addr
.node
= 0;
1546 iocbp
->ioc_cmd
= ASPIOC_CloseSession
;
1547 iocbp
->ioc_rval
= 0;
1548 if (gbuf_cont(mioc
)) {
1549 gbuf_freem(gbuf_cont(mioc
));
1550 gbuf_cont(mioc
) = 0;
1552 gbuf_set_type(mioc
, MSG_IOCACK
);
1553 atalk_putnext(scb
->gref
, mioc
);
1560 scb
->state
= ASPSTATE_Idle
;
1561 atalk_putnext(gref
, mioc
);
1565 if (scb
->next_scb
) {
1567 * find the responsible scb
1569 scb
= (asp_scb_t
*)iocbp
->ioc_cr
;
1570 if ((scb
== 0) || (scb
->magic_num
!= 222)) {
1571 dPrintf(D_M_ASP
, D_L_ERROR
,
1572 ("asp_nak_reply: CAN'T find scb 2\n"));
1578 switch (scb
->state
) {
1579 case ASPSTATE_Close
:
1580 scb
->rem_addr
.node
= 0;
1586 } /* asp_nak_reply */
1589 * delete scb from the use list
1592 asp_dequeue_scb(scb
)
1597 ATDISABLE(s
, aspall_lock
);
1598 if (scb
== scb_used_list
) {
1599 if ((scb_used_list
= scb
->next_scb
) != 0)
1600 scb
->next_scb
->prev_scb
= 0;
1602 if ((scb
->prev_scb
->next_scb
= scb
->next_scb
) != 0)
1603 scb
->next_scb
->prev_scb
= scb
->prev_scb
;
1605 ATENABLE(s
, aspall_lock
);
1614 StaticProc asp_scb_t
*
1615 asp_find_scb(sock_num
, rem_addr
)
1616 unsigned char sock_num
;
1617 at_inet_t
*rem_addr
;
1621 asp_scb_t
*alt_scb
= 0;
1623 ATDISABLE(s
, aspall_lock
);
1624 for (scb
= asp_scbQ
[sock_num
]; scb
; scb
= scb
->next_scb
) {
1625 if ((scb
->rem_addr
.net
== rem_addr
->net
)
1626 && (scb
->rem_addr
.node
== rem_addr
->node
)) {
1627 if ((scb
->rem_addr
.socket
== rem_addr
->socket
)
1628 || (scb
->rem_socket
== rem_addr
->socket
))
1630 else if (alt_scb
== 0)
1635 if ((scb
== 0) && ((scb
= alt_scb
) == 0)) {
1636 dPrintf(D_M_ASP
, D_L_ERROR
,
1637 ("asp_find_scb: CAN'T find scb, loc=%d, rem=%x.%x.%d\n",
1643 ATENABLE(s
, aspall_lock
);
1652 asp_timout(func
, scb
, seconds
)
1654 register asp_scb_t
*scb
;
1659 register asp_scb_t
*curr_scb
, *prev_scb
;
1664 scb
->tmo_func
= func
;
1665 scb
->tmo_delta
= (seconds
>>SESS_TMO_RES
);
1666 scb
->tmo_cnt
= scb_tmo_cnt
;
1668 ATDISABLE(s
, asptmo_lock
);
1669 if (scb_tmo_list
== 0) {
1670 scb
->next_tmo
= scb
->prev_tmo
= 0;
1672 ATENABLE(s
, asptmo_lock
);
1677 curr_scb
= scb_tmo_list
;
1681 sum
+= curr_scb
->tmo_delta
;
1682 if (sum
> scb
->tmo_delta
) {
1683 sum
-= curr_scb
->tmo_delta
;
1684 scb
->tmo_delta
-= sum
;
1685 curr_scb
->tmo_delta
-= scb
->tmo_delta
;
1688 prev_scb
= curr_scb
;
1689 if ((curr_scb
= curr_scb
->next_tmo
) == 0) {
1690 scb
->tmo_delta
-= sum
;
1696 scb
->prev_tmo
= prev_scb
;
1697 if ((scb
->next_tmo
= prev_scb
->next_tmo
) != 0)
1698 prev_scb
->next_tmo
->prev_tmo
= scb
;
1699 prev_scb
->next_tmo
= scb
;
1702 scb
->next_tmo
= scb_tmo_list
;
1703 scb_tmo_list
->prev_tmo
= scb
;
1706 ATENABLE(s
, asptmo_lock
);
1713 asp_untimout(func
, scb
)
1715 register asp_scb_t
*scb
;
1719 if ((scb
->tmo_cnt
== scb_tmo_cnt
) || (scb
->tmo_func
== 0))
1722 ATDISABLE(s
, asptmo_lock
);
1723 if (scb_tmo_list
== scb
) {
1724 if ((scb_tmo_list
= scb
->next_tmo
) != 0) {
1725 scb_tmo_list
->prev_tmo
= 0;
1726 scb
->next_tmo
->tmo_delta
+= scb
->tmo_delta
;
1728 } else if (scb
->prev_tmo
) {
1729 if ((scb
->prev_tmo
->next_tmo
= scb
->next_tmo
) != 0) {
1730 scb
->next_tmo
->prev_tmo
= scb
->prev_tmo
;
1731 scb
->next_tmo
->tmo_delta
+= scb
->tmo_delta
;
1736 ATENABLE(s
, asptmo_lock
);
1749 * set the state to Close
1751 ATDISABLE(s
, scb
->lock
);
1752 scb
->state
= ASPSTATE_Close
;
1753 if (scb
->tickle_tid
) {
1754 atp_cancel_req(scb
->gref
, (unsigned int)scb
->tickle_tid
);
1755 scb
->tickle_tid
= 0;
1759 * notify upstream of the hangup
1761 if (scb
->rem_addr
.node
) {
1762 if (scb
->get_wait
) {
1763 wakeup(&scb
->event
);
1764 ATENABLE(s
, scb
->lock
);
1766 ATENABLE(s
, scb
->lock
);
1767 atalk_notify_sel(scb
->gref
);
1770 ATENABLE(s
, scb
->lock
);
1774 asp_iocack(gref
, mioc
)
1778 if (gbuf_cont(mioc
))
1779 ((ioc_t
*)gbuf_rptr(mioc
))->ioc_count
= gbuf_msgsize(gbuf_cont(mioc
));
1781 ((ioc_t
*)gbuf_rptr(mioc
))->ioc_count
= 0;
1783 gbuf_set_type(mioc
, MSG_IOCACK
);
1784 atalk_putnext(gref
, mioc
);
1788 asp_iocnak(gref
, mioc
, err
)
1793 ((ioc_t
*)gbuf_rptr(mioc
))->ioc_count
= 0;
1796 ((ioc_t
*)gbuf_rptr(mioc
))->ioc_error
= err
;
1797 ((ioc_t
*)gbuf_rptr(mioc
))->ioc_rval
= -1;
1798 if (gbuf_cont(mioc
)) {
1799 gbuf_freem(gbuf_cont(mioc
));
1800 gbuf_cont(mioc
) = 0;
1803 gbuf_set_type(mioc
, MSG_IOCNAK
);
1804 atalk_putnext(gref
, mioc
);
1808 * the alloc scb routine
1810 StaticProc asp_scb_t
*
1815 asp_scb_t
*scb
, *scb_array
;
1817 ATDISABLE(s
, aspall_lock
);
1818 if (scb_free_list
== 0) {
1819 if ((m
= gbuf_alloc(SCBS_PER_BLK
*sizeof(asp_scb_t
), PRI_MED
)) == 0)
1821 ATENABLE(s
, aspall_lock
);
1822 return (asp_scb_t
*)0;
1824 bzero((char *)gbuf_rptr(m
), SCBS_PER_BLK
*sizeof(asp_scb_t
));
1825 gbuf_cont(m
) = scb_resource_m
;
1827 scb_array
= (asp_scb_t
*)gbuf_rptr(m
);
1828 for (i
=0; i
< SCBS_PER_BLK
-1; i
++)
1829 scb_array
[i
].next_scb
= (asp_scb_t
*)&scb_array
[i
+1];
1830 scb_array
[i
].next_scb
= 0;
1831 scb_free_list
= (asp_scb_t
*)&scb_array
[0];
1834 scb
= scb_free_list
;
1835 scb_free_list
= scb
->next_scb
;
1836 ATENABLE(s
, aspall_lock
);
1837 ATLOCKINIT(scb
->lock
);
1838 ATLOCKINIT(scb
->delay_lock
);
1839 ATEVENTINIT(scb
->event
);
1840 ATEVENTINIT(scb
->delay_event
);
1846 * the free scb routine
1854 bzero((char *)scb
, sizeof(asp_scb_t
));
1855 ATDISABLE(s
, aspall_lock
);
1856 scb
->next_scb
= scb_free_list
;
1857 scb_free_list
= scb
;
1858 ATENABLE(s
, aspall_lock
);
1862 * routine to pass up receive data
1865 asp_putnext(gref
, mproto
)
1873 scb
= (asp_scb_t
*)gref
->info
;
1876 * queue the message.
1878 ATDISABLE(s
, scb
->lock
);
1879 gbuf_next(mproto
) = 0;
1880 if ((m
= scb
->sess_ioc
) == 0)
1881 scb
->sess_ioc
= mproto
;
1883 while (gbuf_next(m
))
1885 gbuf_next(m
) = mproto
;
1888 if (scb
->rcv_cnt
>= MAX_RCV_CNT
)
1891 if (scb
->get_wait
) {
1892 wakeup(&scb
->event
);
1893 ATENABLE(s
, scb
->lock
);
1894 } else if (mproto
== scb
->sess_ioc
) {
1895 ATENABLE(s
, scb
->lock
);
1896 atalk_notify_sel(gref
);
1898 ATENABLE(s
, scb
->lock
);
1902 * The following two routines are direct entries from system
1903 * calls to allow fast sending and recving of ASP data.
1906 /* in ASPputmsg we expect:
1912 ASPFUNC_WriteContinue
1914 bms: Make this callable from the kernel.
1915 If mreq != NULL, then must be called from kernel space and the following apply:
1916 1) *mreq is data to be sent already in mbuf chains.
1917 2) datptr->len = size of data
1920 int ASPputmsg(gref_t
*gref
, strbuf_t
*ctlptr
, strbuf_t
*datptr
, gbuf_t
*mreq
, int flags
, int *errp
)
1922 int s
, i
, err
, len
, offset
, remain
, size
, copy_len
;
1923 gbuf_t
*mioc
, *mdata
, *mx
, *m0
;
1928 int nbds
, result
, msize
, Primitive
;
1929 unsigned char *wptr
;
1930 struct atp_set_default
*sd
;
1933 struct atpBDS
*atpBDS
;
1935 union asp_primitives
*primitives
;
1939 if ((scb
= (asp_scb_t
*)gref
->info
) == 0) {
1940 dPrintf(D_M_ASP
, D_L_ERROR
,
1941 ("ASPputmsg: stale handle=0x%x, pid=%d\n",
1942 (u_int
) gref
, gref
->pid
));
1948 if (scb
->state
== ASPSTATE_Close
)
1950 if (scb
->snd_stop
) {
1956 * copy in the control and data info
1959 /* being called from kernel space */
1960 bcopy (ctlptr
, &ctlbuf
, sizeof (strbuf_t
));
1961 bcopy (datptr
, &datbuf
, sizeof (strbuf_t
));
1963 /* being called from user space */
1964 if ((err
= copyin(CAST_USER_ADDR_T(ctlptr
), (caddr_t
)&ctlbuf
, sizeof(ctlbuf
))) != 0)
1966 if ((err
= copyin(CAST_USER_ADDR_T(datptr
), (caddr_t
)&datbuf
, sizeof(datbuf
))) != 0)
1971 * allocate buffer and copy in the control content
1973 if (!(mioc
= gbuf_alloc_wait(ctlbuf
.len
, TRUE
))) {
1974 /* error return should not be possible */
1978 gbuf_set_type(mioc
, MSG_IOCTL
); /* for later, in ATP */
1979 gbuf_wset(mioc
, ctlbuf
.len
);
1982 /* being called from kernel space */
1983 bcopy (ctlbuf
.buf
, gbuf_rptr(mioc
), ctlbuf
.len
);
1985 /* being called from user space */
1986 if ((err
= copyin(CAST_USER_ADDR_T(ctlbuf
.buf
), (caddr_t
)gbuf_rptr(mioc
), ctlbuf
.len
)) != 0) {
1992 iocbp
= (ioc_t
*)gbuf_rptr(mioc
);
1993 primitives
= (union asp_primitives
*)gbuf_rptr(mioc
);
1994 Primitive
= primitives
->Primitive
;
1995 dPrintf(D_M_ASP
, D_L_INFO
,
1996 ("ASPputmsg: %s\n", aspCmdStr(Primitive
)));
1999 * copy in the data content into multiple mbuf clusters if
2000 * required. ATP now expects reply data to be placed in
2001 * standard clusters, not the large external clusters that
2002 * were used previously.
2005 /* set offset for use by some commands */
2006 offset
= (Primitive
== ASPFUNC_CmdReply
) ? 0 : aspCMDsize
;
2009 /* The data from the in-kernel call for use by AFP is passed
2010 * in as one large external cluster. This needs to be copied
2011 * to a chain of standard clusters.
2013 remain
= gbuf_len(mreq
);
2014 dataptr
= mtod(mreq
, caddr_t
);
2016 /* copyin from user space */
2017 remain
= datbuf
.len
;
2018 dataptr
= (caddr_t
)datbuf
.buf
;
2021 /* allocate first buffer */
2022 if (!(mdata
= gbuf_alloc_wait((remain
+ offset
> MCLBYTES
? MCLBYTES
: remain
+ offset
), TRUE
))) {
2023 /* error return should not be possible */
2028 gbuf_wset(mdata
, 0); /* init length to zero */
2029 gbuf_cont(mioc
) = mdata
;
2032 if (remain
+ offset
> MCLBYTES
)
2033 copy_len
= MCLBYTES
- offset
;
2038 bcopy (dataptr
, (gbuf_rptr(mdata
) + offset
), copy_len
);
2039 else if ((err
= copyin(CAST_USER_ADDR_T(dataptr
), (caddr_t
)(gbuf_rptr(mdata
) + offset
), copy_len
)) != 0) {
2043 gbuf_wset(mdata
, (copy_len
+ offset
));
2044 size
+= copy_len
+ offset
;
2045 dataptr
+= copy_len
;
2048 /* allocate the next mbuf */
2049 if ((gbuf_cont(mdata
) = m_get((M_WAIT
), MSG_DATA
)) == 0) {
2054 mdata
= gbuf_cont(mdata
);
2055 MCLGET(mdata
, M_WAIT
);
2056 if (!(mdata
->m_flags
& M_EXT
)) {
2063 mdata
= gbuf_cont(mioc
); /* code further on down expects this to b e set */
2064 mdata
->m_pkthdr
.len
= size
; /* set packet hdr len */
2069 switch (Primitive
) {
2071 case ASPFUNC_Command
:
2073 case ASPFUNC_WriteContinue
:
2074 case ASPFUNC_Attention
:
2076 * build the command/write/write_continue request
2078 wptr
= gbuf_rptr(mdata
);
2079 atpBDS
= (struct atpBDS
*)wptr
;
2081 for (i
=0; i
< ATP_TRESP_MAX
; i
++) {
2082 *(unsigned long *)atpBDS
[i
].bdsBuffAddr
= 1;
2083 *(unsigned short *)atpBDS
[i
].bdsBuffSz
= ATP_DATA_SIZE
;
2085 sd
= (struct atp_set_default
*)wptr
;
2086 wptr
+= sizeof(struct atp_set_default
);
2087 sd
->def_retries
= (scb
->cmd_retry
.retries
== -1) ?
2088 ATP_INFINITE_RETRIES
: scb
->cmd_retry
.retries
;
2089 sd
->def_rate
= scb
->cmd_retry
.interval
*TICKS_PER_SEC
;
2090 sd
->def_BDSlen
= atpBDSsize
;
2091 ddp
= (at_ddp_t
*)wptr
;
2092 NET_ASSIGN(ddp
->src_net
, scb
->loc_addr
.net
);
2093 ddp
->src_node
= scb
->loc_addr
.node
;
2094 NET_ASSIGN(ddp
->dst_net
, scb
->rem_addr
.net
);
2095 ddp
->dst_node
= scb
->rem_addr
.node
;
2096 ddp
->dst_socket
= scb
->rem_addr
.socket
;
2097 UAS_ASSIGN(ddp
->checksum
, 0);
2098 atp
= ATP_ATP_HDR(wptr
);
2099 wptr
+= TOTAL_ATP_HDR_SIZE
;
2103 awp
= (asp_word_t
*)atp
->user_bytes
;
2104 awp
->func
= (unsigned char)Primitive
;
2105 awp
->param1
= scb
->sess_id
;
2106 awp
->param2
= scb
->snd_seq_num
;
2107 iocbp
->ioc_private
= (void *)scb
;
2108 iocbp
->ioc_count
= gbuf_len(mdata
);
2109 iocbp
->ioc_rval
= 0;
2110 iocbp
->ioc_cmd
= AT_ATP_ISSUE_REQUEST_DEF
;
2113 * send the command/write/write_continue/attention request
2115 ATDISABLE(s
, scb
->lock
);
2116 switch (awp
->func
) {
2117 case ASPFUNC_Command
:
2118 scb
->state
= ASPSTATE_WaitingForCommandRsp
;
2121 scb
->state
= ASPSTATE_WaitingForWriteRsp
;
2123 case ASPFUNC_WriteContinue
:
2124 scb
->state
= ASPSTATE_WaitingForWriteContinueRsp
;
2125 awp
->param2
= scb
->wrt_seq_num
;
2127 case ASPFUNC_Attention
:
2128 scb
->state
= ASPSTATE_WaitingForCommandRsp
;
2133 awp
->param2
= *(unsigned short *)gbuf_wptr(mdata
);
2136 ATENABLE(s
, scb
->lock
);
2137 dPrintf(D_M_ASP
,D_L_INFO
,
2138 ("ASPputmsg: %s, loc=%d, rem=%x.%x.%d\n",
2139 (awp
->func
== ASPFUNC_Command
? "CommandReq" :
2140 awp
->func
== ASPFUNC_Write
? "WriteReq" :
2141 awp
->func
== ASPFUNC_WriteContinue
? "WriteContinue" :
2142 "AttentionReq"),scb
->loc_addr
.socket
,
2143 NET_VALUE(ddp
->dst_net
),ddp
->dst_node
,ddp
->dst_socket
));
2144 atp_send_req(gref
, mioc
);
2147 case ASPFUNC_CmdReply
:
2149 ATDISABLE(s
, scb
->lock
);
2150 if (scb
->req_msgq
) {
2152 scb
->req_msgq
= gbuf_next(mx
);
2154 ATENABLE(s
, scb
->lock
);
2155 asp_putnext(scb
->gref
, mx
);
2158 ATENABLE(s
, scb
->lock
);
2160 result
= primitives
->CmdReplyReq
.CmdResult
;
2161 tid
= primitives
->CmdReplyReq
.ReqRefNum
;
2163 /* Re-use the original mioc mbuf to send the response. */
2164 gbuf_rinc(mioc
,sizeof(void *));
2166 ddp
= (at_ddp_t
*)gbuf_wptr(mioc
);
2167 gbuf_winc(mioc
,DDP_X_HDR_SIZE
);
2168 atp
= (at_atp_t
*)gbuf_wptr(mioc
);
2169 gbuf_winc(mioc
,ATP_HDR_SIZE
);
2170 NET_ASSIGN(ddp
->src_net
, scb
->loc_addr
.net
);
2171 ddp
->src_node
= scb
->loc_addr
.node
;
2172 NET_ASSIGN(ddp
->dst_net
, scb
->rem_addr
.net
);
2173 ddp
->dst_node
= scb
->rem_addr
.node
;
2174 ddp
->dst_socket
= scb
->reply_socket
;
2175 ddp
->type
= DDP_ATP
;
2176 UAS_ASSIGN(ddp
->checksum
, 0);
2177 UAS_ASSIGN(atp
->tid
, tid
);
2178 if (scb
->attn_flag
&& (tid
== scb
->attn_tid
)) {
2186 /* setup the atpBDS struct - only the length field is used,
2187 * except for the first one which contains the bds count in
2190 atpBDS
= (struct atpBDS
*)gbuf_wptr(mioc
);
2191 msize
= mdata
? gbuf_msgsize(mdata
) : 0;
2192 for (nbds
=0; (nbds
< ATP_TRESP_MAX
) && (msize
> 0); nbds
++) {
2193 len
= msize
< ATP_DATA_SIZE
? msize
: ATP_DATA_SIZE
;
2194 msize
-= ATP_DATA_SIZE
;
2195 *(long *)atpBDS
[nbds
].bdsUserData
= 0;
2196 UAL_ASSIGN(atpBDS
[nbds
].bdsBuffAddr
, 1);
2197 UAS_ASSIGN(atpBDS
[nbds
].bdsBuffSz
, len
);
2199 UAS_ASSIGN(atpBDS
[0].bdsDataSz
, nbds
);
2200 *(long *)atpBDS
[0].bdsUserData
= (long)result
;
2201 *(long *)atp
->user_bytes
= (long)result
;
2202 gbuf_winc(mioc
,atpBDSsize
);
2203 dPrintf(D_M_ASP
, D_L_INFO
,
2204 ("ASPputmsg: ATP CmdReplyReq, loc=%d, state=%s, msgsize = %d, result = %d, tid = %d\n",
2205 scb
->loc_addr
.socket
, aspStateStr(scb
->state
),
2206 (mdata
? gbuf_msgsize(mdata
) : 0), result
, tid
));
2207 atp_send_rsp(gref
, mioc
, TRUE
);
2211 /* Not an expected ASPFUNC */
2221 /* bms: make this callable from kernel. reply date is passed back as a mbuf chain in *mreply */
2222 int ASPgetmsg(gref_t
*gref
, strbuf_t
*ctlptr
, strbuf_t
*datptr
, gbuf_t
**mreply
, int *flags
, int *errp
)
2224 int err
, s
, len
, sum
, rval
;
2225 gbuf_t
*mproto
, *mdata
;
2229 unsigned char get_wait
;
2231 if ((scb
= (asp_scb_t
*)gref
->info
) == 0) {
2232 dPrintf(D_M_ASP
, D_L_ERROR
,
2233 ("ASPgetmsg: stale handle=0x%x, pid=%d\n",
2234 (u_int
) gref
, gref
->pid
));
2240 ATDISABLE(s
, scb
->lock
);
2241 if (scb
->state
== ASPSTATE_Close
) {
2242 ATENABLE(s
, scb
->lock
);
2249 while ((mproto
= scb
->sess_ioc
) == 0) {
2251 lck_mtx_assert(atalk_mutex
, LCK_MTX_ASSERT_OWNED
);
2252 err
= msleep(&scb
->event
, atalk_mutex
, PSOCK
| PCATCH
, "aspgetmsg", 0);
2255 ATENABLE(s
, scb
->lock
);
2259 if (scb
->state
== ASPSTATE_Close
) {
2261 ATENABLE(s
, scb
->lock
);
2265 get_wait
= scb
->get_wait
;
2267 if ((ctlptr
== 0) && (datptr
== 0)) {
2268 ATENABLE(s
, scb
->lock
);
2271 scb
->sess_ioc
= gbuf_next(mproto
);
2272 mdata
= gbuf_cont(mproto
);
2273 ATENABLE(s
, scb
->lock
);
2275 /* last remaining use of MSG_ERROR */
2276 if (gbuf_type(mproto
) == MSG_ERROR
) {
2277 err
= (int)gbuf_rptr(mproto
)[0];
2282 * copy in the control and data info
2284 if (mreply
!= NULL
) {
2285 /* called from kernel space */
2286 bcopy (ctlptr
, &ctlbuf
, sizeof(ctlbuf
));
2287 bcopy (datptr
, &datbuf
, sizeof(datbuf
));
2289 /* called from user space */
2290 if ((err
= copyin(CAST_USER_ADDR_T(ctlptr
),
2291 (caddr_t
)&ctlbuf
, sizeof(ctlbuf
))) != 0)
2293 if ((err
= copyin(CAST_USER_ADDR_T(datptr
),
2294 (caddr_t
)&datbuf
, sizeof(datbuf
))) != 0)
2297 if ((datbuf
.maxlen
< 0) || (datbuf
.maxlen
< gbuf_msgsize(mdata
))) {
2298 ATDISABLE(s
, scb
->lock
);
2299 gbuf_next(mproto
) = scb
->sess_ioc
;
2300 scb
->sess_ioc
= mproto
;
2301 ATENABLE(s
, scb
->lock
);
2305 if (get_wait
== 0) {
2307 * this is a hack to support the select() call.
2308 * we're not supposed to dequeue messages in the Streams
2309 * head's read queue this way; but there is no better way.
2311 ATDISABLE(s
, scb
->lock
);
2312 if (scb
->sess_ioc
== 0) {
2313 ATENABLE(s
, scb
->lock
);
2315 ATENABLE(s
, scb
->lock
);
2316 atalk_notify_sel(gref
);
2321 * copy out the control content and info
2323 ctlbuf
.len
= gbuf_len(mproto
);
2325 if (mreply
!= NULL
) {
2326 /* called from kernel space */
2327 bcopy (gbuf_rptr(mproto
), ctlbuf
.buf
, ctlbuf
.len
);
2328 bcopy (&ctlbuf
, ctlptr
, sizeof(ctlbuf
));
2330 /* called from user space */
2331 if ((err
= copyout((caddr_t
)gbuf_rptr(mproto
),
2332 CAST_USER_ADDR_T(ctlbuf
.buf
), ctlbuf
.len
)) != 0)
2334 if ((err
= copyout((caddr_t
)&ctlbuf
,
2335 CAST_USER_ADDR_T(ctlptr
), sizeof(ctlbuf
))) != 0)
2340 * copy out the data content and info
2342 for (rval
= 0, sum
= 0; mdata
&& (rval
== 0); mdata
= gbuf_cont(mdata
))
2344 len
= gbuf_len(mdata
);
2346 if ((len
+ sum
) > datbuf
.maxlen
) {
2347 len
= datbuf
.maxlen
- sum
;
2351 if (mreply
== NULL
) {
2352 /* called from user space */
2353 if ((err
= copyout((caddr_t
)gbuf_rptr(mdata
), CAST_USER_ADDR_T(&datbuf
.buf
[sum
]), len
)) != 0)
2360 if (mreply
!= NULL
) {
2361 /* called from kernel space */
2362 bcopy (&datbuf
, datptr
, sizeof(datbuf
));
2364 /* called from user space */
2365 if ((err
= copyout((caddr_t
)&datbuf
, CAST_USER_ADDR_T(datptr
), sizeof(datbuf
))) != 0)
2369 if (mreply
!= NULL
) {
2370 /* called from kernel space */
2371 /* return the reply data in mbufs, so dont free them.
2372 Just free the proto info */
2373 mdata
= gbuf_cont(mproto
);
2375 gbuf_cont(mproto
) = NULL
;
2378 /* called from user space */
2382 ATDISABLE(s
, scb
->lock
);
2389 ATENABLE(s
, scb
->lock
);
2393 ATDISABLE(s
, scb
->lock
);
2394 gbuf_next(mproto
) = scb
->sess_ioc
;
2395 scb
->sess_ioc
= mproto
;
2396 ATENABLE(s
, scb
->lock
);