diff options
Diffstat (limited to 'src/isode/compat/internet.c')
-rw-r--r-- | src/isode/compat/internet.c | 700 |
1 files changed, 700 insertions, 0 deletions
diff --git a/src/isode/compat/internet.c b/src/isode/compat/internet.c new file mode 100644 index 000000000..b6e0ea548 --- /dev/null +++ b/src/isode/compat/internet.c @@ -0,0 +1,700 @@ +/* internet.c - TCP/IP abstractions */ + +#ifndef lint +static char *rcsid = "$Header$"; +#endif + +/* + * $Header$ + * + * + * $Log$ + * Revision 1.1 1994/06/10 03:27:24 eichin + * autoconfed isode for kerberos work + * + * Revision 1.1 94/06/10 03:15:52 eichin + * autoconfed isode for kerberos work + * + * Revision 1.1 1994/05/31 20:33:53 eichin + * reduced-isode release from /mit/isode/isode-subset/src + * + * Revision 8.0 91/07/17 12:17:56 isode + * Release 7.0 + * + * + */ + +/* + * NOTICE + * + * Acquisition, use, and distribution of this module and related + * materials are subject to the restrictions of a license agreement. + * Consult the Preface in the User's Manual for the full terms of + * this agreement. + * + */ + + +/* LINTLIBRARY */ + +#include <ctype.h> +#include <errno.h> +#include <stdio.h> +#include "general.h" +#include "manifest.h" +#include "tailor.h" + +/* */ + +#ifdef TCP +#include "internet.h" + + +extern int errno; + +/* Berkeley UNIX: 4.2 */ + +#ifdef SOCKETS + +/* For real networking, nothing is better than 4BSD! */ + + +int start_tcp_client (sock, priv) +struct sockaddr_in *sock; +int priv; +{ + register int port; + int eindex, + sd; +#ifdef BSD43 + int onoff; +#endif + + if ((sd = socket (AF_INET, SOCK_STREAM, 0)) == NOTOK) { + SLOG (compat_log, LLOG_EXCEPTIONS, "failed", ("socket")); + return NOTOK; + } + + if (sock == NULL) + goto got_socket; + + for (port = IPPORT_RESERVED - priv;; priv ? port-- : port++) { + sock -> sin_port = htons ((u_short) port); + + if (bind (sd, (struct sockaddr *) sock, sizeof *sock) != NOTOK) + break; + + switch (errno) { + case EADDRINUSE: + if (!priv || (port >= IPPORT_RESERVED / 2)) + continue; /* else fall */ + + case EADDRNOTAVAIL: + default: + eindex = errno; + SLOG (compat_log, LLOG_EXCEPTIONS, "failed", ("bind")); + (void) close_tcp_socket (sd); + errno = eindex; + return NOTOK; + } + } + +got_socket: ; +#ifndef BSD43 + if (setsockopt (sd, SOL_SOCKET, SO_KEEPALIVE, NULLCP, 0) == NOTOK) + SLOG (compat_log, LLOG_EXCEPTIONS, "failed", ("set SO_KEEPALIVE")); +#else + onoff = 1; + if (setsockopt (sd, SOL_SOCKET, SO_KEEPALIVE, (char *) &onoff, + sizeof onoff) == NOTOK) + SLOG (compat_log, LLOG_EXCEPTIONS, "failed", ("set SO_KEEPALIVE")); +#endif + + return sd; +} + +/* */ + +int start_tcp_server (sock, backlog, opt1, opt2) +struct sockaddr_in *sock; +int backlog, + opt1, + opt2; +{ + register int port; + int eindex, + sd; +#ifdef BSD43 + int onoff; +#endif + + if ((sd = socket (AF_INET, SOCK_STREAM, 0)) == NOTOK) { + SLOG (compat_log, LLOG_EXCEPTIONS, "failed", ("socket")); + return NOTOK; + } + + if (sock -> sin_port != 0) { + if (bind (sd, (struct sockaddr *) sock, sizeof *sock) != NOTOK) + goto got_socket; + + eindex = errno; + SLOG (compat_log, LLOG_EXCEPTIONS, "failed", ("bind")); + (void) close_tcp_socket (sd); + errno = eindex; + return NOTOK; + } + + for (port = IPPORT_RESERVED;; port++) { + sock -> sin_port = htons ((u_short) port); + + if (bind (sd, (struct sockaddr *) sock, sizeof *sock) != NOTOK) + break; + + switch (errno) { + case EADDRINUSE: + continue; + + case EADDRNOTAVAIL: + default: + eindex = errno; + SLOG (compat_log, LLOG_EXCEPTIONS, "failed", ("bind")); + (void) close_tcp_socket (sd); + errno = eindex; + return NOTOK; + } + } + +got_socket: ; +#ifndef BSD43 + if (setsockopt (sd, SOL_SOCKET, SO_KEEPALIVE, NULLCP, 0) == NOTOK) + SLOG (compat_log, LLOG_EXCEPTIONS, "failed", ("set SO_KEEPALIVE")); + if (opt1 && setsockopt (sd, SOL_SOCKET, opt1, NULLCP, 0) == NOTOK) + SLOG (compat_log, LLOG_EXCEPTIONS, "failed", + ("set socket option 0x%x", opt1)); + if (opt2 && setsockopt (sd, SOL_SOCKET, opt2, NULLCP, 0) == NOTOK) + SLOG (compat_log, LLOG_EXCEPTIONS, "failed", + ("set socket option 0x%x", opt2)); +#else + onoff = 1; + if (setsockopt (sd, SOL_SOCKET, SO_KEEPALIVE, (char *) &onoff, + sizeof onoff) == NOTOK) + SLOG (compat_log, LLOG_EXCEPTIONS, "failed", ("set SO_KEEPALIVE")); + if (opt1 + && setsockopt (sd, SOL_SOCKET, opt1, (char *) &onoff, sizeof onoff) + == NOTOK) + SLOG (compat_log, LLOG_EXCEPTIONS, "failed", + ("set socket option 0x%x", opt1)); + if (opt2 + && setsockopt (sd, SOL_SOCKET, opt2, (char *) &onoff, sizeof onoff) + == NOTOK) + SLOG (compat_log, LLOG_EXCEPTIONS, "failed", + ("set socket option 0x%x", opt2)); +#endif + + (void) listen (sd, backlog); + + return sd; +} + +/* */ + +int join_tcp_client (fd, sock) +int fd; +struct sockaddr_in *sock; +{ + int eindex, + len = sizeof *sock, + result; + + if ((result = accept (fd, (struct sockaddr *) sock, &len)) == NOTOK) { + eindex = errno; + SLOG (compat_log, LLOG_EXCEPTIONS, "failed", ("accept")); + errno = eindex; + } + + return result; +} + +/* */ + +int join_tcp_server (fd, sock) +int fd; +struct sockaddr_in *sock; +{ + int eindex, + result; + + if ((result = connect (fd, (struct sockaddr *) sock, sizeof *sock)) + == NOTOK) { + eindex = errno; + SLOG (compat_log, LLOG_EXCEPTIONS, "failed", ("connect")); + errno = eindex; + } + + return result; +} + +/* */ + +close_tcp_socket (fd) +int fd; +{ +#ifdef never_do_this_if_from_join_tcp_client + (void) shutdown (fd, 2); +#endif + + return (close (fd)); +} + +#endif + +/* AT&T UNIX: 5r3 using TLI */ + + +/* AT&T UNIX: 5 with EXOS 8044 TCP/IP card */ + +#ifdef EXOS + +/* If we had a getsockname() for the EXOS card, then we could postpone some + of the binding until connect time. But since we don't, our hand is forced + and we must prematurely bind the sockets to IP addresses. */ + + +start_tcp_client (sock, priv) +struct sockaddr_in *sock; +int priv; +{ + register int port; + int sd; + register struct hostent *hp; + + if (sock == NULL) + return socket (SOCK_STREAM, 0, (struct sockaddr *) 0, SO_KEEPALIVE); + + if (sock -> sin_addr.s_addr == 0) { + if ((hp = gethostbyname ("localhost")) == NULL) { + errno = EADDRNOTAVAIL; + return NOTOK; + } + sock -> sin_family = hp -> h_addrtype; + inaddr_copy (hp, sock); + } + + for (port = IPPORT_RESERVED - priv;; priv ? port-- : port++) { + sock -> sin_port = htons ((u_short) port); + + if ((sd = socket (SOCK_STREAM, 0, (struct sockaddr *) sock, + SO_KEEPALIVE)) != NOTOK) + return sd; + + switch (errno) { + case EADDRINUSE: + if (!priv || (port >= IPPORT_RESERVED / 2)) + continue; /* else fall */ + + case EADDRNOTAVAIL: + default: + return NOTOK; + } + } +} + +/* */ + +int start_tcp_server (sock, backlog, opt1, opt2) +struct sockaddr_in *sock; +int backlog, + opt1, + opt2; +{ + register int port; + int sd; + register struct hostent *hp; + + if (backlog != 1) + return socket (SOCK_STREAM, 0, (struct sockaddr *) sock, + SO_ACCEPTCONN | SO_KEEPALIVE | opt1 | opt2); + + if (sock -> sin_addr.s_addr == 0) { + if ((hp = gethostbyname ("localhost")) == NULL) { + errno = EADDRNOTAVAIL; + return NOTOK; + } + sock -> sin_family = hp -> h_addrtype; + inaddr_copy (hp, sock); + } + + for (port = IPPORT_RESERVED;; port++) { + sock -> sin_port = htons ((u_short) port); + + if ((sd = socket (SOCK_STREAM, 0, (struct sockaddr *) sock, + SO_ACCEPTCONN | SO_KEEPALIVE | opt1 | opt2)) != NOTOK) + return sd; + + switch (errno) { + case EADDRINUSE: + continue; + + case EADDRNOTAVAIL: + default: + return NOTOK; + } + } +} + +#endif + +/* GETHOSTENT PLUS */ + +static char *empty = NULL; +#ifdef h_addr +static char *addrs[2] = { NULL }; +#endif + +struct hostent *gethostbystring (s) +char *s; +{ + register struct hostent *h; +#ifndef DG + static u_long iaddr; +#else + static struct in_addr iaddr; +#endif + static struct hostent hs; + + iaddr = inet_addr (s); +#ifndef DG + if (iaddr == NOTOK) +#else + if (iaddr.s_addr == NOTOK) +#endif + return gethostbyname (s); + + h = &hs; + h -> h_name = s; + h -> h_aliases = ∅ + h -> h_addrtype = AF_INET; + h -> h_length = sizeof (iaddr); +#ifdef h_addr + h -> h_addr_list = addrs; + bzero ((char *) addrs, sizeof addrs); +#endif + h -> h_addr = (char *) &iaddr; + + return h; +} + +/* AT&T UNIX: 5 with EXOS 8044 TCP/IP card */ + +#ifdef EXOS + +long rhost (); +char *raddr (); + + +struct hostent *gethostbyaddr (addr, len, type) +char *addr; +int len, + type; +{ + long iaddr; + char *name; + static char buffer[BUFSIZ]; + static struct hostent hs; + register struct hostent *h = &hs; + + if (len != sizeof (long) || type != AF_INET) + return NULL; + bcopy (addr, (char *) &iaddr, len); + if ((name = raddr (iaddr)) == NULL) + return NULL; + + (void) strcpy (buffer, name); + free (name); + + h -> h_name = buffer; + h -> h_aliases = ∅ + h -> h_addrtype = type; + h -> h_length = len; + h -> h_addr = addr; + + return h; +} + + +struct hostent *gethostbyname (name) +char *name; +{ + static long iaddr; + static char buffer[BUFSIZ]; + static struct hostent hs; + register struct hostent *h = &hs; + + if ((iaddr = rhost (&name)) == NOTOK) + return NULL; + + (void) strcpy (buffer, name); + free (name); + + h -> h_name = buffer; + h -> h_aliases = ∅ + h -> h_addrtype = AF_INET; + h -> h_length = sizeof (iaddr); + h -> h_addr = (char *) &iaddr; + + return h; + +} + +/* */ + +/* really only need the "tsap" entry in this table... but why not? */ + +static struct servent services[] = { + "tsap", NULL, 102, "tcp", + "miscellany", NULL, 17000, "lpp", + + "echo", NULL, 7, "tcp", /* Network standard functions */ + "echo", NULL, 7, "udp", + "sink", NULL, 9, "tcp", + "sink", NULL, 9, "udp", + "users", NULL, 11, "tcp", + "users", NULL, 11, "udp", + "daytime", NULL, 13, "tcp", + "daytime", NULL, 13, "udp", + "netstat", NULL, 15, "tcp", + "netstat", NULL, 15, "udp", + "qotd", NULL, 17, "tcp", + "qotd", NULL, 17, "udp", + "chargen", NULL, 19, "tcp", + "chargen", NULL, 19, "udp", + "ftp", NULL, 21, "tcp", + "telnet", NULL, 23, "tcp", + "smtp", NULL, 25, "tcp", + "imagen", NULL, 35, "udp", + "time", NULL, 37, "tcp", + "time", NULL, 37, "udp", + "name", NULL, 42, "tcp", + "name", NULL, 42, "udp", + "whois", NULL, 43, "tcp", + "whois", NULL, 43, "udp", + "nameserver", NULL, 53, "tcp", + "nameserver", NULL, 53, "udp", + "mtp", NULL, 57, "tcp", + "hostnames", NULL, 101, "tcp", + "pop", NULL, 109, "tcp", + "pwdgen", NULL, 129, "tcp", + "pwdgen", NULL, 129, "udp", + "x25bridge", NULL, 146, "tcp", + "iso-ip", NULL, 147, "udp", + + "tftp", NULL, 69, "udp", /* Host specific functions */ + "rje", NULL, 77, "tcp", + "nmui", NULL, 77, "udp", + "finger", NULL, 79, "tcp", + "finger", NULL, 79, "udp", + "link", NULL, 87, "tcp", + "supdup", NULL, 95, "tcp", + "path", NULL, 117, "tcp", + + "exec", NULL, 512, "tcp", /* UNIX TCP sockets */ + "login", NULL, 513, "tcp", + "shell", NULL, 514, "tcp", + "printer", NULL, 515, "tcp", + "rfile", NULL, 522, "tcp", + "ingreslock", NULL, 1524, "tcp", + + "biff", NULL, 512, "udp", /* UNIX UDP sockets */ + "who", NULL, 513, "udp", + "syslog", NULL, 514, "udp", + "talk", NULL, 517, "udp", + "routed", NULL, 520, "udp", + "router_1", NULL, 521, "udp", + + NULL, &empty, 0, NULL +}; + + + +struct servent *getservbyname (name, proto) +register char *name, + *proto; +{ + register struct servent *s; + + for (s = services; s -> s_name; s++) + if (strcmp (name, s -> s_name) == 0 + && strcmp (proto, s -> s_proto) == 0) { + if (s -> s_aliases == NULL) { + s -> s_aliases = ∅ + s -> s_port = htons ((u_short) s -> s_port); + } + + return s; + } + + return NULL; +} + +/* */ + +#define s2a(b) (((int) (b)) & 0xff) + +char *inet_ntoa (in) +struct in_addr in; +{ + register char *s = (char *) ∈ + static char addr[4 * 3 + 3 + 1]; + + (void) sprintf (addr, "%d.%d.%d.%d", + s2a (s[0]), s2a (s[1]), s2a (s[2]), s2a (s[3])); + + return addr; +} + + +u_long inet_addr (cp) +char *cp; +{ + register int base; + register char c; + register u_long val; + u_long parts[4]; + register u_long *pp = parts; + + for (;;) { + val = 0, base = 10; + if (*cp == '0') + base = 8, cp++; + if (*cp == 'x' || *cp == 'X') + base = 16, cp++; + + for (; isxdigit ((u_char) (c = *cp)); cp++) + if (base == 16) + val = (val << 4) + (c + 10 - (islower ((u_char) c) ? 'a' : 'A')); + else + if (isdigit ((u_char) c)) + val = (val * base) + (c - '0'); + else + break; + + switch (*cp) { + case '.': + if (pp >= parts + 4) + return NOTOK; + *pp++ = val, cp++; + continue; + + default: + if (*cp && !isspace ((u_char) *cp)) + return NOTOK; + *pp++ = val; + break; + } + + break; + } + + switch (pp - parts) { + case 1: + val = parts[0]; + break; + + case 2: + val = ((parts[0] & 0xff) << 24) + | (parts[1] & 0xffffff); + break; + + case 3: + val = ((parts[0] & 0xff) << 24) + | ((parts[1] & 0xff) << 16) + | (parts[2] & 0xffff); + break; + + case 4: + val = ((parts[0] & 0xff) << 24) + | ((parts[1] & 0xff) << 16) + | ((parts[2] & 0xff) << 8) + | (parts[3] & 0xff); + break; + + default: + return NOTOK; + } + + return htonl (val); +} + +u_long inet_network (cp) +char *cp; +{ + register int base; + register char c; + register u_long val; + u_long parts[4]; + register u_long *pp = parts; + + for (;;) { + val = 0, base = 10; + if (*cp == '0') + base = 8, cp++; + if (*cp == 'x' || *cp == 'X') + base = 16, cp++; + + for (; isxdigit ((u_char) (c = *cp)); cp++) + if (base == 16) + val = (val << 4) + (c + 10 - (islower ((u_char) c) ? 'a' : 'A')); + else + if (isdigit ((u_char) c)) + val = (val * base) + (c - '0'); + else + break; + + switch (*cp) { + case '.': + if (pp >= parts + 4) + return NOTOK; + *pp++ = val, cp++; + continue; + + default: + if (*cp && !isspace ((u_char) *cp)) + return NOTOK; + *pp++ = val; + break; + } + + break; + } + + switch (pp - parts) { + case 1: + val = (parts[0] & 0xff) << 24; + break; + + case 2: + val = ((parts[0] & 0xff) << 24) + | ((parts[1] & 0xff) << 16); + break; + + case 3: + val = ((parts[0] & 0xff) << 24) + | ((parts[1] & 0xff) << 16) + | ((parts[2] & 0xff) << 8) + break; + + case 4: + val = ((parts[0] & 0xff) << 24) + | ((parts[1] & 0xff) << 16) + | ((parts[2] & 0xff) << 8) + | (parts[3] & 0xff); + break; + + default: + return NOTOK; + } + + return htonl (val); +} +#endif +#endif |