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