Start development on 386BSD 0.0
[unix-history] / .ref-BSD-4_3_Net_2 / usr / src / contrib / isode / tsap / tsaplisten.c
CommitLineData
b62cce74
C
1/* tsaplisten.c - "network" listening */
2
3#ifndef lint
4static char *rcsid = "$Header: /f/osi/tsap/RCS/tsaplisten.c,v 7.20 91/03/09 11:58:23 mrose Exp $";
5#endif
6
7/*
8 * $Header: /f/osi/tsap/RCS/tsaplisten.c,v 7.20 91/03/09 11:58:23 mrose Exp $
9 *
10 * RFC1085 (LPP) support contributed by the Wollongong Group, Inc.
11 *
12 *
13 * $Log: tsaplisten.c,v $
14 * Revision 7.20 91/03/09 11:58:23 mrose
15 * update
16 *
17 * Revision 7.19 91/02/22 09:47:29 mrose
18 * Interim 6.8
19 *
20 * Revision 7.18 91/01/24 14:50:52 mrose
21 * update
22 *
23 * Revision 7.17 91/01/07 12:41:30 mrose
24 * update
25 *
26 * Revision 7.16 90/12/17 22:18:03 mrose
27 * tsel
28 *
29 * Revision 7.15 90/10/16 16:24:20 mrose
30 * foo
31 *
32 * Revision 7.14 90/10/16 11:21:27 mrose
33 * iaed
34 *
35 * Revision 7.13 90/07/27 08:48:16 mrose
36 * update
37 *
38 * Revision 7.12 90/07/09 14:51:28 mrose
39 * sync
40 *
41 * Revision 7.11 90/05/08 08:55:45 mrose
42 * touch-up
43 *
44 * Revision 7.10 90/03/23 17:31:37 mrose
45 * 8
46 *
47 * Revision 7.9 90/02/19 13:07:29 mrose
48 * update
49 *
50 * Revision 7.8 89/12/19 22:02:35 mrose
51 * touch-up
52 *
53 * Revision 7.7 89/12/19 16:21:35 mrose
54 * sync
55 *
56 * Revision 7.6 89/12/13 07:05:50 mrose
57 * touch-up
58 *
59 * Revision 7.5 89/12/11 09:35:37 mrose
60 * again
61 *
62 * Revision 7.4 89/12/11 09:20:30 mrose
63 * update
64 *
65 * Revision 7.3 89/12/07 22:15:45 mrose
66 * touch-up
67 *
68 * Revision 7.2 89/12/07 01:07:43 mrose
69 * queued writes
70 *
71 * Revision 7.1 89/11/25 16:31:39 mrose
72 * sync
73 *
74 * Revision 7.0 89/11/23 22:30:46 mrose
75 * Release 6.0
76 *
77 */
78
79/*
80 * NOTICE
81 *
82 * Acquisition, use, and distribution of this module and related
83 * materials are subject to the restrictions of a license agreement.
84 * Consult the Preface in the User's Manual for the full terms of
85 * this agreement.
86 *
87 */
88
89
90/* LINTLIBRARY */
91
92#include <errno.h>
93#include <stdio.h>
94#include <signal.h>
95#include "tailor.h"
96#include "tpkt.h"
97#include "mpkt.h"
98#include <sys/ioctl.h>
99#ifdef BSD42
100#include <sys/file.h>
101#endif
102#ifdef SYS5
103#include <fcntl.h>
104#endif
105
106#ifdef LPP
107#undef X25
108#undef BRIDGE_X25
109#undef TP4
110#endif
111
112#ifdef LPP
113#include "dgram.h"
114#endif
115#ifdef TCP
116#include "internet.h"
117#endif
118#ifdef X25
119#include "x25.h"
120#endif
121#ifdef TP4
122#include "tp4.h"
123#endif
124
125
126#ifdef LPP
127#undef MGMT
128#endif
129
130/* \f DATA */
131
132union naddr {
133#ifdef TCP
134 struct sockaddr_in lb_un_isock;
135#endif
136
137#if defined(X25) || defined(BRIDGE_X25)
138 struct NSAPaddr lb_un_xsock;
139#endif
140
141#ifdef TP4
142 struct TSAPaddr lb_un_tsock;
143#endif
144
145 int lb_dummy;
146};
147
148
149struct listenblk {
150 struct listenblk *lb_forw; /* doubly-linked list */
151 struct listenblk *lb_back; /* .. */
152
153 int lb_fd; /* network handle */
154#define LISTEN_EXCEPTED (-2) /* magic value */
155
156 int lb_type; /* either listener, or exception handler */
157#define LB_UNDEF 0
158#define LB_LISTEN 1
159#define LB_ACCEPT 2
160#define LB_ACCEPTNOW 3
161#define LB_EXCEPTION 4
162#ifndef LPP
163#define LB_QUEUED 5
164#endif
165
166 IFP lb_magic;
167
168 struct TSAPaddr lb_addr; /* transport address */
169
170 struct tsapblk *lb_tb;
171
172 union naddr lb_un1;
173#define lb_loc_isock lb_un1.lb_un_isock
174#define lb_loc_xsock lb_un1.lb_un_xsock
175#define lb_loc_nsock lb_un1.lb_un_nsock
176#define lb_loc_tsock lb_un1.lb_un_tsock
177 union naddr lb_un3;
178#define lb_rem_isock lb_un3.lb_un_isock
179#define lb_rem_xsock lb_un3.lb_un_xsock
180#define lb_rem_nsock lb_un3.lb_un_nsock
181#define lb_rem_tsock lb_un3.lb_un_tsock
182
183 union {
184 struct {
185 IFP accept1; /* accept 1 function */
186 IFP accept2; /* accept 2 function */
187 } lb_un_accept;
188 IFP lb_un_except; /* exception function */
189 } lb_un2;
190#define lb_accept1 lb_un2.lb_un_accept.accept1
191#define lb_accept2 lb_un2.lb_un_accept.accept2
192#define lb_except lb_un2.lb_un_except
193
194 IFP lb_close; /* close function */
195};
196#define NULLLBP ((struct listenblk *) 0)
197
198static int once_only = 0;
199static struct listenblk listenque;
200static struct listenblk *LHead = &listenque;
201
202
203struct listenblk *findlblk (), *newlblk (), *findlblkbyfd ();
204
205
206/*
207 * Event block abstraction. An event block is generated by interfaces
208 * that might need to do things occasionally. Currently this is only
209 * the bridge but other things should be slot inable.
210 * The idea is you but a listenblk of the exception type on a fd.
211 * If the fd `goes off' the listenblk is destroyed and an eventblk
212 * created which will be called every 60 seconds for blocking listens,
213 * and before each listen otherwise.
214 */
215
216struct eventblk {
217 struct eventblk *ev_forw; /* doubly-linked list */
218 struct eventblk *ev_back; /* .. */
219
220 struct TSAPaddr ev_taddr; /* associated address */
221
222 IFP ev_eventfnx; /* the function to call */
223};
224#define NULLEVP ((struct eventblk *) 0)
225
226static struct eventblk eventqueue;
227static struct eventblk *EHead = &eventqueue;
228static int ev_onceonly = 0;
229static int ev_count = 0;
230
231struct eventblk *neweblk ();
232
233
234#define add_fd(fd) \
235{ \
236 if ((fd) >= acl_nfds) \
237 acl_nfds = (fd) + 1; \
238 if (acl_count++ == 0) \
239 FD_ZERO (&acl_mask); \
240 FD_SET (fd, &acl_mask); \
241}
242#define del_fd(fd) \
243{ \
244 if ((fd) + 1 == acl_nfds) \
245 acl_nfds--; \
246 if (--acl_count == 0) \
247 acl_nfds = 0; \
248 FD_CLR (fd, &acl_mask); \
249}
250
251static int acl_nfds = 0;
252static int acl_count = 0;
253static fd_set acl_mask;
254
255static int qw_nfds = 0;
256static int qw_count = 0;
257static fd_set qw_mask;
258
259
260int startlb (), uniqlb ();
261
262/* \f */
263
264#ifdef TCP
265int tcplisten (), tcpaccept1 (), tcpaccept2 (), tcpunique ();
266#endif
267#ifdef X25
268int x25listen (), x25accept1 (), x25accept2 (), x25unique ();
269#endif
270#ifdef BRIDGE_X25
271int bridgelisten (), bridgeaccept1 (), bridgeaccept2 (), bridgeunique ();
272int close_bridge_socket (), bridge_except ();
273#endif
274#ifdef TP4
275int tp4listen (), tp4accept1 (), tp4accept2 (), tp4unique ();
276#endif
277
278static struct nsapent {
279 int ns_type;
280 int ns_stack;
281
282 IFP ns_listen;
283 IFP ns_accept1;
284 IFP ns_accept2;
285 IFP ns_unique;
286 IFP ns_close;
287} nsaps[] = {
288#ifdef TCP
289 NA_TCP, TS_TCP,
290 tcplisten, tcpaccept1, tcpaccept2, tcpunique, close_tcp_socket,
291#endif
292
293#ifdef X25
294 NA_X25, TS_X25,
295 x25listen, x25accept1, x25accept2, x25unique, close_x25_socket,
296#endif
297
298#ifdef BRIDGE_X25
299 NA_BRG, TS_BRG,
300 bridgelisten, bridgeaccept1, bridgeaccept2, bridgeunique, close_bridge_socket,
301#endif
302
303#ifdef TP4
304 NA_NSAP, TS_TP4,
305 tp4listen, tp4accept1, tp4accept2, tp4unique, close_tp4_socket,
306#endif
307
308 NULL
309};
310
311
312#ifdef LPP
313static int _lpp_fd = NOTOK;
314
315u_short _lpp_lastport; /* MOBY HACK */
316#endif
317
318
319#ifdef BSD42
320static int chldhit;
321
322SFD chldser ();
323#endif
324
325
326extern int errno;
327
328/* \f */
329
330int TNetListen (ta, td)
331register struct TSAPaddr *ta;
332struct TSAPdisconnect *td;
333{
334 return TNetWork (ta, td, startlb, NULLIFP);
335}
336
337int TNetListenAux (ta, magic, td)
338register struct TSAPaddr *ta;
339IFP magic;
340struct TSAPdisconnect *td;
341{
342 return TNetWork (ta, td, startlb, magic);
343}
344
345
346int TNetUnique (ta, td)
347register struct TSAPaddr *ta;
348struct TSAPdisconnect *td;
349{
350 return TNetWork (ta, td, uniqlb, NULLIFP);
351}
352
353/* \f */
354
355static int TNetWork (ta, td, fnx, magic)
356register struct TSAPaddr *ta;
357struct TSAPdisconnect *td;
358IFP fnx;
359IFP magic;
360{
361 register int n;
362 int lstn = NOTOK;
363 int fd;
364 register struct NSAPaddr *na;
365 register struct nsapent *ns;
366 struct TSAPdisconnect tds;
367#ifdef MGMT
368 struct TSAPaddr tas;
369 register struct NSAPaddr *ca;
370#endif
371
372 if ((n = ta -> ta_naddr) > NTADDR)
373 return tsaplose (td, DR_PARAMETER, NULLCP,
374 "illegal number of network addresses");
375
376 if (n == 0) {
377 if (fnx == startlb) {
378 for (ns = nsaps; ns -> ns_listen; ns++)
379 if (ns -> ns_type == NA_NSAP && (ns -> ns_stack & ts_stacks))
380 break;
381 if (!ns -> ns_listen)
382 return tsaplose (td, DR_PARAMETER, NULLCP,
383 "unsupported network address (%d)", NA_NSAP);
384
385 fd = (*fnx) (ta, NULLNA, ns, magic, td);
386#ifdef MGMT
387 if (fd == OK)
388 (void) TManGen (STARTLISTEN, NULLBP, ta);
389#endif
390
391 return fd;
392 }
393
394 na = ta -> ta_addrs;
395 for (ns = nsaps; ns -> ns_listen; ns++)
396 if (ns -> ns_stack & ts_stacks) {
397 na -> na_stack = ns -> ns_type;
398 na++;
399 }
400 if ((n = ta -> ta_naddr = na - ta -> ta_addrs) == 0)
401 return tsaplose (td, DR_PARAMETER, NULLCP,
402 "no transport stacks active!?!");
403 }
404
405#ifdef MGMT
406 bzero ((char *) &tas, sizeof tas);
407 if (tas.ta_selectlen = ta -> ta_selectlen)
408 bcopy (ta -> ta_selector, tas.ta_selector, ta -> ta_selectlen);
409 ca = tas.ta_addrs;
410#endif
411
412 /*
413 * stricter checking in force, the proposed listen address must
414 * now be in the communities and not in the tsb communities.
415 * This allows us to give a list of addresses and let this code
416 * sort out the useful from the useless.
417 */
418 for (na = ta -> ta_addrs; n-- > 0; na++) {
419 int *ip;
420
421 for (ns = nsaps; ns -> ns_listen; ns++)
422 if (ns -> ns_type == na -> na_stack && (ns -> ns_stack & ts_stacks))
423 break;
424
425 if (!ns -> ns_listen) /* not one of our supported stacks */
426 continue;
427
428 for (ip = ts_communities; *ip; ip++)
429 if (na -> na_subnet == *ip)
430 break;
431 if (!*ip) /* stack ok, community wrong */
432 continue;
433
434 for (ip = tsb_communities; *ip; ip ++)
435 if (na -> na_subnet == *ip)
436 break;
437 if (*ip) /* only reachable via tsbridge - ignore */
438 continue;
439
440 if ((fd = (*fnx) (ta, na, ns, magic, td)) == NOTOK)
441 goto out;
442
443 lstn = OK;
444#ifdef MGMT
445 *ca++ = *na; /* struct copy */
446#endif
447 }
448
449 if (lstn == OK) {
450#ifdef MGMT
451 tas.ta_naddr = ca - tas.ta_addrs;
452 (void) TManGen (STARTLISTEN, NULLBP, &tas);
453#endif
454
455 return OK;
456 }
457
458 (void) tsaplose (td, DR_PARAMETER, NULLCP,
459 "no supported network addresses");
460
461out: ;
462 (void) TNetClose (ta, &tds);
463 return NOTOK;
464}
465
466/* \f */
467
468static int startlb (ta, na, ns, magic, td)
469register struct TSAPaddr *ta;
470register struct NSAPaddr *na;
471register struct nsapent *ns;
472IFP magic;
473struct TSAPdisconnect *td;
474{
475 struct TSAPaddr tas;
476 register struct listenblk *lb;
477
478 bzero ((char *) &tas, sizeof tas);
479 bcopy (ta -> ta_selector, tas.ta_selector,
480 tas.ta_selectlen = ta -> ta_selectlen);
481 if (na) {
482 tas.ta_naddr = 1;
483 tas.ta_addrs[0] = *na; /* struct copy */
484 }
485
486 ta = &tas;
487
488 if (lb = findlblk (ta, LB_LISTEN))
489 return tsaplose (td, DR_OPERATION, NULLCP,
490 "already listening on %s", taddr2str (ta));
491
492 if ((lb = newlblk (LB_LISTEN, ta)) == NULLLBP)
493 return tsaplose (td, DR_CONGEST, NULLCP, NULLCP);
494 lb -> lb_accept1 = ns -> ns_accept1;
495 lb -> lb_accept2 = ns -> ns_accept2;
496 lb -> lb_close = ns -> ns_close;
497 lb -> lb_magic = magic;
498
499 if ((lb -> lb_fd = (*ns -> ns_listen) (lb, ta, td)) == NOTOK) {
500 freelblk (lb);
501 return NOTOK;
502 }
503 else
504 if (lb -> lb_fd == LISTEN_EXCEPTED)
505 lb -> lb_fd = NOTOK;
506 else
507 add_fd (lb -> lb_fd);
508
509 return OK;
510}
511
512/* \f */
513
514static int uniqlb (ta, na, ns, magic, td)
515register struct TSAPaddr *ta;
516register struct NSAPaddr *na;
517register struct nsapent *ns;
518IFP magic;
519struct TSAPdisconnect *td;
520{
521 int fd;
522 struct TSAPaddr tas;
523 register struct listenblk *lb;
524
525 bzero ((char *) &tas, sizeof tas);
526 bcopy (ta -> ta_selector, tas.ta_selector,
527 tas.ta_selectlen = ta -> ta_selectlen);
528 tas.ta_naddr = 1;
529 tas.ta_addrs[0] = *na; /* struct copy */
530
531 if ((fd = (*ns -> ns_unique) (&tas, td)) == NOTOK)
532 return NOTOK;
533
534 bcopy (tas.ta_selector, ta -> ta_selector,
535 ta -> ta_selectlen = tas.ta_selectlen);
536 *na = tas.ta_addrs[0]; /* struct copy */
537
538 ta = &tas;
539 if ((lb = newlblk (LB_LISTEN, ta)) == NULLLBP)
540 return tsaplose (td, DR_CONGEST, NULLCP, NULLCP);
541
542 lb -> lb_fd = fd;
543 lb -> lb_magic = magic;
544 lb -> lb_accept1 = ns -> ns_accept1;
545 lb -> lb_accept2 = ns -> ns_accept2;
546 lb -> lb_close = ns -> ns_close;
547
548 add_fd (lb -> lb_fd);
549
550 return OK;
551}
552
553/* \f */
554
555int TNetAcceptAux (vecp, vec, newfd, ta, nfds, rfds, wfds, efds, secs, td)
556int *vecp;
557char **vec;
558int *newfd;
559struct TSAPaddr *ta;
560int nfds;
561fd_set *rfds,
562 *wfds,
563 *efds;
564int secs;
565struct TSAPdisconnect *td;
566{
567 int accepted,
568 fd,
569 fd2,
570 n,
571 xsecs;
572 fd_set ifds,
573 ofds,
574 xfds;
575 register struct listenblk *lb, *lb2;
576 static int inited = 0;
577
578 if (!inited) {
579#ifdef BSD42
580 (void) signal (SIGCHLD, chldser);
581#else
582 (void) signal (SIGCLD, SIG_IGN);
583#endif
584 if (acl_count == 0)
585 FD_ZERO (&acl_mask);
586 if (qw_count == 0)
587 FD_ZERO (&qw_mask);
588
589 inited = 1;
590 }
591
592 *vecp = 0;
593 *vec = NULL;
594 if (ta)
595 bzero ((char *) ta, sizeof *ta);
596 if (newfd)
597 *newfd = NOTOK;
598
599 if (acl_count == 0 && ev_count == 0 && qw_count == 0) {
600#ifdef BSD42
601retry: ;
602
603 chldhit = 0;
604#endif
605 if ((n = xselect (nfds, rfds, wfds, efds, secs)) == NOTOK) {
606#ifdef BSD42
607 if (errno == EINTR && chldhit)
608 goto retry;
609#endif
610 (void) tsaplose (td, DR_CONGEST, "failed", "xselect");
611 }
612
613 return n;
614 }
615
616 if (acl_nfds >= nfds)
617 nfds = acl_nfds + 1;
618 ifds = acl_mask;
619 if (rfds)
620 for (fd = 0; fd < nfds; fd++)
621 if (FD_ISSET (fd, rfds))
622 FD_SET (fd, &ifds);
623
624 if (qw_nfds >= nfds)
625 nfds = qw_nfds + 1;
626 ofds = qw_mask;
627 if (wfds)
628 for (fd = 0; fd < nfds; fd++)
629 if (FD_ISSET (fd, wfds))
630 FD_SET (fd, &ofds);
631
632 FD_ZERO (&xfds);
633 if (efds)
634 xfds = *efds; /* struct copy */
635
636 for (;;) {
637 xsecs = secs;
638 if (ev_count) {
639 if (secs == NOTOK)
640 xsecs = 60; /* infinite timeout, arrange for periodic */
641 else
642 check_events (); /* single attempt */
643 }
644
645#ifdef BSD42
646 chldhit = 0;
647#endif
648 switch (n = xselect (nfds, &ifds, &ofds, efds, xsecs)) {
649 case OK:
650 if (secs == NOTOK && ev_count) { /* just a timeout */
651 check_events ();
652 goto next;
653 }
654empty: ;
655 if (rfds)
656 FD_ZERO (rfds);
657 if (wfds)
658 FD_ZERO (wfds);
659 if (efds)
660 FD_ZERO (efds);
661 return OK;
662
663 case NOTOK:
664#ifdef BSD42
665 if (errno == EINTR && chldhit)
666 goto next;
667#endif
668 return tsaplose (td, DR_CONGEST, "failed", "xselect");
669
670 default:
671 accepted = 0;
672 for (lb = LHead -> lb_forw; lb != LHead; ) {
673 lb = (lb2 = lb) -> lb_forw;
674 if ((fd = lb2 -> lb_fd) == NOTOK)
675 continue;
676#ifndef LPP
677 if (lb2 -> lb_type == LB_QUEUED) {
678 if (FD_ISSET (fd, &ofds)) {
679 n --;
680 if (TDoQueues (lb2, td) == NOTOK) {
681 if (rfds && FD_ISSET (fd, rfds)) {
682 /* on error, force caller to look at it */
683 FD_ZERO (rfds);
684 FD_SET (fd, rfds);
685 if (wfds)
686 FD_ZERO (wfds);
687 if (efds)
688 FD_ZERO (efds);
689
690 return 1;
691 }
692
693 SLOG (tsap_log, LLOG_EXCEPTIONS, NULLCP,
694 ("unable to propagate failure of queued write"));
695 return NOTOK;
696 }
697
698 FD_CLR (fd, &ofds);
699 }
700
701 continue;
702 }
703#endif
704 if (FD_ISSET (fd, &ifds)) {
705 n --; /* we are using one up */
706 FD_CLR (fd, &ifds);
707 switch (lb2 -> lb_type) {
708 case LB_LISTEN:
709 errno = 0;
710 if ((fd2 = (*lb2 -> lb_accept1) (lb2, td))
711 == NOTOK) {
712 if (errno == EWOULDBLOCK)
713 continue;
714 return NOTOK;
715 }
716 if ((lb2 = findlblkbyfd (fd2)) == NULL)
717 break;
718 if (lb2 -> lb_type != LB_ACCEPTNOW)
719 break;
720 fd = fd2;
721 /* else fall */
722
723 case LB_ACCEPT:
724 {
725 /* take care - lb2 is free'd by accept2 */
726 IFP closefnx = lb2 -> lb_close,
727 magicfnx = lb2 -> lb_magic;
728
729 if (accepted) /* only 1 accept at a time */
730 break; /* we'll get it next time */
731 if (ta)
732 *ta = lb2 -> lb_addr; /* struct copy */
733 if ((*lb2 -> lb_accept2) (lb2, vecp, vec,
734 td) == NOTOK)
735 return NOTOK;
736 if (newfd)
737 *newfd = fd;
738 if (magicfnx
739 && (*magicfnx) (vecp, vec, td)
740 == NOTOK) {
741 (void) (*closefnx) (fd);
742 return NOTOK;
743 }
744 accepted++;
745 }
746 break;
747
748 case LB_EXCEPTION:
749 if (exception (lb2, td) == NOTOK)
750 return NOTOK;
751 break;
752
753 default:
754 return tsaplose (td, DR_UNKNOWN, NULLCP,
755 "invalid block type");
756 }
757 }
758 }
759 if (!accepted) {
760 for (fd = 0 ; fd < nfds; fd++)
761 if (FD_ISSET (fd, &ifds)
762 || FD_ISSET (fd, &ofds)
763 || (efds && FD_ISSET (fd, efds)))
764 break;
765 if (fd >= nfds) {
766 if (secs != NOTOK)
767 goto empty;
768
769 goto next;
770 }
771 }
772 if (rfds)
773 *rfds = ifds; /* struct copy */
774 if (wfds)
775 *wfds = ofds; /* struct copy */
776 return n;
777 }
778next: ;
779
780 if (acl_nfds >= nfds)
781 nfds = acl_nfds + 1;
782 ifds = acl_mask;
783 if (rfds)
784 for (fd = 0; fd < nfds; fd++)
785 if (FD_ISSET (fd, rfds))
786 FD_SET (fd, &ifds);
787
788 if (qw_nfds >= nfds)
789 nfds = qw_nfds + 1;
790 ofds = qw_mask;
791 if (wfds)
792 for (fd = 0; fd < nfds; fd++)
793 if (FD_ISSET (fd, wfds))
794 FD_SET (fd, &ofds);
795
796 if (efds)
797 *efds = xfds;
798 }
799}
800
801/* \f */
802
803static int exception (lb, td)
804struct listenblk *lb;
805struct TSAPdisconnect *td;
806{
807 register struct listenblk *lb2;
808 register struct eventblk *eb;
809
810 if ((lb2 = findlblk (&lb -> lb_addr, LB_LISTEN)) != NULLLBP)
811 freelblk (lb2);
812
813 if ((eb = neweblk (&lb -> lb_addr)) == NULLEVP)
814 return tsaplose (td, DR_CONGEST, NULLCP, "out of memory");
815 eb -> ev_eventfnx = lb -> lb_except;
816
817 SLOG (tsap_log, LLOG_EXCEPTIONS, NULLCP,
818 ("exception on %s", taddr2str (&lb -> lb_addr)));
819
820 freelblk (lb);
821
822 return OK;
823}
824
825
826static check_events ()
827{
828 register struct eventblk *eb,
829 *ep;
830 struct TSAPdisconnect tds;
831
832 for (eb = EHead -> ev_forw; eb != EHead; eb = ep) {
833 ep = eb -> ev_forw;
834 (void) (*eb -> ev_eventfnx) (eb, &tds);
835 }
836}
837
838/* \f */
839
840int TNetClose (ta, td)
841register struct TSAPaddr *ta;
842struct TSAPdisconnect *td;
843{
844 register struct listenblk *lb,
845 *lp;
846
847 if (ta == NULLTA) {
848 if (once_only == 0)
849 return OK;
850
851 for (lb = LHead -> lb_forw; lb != LHead; lb = lp) {
852 lp = lb -> lb_forw;
853 freelblk (lb);
854 }
855 }
856 else {
857 if (ta -> ta_naddr > 1) {
858 int gotone;
859 register int n = ta -> ta_naddr;
860 register struct NSAPaddr *na = ta -> ta_addrs;
861 struct TSAPaddr tas;
862
863 tas = *ta; /* struct copy */
864 tas.ta_naddr = 1;
865 gotone = 0;
866 for (na = ta -> ta_addrs, n = ta -> ta_naddr; n > 0; na++, n--) {
867 tas.ta_addrs[0] = *na; /* struct copy */
868 if (lb = findlblk (&tas, LB_LISTEN)) {
869 freelblk (lb);
870 gotone = 1;
871 }
872 }
873 if (!gotone)
874 return tsaplose (td, DR_PARAMETER, NULLCP,
875 "no such transport addressess");
876
877 return OK;
878 }
879
880 if ((lb = findlblk (ta, LB_LISTEN)) == NULLLBP)
881 return tsaplose (td, DR_PARAMETER, NULLCP,
882 "no such transport addressess");
883
884 freelblk (lb);
885 }
886
887 return OK;
888}
889
890/* \f */
891
892#ifdef BSD42
893#include <sys/wait.h>
894
895/* ARGSUSED */
896
897static SFD chldser (sig, code, sc)
898int sig;
899long code;
900struct sigcontext *sc;
901{
902 union wait status;
903
904 while (wait3 (&status, WNOHANG, (struct rusage *) NULL) > 0)
905 chldhit = 1;
906}
907#endif
908
909/* \f */
910
911#ifdef LPP
912/* ARGSUSED */
913#endif
914
915int TNetFork (vecp, vec, td)
916int vecp;
917char **vec;
918struct TSAPdisconnect *td;
919{
920 int pid;
921#ifdef TIOCNOTTY
922 int sd;
923#endif
924
925 switch (pid = fork ()) {
926 case OK:
927 break;
928
929 case NOTOK:
930 (void) tsaplose (td, DR_CONGEST, "connection",
931 "unable to fork, so rejecting");
932 default:
933#ifndef LPP
934 {
935 struct TSAPstart tss;
936 register struct TSAPstart *ts = &tss;
937 register struct tsapblk *tb;
938
939 if (TInit (vecp, vec, ts, td) == NOTOK) {
940 SLOG (tsap_log, LLOG_EXCEPTIONS, NULLCP,
941 ("TNetFork: TInit returns [%s]",
942 TErrString (td -> td_reason)));
943 return pid;
944 }
945
946 if ((tb = findtblk (ts -> ts_sd)) == NULL) {
947 SLOG (tsap_log, LLOG_EXCEPTIONS, NULLCP,
948 ("TNetFork: findtblk fails"));
949 return pid;
950 }
951
952 (void) (*tb -> tb_closefnx) (tb -> tb_fd);
953
954 tb -> tb_fd = NOTOK;
955 freetblk (tb);
956 }
957#else
958 if (_lpp_fd != NOTOK) {
959 (void) close_tcp_socket (_lpp_fd);
960 _lpp_fd = NOTOK;
961 }
962#endif
963
964 return pid;
965 }
966
967 (void) TNetClose (NULLTA, td);
968
969#ifdef SETSID
970 (void) setsid ();
971#endif
972#ifdef TIOCNOTTY
973 if ((sd = open ("/dev/tty", O_RDWR)) != NOTOK) {
974 (void) ioctl (sd, TIOCNOTTY, NULLCP);
975 (void) close (sd);
976 }
977#else
978#ifdef SYS5
979 (void) setpgrp ();
980 (void) signal (SIGINT, SIG_IGN);
981 (void) signal (SIGQUIT, SIG_IGN);
982#endif
983#endif
984 isodexport (NULLCP);
985
986#ifdef BSD42
987 (void) signal (SIGCHLD, SIG_DFL);
988#else
989 (void) signal (SIGCLD, SIG_DFL);
990#endif
991
992 return OK;
993}
994
995/* \f TCP */
996
997#ifdef TCP
998static int tcplisten (lb, ta, td)
999register struct listenblk *lb;
1000register struct TSAPaddr *ta;
1001struct TSAPdisconnect *td;
1002{
1003 int fd;
1004 register struct sockaddr_in *isock = &lb -> lb_loc_isock;
1005 register struct hostent *hp;
1006 register struct NSAPaddr *na;
1007
1008 if (ta -> ta_naddr < 1)
1009 return tsaplose (td, DR_ADDRESS, NULLCP, "TCP address not specified");
1010 na = ta -> ta_addrs;
1011
1012 if (na -> na_domain[0]) {
1013 if ((hp = gethostbystring (na -> na_domain)) == NULL)
1014 return tsaplose (td, DR_ADDRESS, NULLCP, "%s: unknown host",
1015 na -> na_domain);
1016 }
1017 else
1018 hp = NULL;
1019
1020 bzero ((char *) isock, sizeof *isock);
1021 isock -> sin_family = hp ? hp -> h_addrtype : AF_INET;
1022 if (na -> na_port == 0) {
1023 register struct servent *sp;
1024
1025 if ((sp = getservbyname ("tsap", "tcp")) == NULL)
1026 sp = getservbyname ("iso-tsap", "tcp");
1027 isock -> sin_port = sp ? sp -> s_port : htons ((u_short) 102);
1028 }
1029 else
1030 isock -> sin_port = na -> na_port;
1031 if (hp)
1032 inaddr_copy (hp, isock);
1033
1034 switch (na -> na_tset) {
1035#ifdef LPP
1036 case NA_TSET_UDP:
1037 if ((fd = start_udp_server (isock, 0, 0, 0)) == NOTOK)
1038 return tsaplose (td, DR_CONGEST, "failed", "start_udp_server");
1039 break;
1040#endif
1041
1042 case NA_TSET_TCP:
1043 default:
1044 if ((fd = start_tcp_server (isock, SOMAXCONN, 0, 0)) == NOTOK)
1045 return tsaplose (td, DR_CONGEST, "failed", "start_tcp_server");
1046 break;
1047 }
1048 lb -> lb_addr.ta_addrs -> na_tset = na -> na_tset;
1049
1050 return fd;
1051}
1052
1053/* \f */
1054
1055#ifdef LPP
1056char *udpsave ();
1057#endif
1058
1059
1060static int tcpaccept1 (lb, td)
1061register struct listenblk *lb;
1062struct TSAPdisconnect *td;
1063{
1064 int fd,
1065 tset = lb -> lb_addr.ta_addrs -> na_tset;
1066 struct listenblk *lb2;
1067 register struct tsapblk *tb = NULL;
1068#ifndef LPP
1069 register struct tsapkt *t = NULL;
1070#endif
1071
1072 if ((lb2 = newlblk (LB_ACCEPT, NULLTA)) == NULL) {
1073 (void) tsaplose (td, DR_CONGEST, NULLCP, "out of memory");
1074 goto out;
1075 }
1076
1077 switch (tset) {
1078#ifdef LPP
1079 case NA_TSET_UDP:
1080 if ((fd = join_udp_client (lb -> lb_fd, &lb2 -> lb_rem_isock))
1081 == NOTOK) {
1082 freelblk (lb2);
1083 return tsaplose (td, DR_NETWORK, "failed", "join_udp_client");
1084 }
1085 break;
1086#endif
1087
1088 case NA_TSET_TCP:
1089 default:
1090 if ((fd = join_tcp_client (lb -> lb_fd, &lb2 -> lb_rem_isock))
1091 == NOTOK) {
1092 freelblk (lb2);
1093 return tsaplose (td, DR_NETWORK, "failed", "join_tcp_client");
1094 }
1095
1096#ifdef LPP
1097 _lpp_fd = fd;
1098 _lpp_lastport = lb -> lb_loc_isock.sin_port;
1099#endif
1100#ifdef EXOS
1101 del_fd (lb -> lb_fd);
1102
1103 if ((lb -> lb_fd = start_tcp_server (&lb -> lb_loc_isock,
1104 SOMAXCONN, 0, 0)) != NOTOK) {
1105 add_fd (lb -> lb_fd);
1106 }
1107#endif
1108 break;
1109 }
1110
1111 lb2 -> lb_fd = fd;
1112 lb2 -> lb_addr = lb -> lb_addr;
1113 lb2 -> lb_loc_isock = lb -> lb_loc_isock;
1114 lb2 -> lb_accept2 = lb -> lb_accept2;
1115 lb2 -> lb_close = lb -> lb_close;
1116 lb2 -> lb_magic = lb -> lb_magic;
1117
1118#ifndef LPP
1119 if ((tb = newtblk ()) == NULL) {
1120 (void) tsaplose (td, DR_CONGEST, NULLCP, "out of memory");
1121 goto out;
1122 }
1123
1124 tb -> tb_fd = fd;
1125 (void) TTService (tb);
1126
1127 add_fd (fd);
1128#else
1129 lb2 -> lb_type = LB_ACCEPTNOW;
1130#endif
1131 lb2 -> lb_tb = tb;
1132
1133 return fd;
1134
1135out: ;
1136#ifndef LPP
1137 if (tb) {
1138 tb -> tb_fd = NOTOK;
1139 freetblk (tb);
1140 }
1141 freetpkt (t);
1142#endif
1143 if (lb2)
1144 freelblk (lb2);
1145
1146 return NOTOK;
1147}
1148
1149/* \f */
1150
1151static int tcpaccept2 (lb, vecp, vec, td)
1152register struct listenblk *lb;
1153int *vecp;
1154char **vec;
1155struct TSAPdisconnect *td;
1156{
1157 int fd;
1158#ifdef LPP
1159 int tset = lb -> lb_addr.ta_addrs -> na_tset;
1160#endif
1161 char buffer1[BUFSIZ],
1162 buffer2[BUFSIZ];
1163#ifdef SOCKETS
1164 struct sockaddr_in in_socket;
1165 struct sockaddr_in *isock = &in_socket;
1166 int len;
1167#endif
1168#ifndef LPP
1169 register struct tsapblk *tb = lb -> lb_tb;
1170 register struct tsapkt *t = NULL;
1171#endif
1172
1173 fd = lb -> lb_fd;
1174 (void) sprintf (buffer1, "%s+%d",
1175 inet_ntoa (lb -> lb_rem_isock.sin_addr),
1176 ntohs (lb -> lb_rem_isock.sin_port));
1177
1178#ifdef SOCKETS
1179 len = sizeof *isock;
1180 if (getsockname (fd, (struct sockaddr *) isock, &len) != NOTOK) {
1181 (void) sprintf (buffer2, "%s+%d",
1182 inet_ntoa (isock -> sin_addr),
1183 ntohs (isock -> sin_port));
1184 }
1185 else
1186#endif
1187 (void) sprintf (buffer2, "%s", TLocalHostName ());
1188
1189#ifndef LPP
1190 if ((t = fd2tpkt (fd, tb -> tb_initfnx,
1191 tb -> tb_readfnx)) == NULL || t -> t_errno != OK) {
1192 (void) tpktlose (tb, td, t ? t -> t_errno : DR_CONGEST, NULLCP,
1193 NULLCP);
1194 goto out;
1195 }
1196
1197 if (TPDU_CODE (t) != TPDU_CR) {
1198 (void) tpktlose (tb, td, DR_PROTOCOL, NULLCP,
1199 "transport protocol mangled: expecting 0x%x, got 0x%x",
1200 TPDU_CR, TPDU_CODE (t));
1201 goto out;
1202 }
1203
1204 if (lb -> lb_addr.ta_selectlen > 0
1205 && (lb -> lb_addr.ta_selectlen != t -> t_calledlen
1206 || bcmp (lb -> lb_addr.ta_selector,
1207 t -> t_called,
1208 lb -> lb_addr.ta_selectlen))) {
1209 (void) tpktlose (tb, td, DR_SESSION, NULLCP,
1210 "not expecting connection for tsap/%s",
1211 sel2str (t -> t_called, t -> t_calledlen, 1));
1212 goto out;
1213 }
1214
1215 vec[0] = "tsaplisten"; /* any value will do */
1216
1217 if ((vec[1] = tcpsave (fd, buffer1, buffer2, td)) == NULL)
1218 goto out;
1219
1220 if ((vec[2] = tpkt2str (t)) == NULL) {
1221 (void) tsaplose (td, DR_CONGEST, NULLCP, NULLCP);
1222 goto out;
1223 }
1224
1225 vec[*vecp = 3] = NULLCP;
1226
1227 tb -> tb_fd = NOTOK;
1228 freetblk (tb);
1229 freetpkt (t);
1230 del_fd (lb -> lb_fd);
1231#else
1232 vec[0] = "psaplisten";
1233
1234 switch (tset) {
1235 case NA_TSET_UDP:
1236 if ((vec[1] = udpsave (fd, buffer1, buffer2, td)) == NULL)
1237 goto out;
1238 break;
1239
1240 case NA_TSET_TCP:
1241 default:
1242 if ((vec[1] = tcpsave (fd, buffer1, buffer2, td)) == NULL)
1243 goto out;
1244 break;
1245 }
1246
1247 vec[*vecp = 2] = NULLCP;
1248#endif
1249
1250 lb -> lb_fd = NOTOK;
1251 freelblk (lb);
1252 return OK;
1253
1254out: ;
1255#ifndef LPP
1256 if (tb) {
1257 tb -> tb_fd = NOTOK;
1258 freetblk (tb);
1259 }
1260 freetpkt (t);
1261#endif
1262 if (lb)
1263 freelblk (lb);
1264
1265 return NOTOK;
1266}
1267
1268/* \f */
1269
1270static int tcpunique (ta, td)
1271register struct TSAPaddr *ta;
1272struct TSAPdisconnect *td;
1273{
1274 int fd;
1275 char *cp;
1276 struct sockaddr_in in_socket;
1277 register struct sockaddr_in *isock = &in_socket;
1278 register struct hostent *hp;
1279 register struct NSAPaddr *na = ta -> ta_addrs;
1280
1281 cp = na -> na_domain[0] ? na -> na_domain : TLocalHostName ();
1282 if ((hp = gethostbystring (cp)) == NULL)
1283 return tsaplose (td, DR_ADDRESS, NULLCP, "%s: unknown host", cp);
1284
1285 bzero ((char *) isock, sizeof *isock);
1286 isock -> sin_family = hp -> h_addrtype;
1287 inaddr_copy (hp, isock);
1288
1289 switch (na -> na_tset) {
1290#ifdef LPP
1291 case NA_TSET_UDP:
1292 if ((fd = start_udp_server (isock, 0, 0, 0)) == NOTOK)
1293 return tsaplose (td, DR_CONGEST, "failed", "start_udp_server");
1294 break;
1295#endif
1296
1297 case NA_TSET_TCP:
1298 default:
1299 if ((fd = start_tcp_server (isock, SOMAXCONN, 0, 0)) == NOTOK)
1300 return tsaplose (td, DR_CONGEST, "failed", "start_tcp_server");
1301 break;
1302 }
1303 (void) strcpy (na -> na_domain, inet_ntoa (isock -> sin_addr));
1304 na -> na_port = isock -> sin_port;
1305
1306 return fd;
1307}
1308#endif
1309
1310/* \f X.25 */
1311
1312#ifdef X25
1313
1314/* ARGSUSED */
1315
1316static int x25listen (lb, ta, td)
1317struct listenblk *lb;
1318struct TSAPaddr *ta;
1319struct TSAPdisconnect *td;
1320{
1321 int fd;
1322
1323 if (ta -> ta_naddr < 1)
1324 return tsaplose (td, DR_ADDRESS, NULLCP, "X.121 DTE not specified");
1325
1326 if ((fd = start_x25_server (ta -> ta_addrs, SOMAXCONN, 0, SO_KEEPALIVE))
1327 == NOTOK)
1328 return tsaplose (td, DR_CONGEST, "failed", "start_x25_server");
1329
1330 lb -> lb_loc_xsock = *ta -> ta_addrs;
1331
1332 return fd;
1333}
1334
1335/* \f */
1336
1337static int x25accept1 (lb, td)
1338register struct listenblk *lb;
1339struct TSAPdisconnect *td;
1340{
1341 int fd;
1342 register struct tsapblk *tb;
1343 struct listenblk *lb2;
1344
1345 if ((lb2 = newlblk (LB_ACCEPT, NULLTA)) == NULL) {
1346 tsaplose (td, DR_CONGEST, NULLCP, "out of memory");
1347 goto out;
1348 }
1349
1350 lb2 -> lb_accept2 = lb -> lb_accept2;
1351 lb2 -> lb_addr = lb -> lb_addr;
1352 lb2 -> lb_close = lb -> lb_close;
1353 lb2 -> lb_loc_xsock = lb -> lb_loc_xsock;
1354 lb2 -> lb_magic = lb -> lb_magic;
1355
1356 if ((fd = join_x25_client (lb -> lb_fd, &lb2 -> lb_rem_xsock)) == NOTOK) {
1357 freelblk (lb2);
1358 return tsaplose (td, DR_NETWORK, "failed", "join_x25_client");
1359 }
1360
1361 lb2 -> lb_fd = fd;
1362
1363 if ((tb = newtblk ()) == NULL) {
1364 (void) tsaplose (td, DR_CONGEST, NULLCP, "out of memory");
1365 goto out;
1366 }
1367
1368 tb -> tb_fd = fd;
1369 (void) XTService (tb);
1370
1371 lb2 -> lb_tb = tb;
1372 add_fd (fd);
1373
1374 return fd;
1375
1376out: ;
1377 if (tb) {
1378 tb -> tb_fd = NOTOK;
1379 freetblk (tb);
1380 }
1381 if (lb2)
1382 freelblk (lb2);
1383
1384 return NOTOK;
1385}
1386
1387/* \f */
1388
1389static int x25accept2 (lb, vecp, vec, td)
1390register struct listenblk *lb;
1391int *vecp;
1392char **vec;
1393struct TSAPdisconnect *td;
1394{
1395 register struct tsapblk *tb = lb -> lb_tb;
1396 register struct tsapkt *t = NULL;
1397 int fd;
1398
1399
1400 if ((t = fd2tpkt (fd = tb -> tb_fd, tb -> tb_initfnx,
1401 tb -> tb_readfnx)) == NULL || t -> t_errno != OK) {
1402 (void) tpktlose (tb, td, t ? t -> t_errno : DR_CONGEST, NULLCP,
1403 NULLCP);
1404 goto out;
1405 }
1406
1407 if (TPDU_CODE (t) != TPDU_CR) {
1408 (void) tpktlose (tb, td, DR_PROTOCOL, NULLCP,
1409 "transport protocol mangled: expecting 0x%x, got 0x%x",
1410 TPDU_CR, TPDU_CODE (t));
1411 goto out;
1412 }
1413
1414 if (lb -> lb_addr.ta_selectlen > 0
1415 && (lb -> lb_addr.ta_selectlen != t -> t_calledlen
1416 || bcmp (lb -> lb_addr.ta_selector,
1417 t -> t_called,
1418 lb -> lb_addr.ta_selectlen))) {
1419 (void) tpktlose (tb, td, DR_SESSION, NULLCP,
1420 "not expecting connection for tsap/%s",
1421 sel2str (t -> t_called, t -> t_calledlen, 1));
1422 goto out;
1423 }
1424
1425 vec[0] = "tsaplisten"; /* any value will do */
1426
1427 if ((vec[1] = x25save (fd, lb -> lb_rem_xsock.na_dte,
1428 lb -> lb_rem_xsock.na_dtelen,
1429 lb -> lb_loc_xsock.na_dte,
1430 lb -> lb_loc_xsock.na_dtelen, td)) == NULL)
1431 goto out;
1432 if ((vec[2] = tpkt2str (t)) == NULL) {
1433 (void) tsaplose (td, DR_CONGEST, NULLCP, NULLCP);
1434 goto out;
1435 }
1436
1437 vec[*vecp = 3] = NULLCP;
1438
1439 tb -> tb_fd = NOTOK;
1440 freetblk (tb);
1441 freetpkt (t);
1442 lb -> lb_fd = NOTOK;
1443 del_fd (fd);
1444 freelblk (lb);
1445
1446 return fd;
1447
1448out: ;
1449 if (tb) {
1450 tb -> tb_fd = NOTOK;
1451 freetblk (tb);
1452 }
1453 freetpkt (t);
1454 freelblk (lb);
1455
1456 return NOTOK;
1457}
1458
1459/* \f */
1460
1461static int x25unique (ta, td)
1462struct TSAPaddr *ta;
1463struct TSAPdisconnect *td;
1464{
1465 int fd;
1466 register struct NSAPaddr *na = ta -> ta_addrs;
1467
1468 bzero ((char *) na, sizeof *na);
1469 na -> na_stack = NA_X25;
1470
1471 if ((fd = start_x25_server (na, SOMAXCONN, 0, SO_KEEPALIVE)) == NOTOK)
1472 return tsaplose (td, DR_CONGEST, "failed", "start_x25_server");
1473
1474 return fd;
1475}
1476#endif
1477
1478/* \f */
1479
1480#ifdef BRIDGE_X25
1481
1482/* ARGSUSED */
1483
1484static int bridgelisten (lb, ta, td)
1485register struct listenblk *lb;
1486register struct TSAPaddr *ta;
1487struct TSAPdisconnect *td;
1488{
1489 int fd;
1490 register struct eventblk *eb;
1491
1492 if ((fd = bridgelisten_aux (lb, ta, td)) != NOTOK)
1493 return fd;
1494
1495 if ((eb = neweblk (ta)) == NULLEVP)
1496 return tsaplose (td, DR_CONGEST, NULLCP, "out of memory");
1497 eb -> ev_eventfnx = bridge_except;
1498
1499 return LISTEN_EXCEPTED;
1500}
1501
1502
1503static int bridge_except (eb, td)
1504register struct eventblk *eb;
1505struct TSAPdisconnect *td;
1506{
1507 register struct listenblk *lb;
1508 register struct TSAPaddr *ta = &eb -> ev_taddr;
1509
1510 if ((lb = newlblk (LB_LISTEN, ta)) == NULLLBP)
1511 return tsaplose (td, DR_CONGEST, NULLCP, "out of memory");
1512 if ((lb -> lb_fd = bridgelisten_aux (lb, ta, td)) == NOTOK) {
1513 freelblk (lb);
1514 return OK;
1515 }
1516 SLOG (tsap_log, LLOG_EXCEPTIONS, NULLCP,
1517 ("reconnection on %s", taddr2str (ta)));
1518 freeeblk (eb);
1519
1520 lb -> lb_close = close_bridge_socket;
1521 lb -> lb_accept1 = bridgeaccept1;
1522 lb -> lb_accept2 = bridgeaccept2;
1523 add_fd (lb -> lb_fd);
1524
1525 return OK;
1526}
1527
1528
1529static int bridgelisten_aux (lb, ta, td)
1530register struct listenblk *lb;
1531register struct TSAPaddr *ta;
1532struct TSAPdisconnect *td;
1533{
1534 int fd;
1535 register struct listenblk *lb2;
1536
1537 if (ta -> ta_naddr < 1)
1538 return tsaplose (td, DR_ADDRESS, NULLCP, "X.121 DTE not specified");
1539
1540 if ((fd = start_bridge_server (ta -> ta_addrs, SOMAXCONN, 0, SO_KEEPALIVE))
1541 == NOTOK)
1542 return tsaplose (td, DR_CONGEST, "failed", "start_bridge_server");
1543
1544 lb -> lb_loc_xsock = *ta -> ta_addrs;
1545 if ((lb2 = newlblk (LB_EXCEPTION, ta)) == NULLLBP) {
1546 close_bridge_socket (fd);
1547 return NOTOK;
1548 }
1549 lb2 -> lb_fd = get_bridge_assfd (fd);
1550 lb2 -> lb_except = bridge_except;
1551 lb2 -> lb_close = close_bridge_socket;
1552
1553 add_fd (lb2 -> lb_fd);
1554
1555 return fd;
1556}
1557
1558/* \f */
1559
1560static int bridgeaccept1 (lb, td)
1561register struct listenblk *lb;
1562struct TSAPdisconnect *td;
1563{
1564 int fd;
1565 register struct tsapblk *tb;
1566 register struct tsapkt *t = NULL;
1567 struct listenblk *lb2;
1568
1569 if ((lb2 = newlblk (LB_ACCEPT, NULLTA)) == NULL) {
1570 (void) tsaplose (td, DR_CONGEST, NULLCP, "out of memory");
1571 goto out;
1572 }
1573 lb2 -> lb_accept2 = lb -> lb_accept2;
1574 lb2 -> lb_addr = lb -> lb_addr;
1575 lb2 -> lb_close = lb -> lb_close;
1576 lb2 -> lb_loc_xsock = lb -> lb_loc_xsock;
1577 lb2 -> lb_magic = lb -> lb_magic;
1578
1579 if ((fd = join_bridge_client (lb -> lb_fd, &lb2 -> lb_rem_xsock))
1580 == NOTOK) {
1581 freelblk (lb2);
1582 return tsaplose (td, DR_NETWORK, "failed", "join_bridge_client");
1583 }
1584
1585 lb2 -> lb_fd = fd;
1586
1587 if ((tb = newtblk ()) == NULL) {
1588 (void) tsaplose (td, DR_CONGEST, NULLCP, "out of memory");
1589 goto out;
1590 }
1591 lb2 -> lb_tb = tb;
1592
1593 tb -> tb_fd = fd;
1594 (void) BTService (tb);
1595
1596 add_fd (fd);
1597 return fd;
1598
1599out: ;
1600 if (tb) {
1601 tb -> tb_fd = NOTOK;
1602 freetblk (tb);
1603 }
1604 if (lb2)
1605 freelblk (lb2);
1606 freetpkt (t);
1607
1608 return NOTOK;
1609}
1610
1611/* \f */
1612
1613static int bridgeaccept2 (lb, vecp, vec, td)
1614register struct listenblk *lb;
1615int *vecp;
1616char **vec;
1617struct TSAPdisconnect *td;
1618{
1619 int fd = lb -> lb_fd;
1620 register struct tsapblk *tb = lb -> lb_tb;
1621 register struct tsapkt *t = NULL;
1622
1623
1624 if ((t = fd2tpkt (tb -> tb_fd, tb -> tb_initfnx, tb -> tb_readfnx)) == NULL
1625 || t -> t_errno != OK) {
1626 (void) tpktlose (tb, td, t ? t -> t_errno : DR_CONGEST, NULLCP,
1627 NULLCP);
1628 goto out;
1629 }
1630
1631 if (TPDU_CODE (t) != TPDU_CR) {
1632 (void) tpktlose (tb, td, DR_PROTOCOL, NULLCP,
1633 "transport protocol mangled: expecting 0x%x, got 0x%x",
1634 TPDU_CR, TPDU_CODE (t));
1635 goto out;
1636 }
1637
1638 if (lb -> lb_addr.ta_selectlen > 0
1639 && (lb -> lb_addr.ta_selectlen != t -> t_calledlen
1640 || bcmp (lb -> lb_addr.ta_selector,
1641 t -> t_called,
1642 lb -> lb_addr.ta_selectlen))) {
1643 (void) tpktlose (tb, td, DR_SESSION, NULLCP,
1644 "not expecting connection for tsap/%s",
1645 sel2str (t -> t_called, t -> t_calledlen, 1));
1646 goto out;
1647 }
1648
1649 vec[0] = "tsaplisten"; /* any value will do */
1650
1651 if ((vec[1] = bridgesave (tb -> tb_fd, lb -> lb_rem_xsock.na_dte,
1652 lb -> lb_rem_xsock.na_dtelen,
1653 lb -> lb_loc_xsock.na_dte,
1654 lb -> lb_loc_xsock.na_dtelen, td)) == NULL)
1655 goto out;
1656 if ((vec[2] = tpkt2str (t)) == NULL) {
1657 (void) tsaplose (td, DR_CONGEST, NULLCP, NULLCP);
1658 goto out;
1659 }
1660
1661 vec[*vecp = 3] = NULLCP;
1662
1663 tb -> tb_fd = NOTOK;
1664 freetblk (tb);
1665 freetpkt (t);
1666 del_fd (fd);
1667 lb -> lb_fd = NOTOK;
1668 freelblk (lb);
1669
1670 return fd;
1671
1672out: ;
1673 if (tb) {
1674 tb -> tb_fd = NOTOK;
1675 freetblk (tb);
1676 }
1677 freetpkt (t);
1678 freelblk (lb);
1679
1680 return NOTOK;
1681}
1682
1683/* \f */
1684
1685/* ARGSUSED */
1686
1687static int bridgeunique (ta, td)
1688struct TSAPaddr *ta;
1689struct TSAPdisconnect *td;
1690{
1691 return tsaplose (td, DR_ADDRESS, NULLCP,
1692 "unique listens not supported at the X.25 bridge");
1693}
1694#endif
1695
1696/* \f TP4 */
1697
1698#ifdef TP4
1699
1700/* \f TP4 from 4.4BSD */
1701
1702#ifdef BSD_TP4
1703/* ARGSUSED */
1704
1705static int tp4listen (lb, ta, td)
1706struct listenblk *lb;
1707register struct TSAPaddr *ta;
1708struct TSAPdisconnect *td;
1709{
1710 return start_tp4_server (ta, SOMAXCONN, SO_KEEPALIVE, 0, td);
1711}
1712
1713/* \f */
1714
1715static int tp4accept1 (lb, td)
1716register struct listenblk *lb;
1717struct TSAPdisconnect *td;
1718{
1719 int fd;
1720 register struct tsapblk *tb;
1721 struct listenblk *lb2;
1722
1723 if ((lb2 = newlblk (LB_ACCEPTNOW, NULLTA)) == NULL) {
1724 (void) tsaplose (td, DR_CONGEST, NULLCP, "out of memory");
1725 goto out;
1726 }
1727
1728 lb2 -> lb_accept2 = lb -> lb_accept2;
1729 lb2 -> lb_addr = lb -> lb_addr;
1730 lb2 -> lb_close = lb -> lb_close;
1731 lb2 -> lb_loc_tsock = lb -> lb_loc_tsock;
1732
1733 if ((fd = join_tp4_client (lb -> lb_fd, &lb2 -> lb_rem_tsock, td))
1734 == NOTOK) {
1735 freelblk (lb2);
1736 return NOTOK;
1737 }
1738
1739 lb2 -> lb_fd = fd;
1740
1741 if ((tb = newtblk ()) == NULL) {
1742 (void) tsaplose (td, DR_CONGEST, NULLCP, "out of memory");
1743 goto out;
1744 }
1745
1746 tb -> tb_fd = fd;
1747 (void) tp4init (tb);
1748
1749 lb2 -> lb_tb = tb;
1750
1751 copyTSAPaddrY (&tb -> tb_responding, &lb2 -> lb_rem_tsock);
1752
1753 return fd;
1754
1755out: ;
1756 if (tb) {
1757 tb -> tb_fd = NOTOK;
1758 freetblk (tb);
1759 }
1760 if (lb2)
1761 freelblk (lb2);
1762 return NOTOK;
1763}
1764
1765/* \f */
1766
1767static int tp4accept2 (lb, vecp, vec, td)
1768register struct listenblk *lb;
1769int *vecp;
1770char **vec;
1771struct TSAPdisconnect *td;
1772{
1773 int cc,
1774 cmsgtype,
1775 fd = lb -> lb_fd,
1776 len;
1777 char udata[TS_SIZE];
1778 register struct tsapblk *tb = lb -> lb_tb;
1779 union sockaddr_osi sock;
1780 struct sockaddr_iso *ifaddr = &sock.osi_sockaddr;
1781 static char buffer[BUFSIZ];
1782
1783 len = sizeof sock;
1784 if (getsockname (fd, (struct sockaddr *) ifaddr, &len) != NOTOK) {
1785 ifaddr -> siso_len = len;
1786 (void) tp42genX (&tb -> tb_initiating, &sock);
1787 }
1788 else
1789 SLOG (tsap_log, LLOG_EXCEPTIONS, "failed",
1790 ("getsockname on incoming connection"));
1791
1792 cc = sizeof udata;
1793 if (tp4getCmsg (fd, &cc, &cmsgtype, udata) == NOTOK) {
1794 (void) tsaplose (td, DR_CONGEST, "TPOPT_CONN_DATA", "unable to get");
1795 goto out;
1796 }
1797 if (cmsgtype != TPOPT_CONN_DATA)
1798 cc = 0;
1799
1800 vec[0] = "tsaplisten"; /* any value will do */
1801
1802 if ((vec[1] = tp4save (tb -> tb_fd, td)) == NULL)
1803 goto out;
1804 len = 0;
1805 if (cc > 0)
1806 len += explode (buffer + len, (u_char *) udata, cc);
1807 buffer[len] = NULL;
1808 vec[2] = buffer;
1809
1810 vec[*vecp = 3] = NULLCP;
1811
1812 tb -> tb_fd = NOTOK;
1813 freetblk (tb);
1814 lb -> lb_fd = NOTOK;
1815 freelblk (lb);
1816
1817 return OK;
1818
1819out: ;
1820 if (tb) {
1821 tb -> tb_fd = NOTOK;
1822 freetblk (tb);
1823 }
1824 freelblk (lb);
1825
1826 return NOTOK;
1827}
1828
1829/* \f */
1830
1831/* ARGSUSED */
1832
1833static int tp4unique (ta, td)
1834struct TSAPaddr *ta;
1835struct TSAPdisconnect *td;
1836{
1837 int fd;
1838 register struct NSAPaddr *na = ta -> ta_addrs;
1839
1840 bzero ((char *) na, sizeof *na);
1841 na -> na_stack = NA_NSAP;
1842
1843 return start_tp4_server (na, SOMAXCONN, SO_KEEPALIVE, 0, td);
1844}
1845#endif
1846
1847/* \f TP4 from SunLink OSI */
1848
1849#ifdef SUN_TP4
1850/* ARGSUSED */
1851
1852static int tp4listen (lb, ta, td)
1853struct listenblk *lb;
1854register struct TSAPaddr *ta;
1855struct TSAPdisconnect *td;
1856{
1857 return start_tp4_server (ta, SOMAXCONN, 0, 0, td);
1858}
1859
1860/* \f */
1861
1862static int tp4accept1 (lb, td)
1863register struct listenblk *lb;
1864struct TSAPdisconnect *td;
1865{
1866 int fd;
1867 register struct tsapblk *tb;
1868 struct listenblk *lb2;
1869
1870 if ((lb2 = newlblk (LB_ACCEPT, NULLTA)) == NULL) {
1871 (void) tsaplose (td, DR_CONGEST, NULLCP, "out of memory");
1872 goto out;
1873 }
1874
1875 lb2 -> lb_loc_isock = lb -> lb_loc_isock;
1876 lb2 -> lb_addr = lb -> lb_addr;
1877 lb2 -> lb_accept2 = lb -> lb_accept2;
1878 lb2 -> lb_close = lb -> lb_close;
1879 lb2 -> lb_magic = lb -> lb_magic;
1880
1881 if ((fd = join_tp4_client (lb -> lb_fd, &lb -> lb_rem_tsock, td))
1882 == NOTOK) {
1883 freelblk (lb2);
1884 return NOTOK;
1885 }
1886
1887 lb2 -> lb_fd = fd;
1888
1889 if ((tb = newtblk ()) == NULL) {
1890 (void) tsaplose (td, DR_CONGEST, NULLCP, "out of memory");
1891 goto out;
1892 }
1893 tb -> tb_fd = fd;
1894 (void) tp4init (tb);
1895
1896 add_fd (fd);
1897 lb2 -> lb_tb = tb;
1898
1899 return fd;
1900
1901out: ;
1902 if (tb) {
1903 tb -> tb_fd = NOTOK;
1904 freetblk (tb);
1905 }
1906 if (lb2)
1907 freelblk (lb2);
1908
1909 return NOTOK;
1910}
1911
1912/* \f */
1913
1914static int tp4accept2 (lb, vecp, vec, td)
1915register struct listenblk *lb;
1916int *vecp;
1917char **vec;
1918struct TSAPdisconnect *td;
1919{
1920 int cc,
1921 fd = lb -> lb_fd,
1922 header_len,
1923 len;
1924 char data[TC_SIZE];
1925 register struct tsapblk *tb = lb -> lb_tb;
1926 register struct tp4pkt *tp = NULL;
1927 static char buffer[BUFSIZ];
1928
1929 if ((tp = newtp4pkt ((TP_EVENT) 0)) == NULL) {
1930 (void) tsaplose (td, DR_CONGEST, NULLCP, NULLCP);
1931 goto out;
1932 }
1933
1934 header_len = sizeof (TP_MSG_CONNECT);
1935 if ((cc = recvfrom (fd, data, sizeof data, 0, (struct sockaddr *) tp,
1936 &header_len)) == NOTOK) {
1937 (void) tpktlose (tb, td, DR_CONGEST, "failed", "recvfrom");
1938 goto out;
1939 }
1940
1941 if (tp -> tp4_event != TP_CONNECT_IND) {
1942 (void) tpktlose (tb, td, DR_REMOTE, NULLCP,
1943 "transport protocol mangled: expecting 0x%x got 0x%x",
1944 TP_CONNECT_IND, tp -> tp4_event);
1945 goto out;
1946 }
1947
1948 (void) tp42genX (&tb -> tb_responding, &tp -> tp4_called);
1949 (void) tp42genX (&tb -> tb_initiating, &tp -> tp4_calling);
1950
1951 vec[0] = "tsaplisten"; /* any value will do */
1952
1953 if ((vec[1] = tp4save (tb -> tb_fd, td)) == NULL)
1954 goto out;
1955 len = explode (buffer, (u_char *) tp, sizeof (TP_MSG_CONNECT));
1956 if (cc > 0)
1957 len += explode (buffer + len, (u_char *) data, cc);
1958 buffer[len] = NULL;
1959 vec[2] = buffer;
1960
1961 vec[*vecp = 3] = NULLCP;
1962
1963 tb -> tb_fd = NOTOK;
1964 freetblk (tb);
1965 freetp4pkt (tp);
1966 del_fd (lb -> lb_fd);
1967 lb -> lb_fd = NOTOK;
1968 freelblk (lb);
1969
1970 return OK;
1971
1972out: ;
1973 if (tb) {
1974 tb -> tb_fd = NOTOK;
1975 freetblk (tb);
1976 }
1977 if (tp)
1978 freetp4pkt (tp);
1979 freelblk (lb);
1980 return NOTOK;
1981}
1982
1983/* \f */
1984
1985/* ARGSUSED */
1986
1987static int tp4unique (ta, td)
1988struct TSAPaddr *ta;
1989struct TSAPdisconnect *td;
1990{
1991 return tsaplose (td, DR_ADDRESS, NULLCP,
1992 "unique listens not yet supported with SunLink OSI");
1993}
1994#endif
1995
1996#endif
1997
1998/* \f INTERNAL */
1999
2000static struct listenblk *newlblk (type, ta)
2001int type;
2002struct TSAPaddr *ta;
2003{
2004 register struct listenblk *lb;
2005
2006 lb = (struct listenblk *) calloc (1, sizeof *lb);
2007 if (lb == NULLLBP)
2008 return lb;
2009
2010 lb -> lb_fd = NOTOK;
2011 if (ta)
2012 lb -> lb_addr = *ta; /* struct copy */
2013 lb -> lb_type = type;
2014
2015 if (once_only == 0) {
2016 LHead -> lb_forw = LHead -> lb_back = LHead;
2017 once_only++;
2018 }
2019
2020 insque (lb, LHead -> lb_back);
2021
2022 return lb;
2023}
2024
2025
2026static freelblk (lb)
2027register struct listenblk *lb;
2028{
2029 if (lb == NULLLBP)
2030 return;
2031
2032#ifdef MGMT
2033 if (lb -> lb_type == LB_LISTEN)
2034 (void) TManGen (ENDLISTEN, NULLBP, &lb -> lb_addr);
2035#endif
2036
2037#ifndef LPP
2038 if (lb -> lb_type != LB_QUEUED)
2039#endif
2040 if (lb -> lb_fd != NOTOK) {
2041 del_fd (lb -> lb_fd);
2042 (void) (*lb -> lb_close) (lb -> lb_fd);
2043 }
2044
2045 remque (lb);
2046
2047 free ((char *) lb);
2048}
2049
2050/* \f */
2051
2052static struct listenblk *findlblk (ta, type)
2053register struct TSAPaddr *ta;
2054int type;
2055{
2056 register struct listenblk *lb;
2057
2058 if (once_only == 0)
2059 return NULLLBP;
2060
2061 for (lb = LHead -> lb_forw; lb != LHead; lb = lb -> lb_forw)
2062 if (lb -> lb_type == type
2063 && bcmp ((char *) &lb -> lb_addr, (char *) ta, sizeof *ta) ==0)
2064 return lb;
2065
2066 return NULLLBP;
2067}
2068
2069static struct listenblk *findlblkbyfd (fd)
2070int fd;
2071{
2072 register struct listenblk *lb;
2073
2074 if (once_only == 0)
2075 return NULLLBP;
2076
2077 for (lb = LHead -> lb_forw; lb != LHead; lb = lb -> lb_forw)
2078#ifndef LPP
2079 if (lb -> lb_type != LB_QUEUED)
2080#endif
2081 if (lb -> lb_fd == fd)
2082 return lb;
2083
2084 return NULLLBP;
2085}
2086
2087/* \f */
2088
2089static struct eventblk *neweblk (ta)
2090struct TSAPaddr *ta;
2091{
2092 register struct eventblk *eb;
2093
2094 eb = (struct eventblk *) calloc (1, sizeof *eb);
2095 if (eb == NULLEVP)
2096 return eb;
2097
2098 eb -> ev_taddr = *ta; /* struct copy */
2099
2100 if (ev_onceonly == 0) {
2101 EHead -> ev_forw = EHead -> ev_back = EHead;
2102 ev_onceonly++;
2103 }
2104
2105 insque (eb, EHead -> ev_back);
2106
2107 ev_count++;
2108
2109 return eb;
2110}
2111
2112
2113#ifdef BRIDGE_X25
2114static freeeblk (eb)
2115register struct eventblk *eb;
2116{
2117 if (eb == NULLEVP)
2118 return;
2119
2120 remque (eb);
2121
2122 free ((char *) eb);
2123
2124 ev_count--;
2125}
2126#endif
2127
2128/* \f */
2129
2130#ifdef LPP
2131#ifdef lint
2132/* VARARGS */
2133
2134int tsaplose (td, reason, what, fmt)
2135struct TSAPdisconnect *td;
2136int reason;
2137char *what,
2138 *fmt;
2139{
2140 return tsaplose (td, reason, what, fmt);
2141}
2142#endif
2143#endif
2144
2145/* \f queued writes */
2146
2147#ifndef LPP
2148static int TNetQueue (tb, insert, td)
2149register struct tsapblk *tb;
2150int insert;
2151struct TSAPdisconnect *td;
2152{
2153 register struct listenblk *lb;
2154
2155 if (once_only == 0) {
2156 LHead -> lb_forw = LHead -> lb_back = LHead;
2157 once_only++;
2158 }
2159
2160 for (lb = LHead -> lb_forw; lb != LHead; lb = lb -> lb_forw)
2161 if (lb -> lb_type == LB_QUEUED && lb -> lb_tb == tb)
2162 break;
2163
2164 if (!insert) {
2165 if (lb != LHead)
2166 TFreeQueues (lb);
2167
2168 return OK;
2169 }
2170 if (lb != LHead) /* should "never happen" */
2171 return OK;
2172
2173 if ((lb = newlblk (LB_QUEUED, NULLTA)) == NULLLBP) {
2174 SLOG (tsap_log, LLOG_EXCEPTIONS, NULLCP,
2175 ("unable to allocate listenblk for queued writes"));
2176 return tsaplose (td, DR_CONGEST, NULLCP, "out of memory");
2177 }
2178 lb -> lb_fd = (lb -> lb_tb = tb) -> tb_fd;
2179
2180 if (lb -> lb_fd >= qw_nfds)
2181 qw_nfds = lb -> lb_fd + 1;
2182 if (qw_count++ == 0)
2183 FD_ZERO (&qw_mask);
2184 FD_SET (lb -> lb_fd, &qw_mask);
2185
2186 return OK;
2187}
2188
2189/* \f */
2190
2191static int TDoQueues (lb, td)
2192register struct listenblk *lb;
2193struct TSAPdisconnect *td;
2194{
2195 register struct tsapblk *tb = lb -> lb_tb;
2196
2197 switch ((*tb -> tb_drainPfnx) (tb, td)) {
2198 case NOTOK:
2199 return NOTOK;
2200
2201 case DONE:
2202 default:
2203 TFreeQueues (lb);
2204 /* and fall... */
2205
2206 case OK:
2207 return OK;
2208 }
2209}
2210
2211/* \f */
2212
2213static int TFreeQueues (lb)
2214register struct listenblk *lb;
2215{
2216 if (lb -> lb_fd + 1 == qw_nfds)
2217 qw_nfds--;
2218 if (--qw_count == 0)
2219 qw_nfds = 0;
2220 FD_CLR (lb -> lb_fd, &qw_mask);
2221 lb -> lb_fd = NOTOK;
2222
2223 freelblk (lb);
2224}
2225
2226/* \f */
2227
2228int TSetQueuesOK (sd, onoff, td)
2229int sd;
2230int onoff;
2231struct TSAPdisconnect *td;
2232{
2233 int result;
2234 SBV smask;
2235 register struct tsapblk *tb;
2236
2237 missingP (td);
2238
2239 smask = sigioblock ();
2240
2241 tsapPsig (tb, sd);
2242
2243 result = OK;
2244 if (onoff) {
2245 if (tb -> tb_drainPfnx == NULLIFP)
2246 result = tsaplose (td, DR_OPERATION, NULLCP,
2247 "queued writes not supported by TS-stack");
2248 else {
2249 tb -> tb_flags |= TB_QWRITES;
2250 tb -> tb_queuePfnx = TNetQueue;
2251 }
2252 }
2253 else
2254 if (tb -> tb_qwrites.qb_forw != &tb -> tb_qwrites)
2255 result = tsaplose (td, DR_WAITING, NULLCP,
2256 "queued writes still waiting to drain");
2257 else {
2258 tb -> tb_flags &= ~TB_QWRITES;
2259 tb -> tb_queuePfnx = NULLIFP;
2260 }
2261
2262 (void) sigiomask (smask);
2263
2264 return result;
2265}
2266#endif