|
|
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.