386BSD 0.1 development
[unix-history] / usr / othersrc / contrib / isode / compat / dgram.c
CommitLineData
48435ab0
WJ
1/* dgram.c - datagram (CL-mode TS) abstractions */
2
3#ifndef lint
4static char *rcsid = "$Header: /f/osi/compat/RCS/dgram.c,v 7.11 91/02/22 09:15:07 mrose Interim $";
5#endif
6
7/*
8 * $Header: /f/osi/compat/RCS/dgram.c,v 7.11 91/02/22 09:15:07 mrose Interim $
9 *
10 *
11 * $Log: dgram.c,v $
12 * Revision 7.11 91/02/22 09:15:07 mrose
13 * Interim 6.8
14 *
15 * Revision 7.10 91/01/10 04:10:25 mrose
16 * set_check_fd
17 *
18 * Revision 7.9 91/01/07 12:39:50 mrose
19 * update
20 *
21 * Revision 7.8 90/12/17 22:17:21 mrose
22 * marv
23 *
24 * Revision 7.7 90/07/09 14:31:43 mrose
25 * sync
26 *
27 * Revision 7.6 90/04/23 00:08:08 mrose
28 * touch-up
29 *
30 * Revision 7.5 90/01/11 18:35:03 mrose
31 * real-sync
32 *
33 * Revision 7.4 89/12/19 17:57:34 mrose
34 * touch-up
35 *
36 * Revision 7.3 89/12/19 15:15:31 mrose
37 * dgram
38 *
39 * Revision 7.2 89/12/17 18:30:11 mrose
40 * foo
41 *
42 * Revision 7.1 89/12/11 16:22:25 mrose
43 * more dgram
44 *
45 * Revision 7.0 89/12/01 10:42:35 mrose
46 * Release 6.0
47 *
48 */
49
50/*
51 * NOTICE
52 *
53 * Acquisition, use, and distribution of this module and related
54 * materials are subject to the restrictions of a license agreement.
55 * Consult the Preface in the User's Manual for the full terms of
56 * this agreement.
57 *
58 */
59
60
61/* LINTLIBRARY */
62
63#include <errno.h>
64#include <stdio.h>
65#include "general.h"
66#include "manifest.h"
67#include "tailor.h"
68
69#include "dgram.h"
70#ifdef TCP
71#include "internet.h"
72#endif
73#ifdef TP4
74#include "tp4.h"
75#endif
76
77
78#if defined(SOCKETS) && (defined(TCP) || defined(CLTS))
79#ifndef DEBUG
80#define action(s,f,i)
81#endif
82
83extern int errno;
84
85/* \f */
86
87union sockaddr_un { /* 'cause sizeof (struct sockaddr_iso) == 32 */
88 struct sockaddr sa;
89
90#ifdef TCP
91 struct sockaddr_in sin;
92#endif
93
94#ifdef BSD_TP4
95 union sockaddr_osi sosi;
96#endif
97};
98
99
100struct dgramblk {
101 int dgram_parent;
102 union sockaddr_un dgram_peer;
103#ifdef BSD44
104 u_char dgram_addrlen;
105#endif
106
107 struct qbuf dgram_queue;
108};
109
110
111static int maxpeers = 0;
112static struct dgramblk *peers = NULL;
113
114/* \f */
115
116#ifdef TCP
117
118/* ARGSUSED */
119
120int start_udp_server (sock, backlog, opt1, opt2)
121struct sockaddr_in *sock;
122int backlog,
123 opt1,
124 opt2;
125{
126 register int port;
127 int sd;
128#ifdef BSD43
129 int onoff;
130#endif
131 register struct dgramblk *up,
132 *vp;
133
134 if (peers == NULL) {
135 maxpeers = getdtablesize ();
136 peers = (struct dgramblk *) calloc ((unsigned)maxpeers, sizeof *peers);
137 if (peers == NULL)
138 return NOTOK;
139
140 for (vp = (up = peers) + maxpeers; up < vp; up++) {
141 up -> dgram_parent = NOTOK;
142 up -> dgram_queue.qb_forw = up -> dgram_queue.qb_back =
143 &up -> dgram_queue;
144 }
145 }
146
147 if ((sd = socket (AF_INET, SOCK_DGRAM, 0)) == NOTOK)
148 return NOTOK;
149
150 if (sock -> sin_port != 0) {
151 action ("BIND", sd, (struct sockaddr *) sock);
152
153 if (bind (sd, (struct sockaddr *) sock, sizeof *sock) != NOTOK)
154 goto got_socket;
155
156 (void) close (sd);
157 return NOTOK;
158 }
159 else
160 sock -> sin_family = AF_INET;
161
162 for (port = IPPORT_RESERVED;; port++) {
163 sock -> sin_port = htons ((u_short) port);
164
165 action ("BIND", sd, (struct sockaddr *) sock);
166
167 if (bind (sd, (struct sockaddr *) sock, sizeof *sock) != NOTOK)
168 break;
169
170 switch (errno) {
171 case EADDRINUSE:
172 continue;
173
174 case EADDRNOTAVAIL:
175 default:
176 (void) close (sd);
177 return NOTOK;
178 }
179 }
180
181got_socket: ;
182#ifdef DEBUG
183 {
184 int len = sizeof *sock;
185
186 action ("FOO1", sd, (struct sockaddr *) sock);
187 if (getsockname (sd, (struct sockaddr *) sock, &len) != NOTOK)
188 action ("FOO2", sd, (struct sockaddr *) sock);
189 }
190#endif
191
192#ifndef BSD43
193 if (opt1)
194 (void) setsockopt (sd, SOL_SOCKET, opt1, NULLCP, 0);
195 if (opt2)
196 (void) setsockopt (sd, SOL_SOCKET, opt2, NULLCP, 0);
197#else
198 onoff = 1;
199 if (opt1)
200 (void) setsockopt (sd, SOL_SOCKET, opt1, (char *)&onoff, sizeof onoff);
201 if (opt2)
202 (void) setsockopt (sd, SOL_SOCKET, opt2, (char *)&onoff, sizeof onoff);
203#endif
204
205 (void) set_check_fd (sd, check_dgram_socket, NULLCP);
206 return (peers[sd].dgram_parent = sd);
207}
208#endif
209
210/* \f */
211
212#ifdef BSD_TP4
213
214/* ARGSUSED */
215
216int start_clts_server (sock, backlog, opt1, opt2)
217union sockaddr_osi *sock;
218int backlog,
219 opt1,
220 opt2;
221{
222 int sd;
223#ifdef BSD43
224 int onoff;
225#endif
226 u_char *cp;
227 register struct dgramblk *up,
228 *vp;
229 struct sockaddr_iso *ifaddr = &sock -> osi_sockaddr;
230
231 if (peers == NULL) {
232 maxpeers = getdtablesize ();
233 peers = (struct dgramblk *) calloc ((unsigned)maxpeers, sizeof *peers);
234 if (peers == NULL)
235 return NOTOK;
236
237 for (vp = (up = peers) + maxpeers; up < vp; up++) {
238 up -> dgram_parent = NOTOK;
239 up -> dgram_queue.qb_forw = up -> dgram_queue.qb_back =
240 &up -> dgram_queue;
241 }
242 }
243
244 if ((sd = socket (AF_ISO, SOCK_DGRAM, 0)) == NOTOK)
245 return NOTOK;
246
247 if (ifaddr -> siso_tlen != 0) {
248 action ("BIND", sd, (struct sockaddr *) ifaddr);
249
250 if (bind (sd, (struct sockaddr *) ifaddr, (int) ifaddr -> siso_len)
251 != NOTOK)
252 goto got_socket;
253
254 (void) close (sd);
255 return NOTOK;
256 }
257 else
258 ifaddr -> siso_family = AF_ISO;
259
260 {
261 int pid;
262 u_char *dp,
263 *ep,
264 *fp;
265
266 pid = getpid ();
267 cp = fp = (u_char *) ifaddr -> siso_data + ifaddr -> siso_nlen;
268 for (ep = (dp = (u_char *) &pid) + sizeof pid; dp < ep; dp++)
269 *cp++ = *dp;
270 ifaddr -> siso_tlen = (cp - fp) + 1;
271 ifaddr -> siso_slen = ifaddr -> siso_plen = 0;
272 ifaddr -> siso_len = sizeof *ifaddr;
273 }
274
275 for (*cp = 0x00; *cp < 0xff; *cp += 1) {
276 action ("BIND", sd, (struct sockaddr *) ifaddr);
277
278 if (bind (sd, (struct sockaddr *) ifaddr, (int) ifaddr -> siso_len)
279 != NOTOK)
280 goto got_socket;
281
282 switch (errno) {
283 case EADDRINUSE:
284 continue;
285
286 case EADDRNOTAVAIL:
287 default:
288 (void) close (sd);
289 return NOTOK;
290 }
291 }
292 (void) close (sd);
293 errno = EADDRNOTAVAIL;
294 return NOTOK;
295
296got_socket: ;
297#ifdef DEBUG
298 {
299 int len = sizeof *sock;
300
301 action ("FOO1", sd, ifaddr);
302 if (getsockname (sd, (struct sockaddr *) ifaddr, &len) != NOTOK)
303 action ("FOO2", sd, ifaddr);
304 }
305#endif
306
307#ifndef BSD43
308 if (opt1)
309 (void) setsockopt (sd, SOL_SOCKET, opt1, NULLCP, 0);
310 if (opt2)
311 (void) setsockopt (sd, SOL_SOCKET, opt2, NULLCP, 0);
312#else
313 onoff = 1;
314 if (opt1)
315 (void) setsockopt (sd, SOL_SOCKET, opt1, (char *)&onoff, sizeof onoff);
316 if (opt2)
317 (void) setsockopt (sd, SOL_SOCKET, opt2, (char *)&onoff, sizeof onoff);
318#endif
319
320 (void) set_check_fd (sd, check_dgram_socket, NULLCP);
321 return (peers[sd].dgram_parent = sd);
322}
323#endif
324
325/* \f */
326
327int join_dgram_aux (fd, sock, newfd)
328int fd,
329 newfd;
330struct sockaddr *sock;
331{
332 int nfds,
333 sd;
334 fd_set ifds;
335 register struct qbuf *qb;
336 register struct dgramblk *up;
337
338 if (fd < 0 || fd >= maxpeers || peers[fd].dgram_parent != fd) {
339 errno = EINVAL;
340 return NOTOK;
341 }
342
343 if (newfd) {
344 FD_ZERO (&ifds);
345
346 nfds = fd + 1;
347 FD_SET (fd, &ifds);
348 if (select_dgram_socket (nfds, &ifds, NULLFD, NULLFD, OK) == NOTOK)
349 return NOTOK;
350
351 up = &peers[fd];
352 if ((qb = up -> dgram_queue.qb_forw) == &up -> dgram_queue) {
353 errno = EWOULDBLOCK;
354 return NOTOK;
355 }
356
357 if ((sd = dup (fd)) == NOTOK)
358 return NOTOK;
359 (void) set_check_fd (fd, check_dgram_socket, NULLCP);
360
361 up = &peers[sd];
362#ifdef BSD44
363 bcopy (qb -> qb_base, (caddr_t) sock,
364 ((struct sockaddr *) qb -> qb_base) -> sa_len);
365#else
366 *sock = *((struct sockaddr *) qb -> qb_base); /* struct copy */
367#endif
368
369 remque (qb);
370 insque (qb, up -> dgram_queue.qb_back);
371 }
372 else
373 up = &peers[fd];
374
375 up -> dgram_parent = fd;
376#ifdef BSD44
377 if (sock -> sa_len == 0)
378 sock -> sa_len = sizeof *sock;
379 bcopy ((caddr_t) sock, (caddr_t) &up -> dgram_peer, sock -> sa_len);
380 {
381 struct sockaddr_in *sin;
382
383 up -> dgram_addrlen = sock -> sa_family != AF_INET ? sock -> sa_len
384 : sizeof *sin - sizeof sin -> sin_zero;
385 }
386#else
387 up -> dgram_peer.sa = *sock; /* struct copy */
388#endif
389
390 action ("JOIN", newfd ? sd : fd, sock);
391
392 return (newfd ? sd : OK);
393}
394
395/* \f */
396
397int read_dgram_socket (fd, q)
398int fd;
399struct qbuf **q;
400{
401 int nfds;
402 fd_set ifds,
403 mask;
404 register struct qbuf *qb;
405 register struct dgramblk *up;
406
407 if (fd < 0
408 || fd >= maxpeers
409 || (up = &peers[fd]) -> dgram_parent == NOTOK) {
410 errno = EINVAL;
411 return NOTOK;
412 }
413
414 if ((qb = up -> dgram_queue.qb_forw) == &up -> dgram_queue) {
415 FD_ZERO (&mask);
416
417 nfds = fd + 1;
418 FD_SET (fd, &mask);
419 for (ifds = mask;; ifds = mask) {
420 if (select_dgram_socket (nfds, &ifds, NULLFD, NULLFD, NOTOK)
421 == NOTOK)
422 return NOTOK;
423
424 if ((qb = up -> dgram_queue.qb_forw) != &up -> dgram_queue)
425 break;
426 }
427 }
428
429 remque (qb);
430 qb -> qb_forw = qb -> qb_back = qb;
431
432 *q = qb;
433
434 return qb -> qb_len;
435}
436
437/* \f */
438
439int hack_dgram_socket (fd, sock)
440int fd;
441struct sockaddr *sock;
442{
443 register struct dgramblk *up;
444
445 if (fd < 0
446 || fd >= maxpeers
447 || (up = &peers[fd]) -> dgram_parent != fd) {
448 errno = EINVAL;
449 return NOTOK;
450 }
451
452 if (sock == NULL) {
453 bzero ((caddr_t) &up -> dgram_peer, sizeof up -> dgram_peer);
454 return OK;
455 }
456
457#ifdef BSD44
458 if (sock -> sa_len == 0)
459 sock -> sa_len = sizeof *sock;
460 bcopy ((caddr_t) sock, (caddr_t) &up -> dgram_peer, sock -> sa_len);
461 up -> dgram_addrlen = 0;
462#else
463 up -> dgram_peer.sa = *sock; /* struct copy */
464#endif
465
466 action ("HACK", fd, sock);
467
468 return OK;
469}
470
471
472int write_dgram_socket (fd, qb)
473int fd;
474register struct qbuf *qb;
475{
476 register struct dgramblk *up;
477
478 if (fd < 0
479 || fd >= maxpeers
480 || (up = &peers[fd]) -> dgram_parent == NOTOK
481 || up -> dgram_peer.sa.sa_family == 0) {
482 errno = EINVAL;
483 return NOTOK;
484 }
485
486 action ("SENDTO", fd, &up -> dgram_peer.sa);
487
488#ifdef BSD44
489 return sendto (fd, qb -> qb_data, qb -> qb_len, NULL,
490 &up -> dgram_peer.sa, (int) up -> dgram_peer.sa.sa_len);
491#else
492 return sendto (fd, qb -> qb_data, qb -> qb_len, NULL,
493 &up -> dgram_peer.sa, sizeof up -> dgram_peer.sa);
494#endif
495}
496
497
498/* \f */
499
500int close_dgram_socket (fd)
501int fd;
502{
503 register struct dgramblk *up,
504 *vp;
505
506 if (fd < 0
507 || fd >= maxpeers
508 || (up = &peers[fd]) -> dgram_parent == NOTOK) {
509 errno = EINVAL;
510 return NOTOK;
511 }
512
513 action ("CLOSE", fd, &up -> dgram_peer.sa);
514
515 up -> dgram_parent = NOTOK;
516 bzero ((char *) &up -> dgram_peer, sizeof up -> dgram_peer);
517 QBFREE (&up -> dgram_queue);
518
519 for (vp = (up = peers) + maxpeers; up < vp; up++)
520 if (up -> dgram_parent == fd)
521 up -> dgram_parent = up - peers;
522
523 (void) set_check_fd (fd, NULLIFP, NULLCP);
524 return close (fd);
525}
526
527/* \f */
528
529int select_dgram_socket (nfds, rfds, wfds, efds, secs)
530int nfds;
531fd_set *rfds,
532 *wfds,
533 *efds;
534int secs;
535{
536 register int fd;
537 int cc,
538 mfds,
539 result;
540 fd_set ifds,
541 jfds;
542 register struct qbuf *qb;
543 register struct dgramblk *up,
544 *vp;
545 struct dgramblk *wp;
546 union sockaddr_un *sock;
547
548 if (rfds) {
549 jfds = *rfds;
550
551 if (secs != OK)
552 for (vp = (up = peers) + maxpeers, fd = 0; up < vp; up++, fd++)
553 if (up -> dgram_parent != NOTOK
554 && FD_ISSET (fd, &jfds)
555 && up -> dgram_queue.qb_forw != &up -> dgram_queue) {
556 secs = OK;
557 break;
558 }
559 }
560
561 if ((result = selsocket (nfds, rfds, wfds, efds, secs)) == NOTOK
562 || rfds == NULLFD)
563 return result;
564
565 ifds = *rfds;
566 if ((mfds = nfds) > maxpeers)
567 mfds = maxpeers;
568 for (fd = 0, up = peers; fd < mfds; fd++, up++)
569 if (FD_ISSET (fd, &ifds)) {
570 int slen;
571 u_char len;
572 char *data;
573
574 FD_CLR (fd, &ifds);
575
576 if (up -> dgram_parent == NOTOK)
577 continue;
578
579 if ((qb = (struct qbuf *) malloc ((unsigned) (sizeof *qb
580 + (slen
581 = sizeof *sock)
582 + MAXDGRAM)))
583 == NULL)
584 return NOTOK;
585
586 sock = (union sockaddr_un *) qb -> qb_base;
587 qb -> qb_data = qb -> qb_base + slen;
588 if ((cc = recvfrom (fd, qb -> qb_data, MAXDGRAM, NULL,
589 &sock -> sa, &slen)) == NOTOK) {
590 free ((char *) qb);
591 return NOTOK;
592 }
593#ifdef BSD44
594 sock -> sa.sa_len = slen;
595#endif
596 qb -> qb_len = cc;
597
598 action ("RECVFROM", fd, &sock -> sa);
599
600 vp = up;
601 data = sock -> sa.sa_data;
602 switch (sock -> sa.sa_family) {
603 case AF_INET: /* XXX: doesn't take into account padding */
604 len = sizeof sock -> sa.sa_data
605 - sizeof sock -> sin.sin_zero;
606 break;
607
608 default:
609#ifdef BSD44
610 len = sock -> sa.sa_len;
611#else
612 len = sizeof sock -> sa;
613#endif
614 break;
615 }
616 if (
617#ifdef BSD44
618 len != up -> dgram_addrlen ||
619#endif
620 bcmp (data, up -> dgram_peer.sa.sa_data, (int) len)
621 != 0) {
622 for (wp = (vp = peers) + maxpeers; vp < wp; vp++)
623 if (vp != up
624 && vp -> dgram_parent == up -> dgram_parent
625#ifdef BSD44
626 && len == vp -> dgram_addrlen
627#endif
628 && bcmp (data, vp -> dgram_peer.sa.sa_data,
629 (int) len) == 0)
630 break;
631 if (vp >= wp
632 && (vp = &peers[up -> dgram_parent])
633 -> dgram_peer.sa.sa_family != 0) {
634 free ((char *) qb);
635 continue;
636 }
637 }
638
639 insque (qb, vp -> dgram_queue.qb_back);
640
641 if (--result <= 0
642 || (result = selsocket (nfds, &ifds, NULLFD, NULLFD, OK))
643 <= 0)
644 break;
645
646 }
647
648 for (vp = (up = peers) + maxpeers, fd = 0; up < vp; up++, fd++)
649 if (up -> dgram_parent != NOTOK && FD_ISSET (fd, &jfds))
650 if (up -> dgram_queue.qb_forw != &up -> dgram_queue)
651 FD_SET (fd, rfds);
652 else
653 FD_CLR (fd, rfds);
654
655 result = 0;
656 ifds = *rfds;
657 if (wfds)
658 for (fd = 0; fd < nfds; fd++)
659 if (FD_ISSET (fd, wfds))
660 FD_SET (fd, &ifds);
661 if (efds)
662 for (fd = 0; fd < nfds; fd++)
663 if (FD_ISSET (fd, efds))
664 FD_SET (fd, &ifds);
665 for (fd = 0; fd < nfds; fd++)
666 if (FD_ISSET (fd, &ifds))
667 result++;
668
669 return result;
670}
671
672/* \f */
673
674int check_dgram_socket (fd)
675int fd;
676{
677 int nfds;
678 fd_set ifds;
679
680 FD_ZERO (&ifds);
681
682 nfds = fd + 1;
683 FD_SET (fd, &ifds);
684
685 return select_dgram_socket (nfds, &ifds, NULLFD, NULLFD, OK);
686}
687
688/* \f */
689
690#ifdef DEBUG
691
692#ifdef TCP
693#include "isoaddrs.h"
694
695
696static inetprint (sin, bp)
697struct sockaddr_in *sin;
698char *bp;
699{
700 (void) sprintf (bp, "Internet=%s+%d+%d", inet_ntoa (sin -> sin_addr),
701 (int) ntohs (sin -> sin_port), NA_TSET_UDP);
702}
703#endif
704
705/* \f */
706
707#ifdef CLTS
708/* prints OSI address using the format described in:
709
710 "A string encoding of Presentation Address"
711
712 S.E. Kille, Research Note RN/89/14, February 1989
713 Department of Computer Science
714 University College London
715
716 */
717
718#ifndef SSEL
719#define SSEL(s) ((s)->siso_tlen + TSEL(s))
720#define PSEL(s) ((s)->siso_slen + SSEL(s))
721#endif
722
723
724static isoprint (siso, bp)
725register struct sockaddr_iso *siso;
726char *bp;
727{
728 int didone = 0;
729
730 if (siso -> siso_plen) {
731 hexprint (bp, siso -> siso_plen, PSEL (siso), "'", "'H");
732 bp += strlen (bp);
733 *bp++ = '/';
734 didone++;
735 }
736 if (siso -> siso_slen || didone) {
737 hexprint (bp, siso -> siso_slen, SSEL (siso), "'", "'H");
738 bp += strlen (bp);
739 *bp++ = '/';
740 didone++;
741 }
742 if (siso -> siso_tlen || didone) {
743 hexprint (bp, siso -> siso_tlen, TSEL (siso), "'", "'H");
744 bp += strlen (bp);
745 *bp++ = '/';
746 didone++;
747 }
748 hexprint (bp, siso -> siso_nlen, siso -> siso_data, "NS+", "");
749}
750
751
752static hexprint (bp, n, buf, start, stop)
753char *bp;
754int n;
755u_char *buf;
756char *start,
757 *stop;
758{
759 register u_char *in = buf, *top = in + n;
760
761 if (n == 0)
762 return;
763
764 (void) strcpy (bp, start);
765 bp += strlen (bp);
766
767 while (in < top) {
768 (void) sprintf (bp, "%02x", *in++ & 0xff);
769 bp += 2;
770 }
771
772 (void) strcpy (bp, stop);
773}
774#endif
775
776/* \f */
777
778static struct printent {
779 int p_family;
780 IFP p_function;
781} ents[] = {
782#ifdef TCP
783 AF_INET, inetprint,
784#endif
785
786#ifdef CLTS
787 AF_ISO, isoprint,
788#endif
789
790 NULL
791};
792
793static action (s, fd, sock)
794char *s;
795int fd;
796struct sockaddr *sock;
797{
798 char buffer[BUFSIZ];
799 register struct printent *p;
800
801 if (!(compat_log -> ll_events & LLOG_TRACE))
802 return;
803
804 for (p = ents; p -> p_family; p++)
805 if (p -> p_family == sock -> sa_family)
806 break;
807 if (!p -> p_family) {
808 DLOG (compat_log, LLOG_EXCEPTIONS,
809 ("unknown dgram address family 0x%x", sock -> sa_family));
810 return;
811 }
812
813 (void) (*p -> p_function) (sock, buffer);
814
815 DLOG (compat_log, LLOG_TRACE, ("%-10.10s %d %s", s, fd, buffer));
816}
817#endif
818
819#else
820
821/* \f */
822
823int dgram_dummy () {}
824
825#endif