2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
26 * Copyright (c) 1995 Apple Computer, Inc.
29 * Created February 20, 1995 by Tuyen Nguyen
30 * Modified for MP, 1996 by Tuyen Nguyen
31 * Modified, March 17, 1997 by Tuyen Nguyen for MacOSX.
34 #include <sys/errno.h>
35 #include <sys/types.h>
36 #include <sys/param.h>
37 #include <machine/spl.h>
38 #include <sys/systm.h>
39 #include <sys/kernel.h>
41 #include <sys/filedesc.h>
42 #include <sys/fcntl.h>
44 #include <sys/ioctl.h>
45 #include <sys/malloc.h>
46 #include <sys/socket.h>
47 #include <sys/socketvar.h>
51 #include <netat/appletalk.h>
52 #include <netat/sysglue.h>
53 #include <netat/at_pcb.h>
54 #include <netat/atp.h>
55 #include <netat/ddp.h>
56 #include <netat/asp.h>
57 #include <netat/at_var.h>
58 #include <netat/debug.h>
61 #define CHK_LOOP(str) { \
62 if (loop_cnt++ > 100) { \
68 #define atpBDSsize (sizeof(struct atpBDS)*ATP_TRESP_MAX)
69 #define aspCMDsize (atpBDSsize+sizeof(struct atp_set_default)+TOTAL_ATP_HDR_SIZE)
70 #define SCBS_PER_BLK 16
71 #define TICKS_PER_SEC HZ
72 #define SESS_TMO_RES 2
73 #define DEF_SESS_TMO 120
74 #define NEXT_SEQ_NUM(x) (x = (x == 65535) ? 0 : (x + 1))
76 #define BAD_REMADDR(addr) \
77 ( (*(long *)&scb->rem_addr != *(long *)&addr) \
78 && ((scb->rem_addr.net != addr.net) \
79 || (scb->rem_addr.node != addr.node)) )
87 void asp_clock_funnel(void *);
91 StaticProc asp_scb_t
*asp_find_scb();
92 StaticProc asp_scb_t
*asp_scb_alloc();
94 StaticProc
void asp_putnext();
95 StaticProc
void asp_iocack();
96 StaticProc
void asp_iocnak();
97 StaticProc
void asp_dequeue_scb();
98 StaticProc
void asp_scb_free();
99 StaticProc
void asp_timout();
100 StaticProc
void asp_untimout();
101 StaticProc
void asp_hangup();
102 StaticProc
void asp_send_tickle();
103 StaticProc
void asp_send_tickle_funnel(void *);
104 StaticProc
void asp_accept();
105 StaticProc
int asp_send_req();
107 extern at_ifaddr_t
*ifID_home
;
108 extern int atp_pidM
[];
109 extern gref_t
*atp_inputQ
[];
110 gbuf_t
*scb_resource_m
= 0;
111 unsigned char asp_inpC
[256];
112 asp_scb_t
*asp_scbQ
[256];
114 static at_retry_t asp_def_retry
= {2, -1, 1};
115 static unsigned char scb_tmo_cnt
;
116 asp_scb_t
*scb_used_list
;
117 static asp_scb_t
*scb_tmo_list
;
118 asp_scb_t
*scb_free_list
;
119 atlock_t aspall_lock
, asptmo_lock
;
125 return (((asp_scb_t
*)gref
->info
)->sess_ioc
? 1 : 0);
135 bzero(asp_inpC
, sizeof(asp_inpC
));
136 bzero(asp_scbQ
, sizeof(asp_scbQ
));
140 * the open routine allocates a state structure
149 * if no asp structure available, return failure
151 if ((scb
= asp_scb_alloc()) == 0)
155 * initialize the gref data structure
157 gref
->info
= (void *)scb
;
158 gref
->readable
= asp_readable
;
161 * initialize the scb data structure
164 scb
->magic_num
= 222;
165 scb
->state
= ASPSTATE_Idle
;
166 scb
->pid
= gref
->pid
;
168 scb
->session_timer
= DEF_SESS_TMO
;
169 scb
->cmd_retry
= asp_def_retry
;
170 ATDISABLE(s
, aspall_lock
);
171 if ((scb
->next_scb
= scb_used_list
) != 0)
172 scb
->next_scb
->prev_scb
= scb
;
174 ATENABLE(s
, aspall_lock
);
179 dPrintf(D_M_ASP
, D_L_INFO
, ("asp_open: pid=%d\n", scb
->pid
));
184 * the close routine frees all the data structures
191 unsigned char sock_num
;
192 asp_scb_t
*scb
, *new_scb
;
195 scb
= (asp_scb_t
*)gref
->info
;
196 dPrintf(D_M_ASP
, D_L_INFO
, ("asp_close: loc=%d\n",
197 scb
->loc_addr
.socket
));
199 if (scb
->pid
&& scb
->sess_ioc
&& (scb
->dflag
!= 1)) {
201 * send the CloseSess response to peer
203 if (gbuf_type(scb
->sess_ioc
) != MSG_PROTO
) {
204 ATDISABLE(s
, scb
->lock
);
206 scb
->sess_ioc
= gbuf_next(m
);
207 ATENABLE(s
, scb
->lock
);
208 atp_send_rsp(scb
->gref
, m
, TRUE
);
212 if (scb
->atp_state
) {
213 sock_num
= scb
->loc_addr
.socket
;
214 ATDISABLE(s
, aspall_lock
);
215 if ((scb
->dflag
!= 1) && scb
->stat_msg
) {
216 untimeout(atp_retry_req
, scb
->stat_msg
);
217 gbuf_freem(scb
->stat_msg
);
220 if (asp_scbQ
[sock_num
]->next_scb
== 0) {
221 asp_scbQ
[sock_num
] = 0;
222 asp_inpC
[sock_num
] = 0;
223 ATENABLE(s
, aspall_lock
);
224 dPrintf(D_M_ASP
, D_L_INFO
,
225 (" : atp_close(), loc=%d\n", scb
->loc_addr
.socket
));
228 asp_inpC
[sock_num
]--;
229 if (scb
== asp_scbQ
[sock_num
]) {
230 new_scb
= scb
->next_scb
;
231 new_scb
->prev_scb
= 0;
232 asp_scbQ
[sock_num
] = new_scb
;
233 new_scb
->atp_state
->atp_gref
= new_scb
->gref
;
234 new_scb
->atp_state
->pid
= new_scb
->pid
;
235 atp_inputQ
[sock_num
] = new_scb
->gref
;
237 if ((scb
->prev_scb
->next_scb
= scb
->next_scb
) != 0)
238 scb
->next_scb
->prev_scb
= scb
->prev_scb
;
241 ATENABLE(s
, aspall_lock
);
244 asp_dequeue_scb(scb
);
247 * free all allocated blocks if any
249 ATDISABLE(s
, scb
->lock
);
251 gbuf_freem(scb
->stat_msg
);
255 gbuf_freel(scb
->sess_ioc
);
259 gbuf_freel(scb
->req_msgq
);
263 scb
->rem_addr
.node
= 0;
264 ATENABLE(s
, scb
->lock
);
270 asp_untimout(asp_hangup
, scb
);
271 untimeout(asp_send_tickle_funnel
, (void *)scb
); /* added for 2225395 */
274 * free the asp session control block
276 scb
->state
= ASPSTATE_Close
;
281 static char *aspStateStr(state
)
284 return ((state
==ASPSTATE_Close
)? "Close":
285 (state
==ASPSTATE_Idle
)? "Idle":
286 (state
==ASPSTATE_WaitingForGetStatusRsp
)? "GetStatusRsp":
287 (state
==ASPSTATE_WaitingForOpenSessRsp
)? "OpenSessRsp":
288 (state
==ASPSTATE_WaitingForCommandRsp
)? "CmdRsp":
289 (state
==ASPSTATE_WaitingForWriteContinue
)? "WriteCont":
290 (state
==ASPSTATE_WaitingForWriteRsp
)? "WriteRsp":
291 (state
==ASPSTATE_WaitingForWriteContinueRsp
)? "WriteContRsp":
292 (state
==ASPSTATE_WaitingForCloseSessRsp
)? "CloseSessRsp":
296 static char *aspCmdStr(aspCmd
)
299 return ((aspCmd
==ASPFUNC_CloseSess
)? "CloseSess":
300 (aspCmd
==ASPFUNC_Command
)? "Command":
301 (aspCmd
==ASPFUNC_GetStatus
)? "GetStatus":
302 (aspCmd
==ASPFUNC_OpenSess
)? "OpenSess":
303 (aspCmd
==ASPFUNC_Tickle
)? "Tickle":
304 (aspCmd
==ASPFUNC_Write
)? "Write":
305 (aspCmd
==ASPFUNC_WriteContinue
)? "WriteContinue":
306 (aspCmd
==ASPFUNC_Attention
)? "Attention":
307 (aspCmd
==ASPFUNC_CmdReply
)? "CmdReply": "unknown");
310 static char *aspIOCStr(aspIOC
)
314 (aspIOC
==ASPIOC_ClientBind
)? "ClientBind":
315 (aspIOC
==ASPIOC_CloseSession
)? "CloseSession":
316 (aspIOC
==ASPIOC_GetLocEntity
)? "GetLocEntity":
317 (aspIOC
==ASPIOC_GetRemEntity
)? "GetRemEntity":
318 (aspIOC
==ASPIOC_GetSession
)? "GetSession":
319 (aspIOC
==ASPIOC_GetStatus
)? "GetStatus":
320 (aspIOC
==ASPIOC_ListenerBind
)? "ListenerBind":
321 (aspIOC
==ASPIOC_OpenSession
)? "OpenSession":
322 (aspIOC
==ASPIOC_StatusBlock
)? "StatusBlock":
323 (aspIOC
==ASPIOC_SetPid
)? "SetPid":
324 (aspIOC
==ASPIOC_GetSessId
)? "GetSessId":
325 (aspIOC
==ASPIOC_EnableSelect
)? "EnableSelect":
326 (aspIOC
==ASPIOC_Look
)? "Look":
333 static char mbuf_str
[100];
338 "dat = %d, prot = %d, ioc = %d, err = %d, hu = %d, ack = %d, nak = %d, ctl = %d",
340 "dat = %d, prot = %d, ioc = %d, ctl = %d",
341 mbstat
.m_mtypes
[MSG_DATA
], mbstat
.m_mtypes
[MSG_PROTO
], mbstat
.m_mtypes
[MSG_IOCTL
],
343 mbstat.m_mtypes[MSG_ERROR], mbstat.m_mtypes[MSG_HANGUP], mbstat.m_mtypes[MSG_IOCACK],
344 mbstat.m_mtypes[MSG_IOCNAK],
346 mbstat
.m_mtypes
[MSG_CTL
]);
347 return(&mbuf_str
[0]);
350 void trace_beg(str
, m
)
355 gbuf_t
*mdata
, *mchain
;
358 for (i
= 0, j
= 0, mdata
= m
, mchain
= m
; mdata
; i
++) {
359 mdata
= gbuf_cont(mdata
);
360 if (!mdata
&& mchain
) {
361 mdata
= gbuf_next(mchain
);
366 dPrintf(D_M_ASP
, D_L_TRACE
,
367 ("%s: %s, m# = %d, c# = %d\n", str
, mbuf_totals(), i
, j
));
373 dPrintf(D_M_ASP
, D_L_TRACE
,
374 (" %s: %s\n", str
, mbuf_totals()));
376 #endif /* AT_MBUF_TRACE */
381 int asp_wput(gref
, m
)
386 unsigned char sockSav
, sock_num
;
387 gbuf_t
*mioc
, *mdata
;
389 asp_scb_t
*scb
, *server_scb
, *curr_scb
;
392 union asp_primitives
*primitives
;
393 asp_status_cmd_t
*status_cmd
;
394 asp_open_cmd_t
*open_cmd
;
397 scb
= (asp_scb_t
*)gref
->info
;
398 if (scb
->dflag
== 0) {
403 if (gbuf_type(m
) != MSG_IOCTL
) {
404 dPrintf(D_M_ASP
, D_L_WARNING
,
405 ("asp_wput: UNKNOWN message, type=%d\n",
412 iocbp
= (ioc_t
*)gbuf_rptr(mioc
);
414 dPrintf(D_M_ASP_LOW
, D_L_INFO
,
415 ("asp_wput: %s, loc=%d, state=%s\n",
416 aspIOCStr(iocbp
->ioc_cmd
), scb
->loc_addr
.socket
,
417 aspStateStr(scb
->state
)));
419 switch (iocbp
->ioc_cmd
) {
420 case ASPIOC_CloseSession
:
421 if ((scb
->state
== ASPSTATE_Close
) || (scb
->rem_addr
.node
== 0))
426 aw
.func
= ASPFUNC_CloseSess
;
427 aw
.param1
= scb
->sess_id
;
429 iocbp
->ioc_private
= (void *)scb
;
430 scb
->ioc_wait
= (unsigned char)(iocbp
->ioc_cmd
& 0xff);
431 iocbp
->ioc_cmd
= AT_ATP_ISSUE_REQUEST
;
432 asp_send_req(gref
, mioc
, &scb
->rem_addr
, &Retry
, &aw
,
433 0, ASPSTATE_WaitingForCloseSessRsp
, 0x01);
436 case ASPIOC_ClientBind
:
438 * open an ATP channel
440 if ((err
= atp_open(gref
, 0)) != 0) {
441 asp_iocnak(gref
, mioc
, err
);
444 scb
->atp_state
= (atp_state_t
*)gref
->info
;
445 scb
->atp_state
->pid
= scb
->pid
;
447 * bind to any available socket
450 sockSav
= scb
->dflag
;
451 if ((sock_num
= (at_socket
)atp_bind(gref
, 0, &sockSav
)) == 0) {
452 scb
->atp_state
= (atp_state_t
*)0;
454 gref
->info
= (void *)scb
;
455 asp_iocnak(gref
, mioc
, EINVAL
);
458 gref
->info
= (void *)scb
;
459 asp_dequeue_scb(scb
);
460 scb
->atp_state
->dflag
= scb
->dflag
;
461 scb
->loc_addr
.socket
= sock_num
;
462 asp_scbQ
[sock_num
] = scb
;
463 asp_inpC
[sock_num
]++;
464 atp_pidM
[sock_num
] = 0;
467 case ASPIOC_ListenerBind
:
469 * open an ATP channel
471 if ((err
= atp_open(gref
, 0)) != 0) {
472 asp_iocnak(gref
, mioc
, err
);
475 scb
->atp_state
= (atp_state_t
*)gref
->info
;
476 scb
->atp_state
->pid
= scb
->pid
;
478 * bind to any available socket
480 if ((sock_num
= (at_socket
)atp_bind(gref
, 0, 0)) == 0) {
481 scb
->atp_state
= (atp_state_t
*)0;
483 gref
->info
= (void *)scb
;
484 asp_iocnak(gref
, mioc
, EINVAL
);
487 gref
->info
= (void *)scb
;
488 asp_dequeue_scb(scb
);
489 scb
->atp_state
->dflag
= scb
->dflag
;
490 scb
->loc_addr
.socket
= sock_num
;
491 asp_scbQ
[sock_num
] = scb
;
492 asp_inpC
[sock_num
]++;
494 *(at_inet_t
*)gbuf_rptr(gbuf_cont(mioc
)) = scb
->loc_addr
;
497 case ASPIOC_GetLocEntity
:
498 if ((gbuf_cont(mioc
) == 0) || (scb
->atp_state
== 0)) {
499 asp_iocnak(gref
, mioc
, EPROTO
);
502 *(at_inet_t
*)gbuf_rptr(gbuf_cont(mioc
)) = scb
->loc_addr
;
505 case ASPIOC_GetRemEntity
:
506 if ((gbuf_cont(mioc
) == 0) || (scb
->atp_state
== 0)) {
507 asp_iocnak(gref
, mioc
, EPROTO
);
510 *(at_inet_t
*)gbuf_rptr(gbuf_cont(mioc
)) = scb
->rem_addr
;
513 case ASPIOC_GetSession
:
514 if ((mdata
= gbuf_cont(mioc
)) == 0) {
515 asp_iocnak(gref
, mioc
, EPROTO
);
518 addr
= (at_inet_t
*)gbuf_rptr(mdata
);
519 scb
->tickle_interval
= (unsigned short)addr
->node
;
520 scb
->session_timer
= addr
->net
;
521 server_scb
= asp_scbQ
[addr
->socket
];
522 /*### LD 10/28/97: changed to make sure we're not accessing a null server_scb */
523 if (server_scb
== 0) {
524 asp_iocnak(gref
, mioc
, EPROTO
);
527 if (server_scb
->sess_ioc
== 0) {
528 asp_iocnak(gref
, mioc
, EPROTO
);
533 * open an ATP channel
535 if ((err
= atp_open(gref
, 0)) != 0) {
536 gref
->info
= (void *)scb
;
537 asp_iocnak(gref
, mioc
, err
);
540 scb
->atp_state
= (atp_state_t
*)gref
->info
;
541 scb
->atp_state
->pid
= scb
->pid
;
543 * bind to any available socket
546 sockSav
= scb
->dflag
;
547 if ((sock_num
= (at_socket
)atp_bind(gref
, 0, &sockSav
)) == 0) {
549 asp_dequeue_scb(scb
);
550 ATDISABLE(s
, aspall_lock
);
552 scb
->loc_addr
.socket
= sock_num
;
553 for (curr_scb
= asp_scbQ
[sock_num
];
554 curr_scb
->next_scb
; curr_scb
= curr_scb
->next_scb
) ;
555 scb
->prev_scb
= curr_scb
;
556 curr_scb
->next_scb
= scb
;
557 scb
->atp_state
= curr_scb
->atp_state
;
558 ATENABLE(s
, aspall_lock
);
560 asp_dequeue_scb(scb
);
561 ATDISABLE(s
, aspall_lock
);
562 scb
->loc_addr
.socket
= sock_num
;
563 asp_scbQ
[sock_num
] = scb
;
564 scb
->atp_state
->dflag
= scb
->dflag
;
565 ATENABLE(s
, aspall_lock
);
567 gref
->info
= (void *)scb
;
568 asp_inpC
[sock_num
]++;
570 asp_accept(server_scb
, scb
, mdata
);
573 case ASPIOC_GetStatus
:
574 if ((mdata
= gbuf_cont(mioc
)) == 0) {
575 asp_iocnak(gref
, mioc
, EINVAL
);
579 status_cmd
= (asp_status_cmd_t
*)gbuf_rptr(mdata
);
580 aw
.func
= ASPFUNC_GetStatus
;
583 scb
->ioc_wait
= (unsigned char)(iocbp
->ioc_cmd
& 0xff);
584 iocbp
->ioc_cmd
= AT_ATP_ISSUE_REQUEST_DEF
;
585 /* bms: make sure this is an ALO request */
586 asp_send_req(gref
, mioc
, &status_cmd
->SLSEntityIdentifier
,
587 &status_cmd
->Retry
, &aw
, 0, ASPSTATE_WaitingForGetStatusRsp
, 0xff);
591 case ASPIOC_OpenSession
:
592 if ((mdata
= gbuf_cont(mioc
)) == 0) {
593 asp_iocnak(gref
, mioc
, EINVAL
);
597 open_cmd
= (asp_open_cmd_t
*)gbuf_rptr(mdata
);
598 scb
->svc_addr
= open_cmd
->SLSEntityIdentifier
;
599 scb
->rem_addr
= scb
->svc_addr
;
600 scb
->rem_node
= scb
->rem_addr
.node
;
601 scb
->rem_addr
.node
= 0;
602 scb
->tickle_interval
= open_cmd
->TickleInterval
;
603 scb
->session_timer
= open_cmd
->SessionTimer
;
604 aw
.func
= ASPFUNC_OpenSess
;
605 aw
.param1
= scb
->loc_addr
.socket
;
606 aw
.param2
= ASP_Version
;
607 scb
->ioc_wait
= (unsigned char)(iocbp
->ioc_cmd
& 0xff);
608 iocbp
->ioc_cmd
= AT_ATP_ISSUE_REQUEST_DEF
;
609 asp_send_req(gref
, mioc
, &open_cmd
->SLSEntityIdentifier
,
610 &open_cmd
->Retry
, &aw
, 1, ASPSTATE_WaitingForOpenSessRsp
, 0x01);
614 case ASPIOC_StatusBlock
:
616 * save the server status block
619 gbuf_freem(scb
->stat_msg
);
620 scb
->stat_msg
= gbuf_cont(mioc
);
624 /* *** Does scb->pid get used in a packet header,
625 and if so is it in ASP, or in ATP?
626 If not, do we need this call for anything?
627 (cap does currently use it in _ANS code.)
630 if (gbuf_cont(mioc
) == 0) {
631 asp_iocnak(gref
, mioc
, EINVAL
);
634 scb
->pid
= *(int *)gbuf_rptr(gbuf_cont(mioc
));
637 case ASPIOC_GetSessId
:
638 if (gbuf_cont(mioc
) == 0) {
639 asp_iocnak(gref
, mioc
, EINVAL
);
642 *(gref_t
**)gbuf_rptr(gbuf_cont(mioc
)) = gref
;
646 if (gbuf_cont(mioc
) == 0) {
647 asp_iocnak(gref
, mioc
, EINVAL
);
651 primitives
= (union asp_primitives
*)gbuf_rptr(scb
->sess_ioc
);
652 if (primitives
->Primitive
== ASPFUNC_CmdReply
)
653 *(int *)gbuf_rptr(gbuf_cont(mioc
)) = 0;
655 *(int *)gbuf_rptr(gbuf_cont(mioc
)) = 1;
657 *(int *)gbuf_rptr(gbuf_cont(mioc
)) = -1;
660 case DDP_IOC_GET_CFG
:
662 struct atp_state
*atp
= (struct atp_state
*)gref
->info
;
664 atp
= (struct atp_state
*)atp
->atp_msgq
;
666 if (gbuf_cont(mioc
) == 0) {
667 asp_iocnak(gref
, mioc
, EINVAL
);
670 /* *** borrowed from ddp_proto.c to handle DDP_IOC_GET_CFG
672 scb
->state
= ASPSTATE_Idle
;
674 /* *** was ddp_get_cfg() *** */
676 (ddp_addr_t
*)gbuf_rptr(gbuf_cont(mioc
));
677 cfgp
->inet
.net
= ifID_home
->ifThisNode
.s_net
;
678 cfgp
->inet
.node
= ifID_home
->ifThisNode
.s_node
;
679 cfgp
->inet
.socket
= atp
->atp_socket_no
;
680 cfgp
->ddptype
= DDP_ATP
;
682 gbuf_wset(gbuf_cont(mioc
), sizeof(at_inet_t
));
687 asp_iocnak(gref
, mioc
, EINVAL
);
691 asp_iocack(gref
, mioc
);
696 * send request routine
699 asp_send_req(gref
, mioc
, dest
, retry
, awp
, xo
, state
, bitmap
)
707 unsigned char bitmap
;
712 struct atp_set_default
*sd
;
715 struct atpBDS
*atpBDS
;
716 asp_scb_t
*scb
= (asp_scb_t
*)gref
->info
;
719 * allocate an ATP buffer for the request
721 if ((gbuf_cont(mioc
) = gbuf_alloc(aspCMDsize
, PRI_MED
)) == 0) {
722 if (awp
->func
== ASPFUNC_Tickle
)
725 asp_iocnak(gref
, mioc
, ENOBUFS
);
726 dPrintf(D_M_ASP
, D_L_WARNING
,
727 ("asp_send_req: ENOBUFS, loc=%d\n", scb
->loc_addr
.socket
));
731 mdata
= gbuf_cont(mioc
);
732 iocbp
= (ioc_t
*)gbuf_rptr(mioc
);
737 atpBDS
= (struct atpBDS
*)gbuf_rptr(mdata
);
738 gbuf_wset(mdata
,atpBDSsize
);
739 for (i
=0; i
< ATP_TRESP_MAX
; i
++) {
740 *(unsigned long *)atpBDS
[i
].bdsBuffAddr
= 1;
741 *(unsigned short *)atpBDS
[i
].bdsBuffSz
= ATP_DATA_SIZE
;
743 sd
= (struct atp_set_default
*)gbuf_wptr(mdata
);
744 gbuf_winc(mdata
,sizeof(struct atp_set_default
));
745 sd
->def_retries
= (retry
->retries
== -1) ?
746 ATP_INFINITE_RETRIES
: retry
->retries
;
747 sd
->def_rate
= retry
->interval
*TICKS_PER_SEC
;
748 sd
->def_BDSlen
= atpBDSsize
;
749 ddp
= (at_ddp_t
*)gbuf_wptr(mdata
);
750 NET_ASSIGN(ddp
->src_net
, scb
->loc_addr
.net
);
751 ddp
->src_node
= scb
->loc_addr
.node
;
752 NET_ASSIGN(ddp
->dst_net
, dest
->net
);
753 ddp
->dst_node
= dest
->node
;
754 ddp
->dst_socket
= dest
->socket
;
755 UAS_ASSIGN(ddp
->checksum
, 0);
756 atp
= ATP_ATP_HDR(gbuf_wptr(mdata
));
759 atp
->bitmap
= bitmap
;
760 gbuf_winc(mdata
,TOTAL_ATP_HDR_SIZE
);
761 *(asp_word_t
*)atp
->user_bytes
= *awp
;
762 iocbp
->ioc_count
= gbuf_len(mdata
);
769 dPrintf(D_M_ASP
, D_L_INFO
,
770 ("asp_send_req: %s, loc=%d, rem= %d, len=%d, state=%s\n",
771 aspCmdStr(awp
->func
),
772 scb
->loc_addr
.socket
, ddp
->dst_socket
, iocbp
->ioc_count
,
773 aspStateStr(scb
->state
)));
775 atp_send_req(gref
, mioc
);
780 * send tickle routine - funnelled version
783 asp_send_tickle_funnel(scb
)
786 thread_funnel_set(network_flock
, TRUE
);
787 asp_send_tickle((asp_scb_t
*)scb
);
788 thread_funnel_set(network_flock
, FALSE
);
793 * send tickle routine
806 * make sure the connection is still there
808 if (scb
->rem_addr
.node
== 0) {
812 if ((mioc
= gbuf_alloc(sizeof(ioc_t
), PRI_HI
)) == 0) {
813 dPrintf(D_M_ASP
, D_L_WARNING
,
814 ("asp_send_tickle: ENOBUFS 0, loc=%d, rem=%d\n",
815 scb
->loc_addr
.socket
,scb
->rem_addr
.socket
));
816 timeout(asp_send_tickle_funnel
, (void *)scb
, 10);
819 gbuf_wset(mioc
,sizeof(ioc_t
));
820 gbuf_set_type(mioc
, MSG_IOCTL
);
822 dest
= scb
->svc_addr
.node
?
823 (at_inet_t
*)&scb
->svc_addr
: (at_inet_t
*)&scb
->rem_addr
;
824 retry
.interval
= scb
->tickle_interval
;
827 aw
.func
= ASPFUNC_Tickle
;
828 aw
.param1
= scb
->sess_id
;
830 ((ioc_t
*)gbuf_rptr(mioc
))->ioc_cr
= (void *)scb
;
831 ((ioc_t
*)gbuf_rptr(mioc
))->ioc_cmd
= AT_ATP_ISSUE_REQUEST_TICKLE
;
833 if (asp_send_req(scb
->gref
, mioc
, dest
, &retry
, &aw
, 0, scb
->state
, 0)) {
834 dPrintf(D_M_ASP
, D_L_WARNING
,
835 ("asp_send_tickle: ENOBUFS 1, loc=%d, rem=%d\n",
836 scb
->loc_addr
.socket
,scb
->rem_addr
.socket
));
838 timeout(asp_send_tickle_funnel
, (void *)scb
, 10);
844 * accept connection routine
847 asp_accept(scb
, sess_scb
, m
)
859 mdata
= scb
->sess_ioc
;
860 ddp
= (at_ddp_t
*)gbuf_rptr(mdata
);
861 atp
= (at_atp_t
*)(gbuf_rptr(mdata
) + DDP_X_HDR_SIZE
);
862 rem_addr
.net
= NET_VALUE(ddp
->src_net
);
863 rem_addr
.node
= ddp
->src_node
;
864 rem_addr
.socket
= ddp
->src_socket
;
865 awp
= (asp_word_t
*)atp
->user_bytes
;
867 sess_scb
->loc_addr
.net
= NET_VALUE(ddp
->dst_net
);
868 sess_scb
->loc_addr
.node
= ddp
->dst_node
;
869 NET_ASSIGN(ddp
->src_net
, sess_scb
->loc_addr
.net
);
870 ddp
->src_node
= sess_scb
->loc_addr
.node
;
871 NET_ASSIGN(ddp
->dst_net
, rem_addr
.net
);
872 ddp
->dst_node
= rem_addr
.node
;
873 ddp
->dst_socket
= rem_addr
.socket
;
875 sess_scb
->sess_id
= sess_scb
->loc_addr
.socket
;
876 sess_scb
->rem_socket
= rem_addr
.socket
;
877 sess_scb
->rem_addr
= rem_addr
;
878 sess_scb
->rem_addr
.socket
= awp
->param1
;
879 sess_scb
->reply_socket
= sess_scb
->rem_addr
.socket
;
880 awp
->func
= sess_scb
->loc_addr
.socket
;
881 awp
->param1
= sess_scb
->sess_id
;
884 ATDISABLE(s
, scb
->lock
);
885 scb
->sess_ioc
= gbuf_next(mdata
);
886 ATENABLE(s
, scb
->lock
);
887 gbuf_next(mdata
) = 0;
888 asp_timout(asp_hangup
, sess_scb
, sess_scb
->session_timer
);
889 atp_send_rsp(scb
->gref
, mdata
, TRUE
);
890 asp_send_tickle(sess_scb
);
891 dPrintf(D_M_ASP
, D_L_INFO
,
892 ("asp_accept: ACCEPT connect request, loc=%d, rem=%x.%x.%d\n",
893 sess_scb
->loc_addr
.socket
,
894 sess_scb
->rem_addr
.net
,
895 sess_scb
->rem_addr
.node
,sess_scb
->rem_addr
.socket
));
899 * timer routine - funneled version
901 void asp_clock_funnel(arg
)
904 thread_funnel_set(network_flock
, TRUE
);
906 thread_funnel_set(network_flock
, FALSE
);
919 ATDISABLE(s
, asptmo_lock
);
921 scb_tmo_list
->tmo_delta
--;
922 while (((scb
= scb_tmo_list
) != 0) && (scb_tmo_list
->tmo_delta
== 0)) {
923 if ((scb_tmo_list
= scb
->next_tmo
) != 0)
924 scb_tmo_list
->prev_tmo
= 0;
925 if ((tmo_func
= scb
->tmo_func
) != 0) {
927 ATENABLE(s
, asptmo_lock
);
929 ATDISABLE(s
, asptmo_lock
);
932 ATENABLE(s
, asptmo_lock
);
934 if (++scb_tmo_cnt
== 0) scb_tmo_cnt
++;
935 timeout(asp_clock_funnel
, (void *)arg
, (1<<SESS_TMO_RES
)*TICKS_PER_SEC
);
943 asp_ack_reply(gref
, mioc
)
944 register gref_t
*gref
;
945 register gbuf_t
*mioc
;
948 int len
, msize
, nbds
;
949 register gbuf_t
*mdata
, *m
, *mx
;
950 struct atpBDS
*atpBDS
;
953 register asp_scb_t
*scb
, *sess_scb
;
954 register ioc_t
*iocbp
;
955 register asp_word_t
*awp
;
956 register asp_command_ind_t
*command_ind
;
957 register asp_cmdreply_ind_t
*cmdreply_ind
;
960 iocbp
= (ioc_t
*)gbuf_rptr(mioc
);
962 if (iocbp
->ioc_cmd
== AT_ATP_ISSUE_REQUEST_TICKLE
) {
964 * ignore the ack for the tickle request
966 scb
= (asp_scb_t
*)iocbp
->ioc_cr
;
967 scb
->tickle_tid
= (unsigned short)iocbp
->ioc_rval
;
972 scb
= (asp_scb_t
*)gref
->info
;
978 if (iocbp
->ioc_cmd
== AT_ATP_GET_POLL
) {
980 * if no data, just drop the request
982 if ((mdata
= gbuf_cont(mioc
)) == 0) {
987 gbuf_set_type(mioc
, MSG_IOCTL
);
988 ddp
= (at_ddp_t
*)gbuf_rptr(mdata
);
989 gbuf_rinc(mdata
,DDP_X_HDR_SIZE
);
990 atp
= (at_atp_t
*)gbuf_rptr(mdata
);
991 gbuf_rinc(mdata
,ATP_HDR_SIZE
);
992 rem_addr
.net
= NET_VALUE(ddp
->src_net
);
993 rem_addr
.node
= ddp
->src_node
;
994 rem_addr
.socket
= ddp
->src_socket
;
995 awp
= (asp_word_t
*)atp
->user_bytes
;
999 * find the responsible scb
1001 if ((scb
= asp_find_scb(scb
->loc_addr
.socket
, &rem_addr
)) == 0) {
1006 dPrintf(D_M_ASP
, D_L_INFO
,
1007 ("asp_ack_reply: %s, loc=%d, rem=%x.%x.%d\n",
1008 aspCmdStr(awp
->func
),scb
->loc_addr
.socket
,
1009 NET_VALUE(ddp
->src_net
) ,ddp
->src_node
,ddp
->src_socket
));
1011 if (scb
->rem_addr
.node
)
1012 asp_untimout(asp_hangup
, scb
);
1014 switch (awp
->func
) {
1015 case ASPFUNC_GetStatus
:
1017 * ignore if this is not a server socket
1020 if ((scb
->dflag
!= 1) || (scb
->stat_msg
1021 && ((mx
= gbuf_dupb(scb
->stat_msg
)) == 0)))
1026 * send the status block
1028 if (gbuf_cont(mdata
)) {
1029 gbuf_freem(gbuf_cont(mdata
));
1030 gbuf_cont(mdata
) = 0;
1032 gbuf_rdec(mdata
,TOTAL_ATP_HDR_SIZE
);
1033 if ((m
= gbuf_alloc( (TOTAL_ATP_HDR_SIZE
+atpBDSsize
), PRI_MED
)) == 0) {
1038 bcopy(gbuf_rptr(mdata
), gbuf_rptr(m
), TOTAL_ATP_HDR_SIZE
);
1041 ddp
= (at_ddp_t
*)gbuf_rptr(mdata
);
1042 gbuf_wset(mdata
,DDP_X_HDR_SIZE
);
1043 atp
= (at_atp_t
*)gbuf_wptr(mdata
);
1044 gbuf_winc(mdata
,ATP_HDR_SIZE
);
1045 awp
= (asp_word_t
*)atp
->user_bytes
;
1046 NET_NET(ddp
->src_net
, ddp
->dst_net
);
1047 ddp
->src_node
= ddp
->dst_node
;
1048 NET_ASSIGN(ddp
->dst_net
, rem_addr
.net
);
1049 ddp
->dst_node
= rem_addr
.node
;
1050 ddp
->dst_socket
= rem_addr
.socket
;
1051 UAS_ASSIGN(ddp
->checksum
, 0);
1052 atpBDS
= (struct atpBDS
*)gbuf_wptr(mdata
);
1053 msize
= mx
? gbuf_msgsize(mx
) : 0;
1054 for (nbds
=0; (nbds
< ATP_TRESP_MAX
) && (msize
> 0); nbds
++) {
1055 len
= msize
< ATP_DATA_SIZE
? msize
: ATP_DATA_SIZE
;
1056 msize
-= ATP_DATA_SIZE
;
1057 *(long *)atpBDS
[nbds
].bdsUserData
= 0;
1058 UAL_ASSIGN(atpBDS
[nbds
].bdsBuffAddr
, 1);
1059 UAS_ASSIGN(atpBDS
[nbds
].bdsBuffSz
, len
);
1061 UAS_ASSIGN(atpBDS
[0].bdsDataSz
, nbds
);
1062 gbuf_winc(mdata
,atpBDSsize
);
1063 gbuf_cont(mdata
) = mx
;
1064 atp_send_rsp(gref
, mdata
, FALSE
);
1067 case ASPFUNC_OpenSess
:
1069 * ignore if server is not ready
1071 if ((scb
->dflag
!= 1) || (scb
->stat_msg
== 0))
1075 if (gbuf_cont(mdata
)) {
1076 gbuf_freem(gbuf_cont(mdata
));
1077 gbuf_cont(mdata
) = 0;
1079 gbuf_rdec(mdata
,TOTAL_ATP_HDR_SIZE
);
1080 gbuf_wset(mdata
,TOTAL_ATP_HDR_SIZE
);
1081 if (awp
->param2
!= ASP_Version
) {
1083 * bad version number, send the OpenSession response
1087 awp
->param2
= (unsigned short)ASPERR_BadVersNum
;
1088 dPrintf(D_M_ASP
, D_L_INFO
,
1090 ASPERR_BadVersNum
));
1092 NET_NET(ddp
->src_net
, ddp
->dst_net
);
1093 ddp
->src_node
= ddp
->dst_node
;
1094 NET_ASSIGN(ddp
->dst_net
, rem_addr
.net
);
1095 ddp
->dst_node
= rem_addr
.node
;
1096 ddp
->dst_socket
= rem_addr
.socket
;
1097 atp_send_rsp(gref
, mdata
, FALSE
);
1102 * queue the connection request
1104 ATDISABLE(s
, scb
->lock
);
1105 gbuf_next(mdata
) = 0;
1106 if ((m
= scb
->sess_ioc
) == 0) {
1107 scb
->sess_ioc
= mdata
;
1109 wakeup(&scb
->event
);
1111 atalk_notify_sel(gref
);
1113 while (gbuf_next(m
))
1115 gbuf_next(m
) = mdata
;
1117 ATENABLE(s
, scb
->lock
);
1118 dPrintf(D_M_ASP
, D_L_INFO
,
1119 (" : QUEUE connect request\n"));
1123 case ASPFUNC_Command
:
1125 if ( (scb
->sess_id
!= awp
->param1
)
1126 || (scb
->rcv_seq_num
!= awp
->param2
)
1127 || BAD_REMADDR(rem_addr
) ) {
1129 sprintf(era
,"%d.%d", scb
->rem_addr
.node
,scb
->rem_addr
.socket
);
1130 sprintf(ra
,"%d.%d", rem_addr
.node
,rem_addr
.socket
);
1131 dPrintf(D_M_ASP
, D_L_WARNING
,
1132 (" : DROP, id=%d,esn=%d,sn=%d,erem=%s,rem=%s\n",
1133 scb
->sess_id
,scb
->rcv_seq_num
,awp
->param2
,era
,ra
));
1134 gbuf_cont(mioc
) = 0;
1135 gbuf_rdec(mdata
,TOTAL_ATP_HDR_SIZE
);
1136 atp_drop_req(gref
, mdata
);
1139 scb
->reply_socket
= rem_addr
.socket
;
1140 if (awp
->func
== ASPFUNC_Write
)
1141 scb
->wrt_seq_num
= scb
->rcv_seq_num
;
1142 NEXT_SEQ_NUM(scb
->rcv_seq_num
);
1143 gbuf_set_type(mioc
, MSG_PROTO
);
1144 gbuf_wset(mioc
,sizeof(asp_command_ind_t
));
1145 command_ind
= (asp_command_ind_t
*)gbuf_rptr(mioc
);
1146 command_ind
->Primitive
= (int)awp
->func
;
1147 command_ind
->ReqRefNum
=
1148 *(unsigned short *)atp
->tid
;
1149 command_ind
->ReqType
= awp
->func
;
1151 mdata
= gbuf_strip(mdata
);
1152 gbuf_cont(mioc
) = mdata
;
1153 ATDISABLE(s
, scb
->lock
);
1154 if (scb
->req_flag
) {
1155 if ((mx
= scb
->req_msgq
) != 0) {
1156 while (gbuf_next(mx
))
1158 gbuf_next(mx
) = mioc
;
1160 scb
->req_msgq
= mioc
;
1161 ATENABLE(s
, scb
->lock
);
1164 ATENABLE(s
, scb
->lock
);
1165 asp_putnext(scb
->gref
, mioc
);
1169 case ASPFUNC_WriteContinue
:
1170 if ( (scb
->sess_id
!= awp
->param1
)
1171 || (scb
->snd_seq_num
!= awp
->param2
)
1172 || BAD_REMADDR(rem_addr
) ) {
1175 scb
->reply_socket
= rem_addr
.socket
;
1176 gbuf_set_type(mioc
, MSG_PROTO
);
1177 gbuf_wset(mioc
,sizeof(asp_command_ind_t
));
1178 command_ind
= (asp_command_ind_t
*)gbuf_rptr(mioc
);
1179 command_ind
->Primitive
= (int)awp
->func
;
1180 command_ind
->ReqRefNum
=
1181 *(unsigned short *)atp
->tid
;
1182 command_ind
->ReqType
= awp
->func
;
1184 mdata
= gbuf_strip(mdata
);
1185 gbuf_cont(mioc
) = mdata
;
1186 asp_putnext(scb
->gref
, mioc
);
1189 case ASPFUNC_Tickle
:
1190 if (scb
->stat_msg
) {
1191 sess_scb
= asp_scbQ
[awp
->param1
];
1192 if (sess_scb
&& sess_scb
->next_scb
)
1193 sess_scb
= asp_find_scb(
1194 sess_scb
->loc_addr
.socket
, &rem_addr
);
1196 if (sess_scb
->rem_addr
.node
)
1197 asp_untimout(asp_hangup
, sess_scb
);
1198 if (sess_scb
->rem_addr
.node
)
1199 asp_timout(asp_hangup
, sess_scb
, sess_scb
->session_timer
);
1202 dPrintf(D_M_ASP
, D_L_INFO
,
1203 (" : Tickle, %d -> %d, id=%d\n",
1204 ddp
->src_socket
,ddp
->dst_socket
,awp
->param1
));
1207 case ASPFUNC_CloseSess
:
1208 if ( (scb
->sess_id
!= awp
->param1
)
1209 || (scb
->state
== ASPSTATE_Close
)
1210 || (scb
->state
== ASPSTATE_WaitingForCloseSessRsp
)
1211 || (scb
->rem_addr
.net
!= rem_addr
.net
)
1212 || (scb
->rem_addr
.node
!= rem_addr
.node
) ) {
1213 dPrintf(D_M_ASP
, D_L_INFO
,
1214 (" : CLOSE retry, loc=%d, rem=%x.%x.%d\n",
1215 scb
->loc_addr
.socket
,
1218 scb
->rem_addr
.socket
));
1225 * build the CloseSess response to be sent to peer
1226 * when the session is closed by the user.
1228 if (gbuf_cont(mdata
)) {
1229 gbuf_freem(gbuf_cont(mdata
));
1230 gbuf_cont(mdata
) = 0;
1232 gbuf_rdec(mdata
,TOTAL_ATP_HDR_SIZE
);
1233 gbuf_wset(mdata
,TOTAL_ATP_HDR_SIZE
);
1234 NET_NET(ddp
->src_net
, ddp
->dst_net
);
1235 ddp
->src_node
= ddp
->dst_node
;
1236 NET_ASSIGN(ddp
->dst_net
, rem_addr
.net
);
1237 ddp
->dst_node
= rem_addr
.node
;
1238 ddp
->dst_socket
= rem_addr
.socket
;
1242 dPrintf(D_M_ASP
,D_L_INFO
,
1243 (" : CLOSE, loc=%d, rem=%x.%x.%d\n",
1244 scb
->loc_addr
.socket
,
1247 scb
->rem_addr
.socket
));
1249 gbuf_next(mdata
) = 0;
1250 ATDISABLE(s
, scb
->lock
);
1252 gbuf_freel(scb
->sess_ioc
);
1253 scb
->sess_ioc
= mdata
;
1254 scb
->state
= ASPSTATE_Close
;
1255 ATENABLE(s
, scb
->lock
);
1258 * notify upstream of the CloseSess from peer
1263 case ASPFUNC_Attention
:
1264 if ( (scb
->sess_id
!= awp
->param1
)
1265 || (scb
->rem_addr
.net
!= rem_addr
.net
)
1266 || (scb
->rem_addr
.node
!= rem_addr
.node
) ) {
1269 gbuf_set_type(mioc
, MSG_PROTO
);
1270 gbuf_wset(mioc
,sizeof(asp_command_ind_t
));
1271 command_ind
= (asp_command_ind_t
*)gbuf_rptr(mioc
);
1272 command_ind
->Primitive
= (int)awp
->func
;
1273 command_ind
->ReqRefNum
=
1274 *(unsigned short *)atp
->tid
;
1275 command_ind
->ReqType
= awp
->func
;
1276 scb
->attn_tid
= *(unsigned short *)atp
->tid
;
1278 gbuf_rdec(mdata
,2); /* attention code */
1280 mdata
= gbuf_strip(mdata
);
1281 gbuf_cont(mioc
) = mdata
;
1282 asp_putnext(scb
->gref
, mioc
);
1286 dPrintf(D_M_ASP
, D_L_WARNING
,
1287 (" : UNKNOWN func, func=%d\n",
1294 else if (iocbp
->ioc_cmd
== AT_ATP_REQUEST_COMPLETE
) {
1295 if (scb
->next_scb
) {
1297 * find the responsible scb
1299 scb
= (asp_scb_t
*)iocbp
->ioc_private
;
1300 if ((scb
== 0) || (scb
->magic_num
!= 222)) {
1301 dPrintf(D_M_ASP
, D_L_ERROR
,
1302 ("asp_ack_reply: CAN'T find scb 1\n"));
1307 dPrintf(D_M_ASP
, D_L_INFO
,
1308 ("asp_ack_reply: RSP, loc=%d, rem=%x.%x.%d, state=%s\n",
1309 scb
->loc_addr
.socket
,
1312 scb
->rem_addr
.socket
,
1313 aspStateStr(scb
->state
)));
1315 switch (scb
->state
) {
1316 case ASPSTATE_Close
:
1318 scb
->rem_addr
.node
= 0;
1320 ATDISABLE(s
, scb
->lock
);
1322 wakeup(&scb
->event
);
1324 atalk_notify_sel(gref
);
1325 ATENABLE(s
, scb
->lock
);
1328 case ASPSTATE_WaitingForGetStatusRsp
:
1330 scb
->state
= ASPSTATE_Idle
;
1331 mx
= gbuf_cont(mioc
);
1332 gbuf_cont(mioc
) = 0;
1333 mdata
= gbuf_cont(mx
);
1335 iocbp
->ioc_cmd
= ASPIOC_GetStatus
;
1336 iocbp
->ioc_count
= 0;
1337 iocbp
->ioc_rval
= mdata
? gbuf_msgsize(mdata
) : 0;
1339 atalk_putnext(gref
, mioc
);
1340 atalk_putnext(gref
, mdata
);
1343 case ASPSTATE_WaitingForOpenSessRsp
:
1345 scb
->state
= ASPSTATE_Idle
;
1346 mx
= gbuf_cont(mioc
);
1347 gbuf_cont(mioc
) = 0;
1348 if (gbuf_cont(mx
)) {
1349 gbuf_freem(gbuf_cont(mx
));
1352 iocbp
->ioc_cmd
= ASPIOC_OpenSession
;
1353 iocbp
->ioc_rval
= 0;
1354 iocbp
->ioc_count
= 0;
1355 atpBDS
= (struct atpBDS
*)gbuf_rptr(mx
);
1356 awp
= (asp_word_t
*)atpBDS
->bdsUserData
;
1359 asp_iocnak(gref
, mioc
, ECONNREFUSED
);
1361 scb
->rem_addr
.node
= scb
->rem_node
;
1362 scb
->rem_addr
.socket
= awp
->func
;
1363 /* bms: need to set the reply_socket for client side too.
1364 This makes ALO atten replies sent by the client work. */
1365 scb
->reply_socket
= scb
->rem_addr
.socket
;
1366 scb
->sess_id
= awp
->param1
;
1368 atalk_putnext(gref
, mioc
);
1369 asp_timout(asp_hangup
, scb
, scb
->session_timer
);
1370 asp_send_tickle(scb
);
1371 dPrintf(D_M_ASP
, D_L_INFO
,
1372 ("asp_ack_reply: CONNECT, loc=%d, rem=%x.%x.%d\n",
1373 scb
->loc_addr
.socket
,
1376 scb
->rem_addr
.socket
));
1380 case ASPSTATE_WaitingForCommandRsp
:
1381 case ASPSTATE_WaitingForWriteRsp
:
1382 case ASPSTATE_WaitingForWriteContinueRsp
:
1383 if (scb
->rem_addr
.node
)
1384 asp_untimout(asp_hangup
, scb
);
1385 NEXT_SEQ_NUM(scb
->snd_seq_num
);
1386 scb
->state
= ASPSTATE_Idle
;
1387 gbuf_set_type(mioc
, MSG_PROTO
);
1388 mx
= gbuf_cont(mioc
);
1389 mdata
= gbuf_cont(mx
);
1390 gbuf_cont(mioc
) = mdata
;
1391 atpBDS
= (struct atpBDS
*)gbuf_rptr(mx
);
1392 cmdreply_ind
= (asp_cmdreply_ind_t
*)gbuf_rptr(mioc
);
1393 cmdreply_ind
->Primitive
= ASPFUNC_CmdReply
;
1394 cmdreply_ind
->CmdResult
= *(int *)atpBDS
->bdsUserData
;
1395 gbuf_wset(mioc
,sizeof(asp_cmdreply_ind_t
));
1397 asp_putnext(scb
->gref
, mioc
);
1400 case ASPSTATE_WaitingForCloseSessRsp
:
1402 scb
->state
= ASPSTATE_Close
;
1403 scb
->rem_addr
.node
= 0;
1404 iocbp
->ioc_cmd
= ASPIOC_CloseSession
;
1405 iocbp
->ioc_rval
= 0;
1406 if (gbuf_cont(mioc
)) {
1407 gbuf_freem(gbuf_cont(mioc
));
1408 gbuf_cont(mioc
) = 0;
1410 atalk_putnext(scb
->gref
, mioc
);
1411 atp_cancel_req(scb
->gref
, (unsigned int)scb
->tickle_tid
);
1412 scb
->tickle_tid
= 0;
1416 dPrintf(D_M_ASP
, D_L_WARNING
,
1417 (" : UNKNOWN state, state=%s\n",
1418 aspStateStr(scb
->state
)));
1424 if (scb
->next_scb
) {
1426 * find the responsible scb
1428 scb
= (asp_scb_t
*)iocbp
->ioc_cr
;
1429 if ((scb
== 0) || (scb
->magic_num
!= 222)) {
1430 dPrintf(D_M_ASP
, D_L_ERROR
,
1431 ("asp_ack_reply: CAN'T find scb 2\n"));
1437 switch (scb
->state
) {
1438 case ASPSTATE_Close
:
1439 scb
->rem_addr
.node
= 0;
1448 if (scb
->rem_addr
.node
)
1449 asp_timout(asp_hangup
, scb
, scb
->session_timer
);
1450 } /* asp_ack_reply */
1456 asp_nak_reply(gref
, mioc
)
1457 register gref_t
*gref
;
1458 register gbuf_t
*mioc
;
1460 register asp_scb_t
*scb
;
1461 register ioc_t
*iocbp
;
1463 iocbp
= (ioc_t
*)gbuf_rptr(mioc
);
1465 if (iocbp
->ioc_cmd
== AT_ATP_ISSUE_REQUEST_TICKLE
) {
1467 * no tickle, close session
1469 scb
= (asp_scb_t
*)iocbp
->ioc_cr
;
1472 dPrintf(D_M_ASP
, D_L_WARNING
,
1473 ("tickle_nak: loc=%d, rem=%x.%x.%d, state=%s\n",
1474 scb
->loc_addr
.socket
,
1477 scb
->rem_addr
.socket
,
1478 aspStateStr(scb
->state
)));
1483 scb
= (asp_scb_t
*)gref
->info
;
1489 if (iocbp
->ioc_cmd
== AT_ATP_REQUEST_COMPLETE
) {
1490 if (scb
->next_scb
) {
1492 * find the responsible scb
1494 scb
= (asp_scb_t
*)iocbp
->ioc_private
;
1495 if ((scb
== 0) || (scb
->magic_num
!= 222)) {
1496 dPrintf(D_M_ASP
, D_L_ERROR
,
1497 ("asp_nak_reply: CAN'T find scb 1\n"));
1502 dPrintf(D_M_ASP
, D_L_WARNING
,
1503 ("asp_nak_reply: RSP, loc=%d, rem=%x.%x.%d, state=%s\n",
1504 scb
->loc_addr
.socket
,
1507 scb
->rem_addr
.socket
,
1508 aspStateStr(scb
->state
)));
1510 switch (scb
->state
) {
1511 case ASPSTATE_WaitingForGetStatusRsp
:
1512 iocbp
->ioc_cmd
= ASPIOC_GetStatus
;
1515 case ASPSTATE_WaitingForOpenSessRsp
:
1516 iocbp
->ioc_cmd
= ASPIOC_OpenSession
;
1519 case ASPSTATE_WaitingForCommandRsp
:
1520 case ASPSTATE_WaitingForWriteRsp
:
1521 case ASPSTATE_WaitingForWriteContinueRsp
:
1522 scb
->state
= ASPSTATE_Idle
;
1524 /* last remaining use of MSG_ERROR */
1525 gbuf_set_type(mioc
, MSG_ERROR
);
1526 *gbuf_rptr(mioc
) = (u_char
)EPROTO
;
1528 if (gbuf_cont(mioc
)) {
1529 gbuf_freem(gbuf_cont(mioc
));
1530 gbuf_cont(mioc
) = 0;
1533 asp_putnext(scb
->gref
, mioc
);
1536 case ASPSTATE_WaitingForCloseSessRsp
:
1537 scb
->state
= ASPSTATE_Close
;
1539 case ASPSTATE_Close
: /* new for PR-2296832 */
1540 scb
->rem_addr
.node
= 0;
1541 iocbp
->ioc_cmd
= ASPIOC_CloseSession
;
1542 iocbp
->ioc_rval
= 0;
1543 if (gbuf_cont(mioc
)) {
1544 gbuf_freem(gbuf_cont(mioc
));
1545 gbuf_cont(mioc
) = 0;
1547 gbuf_set_type(mioc
, MSG_IOCACK
);
1548 atalk_putnext(scb
->gref
, mioc
);
1555 scb
->state
= ASPSTATE_Idle
;
1556 atalk_putnext(gref
, mioc
);
1560 if (scb
->next_scb
) {
1562 * find the responsible scb
1564 scb
= (asp_scb_t
*)iocbp
->ioc_cr
;
1565 if ((scb
== 0) || (scb
->magic_num
!= 222)) {
1566 dPrintf(D_M_ASP
, D_L_ERROR
,
1567 ("asp_nak_reply: CAN'T find scb 2\n"));
1573 switch (scb
->state
) {
1574 case ASPSTATE_Close
:
1575 scb
->rem_addr
.node
= 0;
1581 } /* asp_nak_reply */
1584 * delete scb from the use list
1587 asp_dequeue_scb(scb
)
1592 ATDISABLE(s
, aspall_lock
);
1593 if (scb
== scb_used_list
) {
1594 if ((scb_used_list
= scb
->next_scb
) != 0)
1595 scb
->next_scb
->prev_scb
= 0;
1597 if ((scb
->prev_scb
->next_scb
= scb
->next_scb
) != 0)
1598 scb
->next_scb
->prev_scb
= scb
->prev_scb
;
1600 ATENABLE(s
, aspall_lock
);
1609 StaticProc asp_scb_t
*
1610 asp_find_scb(sock_num
, rem_addr
)
1611 unsigned char sock_num
;
1612 at_inet_t
*rem_addr
;
1616 asp_scb_t
*alt_scb
= 0;
1618 ATDISABLE(s
, aspall_lock
);
1619 for (scb
= asp_scbQ
[sock_num
]; scb
; scb
= scb
->next_scb
) {
1620 if ((scb
->rem_addr
.net
== rem_addr
->net
)
1621 && (scb
->rem_addr
.node
== rem_addr
->node
)) {
1622 if ((scb
->rem_addr
.socket
== rem_addr
->socket
)
1623 || (scb
->rem_socket
== rem_addr
->socket
))
1625 else if (alt_scb
== 0)
1630 if ((scb
== 0) && ((scb
= alt_scb
) == 0)) {
1631 dPrintf(D_M_ASP
, D_L_ERROR
,
1632 ("asp_find_scb: CAN'T find scb, loc=%d, rem=%x.%x.%d\n",
1638 ATENABLE(s
, aspall_lock
);
1647 asp_timout(func
, scb
, seconds
)
1649 register asp_scb_t
*scb
;
1654 register asp_scb_t
*curr_scb
, *prev_scb
;
1659 scb
->tmo_func
= func
;
1660 scb
->tmo_delta
= (seconds
>>SESS_TMO_RES
);
1661 scb
->tmo_cnt
= scb_tmo_cnt
;
1663 ATDISABLE(s
, asptmo_lock
);
1664 if (scb_tmo_list
== 0) {
1665 scb
->next_tmo
= scb
->prev_tmo
= 0;
1667 ATENABLE(s
, asptmo_lock
);
1672 curr_scb
= scb_tmo_list
;
1676 sum
+= curr_scb
->tmo_delta
;
1677 if (sum
> scb
->tmo_delta
) {
1678 sum
-= curr_scb
->tmo_delta
;
1679 scb
->tmo_delta
-= sum
;
1680 curr_scb
->tmo_delta
-= scb
->tmo_delta
;
1683 prev_scb
= curr_scb
;
1684 if ((curr_scb
= curr_scb
->next_tmo
) == 0) {
1685 scb
->tmo_delta
-= sum
;
1691 scb
->prev_tmo
= prev_scb
;
1692 if ((scb
->next_tmo
= prev_scb
->next_tmo
) != 0)
1693 prev_scb
->next_tmo
->prev_tmo
= scb
;
1694 prev_scb
->next_tmo
= scb
;
1697 scb
->next_tmo
= scb_tmo_list
;
1698 scb_tmo_list
->prev_tmo
= scb
;
1701 ATENABLE(s
, asptmo_lock
);
1708 asp_untimout(func
, scb
)
1710 register asp_scb_t
*scb
;
1714 if ((scb
->tmo_cnt
== scb_tmo_cnt
) || (scb
->tmo_func
== 0))
1717 ATDISABLE(s
, asptmo_lock
);
1718 if (scb_tmo_list
== scb
) {
1719 if ((scb_tmo_list
= scb
->next_tmo
) != 0) {
1720 scb_tmo_list
->prev_tmo
= 0;
1721 scb
->next_tmo
->tmo_delta
+= scb
->tmo_delta
;
1723 } else if (scb
->prev_tmo
) {
1724 if ((scb
->prev_tmo
->next_tmo
= scb
->next_tmo
) != 0) {
1725 scb
->next_tmo
->prev_tmo
= scb
->prev_tmo
;
1726 scb
->next_tmo
->tmo_delta
+= scb
->tmo_delta
;
1731 ATENABLE(s
, asptmo_lock
);
1744 * set the state to Close
1746 ATDISABLE(s
, scb
->lock
);
1747 scb
->state
= ASPSTATE_Close
;
1748 if (scb
->tickle_tid
) {
1749 atp_cancel_req(scb
->gref
, (unsigned int)scb
->tickle_tid
);
1750 scb
->tickle_tid
= 0;
1754 * notify upstream of the hangup
1756 if (scb
->rem_addr
.node
) {
1757 if (scb
->get_wait
) {
1758 wakeup(&scb
->event
);
1759 ATENABLE(s
, scb
->lock
);
1761 ATENABLE(s
, scb
->lock
);
1762 atalk_notify_sel(scb
->gref
);
1765 ATENABLE(s
, scb
->lock
);
1769 asp_iocack(gref
, mioc
)
1773 if (gbuf_cont(mioc
))
1774 ((ioc_t
*)gbuf_rptr(mioc
))->ioc_count
= gbuf_msgsize(gbuf_cont(mioc
));
1776 ((ioc_t
*)gbuf_rptr(mioc
))->ioc_count
= 0;
1778 gbuf_set_type(mioc
, MSG_IOCACK
);
1779 atalk_putnext(gref
, mioc
);
1783 asp_iocnak(gref
, mioc
, err
)
1788 ((ioc_t
*)gbuf_rptr(mioc
))->ioc_count
= 0;
1791 ((ioc_t
*)gbuf_rptr(mioc
))->ioc_error
= err
;
1792 ((ioc_t
*)gbuf_rptr(mioc
))->ioc_rval
= -1;
1793 if (gbuf_cont(mioc
)) {
1794 gbuf_freem(gbuf_cont(mioc
));
1795 gbuf_cont(mioc
) = 0;
1798 gbuf_set_type(mioc
, MSG_IOCNAK
);
1799 atalk_putnext(gref
, mioc
);
1803 * the alloc scb routine
1805 StaticProc asp_scb_t
*
1810 asp_scb_t
*scb
, *scb_array
;
1812 ATDISABLE(s
, aspall_lock
);
1813 if (scb_free_list
== 0) {
1814 if ((m
= gbuf_alloc(SCBS_PER_BLK
*sizeof(asp_scb_t
), PRI_MED
)) == 0)
1816 ATENABLE(s
, aspall_lock
);
1817 return (asp_scb_t
*)0;
1819 bzero((char *)gbuf_rptr(m
), SCBS_PER_BLK
*sizeof(asp_scb_t
));
1820 gbuf_cont(m
) = scb_resource_m
;
1822 scb_array
= (asp_scb_t
*)gbuf_rptr(m
);
1823 for (i
=0; i
< SCBS_PER_BLK
-1; i
++)
1824 scb_array
[i
].next_scb
= (asp_scb_t
*)&scb_array
[i
+1];
1825 scb_array
[i
].next_scb
= 0;
1826 scb_free_list
= (asp_scb_t
*)&scb_array
[0];
1829 scb
= scb_free_list
;
1830 scb_free_list
= scb
->next_scb
;
1831 ATENABLE(s
, aspall_lock
);
1832 ATLOCKINIT(scb
->lock
);
1833 ATLOCKINIT(scb
->delay_lock
);
1834 ATEVENTINIT(scb
->event
);
1835 ATEVENTINIT(scb
->delay_event
);
1841 * the free scb routine
1849 bzero((char *)scb
, sizeof(asp_scb_t
));
1850 ATDISABLE(s
, aspall_lock
);
1851 scb
->next_scb
= scb_free_list
;
1852 scb_free_list
= scb
;
1853 ATENABLE(s
, aspall_lock
);
1857 * routine to pass up receive data
1860 asp_putnext(gref
, mproto
)
1868 scb
= (asp_scb_t
*)gref
->info
;
1871 * queue the message.
1873 ATDISABLE(s
, scb
->lock
);
1874 gbuf_next(mproto
) = 0;
1875 if ((m
= scb
->sess_ioc
) == 0)
1876 scb
->sess_ioc
= mproto
;
1878 while (gbuf_next(m
))
1880 gbuf_next(m
) = mproto
;
1883 if (scb
->rcv_cnt
>= MAX_RCV_CNT
)
1886 if (scb
->get_wait
) {
1887 wakeup(&scb
->event
);
1888 ATENABLE(s
, scb
->lock
);
1889 } else if (mproto
== scb
->sess_ioc
) {
1890 ATENABLE(s
, scb
->lock
);
1891 atalk_notify_sel(gref
);
1893 ATENABLE(s
, scb
->lock
);
1897 * The following two routines are direct entries from system
1898 * calls to allow fast sending and recving of ASP data.
1901 /* in ASPputmsg we expect:
1907 ASPFUNC_WriteContinue
1909 bms: Make this callable from the kernel.
1910 If mreq != NULL, then must be called from kernel space and the following apply:
1911 1) *mreq is data to be sent already in mbuf chains.
1912 2) datptr->len = size of data
1915 int ASPputmsg(gref_t
*gref
, strbuf_t
*ctlptr
, strbuf_t
*datptr
, gbuf_t
*mreq
, int flags
, int *errp
)
1917 int s
, i
, err
, len
, offset
, remain
, size
, copy_len
;
1918 gbuf_t
*mioc
, *mdata
, *mx
, *m0
;
1923 int nbds
, result
, msize
, Primitive
;
1924 unsigned char *wptr
;
1925 struct atp_set_default
*sd
;
1928 struct atpBDS
*atpBDS
;
1930 union asp_primitives
*primitives
;
1934 if ((scb
= (asp_scb_t
*)gref
->info
) == 0) {
1935 dPrintf(D_M_ASP
, D_L_ERROR
,
1936 ("ASPputmsg: stale handle=0x%x, pid=%d\n",
1937 (u_int
) gref
, gref
->pid
));
1943 if (scb
->state
== ASPSTATE_Close
)
1945 if (scb
->snd_stop
) {
1951 * copy in the control and data info
1954 /* being called from kernel space */
1955 bcopy (ctlptr
, &ctlbuf
, sizeof (strbuf_t
));
1956 bcopy (datptr
, &datbuf
, sizeof (strbuf_t
));
1958 /* being called from user space */
1959 if ((err
= copyin((caddr_t
)ctlptr
, (caddr_t
)&ctlbuf
, sizeof(ctlbuf
))) != 0)
1961 if ((err
= copyin((caddr_t
)datptr
, (caddr_t
)&datbuf
, sizeof(datbuf
))) != 0)
1966 * allocate buffer and copy in the control content
1968 if (!(mioc
= gbuf_alloc_wait(ctlbuf
.len
, TRUE
))) {
1969 /* error return should not be possible */
1973 gbuf_set_type(mioc
, MSG_IOCTL
); /* for later, in ATP */
1974 gbuf_wset(mioc
, ctlbuf
.len
);
1977 /* being called from kernel space */
1978 bcopy (ctlbuf
.buf
, gbuf_rptr(mioc
), ctlbuf
.len
);
1980 /* being called from user space */
1981 if ((err
= copyin((caddr_t
)ctlbuf
.buf
, (caddr_t
)gbuf_rptr(mioc
), ctlbuf
.len
)) != 0) {
1987 iocbp
= (ioc_t
*)gbuf_rptr(mioc
);
1988 primitives
= (union asp_primitives
*)gbuf_rptr(mioc
);
1989 Primitive
= primitives
->Primitive
;
1990 dPrintf(D_M_ASP
, D_L_INFO
,
1991 ("ASPputmsg: %s\n", aspCmdStr(Primitive
)));
1994 * copy in the data content into multiple mbuf clusters if
1995 * required. ATP now expects reply data to be placed in
1996 * standard clusters, not the large external clusters that
1997 * were used previously.
2000 /* set offset for use by some commands */
2001 offset
= (Primitive
== ASPFUNC_CmdReply
) ? 0 : aspCMDsize
;
2004 /* The data from the in-kernel call for use by AFP is passed
2005 * in as one large external cluster. This needs to be copied
2006 * to a chain of standard clusters.
2008 remain
= gbuf_len(mreq
);
2009 dataptr
= mtod(mreq
, caddr_t
);
2011 /* copyin from user space */
2012 remain
= datbuf
.len
;
2013 dataptr
= (caddr_t
)datbuf
.buf
;
2016 /* allocate first buffer */
2017 if (!(mdata
= gbuf_alloc_wait((remain
+ offset
> MCLBYTES
? MCLBYTES
: remain
+ offset
), TRUE
))) {
2018 /* error return should not be possible */
2023 gbuf_wset(mdata
, 0); /* init length to zero */
2024 gbuf_cont(mioc
) = mdata
;
2027 if (remain
+ offset
> MCLBYTES
)
2028 copy_len
= MCLBYTES
- offset
;
2033 bcopy (dataptr
, (gbuf_rptr(mdata
) + offset
), copy_len
);
2034 else if ((err
= copyin(dataptr
, (caddr_t
)(gbuf_rptr(mdata
) + offset
), copy_len
)) != 0) {
2038 gbuf_wset(mdata
, (copy_len
+ offset
));
2039 size
+= copy_len
+ offset
;
2040 dataptr
+= copy_len
;
2043 /* allocate the next mbuf */
2044 if ((gbuf_cont(mdata
) = m_get((M_WAIT
), MSG_DATA
)) == 0) {
2049 mdata
= gbuf_cont(mdata
);
2050 MCLGET(mdata
, M_WAIT
);
2051 if (!(mdata
->m_flags
& M_EXT
)) {
2058 mdata
= gbuf_cont(mioc
); /* code further on down expects this to b e set */
2059 mdata
->m_pkthdr
.len
= size
; /* set packet hdr len */
2064 switch (Primitive
) {
2066 case ASPFUNC_Command
:
2068 case ASPFUNC_WriteContinue
:
2069 case ASPFUNC_Attention
:
2071 * build the command/write/write_continue request
2073 wptr
= gbuf_rptr(mdata
);
2074 atpBDS
= (struct atpBDS
*)wptr
;
2076 for (i
=0; i
< ATP_TRESP_MAX
; i
++) {
2077 *(unsigned long *)atpBDS
[i
].bdsBuffAddr
= 1;
2078 *(unsigned short *)atpBDS
[i
].bdsBuffSz
= ATP_DATA_SIZE
;
2080 sd
= (struct atp_set_default
*)wptr
;
2081 wptr
+= sizeof(struct atp_set_default
);
2082 sd
->def_retries
= (scb
->cmd_retry
.retries
== -1) ?
2083 ATP_INFINITE_RETRIES
: scb
->cmd_retry
.retries
;
2084 sd
->def_rate
= scb
->cmd_retry
.interval
*TICKS_PER_SEC
;
2085 sd
->def_BDSlen
= atpBDSsize
;
2086 ddp
= (at_ddp_t
*)wptr
;
2087 NET_ASSIGN(ddp
->src_net
, scb
->loc_addr
.net
);
2088 ddp
->src_node
= scb
->loc_addr
.node
;
2089 NET_ASSIGN(ddp
->dst_net
, scb
->rem_addr
.net
);
2090 ddp
->dst_node
= scb
->rem_addr
.node
;
2091 ddp
->dst_socket
= scb
->rem_addr
.socket
;
2092 UAS_ASSIGN(ddp
->checksum
, 0);
2093 atp
= ATP_ATP_HDR(wptr
);
2094 wptr
+= TOTAL_ATP_HDR_SIZE
;
2098 awp
= (asp_word_t
*)atp
->user_bytes
;
2099 awp
->func
= (unsigned char)Primitive
;
2100 awp
->param1
= scb
->sess_id
;
2101 awp
->param2
= scb
->snd_seq_num
;
2102 iocbp
->ioc_private
= (void *)scb
;
2103 iocbp
->ioc_count
= gbuf_len(mdata
);
2104 iocbp
->ioc_rval
= 0;
2105 iocbp
->ioc_cmd
= AT_ATP_ISSUE_REQUEST_DEF
;
2108 * send the command/write/write_continue/attention request
2110 ATDISABLE(s
, scb
->lock
);
2111 switch (awp
->func
) {
2112 case ASPFUNC_Command
:
2113 scb
->state
= ASPSTATE_WaitingForCommandRsp
;
2116 scb
->state
= ASPSTATE_WaitingForWriteRsp
;
2118 case ASPFUNC_WriteContinue
:
2119 scb
->state
= ASPSTATE_WaitingForWriteContinueRsp
;
2120 awp
->param2
= scb
->wrt_seq_num
;
2122 case ASPFUNC_Attention
:
2123 scb
->state
= ASPSTATE_WaitingForCommandRsp
;
2128 awp
->param2
= *(unsigned short *)gbuf_wptr(mdata
);
2131 ATENABLE(s
, scb
->lock
);
2132 dPrintf(D_M_ASP
,D_L_INFO
,
2133 ("ASPputmsg: %s, loc=%d, rem=%x.%x.%d\n",
2134 (awp
->func
== ASPFUNC_Command
? "CommandReq" :
2135 awp
->func
== ASPFUNC_Write
? "WriteReq" :
2136 awp
->func
== ASPFUNC_WriteContinue
? "WriteContinue" :
2137 "AttentionReq"),scb
->loc_addr
.socket
,
2138 NET_VALUE(ddp
->dst_net
),ddp
->dst_node
,ddp
->dst_socket
));
2139 atp_send_req(gref
, mioc
);
2142 case ASPFUNC_CmdReply
:
2144 ATDISABLE(s
, scb
->lock
);
2145 if (scb
->req_msgq
) {
2147 scb
->req_msgq
= gbuf_next(mx
);
2149 ATENABLE(s
, scb
->lock
);
2150 asp_putnext(scb
->gref
, mx
);
2153 ATENABLE(s
, scb
->lock
);
2155 result
= primitives
->CmdReplyReq
.CmdResult
;
2156 tid
= primitives
->CmdReplyReq
.ReqRefNum
;
2158 /* Re-use the original mioc mbuf to send the response. */
2159 gbuf_rinc(mioc
,sizeof(void *));
2161 ddp
= (at_ddp_t
*)gbuf_wptr(mioc
);
2162 gbuf_winc(mioc
,DDP_X_HDR_SIZE
);
2163 atp
= (at_atp_t
*)gbuf_wptr(mioc
);
2164 gbuf_winc(mioc
,ATP_HDR_SIZE
);
2165 NET_ASSIGN(ddp
->src_net
, scb
->loc_addr
.net
);
2166 ddp
->src_node
= scb
->loc_addr
.node
;
2167 NET_ASSIGN(ddp
->dst_net
, scb
->rem_addr
.net
);
2168 ddp
->dst_node
= scb
->rem_addr
.node
;
2169 ddp
->dst_socket
= scb
->reply_socket
;
2170 ddp
->type
= DDP_ATP
;
2171 UAS_ASSIGN(ddp
->checksum
, 0);
2172 UAS_ASSIGN(atp
->tid
, tid
);
2173 if (scb
->attn_flag
&& (tid
== scb
->attn_tid
)) {
2181 /* setup the atpBDS struct - only the length field is used,
2182 * except for the first one which contains the bds count in
2185 atpBDS
= (struct atpBDS
*)gbuf_wptr(mioc
);
2186 msize
= mdata
? gbuf_msgsize(mdata
) : 0;
2187 for (nbds
=0; (nbds
< ATP_TRESP_MAX
) && (msize
> 0); nbds
++) {
2188 len
= msize
< ATP_DATA_SIZE
? msize
: ATP_DATA_SIZE
;
2189 msize
-= ATP_DATA_SIZE
;
2190 *(long *)atpBDS
[nbds
].bdsUserData
= 0;
2191 UAL_ASSIGN(atpBDS
[nbds
].bdsBuffAddr
, 1);
2192 UAS_ASSIGN(atpBDS
[nbds
].bdsBuffSz
, len
);
2194 UAS_ASSIGN(atpBDS
[0].bdsDataSz
, nbds
);
2195 *(long *)atpBDS
[0].bdsUserData
= (long)result
;
2196 *(long *)atp
->user_bytes
= (long)result
;
2197 gbuf_winc(mioc
,atpBDSsize
);
2198 dPrintf(D_M_ASP
, D_L_INFO
,
2199 ("ASPputmsg: ATP CmdReplyReq, loc=%d, state=%s, msgsize = %d, result = %d, tid = %d\n",
2200 scb
->loc_addr
.socket
, aspStateStr(scb
->state
),
2201 (mdata
? gbuf_msgsize(mdata
) : 0), result
, tid
));
2202 atp_send_rsp(gref
, mioc
, TRUE
);
2206 /* Not an expected ASPFUNC */
2216 /* bms: make this callable from kernel. reply date is passed back as a mbuf chain in *mreply */
2217 int ASPgetmsg(gref_t
*gref
, strbuf_t
*ctlptr
, strbuf_t
*datptr
, gbuf_t
**mreply
, int *flags
, int *errp
)
2219 int err
, s
, len
, sum
, rval
;
2220 gbuf_t
*mproto
, *mdata
;
2224 unsigned char get_wait
;
2226 if ((scb
= (asp_scb_t
*)gref
->info
) == 0) {
2227 dPrintf(D_M_ASP
, D_L_ERROR
,
2228 ("ASPgetmsg: stale handle=0x%x, pid=%d\n",
2229 (u_int
) gref
, gref
->pid
));
2235 ATDISABLE(s
, scb
->lock
);
2236 if (scb
->state
== ASPSTATE_Close
) {
2237 ATENABLE(s
, scb
->lock
);
2244 while ((mproto
= scb
->sess_ioc
) == 0) {
2246 err
= tsleep(&scb
->event
, PSOCK
| PCATCH
, "aspgetmsg", 0);
2249 ATENABLE(s
, scb
->lock
);
2253 if (scb
->state
== ASPSTATE_Close
) {
2255 ATENABLE(s
, scb
->lock
);
2259 get_wait
= scb
->get_wait
;
2261 if ((ctlptr
== 0) && (datptr
== 0)) {
2262 ATENABLE(s
, scb
->lock
);
2265 scb
->sess_ioc
= gbuf_next(mproto
);
2266 mdata
= gbuf_cont(mproto
);
2267 ATENABLE(s
, scb
->lock
);
2269 /* last remaining use of MSG_ERROR */
2270 if (gbuf_type(mproto
) == MSG_ERROR
) {
2271 err
= (int)gbuf_rptr(mproto
)[0];
2276 * copy in the control and data info
2278 if (mreply
!= NULL
) {
2279 /* called from kernel space */
2280 bcopy (ctlptr
, &ctlbuf
, sizeof(ctlbuf
));
2281 bcopy (datptr
, &datbuf
, sizeof(datbuf
));
2283 /* called from user space */
2284 if ((err
= copyin((caddr_t
)ctlptr
,
2285 (caddr_t
)&ctlbuf
, sizeof(ctlbuf
))) != 0)
2287 if ((err
= copyin((caddr_t
)datptr
,
2288 (caddr_t
)&datbuf
, sizeof(datbuf
))) != 0)
2291 if ((datbuf
.maxlen
< 0) || (datbuf
.maxlen
< gbuf_msgsize(mdata
))) {
2292 ATDISABLE(s
, scb
->lock
);
2293 gbuf_next(mproto
) = scb
->sess_ioc
;
2294 scb
->sess_ioc
= mproto
;
2295 ATENABLE(s
, scb
->lock
);
2299 if (get_wait
== 0) {
2301 * this is a hack to support the select() call.
2302 * we're not supposed to dequeue messages in the Streams
2303 * head's read queue this way; but there is no better way.
2305 ATDISABLE(s
, scb
->lock
);
2306 if (scb
->sess_ioc
== 0) {
2307 ATENABLE(s
, scb
->lock
);
2309 ATENABLE(s
, scb
->lock
);
2310 atalk_notify_sel(gref
);
2315 * copy out the control content and info
2317 ctlbuf
.len
= gbuf_len(mproto
);
2319 if (mreply
!= NULL
) {
2320 /* called from kernel space */
2321 bcopy (gbuf_rptr(mproto
), ctlbuf
.buf
, ctlbuf
.len
);
2322 bcopy (&ctlbuf
, ctlptr
, sizeof(ctlbuf
));
2324 /* called from user space */
2325 if ((err
= copyout((caddr_t
)gbuf_rptr(mproto
),
2326 (caddr_t
)ctlbuf
.buf
, ctlbuf
.len
)) != 0)
2328 if ((err
= copyout((caddr_t
)&ctlbuf
,
2329 (caddr_t
)ctlptr
, sizeof(ctlbuf
))) != 0)
2334 * copy out the data content and info
2336 for (rval
= 0, sum
= 0; mdata
&& (rval
== 0); mdata
= gbuf_cont(mdata
))
2338 len
= gbuf_len(mdata
);
2340 if ((len
+ sum
) > datbuf
.maxlen
) {
2341 len
= datbuf
.maxlen
- sum
;
2345 if (mreply
== NULL
) {
2346 /* called from user space */
2347 if ((err
= copyout((caddr_t
)gbuf_rptr(mdata
), (caddr_t
)&datbuf
.buf
[sum
], len
)) != 0)
2354 if (mreply
!= NULL
) {
2355 /* called from kernel space */
2356 bcopy (&datbuf
, datptr
, sizeof(datbuf
));
2358 /* called from user space */
2359 if ((err
= copyout((caddr_t
)&datbuf
, (caddr_t
)datptr
, sizeof(datbuf
))) != 0)
2363 if (mreply
!= NULL
) {
2364 /* called from kernel space */
2365 /* return the reply data in mbufs, so dont free them.
2366 Just free the proto info */
2367 mdata
= gbuf_cont(mproto
);
2369 gbuf_cont(mproto
) = NULL
;
2372 /* called from user space */
2376 ATDISABLE(s
, scb
->lock
);
2383 ATENABLE(s
, scb
->lock
);
2387 ATDISABLE(s
, scb
->lock
);
2388 gbuf_next(mproto
) = scb
->sess_ioc
;
2389 scb
->sess_ioc
= mproto
;
2390 ATENABLE(s
, scb
->lock
);