Commit | Line | Data |
---|---|---|
b62cce74 C |
1 | /* tsaplisten.c - "network" listening */ |
2 | ||
3 | #ifndef lint | |
4 | static 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 | ||
132 | union 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 | ||
149 | struct 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 | ||
198 | static int once_only = 0; | |
199 | static struct listenblk listenque; | |
200 | static struct listenblk *LHead = &listenque; | |
201 | ||
202 | ||
203 | struct 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 | ||
216 | struct 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 | ||
226 | static struct eventblk eventqueue; | |
227 | static struct eventblk *EHead = &eventqueue; | |
228 | static int ev_onceonly = 0; | |
229 | static int ev_count = 0; | |
230 | ||
231 | struct 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 | ||
251 | static int acl_nfds = 0; | |
252 | static int acl_count = 0; | |
253 | static fd_set acl_mask; | |
254 | ||
255 | static int qw_nfds = 0; | |
256 | static int qw_count = 0; | |
257 | static fd_set qw_mask; | |
258 | ||
259 | ||
260 | int startlb (), uniqlb (); | |
261 | ||
262 | /* \f */ | |
263 | ||
264 | #ifdef TCP | |
265 | int tcplisten (), tcpaccept1 (), tcpaccept2 (), tcpunique (); | |
266 | #endif | |
267 | #ifdef X25 | |
268 | int x25listen (), x25accept1 (), x25accept2 (), x25unique (); | |
269 | #endif | |
270 | #ifdef BRIDGE_X25 | |
271 | int bridgelisten (), bridgeaccept1 (), bridgeaccept2 (), bridgeunique (); | |
272 | int close_bridge_socket (), bridge_except (); | |
273 | #endif | |
274 | #ifdef TP4 | |
275 | int tp4listen (), tp4accept1 (), tp4accept2 (), tp4unique (); | |
276 | #endif | |
277 | ||
278 | static 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 | |
313 | static int _lpp_fd = NOTOK; | |
314 | ||
315 | u_short _lpp_lastport; /* MOBY HACK */ | |
316 | #endif | |
317 | ||
318 | ||
319 | #ifdef BSD42 | |
320 | static int chldhit; | |
321 | ||
322 | SFD chldser (); | |
323 | #endif | |
324 | ||
325 | ||
326 | extern int errno; | |
327 | ||
328 | /* \f */ | |
329 | ||
330 | int TNetListen (ta, td) | |
331 | register struct TSAPaddr *ta; | |
332 | struct TSAPdisconnect *td; | |
333 | { | |
334 | return TNetWork (ta, td, startlb, NULLIFP); | |
335 | } | |
336 | ||
337 | int TNetListenAux (ta, magic, td) | |
338 | register struct TSAPaddr *ta; | |
339 | IFP magic; | |
340 | struct TSAPdisconnect *td; | |
341 | { | |
342 | return TNetWork (ta, td, startlb, magic); | |
343 | } | |
344 | ||
345 | ||
346 | int TNetUnique (ta, td) | |
347 | register struct TSAPaddr *ta; | |
348 | struct TSAPdisconnect *td; | |
349 | { | |
350 | return TNetWork (ta, td, uniqlb, NULLIFP); | |
351 | } | |
352 | ||
353 | /* \f */ | |
354 | ||
355 | static int TNetWork (ta, td, fnx, magic) | |
356 | register struct TSAPaddr *ta; | |
357 | struct TSAPdisconnect *td; | |
358 | IFP fnx; | |
359 | IFP 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 | ||
461 | out: ; | |
462 | (void) TNetClose (ta, &tds); | |
463 | return NOTOK; | |
464 | } | |
465 | ||
466 | /* \f */ | |
467 | ||
468 | static int startlb (ta, na, ns, magic, td) | |
469 | register struct TSAPaddr *ta; | |
470 | register struct NSAPaddr *na; | |
471 | register struct nsapent *ns; | |
472 | IFP magic; | |
473 | struct 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 | ||
514 | static int uniqlb (ta, na, ns, magic, td) | |
515 | register struct TSAPaddr *ta; | |
516 | register struct NSAPaddr *na; | |
517 | register struct nsapent *ns; | |
518 | IFP magic; | |
519 | struct 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 | ||
555 | int TNetAcceptAux (vecp, vec, newfd, ta, nfds, rfds, wfds, efds, secs, td) | |
556 | int *vecp; | |
557 | char **vec; | |
558 | int *newfd; | |
559 | struct TSAPaddr *ta; | |
560 | int nfds; | |
561 | fd_set *rfds, | |
562 | *wfds, | |
563 | *efds; | |
564 | int secs; | |
565 | struct 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 | |
601 | retry: ; | |
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 | } | |
654 | empty: ; | |
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 | } | |
778 | next: ; | |
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 | ||
803 | static int exception (lb, td) | |
804 | struct listenblk *lb; | |
805 | struct 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 | ||
826 | static 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 | ||
840 | int TNetClose (ta, td) | |
841 | register struct TSAPaddr *ta; | |
842 | struct 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 | ||
897 | static SFD chldser (sig, code, sc) | |
898 | int sig; | |
899 | long code; | |
900 | struct 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 | ||
915 | int TNetFork (vecp, vec, td) | |
916 | int vecp; | |
917 | char **vec; | |
918 | struct 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 | |
998 | static int tcplisten (lb, ta, td) | |
999 | register struct listenblk *lb; | |
1000 | register struct TSAPaddr *ta; | |
1001 | struct 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 | |
1056 | char *udpsave (); | |
1057 | #endif | |
1058 | ||
1059 | ||
1060 | static int tcpaccept1 (lb, td) | |
1061 | register struct listenblk *lb; | |
1062 | struct 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 | ||
1135 | out: ; | |
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 | ||
1151 | static int tcpaccept2 (lb, vecp, vec, td) | |
1152 | register struct listenblk *lb; | |
1153 | int *vecp; | |
1154 | char **vec; | |
1155 | struct 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 | ||
1254 | out: ; | |
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 | ||
1270 | static int tcpunique (ta, td) | |
1271 | register struct TSAPaddr *ta; | |
1272 | struct 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 | ||
1316 | static int x25listen (lb, ta, td) | |
1317 | struct listenblk *lb; | |
1318 | struct TSAPaddr *ta; | |
1319 | struct 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 | ||
1337 | static int x25accept1 (lb, td) | |
1338 | register struct listenblk *lb; | |
1339 | struct 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 | ||
1376 | out: ; | |
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 | ||
1389 | static int x25accept2 (lb, vecp, vec, td) | |
1390 | register struct listenblk *lb; | |
1391 | int *vecp; | |
1392 | char **vec; | |
1393 | struct 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 | ||
1448 | out: ; | |
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 | ||
1461 | static int x25unique (ta, td) | |
1462 | struct TSAPaddr *ta; | |
1463 | struct 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 | ||
1484 | static int bridgelisten (lb, ta, td) | |
1485 | register struct listenblk *lb; | |
1486 | register struct TSAPaddr *ta; | |
1487 | struct 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 | ||
1503 | static int bridge_except (eb, td) | |
1504 | register struct eventblk *eb; | |
1505 | struct 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 | ||
1529 | static int bridgelisten_aux (lb, ta, td) | |
1530 | register struct listenblk *lb; | |
1531 | register struct TSAPaddr *ta; | |
1532 | struct 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 | ||
1560 | static int bridgeaccept1 (lb, td) | |
1561 | register struct listenblk *lb; | |
1562 | struct 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 | ||
1599 | out: ; | |
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 | ||
1613 | static int bridgeaccept2 (lb, vecp, vec, td) | |
1614 | register struct listenblk *lb; | |
1615 | int *vecp; | |
1616 | char **vec; | |
1617 | struct 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 | ||
1672 | out: ; | |
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 | ||
1687 | static int bridgeunique (ta, td) | |
1688 | struct TSAPaddr *ta; | |
1689 | struct 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 | ||
1705 | static int tp4listen (lb, ta, td) | |
1706 | struct listenblk *lb; | |
1707 | register struct TSAPaddr *ta; | |
1708 | struct TSAPdisconnect *td; | |
1709 | { | |
1710 | return start_tp4_server (ta, SOMAXCONN, SO_KEEPALIVE, 0, td); | |
1711 | } | |
1712 | ||
1713 | /* \f */ | |
1714 | ||
1715 | static int tp4accept1 (lb, td) | |
1716 | register struct listenblk *lb; | |
1717 | struct 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 | ||
1755 | out: ; | |
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 | ||
1767 | static int tp4accept2 (lb, vecp, vec, td) | |
1768 | register struct listenblk *lb; | |
1769 | int *vecp; | |
1770 | char **vec; | |
1771 | struct 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 | ||
1819 | out: ; | |
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 | ||
1833 | static int tp4unique (ta, td) | |
1834 | struct TSAPaddr *ta; | |
1835 | struct 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 | ||
1852 | static int tp4listen (lb, ta, td) | |
1853 | struct listenblk *lb; | |
1854 | register struct TSAPaddr *ta; | |
1855 | struct TSAPdisconnect *td; | |
1856 | { | |
1857 | return start_tp4_server (ta, SOMAXCONN, 0, 0, td); | |
1858 | } | |
1859 | ||
1860 | /* \f */ | |
1861 | ||
1862 | static int tp4accept1 (lb, td) | |
1863 | register struct listenblk *lb; | |
1864 | struct 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 | ||
1901 | out: ; | |
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 | ||
1914 | static int tp4accept2 (lb, vecp, vec, td) | |
1915 | register struct listenblk *lb; | |
1916 | int *vecp; | |
1917 | char **vec; | |
1918 | struct 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 | ||
1972 | out: ; | |
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 | ||
1987 | static int tp4unique (ta, td) | |
1988 | struct TSAPaddr *ta; | |
1989 | struct 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 | ||
2000 | static struct listenblk *newlblk (type, ta) | |
2001 | int type; | |
2002 | struct 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 | ||
2026 | static freelblk (lb) | |
2027 | register 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 | ||
2052 | static struct listenblk *findlblk (ta, type) | |
2053 | register struct TSAPaddr *ta; | |
2054 | int 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 | ||
2069 | static struct listenblk *findlblkbyfd (fd) | |
2070 | int 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 | ||
2089 | static struct eventblk *neweblk (ta) | |
2090 | struct 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 | |
2114 | static freeeblk (eb) | |
2115 | register 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 | ||
2134 | int tsaplose (td, reason, what, fmt) | |
2135 | struct TSAPdisconnect *td; | |
2136 | int reason; | |
2137 | char *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 | |
2148 | static int TNetQueue (tb, insert, td) | |
2149 | register struct tsapblk *tb; | |
2150 | int insert; | |
2151 | struct 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 | ||
2191 | static int TDoQueues (lb, td) | |
2192 | register struct listenblk *lb; | |
2193 | struct 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 | ||
2213 | static int TFreeQueues (lb) | |
2214 | register 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 | ||
2228 | int TSetQueuesOK (sd, onoff, td) | |
2229 | int sd; | |
2230 | int onoff; | |
2231 | struct 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 |