]> git.saurik.com Git - apple/xnu.git/blame - bsd/netat/asp_proto.c
xnu-123.5.tar.gz
[apple/xnu.git] / bsd / netat / asp_proto.c
CommitLineData
1c79356b
A
1/*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
11 *
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22/*
23 * Copyright (c) 1995 Apple Computer, Inc.
24 *
25 * Change Log:
26 * Created February 20, 1995 by Tuyen Nguyen
27 * Modified for MP, 1996 by Tuyen Nguyen
28 * Modified, March 17, 1997 by Tuyen Nguyen for MacOSX.
29 */
30
31#include <sys/errno.h>
32#include <sys/types.h>
33#include <sys/param.h>
34#include <machine/spl.h>
35#include <sys/systm.h>
36#include <sys/kernel.h>
37#include <sys/proc.h>
38#include <sys/filedesc.h>
39#include <sys/fcntl.h>
40#include <sys/mbuf.h>
41#include <sys/ioctl.h>
42#include <sys/malloc.h>
43#include <sys/socket.h>
44#include <sys/socketvar.h>
45
46#include <net/if.h>
47
48#include <netat/appletalk.h>
49#include <netat/sysglue.h>
50#include <netat/at_pcb.h>
51#include <netat/atp.h>
52#include <netat/ddp.h>
53#include <netat/asp.h>
54#include <netat/at_var.h>
55#include <netat/debug.h>
56
57static int loop_cnt;
58#define CHK_LOOP(str) { \
59 if (loop_cnt++ > 100) { \
60 kprintf("%s", str); \
61 break; \
62 } \
63}
64
65#define atpBDSsize (sizeof(struct atpBDS)*ATP_TRESP_MAX)
66#define aspCMDsize (atpBDSsize+sizeof(struct atp_set_default)+TOTAL_ATP_HDR_SIZE)
67#define SCBS_PER_BLK 16
68#define TICKS_PER_SEC HZ
69#define SESS_TMO_RES 2
70#define DEF_SESS_TMO 120
71#define NEXT_SEQ_NUM(x) (x = (x == 65535) ? 0 : (x + 1))
72#define MAX_RCV_CNT 5
73#define BAD_REMADDR(addr) \
74 ( (*(long *)&scb->rem_addr != *(long *)&addr) \
75 && ((scb->rem_addr.net != addr.net) \
76 || (scb->rem_addr.node != addr.node)) )
77
78int ASPputmsg();
79int ASPgetmsg();
80void asp_init();
81void asp_ack_reply();
82void asp_nak_reply();
83void asp_clock();
84void asp_clock_funnel();
85int asp_open();
86int asp_close();
87int asp_wput();
88void atp_retry_req();
89StaticProc asp_scb_t *asp_find_scb();
90StaticProc asp_scb_t *asp_scb_alloc();
91
92StaticProc void asp_putnext();
93StaticProc void asp_iocack();
94StaticProc void asp_iocnak();
95StaticProc void asp_dequeue_scb();
96StaticProc void asp_scb_free();
97StaticProc void asp_timout();
98StaticProc void asp_untimout();
99StaticProc void asp_hangup();
100StaticProc void asp_send_tickle();
101StaticProc void asp_send_tickle_funnel();
102StaticProc void asp_accept();
103StaticProc int asp_send_req();
104
105extern at_ifaddr_t *ifID_home;
106extern int atp_pidM[];
107extern gref_t *atp_inputQ[];
108gbuf_t *scb_resource_m = 0;
109unsigned char asp_inpC[256];
110asp_scb_t *asp_scbQ[256];
111
112static at_retry_t asp_def_retry = {2, -1, 1};
113static unsigned char scb_tmo_cnt;
114asp_scb_t *scb_used_list;
115static asp_scb_t *scb_tmo_list;
116asp_scb_t *scb_free_list;
117atlock_t aspall_lock, asptmo_lock;
118
119int
120asp_readable(gref)
121 gref_t *gref;
122{
123 return (((asp_scb_t *)gref->info)->sess_ioc ? 1 : 0);
124}
125
126void
127asp_init()
128{
129 scb_tmo_cnt = 1;
130 scb_tmo_list = 0;
131 scb_used_list = 0;
132 scb_free_list = 0;
133 bzero(asp_inpC, sizeof(asp_inpC));
134 bzero(asp_scbQ, sizeof(asp_scbQ));
135}
136
137/*
138 * the open routine allocates a state structure
139 */
140int asp_open(gref)
141 gref_t *gref;
142{
143 int s;
144 asp_scb_t *scb;
145
146 /*
147 * if no asp structure available, return failure
148 */
149 if ((scb = asp_scb_alloc()) == 0)
150 return ENOBUFS;
151
152 /*
153 * initialize the gref data structure
154 */
155 gref->info = (void *)scb;
156 gref->readable = asp_readable;
157
158 /*
159 * initialize the scb data structure
160 */
161 scb->dflag = 1;
162 scb->magic_num = 222;
163 scb->state = ASPSTATE_Idle;
164 scb->pid = gref->pid;
165 scb->gref = gref;
166 scb->session_timer = DEF_SESS_TMO;
167 scb->cmd_retry = asp_def_retry;
168 ATDISABLE(s, aspall_lock);
169 if ((scb->next_scb = scb_used_list) != 0)
170 scb->next_scb->prev_scb = scb;
171 scb_used_list = scb;
172 ATENABLE(s, aspall_lock);
173
174 /*
175 * return success
176 */
177 dPrintf(D_M_ASP, D_L_INFO, ("asp_open: pid=%d\n", scb->pid));
178 return 0;
179} /* asp_open */
180
181/*
182 * the close routine frees all the data structures
183 */
184int
185asp_close(gref)
186 gref_t *gref;
187{
188 int s;
189 unsigned char sock_num;
190 asp_scb_t *scb, *new_scb;
191 gbuf_t *m;
192
193 scb = (asp_scb_t *)gref->info;
194 dPrintf(D_M_ASP, D_L_INFO, ("asp_close: loc=%d\n",
195 scb->loc_addr.socket));
196
197 if (scb->pid && scb->sess_ioc && (scb->dflag != 1)) {
198 /*
199 * send the CloseSess response to peer
200 */
201 if (gbuf_type(scb->sess_ioc) != MSG_PROTO) {
202 ATDISABLE(s, scb->lock);
203 m = scb->sess_ioc;
204 scb->sess_ioc = gbuf_next(m);
205 ATENABLE(s, scb->lock);
206 atp_send_rsp(scb->gref, m, TRUE);
207 }
208 }
209
210 if (scb->atp_state) {
211 sock_num = scb->loc_addr.socket;
212 ATDISABLE(s, aspall_lock);
213 if ((scb->dflag != 1) && scb->stat_msg) {
214 untimeout(atp_retry_req, scb->stat_msg);
215 gbuf_freem(scb->stat_msg);
216 scb->stat_msg = 0;
217 }
218 if (asp_scbQ[sock_num]->next_scb == 0) {
219 asp_scbQ[sock_num] = 0;
220 asp_inpC[sock_num] = 0;
221 ATENABLE(s, aspall_lock);
222 dPrintf(D_M_ASP, D_L_INFO,
223 (" : atp_close(), loc=%d\n", scb->loc_addr.socket));
224 atp_close(gref, 0);
225 } else {
226 asp_inpC[sock_num]--;
227 if (scb == asp_scbQ[sock_num]) {
228 new_scb = scb->next_scb;
229 new_scb->prev_scb = 0;
230 asp_scbQ[sock_num] = new_scb;
231 new_scb->atp_state->atp_gref = new_scb->gref;
232 new_scb->atp_state->pid = new_scb->pid;
233 atp_inputQ[sock_num] = new_scb->gref;
234 } else {
235 if ((scb->prev_scb->next_scb = scb->next_scb) != 0)
236 scb->next_scb->prev_scb = scb->prev_scb;
237 }
238 scb->next_scb = 0;
239 ATENABLE(s, aspall_lock);
240 }
241 } else
242 asp_dequeue_scb(scb);
243
244 /*
245 * free all allocated blocks if any
246 */
247 ATDISABLE(s, scb->lock);
248 if (scb->stat_msg) {
249 gbuf_freem(scb->stat_msg);
250 scb->stat_msg = 0;
251 }
252 if (scb->sess_ioc) {
253 gbuf_freel(scb->sess_ioc);
254 scb->sess_ioc = 0;
255 }
256 if (scb->req_msgq) {
257 gbuf_freel(scb->req_msgq);
258 scb->req_msgq = 0;
259 }
260
261 scb->rem_addr.node = 0;
262 ATENABLE(s, scb->lock);
263
264 /*
265 * stop all timers
266 */
267 scb->tmo_cnt = 0;
268 asp_untimout(asp_hangup, scb);
269 untimeout(asp_send_tickle_funnel, (void *)scb); /* added for 2225395 */
270
271 /*
272 * free the asp session control block
273 */
274 scb->state = ASPSTATE_Close;
275 asp_scb_free(scb);
276 return 0;
277} /* asp_close */
278
279static char *aspStateStr(state)
280 int state;
281{
282 return ((state==ASPSTATE_Close)? "Close":
283 (state==ASPSTATE_Idle)? "Idle":
284 (state==ASPSTATE_WaitingForGetStatusRsp)? "GetStatusRsp":
285 (state==ASPSTATE_WaitingForOpenSessRsp)? "OpenSessRsp":
286 (state==ASPSTATE_WaitingForCommandRsp)? "CmdRsp":
287 (state==ASPSTATE_WaitingForWriteContinue)? "WriteCont":
288 (state==ASPSTATE_WaitingForWriteRsp)? "WriteRsp":
289 (state==ASPSTATE_WaitingForWriteContinueRsp)? "WriteContRsp":
290 (state==ASPSTATE_WaitingForCloseSessRsp)? "CloseSessRsp":
291 "unknown");
292}
293
294static char *aspCmdStr(aspCmd)
295 int aspCmd;
296{
297return ((aspCmd==ASPFUNC_CloseSess)? "CloseSess":
298 (aspCmd==ASPFUNC_Command)? "Command":
299 (aspCmd==ASPFUNC_GetStatus)? "GetStatus":
300 (aspCmd==ASPFUNC_OpenSess)? "OpenSess":
301 (aspCmd==ASPFUNC_Tickle)? "Tickle":
302 (aspCmd==ASPFUNC_Write)? "Write":
303 (aspCmd==ASPFUNC_WriteContinue)? "WriteContinue":
304 (aspCmd==ASPFUNC_Attention)? "Attention":
305 (aspCmd==ASPFUNC_CmdReply)? "CmdReply": "unknown");
306}
307
308static char *aspIOCStr(aspIOC)
309 int aspIOC;
310{
311return (
312 (aspIOC==ASPIOC_ClientBind)? "ClientBind":
313 (aspIOC==ASPIOC_CloseSession)? "CloseSession":
314 (aspIOC==ASPIOC_GetLocEntity)? "GetLocEntity":
315 (aspIOC==ASPIOC_GetRemEntity)? "GetRemEntity":
316 (aspIOC==ASPIOC_GetSession)? "GetSession":
317 (aspIOC==ASPIOC_GetStatus)? "GetStatus":
318 (aspIOC==ASPIOC_ListenerBind)? "ListenerBind":
319 (aspIOC==ASPIOC_OpenSession)? "OpenSession":
320 (aspIOC==ASPIOC_StatusBlock)? "StatusBlock":
321 (aspIOC==ASPIOC_SetPid)? "SetPid":
322 (aspIOC==ASPIOC_GetSessId)? "GetSessId":
323 (aspIOC==ASPIOC_EnableSelect)? "EnableSelect":
324 (aspIOC==ASPIOC_Look)? "Look":
325 "unknown"
326 );
327}
328
329#ifdef AT_MBUF_TRACE
330
331static char mbuf_str[100];
332char *mbuf_totals()
333{
334 sprintf(mbuf_str,
335 /*
336 "dat = %d, prot = %d, ioc = %d, err = %d, hu = %d, ack = %d, nak = %d, ctl = %d",
337 */
338 "dat = %d, prot = %d, ioc = %d, ctl = %d",
339 mbstat.m_mtypes[MSG_DATA], mbstat.m_mtypes[MSG_PROTO], mbstat.m_mtypes[MSG_IOCTL],
340 /*
341 mbstat.m_mtypes[MSG_ERROR], mbstat.m_mtypes[MSG_HANGUP], mbstat.m_mtypes[MSG_IOCACK],
342 mbstat.m_mtypes[MSG_IOCNAK],
343 */
344 mbstat.m_mtypes[MSG_CTL]);
345 return(&mbuf_str[0]);
346}
347
348void trace_beg(str, m)
349 char *str;
350 gbuf_t *m;
351{
352 int i = 0, j = 0;
353 gbuf_t *mdata, *mchain;
354
355 if (m)
356 for (i = 0, j = 0, mdata = m, mchain = m; mdata; i++) {
357 mdata = gbuf_cont(mdata);
358 if (!mdata && mchain) {
359 mdata = gbuf_next(mchain);
360 mchain = mdata;
361 j++;
362 }
363 }
364 dPrintf(D_M_ASP, D_L_TRACE,
365 ("%s: %s, m# = %d, c# = %d\n", str, mbuf_totals(), i, j));
366}
367
368void trace_end(str)
369 char *str;
370{
371 dPrintf(D_M_ASP, D_L_TRACE,
372 (" %s: %s\n", str, mbuf_totals()));
373}
374#endif AT_MBUF_TRACE
375
376/*
377 * the write routine
378 */
379int asp_wput(gref, m)
380 gref_t *gref;
381 gbuf_t *m;
382{
383 int s, err;
384 unsigned char sockSav, sock_num;
385 gbuf_t *mioc, *mdata;
386 ioc_t *iocbp;
387 asp_scb_t *scb, *server_scb, *curr_scb;
388 at_inet_t *addr;
389 asp_word_t aw;
390 union asp_primitives *primitives;
391 asp_status_cmd_t *status_cmd;
392 asp_open_cmd_t *open_cmd;
393 at_retry_t Retry;
394
395 scb = (asp_scb_t *)gref->info;
396 if (scb->dflag == 0) {
397 atp_wput(gref, m);
398 return 0;
399 }
400
401 if (gbuf_type(m) != MSG_IOCTL) {
402 dPrintf(D_M_ASP, D_L_WARNING,
403 ("asp_wput: UNKNOWN message, type=%d\n",
404 gbuf_type(m)));
405 gbuf_freem(m);
406 return 0;
407 }
408
409 mioc = m;
410 iocbp = (ioc_t *)gbuf_rptr(mioc);
411
412 dPrintf(D_M_ASP_LOW, D_L_INFO,
413 ("asp_wput: %s, loc=%d, state=%s\n",
414 aspIOCStr(iocbp->ioc_cmd), scb->loc_addr.socket,
415 aspStateStr(scb->state)));
416
417 switch (iocbp->ioc_cmd) {
418 case ASPIOC_CloseSession:
419 if ((scb->state == ASPSTATE_Close) || (scb->rem_addr.node == 0))
420 break;
421
422 Retry.retries = 3;
423 Retry.interval = 1;
424 aw.func = ASPFUNC_CloseSess;
425 aw.param1 = scb->sess_id;
426 aw.param2 = 0;
427 iocbp->ioc_private = (void *)scb;
428 scb->ioc_wait = (unsigned char)(iocbp->ioc_cmd & 0xff);
429 iocbp->ioc_cmd = AT_ATP_ISSUE_REQUEST;
430 asp_send_req(gref, mioc, &scb->rem_addr, &Retry, &aw,
431 0, ASPSTATE_WaitingForCloseSessRsp, 0x01);
432 return 0;
433
434 case ASPIOC_ClientBind:
435 /*
436 * open an ATP channel
437 */
438 if ((err = atp_open(gref, 0)) != 0) {
439 asp_iocnak(gref, mioc, err);
440 return 0;
441 }
442 scb->atp_state = (atp_state_t *)gref->info;
443 scb->atp_state->pid = scb->pid;
444 /*
445 * bind to any available socket
446 */
447 scb->dflag = 2;
448 sockSav = scb->dflag;
449 if ((sock_num = (at_socket)atp_bind(gref, 0, &sockSav)) == 0) {
450 scb->atp_state = (atp_state_t *)0;
451 atp_close(gref, 0);
452 gref->info = (void *)scb;
453 asp_iocnak(gref, mioc, EINVAL);
454 return 0;
455 }
456 gref->info = (void *)scb;
457 asp_dequeue_scb(scb);
458 scb->atp_state->dflag = scb->dflag;
459 scb->loc_addr.socket = sock_num;
460 asp_scbQ[sock_num] = scb;
461 asp_inpC[sock_num]++;
462 atp_pidM[sock_num] = 0;
463 break;
464
465 case ASPIOC_ListenerBind:
466 /*
467 * open an ATP channel
468 */
469 if ((err = atp_open(gref, 0)) != 0) {
470 asp_iocnak(gref, mioc, err);
471 return 0;
472 }
473 scb->atp_state = (atp_state_t *)gref->info;
474 scb->atp_state->pid = scb->pid;
475 /*
476 * bind to any available socket
477 */
478 if ((sock_num = (at_socket)atp_bind(gref, 0, 0)) == 0) {
479 scb->atp_state = (atp_state_t *)0;
480 atp_close(gref, 0);
481 gref->info = (void *)scb;
482 asp_iocnak(gref, mioc, EINVAL);
483 return 0;
484 }
485 gref->info = (void *)scb;
486 asp_dequeue_scb(scb);
487 scb->atp_state->dflag = scb->dflag;
488 scb->loc_addr.socket = sock_num;
489 asp_scbQ[sock_num] = scb;
490 asp_inpC[sock_num]++;
491 if (gbuf_cont(mioc))
492 *(at_inet_t *)gbuf_rptr(gbuf_cont(mioc)) = scb->loc_addr;
493 break;
494
495 case ASPIOC_GetLocEntity:
496 if ((gbuf_cont(mioc) == 0) || (scb->atp_state == 0)) {
497 asp_iocnak(gref, mioc, EPROTO);
498 return 0;
499 }
500 *(at_inet_t *)gbuf_rptr(gbuf_cont(mioc)) = scb->loc_addr;
501 break;
502
503 case ASPIOC_GetRemEntity:
504 if ((gbuf_cont(mioc) == 0) || (scb->atp_state == 0)) {
505 asp_iocnak(gref, mioc, EPROTO);
506 return 0;
507 }
508 *(at_inet_t *)gbuf_rptr(gbuf_cont(mioc)) = scb->rem_addr;
509 break;
510
511 case ASPIOC_GetSession:
512 if ((mdata = gbuf_cont(mioc)) == 0) {
513 asp_iocnak(gref, mioc, EPROTO);
514 return 0;
515 }
516 addr = (at_inet_t *)gbuf_rptr(mdata);
517 scb->tickle_interval = (unsigned short)addr->node;
518 scb->session_timer = addr->net;
519 server_scb = asp_scbQ[addr->socket];
520/*### LD 10/28/97: changed to make sure we're not accessing a null server_scb */
521 if (server_scb == 0) {
522 asp_iocnak(gref, mioc, EPROTO);
523 return 0;
524 }
525 if (server_scb->sess_ioc == 0) {
526 asp_iocnak(gref, mioc, EPROTO);
527 return 0;
528 }
529
530 /*
531 * open an ATP channel
532 */
533 if ((err = atp_open(gref, 0)) != 0) {
534 gref->info = (void *)scb;
535 asp_iocnak(gref, mioc, err);
536 return 0;
537 }
538 scb->atp_state = (atp_state_t *)gref->info;
539 scb->atp_state->pid = scb->pid;
540 /*
541 * bind to any available socket
542 */
543 scb->dflag = 3;
544 sockSav = scb->dflag;
545 if ((sock_num = (at_socket)atp_bind(gref, 0, &sockSav)) == 0) {
546 atp_close(gref, 0);
547 asp_dequeue_scb(scb);
548 ATDISABLE(s, aspall_lock);
549 sock_num = sockSav;
550 scb->loc_addr.socket = sock_num;
551 for (curr_scb = asp_scbQ[sock_num];
552 curr_scb->next_scb; curr_scb = curr_scb->next_scb) ;
553 scb->prev_scb = curr_scb;
554 curr_scb->next_scb = scb;
555 scb->atp_state = curr_scb->atp_state;
556 ATENABLE(s, aspall_lock);
557 } else {
558 asp_dequeue_scb(scb);
559 ATDISABLE(s, aspall_lock);
560 scb->loc_addr.socket = sock_num;
561 asp_scbQ[sock_num] = scb;
562 scb->atp_state->dflag = scb->dflag;
563 ATENABLE(s, aspall_lock);
564 }
565 gref->info = (void *)scb;
566 asp_inpC[sock_num]++;
567 gbuf_cont(mioc) = 0;
568 asp_accept(server_scb, scb, mdata);
569 break;
570
571 case ASPIOC_GetStatus:
572 if ((mdata = gbuf_cont(mioc)) == 0) {
573 asp_iocnak(gref, mioc, EINVAL);
574 return 0;
575 }
576 gbuf_cont(mioc) = 0;
577 status_cmd = (asp_status_cmd_t *)gbuf_rptr(mdata);
578 aw.func = ASPFUNC_GetStatus;
579 aw.param1 = 0;
580 aw.param2 = 0;
581 scb->ioc_wait = (unsigned char)(iocbp->ioc_cmd & 0xff);
582 iocbp->ioc_cmd = AT_ATP_ISSUE_REQUEST_DEF;
583 asp_send_req(gref, mioc, &status_cmd->SLSEntityIdentifier,
584 &status_cmd->Retry, &aw, 1, ASPSTATE_WaitingForGetStatusRsp, 0xff);
585 gbuf_freeb(mdata);
586 return 0;
587
588 case ASPIOC_OpenSession:
589 if ((mdata = gbuf_cont(mioc)) == 0) {
590 asp_iocnak(gref, mioc, EINVAL);
591 return 0;
592 }
593 gbuf_cont(mioc) = 0;
594 open_cmd = (asp_open_cmd_t *)gbuf_rptr(mdata);
595 scb->svc_addr = open_cmd->SLSEntityIdentifier;
596 scb->rem_addr = scb->svc_addr;
597 scb->rem_node = scb->rem_addr.node;
598 scb->rem_addr.node = 0;
599 scb->tickle_interval = open_cmd->TickleInterval;
600 scb->session_timer = open_cmd->SessionTimer;
601 aw.func = ASPFUNC_OpenSess;
602 aw.param1 = scb->loc_addr.socket;
603 aw.param2 = ASP_Version;
604 scb->ioc_wait = (unsigned char)(iocbp->ioc_cmd & 0xff);
605 iocbp->ioc_cmd = AT_ATP_ISSUE_REQUEST_DEF;
606 asp_send_req(gref, mioc, &open_cmd->SLSEntityIdentifier,
607 &open_cmd->Retry, &aw, 1, ASPSTATE_WaitingForOpenSessRsp, 0x01);
608 gbuf_freeb(mdata);
609 return 0;
610
611 case ASPIOC_StatusBlock:
612 /*
613 * save the server status block
614 */
615 if (scb->stat_msg)
616 gbuf_freem(scb->stat_msg);
617 scb->stat_msg = gbuf_cont(mioc);
618 gbuf_cont(mioc) = 0;
619 break;
620
621 /* *** Does scb->pid get used in a packet header,
622 and if so is it in ASP, or in ATP?
623 If not, do we need this call for anything?
624 (cap does currently use it in _ANS code.)
625 *** */
626 case ASPIOC_SetPid:
627 if (gbuf_cont(mioc) == 0) {
628 asp_iocnak(gref, mioc, EINVAL);
629 return 0;
630 }
631 scb->pid = *(int *)gbuf_rptr(gbuf_cont(mioc));
632 break;
633
634 case ASPIOC_GetSessId:
635 if (gbuf_cont(mioc) == 0) {
636 asp_iocnak(gref, mioc, EINVAL);
637 return 0;
638 }
639 *(gref_t **)gbuf_rptr(gbuf_cont(mioc)) = gref;
640 break;
641
642 case ASPIOC_Look:
643 if (gbuf_cont(mioc) == 0) {
644 asp_iocnak(gref, mioc, EINVAL);
645 return 0;
646 }
647 if (scb->sess_ioc) {
648 primitives = (union asp_primitives *)gbuf_rptr(scb->sess_ioc);
649 if (primitives->Primitive == ASPFUNC_CmdReply)
650 *(int *)gbuf_rptr(gbuf_cont(mioc)) = 0;
651 else
652 *(int *)gbuf_rptr(gbuf_cont(mioc)) = 1;
653 } else
654 *(int *)gbuf_rptr(gbuf_cont(mioc)) = -1;
655 break;
656
657 case DDP_IOC_GET_CFG:
658 {
659 struct atp_state *atp = (struct atp_state *)gref->info;
660 if (atp->dflag)
661 atp = atp->atp_msgq;
662
663 if (gbuf_cont(mioc) == 0) {
664 asp_iocnak(gref, mioc, EINVAL);
665 return 0;
666 }
667 /* *** borrowed from ddp_proto.c to handle DDP_IOC_GET_CFG
668 on atp fd *** */
669 scb->state = ASPSTATE_Idle;
670 {
671 /* *** was ddp_get_cfg() *** */
672 ddp_addr_t *cfgp =
673 (ddp_addr_t *)gbuf_rptr(gbuf_cont(mioc));
674 cfgp->inet.net = ifID_home->ifThisNode.s_net;
675 cfgp->inet.node = ifID_home->ifThisNode.s_node;
676 cfgp->inet.socket = atp->atp_socket_no;
677 cfgp->ddptype = DDP_ATP;
678 }
679 gbuf_wset(gbuf_cont(mioc), sizeof(at_inet_t));
680 }
681 break;
682
683 default:
684 asp_iocnak(gref, mioc, EINVAL);
685 return 0;
686 }
687
688 asp_iocack(gref, mioc);
689 return 0;
690} /* asp_wput */
691
692/*
693 * send request routine
694 */
695StaticProc int
696asp_send_req(gref, mioc, dest, retry, awp, xo, state, bitmap)
697 gref_t *gref;
698 gbuf_t *mioc;
699 at_inet_t *dest;
700 at_retry_t *retry;
701 asp_word_t *awp;
702 unsigned char xo;
703 unsigned char state;
704 unsigned char bitmap;
705{
706 int i;
707 gbuf_t *mdata;
708 ioc_t *iocbp;
709 struct atp_set_default *sd;
710 at_ddp_t *ddp;
711 at_atp_t *atp;
712 struct atpBDS *atpBDS;
713 asp_scb_t *scb = (asp_scb_t *)gref->info;
714
715 /*
716 * allocate an ATP buffer for the request
717 */
718 if ((gbuf_cont(mioc) = gbuf_alloc(aspCMDsize, PRI_MED)) == 0) {
719 if (awp->func == ASPFUNC_Tickle)
720 gbuf_freem(mioc);
721 else
722 asp_iocnak(gref, mioc, ENOBUFS);
723 dPrintf(D_M_ASP, D_L_WARNING,
724 ("asp_send_req: ENOBUFS, loc=%d\n", scb->loc_addr.socket));
725
726 return -1;
727 }
728 mdata = gbuf_cont(mioc);
729 iocbp = (ioc_t *)gbuf_rptr(mioc);
730
731 /*
732 * build the request
733 */
734 atpBDS = (struct atpBDS *)gbuf_rptr(mdata);
735 gbuf_wset(mdata,atpBDSsize);
736 for (i=0; i < ATP_TRESP_MAX; i++) {
737 *(unsigned long *)atpBDS[i].bdsBuffAddr = 1;
738 *(unsigned short *)atpBDS[i].bdsBuffSz = ATP_DATA_SIZE;
739 }
740 sd = (struct atp_set_default *)gbuf_wptr(mdata);
741 gbuf_winc(mdata,sizeof(struct atp_set_default));
742 sd->def_retries = (retry->retries == -1) ?
743 ATP_INFINITE_RETRIES : retry->retries;
744 sd->def_rate = retry->interval*TICKS_PER_SEC;
745 sd->def_BDSlen = atpBDSsize;
746 ddp = (at_ddp_t *)gbuf_wptr(mdata);
747 NET_ASSIGN(ddp->src_net, scb->loc_addr.net);
748 ddp->src_node = scb->loc_addr.node;
749 NET_ASSIGN(ddp->dst_net, dest->net);
750 ddp->dst_node = dest->node;
751 ddp->dst_socket = dest->socket;
752 UAS_ASSIGN(ddp->checksum, 0);
753 atp = ATP_ATP_HDR(gbuf_wptr(mdata));
754 atp->xo = xo;
755 atp->xo_relt = xo;
756 atp->bitmap = bitmap;
757 gbuf_winc(mdata,TOTAL_ATP_HDR_SIZE);
758 *(asp_word_t *)atp->user_bytes = *awp;
759 iocbp->ioc_count = gbuf_len(mdata);
760 iocbp->ioc_rval = 0;
761
762 /*
763 * send the request
764 */
765 scb->state = state;
766 dPrintf(D_M_ASP, D_L_INFO,
767 ("asp_send_req: %s, loc=%d, rem= %d, len=%d, state=%s\n",
768 aspCmdStr(awp->func),
769 scb->loc_addr.socket, ddp->dst_socket, iocbp->ioc_count,
770 aspStateStr(scb->state)));
771
772 atp_send_req(gref, mioc);
773 return 0;
774}
775
776/*
777 * send tickle routine - funnelled version
778 */
779StaticProc void
780asp_send_tickle_funnel(scb)
781 asp_scb_t *scb;
782{
783 thread_funnel_set(network_flock, TRUE);
784 asp_send_tickle(scb);
785 thread_funnel_set(network_flock, FALSE);
786}
787
788
789/*
790 * send tickle routine
791 */
792StaticProc void
793asp_send_tickle(scb)
794 asp_scb_t *scb;
795{
796 gbuf_t *mioc;
797 at_retry_t retry;
798 asp_word_t aw;
799 at_inet_t *dest;
800
801
802 /*
803 * make sure the connection is still there
804 */
805 if (scb->rem_addr.node == 0) {
806 return;
807 }
808
809 if ((mioc = gbuf_alloc(sizeof(ioc_t), PRI_HI)) == 0) {
810 dPrintf(D_M_ASP, D_L_WARNING,
811 ("asp_send_tickle: ENOBUFS 0, loc=%d, rem=%d\n",
812 scb->loc_addr.socket,scb->rem_addr.socket));
813 timeout(asp_send_tickle_funnel, (void *)scb, 10);
814 return;
815 }
816 gbuf_wset(mioc,sizeof(ioc_t));
817 gbuf_set_type(mioc, MSG_IOCTL);
818
819 dest = scb->svc_addr.node ?
820 (at_inet_t *)&scb->svc_addr : (at_inet_t *)&scb->rem_addr;
821 retry.interval = scb->tickle_interval;
822 retry.retries = -1;
823 retry.backoff = 1;
824 aw.func = ASPFUNC_Tickle;
825 aw.param1 = scb->sess_id;
826 aw.param2 = 0;
827 ((ioc_t *)gbuf_rptr(mioc))->ioc_cr = (void *)scb;
828 ((ioc_t *)gbuf_rptr(mioc))->ioc_cmd = AT_ATP_ISSUE_REQUEST_TICKLE;
829
830 if (asp_send_req(scb->gref, mioc, dest, &retry, &aw, 0, scb->state, 0)) {
831 dPrintf(D_M_ASP, D_L_WARNING,
832 ("asp_send_tickle: ENOBUFS 1, loc=%d, rem=%d\n",
833 scb->loc_addr.socket,scb->rem_addr.socket));
834
835 timeout(asp_send_tickle_funnel, (void *)scb, 10);
836 return;
837 }
838}
839
840/*
841 * accept connection routine
842 */
843StaticProc void
844asp_accept(scb, sess_scb, m)
845 asp_scb_t *scb;
846 asp_scb_t *sess_scb;
847 gbuf_t *m;
848{
849 int s;
850 gbuf_t *mdata;
851 at_ddp_t *ddp;
852 at_atp_t *atp;
853 asp_word_t *awp;
854 at_inet_t rem_addr;
855
856 mdata = scb->sess_ioc;
857 ddp = (at_ddp_t *)gbuf_rptr(mdata);
858 atp = (at_atp_t *)(gbuf_rptr(mdata) + DDP_X_HDR_SIZE);
859 rem_addr.net = NET_VALUE(ddp->src_net);
860 rem_addr.node = ddp->src_node;
861 rem_addr.socket = ddp->src_socket;
862 awp = (asp_word_t *)atp->user_bytes;
863
864 sess_scb->loc_addr.net = NET_VALUE(ddp->dst_net);
865 sess_scb->loc_addr.node = ddp->dst_node;
866 NET_ASSIGN(ddp->src_net, sess_scb->loc_addr.net);
867 ddp->src_node = sess_scb->loc_addr.node;
868 NET_ASSIGN(ddp->dst_net, rem_addr.net);
869 ddp->dst_node = rem_addr.node;
870 ddp->dst_socket = rem_addr.socket;
871
872 sess_scb->sess_id = sess_scb->loc_addr.socket;
873 sess_scb->rem_socket = rem_addr.socket;
874 sess_scb->rem_addr = rem_addr;
875 sess_scb->rem_addr.socket = awp->param1;
876 sess_scb->reply_socket = sess_scb->rem_addr.socket;
877 awp->func = sess_scb->loc_addr.socket;
878 awp->param1 = sess_scb->sess_id;
879 awp->param2 = 0;
880 gbuf_freeb(m);
881 ATDISABLE(s, scb->lock);
882 scb->sess_ioc = gbuf_next(mdata);
883 ATENABLE(s, scb->lock);
884 gbuf_next(mdata) = 0;
885 asp_timout(asp_hangup, sess_scb, sess_scb->session_timer);
886 atp_send_rsp(scb->gref, mdata, TRUE);
887 asp_send_tickle(sess_scb);
888 dPrintf(D_M_ASP, D_L_INFO,
889 ("asp_accept: ACCEPT connect request, loc=%d, rem=%x.%x.%d\n",
890 sess_scb->loc_addr.socket,
891 sess_scb->rem_addr.net,
892 sess_scb->rem_addr.node,sess_scb->rem_addr.socket));
893} /* asp_accept */
894
895/*
896 * timer routine - funneled version
897 */
898void asp_clock_funnel(arg)
899 void *arg;
900{
901 thread_funnel_set(network_flock, TRUE);
902 asp_clock(arg);
903 thread_funnel_set(network_flock, FALSE);
904}
905
906/*
907 * timer routine
908 */
909void asp_clock(arg)
910 void *arg;
911{
912 int s;
913 asp_scb_t *scb;
914 void (*tmo_func)();
915
916 ATDISABLE(s, asptmo_lock);
917 if (scb_tmo_list)
918 scb_tmo_list->tmo_delta--;
919 while (((scb = scb_tmo_list) != 0) && (scb_tmo_list->tmo_delta == 0)) {
920 if ((scb_tmo_list = scb->next_tmo) != 0)
921 scb_tmo_list->prev_tmo = 0;
922 if ((tmo_func = scb->tmo_func) != 0) {
923 scb->tmo_func = 0;
924 ATENABLE(s, asptmo_lock);
925 (*tmo_func)(scb);
926 ATDISABLE(s, asptmo_lock);
927 }
928 }
929 ATENABLE(s, asptmo_lock);
930
931 if (++scb_tmo_cnt == 0) scb_tmo_cnt++;
932 timeout(asp_clock_funnel, (void *)arg, (1<<SESS_TMO_RES)*TICKS_PER_SEC);
933
934}
935
936/*
937 * ACK reply routine
938 */
939void
940asp_ack_reply(gref, mioc)
941 register gref_t *gref;
942 register gbuf_t *mioc;
943{
944 int s;
945 int len, msize, nbds;
946 register gbuf_t *mdata, *m, *mx;
947 struct atpBDS *atpBDS;
948 at_ddp_t *ddp;
949 at_atp_t *atp;
950 register asp_scb_t *scb, *sess_scb;
951 register ioc_t *iocbp;
952 register asp_word_t *awp;
953 register asp_command_ind_t *command_ind;
954 register asp_cmdreply_ind_t *cmdreply_ind;
955 at_inet_t rem_addr;
956
957 iocbp = (ioc_t *)gbuf_rptr(mioc);
958
959 if (iocbp->ioc_cmd == AT_ATP_ISSUE_REQUEST_TICKLE) {
960 /*
961 * ignore the ack for the tickle request
962 */
963 scb = (asp_scb_t *)iocbp->ioc_cr;
964 scb->tickle_tid = (unsigned short)iocbp->ioc_rval;
965 gbuf_freem(mioc);
966 return;
967 }
968
969 scb = (asp_scb_t *)gref->info;
970 if (scb == 0) {
971 gbuf_freem(mioc);
972 return;
973 }
974
975 if (iocbp->ioc_cmd == AT_ATP_GET_POLL) {
976 /*
977 * if no data, just drop the request
978 */
979 if ((mdata = gbuf_cont(mioc)) == 0) {
980 gbuf_freeb(mioc);
981 return;
982 }
983
984 gbuf_set_type(mioc, MSG_IOCTL);
985 ddp = (at_ddp_t *)gbuf_rptr(mdata);
986 gbuf_rinc(mdata,DDP_X_HDR_SIZE);
987 atp = (at_atp_t *)gbuf_rptr(mdata);
988 gbuf_rinc(mdata,ATP_HDR_SIZE);
989 rem_addr.net = NET_VALUE(ddp->src_net);
990 rem_addr.node = ddp->src_node;
991 rem_addr.socket = ddp->src_socket;
992 awp = (asp_word_t *)atp->user_bytes;
993
994 if (scb->next_scb) {
995 /*
996 * find the responsible scb
997 */
998 if ((scb = asp_find_scb(scb->loc_addr.socket, &rem_addr)) == 0) {
999 gbuf_freem(mioc);
1000 return;
1001 }
1002 }
1003 dPrintf(D_M_ASP, D_L_INFO,
1004 ("asp_ack_reply: %s, loc=%d, rem=%x.%x.%d\n",
1005 aspCmdStr(awp->func),scb->loc_addr.socket,
1006 NET_VALUE(ddp->src_net) ,ddp->src_node,ddp->src_socket));
1007
1008 if (scb->rem_addr.node)
1009 asp_untimout(asp_hangup, scb);
1010
1011 switch (awp->func) {
1012 case ASPFUNC_GetStatus:
1013 /*
1014 * ignore if this is not a server socket
1015 */
1016 mx = 0;
1017 if ((scb->dflag != 1) || (scb->stat_msg
1018 && ((mx = gbuf_dupb(scb->stat_msg)) == 0)))
1019 break;
1020 gbuf_freeb(mioc);
1021
1022 /*
1023 * send the status block
1024 */
1025 if (gbuf_cont(mdata)) {
1026 gbuf_freem(gbuf_cont(mdata));
1027 gbuf_cont(mdata) = 0;
1028 }
1029 gbuf_rdec(mdata,TOTAL_ATP_HDR_SIZE);
1030 if ((m = gbuf_alloc( (TOTAL_ATP_HDR_SIZE+atpBDSsize), PRI_MED)) == 0) {
1031 gbuf_freem(mdata);
1032 gbuf_freeb(mx);
1033 goto l_done;
1034 }
1035 bcopy(gbuf_rptr(mdata), gbuf_rptr(m), TOTAL_ATP_HDR_SIZE);
1036 gbuf_freeb(mdata);
1037 mdata = m;
1038 ddp = (at_ddp_t *)gbuf_rptr(mdata);
1039 gbuf_wset(mdata,DDP_X_HDR_SIZE);
1040 atp = (at_atp_t *)gbuf_wptr(mdata);
1041 gbuf_winc(mdata,ATP_HDR_SIZE);
1042 awp = (asp_word_t *)atp->user_bytes;
1043 NET_NET(ddp->src_net, ddp->dst_net);
1044 ddp->src_node = ddp->dst_node;
1045 NET_ASSIGN(ddp->dst_net, rem_addr.net);
1046 ddp->dst_node = rem_addr.node;
1047 ddp->dst_socket = rem_addr.socket;
1048 UAS_ASSIGN(ddp->checksum, 0);
1049 atpBDS = (struct atpBDS *)gbuf_wptr(mdata);
1050 msize = mx ? gbuf_msgsize(mx) : 0;
1051 for (nbds=0; (nbds < ATP_TRESP_MAX) && (msize > 0); nbds++) {
1052 len = msize < ATP_DATA_SIZE ? msize : ATP_DATA_SIZE;
1053 msize -= ATP_DATA_SIZE;
1054 *(long *)atpBDS[nbds].bdsUserData = 0;
1055 UAL_ASSIGN(atpBDS[nbds].bdsBuffAddr, 1);
1056 UAS_ASSIGN(atpBDS[nbds].bdsBuffSz, len);
1057 }
1058 UAS_ASSIGN(atpBDS[0].bdsDataSz, nbds);
1059 gbuf_winc(mdata,atpBDSsize);
1060 gbuf_cont(mdata) = mx;
1061 atp_send_rsp(gref, mdata, FALSE);
1062 goto l_done;
1063
1064 case ASPFUNC_OpenSess:
1065 /*
1066 * ignore if server is not ready
1067 */
1068 if ((scb->dflag != 1) || (scb->stat_msg == 0))
1069 break;
1070 gbuf_freeb(mioc);
1071
1072 if (gbuf_cont(mdata)) {
1073 gbuf_freem(gbuf_cont(mdata));
1074 gbuf_cont(mdata) = 0;
1075 }
1076 gbuf_rdec(mdata,TOTAL_ATP_HDR_SIZE);
1077 gbuf_wset(mdata,TOTAL_ATP_HDR_SIZE);
1078 if (awp->param2 != ASP_Version) {
1079 /*
1080 * bad version number, send the OpenSession response
1081 */
1082 awp->func = 0;
1083 awp->param1 = 0;
1084 awp->param2 = (unsigned short)ASPERR_BadVersNum;
1085 dPrintf(D_M_ASP, D_L_INFO,
1086 (" : version=%d\n",
1087 ASPERR_BadVersNum));
1088
1089 NET_NET(ddp->src_net, ddp->dst_net);
1090 ddp->src_node = ddp->dst_node;
1091 NET_ASSIGN(ddp->dst_net, rem_addr.net);
1092 ddp->dst_node = rem_addr.node;
1093 ddp->dst_socket = rem_addr.socket;
1094 atp_send_rsp(gref, mdata, FALSE);
1095 return;
1096 }
1097
1098 /*
1099 * queue the connection request
1100 */
1101 ATDISABLE(s, scb->lock);
1102 gbuf_next(mdata) = 0;
1103 if ((m = scb->sess_ioc) == 0) {
1104 scb->sess_ioc = mdata;
1105 if (scb->get_wait)
1106 thread_wakeup(&scb->event);
1107 else
1108 atalk_notify_sel(gref);
1109 } else {
1110 while (gbuf_next(m))
1111 m = gbuf_next(m);
1112 gbuf_next(m) = mdata;
1113 }
1114 ATENABLE(s, scb->lock);
1115 dPrintf(D_M_ASP, D_L_INFO,
1116 (" : QUEUE connect request\n"));
1117
1118 return;
1119
1120 case ASPFUNC_Command:
1121 case ASPFUNC_Write:
1122 if ( (scb->sess_id != awp->param1)
1123 || (scb->rcv_seq_num != awp->param2)
1124 || BAD_REMADDR(rem_addr) ) {
1125 char era[8], ra[8];
1126 sprintf(era,"%d.%d", scb->rem_addr.node,scb->rem_addr.socket);
1127 sprintf(ra,"%d.%d", rem_addr.node,rem_addr.socket);
1128 dPrintf(D_M_ASP, D_L_WARNING,
1129 (" : DROP, id=%d,esn=%d,sn=%d,erem=%s,rem=%s\n",
1130 scb->sess_id,scb->rcv_seq_num,awp->param2,era,ra));
1131 gbuf_cont(mioc) = 0;
1132 gbuf_rdec(mdata,TOTAL_ATP_HDR_SIZE);
1133 atp_drop_req(gref, mdata);
1134 break;
1135 }
1136 scb->reply_socket = rem_addr.socket;
1137 if (awp->func == ASPFUNC_Write)
1138 scb->wrt_seq_num = scb->rcv_seq_num;
1139 NEXT_SEQ_NUM(scb->rcv_seq_num);
1140 gbuf_set_type(mioc, MSG_PROTO);
1141 gbuf_wset(mioc,sizeof(asp_command_ind_t));
1142 command_ind = (asp_command_ind_t *)gbuf_rptr(mioc);
1143 command_ind->Primitive = (int)awp->func;
1144 command_ind->ReqRefNum =
1145 *(unsigned short *)atp->tid;
1146 command_ind->ReqType = awp->func;
1147
1148 mdata = gbuf_strip(mdata);
1149 gbuf_cont(mioc) = mdata;
1150 ATDISABLE(s, scb->lock);
1151 if (scb->req_flag) {
1152 if ((mx = scb->req_msgq) != 0) {
1153 while (gbuf_next(mx))
1154 mx = gbuf_next(mx);
1155 gbuf_next(mx) = mioc;
1156 } else
1157 scb->req_msgq = mioc;
1158 ATENABLE(s, scb->lock);
1159 } else {
1160 scb->req_flag = 1;
1161 ATENABLE(s, scb->lock);
1162 asp_putnext(scb->gref, mioc);
1163 }
1164 goto l_done;
1165
1166 case ASPFUNC_WriteContinue:
1167 if ( (scb->sess_id != awp->param1)
1168 || (scb->snd_seq_num != awp->param2)
1169 || BAD_REMADDR(rem_addr) ) {
1170 break;
1171 }
1172 scb->reply_socket = rem_addr.socket;
1173 gbuf_set_type(mioc, MSG_PROTO);
1174 gbuf_wset(mioc,sizeof(asp_command_ind_t));
1175 command_ind = (asp_command_ind_t *)gbuf_rptr(mioc);
1176 command_ind->Primitive = (int)awp->func;
1177 command_ind->ReqRefNum =
1178 *(unsigned short *)atp->tid;
1179 command_ind->ReqType = awp->func;
1180
1181 mdata = gbuf_strip(mdata);
1182 gbuf_cont(mioc) = mdata;
1183 asp_putnext(scb->gref, mioc);
1184 goto l_done;
1185
1186 case ASPFUNC_Tickle:
1187 if (scb->stat_msg) {
1188 sess_scb = asp_scbQ[awp->param1];
1189 if (sess_scb && sess_scb->next_scb)
1190 sess_scb = asp_find_scb(
1191 sess_scb->loc_addr.socket, &rem_addr);
1192 if (sess_scb) {
1193 if (sess_scb->rem_addr.node)
1194 asp_untimout(asp_hangup, sess_scb);
1195 if (sess_scb->rem_addr.node)
1196 asp_timout(asp_hangup, sess_scb, sess_scb->session_timer);
1197 }
1198 }
1199 dPrintf(D_M_ASP, D_L_INFO,
1200 (" : Tickle, %d -> %d, id=%d\n",
1201 ddp->src_socket,ddp->dst_socket,awp->param1));
1202 break;
1203
1204 case ASPFUNC_CloseSess:
1205 if ( (scb->sess_id != awp->param1)
1206 || (scb->state == ASPSTATE_Close)
1207 || (scb->state == ASPSTATE_WaitingForCloseSessRsp)
1208 || (scb->rem_addr.net != rem_addr.net)
1209 || (scb->rem_addr.node != rem_addr.node) ) {
1210 dPrintf(D_M_ASP, D_L_INFO,
1211 (" : CLOSE retry, loc=%d, rem=%x.%x.%d\n",
1212 scb->loc_addr.socket,
1213 scb->rem_addr.net,
1214 scb->rem_addr.node,
1215 scb->rem_addr.socket));
1216
1217 break;
1218 }
1219 gbuf_freeb(mioc);
1220
1221 /*
1222 * build the CloseSess response to be sent to peer
1223 * when the session is closed by the user.
1224 */
1225 if (gbuf_cont(mdata)) {
1226 gbuf_freem(gbuf_cont(mdata));
1227 gbuf_cont(mdata) = 0;
1228 }
1229 gbuf_rdec(mdata,TOTAL_ATP_HDR_SIZE);
1230 gbuf_wset(mdata,TOTAL_ATP_HDR_SIZE);
1231 NET_NET(ddp->src_net, ddp->dst_net);
1232 ddp->src_node = ddp->dst_node;
1233 NET_ASSIGN(ddp->dst_net, rem_addr.net);
1234 ddp->dst_node = rem_addr.node;
1235 ddp->dst_socket = rem_addr.socket;
1236 awp->func = 0;
1237 awp->param1 = 0;
1238 awp->param2 = 0;
1239 dPrintf(D_M_ASP,D_L_INFO,
1240 (" : CLOSE, loc=%d, rem=%x.%x.%d\n",
1241 scb->loc_addr.socket,
1242 scb->rem_addr.net,
1243 scb->rem_addr.node,
1244 scb->rem_addr.socket));
1245
1246 gbuf_next(mdata) = 0;
1247 ATDISABLE(s, scb->lock);
1248 if (scb->sess_ioc)
1249 gbuf_freel(scb->sess_ioc);
1250 scb->sess_ioc = mdata;
1251 scb->state = ASPSTATE_Close;
1252 ATENABLE(s, scb->lock);
1253
1254 /*
1255 * notify upstream of the CloseSess from peer
1256 */
1257 asp_hangup(scb);
1258 return;
1259
1260 case ASPFUNC_Attention:
1261 if ( (scb->sess_id != awp->param1)
1262 || (scb->rem_addr.net != rem_addr.net)
1263 || (scb->rem_addr.node != rem_addr.node) ) {
1264 break;
1265 }
1266 gbuf_set_type(mioc, MSG_PROTO);
1267 gbuf_wset(mioc,sizeof(asp_command_ind_t));
1268 command_ind = (asp_command_ind_t *)gbuf_rptr(mioc);
1269 command_ind->Primitive = (int)awp->func;
1270 command_ind->ReqRefNum =
1271 *(unsigned short *)atp->tid;
1272 command_ind->ReqType = awp->func;
1273 scb->attn_tid = *(unsigned short *)atp->tid;
1274 scb->attn_flag = 1;
1275 gbuf_rdec(mdata,2); /* attention code */
1276
1277 mdata = gbuf_strip(mdata);
1278 gbuf_cont(mioc) = mdata;
1279 asp_putnext(scb->gref, mioc);
1280 goto l_done;
1281
1282 default:
1283 dPrintf(D_M_ASP, D_L_WARNING,
1284 (" : UNKNOWN func, func=%d\n",
1285 awp->func));
1286
1287 break;
1288 }
1289 }
1290
1291 else if (iocbp->ioc_cmd == AT_ATP_REQUEST_COMPLETE) {
1292 if (scb->next_scb) {
1293 /*
1294 * find the responsible scb
1295 */
1296 scb = (asp_scb_t *)iocbp->ioc_private;
1297 if ((scb == 0) || (scb->magic_num != 222)) {
1298 dPrintf(D_M_ASP, D_L_ERROR,
1299 ("asp_ack_reply: CAN'T find scb 1\n"));
1300 gbuf_freem(mioc);
1301 return;
1302 }
1303 }
1304 dPrintf(D_M_ASP, D_L_INFO,
1305 ("asp_ack_reply: RSP, loc=%d, rem=%x.%x.%d, state=%s\n",
1306 scb->loc_addr.socket,
1307 scb->rem_addr.net,
1308 scb->rem_addr.node,
1309 scb->rem_addr.socket,
1310 aspStateStr(scb->state)));
1311
1312 switch (scb->state) {
1313 case ASPSTATE_Close:
1314 case ASPSTATE_Idle:
1315 scb->rem_addr.node = 0;
1316 gbuf_freem(mioc);
1317 ATDISABLE(s, scb->lock);
1318 if (scb->get_wait)
1319 thread_wakeup(&scb->event);
1320 else
1321 atalk_notify_sel(gref);
1322 ATENABLE(s, scb->lock);
1323 return;
1324
1325 case ASPSTATE_WaitingForGetStatusRsp:
1326 scb->ioc_wait = 0;
1327 scb->state = ASPSTATE_Idle;
1328 mx = gbuf_cont(mioc);
1329 gbuf_cont(mioc) = 0;
1330 mdata = gbuf_cont(mx);
1331 gbuf_cont(mx) = 0;
1332 iocbp->ioc_cmd = ASPIOC_GetStatus;
1333 iocbp->ioc_count = 0;
1334 iocbp->ioc_rval = mdata ? gbuf_msgsize(mdata) : 0;
1335 gbuf_freeb(mx);
1336 atalk_putnext(gref, mioc);
1337 atalk_putnext(gref, mdata);
1338 return;
1339
1340 case ASPSTATE_WaitingForOpenSessRsp:
1341 scb->ioc_wait = 0;
1342 scb->state = ASPSTATE_Idle;
1343 mx = gbuf_cont(mioc);
1344 gbuf_cont(mioc) = 0;
1345 if (gbuf_cont(mx)) {
1346 gbuf_freem(gbuf_cont(mx));
1347 gbuf_cont(mx) = 0;
1348 }
1349 iocbp->ioc_cmd = ASPIOC_OpenSession;
1350 iocbp->ioc_rval = 0;
1351 iocbp->ioc_count = 0;
1352 atpBDS = (struct atpBDS *)gbuf_rptr(mx);
1353 awp = (asp_word_t *)atpBDS->bdsUserData;
1354 if (awp->param2) {
1355 gbuf_freeb(mx);
1356 asp_iocnak(gref, mioc, ECONNREFUSED);
1357 } else {
1358 scb->rem_addr.node = scb->rem_node;
1359 scb->rem_addr.socket = awp->func;
1360 scb->sess_id = awp->param1;
1361 gbuf_freeb(mx);
1362 atalk_putnext(gref, mioc);
1363 asp_timout(asp_hangup, scb, scb->session_timer);
1364 asp_send_tickle(scb);
1365 dPrintf(D_M_ASP, D_L_INFO,
1366 ("asp_ack_reply: CONNECT, loc=%d, rem=%x.%x.%d\n",
1367 scb->loc_addr.socket,
1368 scb->rem_addr.net,
1369 scb->rem_addr.node,
1370 scb->rem_addr.socket));
1371 }
1372 return;
1373
1374 case ASPSTATE_WaitingForCommandRsp:
1375 case ASPSTATE_WaitingForWriteRsp:
1376 case ASPSTATE_WaitingForWriteContinueRsp:
1377 if (scb->rem_addr.node)
1378 asp_untimout(asp_hangup, scb);
1379 NEXT_SEQ_NUM(scb->snd_seq_num);
1380 scb->state = ASPSTATE_Idle;
1381 gbuf_set_type(mioc, MSG_PROTO);
1382 mx = gbuf_cont(mioc);
1383 mdata = gbuf_cont(mx);
1384 gbuf_cont(mioc) = mdata;
1385 atpBDS = (struct atpBDS *)gbuf_rptr(mx);
1386 cmdreply_ind = (asp_cmdreply_ind_t *)gbuf_rptr(mioc);
1387 cmdreply_ind->Primitive = ASPFUNC_CmdReply;
1388 cmdreply_ind->CmdResult = *(int *)atpBDS->bdsUserData;
1389 gbuf_wset(mioc,sizeof(asp_cmdreply_ind_t));
1390 gbuf_freeb(mx);
1391 asp_putnext(scb->gref, mioc);
1392 goto l_done;
1393
1394 case ASPSTATE_WaitingForCloseSessRsp:
1395 scb->ioc_wait = 0;
1396 scb->state = ASPSTATE_Close;
1397 scb->rem_addr.node = 0;
1398 iocbp->ioc_cmd = ASPIOC_CloseSession;
1399 iocbp->ioc_rval = 0;
1400 if (gbuf_cont(mioc)) {
1401 gbuf_freem(gbuf_cont(mioc));
1402 gbuf_cont(mioc) = 0;
1403 }
1404 atalk_putnext(scb->gref, mioc);
1405 atp_cancel_req(scb->gref, (unsigned int)scb->tickle_tid);
1406 scb->tickle_tid = 0;
1407 return;
1408
1409 default:
1410 dPrintf(D_M_ASP, D_L_WARNING,
1411 (" : UNKNOWN state, state=%s\n",
1412 aspStateStr(scb->state)));
1413 break;
1414 }
1415 }
1416
1417 else {
1418 if (scb->next_scb) {
1419 /*
1420 * find the responsible scb
1421 */
1422 scb = (asp_scb_t *)iocbp->ioc_cr;
1423 if ((scb == 0) || (scb->magic_num != 222)) {
1424 dPrintf(D_M_ASP, D_L_ERROR,
1425 ("asp_ack_reply: CAN'T find scb 2\n"));
1426 gbuf_freem(mioc);
1427 return;
1428 }
1429 }
1430
1431 switch (scb->state) {
1432 case ASPSTATE_Close:
1433 scb->rem_addr.node = 0;
1434 break;
1435 }
1436 }
1437
1438 if (mioc != 0)
1439 gbuf_freem(mioc);
1440
1441l_done:
1442 if (scb->rem_addr.node)
1443 asp_timout(asp_hangup, scb, scb->session_timer);
1444} /* asp_ack_reply */
1445
1446/*
1447 * NAK reply routine
1448 */
1449void
1450asp_nak_reply(gref, mioc)
1451 register gref_t *gref;
1452 register gbuf_t *mioc;
1453{
1454 register asp_scb_t *scb;
1455 register ioc_t *iocbp;
1456
1457 iocbp = (ioc_t *)gbuf_rptr(mioc);
1458
1459 if (iocbp->ioc_cmd == AT_ATP_ISSUE_REQUEST_TICKLE) {
1460 /*
1461 * no tickle, close session
1462 */
1463 scb = (asp_scb_t *)iocbp->ioc_cr;
1464 gbuf_freem(mioc);
1465 asp_hangup(scb);
1466 dPrintf(D_M_ASP, D_L_WARNING,
1467 ("tickle_nak: loc=%d, rem=%x.%x.%d, state=%s\n",
1468 scb->loc_addr.socket,
1469 scb->rem_addr.net,
1470 scb->rem_addr.node,
1471 scb->rem_addr.socket,
1472 aspStateStr(scb->state)));
1473
1474 return;
1475 }
1476
1477 scb = (asp_scb_t *)gref->info;
1478 if (scb == 0) {
1479 gbuf_freem(mioc);
1480 return;
1481 }
1482
1483 if (iocbp->ioc_cmd == AT_ATP_REQUEST_COMPLETE) {
1484 if (scb->next_scb) {
1485 /*
1486 * find the responsible scb
1487 */
1488 scb = (asp_scb_t *)iocbp->ioc_private;
1489 if ((scb == 0) || (scb->magic_num != 222)) {
1490 dPrintf(D_M_ASP, D_L_ERROR,
1491 ("asp_nak_reply: CAN'T find scb 1\n"));
1492 gbuf_freem(mioc);
1493 return;
1494 }
1495 }
1496 dPrintf(D_M_ASP, D_L_WARNING,
1497 ("asp_nak_reply: RSP, loc=%d, rem=%x.%x.%d, state=%s\n",
1498 scb->loc_addr.socket,
1499 scb->rem_addr.net,
1500 scb->rem_addr.node,
1501 scb->rem_addr.socket,
1502 aspStateStr(scb->state)));
1503
1504 switch (scb->state) {
1505 case ASPSTATE_WaitingForGetStatusRsp:
1506 iocbp->ioc_cmd = ASPIOC_GetStatus;
1507 break;
1508
1509 case ASPSTATE_WaitingForOpenSessRsp:
1510 iocbp->ioc_cmd = ASPIOC_OpenSession;
1511 break;
1512
1513 case ASPSTATE_WaitingForCommandRsp:
1514 case ASPSTATE_WaitingForWriteRsp:
1515 case ASPSTATE_WaitingForWriteContinueRsp:
1516 scb->state = ASPSTATE_Idle;
1517
1518 /* last remaining use of MSG_ERROR */
1519 gbuf_set_type(mioc, MSG_ERROR);
1520 *gbuf_rptr(mioc) = (u_char)EPROTO;
1521 gbuf_wset(mioc, 1);
1522 if (gbuf_cont(mioc)) {
1523 gbuf_freem(gbuf_cont(mioc));
1524 gbuf_cont(mioc) = 0;
1525 }
1526
1527 asp_putnext(scb->gref, mioc);
1528 return;
1529
1530 case ASPSTATE_WaitingForCloseSessRsp:
1531 scb->state = ASPSTATE_Close;
1532 /* fall through */
1533 case ASPSTATE_Close: /* new for PR-2296832 */
1534 scb->rem_addr.node = 0;
1535 iocbp->ioc_cmd = ASPIOC_CloseSession;
1536 iocbp->ioc_rval = 0;
1537 if (gbuf_cont(mioc)) {
1538 gbuf_freem(gbuf_cont(mioc));
1539 gbuf_cont(mioc) = 0;
1540 }
1541 gbuf_set_type(mioc, MSG_IOCACK);
1542 atalk_putnext(scb->gref, mioc);
1543 return;
1544
1545 default:
1546 gbuf_freem(mioc);
1547 return;
1548 }
1549 scb->state = ASPSTATE_Idle;
1550 atalk_putnext(gref, mioc);
1551 }
1552
1553 else {
1554 if (scb->next_scb) {
1555 /*
1556 * find the responsible scb
1557 */
1558 scb = (asp_scb_t *)iocbp->ioc_cr;
1559 if ((scb == 0) || (scb->magic_num != 222)) {
1560 dPrintf(D_M_ASP, D_L_ERROR,
1561 ("asp_nak_reply: CAN'T find scb 2\n"));
1562 gbuf_freem(mioc);
1563 return;
1564 }
1565 }
1566
1567 switch (scb->state) {
1568 case ASPSTATE_Close:
1569 scb->rem_addr.node = 0;
1570 break;
1571 }
1572
1573 gbuf_freem(mioc);
1574 }
1575} /* asp_nak_reply */
1576
1577/*
1578 * delete scb from the use list
1579 */
1580StaticProc void
1581asp_dequeue_scb(scb)
1582 asp_scb_t *scb;
1583{
1584 int s;
1585
1586 ATDISABLE(s, aspall_lock);
1587 if (scb == scb_used_list) {
1588 if ((scb_used_list = scb->next_scb) != 0)
1589 scb->next_scb->prev_scb = 0;
1590 } else {
1591 if ((scb->prev_scb->next_scb = scb->next_scb) != 0)
1592 scb->next_scb->prev_scb = scb->prev_scb;
1593 }
1594 ATENABLE(s, aspall_lock);
1595
1596 scb->next_scb = 0;
1597 scb->prev_scb = 0;
1598}
1599
1600/*
1601 * find scb routine
1602 */
1603StaticProc asp_scb_t *
1604asp_find_scb(sock_num, rem_addr)
1605 unsigned char sock_num;
1606 at_inet_t *rem_addr;
1607{
1608 int s;
1609 asp_scb_t *scb;
1610 asp_scb_t *alt_scb = 0;
1611
1612 ATDISABLE(s, aspall_lock);
1613 for (scb = asp_scbQ[sock_num]; scb; scb = scb->next_scb) {
1614 if ((scb->rem_addr.net == rem_addr->net)
1615 && (scb->rem_addr.node == rem_addr->node)) {
1616 if ((scb->rem_addr.socket == rem_addr->socket)
1617 || (scb->rem_socket == rem_addr->socket))
1618 break;
1619 else if (alt_scb == 0)
1620 alt_scb = scb;
1621 }
1622 }
1623
1624 if ((scb == 0) && ((scb = alt_scb) == 0)) {
1625 dPrintf(D_M_ASP, D_L_ERROR,
1626 ("asp_find_scb: CAN'T find scb, loc=%d, rem=%x.%x.%d\n",
1627 sock_num,
1628 rem_addr->net,
1629 rem_addr->node,
1630 rem_addr->socket));
1631 }
1632 ATENABLE(s, aspall_lock);
1633
1634 return scb;
1635}
1636
1637/*
1638 * timout routine
1639 */
1640StaticProc void
1641asp_timout(func, scb, seconds)
1642 void (*func)();
1643 register asp_scb_t *scb;
1644 int seconds;
1645{
1646 int s;
1647 unsigned char sum;
1648 register asp_scb_t *curr_scb, *prev_scb;
1649
1650 if (scb->tmo_func)
1651 return;
1652
1653 scb->tmo_func = func;
1654 scb->tmo_delta = (seconds>>SESS_TMO_RES);
1655 scb->tmo_cnt = scb_tmo_cnt;
1656
1657 ATDISABLE(s, asptmo_lock);
1658 if (scb_tmo_list == 0) {
1659 scb->next_tmo = scb->prev_tmo = 0;
1660 scb_tmo_list = scb;
1661 ATENABLE(s, asptmo_lock);
1662 return;
1663 }
1664
1665 prev_scb = 0;
1666 curr_scb = scb_tmo_list;
1667 sum = 0;
1668
1669 while (1) {
1670 sum += curr_scb->tmo_delta;
1671 if (sum > scb->tmo_delta) {
1672 sum -= curr_scb->tmo_delta;
1673 scb->tmo_delta -= sum;
1674 curr_scb->tmo_delta -= scb->tmo_delta;
1675 break;
1676 }
1677 prev_scb = curr_scb;
1678 if ((curr_scb = curr_scb->next_tmo) == 0) {
1679 scb->tmo_delta -= sum;
1680 break;
1681 }
1682 }
1683
1684 if (prev_scb) {
1685 scb->prev_tmo = prev_scb;
1686 if ((scb->next_tmo = prev_scb->next_tmo) != 0)
1687 prev_scb->next_tmo->prev_tmo = scb;
1688 prev_scb->next_tmo = scb;
1689 } else {
1690 scb->prev_tmo = 0;
1691 scb->next_tmo = scb_tmo_list;
1692 scb_tmo_list->prev_tmo = scb;
1693 scb_tmo_list = scb;
1694 }
1695 ATENABLE(s, asptmo_lock);
1696}
1697
1698/*
1699 * untimout routine
1700 */
1701StaticProc void
1702asp_untimout(func, scb)
1703 void (*func)();
1704 register asp_scb_t *scb;
1705{
1706 int s;
1707
1708 if ((scb->tmo_cnt == scb_tmo_cnt) || (scb->tmo_func == 0))
1709 return;
1710
1711 ATDISABLE(s, asptmo_lock);
1712 if (scb_tmo_list == scb) {
1713 if ((scb_tmo_list = scb->next_tmo) != 0) {
1714 scb_tmo_list->prev_tmo = 0;
1715 scb->next_tmo->tmo_delta += scb->tmo_delta;
1716 }
1717 } else if (scb->prev_tmo) {
1718 if ((scb->prev_tmo->next_tmo = scb->next_tmo) != 0) {
1719 scb->next_tmo->prev_tmo = scb->prev_tmo;
1720 scb->next_tmo->tmo_delta += scb->tmo_delta;
1721 }
1722 scb->prev_tmo = 0;
1723 }
1724 scb->tmo_func = 0;
1725 ATENABLE(s, asptmo_lock);
1726}
1727
1728/*
1729 * hangup routine
1730 */
1731StaticProc void
1732asp_hangup(scb)
1733 asp_scb_t *scb;
1734{
1735 int s;
1736
1737 /*
1738 * set the state to Close
1739 */
1740 ATDISABLE(s, scb->lock);
1741 scb->state = ASPSTATE_Close;
1742 if (scb->tickle_tid) {
1743 atp_cancel_req(scb->gref, (unsigned int)scb->tickle_tid);
1744 scb->tickle_tid = 0;
1745 }
1746
1747 /*
1748 * notify upstream of the hangup
1749 */
1750 if (scb->rem_addr.node) {
1751 if (scb->get_wait) {
1752 thread_wakeup(&scb->event);
1753 ATENABLE(s, scb->lock);
1754 } else {
1755 ATENABLE(s, scb->lock);
1756 atalk_notify_sel(scb->gref);
1757 }
1758 } else
1759 ATENABLE(s, scb->lock);
1760}
1761
1762StaticProc void
1763asp_iocack(gref, mioc)
1764 gref_t *gref;
1765 gbuf_t *mioc;
1766{
1767 if (gbuf_cont(mioc))
1768 ((ioc_t *)gbuf_rptr(mioc))->ioc_count = gbuf_msgsize(gbuf_cont(mioc));
1769 else
1770 ((ioc_t *)gbuf_rptr(mioc))->ioc_count = 0;
1771
1772 gbuf_set_type(mioc, MSG_IOCACK);
1773 atalk_putnext(gref, mioc);
1774}
1775
1776StaticProc void
1777asp_iocnak(gref, mioc, err)
1778 gref_t *gref;
1779 gbuf_t *mioc;
1780 int err;
1781{
1782 ((ioc_t *)gbuf_rptr(mioc))->ioc_count = 0;
1783 if (err == 0)
1784 err = ENXIO;
1785 ((ioc_t *)gbuf_rptr(mioc))->ioc_error = err;
1786 ((ioc_t *)gbuf_rptr(mioc))->ioc_rval = -1;
1787 if (gbuf_cont(mioc)) {
1788 gbuf_freem(gbuf_cont(mioc));
1789 gbuf_cont(mioc) = 0;
1790 }
1791
1792 gbuf_set_type(mioc, MSG_IOCNAK);
1793 atalk_putnext(gref, mioc);
1794}
1795
1796/*
1797 * the alloc scb routine
1798 */
1799StaticProc asp_scb_t *
1800asp_scb_alloc()
1801{
1802 int s, i;
1803 gbuf_t *m;
1804 asp_scb_t *scb, *scb_array;
1805
1806 ATDISABLE(s, aspall_lock);
1807 if (scb_free_list == 0) {
1808 if ((m = gbuf_alloc(SCBS_PER_BLK*sizeof(asp_scb_t), PRI_MED)) == 0)
1809 {
1810 ATENABLE(s, aspall_lock);
1811 return (asp_scb_t *)0;
1812 }
1813 bzero((char *)gbuf_rptr(m), SCBS_PER_BLK*sizeof(asp_scb_t));
1814 gbuf_cont(m) = scb_resource_m;
1815 scb_resource_m = m;
1816 scb_array = (asp_scb_t *)gbuf_rptr(m);
1817 for (i=0; i < SCBS_PER_BLK-1; i++)
1818 scb_array[i].next_scb = (asp_scb_t *)&scb_array[i+1];
1819 scb_array[i].next_scb = 0;
1820 scb_free_list = (asp_scb_t *)&scb_array[0];
1821 }
1822
1823 scb = scb_free_list;
1824 scb_free_list = scb->next_scb;
1825 ATENABLE(s, aspall_lock);
1826 ATLOCKINIT(scb->lock);
1827 ATLOCKINIT(scb->delay_lock);
1828 ATEVENTINIT(scb->event);
1829 ATEVENTINIT(scb->delay_event);
1830
1831 return scb;
1832}
1833
1834/*
1835 * the free scb routine
1836 */
1837StaticProc void
1838asp_scb_free(scb)
1839 asp_scb_t *scb;
1840{
1841 int s;
1842
1843 bzero((char *)scb, sizeof(asp_scb_t));
1844 ATDISABLE(s, aspall_lock);
1845 scb->next_scb = scb_free_list;
1846 scb_free_list = scb;
1847 ATENABLE(s, aspall_lock);
1848}
1849
1850/*
1851 * routine to pass up receive data
1852 */
1853StaticProc void
1854asp_putnext(gref, mproto)
1855 gref_t *gref;
1856 gbuf_t *mproto;
1857{
1858 int s;
1859 gbuf_t *m;
1860 asp_scb_t *scb;
1861
1862 scb = (asp_scb_t *)gref->info;
1863
1864 /*
1865 * queue the message.
1866 */
1867 ATDISABLE(s, scb->lock);
1868 gbuf_next(mproto) = 0;
1869 if ((m = scb->sess_ioc) == 0)
1870 scb->sess_ioc = mproto;
1871 else {
1872 while (gbuf_next(m))
1873 m = gbuf_next(m);
1874 gbuf_next(m) = mproto;
1875 }
1876 scb->rcv_cnt++;
1877 if (scb->rcv_cnt >= MAX_RCV_CNT)
1878 scb->snd_stop = 1;
1879
1880 if (scb->get_wait) {
1881 thread_wakeup(&scb->event);
1882 ATENABLE(s, scb->lock);
1883 } else if (mproto == scb->sess_ioc) {
1884 ATENABLE(s, scb->lock);
1885 atalk_notify_sel(gref);
1886 } else
1887 ATENABLE(s, scb->lock);
1888} /* asp_putnext */
1889
1890/*
1891 * The following two routines are direct entries from system
1892 * calls to allow fast sending and recving of ASP data.
1893 */
1894
1895/* in ASPputmsg we expect:
1896
1897 ASPFUNC_CmdReply
1898 ASPFUNC_Attention
1899 ASPFUNC_Command
1900 ASPFUNC_Write
1901 ASPFUNC_WriteContinue
1902*/
1903
1904int ASPputmsg(gref, ctlptr, datptr, flags, errp)
1905 gref_t *gref;
1906 strbuf_t *ctlptr;
1907 strbuf_t *datptr;
1908 int flags;
1909 int *errp;
1910{
1911 int s, i, err, len;
1912 gbuf_t *mioc, *mdata, *mx;
1913 ioc_t *iocbp;
1914 strbuf_t ctlbuf;
1915 strbuf_t datbuf;
1916 asp_scb_t *scb;
1917 int nbds, result, msize, Primitive;
1918 unsigned char *wptr;
1919 struct atp_set_default *sd;
1920 at_ddp_t *ddp;
1921 at_atp_t *atp;
1922 struct atpBDS *atpBDS;
1923 asp_word_t *awp;
1924 union asp_primitives *primitives;
1925 unsigned short tid;
1926
1927 if ((scb = (asp_scb_t *)gref->info) == 0) {
1928 dPrintf(D_M_ASP, D_L_ERROR,
1929 ("ASPputmsg: stale handle=0x%x, pid=%d\n",
1930 (u_int) gref, gref->pid));
1931
1932 *errp = EINVAL;
1933 return -1;
1934 }
1935
1936 if (scb->state == ASPSTATE_Close)
1937 return 0;
1938 if (scb->snd_stop) {
1939 *errp = EAGAIN;
1940 return -1;
1941 }
1942
1943 /*
1944 * copy in the control and data info
1945 */
1946 if ((err = copyin((caddr_t)ctlptr,
1947 (caddr_t)&ctlbuf, sizeof(ctlbuf))) != 0)
1948 goto l_err;
1949 if ((err = copyin((caddr_t)datptr,
1950 (caddr_t)&datbuf, sizeof(datbuf))) != 0)
1951 goto l_err;
1952
1953 /*
1954 * allocate buffer and copy in the control content
1955 */
1956 if (!(mioc = gbuf_alloc_wait(ctlbuf.len, TRUE))) {
1957 /* error return should not be possible */
1958 err = ENOBUFS;
1959 goto l_err;
1960 }
1961 gbuf_set_type(mioc, MSG_IOCTL); /* for later, in ATP */
1962 gbuf_wset(mioc, ctlbuf.len);
1963 if ((err = copyin((caddr_t)ctlbuf.buf,
1964 (caddr_t)gbuf_rptr(mioc), ctlbuf.len)) != 0) {
1965 gbuf_freem(mioc);
1966 goto l_err;
1967 }
1968
1969 iocbp = (ioc_t *)gbuf_rptr(mioc);
1970 primitives = (union asp_primitives *)gbuf_rptr(mioc);
1971 Primitive = primitives->Primitive;
1972 dPrintf(D_M_ASP, D_L_INFO,
1973 ("ASPputmsg: %s\n", aspCmdStr(Primitive)));
1974
1975 /*
1976 * allocate buffer and copy in the data content
1977 */
1978 len = (Primitive == ASPFUNC_CmdReply) ? 0 : aspCMDsize;
1979 if (!(mdata = gbuf_alloc_wait(datbuf.len+len, TRUE))) {
1980 /* error return should not be possible */
1981 err = ENOBUFS;
1982 gbuf_freem(mioc);
1983 goto l_err;
1984 }
1985 gbuf_wset(mdata,(datbuf.len+len));
1986 gbuf_cont(mioc) = mdata;
1987 if ((err = copyin((caddr_t)datbuf.buf,
1988 (caddr_t)(gbuf_rptr(mdata)+len), datbuf.len)) != 0) {
1989 gbuf_freem(mioc);
1990 goto l_err;
1991 }
1992
1993 switch (Primitive) {
1994
1995 case ASPFUNC_Command:
1996 case ASPFUNC_Write:
1997 case ASPFUNC_WriteContinue:
1998 case ASPFUNC_Attention:
1999 /*
2000 * build the command/write/write_continue request
2001 */
2002 wptr = gbuf_rptr(mdata);
2003 atpBDS = (struct atpBDS *)wptr;
2004 wptr += atpBDSsize;
2005 for (i=0; i < ATP_TRESP_MAX; i++) {
2006 *(unsigned long *)atpBDS[i].bdsBuffAddr = 1;
2007 *(unsigned short *)atpBDS[i].bdsBuffSz = ATP_DATA_SIZE;
2008 }
2009 sd = (struct atp_set_default *)wptr;
2010 wptr += sizeof(struct atp_set_default);
2011 sd->def_retries = (scb->cmd_retry.retries == -1) ?
2012 ATP_INFINITE_RETRIES : scb->cmd_retry.retries;
2013 sd->def_rate = scb->cmd_retry.interval*TICKS_PER_SEC;
2014 sd->def_BDSlen = atpBDSsize;
2015 ddp = (at_ddp_t *)wptr;
2016 NET_ASSIGN(ddp->src_net, scb->loc_addr.net);
2017 ddp->src_node = scb->loc_addr.node;
2018 NET_ASSIGN(ddp->dst_net, scb->rem_addr.net);
2019 ddp->dst_node = scb->rem_addr.node;
2020 ddp->dst_socket = scb->rem_addr.socket;
2021 UAS_ASSIGN(ddp->checksum, 0);
2022 atp = ATP_ATP_HDR(wptr);
2023 wptr += TOTAL_ATP_HDR_SIZE;
2024 atp->xo = 1;
2025 atp->xo_relt = 1;
2026 atp->bitmap = 0xff;
2027 awp = (asp_word_t *)atp->user_bytes;
2028 awp->func = (unsigned char)Primitive;
2029 awp->param1 = scb->sess_id;
2030 awp->param2 = scb->snd_seq_num;
2031 iocbp->ioc_private = (void *)scb;
2032 iocbp->ioc_count = gbuf_len(mdata);
2033 iocbp->ioc_rval = 0;
2034 iocbp->ioc_cmd = AT_ATP_ISSUE_REQUEST_DEF;
2035
2036 /*
2037 * send the command/write/write_continue/attention request
2038 */
2039 ATDISABLE(s, scb->lock);
2040 switch (awp->func) {
2041 case ASPFUNC_Command:
2042 scb->state = ASPSTATE_WaitingForCommandRsp;
2043 break;
2044 case ASPFUNC_Write:
2045 scb->state = ASPSTATE_WaitingForWriteRsp;
2046 break;
2047 case ASPFUNC_WriteContinue:
2048 scb->state = ASPSTATE_WaitingForWriteContinueRsp;
2049 awp->param2 = scb->wrt_seq_num;
2050 break;
2051 case ASPFUNC_Attention:
2052 scb->state = ASPSTATE_WaitingForCommandRsp;
2053 atp->xo = 0;
2054 atp->xo_relt = 0;
2055 atp->bitmap = 0x01;
2056 gbuf_wdec(mdata,2);
2057 awp->param2 = *(unsigned short *)gbuf_wptr(mdata);
2058 break;
2059 }
2060 ATENABLE(s, scb->lock);
2061 dPrintf(D_M_ASP,D_L_INFO,
2062 ("ASPputmsg: %s, loc=%d, rem=%x.%x.%d\n",
2063 (awp->func == ASPFUNC_Command ? "CommandReq" :
2064 awp->func == ASPFUNC_Write ? "WriteReq" :
2065 awp->func == ASPFUNC_WriteContinue ? "WriteContinue" :
2066 "AttentionReq"),scb->loc_addr.socket,
2067 NET_VALUE(ddp->dst_net),ddp->dst_node,ddp->dst_socket));
2068 atp_send_req(gref, mioc);
2069 return 0;
2070
2071 case ASPFUNC_CmdReply:
2072
2073 ATDISABLE(s, scb->lock);
2074 if (scb->req_msgq) {
2075 mx = scb->req_msgq;
2076 scb->req_msgq = gbuf_next(mx);
2077 gbuf_next(mx) = 0;
2078 ATENABLE(s, scb->lock);
2079 asp_putnext(scb->gref, mx);
2080 } else {
2081 scb->req_flag = 0;
2082 ATENABLE(s, scb->lock);
2083 }
2084 result = primitives->CmdReplyReq.CmdResult;
2085 tid = primitives->CmdReplyReq.ReqRefNum;
2086
2087 /* Re-use the original mioc mbuf to send the response. */
2088 gbuf_rinc(mioc,sizeof(void *));
2089 gbuf_wset(mioc,0);
2090 ddp = (at_ddp_t *)gbuf_wptr(mioc);
2091 gbuf_winc(mioc,DDP_X_HDR_SIZE);
2092 atp = (at_atp_t *)gbuf_wptr(mioc);
2093 gbuf_winc(mioc,ATP_HDR_SIZE);
2094 NET_ASSIGN(ddp->src_net, scb->loc_addr.net);
2095 ddp->src_node = scb->loc_addr.node;
2096 NET_ASSIGN(ddp->dst_net, scb->rem_addr.net);
2097 ddp->dst_node = scb->rem_addr.node;
2098 ddp->dst_socket = scb->reply_socket;
2099 ddp->type = DDP_ATP;
2100 UAS_ASSIGN(ddp->checksum, 0);
2101 UAS_ASSIGN(atp->tid, tid);
2102 if (scb->attn_flag && (tid == scb->attn_tid)) {
2103 scb->attn_flag = 0;
2104 atp->xo = 0;
2105 atp->xo_relt = 0;
2106 } else {
2107 atp->xo = 1;
2108 atp->xo_relt = 1;
2109 }
2110 atpBDS = (struct atpBDS *)gbuf_wptr(mioc);
2111 msize = mdata ? gbuf_msgsize(mdata) : 0;
2112 for (nbds=0; (nbds < ATP_TRESP_MAX) && (msize > 0); nbds++) {
2113 len = msize < ATP_DATA_SIZE ? msize : ATP_DATA_SIZE;
2114 msize -= ATP_DATA_SIZE;
2115 *(long *)atpBDS[nbds].bdsUserData = 0;
2116 UAL_ASSIGN(atpBDS[nbds].bdsBuffAddr, 1);
2117 UAS_ASSIGN(atpBDS[nbds].bdsBuffSz, len);
2118 }
2119 UAS_ASSIGN(atpBDS[0].bdsDataSz, nbds);
2120 *(long *)atpBDS[0].bdsUserData = (long)result;
2121 *(long *)atp->user_bytes = (long)result;
2122 gbuf_winc(mioc,atpBDSsize);
2123 dPrintf(D_M_ASP, D_L_INFO,
2124 ("ASPputmsg: ATP CmdReplyReq, loc=%d, state=%s, msgsize = %d, result = %d, tid = %d\n",
2125 scb->loc_addr.socket, aspStateStr(scb->state),
2126 (mdata ? gbuf_msgsize(mdata) : 0), result, tid));
2127 atp_send_rsp(gref, mioc, TRUE);
2128 return 0;
2129 }
2130
2131 /* Not an expected ASPFUNC */
2132 gbuf_freem(mioc);
2133 err = EOPNOTSUPP;
2134
2135l_err:
2136 *errp = err;
2137 return -1;
2138} /* ASPputmsg */
2139
2140int
2141ASPgetmsg(gref, ctlptr, datptr, flags, errp)
2142 gref_t *gref;
2143 strbuf_t *ctlptr;
2144 strbuf_t *datptr;
2145 int *flags;
2146 int *errp;
2147{
2148 int err, s, len, sum, rval;
2149 gbuf_t *mproto, *mdata;
2150 strbuf_t ctlbuf;
2151 strbuf_t datbuf;
2152 asp_scb_t *scb;
2153 unsigned char get_wait;
2154
2155 if ((scb = (asp_scb_t *)gref->info) == 0) {
2156 dPrintf(D_M_ASP, D_L_ERROR,
2157 ("ASPgetmsg: stale handle=0x%x, pid=%d\n",
2158 (u_int) gref, gref->pid));
2159
2160 *errp = EINVAL;
2161 return -1;
2162 }
2163
2164 ATDISABLE(s, scb->lock);
2165 if (scb->state == ASPSTATE_Close) {
2166 ATENABLE(s, scb->lock);
2167 return 0;
2168 }
2169
2170 /*
2171 * get receive data
2172 */
2173 while ((mproto = scb->sess_ioc) == 0) {
2174 scb->get_wait = 1;
2175 err = tsleep(&scb->event, PSOCK | PCATCH, "aspgetmsg", 0);
2176 if (err != 0) {
2177 scb->get_wait = 0;
2178 ATENABLE(s, scb->lock);
2179 *errp = err;
2180 return -1;
2181 }
2182 if (scb->state == ASPSTATE_Close) {
2183 scb->get_wait = 0;
2184 ATENABLE(s, scb->lock);
2185 return 0;
2186 }
2187 }
2188 get_wait = scb->get_wait;
2189 scb->get_wait = 0;
2190 if ((ctlptr == 0) && (datptr == 0)) {
2191 ATENABLE(s, scb->lock);
2192 return 0;
2193 }
2194 scb->sess_ioc = gbuf_next(mproto);
2195 mdata = gbuf_cont(mproto);
2196 ATENABLE(s, scb->lock);
2197
2198 /* last remaining use of MSG_ERROR */
2199 if (gbuf_type(mproto) == MSG_ERROR) {
2200 err = (int)gbuf_rptr(mproto)[0];
2201 goto l_err;
2202 }
2203
2204 /*
2205 * copy in the control and data info
2206 */
2207 if ((err = copyin((caddr_t)ctlptr,
2208 (caddr_t)&ctlbuf, sizeof(ctlbuf))) != 0)
2209 goto l_err;
2210 if ((err = copyin((caddr_t)datptr,
2211 (caddr_t)&datbuf, sizeof(datbuf))) != 0)
2212 goto l_err;
2213 if ((datbuf.maxlen < 0) || (datbuf.maxlen < gbuf_msgsize(mdata))) {
2214 ATDISABLE(s, scb->lock);
2215 gbuf_next(mproto) = scb->sess_ioc;
2216 scb->sess_ioc = mproto;
2217 ATENABLE(s, scb->lock);
2218 return MOREDATA;
2219 }
2220
2221 if (get_wait == 0) {
2222 /*
2223 * this is a hack to support the select() call.
2224 * we're not supposed to dequeue messages in the Streams
2225 * head's read queue this way; but there is no better way.
2226 */
2227 ATDISABLE(s, scb->lock);
2228 if (scb->sess_ioc == 0) {
2229 ATENABLE(s, scb->lock);
2230 } else {
2231 ATENABLE(s, scb->lock);
2232 atalk_notify_sel(gref);
2233 }
2234 }
2235
2236 /*
2237 * copy out the control content and info
2238 */
2239 ctlbuf.len = gbuf_len(mproto);
2240 if ((err = copyout((caddr_t)gbuf_rptr(mproto),
2241 (caddr_t)ctlbuf.buf, ctlbuf.len)) != 0)
2242 goto l_err;
2243 if ((err = copyout((caddr_t)&ctlbuf,
2244 (caddr_t)ctlptr, sizeof(ctlbuf))) != 0)
2245 goto l_err;
2246
2247 /*
2248 * copy out the data content and info
2249 */
2250 for (rval=0, sum=0; mdata && (rval == 0); mdata = gbuf_cont(mdata)) {
2251 len = gbuf_len(mdata);
2252 if (len) {
2253 if ((len + sum) > datbuf.maxlen) {
2254 len = datbuf.maxlen - sum;
2255 rval = MOREDATA;
2256 }
2257 if ((err = copyout((caddr_t)gbuf_rptr(mdata),
2258 (caddr_t)&datbuf.buf[sum], len)) != 0)
2259 goto l_err;
2260 sum += len;
2261 }
2262 }
2263 datbuf.len = sum;
2264 if ((err = copyout((caddr_t)&datbuf,
2265 (caddr_t)datptr, sizeof(datbuf))) != 0)
2266 goto l_err;
2267
2268#ifdef APPLETALK_DEBUG
2269 if (mproto == 0)
2270 kprintf("ASPgetmsg: null mproto!!!\n");
2271#endif
2272
2273 gbuf_freem(mproto);
2274
2275 ATDISABLE(s, scb->lock);
2276 if (scb->sess_ioc)
2277 scb->rcv_cnt--;
2278 else {
2279 scb->rcv_cnt = 0;
2280 scb->snd_stop = 0;
2281 }
2282 ATENABLE(s, scb->lock);
2283 return rval;
2284
2285l_err:
2286 dPrintf(D_M_ASP, D_L_ERROR,
2287 ("ASPgetmsg: err=%d, loc=%d, rem=%x.%x.%d, state=%s\n",
2288 err, scb->loc_addr.socket,
2289 scb->rem_addr.net,
2290 scb->rem_addr.node, scb->rem_addr.socket,
2291 aspStateStr(scb->state)));
2292 ATDISABLE(s, scb->lock);
2293 gbuf_next(mproto) = scb->sess_ioc;
2294 scb->sess_ioc = mproto;
2295 ATENABLE(s, scb->lock);
2296 *errp = err;
2297 return -1;
2298}