2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
23 * Copyright (c) 1995 Apple Computer, Inc.
26 * Created February 20, 1995 by Tuyen Nguyen
27 * Modified for MP, 1996 by Tuyen Nguyen
28 * Modified, March 17, 1997 by Tuyen Nguyen for MacOSX.
31 #include <sys/errno.h>
32 #include <sys/types.h>
33 #include <sys/param.h>
34 #include <machine/spl.h>
35 #include <sys/systm.h>
36 #include <sys/kernel.h>
38 #include <sys/filedesc.h>
39 #include <sys/fcntl.h>
41 #include <sys/ioctl.h>
42 #include <sys/malloc.h>
43 #include <sys/socket.h>
44 #include <sys/socketvar.h>
48 #include <netat/appletalk.h>
49 #include <netat/sysglue.h>
50 #include <netat/at_pcb.h>
51 #include <netat/atp.h>
52 #include <netat/ddp.h>
53 #include <netat/asp.h>
54 #include <netat/at_var.h>
55 #include <netat/debug.h>
58 #define CHK_LOOP(str) { \
59 if (loop_cnt++ > 100) { \
65 #define atpBDSsize (sizeof(struct atpBDS)*ATP_TRESP_MAX)
66 #define aspCMDsize (atpBDSsize+sizeof(struct atp_set_default)+TOTAL_ATP_HDR_SIZE)
67 #define SCBS_PER_BLK 16
68 #define TICKS_PER_SEC HZ
69 #define SESS_TMO_RES 2
70 #define DEF_SESS_TMO 120
71 #define NEXT_SEQ_NUM(x) (x = (x == 65535) ? 0 : (x + 1))
73 #define BAD_REMADDR(addr) \
74 ( (*(long *)&scb->rem_addr != *(long *)&addr) \
75 && ((scb->rem_addr.net != addr.net) \
76 || (scb->rem_addr.node != addr.node)) )
84 void asp_clock_funnel();
89 StaticProc asp_scb_t
*asp_find_scb();
90 StaticProc asp_scb_t
*asp_scb_alloc();
92 StaticProc
void asp_putnext();
93 StaticProc
void asp_iocack();
94 StaticProc
void asp_iocnak();
95 StaticProc
void asp_dequeue_scb();
96 StaticProc
void asp_scb_free();
97 StaticProc
void asp_timout();
98 StaticProc
void asp_untimout();
99 StaticProc
void asp_hangup();
100 StaticProc
void asp_send_tickle();
101 StaticProc
void asp_send_tickle_funnel();
102 StaticProc
void asp_accept();
103 StaticProc
int asp_send_req();
105 extern at_ifaddr_t
*ifID_home
;
106 extern int atp_pidM
[];
107 extern gref_t
*atp_inputQ
[];
108 gbuf_t
*scb_resource_m
= 0;
109 unsigned char asp_inpC
[256];
110 asp_scb_t
*asp_scbQ
[256];
112 static at_retry_t asp_def_retry
= {2, -1, 1};
113 static unsigned char scb_tmo_cnt
;
114 asp_scb_t
*scb_used_list
;
115 static asp_scb_t
*scb_tmo_list
;
116 asp_scb_t
*scb_free_list
;
117 atlock_t aspall_lock
, asptmo_lock
;
123 return (((asp_scb_t
*)gref
->info
)->sess_ioc
? 1 : 0);
133 bzero(asp_inpC
, sizeof(asp_inpC
));
134 bzero(asp_scbQ
, sizeof(asp_scbQ
));
138 * the open routine allocates a state structure
147 * if no asp structure available, return failure
149 if ((scb
= asp_scb_alloc()) == 0)
153 * initialize the gref data structure
155 gref
->info
= (void *)scb
;
156 gref
->readable
= asp_readable
;
159 * initialize the scb data structure
162 scb
->magic_num
= 222;
163 scb
->state
= ASPSTATE_Idle
;
164 scb
->pid
= gref
->pid
;
166 scb
->session_timer
= DEF_SESS_TMO
;
167 scb
->cmd_retry
= asp_def_retry
;
168 ATDISABLE(s
, aspall_lock
);
169 if ((scb
->next_scb
= scb_used_list
) != 0)
170 scb
->next_scb
->prev_scb
= scb
;
172 ATENABLE(s
, aspall_lock
);
177 dPrintf(D_M_ASP
, D_L_INFO
, ("asp_open: pid=%d\n", scb
->pid
));
182 * the close routine frees all the data structures
189 unsigned char sock_num
;
190 asp_scb_t
*scb
, *new_scb
;
193 scb
= (asp_scb_t
*)gref
->info
;
194 dPrintf(D_M_ASP
, D_L_INFO
, ("asp_close: loc=%d\n",
195 scb
->loc_addr
.socket
));
197 if (scb
->pid
&& scb
->sess_ioc
&& (scb
->dflag
!= 1)) {
199 * send the CloseSess response to peer
201 if (gbuf_type(scb
->sess_ioc
) != MSG_PROTO
) {
202 ATDISABLE(s
, scb
->lock
);
204 scb
->sess_ioc
= gbuf_next(m
);
205 ATENABLE(s
, scb
->lock
);
206 atp_send_rsp(scb
->gref
, m
, TRUE
);
210 if (scb
->atp_state
) {
211 sock_num
= scb
->loc_addr
.socket
;
212 ATDISABLE(s
, aspall_lock
);
213 if ((scb
->dflag
!= 1) && scb
->stat_msg
) {
214 untimeout(atp_retry_req
, scb
->stat_msg
);
215 gbuf_freem(scb
->stat_msg
);
218 if (asp_scbQ
[sock_num
]->next_scb
== 0) {
219 asp_scbQ
[sock_num
] = 0;
220 asp_inpC
[sock_num
] = 0;
221 ATENABLE(s
, aspall_lock
);
222 dPrintf(D_M_ASP
, D_L_INFO
,
223 (" : atp_close(), loc=%d\n", scb
->loc_addr
.socket
));
226 asp_inpC
[sock_num
]--;
227 if (scb
== asp_scbQ
[sock_num
]) {
228 new_scb
= scb
->next_scb
;
229 new_scb
->prev_scb
= 0;
230 asp_scbQ
[sock_num
] = new_scb
;
231 new_scb
->atp_state
->atp_gref
= new_scb
->gref
;
232 new_scb
->atp_state
->pid
= new_scb
->pid
;
233 atp_inputQ
[sock_num
] = new_scb
->gref
;
235 if ((scb
->prev_scb
->next_scb
= scb
->next_scb
) != 0)
236 scb
->next_scb
->prev_scb
= scb
->prev_scb
;
239 ATENABLE(s
, aspall_lock
);
242 asp_dequeue_scb(scb
);
245 * free all allocated blocks if any
247 ATDISABLE(s
, scb
->lock
);
249 gbuf_freem(scb
->stat_msg
);
253 gbuf_freel(scb
->sess_ioc
);
257 gbuf_freel(scb
->req_msgq
);
261 scb
->rem_addr
.node
= 0;
262 ATENABLE(s
, scb
->lock
);
268 asp_untimout(asp_hangup
, scb
);
269 untimeout(asp_send_tickle_funnel
, (void *)scb
); /* added for 2225395 */
272 * free the asp session control block
274 scb
->state
= ASPSTATE_Close
;
279 static char *aspStateStr(state
)
282 return ((state
==ASPSTATE_Close
)? "Close":
283 (state
==ASPSTATE_Idle
)? "Idle":
284 (state
==ASPSTATE_WaitingForGetStatusRsp
)? "GetStatusRsp":
285 (state
==ASPSTATE_WaitingForOpenSessRsp
)? "OpenSessRsp":
286 (state
==ASPSTATE_WaitingForCommandRsp
)? "CmdRsp":
287 (state
==ASPSTATE_WaitingForWriteContinue
)? "WriteCont":
288 (state
==ASPSTATE_WaitingForWriteRsp
)? "WriteRsp":
289 (state
==ASPSTATE_WaitingForWriteContinueRsp
)? "WriteContRsp":
290 (state
==ASPSTATE_WaitingForCloseSessRsp
)? "CloseSessRsp":
294 static char *aspCmdStr(aspCmd
)
297 return ((aspCmd
==ASPFUNC_CloseSess
)? "CloseSess":
298 (aspCmd
==ASPFUNC_Command
)? "Command":
299 (aspCmd
==ASPFUNC_GetStatus
)? "GetStatus":
300 (aspCmd
==ASPFUNC_OpenSess
)? "OpenSess":
301 (aspCmd
==ASPFUNC_Tickle
)? "Tickle":
302 (aspCmd
==ASPFUNC_Write
)? "Write":
303 (aspCmd
==ASPFUNC_WriteContinue
)? "WriteContinue":
304 (aspCmd
==ASPFUNC_Attention
)? "Attention":
305 (aspCmd
==ASPFUNC_CmdReply
)? "CmdReply": "unknown");
308 static char *aspIOCStr(aspIOC
)
312 (aspIOC
==ASPIOC_ClientBind
)? "ClientBind":
313 (aspIOC
==ASPIOC_CloseSession
)? "CloseSession":
314 (aspIOC
==ASPIOC_GetLocEntity
)? "GetLocEntity":
315 (aspIOC
==ASPIOC_GetRemEntity
)? "GetRemEntity":
316 (aspIOC
==ASPIOC_GetSession
)? "GetSession":
317 (aspIOC
==ASPIOC_GetStatus
)? "GetStatus":
318 (aspIOC
==ASPIOC_ListenerBind
)? "ListenerBind":
319 (aspIOC
==ASPIOC_OpenSession
)? "OpenSession":
320 (aspIOC
==ASPIOC_StatusBlock
)? "StatusBlock":
321 (aspIOC
==ASPIOC_SetPid
)? "SetPid":
322 (aspIOC
==ASPIOC_GetSessId
)? "GetSessId":
323 (aspIOC
==ASPIOC_EnableSelect
)? "EnableSelect":
324 (aspIOC
==ASPIOC_Look
)? "Look":
331 static char mbuf_str
[100];
336 "dat = %d, prot = %d, ioc = %d, err = %d, hu = %d, ack = %d, nak = %d, ctl = %d",
338 "dat = %d, prot = %d, ioc = %d, ctl = %d",
339 mbstat
.m_mtypes
[MSG_DATA
], mbstat
.m_mtypes
[MSG_PROTO
], mbstat
.m_mtypes
[MSG_IOCTL
],
341 mbstat.m_mtypes[MSG_ERROR], mbstat.m_mtypes[MSG_HANGUP], mbstat.m_mtypes[MSG_IOCACK],
342 mbstat.m_mtypes[MSG_IOCNAK],
344 mbstat
.m_mtypes
[MSG_CTL
]);
345 return(&mbuf_str
[0]);
348 void trace_beg(str
, m
)
353 gbuf_t
*mdata
, *mchain
;
356 for (i
= 0, j
= 0, mdata
= m
, mchain
= m
; mdata
; i
++) {
357 mdata
= gbuf_cont(mdata
);
358 if (!mdata
&& mchain
) {
359 mdata
= gbuf_next(mchain
);
364 dPrintf(D_M_ASP
, D_L_TRACE
,
365 ("%s: %s, m# = %d, c# = %d\n", str
, mbuf_totals(), i
, j
));
371 dPrintf(D_M_ASP
, D_L_TRACE
,
372 (" %s: %s\n", str
, mbuf_totals()));
379 int asp_wput(gref
, m
)
384 unsigned char sockSav
, sock_num
;
385 gbuf_t
*mioc
, *mdata
;
387 asp_scb_t
*scb
, *server_scb
, *curr_scb
;
390 union asp_primitives
*primitives
;
391 asp_status_cmd_t
*status_cmd
;
392 asp_open_cmd_t
*open_cmd
;
395 scb
= (asp_scb_t
*)gref
->info
;
396 if (scb
->dflag
== 0) {
401 if (gbuf_type(m
) != MSG_IOCTL
) {
402 dPrintf(D_M_ASP
, D_L_WARNING
,
403 ("asp_wput: UNKNOWN message, type=%d\n",
410 iocbp
= (ioc_t
*)gbuf_rptr(mioc
);
412 dPrintf(D_M_ASP_LOW
, D_L_INFO
,
413 ("asp_wput: %s, loc=%d, state=%s\n",
414 aspIOCStr(iocbp
->ioc_cmd
), scb
->loc_addr
.socket
,
415 aspStateStr(scb
->state
)));
417 switch (iocbp
->ioc_cmd
) {
418 case ASPIOC_CloseSession
:
419 if ((scb
->state
== ASPSTATE_Close
) || (scb
->rem_addr
.node
== 0))
424 aw
.func
= ASPFUNC_CloseSess
;
425 aw
.param1
= scb
->sess_id
;
427 iocbp
->ioc_private
= (void *)scb
;
428 scb
->ioc_wait
= (unsigned char)(iocbp
->ioc_cmd
& 0xff);
429 iocbp
->ioc_cmd
= AT_ATP_ISSUE_REQUEST
;
430 asp_send_req(gref
, mioc
, &scb
->rem_addr
, &Retry
, &aw
,
431 0, ASPSTATE_WaitingForCloseSessRsp
, 0x01);
434 case ASPIOC_ClientBind
:
436 * open an ATP channel
438 if ((err
= atp_open(gref
, 0)) != 0) {
439 asp_iocnak(gref
, mioc
, err
);
442 scb
->atp_state
= (atp_state_t
*)gref
->info
;
443 scb
->atp_state
->pid
= scb
->pid
;
445 * bind to any available socket
448 sockSav
= scb
->dflag
;
449 if ((sock_num
= (at_socket
)atp_bind(gref
, 0, &sockSav
)) == 0) {
450 scb
->atp_state
= (atp_state_t
*)0;
452 gref
->info
= (void *)scb
;
453 asp_iocnak(gref
, mioc
, EINVAL
);
456 gref
->info
= (void *)scb
;
457 asp_dequeue_scb(scb
);
458 scb
->atp_state
->dflag
= scb
->dflag
;
459 scb
->loc_addr
.socket
= sock_num
;
460 asp_scbQ
[sock_num
] = scb
;
461 asp_inpC
[sock_num
]++;
462 atp_pidM
[sock_num
] = 0;
465 case ASPIOC_ListenerBind
:
467 * open an ATP channel
469 if ((err
= atp_open(gref
, 0)) != 0) {
470 asp_iocnak(gref
, mioc
, err
);
473 scb
->atp_state
= (atp_state_t
*)gref
->info
;
474 scb
->atp_state
->pid
= scb
->pid
;
476 * bind to any available socket
478 if ((sock_num
= (at_socket
)atp_bind(gref
, 0, 0)) == 0) {
479 scb
->atp_state
= (atp_state_t
*)0;
481 gref
->info
= (void *)scb
;
482 asp_iocnak(gref
, mioc
, EINVAL
);
485 gref
->info
= (void *)scb
;
486 asp_dequeue_scb(scb
);
487 scb
->atp_state
->dflag
= scb
->dflag
;
488 scb
->loc_addr
.socket
= sock_num
;
489 asp_scbQ
[sock_num
] = scb
;
490 asp_inpC
[sock_num
]++;
492 *(at_inet_t
*)gbuf_rptr(gbuf_cont(mioc
)) = scb
->loc_addr
;
495 case ASPIOC_GetLocEntity
:
496 if ((gbuf_cont(mioc
) == 0) || (scb
->atp_state
== 0)) {
497 asp_iocnak(gref
, mioc
, EPROTO
);
500 *(at_inet_t
*)gbuf_rptr(gbuf_cont(mioc
)) = scb
->loc_addr
;
503 case ASPIOC_GetRemEntity
:
504 if ((gbuf_cont(mioc
) == 0) || (scb
->atp_state
== 0)) {
505 asp_iocnak(gref
, mioc
, EPROTO
);
508 *(at_inet_t
*)gbuf_rptr(gbuf_cont(mioc
)) = scb
->rem_addr
;
511 case ASPIOC_GetSession
:
512 if ((mdata
= gbuf_cont(mioc
)) == 0) {
513 asp_iocnak(gref
, mioc
, EPROTO
);
516 addr
= (at_inet_t
*)gbuf_rptr(mdata
);
517 scb
->tickle_interval
= (unsigned short)addr
->node
;
518 scb
->session_timer
= addr
->net
;
519 server_scb
= asp_scbQ
[addr
->socket
];
520 /*### LD 10/28/97: changed to make sure we're not accessing a null server_scb */
521 if (server_scb
== 0) {
522 asp_iocnak(gref
, mioc
, EPROTO
);
525 if (server_scb
->sess_ioc
== 0) {
526 asp_iocnak(gref
, mioc
, EPROTO
);
531 * open an ATP channel
533 if ((err
= atp_open(gref
, 0)) != 0) {
534 gref
->info
= (void *)scb
;
535 asp_iocnak(gref
, mioc
, err
);
538 scb
->atp_state
= (atp_state_t
*)gref
->info
;
539 scb
->atp_state
->pid
= scb
->pid
;
541 * bind to any available socket
544 sockSav
= scb
->dflag
;
545 if ((sock_num
= (at_socket
)atp_bind(gref
, 0, &sockSav
)) == 0) {
547 asp_dequeue_scb(scb
);
548 ATDISABLE(s
, aspall_lock
);
550 scb
->loc_addr
.socket
= sock_num
;
551 for (curr_scb
= asp_scbQ
[sock_num
];
552 curr_scb
->next_scb
; curr_scb
= curr_scb
->next_scb
) ;
553 scb
->prev_scb
= curr_scb
;
554 curr_scb
->next_scb
= scb
;
555 scb
->atp_state
= curr_scb
->atp_state
;
556 ATENABLE(s
, aspall_lock
);
558 asp_dequeue_scb(scb
);
559 ATDISABLE(s
, aspall_lock
);
560 scb
->loc_addr
.socket
= sock_num
;
561 asp_scbQ
[sock_num
] = scb
;
562 scb
->atp_state
->dflag
= scb
->dflag
;
563 ATENABLE(s
, aspall_lock
);
565 gref
->info
= (void *)scb
;
566 asp_inpC
[sock_num
]++;
568 asp_accept(server_scb
, scb
, mdata
);
571 case ASPIOC_GetStatus
:
572 if ((mdata
= gbuf_cont(mioc
)) == 0) {
573 asp_iocnak(gref
, mioc
, EINVAL
);
577 status_cmd
= (asp_status_cmd_t
*)gbuf_rptr(mdata
);
578 aw
.func
= ASPFUNC_GetStatus
;
581 scb
->ioc_wait
= (unsigned char)(iocbp
->ioc_cmd
& 0xff);
582 iocbp
->ioc_cmd
= AT_ATP_ISSUE_REQUEST_DEF
;
583 /* bms: make sure this is an ALO request */
584 asp_send_req(gref
, mioc
, &status_cmd
->SLSEntityIdentifier
,
585 &status_cmd
->Retry
, &aw
, 0, ASPSTATE_WaitingForGetStatusRsp
, 0xff);
589 case ASPIOC_OpenSession
:
590 if ((mdata
= gbuf_cont(mioc
)) == 0) {
591 asp_iocnak(gref
, mioc
, EINVAL
);
595 open_cmd
= (asp_open_cmd_t
*)gbuf_rptr(mdata
);
596 scb
->svc_addr
= open_cmd
->SLSEntityIdentifier
;
597 scb
->rem_addr
= scb
->svc_addr
;
598 scb
->rem_node
= scb
->rem_addr
.node
;
599 scb
->rem_addr
.node
= 0;
600 scb
->tickle_interval
= open_cmd
->TickleInterval
;
601 scb
->session_timer
= open_cmd
->SessionTimer
;
602 aw
.func
= ASPFUNC_OpenSess
;
603 aw
.param1
= scb
->loc_addr
.socket
;
604 aw
.param2
= ASP_Version
;
605 scb
->ioc_wait
= (unsigned char)(iocbp
->ioc_cmd
& 0xff);
606 iocbp
->ioc_cmd
= AT_ATP_ISSUE_REQUEST_DEF
;
607 asp_send_req(gref
, mioc
, &open_cmd
->SLSEntityIdentifier
,
608 &open_cmd
->Retry
, &aw
, 1, ASPSTATE_WaitingForOpenSessRsp
, 0x01);
612 case ASPIOC_StatusBlock
:
614 * save the server status block
617 gbuf_freem(scb
->stat_msg
);
618 scb
->stat_msg
= gbuf_cont(mioc
);
622 /* *** Does scb->pid get used in a packet header,
623 and if so is it in ASP, or in ATP?
624 If not, do we need this call for anything?
625 (cap does currently use it in _ANS code.)
628 if (gbuf_cont(mioc
) == 0) {
629 asp_iocnak(gref
, mioc
, EINVAL
);
632 scb
->pid
= *(int *)gbuf_rptr(gbuf_cont(mioc
));
635 case ASPIOC_GetSessId
:
636 if (gbuf_cont(mioc
) == 0) {
637 asp_iocnak(gref
, mioc
, EINVAL
);
640 *(gref_t
**)gbuf_rptr(gbuf_cont(mioc
)) = gref
;
644 if (gbuf_cont(mioc
) == 0) {
645 asp_iocnak(gref
, mioc
, EINVAL
);
649 primitives
= (union asp_primitives
*)gbuf_rptr(scb
->sess_ioc
);
650 if (primitives
->Primitive
== ASPFUNC_CmdReply
)
651 *(int *)gbuf_rptr(gbuf_cont(mioc
)) = 0;
653 *(int *)gbuf_rptr(gbuf_cont(mioc
)) = 1;
655 *(int *)gbuf_rptr(gbuf_cont(mioc
)) = -1;
658 case DDP_IOC_GET_CFG
:
660 struct atp_state
*atp
= (struct atp_state
*)gref
->info
;
664 if (gbuf_cont(mioc
) == 0) {
665 asp_iocnak(gref
, mioc
, EINVAL
);
668 /* *** borrowed from ddp_proto.c to handle DDP_IOC_GET_CFG
670 scb
->state
= ASPSTATE_Idle
;
672 /* *** was ddp_get_cfg() *** */
674 (ddp_addr_t
*)gbuf_rptr(gbuf_cont(mioc
));
675 cfgp
->inet
.net
= ifID_home
->ifThisNode
.s_net
;
676 cfgp
->inet
.node
= ifID_home
->ifThisNode
.s_node
;
677 cfgp
->inet
.socket
= atp
->atp_socket_no
;
678 cfgp
->ddptype
= DDP_ATP
;
680 gbuf_wset(gbuf_cont(mioc
), sizeof(at_inet_t
));
685 asp_iocnak(gref
, mioc
, EINVAL
);
689 asp_iocack(gref
, mioc
);
694 * send request routine
697 asp_send_req(gref
, mioc
, dest
, retry
, awp
, xo
, state
, bitmap
)
705 unsigned char bitmap
;
710 struct atp_set_default
*sd
;
713 struct atpBDS
*atpBDS
;
714 asp_scb_t
*scb
= (asp_scb_t
*)gref
->info
;
717 * allocate an ATP buffer for the request
719 if ((gbuf_cont(mioc
) = gbuf_alloc(aspCMDsize
, PRI_MED
)) == 0) {
720 if (awp
->func
== ASPFUNC_Tickle
)
723 asp_iocnak(gref
, mioc
, ENOBUFS
);
724 dPrintf(D_M_ASP
, D_L_WARNING
,
725 ("asp_send_req: ENOBUFS, loc=%d\n", scb
->loc_addr
.socket
));
729 mdata
= gbuf_cont(mioc
);
730 iocbp
= (ioc_t
*)gbuf_rptr(mioc
);
735 atpBDS
= (struct atpBDS
*)gbuf_rptr(mdata
);
736 gbuf_wset(mdata
,atpBDSsize
);
737 for (i
=0; i
< ATP_TRESP_MAX
; i
++) {
738 *(unsigned long *)atpBDS
[i
].bdsBuffAddr
= 1;
739 *(unsigned short *)atpBDS
[i
].bdsBuffSz
= ATP_DATA_SIZE
;
741 sd
= (struct atp_set_default
*)gbuf_wptr(mdata
);
742 gbuf_winc(mdata
,sizeof(struct atp_set_default
));
743 sd
->def_retries
= (retry
->retries
== -1) ?
744 ATP_INFINITE_RETRIES
: retry
->retries
;
745 sd
->def_rate
= retry
->interval
*TICKS_PER_SEC
;
746 sd
->def_BDSlen
= atpBDSsize
;
747 ddp
= (at_ddp_t
*)gbuf_wptr(mdata
);
748 NET_ASSIGN(ddp
->src_net
, scb
->loc_addr
.net
);
749 ddp
->src_node
= scb
->loc_addr
.node
;
750 NET_ASSIGN(ddp
->dst_net
, dest
->net
);
751 ddp
->dst_node
= dest
->node
;
752 ddp
->dst_socket
= dest
->socket
;
753 UAS_ASSIGN(ddp
->checksum
, 0);
754 atp
= ATP_ATP_HDR(gbuf_wptr(mdata
));
757 atp
->bitmap
= bitmap
;
758 gbuf_winc(mdata
,TOTAL_ATP_HDR_SIZE
);
759 *(asp_word_t
*)atp
->user_bytes
= *awp
;
760 iocbp
->ioc_count
= gbuf_len(mdata
);
767 dPrintf(D_M_ASP
, D_L_INFO
,
768 ("asp_send_req: %s, loc=%d, rem= %d, len=%d, state=%s\n",
769 aspCmdStr(awp
->func
),
770 scb
->loc_addr
.socket
, ddp
->dst_socket
, iocbp
->ioc_count
,
771 aspStateStr(scb
->state
)));
773 atp_send_req(gref
, mioc
);
778 * send tickle routine - funnelled version
781 asp_send_tickle_funnel(scb
)
784 thread_funnel_set(network_flock
, TRUE
);
785 asp_send_tickle(scb
);
786 thread_funnel_set(network_flock
, FALSE
);
791 * send tickle routine
804 * make sure the connection is still there
806 if (scb
->rem_addr
.node
== 0) {
810 if ((mioc
= gbuf_alloc(sizeof(ioc_t
), PRI_HI
)) == 0) {
811 dPrintf(D_M_ASP
, D_L_WARNING
,
812 ("asp_send_tickle: ENOBUFS 0, loc=%d, rem=%d\n",
813 scb
->loc_addr
.socket
,scb
->rem_addr
.socket
));
814 timeout(asp_send_tickle_funnel
, (void *)scb
, 10);
817 gbuf_wset(mioc
,sizeof(ioc_t
));
818 gbuf_set_type(mioc
, MSG_IOCTL
);
820 dest
= scb
->svc_addr
.node
?
821 (at_inet_t
*)&scb
->svc_addr
: (at_inet_t
*)&scb
->rem_addr
;
822 retry
.interval
= scb
->tickle_interval
;
825 aw
.func
= ASPFUNC_Tickle
;
826 aw
.param1
= scb
->sess_id
;
828 ((ioc_t
*)gbuf_rptr(mioc
))->ioc_cr
= (void *)scb
;
829 ((ioc_t
*)gbuf_rptr(mioc
))->ioc_cmd
= AT_ATP_ISSUE_REQUEST_TICKLE
;
831 if (asp_send_req(scb
->gref
, mioc
, dest
, &retry
, &aw
, 0, scb
->state
, 0)) {
832 dPrintf(D_M_ASP
, D_L_WARNING
,
833 ("asp_send_tickle: ENOBUFS 1, loc=%d, rem=%d\n",
834 scb
->loc_addr
.socket
,scb
->rem_addr
.socket
));
836 timeout(asp_send_tickle_funnel
, (void *)scb
, 10);
842 * accept connection routine
845 asp_accept(scb
, sess_scb
, m
)
857 mdata
= scb
->sess_ioc
;
858 ddp
= (at_ddp_t
*)gbuf_rptr(mdata
);
859 atp
= (at_atp_t
*)(gbuf_rptr(mdata
) + DDP_X_HDR_SIZE
);
860 rem_addr
.net
= NET_VALUE(ddp
->src_net
);
861 rem_addr
.node
= ddp
->src_node
;
862 rem_addr
.socket
= ddp
->src_socket
;
863 awp
= (asp_word_t
*)atp
->user_bytes
;
865 sess_scb
->loc_addr
.net
= NET_VALUE(ddp
->dst_net
);
866 sess_scb
->loc_addr
.node
= ddp
->dst_node
;
867 NET_ASSIGN(ddp
->src_net
, sess_scb
->loc_addr
.net
);
868 ddp
->src_node
= sess_scb
->loc_addr
.node
;
869 NET_ASSIGN(ddp
->dst_net
, rem_addr
.net
);
870 ddp
->dst_node
= rem_addr
.node
;
871 ddp
->dst_socket
= rem_addr
.socket
;
873 sess_scb
->sess_id
= sess_scb
->loc_addr
.socket
;
874 sess_scb
->rem_socket
= rem_addr
.socket
;
875 sess_scb
->rem_addr
= rem_addr
;
876 sess_scb
->rem_addr
.socket
= awp
->param1
;
877 sess_scb
->reply_socket
= sess_scb
->rem_addr
.socket
;
878 awp
->func
= sess_scb
->loc_addr
.socket
;
879 awp
->param1
= sess_scb
->sess_id
;
882 ATDISABLE(s
, scb
->lock
);
883 scb
->sess_ioc
= gbuf_next(mdata
);
884 ATENABLE(s
, scb
->lock
);
885 gbuf_next(mdata
) = 0;
886 asp_timout(asp_hangup
, sess_scb
, sess_scb
->session_timer
);
887 atp_send_rsp(scb
->gref
, mdata
, TRUE
);
888 asp_send_tickle(sess_scb
);
889 dPrintf(D_M_ASP
, D_L_INFO
,
890 ("asp_accept: ACCEPT connect request, loc=%d, rem=%x.%x.%d\n",
891 sess_scb
->loc_addr
.socket
,
892 sess_scb
->rem_addr
.net
,
893 sess_scb
->rem_addr
.node
,sess_scb
->rem_addr
.socket
));
897 * timer routine - funneled version
899 void asp_clock_funnel(arg
)
902 thread_funnel_set(network_flock
, TRUE
);
904 thread_funnel_set(network_flock
, FALSE
);
917 ATDISABLE(s
, asptmo_lock
);
919 scb_tmo_list
->tmo_delta
--;
920 while (((scb
= scb_tmo_list
) != 0) && (scb_tmo_list
->tmo_delta
== 0)) {
921 if ((scb_tmo_list
= scb
->next_tmo
) != 0)
922 scb_tmo_list
->prev_tmo
= 0;
923 if ((tmo_func
= scb
->tmo_func
) != 0) {
925 ATENABLE(s
, asptmo_lock
);
927 ATDISABLE(s
, asptmo_lock
);
930 ATENABLE(s
, asptmo_lock
);
932 if (++scb_tmo_cnt
== 0) scb_tmo_cnt
++;
933 timeout(asp_clock_funnel
, (void *)arg
, (1<<SESS_TMO_RES
)*TICKS_PER_SEC
);
941 asp_ack_reply(gref
, mioc
)
942 register gref_t
*gref
;
943 register gbuf_t
*mioc
;
946 int len
, msize
, nbds
;
947 register gbuf_t
*mdata
, *m
, *mx
;
948 struct atpBDS
*atpBDS
;
951 register asp_scb_t
*scb
, *sess_scb
;
952 register ioc_t
*iocbp
;
953 register asp_word_t
*awp
;
954 register asp_command_ind_t
*command_ind
;
955 register asp_cmdreply_ind_t
*cmdreply_ind
;
958 iocbp
= (ioc_t
*)gbuf_rptr(mioc
);
960 if (iocbp
->ioc_cmd
== AT_ATP_ISSUE_REQUEST_TICKLE
) {
962 * ignore the ack for the tickle request
964 scb
= (asp_scb_t
*)iocbp
->ioc_cr
;
965 scb
->tickle_tid
= (unsigned short)iocbp
->ioc_rval
;
970 scb
= (asp_scb_t
*)gref
->info
;
976 if (iocbp
->ioc_cmd
== AT_ATP_GET_POLL
) {
978 * if no data, just drop the request
980 if ((mdata
= gbuf_cont(mioc
)) == 0) {
985 gbuf_set_type(mioc
, MSG_IOCTL
);
986 ddp
= (at_ddp_t
*)gbuf_rptr(mdata
);
987 gbuf_rinc(mdata
,DDP_X_HDR_SIZE
);
988 atp
= (at_atp_t
*)gbuf_rptr(mdata
);
989 gbuf_rinc(mdata
,ATP_HDR_SIZE
);
990 rem_addr
.net
= NET_VALUE(ddp
->src_net
);
991 rem_addr
.node
= ddp
->src_node
;
992 rem_addr
.socket
= ddp
->src_socket
;
993 awp
= (asp_word_t
*)atp
->user_bytes
;
997 * find the responsible scb
999 if ((scb
= asp_find_scb(scb
->loc_addr
.socket
, &rem_addr
)) == 0) {
1004 dPrintf(D_M_ASP
, D_L_INFO
,
1005 ("asp_ack_reply: %s, loc=%d, rem=%x.%x.%d\n",
1006 aspCmdStr(awp
->func
),scb
->loc_addr
.socket
,
1007 NET_VALUE(ddp
->src_net
) ,ddp
->src_node
,ddp
->src_socket
));
1009 if (scb
->rem_addr
.node
)
1010 asp_untimout(asp_hangup
, scb
);
1012 switch (awp
->func
) {
1013 case ASPFUNC_GetStatus
:
1015 * ignore if this is not a server socket
1018 if ((scb
->dflag
!= 1) || (scb
->stat_msg
1019 && ((mx
= gbuf_dupb(scb
->stat_msg
)) == 0)))
1024 * send the status block
1026 if (gbuf_cont(mdata
)) {
1027 gbuf_freem(gbuf_cont(mdata
));
1028 gbuf_cont(mdata
) = 0;
1030 gbuf_rdec(mdata
,TOTAL_ATP_HDR_SIZE
);
1031 if ((m
= gbuf_alloc( (TOTAL_ATP_HDR_SIZE
+atpBDSsize
), PRI_MED
)) == 0) {
1036 bcopy(gbuf_rptr(mdata
), gbuf_rptr(m
), TOTAL_ATP_HDR_SIZE
);
1039 ddp
= (at_ddp_t
*)gbuf_rptr(mdata
);
1040 gbuf_wset(mdata
,DDP_X_HDR_SIZE
);
1041 atp
= (at_atp_t
*)gbuf_wptr(mdata
);
1042 gbuf_winc(mdata
,ATP_HDR_SIZE
);
1043 awp
= (asp_word_t
*)atp
->user_bytes
;
1044 NET_NET(ddp
->src_net
, ddp
->dst_net
);
1045 ddp
->src_node
= ddp
->dst_node
;
1046 NET_ASSIGN(ddp
->dst_net
, rem_addr
.net
);
1047 ddp
->dst_node
= rem_addr
.node
;
1048 ddp
->dst_socket
= rem_addr
.socket
;
1049 UAS_ASSIGN(ddp
->checksum
, 0);
1050 atpBDS
= (struct atpBDS
*)gbuf_wptr(mdata
);
1051 msize
= mx
? gbuf_msgsize(mx
) : 0;
1052 for (nbds
=0; (nbds
< ATP_TRESP_MAX
) && (msize
> 0); nbds
++) {
1053 len
= msize
< ATP_DATA_SIZE
? msize
: ATP_DATA_SIZE
;
1054 msize
-= ATP_DATA_SIZE
;
1055 *(long *)atpBDS
[nbds
].bdsUserData
= 0;
1056 UAL_ASSIGN(atpBDS
[nbds
].bdsBuffAddr
, 1);
1057 UAS_ASSIGN(atpBDS
[nbds
].bdsBuffSz
, len
);
1059 UAS_ASSIGN(atpBDS
[0].bdsDataSz
, nbds
);
1060 gbuf_winc(mdata
,atpBDSsize
);
1061 gbuf_cont(mdata
) = mx
;
1062 atp_send_rsp(gref
, mdata
, FALSE
);
1065 case ASPFUNC_OpenSess
:
1067 * ignore if server is not ready
1069 if ((scb
->dflag
!= 1) || (scb
->stat_msg
== 0))
1073 if (gbuf_cont(mdata
)) {
1074 gbuf_freem(gbuf_cont(mdata
));
1075 gbuf_cont(mdata
) = 0;
1077 gbuf_rdec(mdata
,TOTAL_ATP_HDR_SIZE
);
1078 gbuf_wset(mdata
,TOTAL_ATP_HDR_SIZE
);
1079 if (awp
->param2
!= ASP_Version
) {
1081 * bad version number, send the OpenSession response
1085 awp
->param2
= (unsigned short)ASPERR_BadVersNum
;
1086 dPrintf(D_M_ASP
, D_L_INFO
,
1088 ASPERR_BadVersNum
));
1090 NET_NET(ddp
->src_net
, ddp
->dst_net
);
1091 ddp
->src_node
= ddp
->dst_node
;
1092 NET_ASSIGN(ddp
->dst_net
, rem_addr
.net
);
1093 ddp
->dst_node
= rem_addr
.node
;
1094 ddp
->dst_socket
= rem_addr
.socket
;
1095 atp_send_rsp(gref
, mdata
, FALSE
);
1100 * queue the connection request
1102 ATDISABLE(s
, scb
->lock
);
1103 gbuf_next(mdata
) = 0;
1104 if ((m
= scb
->sess_ioc
) == 0) {
1105 scb
->sess_ioc
= mdata
;
1107 thread_wakeup(&scb
->event
);
1109 atalk_notify_sel(gref
);
1111 while (gbuf_next(m
))
1113 gbuf_next(m
) = mdata
;
1115 ATENABLE(s
, scb
->lock
);
1116 dPrintf(D_M_ASP
, D_L_INFO
,
1117 (" : QUEUE connect request\n"));
1121 case ASPFUNC_Command
:
1123 if ( (scb
->sess_id
!= awp
->param1
)
1124 || (scb
->rcv_seq_num
!= awp
->param2
)
1125 || BAD_REMADDR(rem_addr
) ) {
1127 sprintf(era
,"%d.%d", scb
->rem_addr
.node
,scb
->rem_addr
.socket
);
1128 sprintf(ra
,"%d.%d", rem_addr
.node
,rem_addr
.socket
);
1129 dPrintf(D_M_ASP
, D_L_WARNING
,
1130 (" : DROP, id=%d,esn=%d,sn=%d,erem=%s,rem=%s\n",
1131 scb
->sess_id
,scb
->rcv_seq_num
,awp
->param2
,era
,ra
));
1132 gbuf_cont(mioc
) = 0;
1133 gbuf_rdec(mdata
,TOTAL_ATP_HDR_SIZE
);
1134 atp_drop_req(gref
, mdata
);
1137 scb
->reply_socket
= rem_addr
.socket
;
1138 if (awp
->func
== ASPFUNC_Write
)
1139 scb
->wrt_seq_num
= scb
->rcv_seq_num
;
1140 NEXT_SEQ_NUM(scb
->rcv_seq_num
);
1141 gbuf_set_type(mioc
, MSG_PROTO
);
1142 gbuf_wset(mioc
,sizeof(asp_command_ind_t
));
1143 command_ind
= (asp_command_ind_t
*)gbuf_rptr(mioc
);
1144 command_ind
->Primitive
= (int)awp
->func
;
1145 command_ind
->ReqRefNum
=
1146 *(unsigned short *)atp
->tid
;
1147 command_ind
->ReqType
= awp
->func
;
1149 mdata
= gbuf_strip(mdata
);
1150 gbuf_cont(mioc
) = mdata
;
1151 ATDISABLE(s
, scb
->lock
);
1152 if (scb
->req_flag
) {
1153 if ((mx
= scb
->req_msgq
) != 0) {
1154 while (gbuf_next(mx
))
1156 gbuf_next(mx
) = mioc
;
1158 scb
->req_msgq
= mioc
;
1159 ATENABLE(s
, scb
->lock
);
1162 ATENABLE(s
, scb
->lock
);
1163 asp_putnext(scb
->gref
, mioc
);
1167 case ASPFUNC_WriteContinue
:
1168 if ( (scb
->sess_id
!= awp
->param1
)
1169 || (scb
->snd_seq_num
!= awp
->param2
)
1170 || BAD_REMADDR(rem_addr
) ) {
1173 scb
->reply_socket
= rem_addr
.socket
;
1174 gbuf_set_type(mioc
, MSG_PROTO
);
1175 gbuf_wset(mioc
,sizeof(asp_command_ind_t
));
1176 command_ind
= (asp_command_ind_t
*)gbuf_rptr(mioc
);
1177 command_ind
->Primitive
= (int)awp
->func
;
1178 command_ind
->ReqRefNum
=
1179 *(unsigned short *)atp
->tid
;
1180 command_ind
->ReqType
= awp
->func
;
1182 mdata
= gbuf_strip(mdata
);
1183 gbuf_cont(mioc
) = mdata
;
1184 asp_putnext(scb
->gref
, mioc
);
1187 case ASPFUNC_Tickle
:
1188 if (scb
->stat_msg
) {
1189 sess_scb
= asp_scbQ
[awp
->param1
];
1190 if (sess_scb
&& sess_scb
->next_scb
)
1191 sess_scb
= asp_find_scb(
1192 sess_scb
->loc_addr
.socket
, &rem_addr
);
1194 if (sess_scb
->rem_addr
.node
)
1195 asp_untimout(asp_hangup
, sess_scb
);
1196 if (sess_scb
->rem_addr
.node
)
1197 asp_timout(asp_hangup
, sess_scb
, sess_scb
->session_timer
);
1200 dPrintf(D_M_ASP
, D_L_INFO
,
1201 (" : Tickle, %d -> %d, id=%d\n",
1202 ddp
->src_socket
,ddp
->dst_socket
,awp
->param1
));
1205 case ASPFUNC_CloseSess
:
1206 if ( (scb
->sess_id
!= awp
->param1
)
1207 || (scb
->state
== ASPSTATE_Close
)
1208 || (scb
->state
== ASPSTATE_WaitingForCloseSessRsp
)
1209 || (scb
->rem_addr
.net
!= rem_addr
.net
)
1210 || (scb
->rem_addr
.node
!= rem_addr
.node
) ) {
1211 dPrintf(D_M_ASP
, D_L_INFO
,
1212 (" : CLOSE retry, loc=%d, rem=%x.%x.%d\n",
1213 scb
->loc_addr
.socket
,
1216 scb
->rem_addr
.socket
));
1223 * build the CloseSess response to be sent to peer
1224 * when the session is closed by the user.
1226 if (gbuf_cont(mdata
)) {
1227 gbuf_freem(gbuf_cont(mdata
));
1228 gbuf_cont(mdata
) = 0;
1230 gbuf_rdec(mdata
,TOTAL_ATP_HDR_SIZE
);
1231 gbuf_wset(mdata
,TOTAL_ATP_HDR_SIZE
);
1232 NET_NET(ddp
->src_net
, ddp
->dst_net
);
1233 ddp
->src_node
= ddp
->dst_node
;
1234 NET_ASSIGN(ddp
->dst_net
, rem_addr
.net
);
1235 ddp
->dst_node
= rem_addr
.node
;
1236 ddp
->dst_socket
= rem_addr
.socket
;
1240 dPrintf(D_M_ASP
,D_L_INFO
,
1241 (" : CLOSE, loc=%d, rem=%x.%x.%d\n",
1242 scb
->loc_addr
.socket
,
1245 scb
->rem_addr
.socket
));
1247 gbuf_next(mdata
) = 0;
1248 ATDISABLE(s
, scb
->lock
);
1250 gbuf_freel(scb
->sess_ioc
);
1251 scb
->sess_ioc
= mdata
;
1252 scb
->state
= ASPSTATE_Close
;
1253 ATENABLE(s
, scb
->lock
);
1256 * notify upstream of the CloseSess from peer
1261 case ASPFUNC_Attention
:
1262 if ( (scb
->sess_id
!= awp
->param1
)
1263 || (scb
->rem_addr
.net
!= rem_addr
.net
)
1264 || (scb
->rem_addr
.node
!= rem_addr
.node
) ) {
1267 gbuf_set_type(mioc
, MSG_PROTO
);
1268 gbuf_wset(mioc
,sizeof(asp_command_ind_t
));
1269 command_ind
= (asp_command_ind_t
*)gbuf_rptr(mioc
);
1270 command_ind
->Primitive
= (int)awp
->func
;
1271 command_ind
->ReqRefNum
=
1272 *(unsigned short *)atp
->tid
;
1273 command_ind
->ReqType
= awp
->func
;
1274 scb
->attn_tid
= *(unsigned short *)atp
->tid
;
1276 gbuf_rdec(mdata
,2); /* attention code */
1278 mdata
= gbuf_strip(mdata
);
1279 gbuf_cont(mioc
) = mdata
;
1280 asp_putnext(scb
->gref
, mioc
);
1284 dPrintf(D_M_ASP
, D_L_WARNING
,
1285 (" : UNKNOWN func, func=%d\n",
1292 else if (iocbp
->ioc_cmd
== AT_ATP_REQUEST_COMPLETE
) {
1293 if (scb
->next_scb
) {
1295 * find the responsible scb
1297 scb
= (asp_scb_t
*)iocbp
->ioc_private
;
1298 if ((scb
== 0) || (scb
->magic_num
!= 222)) {
1299 dPrintf(D_M_ASP
, D_L_ERROR
,
1300 ("asp_ack_reply: CAN'T find scb 1\n"));
1305 dPrintf(D_M_ASP
, D_L_INFO
,
1306 ("asp_ack_reply: RSP, loc=%d, rem=%x.%x.%d, state=%s\n",
1307 scb
->loc_addr
.socket
,
1310 scb
->rem_addr
.socket
,
1311 aspStateStr(scb
->state
)));
1313 switch (scb
->state
) {
1314 case ASPSTATE_Close
:
1316 scb
->rem_addr
.node
= 0;
1318 ATDISABLE(s
, scb
->lock
);
1320 thread_wakeup(&scb
->event
);
1322 atalk_notify_sel(gref
);
1323 ATENABLE(s
, scb
->lock
);
1326 case ASPSTATE_WaitingForGetStatusRsp
:
1328 scb
->state
= ASPSTATE_Idle
;
1329 mx
= gbuf_cont(mioc
);
1330 gbuf_cont(mioc
) = 0;
1331 mdata
= gbuf_cont(mx
);
1333 iocbp
->ioc_cmd
= ASPIOC_GetStatus
;
1334 iocbp
->ioc_count
= 0;
1335 iocbp
->ioc_rval
= mdata
? gbuf_msgsize(mdata
) : 0;
1337 atalk_putnext(gref
, mioc
);
1338 atalk_putnext(gref
, mdata
);
1341 case ASPSTATE_WaitingForOpenSessRsp
:
1343 scb
->state
= ASPSTATE_Idle
;
1344 mx
= gbuf_cont(mioc
);
1345 gbuf_cont(mioc
) = 0;
1346 if (gbuf_cont(mx
)) {
1347 gbuf_freem(gbuf_cont(mx
));
1350 iocbp
->ioc_cmd
= ASPIOC_OpenSession
;
1351 iocbp
->ioc_rval
= 0;
1352 iocbp
->ioc_count
= 0;
1353 atpBDS
= (struct atpBDS
*)gbuf_rptr(mx
);
1354 awp
= (asp_word_t
*)atpBDS
->bdsUserData
;
1357 asp_iocnak(gref
, mioc
, ECONNREFUSED
);
1359 scb
->rem_addr
.node
= scb
->rem_node
;
1360 scb
->rem_addr
.socket
= awp
->func
;
1361 /* bms: need to set the reply_socket for client side too.
1362 This makes ALO atten replies sent by the client work. */
1363 scb
->reply_socket
= scb
->rem_addr
.socket
;
1364 scb
->sess_id
= awp
->param1
;
1366 atalk_putnext(gref
, mioc
);
1367 asp_timout(asp_hangup
, scb
, scb
->session_timer
);
1368 asp_send_tickle(scb
);
1369 dPrintf(D_M_ASP
, D_L_INFO
,
1370 ("asp_ack_reply: CONNECT, loc=%d, rem=%x.%x.%d\n",
1371 scb
->loc_addr
.socket
,
1374 scb
->rem_addr
.socket
));
1378 case ASPSTATE_WaitingForCommandRsp
:
1379 case ASPSTATE_WaitingForWriteRsp
:
1380 case ASPSTATE_WaitingForWriteContinueRsp
:
1381 if (scb
->rem_addr
.node
)
1382 asp_untimout(asp_hangup
, scb
);
1383 NEXT_SEQ_NUM(scb
->snd_seq_num
);
1384 scb
->state
= ASPSTATE_Idle
;
1385 gbuf_set_type(mioc
, MSG_PROTO
);
1386 mx
= gbuf_cont(mioc
);
1387 mdata
= gbuf_cont(mx
);
1388 gbuf_cont(mioc
) = mdata
;
1389 atpBDS
= (struct atpBDS
*)gbuf_rptr(mx
);
1390 cmdreply_ind
= (asp_cmdreply_ind_t
*)gbuf_rptr(mioc
);
1391 cmdreply_ind
->Primitive
= ASPFUNC_CmdReply
;
1392 cmdreply_ind
->CmdResult
= *(int *)atpBDS
->bdsUserData
;
1393 gbuf_wset(mioc
,sizeof(asp_cmdreply_ind_t
));
1395 asp_putnext(scb
->gref
, mioc
);
1398 case ASPSTATE_WaitingForCloseSessRsp
:
1400 scb
->state
= ASPSTATE_Close
;
1401 scb
->rem_addr
.node
= 0;
1402 iocbp
->ioc_cmd
= ASPIOC_CloseSession
;
1403 iocbp
->ioc_rval
= 0;
1404 if (gbuf_cont(mioc
)) {
1405 gbuf_freem(gbuf_cont(mioc
));
1406 gbuf_cont(mioc
) = 0;
1408 atalk_putnext(scb
->gref
, mioc
);
1409 atp_cancel_req(scb
->gref
, (unsigned int)scb
->tickle_tid
);
1410 scb
->tickle_tid
= 0;
1414 dPrintf(D_M_ASP
, D_L_WARNING
,
1415 (" : UNKNOWN state, state=%s\n",
1416 aspStateStr(scb
->state
)));
1422 if (scb
->next_scb
) {
1424 * find the responsible scb
1426 scb
= (asp_scb_t
*)iocbp
->ioc_cr
;
1427 if ((scb
== 0) || (scb
->magic_num
!= 222)) {
1428 dPrintf(D_M_ASP
, D_L_ERROR
,
1429 ("asp_ack_reply: CAN'T find scb 2\n"));
1435 switch (scb
->state
) {
1436 case ASPSTATE_Close
:
1437 scb
->rem_addr
.node
= 0;
1446 if (scb
->rem_addr
.node
)
1447 asp_timout(asp_hangup
, scb
, scb
->session_timer
);
1448 } /* asp_ack_reply */
1454 asp_nak_reply(gref
, mioc
)
1455 register gref_t
*gref
;
1456 register gbuf_t
*mioc
;
1458 register asp_scb_t
*scb
;
1459 register ioc_t
*iocbp
;
1461 iocbp
= (ioc_t
*)gbuf_rptr(mioc
);
1463 if (iocbp
->ioc_cmd
== AT_ATP_ISSUE_REQUEST_TICKLE
) {
1465 * no tickle, close session
1467 scb
= (asp_scb_t
*)iocbp
->ioc_cr
;
1470 dPrintf(D_M_ASP
, D_L_WARNING
,
1471 ("tickle_nak: loc=%d, rem=%x.%x.%d, state=%s\n",
1472 scb
->loc_addr
.socket
,
1475 scb
->rem_addr
.socket
,
1476 aspStateStr(scb
->state
)));
1481 scb
= (asp_scb_t
*)gref
->info
;
1487 if (iocbp
->ioc_cmd
== AT_ATP_REQUEST_COMPLETE
) {
1488 if (scb
->next_scb
) {
1490 * find the responsible scb
1492 scb
= (asp_scb_t
*)iocbp
->ioc_private
;
1493 if ((scb
== 0) || (scb
->magic_num
!= 222)) {
1494 dPrintf(D_M_ASP
, D_L_ERROR
,
1495 ("asp_nak_reply: CAN'T find scb 1\n"));
1500 dPrintf(D_M_ASP
, D_L_WARNING
,
1501 ("asp_nak_reply: RSP, loc=%d, rem=%x.%x.%d, state=%s\n",
1502 scb
->loc_addr
.socket
,
1505 scb
->rem_addr
.socket
,
1506 aspStateStr(scb
->state
)));
1508 switch (scb
->state
) {
1509 case ASPSTATE_WaitingForGetStatusRsp
:
1510 iocbp
->ioc_cmd
= ASPIOC_GetStatus
;
1513 case ASPSTATE_WaitingForOpenSessRsp
:
1514 iocbp
->ioc_cmd
= ASPIOC_OpenSession
;
1517 case ASPSTATE_WaitingForCommandRsp
:
1518 case ASPSTATE_WaitingForWriteRsp
:
1519 case ASPSTATE_WaitingForWriteContinueRsp
:
1520 scb
->state
= ASPSTATE_Idle
;
1522 /* last remaining use of MSG_ERROR */
1523 gbuf_set_type(mioc
, MSG_ERROR
);
1524 *gbuf_rptr(mioc
) = (u_char
)EPROTO
;
1526 if (gbuf_cont(mioc
)) {
1527 gbuf_freem(gbuf_cont(mioc
));
1528 gbuf_cont(mioc
) = 0;
1531 asp_putnext(scb
->gref
, mioc
);
1534 case ASPSTATE_WaitingForCloseSessRsp
:
1535 scb
->state
= ASPSTATE_Close
;
1537 case ASPSTATE_Close
: /* new for PR-2296832 */
1538 scb
->rem_addr
.node
= 0;
1539 iocbp
->ioc_cmd
= ASPIOC_CloseSession
;
1540 iocbp
->ioc_rval
= 0;
1541 if (gbuf_cont(mioc
)) {
1542 gbuf_freem(gbuf_cont(mioc
));
1543 gbuf_cont(mioc
) = 0;
1545 gbuf_set_type(mioc
, MSG_IOCACK
);
1546 atalk_putnext(scb
->gref
, mioc
);
1553 scb
->state
= ASPSTATE_Idle
;
1554 atalk_putnext(gref
, mioc
);
1558 if (scb
->next_scb
) {
1560 * find the responsible scb
1562 scb
= (asp_scb_t
*)iocbp
->ioc_cr
;
1563 if ((scb
== 0) || (scb
->magic_num
!= 222)) {
1564 dPrintf(D_M_ASP
, D_L_ERROR
,
1565 ("asp_nak_reply: CAN'T find scb 2\n"));
1571 switch (scb
->state
) {
1572 case ASPSTATE_Close
:
1573 scb
->rem_addr
.node
= 0;
1579 } /* asp_nak_reply */
1582 * delete scb from the use list
1585 asp_dequeue_scb(scb
)
1590 ATDISABLE(s
, aspall_lock
);
1591 if (scb
== scb_used_list
) {
1592 if ((scb_used_list
= scb
->next_scb
) != 0)
1593 scb
->next_scb
->prev_scb
= 0;
1595 if ((scb
->prev_scb
->next_scb
= scb
->next_scb
) != 0)
1596 scb
->next_scb
->prev_scb
= scb
->prev_scb
;
1598 ATENABLE(s
, aspall_lock
);
1607 StaticProc asp_scb_t
*
1608 asp_find_scb(sock_num
, rem_addr
)
1609 unsigned char sock_num
;
1610 at_inet_t
*rem_addr
;
1614 asp_scb_t
*alt_scb
= 0;
1616 ATDISABLE(s
, aspall_lock
);
1617 for (scb
= asp_scbQ
[sock_num
]; scb
; scb
= scb
->next_scb
) {
1618 if ((scb
->rem_addr
.net
== rem_addr
->net
)
1619 && (scb
->rem_addr
.node
== rem_addr
->node
)) {
1620 if ((scb
->rem_addr
.socket
== rem_addr
->socket
)
1621 || (scb
->rem_socket
== rem_addr
->socket
))
1623 else if (alt_scb
== 0)
1628 if ((scb
== 0) && ((scb
= alt_scb
) == 0)) {
1629 dPrintf(D_M_ASP
, D_L_ERROR
,
1630 ("asp_find_scb: CAN'T find scb, loc=%d, rem=%x.%x.%d\n",
1636 ATENABLE(s
, aspall_lock
);
1645 asp_timout(func
, scb
, seconds
)
1647 register asp_scb_t
*scb
;
1652 register asp_scb_t
*curr_scb
, *prev_scb
;
1657 scb
->tmo_func
= func
;
1658 scb
->tmo_delta
= (seconds
>>SESS_TMO_RES
);
1659 scb
->tmo_cnt
= scb_tmo_cnt
;
1661 ATDISABLE(s
, asptmo_lock
);
1662 if (scb_tmo_list
== 0) {
1663 scb
->next_tmo
= scb
->prev_tmo
= 0;
1665 ATENABLE(s
, asptmo_lock
);
1670 curr_scb
= scb_tmo_list
;
1674 sum
+= curr_scb
->tmo_delta
;
1675 if (sum
> scb
->tmo_delta
) {
1676 sum
-= curr_scb
->tmo_delta
;
1677 scb
->tmo_delta
-= sum
;
1678 curr_scb
->tmo_delta
-= scb
->tmo_delta
;
1681 prev_scb
= curr_scb
;
1682 if ((curr_scb
= curr_scb
->next_tmo
) == 0) {
1683 scb
->tmo_delta
-= sum
;
1689 scb
->prev_tmo
= prev_scb
;
1690 if ((scb
->next_tmo
= prev_scb
->next_tmo
) != 0)
1691 prev_scb
->next_tmo
->prev_tmo
= scb
;
1692 prev_scb
->next_tmo
= scb
;
1695 scb
->next_tmo
= scb_tmo_list
;
1696 scb_tmo_list
->prev_tmo
= scb
;
1699 ATENABLE(s
, asptmo_lock
);
1706 asp_untimout(func
, scb
)
1708 register asp_scb_t
*scb
;
1712 if ((scb
->tmo_cnt
== scb_tmo_cnt
) || (scb
->tmo_func
== 0))
1715 ATDISABLE(s
, asptmo_lock
);
1716 if (scb_tmo_list
== scb
) {
1717 if ((scb_tmo_list
= scb
->next_tmo
) != 0) {
1718 scb_tmo_list
->prev_tmo
= 0;
1719 scb
->next_tmo
->tmo_delta
+= scb
->tmo_delta
;
1721 } else if (scb
->prev_tmo
) {
1722 if ((scb
->prev_tmo
->next_tmo
= scb
->next_tmo
) != 0) {
1723 scb
->next_tmo
->prev_tmo
= scb
->prev_tmo
;
1724 scb
->next_tmo
->tmo_delta
+= scb
->tmo_delta
;
1729 ATENABLE(s
, asptmo_lock
);
1742 * set the state to Close
1744 ATDISABLE(s
, scb
->lock
);
1745 scb
->state
= ASPSTATE_Close
;
1746 if (scb
->tickle_tid
) {
1747 atp_cancel_req(scb
->gref
, (unsigned int)scb
->tickle_tid
);
1748 scb
->tickle_tid
= 0;
1752 * notify upstream of the hangup
1754 if (scb
->rem_addr
.node
) {
1755 if (scb
->get_wait
) {
1756 thread_wakeup(&scb
->event
);
1757 ATENABLE(s
, scb
->lock
);
1759 ATENABLE(s
, scb
->lock
);
1760 atalk_notify_sel(scb
->gref
);
1763 ATENABLE(s
, scb
->lock
);
1767 asp_iocack(gref
, mioc
)
1771 if (gbuf_cont(mioc
))
1772 ((ioc_t
*)gbuf_rptr(mioc
))->ioc_count
= gbuf_msgsize(gbuf_cont(mioc
));
1774 ((ioc_t
*)gbuf_rptr(mioc
))->ioc_count
= 0;
1776 gbuf_set_type(mioc
, MSG_IOCACK
);
1777 atalk_putnext(gref
, mioc
);
1781 asp_iocnak(gref
, mioc
, err
)
1786 ((ioc_t
*)gbuf_rptr(mioc
))->ioc_count
= 0;
1789 ((ioc_t
*)gbuf_rptr(mioc
))->ioc_error
= err
;
1790 ((ioc_t
*)gbuf_rptr(mioc
))->ioc_rval
= -1;
1791 if (gbuf_cont(mioc
)) {
1792 gbuf_freem(gbuf_cont(mioc
));
1793 gbuf_cont(mioc
) = 0;
1796 gbuf_set_type(mioc
, MSG_IOCNAK
);
1797 atalk_putnext(gref
, mioc
);
1801 * the alloc scb routine
1803 StaticProc asp_scb_t
*
1808 asp_scb_t
*scb
, *scb_array
;
1810 ATDISABLE(s
, aspall_lock
);
1811 if (scb_free_list
== 0) {
1812 if ((m
= gbuf_alloc(SCBS_PER_BLK
*sizeof(asp_scb_t
), PRI_MED
)) == 0)
1814 ATENABLE(s
, aspall_lock
);
1815 return (asp_scb_t
*)0;
1817 bzero((char *)gbuf_rptr(m
), SCBS_PER_BLK
*sizeof(asp_scb_t
));
1818 gbuf_cont(m
) = scb_resource_m
;
1820 scb_array
= (asp_scb_t
*)gbuf_rptr(m
);
1821 for (i
=0; i
< SCBS_PER_BLK
-1; i
++)
1822 scb_array
[i
].next_scb
= (asp_scb_t
*)&scb_array
[i
+1];
1823 scb_array
[i
].next_scb
= 0;
1824 scb_free_list
= (asp_scb_t
*)&scb_array
[0];
1827 scb
= scb_free_list
;
1828 scb_free_list
= scb
->next_scb
;
1829 ATENABLE(s
, aspall_lock
);
1830 ATLOCKINIT(scb
->lock
);
1831 ATLOCKINIT(scb
->delay_lock
);
1832 ATEVENTINIT(scb
->event
);
1833 ATEVENTINIT(scb
->delay_event
);
1839 * the free scb routine
1847 bzero((char *)scb
, sizeof(asp_scb_t
));
1848 ATDISABLE(s
, aspall_lock
);
1849 scb
->next_scb
= scb_free_list
;
1850 scb_free_list
= scb
;
1851 ATENABLE(s
, aspall_lock
);
1855 * routine to pass up receive data
1858 asp_putnext(gref
, mproto
)
1866 scb
= (asp_scb_t
*)gref
->info
;
1869 * queue the message.
1871 ATDISABLE(s
, scb
->lock
);
1872 gbuf_next(mproto
) = 0;
1873 if ((m
= scb
->sess_ioc
) == 0)
1874 scb
->sess_ioc
= mproto
;
1876 while (gbuf_next(m
))
1878 gbuf_next(m
) = mproto
;
1881 if (scb
->rcv_cnt
>= MAX_RCV_CNT
)
1884 if (scb
->get_wait
) {
1885 thread_wakeup(&scb
->event
);
1886 ATENABLE(s
, scb
->lock
);
1887 } else if (mproto
== scb
->sess_ioc
) {
1888 ATENABLE(s
, scb
->lock
);
1889 atalk_notify_sel(gref
);
1891 ATENABLE(s
, scb
->lock
);
1895 * The following two routines are direct entries from system
1896 * calls to allow fast sending and recving of ASP data.
1899 /* in ASPputmsg we expect:
1905 ASPFUNC_WriteContinue
1907 bms: Make this callable from the kernel.
1908 If mreq != NULL, then must be called from kernel space and the following apply:
1909 1) *mreq is data to be sent already in mbuf chains.
1910 2) datptr->len = size of data
1913 int ASPputmsg(gref_t
*gref
, strbuf_t
*ctlptr
, strbuf_t
*datptr
, gbuf_t
*mreq
, int flags
, int *errp
)
1916 gbuf_t
*mioc
, *mdata
, *mx
;
1921 int nbds
, result
, msize
, Primitive
;
1922 unsigned char *wptr
;
1923 struct atp_set_default
*sd
;
1926 struct atpBDS
*atpBDS
;
1928 union asp_primitives
*primitives
;
1931 if ((scb
= (asp_scb_t
*)gref
->info
) == 0) {
1932 dPrintf(D_M_ASP
, D_L_ERROR
,
1933 ("ASPputmsg: stale handle=0x%x, pid=%d\n",
1934 (u_int
) gref
, gref
->pid
));
1940 if (scb
->state
== ASPSTATE_Close
)
1942 if (scb
->snd_stop
) {
1948 * copy in the control and data info
1951 /* being called from kernel space */
1952 bcopy (ctlptr
, &ctlbuf
, sizeof (strbuf_t
));
1953 bcopy (datptr
, &datbuf
, sizeof (strbuf_t
));
1955 /* being called from user space */
1956 if ((err
= copyin((caddr_t
)ctlptr
, (caddr_t
)&ctlbuf
, sizeof(ctlbuf
))) != 0)
1958 if ((err
= copyin((caddr_t
)datptr
, (caddr_t
)&datbuf
, sizeof(datbuf
))) != 0)
1963 * allocate buffer and copy in the control content
1965 if (!(mioc
= gbuf_alloc_wait(ctlbuf
.len
, TRUE
))) {
1966 /* error return should not be possible */
1970 gbuf_set_type(mioc
, MSG_IOCTL
); /* for later, in ATP */
1971 gbuf_wset(mioc
, ctlbuf
.len
);
1974 /* being called from kernel space */
1975 bcopy (ctlbuf
.buf
, gbuf_rptr(mioc
), ctlbuf
.len
);
1977 /* being called from user space */
1978 if ((err
= copyin((caddr_t
)ctlbuf
.buf
, (caddr_t
)gbuf_rptr(mioc
), ctlbuf
.len
)) != 0) {
1984 iocbp
= (ioc_t
*)gbuf_rptr(mioc
);
1985 primitives
= (union asp_primitives
*)gbuf_rptr(mioc
);
1986 Primitive
= primitives
->Primitive
;
1987 dPrintf(D_M_ASP
, D_L_INFO
,
1988 ("ASPputmsg: %s\n", aspCmdStr(Primitive
)));
1991 * allocate buffer and copy in the data content
1993 len
= (Primitive
== ASPFUNC_CmdReply
) ? 0 : aspCMDsize
;
1995 if (!(mdata
= gbuf_alloc_wait(datbuf
.len
+len
, TRUE
))) {
1996 /* error return should not be possible */
2001 gbuf_wset(mdata
, (datbuf
.len
+len
));
2002 gbuf_cont(mioc
) = mdata
;
2005 /* being called from kernel space */
2007 unsigned long offset
= 0;
2009 /* copy afp cmd data from the passed in mbufs to mdata. I cant
2010 chain mreq to mdata since the rest of this code assumes
2011 just one big mbuf with space in front for the BDS */
2013 while (tmp
!= NULL
) {
2014 bcopy (gbuf_rptr(tmp
), (gbuf_rptr(mdata
) + offset
), gbuf_len(tmp
));
2015 offset
+= gbuf_len(tmp
);
2016 tmp
= gbuf_cont(tmp
); /* on to next mbuf in chain */
2019 /* all data copied out of mreq so free it */
2022 /* being called from user space */
2023 if ((err
= copyin((caddr_t
)datbuf
.buf
,
2024 (caddr_t
)(gbuf_rptr(mdata
)+len
), datbuf
.len
)) != 0) {
2030 switch (Primitive
) {
2032 case ASPFUNC_Command
:
2034 case ASPFUNC_WriteContinue
:
2035 case ASPFUNC_Attention
:
2037 * build the command/write/write_continue request
2039 wptr
= gbuf_rptr(mdata
);
2040 atpBDS
= (struct atpBDS
*)wptr
;
2042 for (i
=0; i
< ATP_TRESP_MAX
; i
++) {
2043 *(unsigned long *)atpBDS
[i
].bdsBuffAddr
= 1;
2044 *(unsigned short *)atpBDS
[i
].bdsBuffSz
= ATP_DATA_SIZE
;
2046 sd
= (struct atp_set_default
*)wptr
;
2047 wptr
+= sizeof(struct atp_set_default
);
2048 sd
->def_retries
= (scb
->cmd_retry
.retries
== -1) ?
2049 ATP_INFINITE_RETRIES
: scb
->cmd_retry
.retries
;
2050 sd
->def_rate
= scb
->cmd_retry
.interval
*TICKS_PER_SEC
;
2051 sd
->def_BDSlen
= atpBDSsize
;
2052 ddp
= (at_ddp_t
*)wptr
;
2053 NET_ASSIGN(ddp
->src_net
, scb
->loc_addr
.net
);
2054 ddp
->src_node
= scb
->loc_addr
.node
;
2055 NET_ASSIGN(ddp
->dst_net
, scb
->rem_addr
.net
);
2056 ddp
->dst_node
= scb
->rem_addr
.node
;
2057 ddp
->dst_socket
= scb
->rem_addr
.socket
;
2058 UAS_ASSIGN(ddp
->checksum
, 0);
2059 atp
= ATP_ATP_HDR(wptr
);
2060 wptr
+= TOTAL_ATP_HDR_SIZE
;
2064 awp
= (asp_word_t
*)atp
->user_bytes
;
2065 awp
->func
= (unsigned char)Primitive
;
2066 awp
->param1
= scb
->sess_id
;
2067 awp
->param2
= scb
->snd_seq_num
;
2068 iocbp
->ioc_private
= (void *)scb
;
2069 iocbp
->ioc_count
= gbuf_len(mdata
);
2070 iocbp
->ioc_rval
= 0;
2071 iocbp
->ioc_cmd
= AT_ATP_ISSUE_REQUEST_DEF
;
2074 * send the command/write/write_continue/attention request
2076 ATDISABLE(s
, scb
->lock
);
2077 switch (awp
->func
) {
2078 case ASPFUNC_Command
:
2079 scb
->state
= ASPSTATE_WaitingForCommandRsp
;
2082 scb
->state
= ASPSTATE_WaitingForWriteRsp
;
2084 case ASPFUNC_WriteContinue
:
2085 scb
->state
= ASPSTATE_WaitingForWriteContinueRsp
;
2086 awp
->param2
= scb
->wrt_seq_num
;
2088 case ASPFUNC_Attention
:
2089 scb
->state
= ASPSTATE_WaitingForCommandRsp
;
2094 awp
->param2
= *(unsigned short *)gbuf_wptr(mdata
);
2097 ATENABLE(s
, scb
->lock
);
2098 dPrintf(D_M_ASP
,D_L_INFO
,
2099 ("ASPputmsg: %s, loc=%d, rem=%x.%x.%d\n",
2100 (awp
->func
== ASPFUNC_Command
? "CommandReq" :
2101 awp
->func
== ASPFUNC_Write
? "WriteReq" :
2102 awp
->func
== ASPFUNC_WriteContinue
? "WriteContinue" :
2103 "AttentionReq"),scb
->loc_addr
.socket
,
2104 NET_VALUE(ddp
->dst_net
),ddp
->dst_node
,ddp
->dst_socket
));
2105 atp_send_req(gref
, mioc
);
2108 case ASPFUNC_CmdReply
:
2110 ATDISABLE(s
, scb
->lock
);
2111 if (scb
->req_msgq
) {
2113 scb
->req_msgq
= gbuf_next(mx
);
2115 ATENABLE(s
, scb
->lock
);
2116 asp_putnext(scb
->gref
, mx
);
2119 ATENABLE(s
, scb
->lock
);
2121 result
= primitives
->CmdReplyReq
.CmdResult
;
2122 tid
= primitives
->CmdReplyReq
.ReqRefNum
;
2124 /* Re-use the original mioc mbuf to send the response. */
2125 gbuf_rinc(mioc
,sizeof(void *));
2127 ddp
= (at_ddp_t
*)gbuf_wptr(mioc
);
2128 gbuf_winc(mioc
,DDP_X_HDR_SIZE
);
2129 atp
= (at_atp_t
*)gbuf_wptr(mioc
);
2130 gbuf_winc(mioc
,ATP_HDR_SIZE
);
2131 NET_ASSIGN(ddp
->src_net
, scb
->loc_addr
.net
);
2132 ddp
->src_node
= scb
->loc_addr
.node
;
2133 NET_ASSIGN(ddp
->dst_net
, scb
->rem_addr
.net
);
2134 ddp
->dst_node
= scb
->rem_addr
.node
;
2135 ddp
->dst_socket
= scb
->reply_socket
;
2136 ddp
->type
= DDP_ATP
;
2137 UAS_ASSIGN(ddp
->checksum
, 0);
2138 UAS_ASSIGN(atp
->tid
, tid
);
2139 if (scb
->attn_flag
&& (tid
== scb
->attn_tid
)) {
2147 atpBDS
= (struct atpBDS
*)gbuf_wptr(mioc
);
2148 msize
= mdata
? gbuf_msgsize(mdata
) : 0;
2149 for (nbds
=0; (nbds
< ATP_TRESP_MAX
) && (msize
> 0); nbds
++) {
2150 len
= msize
< ATP_DATA_SIZE
? msize
: ATP_DATA_SIZE
;
2151 msize
-= ATP_DATA_SIZE
;
2152 *(long *)atpBDS
[nbds
].bdsUserData
= 0;
2153 UAL_ASSIGN(atpBDS
[nbds
].bdsBuffAddr
, 1);
2154 UAS_ASSIGN(atpBDS
[nbds
].bdsBuffSz
, len
);
2156 UAS_ASSIGN(atpBDS
[0].bdsDataSz
, nbds
);
2157 *(long *)atpBDS
[0].bdsUserData
= (long)result
;
2158 *(long *)atp
->user_bytes
= (long)result
;
2159 gbuf_winc(mioc
,atpBDSsize
);
2160 dPrintf(D_M_ASP
, D_L_INFO
,
2161 ("ASPputmsg: ATP CmdReplyReq, loc=%d, state=%s, msgsize = %d, result = %d, tid = %d\n",
2162 scb
->loc_addr
.socket
, aspStateStr(scb
->state
),
2163 (mdata
? gbuf_msgsize(mdata
) : 0), result
, tid
));
2164 atp_send_rsp(gref
, mioc
, TRUE
);
2168 /* Not an expected ASPFUNC */
2178 /* bms: make this callable from kernel. reply date is passed back as a mbuf chain in *mreply */
2179 int ASPgetmsg(gref_t
*gref
, strbuf_t
*ctlptr
, strbuf_t
*datptr
, gbuf_t
**mreply
, int *flags
, int *errp
)
2181 int err
, s
, len
, sum
, rval
;
2182 gbuf_t
*mproto
, *mdata
;
2186 unsigned char get_wait
;
2188 if ((scb
= (asp_scb_t
*)gref
->info
) == 0) {
2189 dPrintf(D_M_ASP
, D_L_ERROR
,
2190 ("ASPgetmsg: stale handle=0x%x, pid=%d\n",
2191 (u_int
) gref
, gref
->pid
));
2197 ATDISABLE(s
, scb
->lock
);
2198 if (scb
->state
== ASPSTATE_Close
) {
2199 ATENABLE(s
, scb
->lock
);
2206 while ((mproto
= scb
->sess_ioc
) == 0) {
2208 err
= tsleep(&scb
->event
, PSOCK
| PCATCH
, "aspgetmsg", 0);
2211 ATENABLE(s
, scb
->lock
);
2215 if (scb
->state
== ASPSTATE_Close
) {
2217 ATENABLE(s
, scb
->lock
);
2221 get_wait
= scb
->get_wait
;
2223 if ((ctlptr
== 0) && (datptr
== 0)) {
2224 ATENABLE(s
, scb
->lock
);
2227 scb
->sess_ioc
= gbuf_next(mproto
);
2228 mdata
= gbuf_cont(mproto
);
2229 ATENABLE(s
, scb
->lock
);
2231 /* last remaining use of MSG_ERROR */
2232 if (gbuf_type(mproto
) == MSG_ERROR
) {
2233 err
= (int)gbuf_rptr(mproto
)[0];
2238 * copy in the control and data info
2240 if (mreply
!= NULL
) {
2241 /* called from kernel space */
2242 bcopy (ctlptr
, &ctlbuf
, sizeof(ctlbuf
));
2243 bcopy (datptr
, &datbuf
, sizeof(datbuf
));
2245 /* called from user space */
2246 if ((err
= copyin((caddr_t
)ctlptr
,
2247 (caddr_t
)&ctlbuf
, sizeof(ctlbuf
))) != 0)
2249 if ((err
= copyin((caddr_t
)datptr
,
2250 (caddr_t
)&datbuf
, sizeof(datbuf
))) != 0)
2253 if ((datbuf
.maxlen
< 0) || (datbuf
.maxlen
< gbuf_msgsize(mdata
))) {
2254 ATDISABLE(s
, scb
->lock
);
2255 gbuf_next(mproto
) = scb
->sess_ioc
;
2256 scb
->sess_ioc
= mproto
;
2257 ATENABLE(s
, scb
->lock
);
2261 if (get_wait
== 0) {
2263 * this is a hack to support the select() call.
2264 * we're not supposed to dequeue messages in the Streams
2265 * head's read queue this way; but there is no better way.
2267 ATDISABLE(s
, scb
->lock
);
2268 if (scb
->sess_ioc
== 0) {
2269 ATENABLE(s
, scb
->lock
);
2271 ATENABLE(s
, scb
->lock
);
2272 atalk_notify_sel(gref
);
2277 * copy out the control content and info
2279 ctlbuf
.len
= gbuf_len(mproto
);
2281 if (mreply
!= NULL
) {
2282 /* called from kernel space */
2283 bcopy (gbuf_rptr(mproto
), ctlbuf
.buf
, ctlbuf
.len
);
2284 bcopy (&ctlbuf
, ctlptr
, sizeof(ctlbuf
));
2286 /* called from user space */
2287 if ((err
= copyout((caddr_t
)gbuf_rptr(mproto
),
2288 (caddr_t
)ctlbuf
.buf
, ctlbuf
.len
)) != 0)
2290 if ((err
= copyout((caddr_t
)&ctlbuf
,
2291 (caddr_t
)ctlptr
, sizeof(ctlbuf
))) != 0)
2296 * copy out the data content and info
2298 for (rval
= 0, sum
= 0; mdata
&& (rval
== 0); mdata
= gbuf_cont(mdata
))
2300 len
= gbuf_len(mdata
);
2302 if ((len
+ sum
) > datbuf
.maxlen
) {
2303 len
= datbuf
.maxlen
- sum
;
2307 if (mreply
== NULL
) {
2308 /* called from user space */
2309 if ((err
= copyout((caddr_t
)gbuf_rptr(mdata
), (caddr_t
)&datbuf
.buf
[sum
], len
)) != 0)
2316 if (mreply
!= NULL
) {
2317 /* called from kernel space */
2318 bcopy (&datbuf
, datptr
, sizeof(datbuf
));
2320 /* called from user space */
2321 if ((err
= copyout((caddr_t
)&datbuf
, (caddr_t
)datptr
, sizeof(datbuf
))) != 0)
2325 if (mreply
!= NULL
) {
2326 /* called from kernel space */
2327 /* return the reply data in mbufs, so dont free them.
2328 Just free the proto info */
2329 mdata
= gbuf_cont(mproto
);
2331 gbuf_cont(mproto
) = NULL
;
2334 /* called from user space */
2338 ATDISABLE(s
, scb
->lock
);
2345 ATENABLE(s
, scb
->lock
);
2349 ATDISABLE(s
, scb
->lock
);
2350 gbuf_next(mproto
) = scb
->sess_ioc
;
2351 scb
->sess_ioc
= mproto
;
2352 ATENABLE(s
, scb
->lock
);