2 * Copyright (c) 1995-2007 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
30 * Created February 20, 1995 by Tuyen Nguyen
31 * Modified for MP, 1996 by Tuyen Nguyen
32 * Modified, March 17, 1997 by Tuyen Nguyen for MacOSX.
35 #include <sys/errno.h>
36 #include <sys/types.h>
37 #include <sys/param.h>
38 #include <machine/spl.h>
39 #include <sys/systm.h>
40 #include <sys/kernel.h>
42 #include <sys/filedesc.h>
43 #include <sys/fcntl.h>
45 #include <sys/ioctl.h>
46 #include <sys/malloc.h>
47 #include <kern/locks.h>
48 #include <sys/socket.h>
49 #include <sys/socketvar.h>
53 #include <netat/sysglue.h>
54 #include <netat/appletalk.h>
55 #include <netat/at_pcb.h>
56 #include <netat/atp.h>
57 #include <netat/ddp.h>
58 #include <netat/asp.h>
59 #include <netat/at_var.h>
60 #include <netat/debug.h>
63 #define atpBDSsize (sizeof(struct atpBDS)*ATP_TRESP_MAX)
64 #define aspCMDsize (atpBDSsize+sizeof(struct atp_set_default)+TOTAL_ATP_HDR_SIZE)
65 #define SCBS_PER_BLK 16
66 #define TICKS_PER_SEC HZ
67 #define SESS_TMO_RES 2
68 #define DEF_SESS_TMO 120
69 #define NEXT_SEQ_NUM(x) (x = (x == 65535) ? 0 : (x + 1))
71 #define BAD_REMADDR(addr) \
72 ( (*(long *)&scb->rem_addr != *(long *)&addr) \
73 && ((scb->rem_addr.net != addr.net) \
74 || (scb->rem_addr.node != addr.node)) )
76 StaticProc asp_scb_t
*asp_find_scb(unsigned char, at_inet_t
*);
77 StaticProc asp_scb_t
*asp_scb_alloc(void);
79 StaticProc
void asp_putnext(gref_t
*, gbuf_t
*);
80 StaticProc
void asp_iocack(gref_t
*, gbuf_t
*);
81 StaticProc
void asp_iocnak(gref_t
*, gbuf_t
*, int);
82 StaticProc
void asp_dequeue_scb(asp_scb_t
*);
83 StaticProc
void asp_scb_free(asp_scb_t
*);
84 StaticProc
void asp_timout(asp_tmo_func
, asp_scb_t
*, int);
85 StaticProc
void asp_untimout(asp_tmo_func
, asp_scb_t
*);
86 StaticProc
void asp_hangup(asp_scb_t
*);
87 StaticProc
void asp_send_tickle(asp_scb_t
*);
88 StaticProc
void asp_send_tickle_locked(void *);
89 StaticProc
void asp_accept(asp_scb_t
*scb
, asp_scb_t
*sess_scb
, gbuf_t
*m
);
90 StaticProc
int asp_send_req(gref_t
*, gbuf_t
*, at_inet_t
*, at_retry_t
*, asp_word_t
*,
91 unsigned char , unsigned char, unsigned char);
93 extern at_ifaddr_t
*ifID_home
;
94 extern int atp_pidM
[];
95 extern gref_t
*atp_inputQ
[];
96 extern lck_mtx_t
*atalk_mutex
;
97 gbuf_t
*scb_resource_m
= 0;
98 unsigned char asp_inpC
[256];
99 asp_scb_t
*asp_scbQ
[256];
101 static at_retry_t asp_def_retry
= {2, -1, 1};
102 static unsigned char scb_tmo_cnt
;
103 asp_scb_t
*scb_used_list
;
104 static asp_scb_t
*scb_tmo_list
;
105 asp_scb_t
*scb_free_list
;
107 int asp_readable(gref_t
*);
113 return (((asp_scb_t
*)gref
->info
)->sess_ioc
? 1 : 0);
123 bzero(asp_inpC
, sizeof(asp_inpC
));
124 bzero(asp_scbQ
, sizeof(asp_scbQ
));
128 * the open routine allocates a state structure
136 * if no asp structure available, return failure
138 if ((scb
= asp_scb_alloc()) == 0)
142 * initialize the gref data structure
144 gref
->info
= (void *)scb
;
145 gref
->readable
= asp_readable
;
148 * initialize the scb data structure
151 scb
->magic_num
= 222;
152 scb
->state
= ASPSTATE_Idle
;
153 scb
->pid
= gref
->pid
;
155 scb
->session_timer
= DEF_SESS_TMO
;
156 scb
->cmd_retry
= asp_def_retry
;
157 if ((scb
->next_scb
= scb_used_list
) != 0)
158 scb
->next_scb
->prev_scb
= scb
;
164 dPrintf(D_M_ASP
, D_L_INFO
, ("asp_open: pid=%d\n", scb
->pid
));
169 * the close routine frees all the data structures
175 unsigned char sock_num
;
176 asp_scb_t
*scb
, *new_scb
;
179 scb
= (asp_scb_t
*)gref
->info
;
180 dPrintf(D_M_ASP
, D_L_INFO
, ("asp_close: loc=%d\n",
181 scb
->loc_addr
.socket
));
183 if (scb
->pid
&& scb
->sess_ioc
&& (scb
->dflag
!= 1)) {
185 * send the CloseSess response to peer
187 if (gbuf_type(scb
->sess_ioc
) != MSG_PROTO
) {
189 scb
->sess_ioc
= gbuf_next(m
);
190 atp_send_rsp(scb
->gref
, m
, TRUE
);
194 if (scb
->atp_state
) {
195 sock_num
= scb
->loc_addr
.socket
;
196 if ((scb
->dflag
!= 1) && scb
->stat_msg
) {
197 untimeout(atp_retry_req
, scb
->stat_msg
);
198 gbuf_freem(scb
->stat_msg
);
201 if (asp_scbQ
[sock_num
]->next_scb
== 0) {
202 asp_scbQ
[sock_num
] = 0;
203 asp_inpC
[sock_num
] = 0;
204 dPrintf(D_M_ASP
, D_L_INFO
,
205 (" : atp_close(), loc=%d\n", scb
->loc_addr
.socket
));
208 asp_inpC
[sock_num
]--;
209 if (scb
== asp_scbQ
[sock_num
]) {
210 new_scb
= scb
->next_scb
;
211 new_scb
->prev_scb
= 0;
212 asp_scbQ
[sock_num
] = new_scb
;
213 new_scb
->atp_state
->atp_gref
= new_scb
->gref
;
214 new_scb
->atp_state
->pid
= new_scb
->pid
;
215 atp_inputQ
[sock_num
] = new_scb
->gref
;
217 if ((scb
->prev_scb
->next_scb
= scb
->next_scb
) != 0)
218 scb
->next_scb
->prev_scb
= scb
->prev_scb
;
223 asp_dequeue_scb(scb
);
226 * free all allocated blocks if any
229 gbuf_freem(scb
->stat_msg
);
233 gbuf_freel(scb
->sess_ioc
);
237 gbuf_freel(scb
->req_msgq
);
241 scb
->rem_addr
.node
= 0;
247 asp_untimout(asp_hangup
, scb
);
248 untimeout(asp_send_tickle_locked
, (void *)scb
); /* added for 2225395 */
251 * free the asp session control block
253 scb
->state
= ASPSTATE_Close
;
260 static const char *aspStateStr(int);
262 static const char *aspStateStr(state
)
265 return ((state
==ASPSTATE_Close
)? "Close":
266 (state
==ASPSTATE_Idle
)? "Idle":
267 (state
==ASPSTATE_WaitingForGetStatusRsp
)? "GetStatusRsp":
268 (state
==ASPSTATE_WaitingForOpenSessRsp
)? "OpenSessRsp":
269 (state
==ASPSTATE_WaitingForCommandRsp
)? "CmdRsp":
270 (state
==ASPSTATE_WaitingForWriteContinue
)? "WriteCont":
271 (state
==ASPSTATE_WaitingForWriteRsp
)? "WriteRsp":
272 (state
==ASPSTATE_WaitingForWriteContinueRsp
)? "WriteContRsp":
273 (state
==ASPSTATE_WaitingForCloseSessRsp
)? "CloseSessRsp":
277 static const char *aspCmdStr(int);
279 static const char *aspCmdStr(aspCmd
)
282 return ((aspCmd
==ASPFUNC_CloseSess
)? "CloseSess":
283 (aspCmd
==ASPFUNC_Command
)? "Command":
284 (aspCmd
==ASPFUNC_GetStatus
)? "GetStatus":
285 (aspCmd
==ASPFUNC_OpenSess
)? "OpenSess":
286 (aspCmd
==ASPFUNC_Tickle
)? "Tickle":
287 (aspCmd
==ASPFUNC_Write
)? "Write":
288 (aspCmd
==ASPFUNC_WriteContinue
)? "WriteContinue":
289 (aspCmd
==ASPFUNC_Attention
)? "Attention":
290 (aspCmd
==ASPFUNC_CmdReply
)? "CmdReply": "unknown");
293 static const char *aspIOCStr(int);
295 static const char *aspIOCStr(aspIOC
)
299 (aspIOC
==ASPIOC_ClientBind
)? "ClientBind":
300 (aspIOC
==ASPIOC_CloseSession
)? "CloseSession":
301 (aspIOC
==ASPIOC_GetLocEntity
)? "GetLocEntity":
302 (aspIOC
==ASPIOC_GetRemEntity
)? "GetRemEntity":
303 (aspIOC
==ASPIOC_GetSession
)? "GetSession":
304 (aspIOC
==ASPIOC_GetStatus
)? "GetStatus":
305 (aspIOC
==ASPIOC_ListenerBind
)? "ListenerBind":
306 (aspIOC
==ASPIOC_OpenSession
)? "OpenSession":
307 (aspIOC
==ASPIOC_StatusBlock
)? "StatusBlock":
308 (aspIOC
==ASPIOC_SetPid
)? "SetPid":
309 (aspIOC
==ASPIOC_GetSessId
)? "GetSessId":
310 (aspIOC
==ASPIOC_EnableSelect
)? "EnableSelect":
311 (aspIOC
==ASPIOC_Look
)? "Look":
319 static char mbuf_str
[100];
324 "dat = %d, prot = %d, ioc = %d, err = %d, hu = %d, ack = %d, nak = %d, ctl = %d",
326 "dat = %d, prot = %d, ioc = %d, ctl = %d",
327 mbstat
.m_mtypes
[MSG_DATA
], mbstat
.m_mtypes
[MSG_PROTO
], mbstat
.m_mtypes
[MSG_IOCTL
],
329 mbstat.m_mtypes[MSG_ERROR], mbstat.m_mtypes[MSG_HANGUP], mbstat.m_mtypes[MSG_IOCACK],
330 mbstat.m_mtypes[MSG_IOCNAK],
332 mbstat
.m_mtypes
[MSG_CTL
]);
333 return(&mbuf_str
[0]);
336 void trace_beg(str
, m
)
341 gbuf_t
*mdata
, *mchain
;
344 for (i
= 0, j
= 0, mdata
= m
, mchain
= m
; mdata
; i
++) {
345 mdata
= gbuf_cont(mdata
);
346 if (!mdata
&& mchain
) {
347 mdata
= gbuf_next(mchain
);
352 dPrintf(D_M_ASP
, D_L_TRACE
,
353 ("%s: %s, m# = %d, c# = %d\n", str
, mbuf_totals(), i
, j
));
359 dPrintf(D_M_ASP
, D_L_TRACE
,
360 (" %s: %s\n", str
, mbuf_totals()));
362 #endif /* AT_MBUF_TRACE */
367 int asp_wput(gref
, m
)
372 unsigned char sockSav
, sock_num
;
373 gbuf_t
*mioc
, *mdata
;
375 asp_scb_t
*scb
, *server_scb
, *curr_scb
;
378 union asp_primitives
*primitives
;
379 asp_status_cmd_t
*status_cmd
;
380 asp_open_cmd_t
*open_cmd
;
383 scb
= (asp_scb_t
*)gref
->info
;
384 if (scb
->dflag
== 0) {
389 if (gbuf_type(m
) != MSG_IOCTL
) {
390 dPrintf(D_M_ASP
, D_L_WARNING
,
391 ("asp_wput: UNKNOWN message, type=%d\n",
398 iocbp
= (ioc_t
*)gbuf_rptr(mioc
);
400 dPrintf(D_M_ASP_LOW
, D_L_INFO
,
401 ("asp_wput: %s, loc=%d, state=%s\n",
402 aspIOCStr(iocbp
->ioc_cmd
), scb
->loc_addr
.socket
,
403 aspStateStr(scb
->state
)));
405 switch (iocbp
->ioc_cmd
) {
406 case ASPIOC_CloseSession
:
407 if ((scb
->state
== ASPSTATE_Close
) || (scb
->rem_addr
.node
== 0))
412 aw
.func
= ASPFUNC_CloseSess
;
413 aw
.param1
= scb
->sess_id
;
415 iocbp
->ioc_private
= (void *)scb
;
416 scb
->ioc_wait
= (unsigned char)(iocbp
->ioc_cmd
& 0xff);
417 iocbp
->ioc_cmd
= AT_ATP_ISSUE_REQUEST
;
418 asp_send_req(gref
, mioc
, &scb
->rem_addr
, &Retry
, &aw
,
419 0, ASPSTATE_WaitingForCloseSessRsp
, 0x01);
422 case ASPIOC_ClientBind
:
424 * open an ATP channel
426 if ((err
= atp_open(gref
, 0)) != 0) {
427 asp_iocnak(gref
, mioc
, err
);
430 scb
->atp_state
= (atp_state_t
*)gref
->info
;
431 scb
->atp_state
->pid
= scb
->pid
;
433 * bind to any available socket
436 sockSav
= scb
->dflag
;
437 if ((sock_num
= (at_socket
)atp_bind(gref
, 0, &sockSav
)) == 0) {
438 scb
->atp_state
= (atp_state_t
*)0;
440 gref
->info
= (void *)scb
;
441 asp_iocnak(gref
, mioc
, EINVAL
);
444 gref
->info
= (void *)scb
;
445 asp_dequeue_scb(scb
);
446 scb
->atp_state
->dflag
= scb
->dflag
;
447 scb
->loc_addr
.socket
= sock_num
;
448 asp_scbQ
[sock_num
] = scb
;
449 asp_inpC
[sock_num
]++;
450 atp_pidM
[sock_num
] = 0;
453 case ASPIOC_ListenerBind
:
455 * open an ATP channel
457 if ((err
= atp_open(gref
, 0)) != 0) {
458 asp_iocnak(gref
, mioc
, err
);
461 scb
->atp_state
= (atp_state_t
*)gref
->info
;
462 scb
->atp_state
->pid
= scb
->pid
;
464 * bind to any available socket
466 if ((sock_num
= (at_socket
)atp_bind(gref
, 0, 0)) == 0) {
467 scb
->atp_state
= (atp_state_t
*)0;
469 gref
->info
= (void *)scb
;
470 asp_iocnak(gref
, mioc
, EINVAL
);
473 gref
->info
= (void *)scb
;
474 asp_dequeue_scb(scb
);
475 scb
->atp_state
->dflag
= scb
->dflag
;
476 scb
->loc_addr
.socket
= sock_num
;
477 asp_scbQ
[sock_num
] = scb
;
478 asp_inpC
[sock_num
]++;
480 *(at_inet_t
*)gbuf_rptr(gbuf_cont(mioc
)) = scb
->loc_addr
;
483 case ASPIOC_GetLocEntity
:
484 if ((gbuf_cont(mioc
) == 0) || (scb
->atp_state
== 0)) {
485 asp_iocnak(gref
, mioc
, EPROTOTYPE
);
488 *(at_inet_t
*)gbuf_rptr(gbuf_cont(mioc
)) = scb
->loc_addr
;
491 case ASPIOC_GetRemEntity
:
492 if ((gbuf_cont(mioc
) == 0) || (scb
->atp_state
== 0)) {
493 asp_iocnak(gref
, mioc
, EPROTOTYPE
);
496 *(at_inet_t
*)gbuf_rptr(gbuf_cont(mioc
)) = scb
->rem_addr
;
499 case ASPIOC_GetSession
:
500 if ((mdata
= gbuf_cont(mioc
)) == 0) {
501 asp_iocnak(gref
, mioc
, EPROTOTYPE
);
504 addr
= (at_inet_t
*)gbuf_rptr(mdata
);
505 scb
->tickle_interval
= (unsigned short)addr
->node
;
506 scb
->session_timer
= addr
->net
;
507 server_scb
= asp_scbQ
[addr
->socket
];
508 /*### LD 10/28/97: changed to make sure we're not accessing a null server_scb */
509 if (server_scb
== 0) {
510 asp_iocnak(gref
, mioc
, EPROTOTYPE
);
513 if (server_scb
->sess_ioc
== 0) {
514 asp_iocnak(gref
, mioc
, EPROTOTYPE
);
519 * open an ATP channel
521 if ((err
= atp_open(gref
, 0)) != 0) {
522 gref
->info
= (void *)scb
;
523 asp_iocnak(gref
, mioc
, err
);
526 scb
->atp_state
= (atp_state_t
*)gref
->info
;
527 scb
->atp_state
->pid
= scb
->pid
;
529 * bind to any available socket
532 sockSav
= scb
->dflag
;
533 if ((sock_num
= (at_socket
)atp_bind(gref
, 0, &sockSav
)) == 0) {
535 asp_dequeue_scb(scb
);
537 scb
->loc_addr
.socket
= sock_num
;
538 for (curr_scb
= asp_scbQ
[sock_num
];
539 curr_scb
->next_scb
; curr_scb
= curr_scb
->next_scb
) ;
540 scb
->prev_scb
= curr_scb
;
541 curr_scb
->next_scb
= scb
;
542 scb
->atp_state
= curr_scb
->atp_state
;
544 asp_dequeue_scb(scb
);
545 scb
->loc_addr
.socket
= sock_num
;
546 asp_scbQ
[sock_num
] = scb
;
547 scb
->atp_state
->dflag
= scb
->dflag
;
549 gref
->info
= (void *)scb
;
550 asp_inpC
[sock_num
]++;
552 asp_accept(server_scb
, scb
, mdata
);
555 case ASPIOC_GetStatus
:
556 if ((mdata
= gbuf_cont(mioc
)) == 0) {
557 asp_iocnak(gref
, mioc
, EINVAL
);
561 status_cmd
= (asp_status_cmd_t
*)gbuf_rptr(mdata
);
562 aw
.func
= ASPFUNC_GetStatus
;
565 scb
->ioc_wait
= (unsigned char)(iocbp
->ioc_cmd
& 0xff);
566 iocbp
->ioc_cmd
= AT_ATP_ISSUE_REQUEST_DEF
;
567 /* bms: make sure this is an ALO request */
568 asp_send_req(gref
, mioc
, &status_cmd
->SLSEntityIdentifier
,
569 &status_cmd
->Retry
, &aw
, 0, ASPSTATE_WaitingForGetStatusRsp
, 0xff);
573 case ASPIOC_OpenSession
:
574 if ((mdata
= gbuf_cont(mioc
)) == 0) {
575 asp_iocnak(gref
, mioc
, EINVAL
);
579 open_cmd
= (asp_open_cmd_t
*)gbuf_rptr(mdata
);
580 scb
->svc_addr
= open_cmd
->SLSEntityIdentifier
;
581 scb
->rem_addr
= scb
->svc_addr
;
582 scb
->rem_node
= scb
->rem_addr
.node
;
583 scb
->rem_addr
.node
= 0;
584 scb
->tickle_interval
= open_cmd
->TickleInterval
;
585 scb
->session_timer
= open_cmd
->SessionTimer
;
586 aw
.func
= ASPFUNC_OpenSess
;
587 aw
.param1
= scb
->loc_addr
.socket
;
588 aw
.param2
= htons(ASP_Version
);
589 scb
->ioc_wait
= (unsigned char)(iocbp
->ioc_cmd
& 0xff);
590 iocbp
->ioc_cmd
= AT_ATP_ISSUE_REQUEST_DEF
;
591 asp_send_req(gref
, mioc
, &open_cmd
->SLSEntityIdentifier
,
592 &open_cmd
->Retry
, &aw
, 1, ASPSTATE_WaitingForOpenSessRsp
, 0x01);
596 case ASPIOC_StatusBlock
:
598 * save the server status block
601 gbuf_freem(scb
->stat_msg
);
602 scb
->stat_msg
= gbuf_cont(mioc
);
606 /* *** Does scb->pid get used in a packet header,
607 and if so is it in ASP, or in ATP?
608 If not, do we need this call for anything?
609 (cap does currently use it in _ANS code.)
612 if (gbuf_cont(mioc
) == 0) {
613 asp_iocnak(gref
, mioc
, EINVAL
);
616 scb
->pid
= *(int *)gbuf_rptr(gbuf_cont(mioc
));
619 case ASPIOC_GetSessId
:
620 if (gbuf_cont(mioc
) == 0) {
621 asp_iocnak(gref
, mioc
, EINVAL
);
624 *(gref_t
**)gbuf_rptr(gbuf_cont(mioc
)) = gref
;
628 if (gbuf_cont(mioc
) == 0) {
629 asp_iocnak(gref
, mioc
, EINVAL
);
633 primitives
= (union asp_primitives
*)gbuf_rptr(scb
->sess_ioc
);
634 if (primitives
->Primitive
== ASPFUNC_CmdReply
)
635 *(int *)gbuf_rptr(gbuf_cont(mioc
)) = 0;
637 *(int *)gbuf_rptr(gbuf_cont(mioc
)) = 1;
639 *(int *)gbuf_rptr(gbuf_cont(mioc
)) = -1;
642 case DDP_IOC_GET_CFG
:
644 struct atp_state
*atp
= (struct atp_state
*)gref
->info
;
646 atp
= (struct atp_state
*)atp
->atp_msgq
;
648 if (gbuf_cont(mioc
) == 0) {
649 asp_iocnak(gref
, mioc
, EINVAL
);
652 /* *** borrowed from ddp_proto.c to handle DDP_IOC_GET_CFG
654 scb
->state
= ASPSTATE_Idle
;
656 /* *** was ddp_get_cfg() *** */
658 (ddp_addr_t
*)gbuf_rptr(gbuf_cont(mioc
));
659 cfgp
->inet
.net
= ifID_home
->ifThisNode
.s_net
;
660 cfgp
->inet
.node
= ifID_home
->ifThisNode
.s_node
;
661 cfgp
->inet
.socket
= atp
->atp_socket_no
;
662 cfgp
->ddptype
= DDP_ATP
;
664 gbuf_wset(gbuf_cont(mioc
), sizeof(at_inet_t
));
669 asp_iocnak(gref
, mioc
, EINVAL
);
673 asp_iocack(gref
, mioc
);
678 * send request routine
681 asp_send_req(gref
, mioc
, dest
, retry
, awp
, xo
, state
, bitmap
)
689 unsigned char bitmap
;
694 struct atp_set_default
*sd
;
697 struct atpBDS
*atpBDS
;
698 asp_scb_t
*scb
= (asp_scb_t
*)gref
->info
;
701 * allocate an ATP buffer for the request
703 if ((gbuf_cont(mioc
) = gbuf_alloc(aspCMDsize
, PRI_MED
)) == 0) {
704 if (awp
->func
== ASPFUNC_Tickle
)
707 asp_iocnak(gref
, mioc
, ENOBUFS
);
708 dPrintf(D_M_ASP
, D_L_WARNING
,
709 ("asp_send_req: ENOBUFS, loc=%d\n", scb
->loc_addr
.socket
));
713 mdata
= gbuf_cont(mioc
);
714 iocbp
= (ioc_t
*)gbuf_rptr(mioc
);
719 atpBDS
= (struct atpBDS
*)gbuf_rptr(mdata
);
720 gbuf_wset(mdata
,atpBDSsize
);
721 for (i
=0; i
< ATP_TRESP_MAX
; i
++) {
722 *(unsigned long *)atpBDS
[i
].bdsBuffAddr
= 1;
723 *(unsigned short *)atpBDS
[i
].bdsBuffSz
= ATP_DATA_SIZE
;
725 sd
= (struct atp_set_default
*)gbuf_wptr(mdata
);
726 gbuf_winc(mdata
,sizeof(struct atp_set_default
));
727 sd
->def_retries
= (retry
->retries
== -1) ?
728 ATP_INFINITE_RETRIES
: retry
->retries
;
729 sd
->def_rate
= retry
->interval
*TICKS_PER_SEC
;
730 sd
->def_BDSlen
= atpBDSsize
;
731 ddp
= (at_ddp_t
*)gbuf_wptr(mdata
);
732 NET_ASSIGN(ddp
->src_net
, scb
->loc_addr
.net
);
733 ddp
->src_node
= scb
->loc_addr
.node
;
734 NET_ASSIGN(ddp
->dst_net
, dest
->net
);
735 ddp
->dst_node
= dest
->node
;
736 ddp
->dst_socket
= dest
->socket
;
737 UAS_ASSIGN(ddp
->checksum
, 0);
738 atp
= ATP_ATP_HDR(gbuf_wptr(mdata
));
741 atp
->bitmap
= bitmap
;
742 gbuf_winc(mdata
,TOTAL_ATP_HDR_SIZE
);
743 *(asp_word_t
*)atp
->user_bytes
= *awp
;
744 iocbp
->ioc_count
= gbuf_len(mdata
);
751 dPrintf(D_M_ASP
, D_L_INFO
,
752 ("asp_send_req: %s, loc=%d, rem= %d, len=%d, state=%s\n",
753 aspCmdStr(awp
->func
),
754 scb
->loc_addr
.socket
, ddp
->dst_socket
, iocbp
->ioc_count
,
755 aspStateStr(scb
->state
)));
757 atp_send_req(gref
, mioc
);
762 * send tickle routine - locked version
765 asp_send_tickle_locked(scb
)
769 asp_send_tickle((asp_scb_t
*)scb
);
775 * send tickle routine
788 * make sure the connection is still there
790 if (scb
->rem_addr
.node
== 0) {
794 if ((mioc
= gbuf_alloc(sizeof(ioc_t
), PRI_HI
)) == 0) {
795 dPrintf(D_M_ASP
, D_L_WARNING
,
796 ("asp_send_tickle: ENOBUFS 0, loc=%d, rem=%d\n",
797 scb
->loc_addr
.socket
,scb
->rem_addr
.socket
));
798 timeout(asp_send_tickle_locked
, (void *)scb
, 10);
801 gbuf_wset(mioc
,sizeof(ioc_t
));
802 gbuf_set_type(mioc
, MSG_IOCTL
);
804 dest
= scb
->svc_addr
.node
?
805 (at_inet_t
*)&scb
->svc_addr
: (at_inet_t
*)&scb
->rem_addr
;
806 retry
.interval
= scb
->tickle_interval
;
809 aw
.func
= ASPFUNC_Tickle
;
810 aw
.param1
= scb
->sess_id
;
812 ((ioc_t
*)gbuf_rptr(mioc
))->ioc_cr
= (void *)scb
;
813 ((ioc_t
*)gbuf_rptr(mioc
))->ioc_cmd
= AT_ATP_ISSUE_REQUEST_TICKLE
;
815 if (asp_send_req(scb
->gref
, mioc
, dest
, &retry
, &aw
, 0, scb
->state
, 0)) {
816 dPrintf(D_M_ASP
, D_L_WARNING
,
817 ("asp_send_tickle: ENOBUFS 1, loc=%d, rem=%d\n",
818 scb
->loc_addr
.socket
,scb
->rem_addr
.socket
));
820 timeout(asp_send_tickle_locked
, (void *)scb
, 10);
826 * accept connection routine
829 asp_accept(scb
, sess_scb
, m
)
840 mdata
= scb
->sess_ioc
;
841 ddp
= (at_ddp_t
*)gbuf_rptr(mdata
);
842 atp
= (at_atp_t
*)(gbuf_rptr(mdata
) + DDP_X_HDR_SIZE
);
843 rem_addr
.net
= NET_VALUE(ddp
->src_net
);
844 rem_addr
.node
= ddp
->src_node
;
845 rem_addr
.socket
= ddp
->src_socket
;
846 awp
= (asp_word_t
*)atp
->user_bytes
;
848 sess_scb
->loc_addr
.net
= NET_VALUE(ddp
->dst_net
);
849 sess_scb
->loc_addr
.node
= ddp
->dst_node
;
850 NET_ASSIGN(ddp
->src_net
, sess_scb
->loc_addr
.net
);
851 ddp
->src_node
= sess_scb
->loc_addr
.node
;
852 NET_ASSIGN(ddp
->dst_net
, rem_addr
.net
);
853 ddp
->dst_node
= rem_addr
.node
;
854 ddp
->dst_socket
= rem_addr
.socket
;
856 sess_scb
->sess_id
= sess_scb
->loc_addr
.socket
;
857 sess_scb
->rem_socket
= rem_addr
.socket
;
858 sess_scb
->rem_addr
= rem_addr
;
859 sess_scb
->rem_addr
.socket
= awp
->param1
;
860 sess_scb
->reply_socket
= sess_scb
->rem_addr
.socket
;
861 awp
->func
= sess_scb
->loc_addr
.socket
;
862 awp
->param1
= sess_scb
->sess_id
;
865 scb
->sess_ioc
= gbuf_next(mdata
);
866 gbuf_next(mdata
) = 0;
867 asp_timout(asp_hangup
, sess_scb
, sess_scb
->session_timer
);
868 atp_send_rsp(scb
->gref
, mdata
, TRUE
);
869 asp_send_tickle(sess_scb
);
870 dPrintf(D_M_ASP
, D_L_INFO
,
871 ("asp_accept: ACCEPT connect request, loc=%d, rem=%x.%x.%d\n",
872 sess_scb
->loc_addr
.socket
,
873 sess_scb
->rem_addr
.net
,
874 sess_scb
->rem_addr
.node
,sess_scb
->rem_addr
.socket
));
878 * timer routine - locked version
880 void asp_clock_locked(arg
)
895 asp_tmo_func tmo_func
;
898 scb_tmo_list
->tmo_delta
--;
899 while (((scb
= scb_tmo_list
) != 0) && (scb_tmo_list
->tmo_delta
== 0)) {
900 if ((scb_tmo_list
= scb
->next_tmo
) != 0)
901 scb_tmo_list
->prev_tmo
= 0;
902 if ((tmo_func
= scb
->tmo_func
) != 0) {
908 if (++scb_tmo_cnt
== 0) scb_tmo_cnt
++;
909 timeout(asp_clock_locked
, (void *)arg
, (1<<SESS_TMO_RES
)*TICKS_PER_SEC
);
917 asp_ack_reply(gref
, mioc
)
918 register gref_t
*gref
;
919 register gbuf_t
*mioc
;
921 int len
, msize
, nbds
;
922 register gbuf_t
*mdata
, *m
, *mx
;
923 struct atpBDS
*atpBDS
;
926 register asp_scb_t
*scb
, *sess_scb
;
927 register ioc_t
*iocbp
;
928 register asp_word_t
*awp
;
929 register asp_command_ind_t
*command_ind
;
930 register asp_cmdreply_ind_t
*cmdreply_ind
;
933 iocbp
= (ioc_t
*)gbuf_rptr(mioc
);
935 if (iocbp
->ioc_cmd
== AT_ATP_ISSUE_REQUEST_TICKLE
) {
937 * ignore the ack for the tickle request
939 scb
= (asp_scb_t
*)iocbp
->ioc_cr
;
940 scb
->tickle_tid
= (unsigned short)iocbp
->ioc_rval
;
945 scb
= (asp_scb_t
*)gref
->info
;
951 if (iocbp
->ioc_cmd
== AT_ATP_GET_POLL
) {
953 * if no data, just drop the request
955 if ((mdata
= gbuf_cont(mioc
)) == 0) {
960 gbuf_set_type(mioc
, MSG_IOCTL
);
961 ddp
= (at_ddp_t
*)gbuf_rptr(mdata
);
962 gbuf_rinc(mdata
,DDP_X_HDR_SIZE
);
963 atp
= (at_atp_t
*)gbuf_rptr(mdata
);
964 gbuf_rinc(mdata
,ATP_HDR_SIZE
);
965 rem_addr
.net
= NET_VALUE(ddp
->src_net
);
966 rem_addr
.node
= ddp
->src_node
;
967 rem_addr
.socket
= ddp
->src_socket
;
968 awp
= (asp_word_t
*)atp
->user_bytes
;
972 * find the responsible scb
974 if ((scb
= asp_find_scb(scb
->loc_addr
.socket
, &rem_addr
)) == 0) {
979 dPrintf(D_M_ASP
, D_L_INFO
,
980 ("asp_ack_reply: %s, loc=%d, rem=%x.%x.%d\n",
981 aspCmdStr(awp
->func
),scb
->loc_addr
.socket
,
982 NET_VALUE(ddp
->src_net
) ,ddp
->src_node
,ddp
->src_socket
));
984 if (scb
->rem_addr
.node
)
985 asp_untimout(asp_hangup
, scb
);
988 case ASPFUNC_GetStatus
:
990 * ignore if this is not a server socket
993 if ((scb
->dflag
!= 1) || (scb
->stat_msg
994 && ((mx
= gbuf_dupb(scb
->stat_msg
)) == 0)))
999 * send the status block
1001 if (gbuf_cont(mdata
)) {
1002 gbuf_freem(gbuf_cont(mdata
));
1003 gbuf_cont(mdata
) = 0;
1005 gbuf_rdec(mdata
,TOTAL_ATP_HDR_SIZE
);
1006 if ((m
= gbuf_alloc( (TOTAL_ATP_HDR_SIZE
+atpBDSsize
), PRI_MED
)) == 0) {
1011 bcopy(gbuf_rptr(mdata
), gbuf_rptr(m
), TOTAL_ATP_HDR_SIZE
);
1014 ddp
= (at_ddp_t
*)gbuf_rptr(mdata
);
1015 gbuf_wset(mdata
,DDP_X_HDR_SIZE
);
1016 atp
= (at_atp_t
*)gbuf_wptr(mdata
);
1017 gbuf_winc(mdata
,ATP_HDR_SIZE
);
1018 awp
= (asp_word_t
*)atp
->user_bytes
;
1019 NET_NET(ddp
->src_net
, ddp
->dst_net
);
1020 ddp
->src_node
= ddp
->dst_node
;
1021 NET_ASSIGN(ddp
->dst_net
, rem_addr
.net
);
1022 ddp
->dst_node
= rem_addr
.node
;
1023 ddp
->dst_socket
= rem_addr
.socket
;
1024 UAS_ASSIGN(ddp
->checksum
, 0);
1025 atpBDS
= (struct atpBDS
*)gbuf_wptr(mdata
);
1026 msize
= mx
? gbuf_msgsize(mx
) : 0;
1027 for (nbds
=0; (nbds
< ATP_TRESP_MAX
) && (msize
> 0); nbds
++) {
1028 len
= msize
< ATP_DATA_SIZE
? msize
: ATP_DATA_SIZE
;
1029 msize
-= ATP_DATA_SIZE
;
1030 *(long *)atpBDS
[nbds
].bdsUserData
= 0;
1031 UAL_ASSIGN(atpBDS
[nbds
].bdsBuffAddr
, 1);
1032 UAS_ASSIGN(atpBDS
[nbds
].bdsBuffSz
, len
);
1034 UAS_ASSIGN(atpBDS
[0].bdsDataSz
, nbds
);
1035 gbuf_winc(mdata
,atpBDSsize
);
1036 gbuf_cont(mdata
) = mx
;
1037 atp_send_rsp(gref
, mdata
, FALSE
);
1040 case ASPFUNC_OpenSess
:
1042 * ignore if server is not ready
1044 if ((scb
->dflag
!= 1) || (scb
->stat_msg
== 0))
1048 if (gbuf_cont(mdata
)) {
1049 gbuf_freem(gbuf_cont(mdata
));
1050 gbuf_cont(mdata
) = 0;
1052 gbuf_rdec(mdata
,TOTAL_ATP_HDR_SIZE
);
1053 gbuf_wset(mdata
,TOTAL_ATP_HDR_SIZE
);
1054 if (awp
->param2
!= ASP_Version
) {
1056 * bad version number, send the OpenSession response
1060 awp
->param2
= htons((unsigned short)ASPERR_BadVersNum
);
1061 dPrintf(D_M_ASP
, D_L_INFO
,
1063 ASPERR_BadVersNum
));
1065 NET_NET(ddp
->src_net
, ddp
->dst_net
);
1066 ddp
->src_node
= ddp
->dst_node
;
1067 NET_ASSIGN(ddp
->dst_net
, rem_addr
.net
);
1068 ddp
->dst_node
= rem_addr
.node
;
1069 ddp
->dst_socket
= rem_addr
.socket
;
1070 atp_send_rsp(gref
, mdata
, FALSE
);
1075 * queue the connection request
1077 gbuf_next(mdata
) = 0;
1078 if ((m
= scb
->sess_ioc
) == 0) {
1079 scb
->sess_ioc
= mdata
;
1081 wakeup(&scb
->event
);
1083 atalk_notify_sel(gref
);
1085 while (gbuf_next(m
))
1087 gbuf_next(m
) = mdata
;
1089 dPrintf(D_M_ASP
, D_L_INFO
,
1090 (" : QUEUE connect request\n"));
1094 case ASPFUNC_Command
:
1096 if ( (scb
->sess_id
!= awp
->param1
)
1097 || (scb
->rcv_seq_num
!= ntohs(awp
->param2
))
1098 || BAD_REMADDR(rem_addr
) ) {
1100 snprintf(era
, sizeof(era
), "%d.%d", scb
->rem_addr
.node
,scb
->rem_addr
.socket
);
1101 snprintf(ra
, sizeof(ra
), "%d.%d", rem_addr
.node
,rem_addr
.socket
);
1102 dPrintf(D_M_ASP
, D_L_WARNING
,
1103 (" : DROP, id=%d,esn=%d,sn=%d,erem=%s,rem=%s\n",
1104 scb
->sess_id
,scb
->rcv_seq_num
,awp
->param2
,era
,ra
));
1105 gbuf_cont(mioc
) = 0;
1106 gbuf_rdec(mdata
,TOTAL_ATP_HDR_SIZE
);
1107 atp_drop_req(gref
, mdata
);
1110 scb
->reply_socket
= rem_addr
.socket
;
1111 if (awp
->func
== ASPFUNC_Write
)
1112 scb
->wrt_seq_num
= scb
->rcv_seq_num
;
1113 NEXT_SEQ_NUM(scb
->rcv_seq_num
);
1114 gbuf_set_type(mioc
, MSG_PROTO
);
1115 gbuf_wset(mioc
,sizeof(asp_command_ind_t
));
1116 command_ind
= (asp_command_ind_t
*)gbuf_rptr(mioc
);
1117 command_ind
->Primitive
= (int)awp
->func
;
1118 command_ind
->ReqRefNum
=
1119 ntohs(*(unsigned short *)atp
->tid
);
1120 command_ind
->ReqType
= awp
->func
;
1122 mdata
= gbuf_strip(mdata
);
1123 gbuf_cont(mioc
) = mdata
;
1124 if (scb
->req_flag
) {
1125 if ((mx
= scb
->req_msgq
) != 0) {
1126 while (gbuf_next(mx
))
1128 gbuf_next(mx
) = mioc
;
1130 scb
->req_msgq
= mioc
;
1133 asp_putnext(scb
->gref
, mioc
);
1137 case ASPFUNC_WriteContinue
:
1138 if ( (scb
->sess_id
!= awp
->param1
)
1139 || (scb
->snd_seq_num
!= awp
->param2
)
1140 || BAD_REMADDR(rem_addr
) ) {
1143 scb
->reply_socket
= rem_addr
.socket
;
1144 gbuf_set_type(mioc
, MSG_PROTO
);
1145 gbuf_wset(mioc
,sizeof(asp_command_ind_t
));
1146 command_ind
= (asp_command_ind_t
*)gbuf_rptr(mioc
);
1147 command_ind
->Primitive
= (int)awp
->func
;
1148 command_ind
->ReqRefNum
=
1149 ntohs(*(unsigned short *)atp
->tid
);
1150 command_ind
->ReqType
= awp
->func
;
1152 mdata
= gbuf_strip(mdata
);
1153 gbuf_cont(mioc
) = mdata
;
1154 asp_putnext(scb
->gref
, mioc
);
1157 case ASPFUNC_Tickle
:
1158 if (scb
->stat_msg
) {
1159 sess_scb
= asp_scbQ
[awp
->param1
];
1160 if (sess_scb
&& sess_scb
->next_scb
)
1161 sess_scb
= asp_find_scb(
1162 sess_scb
->loc_addr
.socket
, &rem_addr
);
1164 if (sess_scb
->rem_addr
.node
)
1165 asp_untimout(asp_hangup
, sess_scb
);
1166 if (sess_scb
->rem_addr
.node
)
1167 asp_timout(asp_hangup
, sess_scb
, sess_scb
->session_timer
);
1170 dPrintf(D_M_ASP
, D_L_INFO
,
1171 (" : Tickle, %d -> %d, id=%d\n",
1172 ddp
->src_socket
,ddp
->dst_socket
,awp
->param1
));
1175 case ASPFUNC_CloseSess
:
1176 if ( (scb
->sess_id
!= awp
->param1
)
1177 || (scb
->state
== ASPSTATE_Close
)
1178 || (scb
->state
== ASPSTATE_WaitingForCloseSessRsp
)
1179 || (scb
->rem_addr
.net
!= rem_addr
.net
)
1180 || (scb
->rem_addr
.node
!= rem_addr
.node
) ) {
1181 dPrintf(D_M_ASP
, D_L_INFO
,
1182 (" : CLOSE retry, loc=%d, rem=%x.%x.%d\n",
1183 scb
->loc_addr
.socket
,
1186 scb
->rem_addr
.socket
));
1193 * build the CloseSess response to be sent to peer
1194 * when the session is closed by the user.
1196 if (gbuf_cont(mdata
)) {
1197 gbuf_freem(gbuf_cont(mdata
));
1198 gbuf_cont(mdata
) = 0;
1200 gbuf_rdec(mdata
,TOTAL_ATP_HDR_SIZE
);
1201 gbuf_wset(mdata
,TOTAL_ATP_HDR_SIZE
);
1202 NET_NET(ddp
->src_net
, ddp
->dst_net
);
1203 ddp
->src_node
= ddp
->dst_node
;
1204 NET_ASSIGN(ddp
->dst_net
, rem_addr
.net
);
1205 ddp
->dst_node
= rem_addr
.node
;
1206 ddp
->dst_socket
= rem_addr
.socket
;
1210 dPrintf(D_M_ASP
,D_L_INFO
,
1211 (" : CLOSE, loc=%d, rem=%x.%x.%d\n",
1212 scb
->loc_addr
.socket
,
1215 scb
->rem_addr
.socket
));
1217 gbuf_next(mdata
) = 0;
1219 gbuf_freel(scb
->sess_ioc
);
1220 scb
->sess_ioc
= mdata
;
1221 scb
->state
= ASPSTATE_Close
;
1224 * notify upstream of the CloseSess from peer
1229 case ASPFUNC_Attention
:
1230 if ( (scb
->sess_id
!= awp
->param1
)
1231 || (scb
->rem_addr
.net
!= rem_addr
.net
)
1232 || (scb
->rem_addr
.node
!= rem_addr
.node
) ) {
1235 gbuf_set_type(mioc
, MSG_PROTO
);
1236 gbuf_wset(mioc
,sizeof(asp_command_ind_t
));
1237 command_ind
= (asp_command_ind_t
*)gbuf_rptr(mioc
);
1238 command_ind
->Primitive
= (int)awp
->func
;
1239 command_ind
->ReqRefNum
=
1240 ntohs(*(unsigned short *)atp
->tid
);
1241 command_ind
->ReqType
= awp
->func
;
1242 scb
->attn_tid
= *(unsigned short *)atp
->tid
;
1244 gbuf_rdec(mdata
,2); /* attention code */
1246 mdata
= gbuf_strip(mdata
);
1247 gbuf_cont(mioc
) = mdata
;
1248 asp_putnext(scb
->gref
, mioc
);
1252 dPrintf(D_M_ASP
, D_L_WARNING
,
1253 (" : UNKNOWN func, func=%d\n",
1260 else if (iocbp
->ioc_cmd
== AT_ATP_REQUEST_COMPLETE
) {
1261 if (scb
->next_scb
) {
1263 * find the responsible scb
1265 scb
= (asp_scb_t
*)iocbp
->ioc_private
;
1266 if ((scb
== 0) || (scb
->magic_num
!= 222)) {
1267 dPrintf(D_M_ASP
, D_L_ERROR
,
1268 ("asp_ack_reply: CAN'T find scb 1\n"));
1273 dPrintf(D_M_ASP
, D_L_INFO
,
1274 ("asp_ack_reply: RSP, loc=%d, rem=%x.%x.%d, state=%s\n",
1275 scb
->loc_addr
.socket
,
1278 scb
->rem_addr
.socket
,
1279 aspStateStr(scb
->state
)));
1281 switch (scb
->state
) {
1282 case ASPSTATE_Close
:
1284 scb
->rem_addr
.node
= 0;
1287 wakeup(&scb
->event
);
1289 atalk_notify_sel(gref
);
1292 case ASPSTATE_WaitingForGetStatusRsp
:
1294 scb
->state
= ASPSTATE_Idle
;
1295 mx
= gbuf_cont(mioc
);
1296 gbuf_cont(mioc
) = 0;
1297 mdata
= gbuf_cont(mx
);
1299 iocbp
->ioc_cmd
= ASPIOC_GetStatus
;
1300 iocbp
->ioc_count
= 0;
1301 iocbp
->ioc_rval
= mdata
? gbuf_msgsize(mdata
) : 0;
1303 atalk_putnext(gref
, mioc
);
1304 atalk_putnext(gref
, mdata
);
1307 case ASPSTATE_WaitingForOpenSessRsp
:
1309 scb
->state
= ASPSTATE_Idle
;
1310 mx
= gbuf_cont(mioc
);
1311 gbuf_cont(mioc
) = 0;
1312 if (gbuf_cont(mx
)) {
1313 gbuf_freem(gbuf_cont(mx
));
1316 iocbp
->ioc_cmd
= ASPIOC_OpenSession
;
1317 iocbp
->ioc_rval
= 0;
1318 iocbp
->ioc_count
= 0;
1319 atpBDS
= (struct atpBDS
*)gbuf_rptr(mx
);
1320 awp
= (asp_word_t
*)atpBDS
->bdsUserData
;
1323 asp_iocnak(gref
, mioc
, ECONNREFUSED
);
1325 scb
->rem_addr
.node
= scb
->rem_node
;
1326 scb
->rem_addr
.socket
= awp
->func
;
1327 /* bms: need to set the reply_socket for client side too.
1328 This makes ALO atten replies sent by the client work. */
1329 scb
->reply_socket
= scb
->rem_addr
.socket
;
1330 scb
->sess_id
= awp
->param1
;
1332 atalk_putnext(gref
, mioc
);
1333 asp_timout(asp_hangup
, scb
, scb
->session_timer
);
1334 asp_send_tickle(scb
);
1335 dPrintf(D_M_ASP
, D_L_INFO
,
1336 ("asp_ack_reply: CONNECT, loc=%d, rem=%x.%x.%d\n",
1337 scb
->loc_addr
.socket
,
1340 scb
->rem_addr
.socket
));
1344 case ASPSTATE_WaitingForCommandRsp
:
1345 case ASPSTATE_WaitingForWriteRsp
:
1346 case ASPSTATE_WaitingForWriteContinueRsp
:
1347 if (scb
->rem_addr
.node
)
1348 asp_untimout(asp_hangup
, scb
);
1349 NEXT_SEQ_NUM(scb
->snd_seq_num
);
1350 scb
->state
= ASPSTATE_Idle
;
1351 gbuf_set_type(mioc
, MSG_PROTO
);
1352 mx
= gbuf_cont(mioc
);
1353 mdata
= gbuf_cont(mx
);
1354 gbuf_cont(mioc
) = mdata
;
1355 atpBDS
= (struct atpBDS
*)gbuf_rptr(mx
);
1356 cmdreply_ind
= (asp_cmdreply_ind_t
*)gbuf_rptr(mioc
);
1357 cmdreply_ind
->Primitive
= ASPFUNC_CmdReply
;
1358 cmdreply_ind
->CmdResult
= ntohl(*(int *)atpBDS
->bdsUserData
);
1359 gbuf_wset(mioc
,sizeof(asp_cmdreply_ind_t
));
1361 asp_putnext(scb
->gref
, mioc
);
1364 case ASPSTATE_WaitingForCloseSessRsp
:
1366 scb
->state
= ASPSTATE_Close
;
1367 scb
->rem_addr
.node
= 0;
1368 iocbp
->ioc_cmd
= ASPIOC_CloseSession
;
1369 iocbp
->ioc_rval
= 0;
1370 if (gbuf_cont(mioc
)) {
1371 gbuf_freem(gbuf_cont(mioc
));
1372 gbuf_cont(mioc
) = 0;
1374 atalk_putnext(scb
->gref
, mioc
);
1375 atp_cancel_req(scb
->gref
, (unsigned int)scb
->tickle_tid
);
1376 scb
->tickle_tid
= 0;
1380 dPrintf(D_M_ASP
, D_L_WARNING
,
1381 (" : UNKNOWN state, state=%s\n",
1382 aspStateStr(scb
->state
)));
1388 if (scb
->next_scb
) {
1390 * find the responsible scb
1392 scb
= (asp_scb_t
*)iocbp
->ioc_cr
;
1393 if ((scb
== 0) || (scb
->magic_num
!= 222)) {
1394 dPrintf(D_M_ASP
, D_L_ERROR
,
1395 ("asp_ack_reply: CAN'T find scb 2\n"));
1401 switch (scb
->state
) {
1402 case ASPSTATE_Close
:
1403 scb
->rem_addr
.node
= 0;
1412 if (scb
->rem_addr
.node
)
1413 asp_timout(asp_hangup
, scb
, scb
->session_timer
);
1414 } /* asp_ack_reply */
1420 asp_nak_reply(gref
, mioc
)
1421 register gref_t
*gref
;
1422 register gbuf_t
*mioc
;
1424 register asp_scb_t
*scb
;
1425 register ioc_t
*iocbp
;
1427 iocbp
= (ioc_t
*)gbuf_rptr(mioc
);
1429 if (iocbp
->ioc_cmd
== AT_ATP_ISSUE_REQUEST_TICKLE
) {
1431 * no tickle, close session
1433 scb
= (asp_scb_t
*)iocbp
->ioc_cr
;
1436 dPrintf(D_M_ASP
, D_L_WARNING
,
1437 ("tickle_nak: loc=%d, rem=%x.%x.%d, state=%s\n",
1438 scb
->loc_addr
.socket
,
1441 scb
->rem_addr
.socket
,
1442 aspStateStr(scb
->state
)));
1447 scb
= (asp_scb_t
*)gref
->info
;
1453 if (iocbp
->ioc_cmd
== AT_ATP_REQUEST_COMPLETE
) {
1454 if (scb
->next_scb
) {
1456 * find the responsible scb
1458 scb
= (asp_scb_t
*)iocbp
->ioc_private
;
1459 if ((scb
== 0) || (scb
->magic_num
!= 222)) {
1460 dPrintf(D_M_ASP
, D_L_ERROR
,
1461 ("asp_nak_reply: CAN'T find scb 1\n"));
1466 dPrintf(D_M_ASP
, D_L_WARNING
,
1467 ("asp_nak_reply: RSP, loc=%d, rem=%x.%x.%d, state=%s\n",
1468 scb
->loc_addr
.socket
,
1471 scb
->rem_addr
.socket
,
1472 aspStateStr(scb
->state
)));
1474 switch (scb
->state
) {
1475 case ASPSTATE_WaitingForGetStatusRsp
:
1476 iocbp
->ioc_cmd
= ASPIOC_GetStatus
;
1479 case ASPSTATE_WaitingForOpenSessRsp
:
1480 iocbp
->ioc_cmd
= ASPIOC_OpenSession
;
1483 case ASPSTATE_WaitingForCommandRsp
:
1484 case ASPSTATE_WaitingForWriteRsp
:
1485 case ASPSTATE_WaitingForWriteContinueRsp
:
1486 scb
->state
= ASPSTATE_Idle
;
1488 /* last remaining use of MSG_ERROR */
1489 gbuf_set_type(mioc
, MSG_ERROR
);
1490 *gbuf_rptr(mioc
) = (u_char
)EPROTOTYPE
;
1492 if (gbuf_cont(mioc
)) {
1493 gbuf_freem(gbuf_cont(mioc
));
1494 gbuf_cont(mioc
) = 0;
1497 asp_putnext(scb
->gref
, mioc
);
1500 case ASPSTATE_WaitingForCloseSessRsp
:
1501 scb
->state
= ASPSTATE_Close
;
1503 case ASPSTATE_Close
: /* new for PR-2296832 */
1504 scb
->rem_addr
.node
= 0;
1505 iocbp
->ioc_cmd
= ASPIOC_CloseSession
;
1506 iocbp
->ioc_rval
= 0;
1507 if (gbuf_cont(mioc
)) {
1508 gbuf_freem(gbuf_cont(mioc
));
1509 gbuf_cont(mioc
) = 0;
1511 gbuf_set_type(mioc
, MSG_IOCACK
);
1512 atalk_putnext(scb
->gref
, mioc
);
1519 scb
->state
= ASPSTATE_Idle
;
1520 atalk_putnext(gref
, mioc
);
1524 if (scb
->next_scb
) {
1526 * find the responsible scb
1528 scb
= (asp_scb_t
*)iocbp
->ioc_cr
;
1529 if ((scb
== 0) || (scb
->magic_num
!= 222)) {
1530 dPrintf(D_M_ASP
, D_L_ERROR
,
1531 ("asp_nak_reply: CAN'T find scb 2\n"));
1537 switch (scb
->state
) {
1538 case ASPSTATE_Close
:
1539 scb
->rem_addr
.node
= 0;
1545 } /* asp_nak_reply */
1548 * delete scb from the use list
1551 asp_dequeue_scb(scb
)
1555 if (scb
== scb_used_list
) {
1556 if ((scb_used_list
= scb
->next_scb
) != 0)
1557 scb
->next_scb
->prev_scb
= 0;
1559 if ((scb
->prev_scb
->next_scb
= scb
->next_scb
) != 0)
1560 scb
->next_scb
->prev_scb
= scb
->prev_scb
;
1570 StaticProc asp_scb_t
*
1571 asp_find_scb(sock_num
, rem_addr
)
1572 unsigned char sock_num
;
1573 at_inet_t
*rem_addr
;
1576 asp_scb_t
*alt_scb
= 0;
1578 for (scb
= asp_scbQ
[sock_num
]; scb
; scb
= scb
->next_scb
) {
1579 if ((scb
->rem_addr
.net
== rem_addr
->net
)
1580 && (scb
->rem_addr
.node
== rem_addr
->node
)) {
1581 if ((scb
->rem_addr
.socket
== rem_addr
->socket
)
1582 || (scb
->rem_socket
== rem_addr
->socket
))
1584 else if (alt_scb
== 0)
1589 if ((scb
== 0) && ((scb
= alt_scb
) == 0)) {
1590 dPrintf(D_M_ASP
, D_L_ERROR
,
1591 ("asp_find_scb: CAN'T find scb, loc=%d, rem=%x.%x.%d\n",
1605 asp_timout(func
, scb
, seconds
)
1607 register asp_scb_t
*scb
;
1611 register asp_scb_t
*curr_scb
, *prev_scb
;
1616 scb
->tmo_func
= func
;
1617 scb
->tmo_delta
= (seconds
>>SESS_TMO_RES
);
1618 scb
->tmo_cnt
= scb_tmo_cnt
;
1620 if (scb_tmo_list
== 0) {
1621 scb
->next_tmo
= scb
->prev_tmo
= 0;
1627 curr_scb
= scb_tmo_list
;
1631 sum
+= curr_scb
->tmo_delta
;
1632 if (sum
> scb
->tmo_delta
) {
1633 sum
-= curr_scb
->tmo_delta
;
1634 scb
->tmo_delta
-= sum
;
1635 curr_scb
->tmo_delta
-= scb
->tmo_delta
;
1638 prev_scb
= curr_scb
;
1639 if ((curr_scb
= curr_scb
->next_tmo
) == 0) {
1640 scb
->tmo_delta
-= sum
;
1646 scb
->prev_tmo
= prev_scb
;
1647 if ((scb
->next_tmo
= prev_scb
->next_tmo
) != 0)
1648 prev_scb
->next_tmo
->prev_tmo
= scb
;
1649 prev_scb
->next_tmo
= scb
;
1652 scb
->next_tmo
= scb_tmo_list
;
1653 scb_tmo_list
->prev_tmo
= scb
;
1663 __unused asp_tmo_func tmo_func
,
1664 register asp_scb_t
*scb
)
1667 if ((scb
->tmo_cnt
== scb_tmo_cnt
) || (scb
->tmo_func
== 0))
1670 if (scb_tmo_list
== scb
) {
1671 if ((scb_tmo_list
= scb
->next_tmo
) != 0) {
1672 scb_tmo_list
->prev_tmo
= 0;
1673 scb
->next_tmo
->tmo_delta
+= scb
->tmo_delta
;
1675 } else if (scb
->prev_tmo
) {
1676 if ((scb
->prev_tmo
->next_tmo
= scb
->next_tmo
) != 0) {
1677 scb
->next_tmo
->prev_tmo
= scb
->prev_tmo
;
1678 scb
->next_tmo
->tmo_delta
+= scb
->tmo_delta
;
1693 * set the state to Close
1695 scb
->state
= ASPSTATE_Close
;
1696 if (scb
->tickle_tid
) {
1697 atp_cancel_req(scb
->gref
, (unsigned int)scb
->tickle_tid
);
1698 scb
->tickle_tid
= 0;
1702 * notify upstream of the hangup
1704 if (scb
->rem_addr
.node
) {
1706 wakeup(&scb
->event
);
1708 atalk_notify_sel(scb
->gref
);
1713 asp_iocack(gref
, mioc
)
1717 if (gbuf_cont(mioc
))
1718 ((ioc_t
*)gbuf_rptr(mioc
))->ioc_count
= gbuf_msgsize(gbuf_cont(mioc
));
1720 ((ioc_t
*)gbuf_rptr(mioc
))->ioc_count
= 0;
1722 gbuf_set_type(mioc
, MSG_IOCACK
);
1723 atalk_putnext(gref
, mioc
);
1727 asp_iocnak(gref
, mioc
, err
)
1732 ((ioc_t
*)gbuf_rptr(mioc
))->ioc_count
= 0;
1735 ((ioc_t
*)gbuf_rptr(mioc
))->ioc_error
= err
;
1736 ((ioc_t
*)gbuf_rptr(mioc
))->ioc_rval
= -1;
1737 if (gbuf_cont(mioc
)) {
1738 gbuf_freem(gbuf_cont(mioc
));
1739 gbuf_cont(mioc
) = 0;
1742 gbuf_set_type(mioc
, MSG_IOCNAK
);
1743 atalk_putnext(gref
, mioc
);
1747 * the alloc scb routine
1749 StaticProc asp_scb_t
*
1754 asp_scb_t
*scb
, *scb_array
;
1756 if (scb_free_list
== 0) {
1757 if ((m
= gbuf_alloc(SCBS_PER_BLK
*sizeof(asp_scb_t
), PRI_MED
)) == 0)
1758 return (asp_scb_t
*)0;
1759 bzero((char *)gbuf_rptr(m
), SCBS_PER_BLK
*sizeof(asp_scb_t
));
1760 gbuf_cont(m
) = scb_resource_m
;
1762 scb_array
= (asp_scb_t
*)gbuf_rptr(m
);
1763 for (i
=0; i
< SCBS_PER_BLK
-1; i
++)
1764 scb_array
[i
].next_scb
= (asp_scb_t
*)&scb_array
[i
+1];
1765 scb_array
[i
].next_scb
= 0;
1766 scb_free_list
= (asp_scb_t
*)&scb_array
[0];
1769 scb
= scb_free_list
;
1770 scb_free_list
= scb
->next_scb
;
1771 ATEVENTINIT(scb
->event
);
1772 ATEVENTINIT(scb
->delay_event
);
1778 * the free scb routine
1785 bzero((char *)scb
, sizeof(asp_scb_t
));
1786 scb
->next_scb
= scb_free_list
;
1787 scb_free_list
= scb
;
1791 * routine to pass up receive data
1794 asp_putnext(gref
, mproto
)
1801 scb
= (asp_scb_t
*)gref
->info
;
1804 * queue the message.
1806 gbuf_next(mproto
) = 0;
1807 if ((m
= scb
->sess_ioc
) == 0)
1808 scb
->sess_ioc
= mproto
;
1810 while (gbuf_next(m
))
1812 gbuf_next(m
) = mproto
;
1815 if (scb
->rcv_cnt
>= MAX_RCV_CNT
)
1819 wakeup(&scb
->event
);
1820 else if (mproto
== scb
->sess_ioc
)
1821 atalk_notify_sel(gref
);
1826 * The following two routines are direct entries from system
1827 * calls to allow fast sending and recving of ASP data.
1830 /* in ASPputmsg we expect:
1836 ASPFUNC_WriteContinue
1838 bms: Make this callable from the kernel.
1839 If mreq != NULL, then must be called from kernel space and the following apply:
1840 1) *mreq is data to be sent already in mbuf chains.
1841 2) datptr->len = size of data
1844 int ASPputmsg(gref_t
*gref
, strbuf_t
*ctlptr
, strbuf_t
*datptr
, gbuf_t
*mreq
, __unused
int flags
, int *errp
)
1846 int i
, err
, len
, offset
, remain
, size
, copy_len
;
1847 gbuf_t
*mioc
, *mdata
, *mx
;
1852 int nbds
, result
, msize
, Primitive
;
1853 unsigned char *wptr
;
1854 struct atp_set_default
*sd
;
1857 struct atpBDS
*atpBDS
;
1859 union asp_primitives
*primitives
;
1863 if ((scb
= (asp_scb_t
*)gref
->info
) == 0) {
1864 dPrintf(D_M_ASP
, D_L_ERROR
,
1865 ("ASPputmsg: stale handle=0x%x, pid=%d\n",
1866 (u_int
) gref
, gref
->pid
));
1872 if (scb
->state
== ASPSTATE_Close
)
1874 if (scb
->snd_stop
) {
1880 * copy in the control and data info
1883 /* being called from kernel space */
1884 bcopy (ctlptr
, &ctlbuf
, sizeof (strbuf_t
));
1885 bcopy (datptr
, &datbuf
, sizeof (strbuf_t
));
1887 /* being called from user space */
1888 if ((err
= copyin(CAST_USER_ADDR_T(ctlptr
), (caddr_t
)&ctlbuf
, sizeof(ctlbuf
))) != 0)
1890 if ((err
= copyin(CAST_USER_ADDR_T(datptr
), (caddr_t
)&datbuf
, sizeof(datbuf
))) != 0)
1894 /* Radar 5398072: check for bogus length
1895 * Max ASP data is 8 ATP packets
1898 if ((ctlbuf
.len
< 0) || (ctlbuf
.len
> (ATP_DATA_SIZE
* 8))) {
1902 if ((datbuf
.len
< 0) || (datbuf
.len
> (ATP_DATA_SIZE
* 8))) {
1908 * allocate buffer and copy in the control content
1910 if (!(mioc
= gbuf_alloc_wait(ctlbuf
.len
, TRUE
))) {
1911 /* error return should not be possible */
1915 gbuf_set_type(mioc
, MSG_IOCTL
); /* for later, in ATP */
1916 gbuf_wset(mioc
, ctlbuf
.len
);
1919 /* being called from kernel space */
1920 bcopy (ctlbuf
.buf
, gbuf_rptr(mioc
), ctlbuf
.len
);
1922 /* being called from user space */
1923 if ((err
= copyin(CAST_USER_ADDR_T(ctlbuf
.buf
), (caddr_t
)gbuf_rptr(mioc
), ctlbuf
.len
)) != 0) {
1929 iocbp
= (ioc_t
*)gbuf_rptr(mioc
);
1930 primitives
= (union asp_primitives
*)gbuf_rptr(mioc
);
1931 Primitive
= primitives
->Primitive
;
1932 dPrintf(D_M_ASP
, D_L_INFO
,
1933 ("ASPputmsg: %s\n", aspCmdStr(Primitive
)));
1936 * copy in the data content into multiple mbuf clusters if
1937 * required. ATP now expects reply data to be placed in
1938 * standard clusters, not the large external clusters that
1939 * were used previously.
1942 /* set offset for use by some commands */
1943 offset
= (Primitive
== ASPFUNC_CmdReply
) ? 0 : aspCMDsize
;
1946 /* The data from the in-kernel call for use by AFP is passed
1947 * in as one large external cluster. This needs to be copied
1948 * to a chain of standard clusters.
1950 remain
= gbuf_len(mreq
);
1951 dataptr
= mtod(mreq
, caddr_t
);
1953 /* copyin from user space */
1954 remain
= datbuf
.len
;
1955 dataptr
= (caddr_t
)datbuf
.buf
;
1958 /* allocate first buffer */
1959 if (!(mdata
= gbuf_alloc_wait((remain
+ offset
> MCLBYTES
? MCLBYTES
: remain
+ offset
), TRUE
))) {
1960 /* error return should not be possible */
1965 gbuf_wset(mdata
, 0); /* init length to zero */
1966 gbuf_cont(mioc
) = mdata
;
1969 if (remain
+ offset
> MCLBYTES
)
1970 copy_len
= MCLBYTES
- offset
;
1975 bcopy (dataptr
, (gbuf_rptr(mdata
) + offset
), copy_len
);
1976 else if ((err
= copyin(CAST_USER_ADDR_T(dataptr
), (caddr_t
)(gbuf_rptr(mdata
) + offset
), copy_len
)) != 0) {
1980 gbuf_wset(mdata
, (copy_len
+ offset
));
1981 size
+= copy_len
+ offset
;
1982 dataptr
+= copy_len
;
1985 /* allocate the next mbuf */
1986 if ((gbuf_cont(mdata
) = m_get((M_WAIT
), MSG_DATA
)) == 0) {
1991 mdata
= gbuf_cont(mdata
);
1992 MCLGET(mdata
, M_WAIT
);
1993 if (!(mdata
->m_flags
& M_EXT
)) {
2000 mdata
= gbuf_cont(mioc
); /* code further on down expects this to b e set */
2001 mdata
->m_pkthdr
.len
= size
; /* set packet hdr len */
2006 switch (Primitive
) {
2008 case ASPFUNC_Command
:
2010 case ASPFUNC_WriteContinue
:
2011 case ASPFUNC_Attention
:
2013 * build the command/write/write_continue request
2015 wptr
= (unsigned char *)gbuf_rptr(mdata
);
2016 atpBDS
= (struct atpBDS
*)wptr
;
2018 for (i
=0; i
< ATP_TRESP_MAX
; i
++) {
2019 *(unsigned long *)atpBDS
[i
].bdsBuffAddr
= 1;
2020 *(unsigned short *)atpBDS
[i
].bdsBuffSz
= ATP_DATA_SIZE
;
2022 sd
= (struct atp_set_default
*)wptr
;
2023 wptr
+= sizeof(struct atp_set_default
);
2024 sd
->def_retries
= (scb
->cmd_retry
.retries
== -1) ?
2025 ATP_INFINITE_RETRIES
: scb
->cmd_retry
.retries
;
2026 sd
->def_rate
= scb
->cmd_retry
.interval
*TICKS_PER_SEC
;
2027 sd
->def_BDSlen
= atpBDSsize
;
2028 ddp
= (at_ddp_t
*)wptr
;
2029 NET_ASSIGN(ddp
->src_net
, scb
->loc_addr
.net
);
2030 ddp
->src_node
= scb
->loc_addr
.node
;
2031 NET_ASSIGN(ddp
->dst_net
, scb
->rem_addr
.net
);
2032 ddp
->dst_node
= scb
->rem_addr
.node
;
2033 ddp
->dst_socket
= scb
->rem_addr
.socket
;
2034 UAS_ASSIGN(ddp
->checksum
, 0);
2035 atp
= ATP_ATP_HDR(wptr
);
2036 wptr
+= TOTAL_ATP_HDR_SIZE
;
2040 awp
= (asp_word_t
*)atp
->user_bytes
;
2041 awp
->func
= (unsigned char)Primitive
;
2042 awp
->param1
= scb
->sess_id
;
2043 awp
->param2
= htons(scb
->snd_seq_num
);
2044 iocbp
->ioc_private
= (void *)scb
;
2045 iocbp
->ioc_count
= gbuf_len(mdata
);
2046 iocbp
->ioc_rval
= 0;
2047 iocbp
->ioc_cmd
= AT_ATP_ISSUE_REQUEST_DEF
;
2050 * send the command/write/write_continue/attention request
2052 switch (awp
->func
) {
2053 case ASPFUNC_Command
:
2054 scb
->state
= ASPSTATE_WaitingForCommandRsp
;
2057 scb
->state
= ASPSTATE_WaitingForWriteRsp
;
2059 case ASPFUNC_WriteContinue
:
2060 scb
->state
= ASPSTATE_WaitingForWriteContinueRsp
;
2061 awp
->param2
= htons(scb
->wrt_seq_num
);
2063 case ASPFUNC_Attention
:
2064 scb
->state
= ASPSTATE_WaitingForCommandRsp
;
2069 awp
->param2
= htons(*(unsigned short *)gbuf_wptr(mdata
));
2072 dPrintf(D_M_ASP
,D_L_INFO
,
2073 ("ASPputmsg: %s, loc=%d, rem=%x.%x.%d\n",
2074 (awp
->func
== ASPFUNC_Command
? "CommandReq" :
2075 awp
->func
== ASPFUNC_Write
? "WriteReq" :
2076 awp
->func
== ASPFUNC_WriteContinue
? "WriteContinue" :
2077 "AttentionReq"),scb
->loc_addr
.socket
,
2078 NET_VALUE(ddp
->dst_net
),ddp
->dst_node
,ddp
->dst_socket
));
2079 atp_send_req(gref
, mioc
);
2082 case ASPFUNC_CmdReply
:
2084 if (scb
->req_msgq
) {
2086 scb
->req_msgq
= gbuf_next(mx
);
2088 asp_putnext(scb
->gref
, mx
);
2092 result
= primitives
->CmdReplyReq
.CmdResult
;
2093 tid
= primitives
->CmdReplyReq
.ReqRefNum
;
2095 /* Re-use the original mioc mbuf to send the response. */
2096 gbuf_rinc(mioc
,sizeof(void *));
2098 ddp
= (at_ddp_t
*)gbuf_wptr(mioc
);
2099 gbuf_winc(mioc
,DDP_X_HDR_SIZE
);
2100 atp
= (at_atp_t
*)gbuf_wptr(mioc
);
2101 gbuf_winc(mioc
,ATP_HDR_SIZE
);
2102 NET_ASSIGN(ddp
->src_net
, scb
->loc_addr
.net
);
2103 ddp
->src_node
= scb
->loc_addr
.node
;
2104 NET_ASSIGN(ddp
->dst_net
, scb
->rem_addr
.net
);
2105 ddp
->dst_node
= scb
->rem_addr
.node
;
2106 ddp
->dst_socket
= scb
->reply_socket
;
2107 ddp
->type
= DDP_ATP
;
2108 UAS_ASSIGN(ddp
->checksum
, 0);
2109 UAS_ASSIGN(atp
->tid
, htons(tid
));
2110 if (scb
->attn_flag
&& (tid
== scb
->attn_tid
)) {
2118 /* setup the atpBDS struct - only the length field is used,
2119 * except for the first one which contains the bds count in
2122 atpBDS
= (struct atpBDS
*)gbuf_wptr(mioc
);
2123 msize
= mdata
? gbuf_msgsize(mdata
) : 0;
2124 for (nbds
=0; (nbds
< ATP_TRESP_MAX
) && (msize
> 0); nbds
++) {
2125 len
= msize
< ATP_DATA_SIZE
? msize
: ATP_DATA_SIZE
;
2126 msize
-= ATP_DATA_SIZE
;
2127 *(long *)atpBDS
[nbds
].bdsUserData
= 0;
2128 UAL_ASSIGN(atpBDS
[nbds
].bdsBuffAddr
, 1);
2129 UAS_ASSIGN(atpBDS
[nbds
].bdsBuffSz
, len
);
2131 UAS_ASSIGN(atpBDS
[0].bdsDataSz
, nbds
);
2132 *(long *)atpBDS
[0].bdsUserData
= (long)result
;
2133 *(long *)atp
->user_bytes
= (long)result
;
2134 gbuf_winc(mioc
,atpBDSsize
);
2135 dPrintf(D_M_ASP
, D_L_INFO
,
2136 ("ASPputmsg: ATP CmdReplyReq, loc=%d, state=%s, msgsize = %d, result = %d, tid = %d\n",
2137 scb
->loc_addr
.socket
, aspStateStr(scb
->state
),
2138 (mdata
? gbuf_msgsize(mdata
) : 0), result
, tid
));
2139 atp_send_rsp(gref
, mioc
, TRUE
);
2143 /* Not an expected ASPFUNC */
2153 /* bms: make this callable from kernel. reply date is passed back as a mbuf chain in *mreply */
2154 int ASPgetmsg(gref_t
*gref
, strbuf_t
*ctlptr
, strbuf_t
*datptr
, gbuf_t
**mreply
, __unused
int *flags
, int *errp
)
2156 int err
, len
, sum
, rval
;
2157 gbuf_t
*mproto
, *mdata
;
2161 unsigned char get_wait
;
2163 if ((scb
= (asp_scb_t
*)gref
->info
) == 0) {
2164 dPrintf(D_M_ASP
, D_L_ERROR
,
2165 ("ASPgetmsg: stale handle=0x%x, pid=%d\n",
2166 (u_int
) gref
, gref
->pid
));
2172 if (scb
->state
== ASPSTATE_Close
)
2178 while ((mproto
= scb
->sess_ioc
) == 0) {
2180 lck_mtx_assert(atalk_mutex
, LCK_MTX_ASSERT_OWNED
);
2181 err
= msleep(&scb
->event
, atalk_mutex
, PSOCK
| PCATCH
, "aspgetmsg", 0);
2187 if (scb
->state
== ASPSTATE_Close
) {
2192 get_wait
= scb
->get_wait
;
2194 if ((ctlptr
== 0) && (datptr
== 0))
2196 scb
->sess_ioc
= gbuf_next(mproto
);
2197 mdata
= gbuf_cont(mproto
);
2199 /* last remaining use of MSG_ERROR */
2200 if (gbuf_type(mproto
) == MSG_ERROR
) {
2201 err
= (int)gbuf_rptr(mproto
)[0];
2206 * copy in the control and data info
2208 if (mreply
!= NULL
) {
2209 /* called from kernel space */
2210 bcopy (ctlptr
, &ctlbuf
, sizeof(ctlbuf
));
2211 bcopy (datptr
, &datbuf
, sizeof(datbuf
));
2213 /* called from user space */
2214 if ((err
= copyin(CAST_USER_ADDR_T(ctlptr
),
2215 (caddr_t
)&ctlbuf
, sizeof(ctlbuf
))) != 0)
2217 if ((err
= copyin(CAST_USER_ADDR_T(datptr
),
2218 (caddr_t
)&datbuf
, sizeof(datbuf
))) != 0)
2221 if ((datbuf
.maxlen
< 0) || (datbuf
.maxlen
< gbuf_msgsize(mdata
))) {
2222 gbuf_next(mproto
) = scb
->sess_ioc
;
2223 scb
->sess_ioc
= mproto
;
2227 if (get_wait
== 0) {
2229 * this is a hack to support the select() call.
2230 * we're not supposed to dequeue messages in the Streams
2231 * head's read queue this way; but there is no better way.
2233 if (scb
->sess_ioc
!= 0)
2234 atalk_notify_sel(gref
);
2239 * copy out the control content and info
2241 ctlbuf
.len
= gbuf_len(mproto
);
2243 if (mreply
!= NULL
) {
2244 /* called from kernel space */
2245 bcopy (gbuf_rptr(mproto
), ctlbuf
.buf
, ctlbuf
.len
);
2246 bcopy (&ctlbuf
, ctlptr
, sizeof(ctlbuf
));
2248 /* called from user space */
2249 if ((err
= copyout((caddr_t
)gbuf_rptr(mproto
),
2250 CAST_USER_ADDR_T(ctlbuf
.buf
), ctlbuf
.len
)) != 0)
2252 if ((err
= copyout((caddr_t
)&ctlbuf
,
2253 CAST_USER_ADDR_T(ctlptr
), sizeof(ctlbuf
))) != 0)
2258 * copy out the data content and info
2260 for (rval
= 0, sum
= 0; mdata
&& (rval
== 0); mdata
= gbuf_cont(mdata
))
2262 len
= gbuf_len(mdata
);
2264 if ((len
+ sum
) > datbuf
.maxlen
) {
2265 len
= datbuf
.maxlen
- sum
;
2269 if (mreply
== NULL
) {
2270 /* called from user space */
2271 if ((err
= copyout((caddr_t
)gbuf_rptr(mdata
), CAST_USER_ADDR_T(&datbuf
.buf
[sum
]), len
)) != 0)
2278 if (mreply
!= NULL
) {
2279 /* called from kernel space */
2280 bcopy (&datbuf
, datptr
, sizeof(datbuf
));
2282 /* called from user space */
2283 if ((err
= copyout((caddr_t
)&datbuf
, CAST_USER_ADDR_T(datptr
), sizeof(datbuf
))) != 0)
2287 if (mreply
!= NULL
) {
2288 /* called from kernel space */
2289 /* return the reply data in mbufs, so dont free them.
2290 Just free the proto info */
2291 mdata
= gbuf_cont(mproto
);
2293 gbuf_cont(mproto
) = NULL
;
2296 /* called from user space */
2309 gbuf_next(mproto
) = scb
->sess_ioc
;
2310 scb
->sess_ioc
= mproto
;