|
|
1.1 root 1: /* internet.c - TCP/IP abstractions */
2:
3: #ifndef lint
4: static char *rcsid = "$Header: /f/osi/compat/RCS/internet.c,v 7.1 90/01/11 18:35:06 mrose Exp $";
5: #endif
6:
7: /*
8: * $Header: /f/osi/compat/RCS/internet.c,v 7.1 90/01/11 18:35:06 mrose Exp $
9: *
10: *
11: * $Log: internet.c,v $
12: * Revision 7.1 90/01/11 18:35:06 mrose
13: * real-sync
14: *
15: * Revision 7.0 89/11/23 21:23:03 mrose
16: * Release 6.0
17: *
18: */
19:
20: /*
21: * NOTICE
22: *
23: * Acquisition, use, and distribution of this module and related
24: * materials are subject to the restrictions of a license agreement.
25: * Consult the Preface in the User's Manual for the full terms of
26: * this agreement.
27: *
28: */
29:
30:
31: /* LINTLIBRARY */
32:
33: #include <ctype.h>
34: #include <errno.h>
35: #include <stdio.h>
36: #include "general.h"
37: #include "manifest.h"
38: #include "tailor.h"
39:
40: /* */
41:
42: #ifdef TCP
43: #include "internet.h"
44:
45:
46: extern int errno;
47:
48: /* Berkeley UNIX: 4.2 */
49:
50: #ifdef SOCKETS
51:
52: /* For real networking, nothing is better than 4BSD! */
53:
54:
55: int start_tcp_client (sock, priv)
56: struct sockaddr_in *sock;
57: int priv;
58: {
59: register int port;
60: int eindex,
61: sd;
62: #ifdef BSD43
63: int onoff;
64: #endif
65:
66: if ((sd = socket (AF_INET, SOCK_STREAM, 0)) == NOTOK) {
67: SLOG (compat_log, LLOG_EXCEPTIONS, "failed", ("socket"));
68: return NOTOK;
69: }
70:
71: if (sock == NULL)
72: goto got_socket;
73:
74: for (port = IPPORT_RESERVED - priv;; priv ? port-- : port++) {
75: sock -> sin_port = htons ((u_short) port);
76:
77: if (bind (sd, (struct sockaddr *) sock, sizeof *sock) != NOTOK)
78: break;
79:
80: switch (errno) {
81: case EADDRINUSE:
82: if (!priv || (port >= IPPORT_RESERVED / 2))
83: continue; /* else fall */
84:
85: case EADDRNOTAVAIL:
86: default:
87: eindex = errno;
88: SLOG (compat_log, LLOG_EXCEPTIONS, "failed", ("bind"));
89: (void) close_tcp_socket (sd);
90: errno = eindex;
91: return NOTOK;
92: }
93: }
94:
95: got_socket: ;
96: #ifndef BSD43
97: if (setsockopt (sd, SOL_SOCKET, SO_KEEPALIVE, NULLCP, 0) == NOTOK)
98: SLOG (compat_log, LLOG_EXCEPTIONS, "failed", ("set SO_KEEPALIVE"));
99: #else
100: onoff = 1;
101: if (setsockopt (sd, SOL_SOCKET, SO_KEEPALIVE, (char *) &onoff,
102: sizeof onoff) == NOTOK)
103: SLOG (compat_log, LLOG_EXCEPTIONS, "failed", ("set SO_KEEPALIVE"));
104: #endif
105:
106: return sd;
107: }
108:
109: /* */
110:
111: int start_tcp_server (sock, backlog, opt1, opt2)
112: struct sockaddr_in *sock;
113: int backlog,
114: opt1,
115: opt2;
116: {
117: register int port;
118: int eindex,
119: sd;
120: #ifdef BSD43
121: int onoff;
122: #endif
123:
124: if ((sd = socket (AF_INET, SOCK_STREAM, 0)) == NOTOK) {
125: SLOG (compat_log, LLOG_EXCEPTIONS, "failed", ("socket"));
126: return NOTOK;
127: }
128:
129: if (sock -> sin_port != 0) {
130: if (bind (sd, (struct sockaddr *) sock, sizeof *sock) != NOTOK)
131: goto got_socket;
132:
133: eindex = errno;
134: SLOG (compat_log, LLOG_EXCEPTIONS, "failed", ("bind"));
135: (void) close_tcp_socket (sd);
136: errno = eindex;
137: return NOTOK;
138: }
139:
140: for (port = IPPORT_RESERVED;; port++) {
141: sock -> sin_port = htons ((u_short) port);
142:
143: if (bind (sd, (struct sockaddr *) sock, sizeof *sock) != NOTOK)
144: break;
145:
146: switch (errno) {
147: case EADDRINUSE:
148: continue;
149:
150: case EADDRNOTAVAIL:
151: default:
152: eindex = errno;
153: SLOG (compat_log, LLOG_EXCEPTIONS, "failed", ("bind"));
154: (void) close_tcp_socket (sd);
155: errno = eindex;
156: return NOTOK;
157: }
158: }
159:
160: got_socket: ;
161: #ifndef BSD43
162: if (setsockopt (sd, SOL_SOCKET, SO_KEEPALIVE, NULLCP, 0) == NOTOK)
163: SLOG (compat_log, LLOG_EXCEPTIONS, "failed", ("set SO_KEEPALIVE"));
164: if (opt1 && setsockopt (sd, SOL_SOCKET, opt1, NULLCP, 0) == NOTOK)
165: SLOG (compat_log, LLOG_EXCEPTIONS, "failed",
166: ("set socket option 0x%x", opt1));
167: if (opt2 && setsockopt (sd, SOL_SOCKET, opt2, NULLCP, 0) == NOTOK)
168: SLOG (compat_log, LLOG_EXCEPTIONS, "failed",
169: ("set socket option 0x%x", opt2));
170: #else
171: onoff = 1;
172: if (setsockopt (sd, SOL_SOCKET, SO_KEEPALIVE, (char *) &onoff,
173: sizeof onoff) == NOTOK)
174: SLOG (compat_log, LLOG_EXCEPTIONS, "failed", ("set SO_KEEPALIVE"));
175: if (opt1
176: && setsockopt (sd, SOL_SOCKET, opt1, (char *) &onoff, sizeof onoff)
177: == NOTOK)
178: SLOG (compat_log, LLOG_EXCEPTIONS, "failed",
179: ("set socket option 0x%x", opt1));
180: if (opt2
181: && setsockopt (sd, SOL_SOCKET, opt2, (char *) &onoff, sizeof onoff)
182: == NOTOK)
183: SLOG (compat_log, LLOG_EXCEPTIONS, "failed",
184: ("set socket option 0x%x", opt2));
185: #endif
186:
187: (void) listen (sd, backlog);
188:
189: return sd;
190: }
191:
192: /* */
193:
194: int join_tcp_client (fd, sock)
195: int fd;
196: struct sockaddr_in *sock;
197: {
198: int eindex,
199: len = sizeof *sock,
200: result;
201:
202: if ((result = accept (fd, (struct sockaddr *) sock, &len)) == NOTOK) {
203: eindex = errno;
204: SLOG (compat_log, LLOG_EXCEPTIONS, "failed", ("accept"));
205: errno = eindex;
206: }
207:
208: return result;
209: }
210:
211: /* */
212:
213: int join_tcp_server (fd, sock)
214: int fd;
215: struct sockaddr_in *sock;
216: {
217: int eindex,
218: result;
219:
220: if ((result = connect (fd, (struct sockaddr *) sock, sizeof *sock))
221: == NOTOK) {
222: eindex = errno;
223: SLOG (compat_log, LLOG_EXCEPTIONS, "failed", ("connect"));
224: errno = eindex;
225: }
226:
227: return result;
228: }
229:
230: /* */
231:
232: close_tcp_socket (fd)
233: int fd;
234: {
235: #ifdef never_do_this_if_from_join_tcp_client
236: (void) shutdown (fd, 2);
237: #endif
238:
239: return (close (fd));
240: }
241:
242: #endif
243:
244: /* AT&T UNIX: 5r3 using TLI */
245:
246:
247: /* AT&T UNIX: 5 with EXOS 8044 TCP/IP card */
248:
249: #ifdef EXOS
250:
251: /* If we had a getsockname() for the EXOS card, then we could postpone some
252: of the binding until connect time. But since we don't, our hand is forced
253: and we must prematurely bind the sockets to IP addresses. */
254:
255:
256: start_tcp_client (sock, priv)
257: struct sockaddr_in *sock;
258: int priv;
259: {
260: register int port;
261: int sd;
262: register struct hostent *hp;
263:
264: if (sock == NULL)
265: return socket (SOCK_STREAM, 0, (struct sockaddr *) 0, SO_KEEPALIVE);
266:
267: if (sock -> sin_addr.s_addr == 0) {
268: if ((hp = gethostbyname ("localhost")) == NULL) {
269: errno = EADDRNOTAVAIL;
270: return NOTOK;
271: }
272: sock -> sin_family = hp -> h_addrtype;
273: inaddr_copy (hp, sock);
274: }
275:
276: for (port = IPPORT_RESERVED - priv;; priv ? port-- : port++) {
277: sock -> sin_port = htons ((u_short) port);
278:
279: if ((sd = socket (SOCK_STREAM, 0, (struct sockaddr *) sock,
280: SO_KEEPALIVE)) != NOTOK)
281: return sd;
282:
283: switch (errno) {
284: case EADDRINUSE:
285: if (!priv || (port >= IPPORT_RESERVED / 2))
286: continue; /* else fall */
287:
288: case EADDRNOTAVAIL:
289: default:
290: return NOTOK;
291: }
292: }
293: }
294:
295: /* */
296:
297: int start_tcp_server (sock, backlog, opt1, opt2)
298: struct sockaddr_in *sock;
299: int backlog,
300: opt1,
301: opt2;
302: {
303: register int port;
304: int sd;
305: register struct hostent *hp;
306:
307: if (backlog != 1)
308: return socket (SOCK_STREAM, 0, (struct sockaddr *) sock,
309: SO_ACCEPTCONN | SO_KEEPALIVE | opt1 | opt2);
310:
311: if (sock -> sin_addr.s_addr == 0) {
312: if ((hp = gethostbyname ("localhost")) == NULL) {
313: errno = EADDRNOTAVAIL;
314: return NOTOK;
315: }
316: sock -> sin_family = hp -> h_addrtype;
317: inaddr_copy (hp, sock);
318: }
319:
320: for (port = IPPORT_RESERVED;; port++) {
321: sock -> sin_port = htons ((u_short) port);
322:
323: if ((sd = socket (SOCK_STREAM, 0, (struct sockaddr *) sock,
324: SO_ACCEPTCONN | SO_KEEPALIVE | opt1 | opt2)) != NOTOK)
325: return sd;
326:
327: switch (errno) {
328: case EADDRINUSE:
329: continue;
330:
331: case EADDRNOTAVAIL:
332: default:
333: return NOTOK;
334: }
335: }
336: }
337:
338: #endif
339:
340: /* GETHOSTENT PLUS */
341:
342: static char *empty = NULL;
343: #ifdef h_addr
344: static char *addrs[2] = { NULL };
345: #endif
346:
347: struct hostent *gethostbystring (s)
348: char *s;
349: {
350: register struct hostent *h;
351: #ifndef DG
352: static u_long iaddr;
353: #else
354: static struct in_addr iaddr;
355: #endif
356: static struct hostent hs;
357:
358: iaddr = inet_addr (s);
359: #ifndef DG
360: if (iaddr == NOTOK)
361: #else
362: if (iaddr.s_addr == NOTOK)
363: #endif
364: return gethostbyname (s);
365:
366: h = &hs;
367: h -> h_name = s;
368: h -> h_aliases = ∅
369: h -> h_addrtype = AF_INET;
370: h -> h_length = sizeof (iaddr);
371: #ifdef h_addr
372: h -> h_addr_list = addrs;
373: bzero ((char *) addrs, sizeof addrs);
374: #endif
375: h -> h_addr = (char *) &iaddr;
376:
377: return h;
378: }
379:
380: /* AT&T UNIX: 5 with EXOS 8044 TCP/IP card */
381:
382: #ifdef EXOS
383:
384: long rhost ();
385: char *raddr ();
386:
387:
388: struct hostent *gethostbyaddr (addr, len, type)
389: char *addr;
390: int len,
391: type;
392: {
393: long iaddr;
394: char *name;
395: static char buffer[BUFSIZ];
396: static struct hostent hs;
397: register struct hostent *h = &hs;
398:
399: if (len != sizeof (long) || type != AF_INET)
400: return NULL;
401: bcopy (addr, (char *) &iaddr, len);
402: if ((name = raddr (iaddr)) == NULL)
403: return NULL;
404:
405: (void) strcpy (buffer, name);
406: free (name);
407:
408: h -> h_name = buffer;
409: h -> h_aliases = ∅
410: h -> h_addrtype = type;
411: h -> h_length = len;
412: h -> h_addr = addr;
413:
414: return h;
415: }
416:
417:
418: struct hostent *gethostbyname (name)
419: char *name;
420: {
421: static long iaddr;
422: static char buffer[BUFSIZ];
423: static struct hostent hs;
424: register struct hostent *h = &hs;
425:
426: if ((iaddr = rhost (&name)) == NOTOK)
427: return NULL;
428:
429: (void) strcpy (buffer, name);
430: free (name);
431:
432: h -> h_name = buffer;
433: h -> h_aliases = ∅
434: h -> h_addrtype = AF_INET;
435: h -> h_length = sizeof (iaddr);
436: h -> h_addr = (char *) &iaddr;
437:
438: return h;
439:
440: }
441:
442: /* */
443:
444: /* really only need the "tsap" entry in this table... but why not? */
445:
446: static struct servent services[] = {
447: "tsap", NULL, 102, "tcp",
448: "miscellany", NULL, 17000, "lpp",
449:
450: "echo", NULL, 7, "tcp", /* Network standard functions */
451: "echo", NULL, 7, "udp",
452: "sink", NULL, 9, "tcp",
453: "sink", NULL, 9, "udp",
454: "users", NULL, 11, "tcp",
455: "users", NULL, 11, "udp",
456: "daytime", NULL, 13, "tcp",
457: "daytime", NULL, 13, "udp",
458: "netstat", NULL, 15, "tcp",
459: "netstat", NULL, 15, "udp",
460: "qotd", NULL, 17, "tcp",
461: "qotd", NULL, 17, "udp",
462: "chargen", NULL, 19, "tcp",
463: "chargen", NULL, 19, "udp",
464: "ftp", NULL, 21, "tcp",
465: "telnet", NULL, 23, "tcp",
466: "smtp", NULL, 25, "tcp",
467: "imagen", NULL, 35, "udp",
468: "time", NULL, 37, "tcp",
469: "time", NULL, 37, "udp",
470: "name", NULL, 42, "tcp",
471: "name", NULL, 42, "udp",
472: "whois", NULL, 43, "tcp",
473: "whois", NULL, 43, "udp",
474: "nameserver", NULL, 53, "tcp",
475: "nameserver", NULL, 53, "udp",
476: "mtp", NULL, 57, "tcp",
477: "hostnames", NULL, 101, "tcp",
478: "pop", NULL, 109, "tcp",
479: "pwdgen", NULL, 129, "tcp",
480: "pwdgen", NULL, 129, "udp",
481: "x25bridge", NULL, 146, "tcp",
482: "iso-ip", NULL, 147, "udp",
483:
484: "tftp", NULL, 69, "udp", /* Host specific functions */
485: "rje", NULL, 77, "tcp",
486: "nmui", NULL, 77, "udp",
487: "finger", NULL, 79, "tcp",
488: "finger", NULL, 79, "udp",
489: "link", NULL, 87, "tcp",
490: "supdup", NULL, 95, "tcp",
491: "path", NULL, 117, "tcp",
492:
493: "exec", NULL, 512, "tcp", /* UNIX TCP sockets */
494: "login", NULL, 513, "tcp",
495: "shell", NULL, 514, "tcp",
496: "printer", NULL, 515, "tcp",
497: "rfile", NULL, 522, "tcp",
498: "ingreslock", NULL, 1524, "tcp",
499:
500: "biff", NULL, 512, "udp", /* UNIX UDP sockets */
501: "who", NULL, 513, "udp",
502: "syslog", NULL, 514, "udp",
503: "talk", NULL, 517, "udp",
504: "routed", NULL, 520, "udp",
505: "router_1", NULL, 521, "udp",
506:
507: NULL, &empty, 0, NULL
508: };
509:
510:
511:
512: struct servent *getservbyname (name, proto)
513: register char *name,
514: *proto;
515: {
516: register struct servent *s;
517:
518: for (s = services; s -> s_name; s++)
519: if (strcmp (name, s -> s_name) == 0
520: && strcmp (proto, s -> s_proto) == 0) {
521: if (s -> s_aliases == NULL) {
522: s -> s_aliases = ∅
523: s -> s_port = htons ((u_short) s -> s_port);
524: }
525:
526: return s;
527: }
528:
529: return NULL;
530: }
531:
532: /* */
533:
534: #define s2a(b) (((int) (b)) & 0xff)
535:
536: char *inet_ntoa (in)
537: struct in_addr in;
538: {
539: register char *s = (char *) ∈
540: static char addr[4 * 3 + 3 + 1];
541:
542: (void) sprintf (addr, "%d.%d.%d.%d",
543: s2a (s[0]), s2a (s[1]), s2a (s[2]), s2a (s[3]));
544:
545: return addr;
546: }
547:
548:
549: u_long inet_addr (cp)
550: char *cp;
551: {
552: register int base;
553: register char c;
554: register u_long val;
555: u_long parts[4];
556: register u_long *pp = parts;
557:
558: for (;;) {
559: val = 0, base = 10;
560: if (*cp == '0')
561: base = 8, cp++;
562: if (*cp == 'x' || *cp == 'X')
563: base = 16, cp++;
564:
565: for (; isxdigit (c = *cp); cp++)
566: if (base == 16)
567: val = (val << 4) + (c + 10 - (islower (c) ? 'a' : 'A'));
568: else
569: if (isdigit (c))
570: val = (val * base) + (c - '0');
571: else
572: break;
573:
574: switch (*cp) {
575: case '.':
576: if (pp >= parts + 4)
577: return NOTOK;
578: *pp++ = val, cp++;
579: continue;
580:
581: default:
582: if (*cp && !isspace (*cp))
583: return NOTOK;
584: *pp++ = val;
585: break;
586: }
587:
588: break;
589: }
590:
591: switch (pp - parts) {
592: case 1:
593: val = parts[0];
594: break;
595:
596: case 2:
597: val = ((parts[0] & 0xff) << 24)
598: | (parts[1] & 0xffffff);
599: break;
600:
601: case 3:
602: val = ((parts[0] & 0xff) << 24)
603: | ((parts[1] & 0xff) << 16)
604: | (parts[2] & 0xffff);
605: break;
606:
607: case 4:
608: val = ((parts[0] & 0xff) << 24)
609: | ((parts[1] & 0xff) << 16)
610: | ((parts[2] & 0xff) << 8)
611: | (parts[3] & 0xff);
612: break;
613:
614: default:
615: return NOTOK;
616: }
617:
618: return htonl (val);
619: }
620:
621: u_long inet_network (cp)
622: char *cp;
623: {
624: register int base;
625: register char c;
626: register u_long val;
627: u_long parts[4];
628: register u_long *pp = parts;
629:
630: for (;;) {
631: val = 0, base = 10;
632: if (*cp == '0')
633: base = 8, cp++;
634: if (*cp == 'x' || *cp == 'X')
635: base = 16, cp++;
636:
637: for (; isxdigit (c = *cp); cp++)
638: if (base == 16)
639: val = (val << 4) + (c + 10 - (islower (c) ? 'a' : 'A'));
640: else
641: if (isdigit (c))
642: val = (val * base) + (c - '0');
643: else
644: break;
645:
646: switch (*cp) {
647: case '.':
648: if (pp >= parts + 4)
649: return NOTOK;
650: *pp++ = val, cp++;
651: continue;
652:
653: default:
654: if (*cp && !isspace (*cp))
655: return NOTOK;
656: *pp++ = val;
657: break;
658: }
659:
660: break;
661: }
662:
663: switch (pp - parts) {
664: case 1:
665: val = (parts[0] & 0xff) << 24;
666: break;
667:
668: case 2:
669: val = ((parts[0] & 0xff) << 24)
670: | ((parts[1] & 0xff) << 16);
671: break;
672:
673: case 3:
674: val = ((parts[0] & 0xff) << 24)
675: | ((parts[1] & 0xff) << 16)
676: | ((parts[2] & 0xff) << 8)
677: break;
678:
679: case 4:
680: val = ((parts[0] & 0xff) << 24)
681: | ((parts[1] & 0xff) << 16)
682: | ((parts[2] & 0xff) << 8)
683: | (parts[3] & 0xff);
684: break;
685:
686: default:
687: return NOTOK;
688: }
689:
690: return htonl (val);
691: }
692: #endif
693: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.