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(void *);
88 StaticProc asp_scb_t
*asp_find_scb();
89 StaticProc asp_scb_t
*asp_scb_alloc();
91 StaticProc
void asp_putnext();
92 StaticProc
void asp_iocack();
93 StaticProc
void asp_iocnak();
94 StaticProc
void asp_dequeue_scb();
95 StaticProc
void asp_scb_free();
96 StaticProc
void asp_timout();
97 StaticProc
void asp_untimout();
98 StaticProc
void asp_hangup();
99 StaticProc
void asp_send_tickle();
100 StaticProc
void asp_send_tickle_funnel(void *);
101 StaticProc
void asp_accept();
102 StaticProc
int asp_send_req();
104 extern at_ifaddr_t
*ifID_home
;
105 extern int atp_pidM
[];
106 extern gref_t
*atp_inputQ
[];
107 gbuf_t
*scb_resource_m
= 0;
108 unsigned char asp_inpC
[256];
109 asp_scb_t
*asp_scbQ
[256];
111 static at_retry_t asp_def_retry
= {2, -1, 1};
112 static unsigned char scb_tmo_cnt
;
113 asp_scb_t
*scb_used_list
;
114 static asp_scb_t
*scb_tmo_list
;
115 asp_scb_t
*scb_free_list
;
116 atlock_t aspall_lock
, asptmo_lock
;
122 return (((asp_scb_t
*)gref
->info
)->sess_ioc
? 1 : 0);
132 bzero(asp_inpC
, sizeof(asp_inpC
));
133 bzero(asp_scbQ
, sizeof(asp_scbQ
));
137 * the open routine allocates a state structure
146 * if no asp structure available, return failure
148 if ((scb
= asp_scb_alloc()) == 0)
152 * initialize the gref data structure
154 gref
->info
= (void *)scb
;
155 gref
->readable
= asp_readable
;
158 * initialize the scb data structure
161 scb
->magic_num
= 222;
162 scb
->state
= ASPSTATE_Idle
;
163 scb
->pid
= gref
->pid
;
165 scb
->session_timer
= DEF_SESS_TMO
;
166 scb
->cmd_retry
= asp_def_retry
;
167 ATDISABLE(s
, aspall_lock
);
168 if ((scb
->next_scb
= scb_used_list
) != 0)
169 scb
->next_scb
->prev_scb
= scb
;
171 ATENABLE(s
, aspall_lock
);
176 dPrintf(D_M_ASP
, D_L_INFO
, ("asp_open: pid=%d\n", scb
->pid
));
181 * the close routine frees all the data structures
188 unsigned char sock_num
;
189 asp_scb_t
*scb
, *new_scb
;
192 scb
= (asp_scb_t
*)gref
->info
;
193 dPrintf(D_M_ASP
, D_L_INFO
, ("asp_close: loc=%d\n",
194 scb
->loc_addr
.socket
));
196 if (scb
->pid
&& scb
->sess_ioc
&& (scb
->dflag
!= 1)) {
198 * send the CloseSess response to peer
200 if (gbuf_type(scb
->sess_ioc
) != MSG_PROTO
) {
201 ATDISABLE(s
, scb
->lock
);
203 scb
->sess_ioc
= gbuf_next(m
);
204 ATENABLE(s
, scb
->lock
);
205 atp_send_rsp(scb
->gref
, m
, TRUE
);
209 if (scb
->atp_state
) {
210 sock_num
= scb
->loc_addr
.socket
;
211 ATDISABLE(s
, aspall_lock
);
212 if ((scb
->dflag
!= 1) && scb
->stat_msg
) {
213 untimeout(atp_retry_req
, scb
->stat_msg
);
214 gbuf_freem(scb
->stat_msg
);
217 if (asp_scbQ
[sock_num
]->next_scb
== 0) {
218 asp_scbQ
[sock_num
] = 0;
219 asp_inpC
[sock_num
] = 0;
220 ATENABLE(s
, aspall_lock
);
221 dPrintf(D_M_ASP
, D_L_INFO
,
222 (" : atp_close(), loc=%d\n", scb
->loc_addr
.socket
));
225 asp_inpC
[sock_num
]--;
226 if (scb
== asp_scbQ
[sock_num
]) {
227 new_scb
= scb
->next_scb
;
228 new_scb
->prev_scb
= 0;
229 asp_scbQ
[sock_num
] = new_scb
;
230 new_scb
->atp_state
->atp_gref
= new_scb
->gref
;
231 new_scb
->atp_state
->pid
= new_scb
->pid
;
232 atp_inputQ
[sock_num
] = new_scb
->gref
;
234 if ((scb
->prev_scb
->next_scb
= scb
->next_scb
) != 0)
235 scb
->next_scb
->prev_scb
= scb
->prev_scb
;
238 ATENABLE(s
, aspall_lock
);
241 asp_dequeue_scb(scb
);
244 * free all allocated blocks if any
246 ATDISABLE(s
, scb
->lock
);
248 gbuf_freem(scb
->stat_msg
);
252 gbuf_freel(scb
->sess_ioc
);
256 gbuf_freel(scb
->req_msgq
);
260 scb
->rem_addr
.node
= 0;
261 ATENABLE(s
, scb
->lock
);
267 asp_untimout(asp_hangup
, scb
);
268 untimeout(asp_send_tickle_funnel
, (void *)scb
); /* added for 2225395 */
271 * free the asp session control block
273 scb
->state
= ASPSTATE_Close
;
278 static char *aspStateStr(state
)
281 return ((state
==ASPSTATE_Close
)? "Close":
282 (state
==ASPSTATE_Idle
)? "Idle":
283 (state
==ASPSTATE_WaitingForGetStatusRsp
)? "GetStatusRsp":
284 (state
==ASPSTATE_WaitingForOpenSessRsp
)? "OpenSessRsp":
285 (state
==ASPSTATE_WaitingForCommandRsp
)? "CmdRsp":
286 (state
==ASPSTATE_WaitingForWriteContinue
)? "WriteCont":
287 (state
==ASPSTATE_WaitingForWriteRsp
)? "WriteRsp":
288 (state
==ASPSTATE_WaitingForWriteContinueRsp
)? "WriteContRsp":
289 (state
==ASPSTATE_WaitingForCloseSessRsp
)? "CloseSessRsp":
293 static char *aspCmdStr(aspCmd
)
296 return ((aspCmd
==ASPFUNC_CloseSess
)? "CloseSess":
297 (aspCmd
==ASPFUNC_Command
)? "Command":
298 (aspCmd
==ASPFUNC_GetStatus
)? "GetStatus":
299 (aspCmd
==ASPFUNC_OpenSess
)? "OpenSess":
300 (aspCmd
==ASPFUNC_Tickle
)? "Tickle":
301 (aspCmd
==ASPFUNC_Write
)? "Write":
302 (aspCmd
==ASPFUNC_WriteContinue
)? "WriteContinue":
303 (aspCmd
==ASPFUNC_Attention
)? "Attention":
304 (aspCmd
==ASPFUNC_CmdReply
)? "CmdReply": "unknown");
307 static char *aspIOCStr(aspIOC
)
311 (aspIOC
==ASPIOC_ClientBind
)? "ClientBind":
312 (aspIOC
==ASPIOC_CloseSession
)? "CloseSession":
313 (aspIOC
==ASPIOC_GetLocEntity
)? "GetLocEntity":
314 (aspIOC
==ASPIOC_GetRemEntity
)? "GetRemEntity":
315 (aspIOC
==ASPIOC_GetSession
)? "GetSession":
316 (aspIOC
==ASPIOC_GetStatus
)? "GetStatus":
317 (aspIOC
==ASPIOC_ListenerBind
)? "ListenerBind":
318 (aspIOC
==ASPIOC_OpenSession
)? "OpenSession":
319 (aspIOC
==ASPIOC_StatusBlock
)? "StatusBlock":
320 (aspIOC
==ASPIOC_SetPid
)? "SetPid":
321 (aspIOC
==ASPIOC_GetSessId
)? "GetSessId":
322 (aspIOC
==ASPIOC_EnableSelect
)? "EnableSelect":
323 (aspIOC
==ASPIOC_Look
)? "Look":
330 static char mbuf_str
[100];
335 "dat = %d, prot = %d, ioc = %d, err = %d, hu = %d, ack = %d, nak = %d, ctl = %d",
337 "dat = %d, prot = %d, ioc = %d, ctl = %d",
338 mbstat
.m_mtypes
[MSG_DATA
], mbstat
.m_mtypes
[MSG_PROTO
], mbstat
.m_mtypes
[MSG_IOCTL
],
340 mbstat.m_mtypes[MSG_ERROR], mbstat.m_mtypes[MSG_HANGUP], mbstat.m_mtypes[MSG_IOCACK],
341 mbstat.m_mtypes[MSG_IOCNAK],
343 mbstat
.m_mtypes
[MSG_CTL
]);
344 return(&mbuf_str
[0]);
347 void trace_beg(str
, m
)
352 gbuf_t
*mdata
, *mchain
;
355 for (i
= 0, j
= 0, mdata
= m
, mchain
= m
; mdata
; i
++) {
356 mdata
= gbuf_cont(mdata
);
357 if (!mdata
&& mchain
) {
358 mdata
= gbuf_next(mchain
);
363 dPrintf(D_M_ASP
, D_L_TRACE
,
364 ("%s: %s, m# = %d, c# = %d\n", str
, mbuf_totals(), i
, j
));
370 dPrintf(D_M_ASP
, D_L_TRACE
,
371 (" %s: %s\n", str
, mbuf_totals()));
373 #endif /* AT_MBUF_TRACE */
378 int asp_wput(gref
, m
)
383 unsigned char sockSav
, sock_num
;
384 gbuf_t
*mioc
, *mdata
;
386 asp_scb_t
*scb
, *server_scb
, *curr_scb
;
389 union asp_primitives
*primitives
;
390 asp_status_cmd_t
*status_cmd
;
391 asp_open_cmd_t
*open_cmd
;
394 scb
= (asp_scb_t
*)gref
->info
;
395 if (scb
->dflag
== 0) {
400 if (gbuf_type(m
) != MSG_IOCTL
) {
401 dPrintf(D_M_ASP
, D_L_WARNING
,
402 ("asp_wput: UNKNOWN message, type=%d\n",
409 iocbp
= (ioc_t
*)gbuf_rptr(mioc
);
411 dPrintf(D_M_ASP_LOW
, D_L_INFO
,
412 ("asp_wput: %s, loc=%d, state=%s\n",
413 aspIOCStr(iocbp
->ioc_cmd
), scb
->loc_addr
.socket
,
414 aspStateStr(scb
->state
)));
416 switch (iocbp
->ioc_cmd
) {
417 case ASPIOC_CloseSession
:
418 if ((scb
->state
== ASPSTATE_Close
) || (scb
->rem_addr
.node
== 0))
423 aw
.func
= ASPFUNC_CloseSess
;
424 aw
.param1
= scb
->sess_id
;
426 iocbp
->ioc_private
= (void *)scb
;
427 scb
->ioc_wait
= (unsigned char)(iocbp
->ioc_cmd
& 0xff);
428 iocbp
->ioc_cmd
= AT_ATP_ISSUE_REQUEST
;
429 asp_send_req(gref
, mioc
, &scb
->rem_addr
, &Retry
, &aw
,
430 0, ASPSTATE_WaitingForCloseSessRsp
, 0x01);
433 case ASPIOC_ClientBind
:
435 * open an ATP channel
437 if ((err
= atp_open(gref
, 0)) != 0) {
438 asp_iocnak(gref
, mioc
, err
);
441 scb
->atp_state
= (atp_state_t
*)gref
->info
;
442 scb
->atp_state
->pid
= scb
->pid
;
444 * bind to any available socket
447 sockSav
= scb
->dflag
;
448 if ((sock_num
= (at_socket
)atp_bind(gref
, 0, &sockSav
)) == 0) {
449 scb
->atp_state
= (atp_state_t
*)0;
451 gref
->info
= (void *)scb
;
452 asp_iocnak(gref
, mioc
, EINVAL
);
455 gref
->info
= (void *)scb
;
456 asp_dequeue_scb(scb
);
457 scb
->atp_state
->dflag
= scb
->dflag
;
458 scb
->loc_addr
.socket
= sock_num
;
459 asp_scbQ
[sock_num
] = scb
;
460 asp_inpC
[sock_num
]++;
461 atp_pidM
[sock_num
] = 0;
464 case ASPIOC_ListenerBind
:
466 * open an ATP channel
468 if ((err
= atp_open(gref
, 0)) != 0) {
469 asp_iocnak(gref
, mioc
, err
);
472 scb
->atp_state
= (atp_state_t
*)gref
->info
;
473 scb
->atp_state
->pid
= scb
->pid
;
475 * bind to any available socket
477 if ((sock_num
= (at_socket
)atp_bind(gref
, 0, 0)) == 0) {
478 scb
->atp_state
= (atp_state_t
*)0;
480 gref
->info
= (void *)scb
;
481 asp_iocnak(gref
, mioc
, EINVAL
);
484 gref
->info
= (void *)scb
;
485 asp_dequeue_scb(scb
);
486 scb
->atp_state
->dflag
= scb
->dflag
;
487 scb
->loc_addr
.socket
= sock_num
;
488 asp_scbQ
[sock_num
] = scb
;
489 asp_inpC
[sock_num
]++;
491 *(at_inet_t
*)gbuf_rptr(gbuf_cont(mioc
)) = scb
->loc_addr
;
494 case ASPIOC_GetLocEntity
:
495 if ((gbuf_cont(mioc
) == 0) || (scb
->atp_state
== 0)) {
496 asp_iocnak(gref
, mioc
, EPROTO
);
499 *(at_inet_t
*)gbuf_rptr(gbuf_cont(mioc
)) = scb
->loc_addr
;
502 case ASPIOC_GetRemEntity
:
503 if ((gbuf_cont(mioc
) == 0) || (scb
->atp_state
== 0)) {
504 asp_iocnak(gref
, mioc
, EPROTO
);
507 *(at_inet_t
*)gbuf_rptr(gbuf_cont(mioc
)) = scb
->rem_addr
;
510 case ASPIOC_GetSession
:
511 if ((mdata
= gbuf_cont(mioc
)) == 0) {
512 asp_iocnak(gref
, mioc
, EPROTO
);
515 addr
= (at_inet_t
*)gbuf_rptr(mdata
);
516 scb
->tickle_interval
= (unsigned short)addr
->node
;
517 scb
->session_timer
= addr
->net
;
518 server_scb
= asp_scbQ
[addr
->socket
];
519 /*### LD 10/28/97: changed to make sure we're not accessing a null server_scb */
520 if (server_scb
== 0) {
521 asp_iocnak(gref
, mioc
, EPROTO
);
524 if (server_scb
->sess_ioc
== 0) {
525 asp_iocnak(gref
, mioc
, EPROTO
);
530 * open an ATP channel
532 if ((err
= atp_open(gref
, 0)) != 0) {
533 gref
->info
= (void *)scb
;
534 asp_iocnak(gref
, mioc
, err
);
537 scb
->atp_state
= (atp_state_t
*)gref
->info
;
538 scb
->atp_state
->pid
= scb
->pid
;
540 * bind to any available socket
543 sockSav
= scb
->dflag
;
544 if ((sock_num
= (at_socket
)atp_bind(gref
, 0, &sockSav
)) == 0) {
546 asp_dequeue_scb(scb
);
547 ATDISABLE(s
, aspall_lock
);
549 scb
->loc_addr
.socket
= sock_num
;
550 for (curr_scb
= asp_scbQ
[sock_num
];
551 curr_scb
->next_scb
; curr_scb
= curr_scb
->next_scb
) ;
552 scb
->prev_scb
= curr_scb
;
553 curr_scb
->next_scb
= scb
;
554 scb
->atp_state
= curr_scb
->atp_state
;
555 ATENABLE(s
, aspall_lock
);
557 asp_dequeue_scb(scb
);
558 ATDISABLE(s
, aspall_lock
);
559 scb
->loc_addr
.socket
= sock_num
;
560 asp_scbQ
[sock_num
] = scb
;
561 scb
->atp_state
->dflag
= scb
->dflag
;
562 ATENABLE(s
, aspall_lock
);
564 gref
->info
= (void *)scb
;
565 asp_inpC
[sock_num
]++;
567 asp_accept(server_scb
, scb
, mdata
);
570 case ASPIOC_GetStatus
:
571 if ((mdata
= gbuf_cont(mioc
)) == 0) {
572 asp_iocnak(gref
, mioc
, EINVAL
);
576 status_cmd
= (asp_status_cmd_t
*)gbuf_rptr(mdata
);
577 aw
.func
= ASPFUNC_GetStatus
;
580 scb
->ioc_wait
= (unsigned char)(iocbp
->ioc_cmd
& 0xff);
581 iocbp
->ioc_cmd
= AT_ATP_ISSUE_REQUEST_DEF
;
582 /* bms: make sure this is an ALO request */
583 asp_send_req(gref
, mioc
, &status_cmd
->SLSEntityIdentifier
,
584 &status_cmd
->Retry
, &aw
, 0, ASPSTATE_WaitingForGetStatusRsp
, 0xff);
588 case ASPIOC_OpenSession
:
589 if ((mdata
= gbuf_cont(mioc
)) == 0) {
590 asp_iocnak(gref
, mioc
, EINVAL
);
594 open_cmd
= (asp_open_cmd_t
*)gbuf_rptr(mdata
);
595 scb
->svc_addr
= open_cmd
->SLSEntityIdentifier
;
596 scb
->rem_addr
= scb
->svc_addr
;
597 scb
->rem_node
= scb
->rem_addr
.node
;
598 scb
->rem_addr
.node
= 0;
599 scb
->tickle_interval
= open_cmd
->TickleInterval
;
600 scb
->session_timer
= open_cmd
->SessionTimer
;
601 aw
.func
= ASPFUNC_OpenSess
;
602 aw
.param1
= scb
->loc_addr
.socket
;
603 aw
.param2
= ASP_Version
;
604 scb
->ioc_wait
= (unsigned char)(iocbp
->ioc_cmd
& 0xff);
605 iocbp
->ioc_cmd
= AT_ATP_ISSUE_REQUEST_DEF
;
606 asp_send_req(gref
, mioc
, &open_cmd
->SLSEntityIdentifier
,
607 &open_cmd
->Retry
, &aw
, 1, ASPSTATE_WaitingForOpenSessRsp
, 0x01);
611 case ASPIOC_StatusBlock
:
613 * save the server status block
616 gbuf_freem(scb
->stat_msg
);
617 scb
->stat_msg
= gbuf_cont(mioc
);
621 /* *** Does scb->pid get used in a packet header,
622 and if so is it in ASP, or in ATP?
623 If not, do we need this call for anything?
624 (cap does currently use it in _ANS code.)
627 if (gbuf_cont(mioc
) == 0) {
628 asp_iocnak(gref
, mioc
, EINVAL
);
631 scb
->pid
= *(int *)gbuf_rptr(gbuf_cont(mioc
));
634 case ASPIOC_GetSessId
:
635 if (gbuf_cont(mioc
) == 0) {
636 asp_iocnak(gref
, mioc
, EINVAL
);
639 *(gref_t
**)gbuf_rptr(gbuf_cont(mioc
)) = gref
;
643 if (gbuf_cont(mioc
) == 0) {
644 asp_iocnak(gref
, mioc
, EINVAL
);
648 primitives
= (union asp_primitives
*)gbuf_rptr(scb
->sess_ioc
);
649 if (primitives
->Primitive
== ASPFUNC_CmdReply
)
650 *(int *)gbuf_rptr(gbuf_cont(mioc
)) = 0;
652 *(int *)gbuf_rptr(gbuf_cont(mioc
)) = 1;
654 *(int *)gbuf_rptr(gbuf_cont(mioc
)) = -1;
657 case DDP_IOC_GET_CFG
:
659 struct atp_state
*atp
= (struct atp_state
*)gref
->info
;
661 atp
= (struct atp_state
*)atp
->atp_msgq
;
663 if (gbuf_cont(mioc
) == 0) {
664 asp_iocnak(gref
, mioc
, EINVAL
);
667 /* *** borrowed from ddp_proto.c to handle DDP_IOC_GET_CFG
669 scb
->state
= ASPSTATE_Idle
;
671 /* *** was ddp_get_cfg() *** */
673 (ddp_addr_t
*)gbuf_rptr(gbuf_cont(mioc
));
674 cfgp
->inet
.net
= ifID_home
->ifThisNode
.s_net
;
675 cfgp
->inet
.node
= ifID_home
->ifThisNode
.s_node
;
676 cfgp
->inet
.socket
= atp
->atp_socket_no
;
677 cfgp
->ddptype
= DDP_ATP
;
679 gbuf_wset(gbuf_cont(mioc
), sizeof(at_inet_t
));
684 asp_iocnak(gref
, mioc
, EINVAL
);
688 asp_iocack(gref
, mioc
);
693 * send request routine
696 asp_send_req(gref
, mioc
, dest
, retry
, awp
, xo
, state
, bitmap
)
704 unsigned char bitmap
;
709 struct atp_set_default
*sd
;
712 struct atpBDS
*atpBDS
;
713 asp_scb_t
*scb
= (asp_scb_t
*)gref
->info
;
716 * allocate an ATP buffer for the request
718 if ((gbuf_cont(mioc
) = gbuf_alloc(aspCMDsize
, PRI_MED
)) == 0) {
719 if (awp
->func
== ASPFUNC_Tickle
)
722 asp_iocnak(gref
, mioc
, ENOBUFS
);
723 dPrintf(D_M_ASP
, D_L_WARNING
,
724 ("asp_send_req: ENOBUFS, loc=%d\n", scb
->loc_addr
.socket
));
728 mdata
= gbuf_cont(mioc
);
729 iocbp
= (ioc_t
*)gbuf_rptr(mioc
);
734 atpBDS
= (struct atpBDS
*)gbuf_rptr(mdata
);
735 gbuf_wset(mdata
,atpBDSsize
);
736 for (i
=0; i
< ATP_TRESP_MAX
; i
++) {
737 *(unsigned long *)atpBDS
[i
].bdsBuffAddr
= 1;
738 *(unsigned short *)atpBDS
[i
].bdsBuffSz
= ATP_DATA_SIZE
;
740 sd
= (struct atp_set_default
*)gbuf_wptr(mdata
);
741 gbuf_winc(mdata
,sizeof(struct atp_set_default
));
742 sd
->def_retries
= (retry
->retries
== -1) ?
743 ATP_INFINITE_RETRIES
: retry
->retries
;
744 sd
->def_rate
= retry
->interval
*TICKS_PER_SEC
;
745 sd
->def_BDSlen
= atpBDSsize
;
746 ddp
= (at_ddp_t
*)gbuf_wptr(mdata
);
747 NET_ASSIGN(ddp
->src_net
, scb
->loc_addr
.net
);
748 ddp
->src_node
= scb
->loc_addr
.node
;
749 NET_ASSIGN(ddp
->dst_net
, dest
->net
);
750 ddp
->dst_node
= dest
->node
;
751 ddp
->dst_socket
= dest
->socket
;
752 UAS_ASSIGN(ddp
->checksum
, 0);
753 atp
= ATP_ATP_HDR(gbuf_wptr(mdata
));
756 atp
->bitmap
= bitmap
;
757 gbuf_winc(mdata
,TOTAL_ATP_HDR_SIZE
);
758 *(asp_word_t
*)atp
->user_bytes
= *awp
;
759 iocbp
->ioc_count
= gbuf_len(mdata
);
766 dPrintf(D_M_ASP
, D_L_INFO
,
767 ("asp_send_req: %s, loc=%d, rem= %d, len=%d, state=%s\n",
768 aspCmdStr(awp
->func
),
769 scb
->loc_addr
.socket
, ddp
->dst_socket
, iocbp
->ioc_count
,
770 aspStateStr(scb
->state
)));
772 atp_send_req(gref
, mioc
);
777 * send tickle routine - funnelled version
780 asp_send_tickle_funnel(scb
)
783 thread_funnel_set(network_flock
, TRUE
);
784 asp_send_tickle((asp_scb_t
*)scb
);
785 thread_funnel_set(network_flock
, FALSE
);
790 * send tickle routine
803 * make sure the connection is still there
805 if (scb
->rem_addr
.node
== 0) {
809 if ((mioc
= gbuf_alloc(sizeof(ioc_t
), PRI_HI
)) == 0) {
810 dPrintf(D_M_ASP
, D_L_WARNING
,
811 ("asp_send_tickle: ENOBUFS 0, loc=%d, rem=%d\n",
812 scb
->loc_addr
.socket
,scb
->rem_addr
.socket
));
813 timeout(asp_send_tickle_funnel
, (void *)scb
, 10);
816 gbuf_wset(mioc
,sizeof(ioc_t
));
817 gbuf_set_type(mioc
, MSG_IOCTL
);
819 dest
= scb
->svc_addr
.node
?
820 (at_inet_t
*)&scb
->svc_addr
: (at_inet_t
*)&scb
->rem_addr
;
821 retry
.interval
= scb
->tickle_interval
;
824 aw
.func
= ASPFUNC_Tickle
;
825 aw
.param1
= scb
->sess_id
;
827 ((ioc_t
*)gbuf_rptr(mioc
))->ioc_cr
= (void *)scb
;
828 ((ioc_t
*)gbuf_rptr(mioc
))->ioc_cmd
= AT_ATP_ISSUE_REQUEST_TICKLE
;
830 if (asp_send_req(scb
->gref
, mioc
, dest
, &retry
, &aw
, 0, scb
->state
, 0)) {
831 dPrintf(D_M_ASP
, D_L_WARNING
,
832 ("asp_send_tickle: ENOBUFS 1, loc=%d, rem=%d\n",
833 scb
->loc_addr
.socket
,scb
->rem_addr
.socket
));
835 timeout(asp_send_tickle_funnel
, (void *)scb
, 10);
841 * accept connection routine
844 asp_accept(scb
, sess_scb
, m
)
856 mdata
= scb
->sess_ioc
;
857 ddp
= (at_ddp_t
*)gbuf_rptr(mdata
);
858 atp
= (at_atp_t
*)(gbuf_rptr(mdata
) + DDP_X_HDR_SIZE
);
859 rem_addr
.net
= NET_VALUE(ddp
->src_net
);
860 rem_addr
.node
= ddp
->src_node
;
861 rem_addr
.socket
= ddp
->src_socket
;
862 awp
= (asp_word_t
*)atp
->user_bytes
;
864 sess_scb
->loc_addr
.net
= NET_VALUE(ddp
->dst_net
);
865 sess_scb
->loc_addr
.node
= ddp
->dst_node
;
866 NET_ASSIGN(ddp
->src_net
, sess_scb
->loc_addr
.net
);
867 ddp
->src_node
= sess_scb
->loc_addr
.node
;
868 NET_ASSIGN(ddp
->dst_net
, rem_addr
.net
);
869 ddp
->dst_node
= rem_addr
.node
;
870 ddp
->dst_socket
= rem_addr
.socket
;
872 sess_scb
->sess_id
= sess_scb
->loc_addr
.socket
;
873 sess_scb
->rem_socket
= rem_addr
.socket
;
874 sess_scb
->rem_addr
= rem_addr
;
875 sess_scb
->rem_addr
.socket
= awp
->param1
;
876 sess_scb
->reply_socket
= sess_scb
->rem_addr
.socket
;
877 awp
->func
= sess_scb
->loc_addr
.socket
;
878 awp
->param1
= sess_scb
->sess_id
;
881 ATDISABLE(s
, scb
->lock
);
882 scb
->sess_ioc
= gbuf_next(mdata
);
883 ATENABLE(s
, scb
->lock
);
884 gbuf_next(mdata
) = 0;
885 asp_timout(asp_hangup
, sess_scb
, sess_scb
->session_timer
);
886 atp_send_rsp(scb
->gref
, mdata
, TRUE
);
887 asp_send_tickle(sess_scb
);
888 dPrintf(D_M_ASP
, D_L_INFO
,
889 ("asp_accept: ACCEPT connect request, loc=%d, rem=%x.%x.%d\n",
890 sess_scb
->loc_addr
.socket
,
891 sess_scb
->rem_addr
.net
,
892 sess_scb
->rem_addr
.node
,sess_scb
->rem_addr
.socket
));
896 * timer routine - funneled version
898 void asp_clock_funnel(arg
)
901 thread_funnel_set(network_flock
, TRUE
);
903 thread_funnel_set(network_flock
, FALSE
);
916 ATDISABLE(s
, asptmo_lock
);
918 scb_tmo_list
->tmo_delta
--;
919 while (((scb
= scb_tmo_list
) != 0) && (scb_tmo_list
->tmo_delta
== 0)) {
920 if ((scb_tmo_list
= scb
->next_tmo
) != 0)
921 scb_tmo_list
->prev_tmo
= 0;
922 if ((tmo_func
= scb
->tmo_func
) != 0) {
924 ATENABLE(s
, asptmo_lock
);
926 ATDISABLE(s
, asptmo_lock
);
929 ATENABLE(s
, asptmo_lock
);
931 if (++scb_tmo_cnt
== 0) scb_tmo_cnt
++;
932 timeout(asp_clock_funnel
, (void *)arg
, (1<<SESS_TMO_RES
)*TICKS_PER_SEC
);
940 asp_ack_reply(gref
, mioc
)
941 register gref_t
*gref
;
942 register gbuf_t
*mioc
;
945 int len
, msize
, nbds
;
946 register gbuf_t
*mdata
, *m
, *mx
;
947 struct atpBDS
*atpBDS
;
950 register asp_scb_t
*scb
, *sess_scb
;
951 register ioc_t
*iocbp
;
952 register asp_word_t
*awp
;
953 register asp_command_ind_t
*command_ind
;
954 register asp_cmdreply_ind_t
*cmdreply_ind
;
957 iocbp
= (ioc_t
*)gbuf_rptr(mioc
);
959 if (iocbp
->ioc_cmd
== AT_ATP_ISSUE_REQUEST_TICKLE
) {
961 * ignore the ack for the tickle request
963 scb
= (asp_scb_t
*)iocbp
->ioc_cr
;
964 scb
->tickle_tid
= (unsigned short)iocbp
->ioc_rval
;
969 scb
= (asp_scb_t
*)gref
->info
;
975 if (iocbp
->ioc_cmd
== AT_ATP_GET_POLL
) {
977 * if no data, just drop the request
979 if ((mdata
= gbuf_cont(mioc
)) == 0) {
984 gbuf_set_type(mioc
, MSG_IOCTL
);
985 ddp
= (at_ddp_t
*)gbuf_rptr(mdata
);
986 gbuf_rinc(mdata
,DDP_X_HDR_SIZE
);
987 atp
= (at_atp_t
*)gbuf_rptr(mdata
);
988 gbuf_rinc(mdata
,ATP_HDR_SIZE
);
989 rem_addr
.net
= NET_VALUE(ddp
->src_net
);
990 rem_addr
.node
= ddp
->src_node
;
991 rem_addr
.socket
= ddp
->src_socket
;
992 awp
= (asp_word_t
*)atp
->user_bytes
;
996 * find the responsible scb
998 if ((scb
= asp_find_scb(scb
->loc_addr
.socket
, &rem_addr
)) == 0) {
1003 dPrintf(D_M_ASP
, D_L_INFO
,
1004 ("asp_ack_reply: %s, loc=%d, rem=%x.%x.%d\n",
1005 aspCmdStr(awp
->func
),scb
->loc_addr
.socket
,
1006 NET_VALUE(ddp
->src_net
) ,ddp
->src_node
,ddp
->src_socket
));
1008 if (scb
->rem_addr
.node
)
1009 asp_untimout(asp_hangup
, scb
);
1011 switch (awp
->func
) {
1012 case ASPFUNC_GetStatus
:
1014 * ignore if this is not a server socket
1017 if ((scb
->dflag
!= 1) || (scb
->stat_msg
1018 && ((mx
= gbuf_dupb(scb
->stat_msg
)) == 0)))
1023 * send the status block
1025 if (gbuf_cont(mdata
)) {
1026 gbuf_freem(gbuf_cont(mdata
));
1027 gbuf_cont(mdata
) = 0;
1029 gbuf_rdec(mdata
,TOTAL_ATP_HDR_SIZE
);
1030 if ((m
= gbuf_alloc( (TOTAL_ATP_HDR_SIZE
+atpBDSsize
), PRI_MED
)) == 0) {
1035 bcopy(gbuf_rptr(mdata
), gbuf_rptr(m
), TOTAL_ATP_HDR_SIZE
);
1038 ddp
= (at_ddp_t
*)gbuf_rptr(mdata
);
1039 gbuf_wset(mdata
,DDP_X_HDR_SIZE
);
1040 atp
= (at_atp_t
*)gbuf_wptr(mdata
);
1041 gbuf_winc(mdata
,ATP_HDR_SIZE
);
1042 awp
= (asp_word_t
*)atp
->user_bytes
;
1043 NET_NET(ddp
->src_net
, ddp
->dst_net
);
1044 ddp
->src_node
= ddp
->dst_node
;
1045 NET_ASSIGN(ddp
->dst_net
, rem_addr
.net
);
1046 ddp
->dst_node
= rem_addr
.node
;
1047 ddp
->dst_socket
= rem_addr
.socket
;
1048 UAS_ASSIGN(ddp
->checksum
, 0);
1049 atpBDS
= (struct atpBDS
*)gbuf_wptr(mdata
);
1050 msize
= mx
? gbuf_msgsize(mx
) : 0;
1051 for (nbds
=0; (nbds
< ATP_TRESP_MAX
) && (msize
> 0); nbds
++) {
1052 len
= msize
< ATP_DATA_SIZE
? msize
: ATP_DATA_SIZE
;
1053 msize
-= ATP_DATA_SIZE
;
1054 *(long *)atpBDS
[nbds
].bdsUserData
= 0;
1055 UAL_ASSIGN(atpBDS
[nbds
].bdsBuffAddr
, 1);
1056 UAS_ASSIGN(atpBDS
[nbds
].bdsBuffSz
, len
);
1058 UAS_ASSIGN(atpBDS
[0].bdsDataSz
, nbds
);
1059 gbuf_winc(mdata
,atpBDSsize
);
1060 gbuf_cont(mdata
) = mx
;
1061 atp_send_rsp(gref
, mdata
, FALSE
);
1064 case ASPFUNC_OpenSess
:
1066 * ignore if server is not ready
1068 if ((scb
->dflag
!= 1) || (scb
->stat_msg
== 0))
1072 if (gbuf_cont(mdata
)) {
1073 gbuf_freem(gbuf_cont(mdata
));
1074 gbuf_cont(mdata
) = 0;
1076 gbuf_rdec(mdata
,TOTAL_ATP_HDR_SIZE
);
1077 gbuf_wset(mdata
,TOTAL_ATP_HDR_SIZE
);
1078 if (awp
->param2
!= ASP_Version
) {
1080 * bad version number, send the OpenSession response
1084 awp
->param2
= (unsigned short)ASPERR_BadVersNum
;
1085 dPrintf(D_M_ASP
, D_L_INFO
,
1087 ASPERR_BadVersNum
));
1089 NET_NET(ddp
->src_net
, ddp
->dst_net
);
1090 ddp
->src_node
= ddp
->dst_node
;
1091 NET_ASSIGN(ddp
->dst_net
, rem_addr
.net
);
1092 ddp
->dst_node
= rem_addr
.node
;
1093 ddp
->dst_socket
= rem_addr
.socket
;
1094 atp_send_rsp(gref
, mdata
, FALSE
);
1099 * queue the connection request
1101 ATDISABLE(s
, scb
->lock
);
1102 gbuf_next(mdata
) = 0;
1103 if ((m
= scb
->sess_ioc
) == 0) {
1104 scb
->sess_ioc
= mdata
;
1106 wakeup(&scb
->event
);
1108 atalk_notify_sel(gref
);
1110 while (gbuf_next(m
))
1112 gbuf_next(m
) = mdata
;
1114 ATENABLE(s
, scb
->lock
);
1115 dPrintf(D_M_ASP
, D_L_INFO
,
1116 (" : QUEUE connect request\n"));
1120 case ASPFUNC_Command
:
1122 if ( (scb
->sess_id
!= awp
->param1
)
1123 || (scb
->rcv_seq_num
!= awp
->param2
)
1124 || BAD_REMADDR(rem_addr
) ) {
1126 sprintf(era
,"%d.%d", scb
->rem_addr
.node
,scb
->rem_addr
.socket
);
1127 sprintf(ra
,"%d.%d", rem_addr
.node
,rem_addr
.socket
);
1128 dPrintf(D_M_ASP
, D_L_WARNING
,
1129 (" : DROP, id=%d,esn=%d,sn=%d,erem=%s,rem=%s\n",
1130 scb
->sess_id
,scb
->rcv_seq_num
,awp
->param2
,era
,ra
));
1131 gbuf_cont(mioc
) = 0;
1132 gbuf_rdec(mdata
,TOTAL_ATP_HDR_SIZE
);
1133 atp_drop_req(gref
, mdata
);
1136 scb
->reply_socket
= rem_addr
.socket
;
1137 if (awp
->func
== ASPFUNC_Write
)
1138 scb
->wrt_seq_num
= scb
->rcv_seq_num
;
1139 NEXT_SEQ_NUM(scb
->rcv_seq_num
);
1140 gbuf_set_type(mioc
, MSG_PROTO
);
1141 gbuf_wset(mioc
,sizeof(asp_command_ind_t
));
1142 command_ind
= (asp_command_ind_t
*)gbuf_rptr(mioc
);
1143 command_ind
->Primitive
= (int)awp
->func
;
1144 command_ind
->ReqRefNum
=
1145 *(unsigned short *)atp
->tid
;
1146 command_ind
->ReqType
= awp
->func
;
1148 mdata
= gbuf_strip(mdata
);
1149 gbuf_cont(mioc
) = mdata
;
1150 ATDISABLE(s
, scb
->lock
);
1151 if (scb
->req_flag
) {
1152 if ((mx
= scb
->req_msgq
) != 0) {
1153 while (gbuf_next(mx
))
1155 gbuf_next(mx
) = mioc
;
1157 scb
->req_msgq
= mioc
;
1158 ATENABLE(s
, scb
->lock
);
1161 ATENABLE(s
, scb
->lock
);
1162 asp_putnext(scb
->gref
, mioc
);
1166 case ASPFUNC_WriteContinue
:
1167 if ( (scb
->sess_id
!= awp
->param1
)
1168 || (scb
->snd_seq_num
!= awp
->param2
)
1169 || BAD_REMADDR(rem_addr
) ) {
1172 scb
->reply_socket
= rem_addr
.socket
;
1173 gbuf_set_type(mioc
, MSG_PROTO
);
1174 gbuf_wset(mioc
,sizeof(asp_command_ind_t
));
1175 command_ind
= (asp_command_ind_t
*)gbuf_rptr(mioc
);
1176 command_ind
->Primitive
= (int)awp
->func
;
1177 command_ind
->ReqRefNum
=
1178 *(unsigned short *)atp
->tid
;
1179 command_ind
->ReqType
= awp
->func
;
1181 mdata
= gbuf_strip(mdata
);
1182 gbuf_cont(mioc
) = mdata
;
1183 asp_putnext(scb
->gref
, mioc
);
1186 case ASPFUNC_Tickle
:
1187 if (scb
->stat_msg
) {
1188 sess_scb
= asp_scbQ
[awp
->param1
];
1189 if (sess_scb
&& sess_scb
->next_scb
)
1190 sess_scb
= asp_find_scb(
1191 sess_scb
->loc_addr
.socket
, &rem_addr
);
1193 if (sess_scb
->rem_addr
.node
)
1194 asp_untimout(asp_hangup
, sess_scb
);
1195 if (sess_scb
->rem_addr
.node
)
1196 asp_timout(asp_hangup
, sess_scb
, sess_scb
->session_timer
);
1199 dPrintf(D_M_ASP
, D_L_INFO
,
1200 (" : Tickle, %d -> %d, id=%d\n",
1201 ddp
->src_socket
,ddp
->dst_socket
,awp
->param1
));
1204 case ASPFUNC_CloseSess
:
1205 if ( (scb
->sess_id
!= awp
->param1
)
1206 || (scb
->state
== ASPSTATE_Close
)
1207 || (scb
->state
== ASPSTATE_WaitingForCloseSessRsp
)
1208 || (scb
->rem_addr
.net
!= rem_addr
.net
)
1209 || (scb
->rem_addr
.node
!= rem_addr
.node
) ) {
1210 dPrintf(D_M_ASP
, D_L_INFO
,
1211 (" : CLOSE retry, loc=%d, rem=%x.%x.%d\n",
1212 scb
->loc_addr
.socket
,
1215 scb
->rem_addr
.socket
));
1222 * build the CloseSess response to be sent to peer
1223 * when the session is closed by the user.
1225 if (gbuf_cont(mdata
)) {
1226 gbuf_freem(gbuf_cont(mdata
));
1227 gbuf_cont(mdata
) = 0;
1229 gbuf_rdec(mdata
,TOTAL_ATP_HDR_SIZE
);
1230 gbuf_wset(mdata
,TOTAL_ATP_HDR_SIZE
);
1231 NET_NET(ddp
->src_net
, ddp
->dst_net
);
1232 ddp
->src_node
= ddp
->dst_node
;
1233 NET_ASSIGN(ddp
->dst_net
, rem_addr
.net
);
1234 ddp
->dst_node
= rem_addr
.node
;
1235 ddp
->dst_socket
= rem_addr
.socket
;
1239 dPrintf(D_M_ASP
,D_L_INFO
,
1240 (" : CLOSE, loc=%d, rem=%x.%x.%d\n",
1241 scb
->loc_addr
.socket
,
1244 scb
->rem_addr
.socket
));
1246 gbuf_next(mdata
) = 0;
1247 ATDISABLE(s
, scb
->lock
);
1249 gbuf_freel(scb
->sess_ioc
);
1250 scb
->sess_ioc
= mdata
;
1251 scb
->state
= ASPSTATE_Close
;
1252 ATENABLE(s
, scb
->lock
);
1255 * notify upstream of the CloseSess from peer
1260 case ASPFUNC_Attention
:
1261 if ( (scb
->sess_id
!= awp
->param1
)
1262 || (scb
->rem_addr
.net
!= rem_addr
.net
)
1263 || (scb
->rem_addr
.node
!= rem_addr
.node
) ) {
1266 gbuf_set_type(mioc
, MSG_PROTO
);
1267 gbuf_wset(mioc
,sizeof(asp_command_ind_t
));
1268 command_ind
= (asp_command_ind_t
*)gbuf_rptr(mioc
);
1269 command_ind
->Primitive
= (int)awp
->func
;
1270 command_ind
->ReqRefNum
=
1271 *(unsigned short *)atp
->tid
;
1272 command_ind
->ReqType
= awp
->func
;
1273 scb
->attn_tid
= *(unsigned short *)atp
->tid
;
1275 gbuf_rdec(mdata
,2); /* attention code */
1277 mdata
= gbuf_strip(mdata
);
1278 gbuf_cont(mioc
) = mdata
;
1279 asp_putnext(scb
->gref
, mioc
);
1283 dPrintf(D_M_ASP
, D_L_WARNING
,
1284 (" : UNKNOWN func, func=%d\n",
1291 else if (iocbp
->ioc_cmd
== AT_ATP_REQUEST_COMPLETE
) {
1292 if (scb
->next_scb
) {
1294 * find the responsible scb
1296 scb
= (asp_scb_t
*)iocbp
->ioc_private
;
1297 if ((scb
== 0) || (scb
->magic_num
!= 222)) {
1298 dPrintf(D_M_ASP
, D_L_ERROR
,
1299 ("asp_ack_reply: CAN'T find scb 1\n"));
1304 dPrintf(D_M_ASP
, D_L_INFO
,
1305 ("asp_ack_reply: RSP, loc=%d, rem=%x.%x.%d, state=%s\n",
1306 scb
->loc_addr
.socket
,
1309 scb
->rem_addr
.socket
,
1310 aspStateStr(scb
->state
)));
1312 switch (scb
->state
) {
1313 case ASPSTATE_Close
:
1315 scb
->rem_addr
.node
= 0;
1317 ATDISABLE(s
, scb
->lock
);
1319 wakeup(&scb
->event
);
1321 atalk_notify_sel(gref
);
1322 ATENABLE(s
, scb
->lock
);
1325 case ASPSTATE_WaitingForGetStatusRsp
:
1327 scb
->state
= ASPSTATE_Idle
;
1328 mx
= gbuf_cont(mioc
);
1329 gbuf_cont(mioc
) = 0;
1330 mdata
= gbuf_cont(mx
);
1332 iocbp
->ioc_cmd
= ASPIOC_GetStatus
;
1333 iocbp
->ioc_count
= 0;
1334 iocbp
->ioc_rval
= mdata
? gbuf_msgsize(mdata
) : 0;
1336 atalk_putnext(gref
, mioc
);
1337 atalk_putnext(gref
, mdata
);
1340 case ASPSTATE_WaitingForOpenSessRsp
:
1342 scb
->state
= ASPSTATE_Idle
;
1343 mx
= gbuf_cont(mioc
);
1344 gbuf_cont(mioc
) = 0;
1345 if (gbuf_cont(mx
)) {
1346 gbuf_freem(gbuf_cont(mx
));
1349 iocbp
->ioc_cmd
= ASPIOC_OpenSession
;
1350 iocbp
->ioc_rval
= 0;
1351 iocbp
->ioc_count
= 0;
1352 atpBDS
= (struct atpBDS
*)gbuf_rptr(mx
);
1353 awp
= (asp_word_t
*)atpBDS
->bdsUserData
;
1356 asp_iocnak(gref
, mioc
, ECONNREFUSED
);
1358 scb
->rem_addr
.node
= scb
->rem_node
;
1359 scb
->rem_addr
.socket
= awp
->func
;
1360 /* bms: need to set the reply_socket for client side too.
1361 This makes ALO atten replies sent by the client work. */
1362 scb
->reply_socket
= scb
->rem_addr
.socket
;
1363 scb
->sess_id
= awp
->param1
;
1365 atalk_putnext(gref
, mioc
);
1366 asp_timout(asp_hangup
, scb
, scb
->session_timer
);
1367 asp_send_tickle(scb
);
1368 dPrintf(D_M_ASP
, D_L_INFO
,
1369 ("asp_ack_reply: CONNECT, loc=%d, rem=%x.%x.%d\n",
1370 scb
->loc_addr
.socket
,
1373 scb
->rem_addr
.socket
));
1377 case ASPSTATE_WaitingForCommandRsp
:
1378 case ASPSTATE_WaitingForWriteRsp
:
1379 case ASPSTATE_WaitingForWriteContinueRsp
:
1380 if (scb
->rem_addr
.node
)
1381 asp_untimout(asp_hangup
, scb
);
1382 NEXT_SEQ_NUM(scb
->snd_seq_num
);
1383 scb
->state
= ASPSTATE_Idle
;
1384 gbuf_set_type(mioc
, MSG_PROTO
);
1385 mx
= gbuf_cont(mioc
);
1386 mdata
= gbuf_cont(mx
);
1387 gbuf_cont(mioc
) = mdata
;
1388 atpBDS
= (struct atpBDS
*)gbuf_rptr(mx
);
1389 cmdreply_ind
= (asp_cmdreply_ind_t
*)gbuf_rptr(mioc
);
1390 cmdreply_ind
->Primitive
= ASPFUNC_CmdReply
;
1391 cmdreply_ind
->CmdResult
= *(int *)atpBDS
->bdsUserData
;
1392 gbuf_wset(mioc
,sizeof(asp_cmdreply_ind_t
));
1394 asp_putnext(scb
->gref
, mioc
);
1397 case ASPSTATE_WaitingForCloseSessRsp
:
1399 scb
->state
= ASPSTATE_Close
;
1400 scb
->rem_addr
.node
= 0;
1401 iocbp
->ioc_cmd
= ASPIOC_CloseSession
;
1402 iocbp
->ioc_rval
= 0;
1403 if (gbuf_cont(mioc
)) {
1404 gbuf_freem(gbuf_cont(mioc
));
1405 gbuf_cont(mioc
) = 0;
1407 atalk_putnext(scb
->gref
, mioc
);
1408 atp_cancel_req(scb
->gref
, (unsigned int)scb
->tickle_tid
);
1409 scb
->tickle_tid
= 0;
1413 dPrintf(D_M_ASP
, D_L_WARNING
,
1414 (" : UNKNOWN state, state=%s\n",
1415 aspStateStr(scb
->state
)));
1421 if (scb
->next_scb
) {
1423 * find the responsible scb
1425 scb
= (asp_scb_t
*)iocbp
->ioc_cr
;
1426 if ((scb
== 0) || (scb
->magic_num
!= 222)) {
1427 dPrintf(D_M_ASP
, D_L_ERROR
,
1428 ("asp_ack_reply: CAN'T find scb 2\n"));
1434 switch (scb
->state
) {
1435 case ASPSTATE_Close
:
1436 scb
->rem_addr
.node
= 0;
1445 if (scb
->rem_addr
.node
)
1446 asp_timout(asp_hangup
, scb
, scb
->session_timer
);
1447 } /* asp_ack_reply */
1453 asp_nak_reply(gref
, mioc
)
1454 register gref_t
*gref
;
1455 register gbuf_t
*mioc
;
1457 register asp_scb_t
*scb
;
1458 register ioc_t
*iocbp
;
1460 iocbp
= (ioc_t
*)gbuf_rptr(mioc
);
1462 if (iocbp
->ioc_cmd
== AT_ATP_ISSUE_REQUEST_TICKLE
) {
1464 * no tickle, close session
1466 scb
= (asp_scb_t
*)iocbp
->ioc_cr
;
1469 dPrintf(D_M_ASP
, D_L_WARNING
,
1470 ("tickle_nak: loc=%d, rem=%x.%x.%d, state=%s\n",
1471 scb
->loc_addr
.socket
,
1474 scb
->rem_addr
.socket
,
1475 aspStateStr(scb
->state
)));
1480 scb
= (asp_scb_t
*)gref
->info
;
1486 if (iocbp
->ioc_cmd
== AT_ATP_REQUEST_COMPLETE
) {
1487 if (scb
->next_scb
) {
1489 * find the responsible scb
1491 scb
= (asp_scb_t
*)iocbp
->ioc_private
;
1492 if ((scb
== 0) || (scb
->magic_num
!= 222)) {
1493 dPrintf(D_M_ASP
, D_L_ERROR
,
1494 ("asp_nak_reply: CAN'T find scb 1\n"));
1499 dPrintf(D_M_ASP
, D_L_WARNING
,
1500 ("asp_nak_reply: RSP, loc=%d, rem=%x.%x.%d, state=%s\n",
1501 scb
->loc_addr
.socket
,
1504 scb
->rem_addr
.socket
,
1505 aspStateStr(scb
->state
)));
1507 switch (scb
->state
) {
1508 case ASPSTATE_WaitingForGetStatusRsp
:
1509 iocbp
->ioc_cmd
= ASPIOC_GetStatus
;
1512 case ASPSTATE_WaitingForOpenSessRsp
:
1513 iocbp
->ioc_cmd
= ASPIOC_OpenSession
;
1516 case ASPSTATE_WaitingForCommandRsp
:
1517 case ASPSTATE_WaitingForWriteRsp
:
1518 case ASPSTATE_WaitingForWriteContinueRsp
:
1519 scb
->state
= ASPSTATE_Idle
;
1521 /* last remaining use of MSG_ERROR */
1522 gbuf_set_type(mioc
, MSG_ERROR
);
1523 *gbuf_rptr(mioc
) = (u_char
)EPROTO
;
1525 if (gbuf_cont(mioc
)) {
1526 gbuf_freem(gbuf_cont(mioc
));
1527 gbuf_cont(mioc
) = 0;
1530 asp_putnext(scb
->gref
, mioc
);
1533 case ASPSTATE_WaitingForCloseSessRsp
:
1534 scb
->state
= ASPSTATE_Close
;
1536 case ASPSTATE_Close
: /* new for PR-2296832 */
1537 scb
->rem_addr
.node
= 0;
1538 iocbp
->ioc_cmd
= ASPIOC_CloseSession
;
1539 iocbp
->ioc_rval
= 0;
1540 if (gbuf_cont(mioc
)) {
1541 gbuf_freem(gbuf_cont(mioc
));
1542 gbuf_cont(mioc
) = 0;
1544 gbuf_set_type(mioc
, MSG_IOCACK
);
1545 atalk_putnext(scb
->gref
, mioc
);
1552 scb
->state
= ASPSTATE_Idle
;
1553 atalk_putnext(gref
, mioc
);
1557 if (scb
->next_scb
) {
1559 * find the responsible scb
1561 scb
= (asp_scb_t
*)iocbp
->ioc_cr
;
1562 if ((scb
== 0) || (scb
->magic_num
!= 222)) {
1563 dPrintf(D_M_ASP
, D_L_ERROR
,
1564 ("asp_nak_reply: CAN'T find scb 2\n"));
1570 switch (scb
->state
) {
1571 case ASPSTATE_Close
:
1572 scb
->rem_addr
.node
= 0;
1578 } /* asp_nak_reply */
1581 * delete scb from the use list
1584 asp_dequeue_scb(scb
)
1589 ATDISABLE(s
, aspall_lock
);
1590 if (scb
== scb_used_list
) {
1591 if ((scb_used_list
= scb
->next_scb
) != 0)
1592 scb
->next_scb
->prev_scb
= 0;
1594 if ((scb
->prev_scb
->next_scb
= scb
->next_scb
) != 0)
1595 scb
->next_scb
->prev_scb
= scb
->prev_scb
;
1597 ATENABLE(s
, aspall_lock
);
1606 StaticProc asp_scb_t
*
1607 asp_find_scb(sock_num
, rem_addr
)
1608 unsigned char sock_num
;
1609 at_inet_t
*rem_addr
;
1613 asp_scb_t
*alt_scb
= 0;
1615 ATDISABLE(s
, aspall_lock
);
1616 for (scb
= asp_scbQ
[sock_num
]; scb
; scb
= scb
->next_scb
) {
1617 if ((scb
->rem_addr
.net
== rem_addr
->net
)
1618 && (scb
->rem_addr
.node
== rem_addr
->node
)) {
1619 if ((scb
->rem_addr
.socket
== rem_addr
->socket
)
1620 || (scb
->rem_socket
== rem_addr
->socket
))
1622 else if (alt_scb
== 0)
1627 if ((scb
== 0) && ((scb
= alt_scb
) == 0)) {
1628 dPrintf(D_M_ASP
, D_L_ERROR
,
1629 ("asp_find_scb: CAN'T find scb, loc=%d, rem=%x.%x.%d\n",
1635 ATENABLE(s
, aspall_lock
);
1644 asp_timout(func
, scb
, seconds
)
1646 register asp_scb_t
*scb
;
1651 register asp_scb_t
*curr_scb
, *prev_scb
;
1656 scb
->tmo_func
= func
;
1657 scb
->tmo_delta
= (seconds
>>SESS_TMO_RES
);
1658 scb
->tmo_cnt
= scb_tmo_cnt
;
1660 ATDISABLE(s
, asptmo_lock
);
1661 if (scb_tmo_list
== 0) {
1662 scb
->next_tmo
= scb
->prev_tmo
= 0;
1664 ATENABLE(s
, asptmo_lock
);
1669 curr_scb
= scb_tmo_list
;
1673 sum
+= curr_scb
->tmo_delta
;
1674 if (sum
> scb
->tmo_delta
) {
1675 sum
-= curr_scb
->tmo_delta
;
1676 scb
->tmo_delta
-= sum
;
1677 curr_scb
->tmo_delta
-= scb
->tmo_delta
;
1680 prev_scb
= curr_scb
;
1681 if ((curr_scb
= curr_scb
->next_tmo
) == 0) {
1682 scb
->tmo_delta
-= sum
;
1688 scb
->prev_tmo
= prev_scb
;
1689 if ((scb
->next_tmo
= prev_scb
->next_tmo
) != 0)
1690 prev_scb
->next_tmo
->prev_tmo
= scb
;
1691 prev_scb
->next_tmo
= scb
;
1694 scb
->next_tmo
= scb_tmo_list
;
1695 scb_tmo_list
->prev_tmo
= scb
;
1698 ATENABLE(s
, asptmo_lock
);
1705 asp_untimout(func
, scb
)
1707 register asp_scb_t
*scb
;
1711 if ((scb
->tmo_cnt
== scb_tmo_cnt
) || (scb
->tmo_func
== 0))
1714 ATDISABLE(s
, asptmo_lock
);
1715 if (scb_tmo_list
== scb
) {
1716 if ((scb_tmo_list
= scb
->next_tmo
) != 0) {
1717 scb_tmo_list
->prev_tmo
= 0;
1718 scb
->next_tmo
->tmo_delta
+= scb
->tmo_delta
;
1720 } else if (scb
->prev_tmo
) {
1721 if ((scb
->prev_tmo
->next_tmo
= scb
->next_tmo
) != 0) {
1722 scb
->next_tmo
->prev_tmo
= scb
->prev_tmo
;
1723 scb
->next_tmo
->tmo_delta
+= scb
->tmo_delta
;
1728 ATENABLE(s
, asptmo_lock
);
1741 * set the state to Close
1743 ATDISABLE(s
, scb
->lock
);
1744 scb
->state
= ASPSTATE_Close
;
1745 if (scb
->tickle_tid
) {
1746 atp_cancel_req(scb
->gref
, (unsigned int)scb
->tickle_tid
);
1747 scb
->tickle_tid
= 0;
1751 * notify upstream of the hangup
1753 if (scb
->rem_addr
.node
) {
1754 if (scb
->get_wait
) {
1755 wakeup(&scb
->event
);
1756 ATENABLE(s
, scb
->lock
);
1758 ATENABLE(s
, scb
->lock
);
1759 atalk_notify_sel(scb
->gref
);
1762 ATENABLE(s
, scb
->lock
);
1766 asp_iocack(gref
, mioc
)
1770 if (gbuf_cont(mioc
))
1771 ((ioc_t
*)gbuf_rptr(mioc
))->ioc_count
= gbuf_msgsize(gbuf_cont(mioc
));
1773 ((ioc_t
*)gbuf_rptr(mioc
))->ioc_count
= 0;
1775 gbuf_set_type(mioc
, MSG_IOCACK
);
1776 atalk_putnext(gref
, mioc
);
1780 asp_iocnak(gref
, mioc
, err
)
1785 ((ioc_t
*)gbuf_rptr(mioc
))->ioc_count
= 0;
1788 ((ioc_t
*)gbuf_rptr(mioc
))->ioc_error
= err
;
1789 ((ioc_t
*)gbuf_rptr(mioc
))->ioc_rval
= -1;
1790 if (gbuf_cont(mioc
)) {
1791 gbuf_freem(gbuf_cont(mioc
));
1792 gbuf_cont(mioc
) = 0;
1795 gbuf_set_type(mioc
, MSG_IOCNAK
);
1796 atalk_putnext(gref
, mioc
);
1800 * the alloc scb routine
1802 StaticProc asp_scb_t
*
1807 asp_scb_t
*scb
, *scb_array
;
1809 ATDISABLE(s
, aspall_lock
);
1810 if (scb_free_list
== 0) {
1811 if ((m
= gbuf_alloc(SCBS_PER_BLK
*sizeof(asp_scb_t
), PRI_MED
)) == 0)
1813 ATENABLE(s
, aspall_lock
);
1814 return (asp_scb_t
*)0;
1816 bzero((char *)gbuf_rptr(m
), SCBS_PER_BLK
*sizeof(asp_scb_t
));
1817 gbuf_cont(m
) = scb_resource_m
;
1819 scb_array
= (asp_scb_t
*)gbuf_rptr(m
);
1820 for (i
=0; i
< SCBS_PER_BLK
-1; i
++)
1821 scb_array
[i
].next_scb
= (asp_scb_t
*)&scb_array
[i
+1];
1822 scb_array
[i
].next_scb
= 0;
1823 scb_free_list
= (asp_scb_t
*)&scb_array
[0];
1826 scb
= scb_free_list
;
1827 scb_free_list
= scb
->next_scb
;
1828 ATENABLE(s
, aspall_lock
);
1829 ATLOCKINIT(scb
->lock
);
1830 ATLOCKINIT(scb
->delay_lock
);
1831 ATEVENTINIT(scb
->event
);
1832 ATEVENTINIT(scb
->delay_event
);
1838 * the free scb routine
1846 bzero((char *)scb
, sizeof(asp_scb_t
));
1847 ATDISABLE(s
, aspall_lock
);
1848 scb
->next_scb
= scb_free_list
;
1849 scb_free_list
= scb
;
1850 ATENABLE(s
, aspall_lock
);
1854 * routine to pass up receive data
1857 asp_putnext(gref
, mproto
)
1865 scb
= (asp_scb_t
*)gref
->info
;
1868 * queue the message.
1870 ATDISABLE(s
, scb
->lock
);
1871 gbuf_next(mproto
) = 0;
1872 if ((m
= scb
->sess_ioc
) == 0)
1873 scb
->sess_ioc
= mproto
;
1875 while (gbuf_next(m
))
1877 gbuf_next(m
) = mproto
;
1880 if (scb
->rcv_cnt
>= MAX_RCV_CNT
)
1883 if (scb
->get_wait
) {
1884 wakeup(&scb
->event
);
1885 ATENABLE(s
, scb
->lock
);
1886 } else if (mproto
== scb
->sess_ioc
) {
1887 ATENABLE(s
, scb
->lock
);
1888 atalk_notify_sel(gref
);
1890 ATENABLE(s
, scb
->lock
);
1894 * The following two routines are direct entries from system
1895 * calls to allow fast sending and recving of ASP data.
1898 /* in ASPputmsg we expect:
1904 ASPFUNC_WriteContinue
1906 bms: Make this callable from the kernel.
1907 If mreq != NULL, then must be called from kernel space and the following apply:
1908 1) *mreq is data to be sent already in mbuf chains.
1909 2) datptr->len = size of data
1912 int ASPputmsg(gref_t
*gref
, strbuf_t
*ctlptr
, strbuf_t
*datptr
, gbuf_t
*mreq
, int flags
, int *errp
)
1914 int s
, i
, err
, len
, offset
, remain
, size
, copy_len
;
1915 gbuf_t
*mioc
, *mdata
, *mx
, *m0
;
1920 int nbds
, result
, msize
, Primitive
;
1921 unsigned char *wptr
;
1922 struct atp_set_default
*sd
;
1925 struct atpBDS
*atpBDS
;
1927 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 * copy in the data content into multiple mbuf clusters if
1992 * required. ATP now expects reply data to be placed in
1993 * standard clusters, not the large external clusters that
1994 * were used previously.
1997 /* set offset for use by some commands */
1998 offset
= (Primitive
== ASPFUNC_CmdReply
) ? 0 : aspCMDsize
;
2001 /* The data from the in-kernel call for use by AFP is passed
2002 * in as one large external cluster. This needs to be copied
2003 * to a chain of standard clusters.
2005 remain
= gbuf_len(mreq
);
2006 dataptr
= mtod(mreq
, caddr_t
);
2008 /* copyin from user space */
2009 remain
= datbuf
.len
;
2010 dataptr
= (caddr_t
)datbuf
.buf
;
2013 /* allocate first buffer */
2014 if (!(mdata
= gbuf_alloc_wait((remain
+ offset
> MCLBYTES
? MCLBYTES
: remain
+ offset
), TRUE
))) {
2015 /* error return should not be possible */
2020 gbuf_wset(mdata
, 0); /* init length to zero */
2021 gbuf_cont(mioc
) = mdata
;
2024 if (remain
+ offset
> MCLBYTES
)
2025 copy_len
= MCLBYTES
- offset
;
2030 bcopy (dataptr
, (gbuf_rptr(mdata
) + offset
), copy_len
);
2031 else if ((err
= copyin(dataptr
, (caddr_t
)(gbuf_rptr(mdata
) + offset
), copy_len
)) != 0) {
2035 gbuf_wset(mdata
, (copy_len
+ offset
));
2036 size
+= copy_len
+ offset
;
2037 dataptr
+= copy_len
;
2040 /* allocate the next mbuf */
2041 if ((gbuf_cont(mdata
) = m_get((M_WAIT
), MSG_DATA
)) == 0) {
2046 mdata
= gbuf_cont(mdata
);
2047 MCLGET(mdata
, M_WAIT
);
2048 if (!(mdata
->m_flags
& M_EXT
)) {
2055 mdata
= gbuf_cont(mioc
); /* code further on down expects this to b e set */
2056 mdata
->m_pkthdr
.len
= size
; /* set packet hdr len */
2061 switch (Primitive
) {
2063 case ASPFUNC_Command
:
2065 case ASPFUNC_WriteContinue
:
2066 case ASPFUNC_Attention
:
2068 * build the command/write/write_continue request
2070 wptr
= gbuf_rptr(mdata
);
2071 atpBDS
= (struct atpBDS
*)wptr
;
2073 for (i
=0; i
< ATP_TRESP_MAX
; i
++) {
2074 *(unsigned long *)atpBDS
[i
].bdsBuffAddr
= 1;
2075 *(unsigned short *)atpBDS
[i
].bdsBuffSz
= ATP_DATA_SIZE
;
2077 sd
= (struct atp_set_default
*)wptr
;
2078 wptr
+= sizeof(struct atp_set_default
);
2079 sd
->def_retries
= (scb
->cmd_retry
.retries
== -1) ?
2080 ATP_INFINITE_RETRIES
: scb
->cmd_retry
.retries
;
2081 sd
->def_rate
= scb
->cmd_retry
.interval
*TICKS_PER_SEC
;
2082 sd
->def_BDSlen
= atpBDSsize
;
2083 ddp
= (at_ddp_t
*)wptr
;
2084 NET_ASSIGN(ddp
->src_net
, scb
->loc_addr
.net
);
2085 ddp
->src_node
= scb
->loc_addr
.node
;
2086 NET_ASSIGN(ddp
->dst_net
, scb
->rem_addr
.net
);
2087 ddp
->dst_node
= scb
->rem_addr
.node
;
2088 ddp
->dst_socket
= scb
->rem_addr
.socket
;
2089 UAS_ASSIGN(ddp
->checksum
, 0);
2090 atp
= ATP_ATP_HDR(wptr
);
2091 wptr
+= TOTAL_ATP_HDR_SIZE
;
2095 awp
= (asp_word_t
*)atp
->user_bytes
;
2096 awp
->func
= (unsigned char)Primitive
;
2097 awp
->param1
= scb
->sess_id
;
2098 awp
->param2
= scb
->snd_seq_num
;
2099 iocbp
->ioc_private
= (void *)scb
;
2100 iocbp
->ioc_count
= gbuf_len(mdata
);
2101 iocbp
->ioc_rval
= 0;
2102 iocbp
->ioc_cmd
= AT_ATP_ISSUE_REQUEST_DEF
;
2105 * send the command/write/write_continue/attention request
2107 ATDISABLE(s
, scb
->lock
);
2108 switch (awp
->func
) {
2109 case ASPFUNC_Command
:
2110 scb
->state
= ASPSTATE_WaitingForCommandRsp
;
2113 scb
->state
= ASPSTATE_WaitingForWriteRsp
;
2115 case ASPFUNC_WriteContinue
:
2116 scb
->state
= ASPSTATE_WaitingForWriteContinueRsp
;
2117 awp
->param2
= scb
->wrt_seq_num
;
2119 case ASPFUNC_Attention
:
2120 scb
->state
= ASPSTATE_WaitingForCommandRsp
;
2125 awp
->param2
= *(unsigned short *)gbuf_wptr(mdata
);
2128 ATENABLE(s
, scb
->lock
);
2129 dPrintf(D_M_ASP
,D_L_INFO
,
2130 ("ASPputmsg: %s, loc=%d, rem=%x.%x.%d\n",
2131 (awp
->func
== ASPFUNC_Command
? "CommandReq" :
2132 awp
->func
== ASPFUNC_Write
? "WriteReq" :
2133 awp
->func
== ASPFUNC_WriteContinue
? "WriteContinue" :
2134 "AttentionReq"),scb
->loc_addr
.socket
,
2135 NET_VALUE(ddp
->dst_net
),ddp
->dst_node
,ddp
->dst_socket
));
2136 atp_send_req(gref
, mioc
);
2139 case ASPFUNC_CmdReply
:
2141 ATDISABLE(s
, scb
->lock
);
2142 if (scb
->req_msgq
) {
2144 scb
->req_msgq
= gbuf_next(mx
);
2146 ATENABLE(s
, scb
->lock
);
2147 asp_putnext(scb
->gref
, mx
);
2150 ATENABLE(s
, scb
->lock
);
2152 result
= primitives
->CmdReplyReq
.CmdResult
;
2153 tid
= primitives
->CmdReplyReq
.ReqRefNum
;
2155 /* Re-use the original mioc mbuf to send the response. */
2156 gbuf_rinc(mioc
,sizeof(void *));
2158 ddp
= (at_ddp_t
*)gbuf_wptr(mioc
);
2159 gbuf_winc(mioc
,DDP_X_HDR_SIZE
);
2160 atp
= (at_atp_t
*)gbuf_wptr(mioc
);
2161 gbuf_winc(mioc
,ATP_HDR_SIZE
);
2162 NET_ASSIGN(ddp
->src_net
, scb
->loc_addr
.net
);
2163 ddp
->src_node
= scb
->loc_addr
.node
;
2164 NET_ASSIGN(ddp
->dst_net
, scb
->rem_addr
.net
);
2165 ddp
->dst_node
= scb
->rem_addr
.node
;
2166 ddp
->dst_socket
= scb
->reply_socket
;
2167 ddp
->type
= DDP_ATP
;
2168 UAS_ASSIGN(ddp
->checksum
, 0);
2169 UAS_ASSIGN(atp
->tid
, tid
);
2170 if (scb
->attn_flag
&& (tid
== scb
->attn_tid
)) {
2178 /* setup the atpBDS struct - only the length field is used,
2179 * except for the first one which contains the bds count in
2182 atpBDS
= (struct atpBDS
*)gbuf_wptr(mioc
);
2183 msize
= mdata
? gbuf_msgsize(mdata
) : 0;
2184 for (nbds
=0; (nbds
< ATP_TRESP_MAX
) && (msize
> 0); nbds
++) {
2185 len
= msize
< ATP_DATA_SIZE
? msize
: ATP_DATA_SIZE
;
2186 msize
-= ATP_DATA_SIZE
;
2187 *(long *)atpBDS
[nbds
].bdsUserData
= 0;
2188 UAL_ASSIGN(atpBDS
[nbds
].bdsBuffAddr
, 1);
2189 UAS_ASSIGN(atpBDS
[nbds
].bdsBuffSz
, len
);
2191 UAS_ASSIGN(atpBDS
[0].bdsDataSz
, nbds
);
2192 *(long *)atpBDS
[0].bdsUserData
= (long)result
;
2193 *(long *)atp
->user_bytes
= (long)result
;
2194 gbuf_winc(mioc
,atpBDSsize
);
2195 dPrintf(D_M_ASP
, D_L_INFO
,
2196 ("ASPputmsg: ATP CmdReplyReq, loc=%d, state=%s, msgsize = %d, result = %d, tid = %d\n",
2197 scb
->loc_addr
.socket
, aspStateStr(scb
->state
),
2198 (mdata
? gbuf_msgsize(mdata
) : 0), result
, tid
));
2199 atp_send_rsp(gref
, mioc
, TRUE
);
2203 /* Not an expected ASPFUNC */
2213 /* bms: make this callable from kernel. reply date is passed back as a mbuf chain in *mreply */
2214 int ASPgetmsg(gref_t
*gref
, strbuf_t
*ctlptr
, strbuf_t
*datptr
, gbuf_t
**mreply
, int *flags
, int *errp
)
2216 int err
, s
, len
, sum
, rval
;
2217 gbuf_t
*mproto
, *mdata
;
2221 unsigned char get_wait
;
2223 if ((scb
= (asp_scb_t
*)gref
->info
) == 0) {
2224 dPrintf(D_M_ASP
, D_L_ERROR
,
2225 ("ASPgetmsg: stale handle=0x%x, pid=%d\n",
2226 (u_int
) gref
, gref
->pid
));
2232 ATDISABLE(s
, scb
->lock
);
2233 if (scb
->state
== ASPSTATE_Close
) {
2234 ATENABLE(s
, scb
->lock
);
2241 while ((mproto
= scb
->sess_ioc
) == 0) {
2243 err
= tsleep(&scb
->event
, PSOCK
| PCATCH
, "aspgetmsg", 0);
2246 ATENABLE(s
, scb
->lock
);
2250 if (scb
->state
== ASPSTATE_Close
) {
2252 ATENABLE(s
, scb
->lock
);
2256 get_wait
= scb
->get_wait
;
2258 if ((ctlptr
== 0) && (datptr
== 0)) {
2259 ATENABLE(s
, scb
->lock
);
2262 scb
->sess_ioc
= gbuf_next(mproto
);
2263 mdata
= gbuf_cont(mproto
);
2264 ATENABLE(s
, scb
->lock
);
2266 /* last remaining use of MSG_ERROR */
2267 if (gbuf_type(mproto
) == MSG_ERROR
) {
2268 err
= (int)gbuf_rptr(mproto
)[0];
2273 * copy in the control and data info
2275 if (mreply
!= NULL
) {
2276 /* called from kernel space */
2277 bcopy (ctlptr
, &ctlbuf
, sizeof(ctlbuf
));
2278 bcopy (datptr
, &datbuf
, sizeof(datbuf
));
2280 /* called from user space */
2281 if ((err
= copyin((caddr_t
)ctlptr
,
2282 (caddr_t
)&ctlbuf
, sizeof(ctlbuf
))) != 0)
2284 if ((err
= copyin((caddr_t
)datptr
,
2285 (caddr_t
)&datbuf
, sizeof(datbuf
))) != 0)
2288 if ((datbuf
.maxlen
< 0) || (datbuf
.maxlen
< gbuf_msgsize(mdata
))) {
2289 ATDISABLE(s
, scb
->lock
);
2290 gbuf_next(mproto
) = scb
->sess_ioc
;
2291 scb
->sess_ioc
= mproto
;
2292 ATENABLE(s
, scb
->lock
);
2296 if (get_wait
== 0) {
2298 * this is a hack to support the select() call.
2299 * we're not supposed to dequeue messages in the Streams
2300 * head's read queue this way; but there is no better way.
2302 ATDISABLE(s
, scb
->lock
);
2303 if (scb
->sess_ioc
== 0) {
2304 ATENABLE(s
, scb
->lock
);
2306 ATENABLE(s
, scb
->lock
);
2307 atalk_notify_sel(gref
);
2312 * copy out the control content and info
2314 ctlbuf
.len
= gbuf_len(mproto
);
2316 if (mreply
!= NULL
) {
2317 /* called from kernel space */
2318 bcopy (gbuf_rptr(mproto
), ctlbuf
.buf
, ctlbuf
.len
);
2319 bcopy (&ctlbuf
, ctlptr
, sizeof(ctlbuf
));
2321 /* called from user space */
2322 if ((err
= copyout((caddr_t
)gbuf_rptr(mproto
),
2323 (caddr_t
)ctlbuf
.buf
, ctlbuf
.len
)) != 0)
2325 if ((err
= copyout((caddr_t
)&ctlbuf
,
2326 (caddr_t
)ctlptr
, sizeof(ctlbuf
))) != 0)
2331 * copy out the data content and info
2333 for (rval
= 0, sum
= 0; mdata
&& (rval
== 0); mdata
= gbuf_cont(mdata
))
2335 len
= gbuf_len(mdata
);
2337 if ((len
+ sum
) > datbuf
.maxlen
) {
2338 len
= datbuf
.maxlen
- sum
;
2342 if (mreply
== NULL
) {
2343 /* called from user space */
2344 if ((err
= copyout((caddr_t
)gbuf_rptr(mdata
), (caddr_t
)&datbuf
.buf
[sum
], len
)) != 0)
2351 if (mreply
!= NULL
) {
2352 /* called from kernel space */
2353 bcopy (&datbuf
, datptr
, sizeof(datbuf
));
2355 /* called from user space */
2356 if ((err
= copyout((caddr_t
)&datbuf
, (caddr_t
)datptr
, sizeof(datbuf
))) != 0)
2360 if (mreply
!= NULL
) {
2361 /* called from kernel space */
2362 /* return the reply data in mbufs, so dont free them.
2363 Just free the proto info */
2364 mdata
= gbuf_cont(mproto
);
2366 gbuf_cont(mproto
) = NULL
;
2369 /* called from user space */
2373 ATDISABLE(s
, scb
->lock
);
2380 ATENABLE(s
, scb
->lock
);
2384 ATDISABLE(s
, scb
->lock
);
2385 gbuf_next(mproto
) = scb
->sess_ioc
;
2386 scb
->sess_ioc
= mproto
;
2387 ATENABLE(s
, scb
->lock
);