12aef6930SMark Murray /* 22aef6930SMark Murray * tli_host() determines the type of transport (connected, connectionless), 32aef6930SMark Murray * the transport address of a client host, and the transport address of a 42aef6930SMark Murray * server endpoint. In addition, it provides methods to map a transport 52aef6930SMark Murray * address to a printable host name or address. Socket address results are 62aef6930SMark Murray * in static memory; tli structures are allocated from the heap. 72aef6930SMark Murray * 82aef6930SMark Murray * The result from the hostname lookup method is STRING_PARANOID when a host 92aef6930SMark Murray * pretends to have someone elses name, or when a host name is available but 102aef6930SMark Murray * could not be verified. 112aef6930SMark Murray * 122aef6930SMark Murray * Diagnostics are reported through syslog(3). 132aef6930SMark Murray * 142aef6930SMark Murray * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands. 158053080cSYoshinobu Inoue * 168053080cSYoshinobu Inoue * $FreeBSD$ 172aef6930SMark Murray */ 182aef6930SMark Murray 192aef6930SMark Murray #ifndef lint 202aef6930SMark Murray static char sccsid[] = "@(#) tli.c 1.15 97/03/21 19:27:25"; 212aef6930SMark Murray #endif 222aef6930SMark Murray 232aef6930SMark Murray #ifdef TLI 242aef6930SMark Murray 252aef6930SMark Murray /* System libraries. */ 262aef6930SMark Murray 272aef6930SMark Murray #include <sys/types.h> 282aef6930SMark Murray #include <sys/param.h> 292aef6930SMark Murray #include <sys/stream.h> 302aef6930SMark Murray #include <sys/stat.h> 312aef6930SMark Murray #include <sys/mkdev.h> 322aef6930SMark Murray #include <sys/tiuser.h> 332aef6930SMark Murray #include <sys/timod.h> 342aef6930SMark Murray #include <sys/socket.h> 352aef6930SMark Murray #include <netinet/in.h> 362aef6930SMark Murray #include <stdio.h> 372aef6930SMark Murray #include <syslog.h> 382aef6930SMark Murray #include <errno.h> 392aef6930SMark Murray #include <netconfig.h> 402aef6930SMark Murray #include <netdir.h> 412aef6930SMark Murray #include <string.h> 422aef6930SMark Murray 432aef6930SMark Murray extern char *nc_sperror(); 442aef6930SMark Murray extern int errno; 452aef6930SMark Murray extern char *sys_errlist[]; 462aef6930SMark Murray extern int sys_nerr; 472aef6930SMark Murray extern int t_errno; 482aef6930SMark Murray extern char *t_errlist[]; 492aef6930SMark Murray extern int t_nerr; 502aef6930SMark Murray 512aef6930SMark Murray /* Local stuff. */ 522aef6930SMark Murray 532aef6930SMark Murray #include "tcpd.h" 542aef6930SMark Murray 552aef6930SMark Murray /* Forward declarations. */ 562aef6930SMark Murray 572aef6930SMark Murray static void tli_endpoints(); 582aef6930SMark Murray static struct netconfig *tli_transport(); 592aef6930SMark Murray static void tli_hostname(); 602aef6930SMark Murray static void tli_hostaddr(); 612aef6930SMark Murray static void tli_cleanup(); 622aef6930SMark Murray static char *tli_error(); 632aef6930SMark Murray static void tli_sink(); 642aef6930SMark Murray 652aef6930SMark Murray /* tli_host - look up endpoint addresses and install conversion methods */ 662aef6930SMark Murray 672aef6930SMark Murray void tli_host(request) 682aef6930SMark Murray struct request_info *request; 692aef6930SMark Murray { 708053080cSYoshinobu Inoue #ifdef INET6 718053080cSYoshinobu Inoue static struct sockaddr_storage client; 728053080cSYoshinobu Inoue static struct sockaddr_storage server; 738053080cSYoshinobu Inoue #else 742aef6930SMark Murray static struct sockaddr_in client; 752aef6930SMark Murray static struct sockaddr_in server; 768053080cSYoshinobu Inoue #endif 772aef6930SMark Murray 782aef6930SMark Murray /* 792aef6930SMark Murray * If we discover that we are using an IP transport, pretend we never 802aef6930SMark Murray * were here. Otherwise, use the transport-independent method and stick 812aef6930SMark Murray * to generic network addresses. XXX hard-coded protocol family name. 822aef6930SMark Murray */ 832aef6930SMark Murray 842aef6930SMark Murray tli_endpoints(request); 858053080cSYoshinobu Inoue #ifdef INET6 868053080cSYoshinobu Inoue if ((request->config = tli_transport(request->fd)) != 0 878053080cSYoshinobu Inoue && (STR_EQ(request->config->nc_protofmly, "inet") || 888053080cSYoshinobu Inoue STR_EQ(request->config->nc_protofmly, "inet6"))) { 898053080cSYoshinobu Inoue #else 902aef6930SMark Murray if ((request->config = tli_transport(request->fd)) != 0 912aef6930SMark Murray && STR_EQ(request->config->nc_protofmly, "inet")) { 928053080cSYoshinobu Inoue #endif 932aef6930SMark Murray if (request->client->unit != 0) { 948053080cSYoshinobu Inoue #ifdef INET6 958053080cSYoshinobu Inoue client = *(struct sockaddr_storage *) request->client->unit->addr.buf; 968053080cSYoshinobu Inoue request->client->sin = (struct sockaddr *) &client; 978053080cSYoshinobu Inoue #else 982aef6930SMark Murray client = *(struct sockaddr_in *) request->client->unit->addr.buf; 992aef6930SMark Murray request->client->sin = &client; 1008053080cSYoshinobu Inoue #endif 1012aef6930SMark Murray } 1022aef6930SMark Murray if (request->server->unit != 0) { 1038053080cSYoshinobu Inoue #ifdef INET6 1048053080cSYoshinobu Inoue server = *(struct sockaddr_storage *) request->server->unit->addr.buf; 1058053080cSYoshinobu Inoue request->server->sin = (struct sockaddr *) &server; 1068053080cSYoshinobu Inoue #else 1072aef6930SMark Murray server = *(struct sockaddr_in *) request->server->unit->addr.buf; 1082aef6930SMark Murray request->server->sin = &server; 1098053080cSYoshinobu Inoue #endif 1102aef6930SMark Murray } 1112aef6930SMark Murray tli_cleanup(request); 1122aef6930SMark Murray sock_methods(request); 1132aef6930SMark Murray } else { 1142aef6930SMark Murray request->hostname = tli_hostname; 1152aef6930SMark Murray request->hostaddr = tli_hostaddr; 1162aef6930SMark Murray request->cleanup = tli_cleanup; 1172aef6930SMark Murray } 1182aef6930SMark Murray } 1192aef6930SMark Murray 1202aef6930SMark Murray /* tli_cleanup - cleanup some dynamically-allocated data structures */ 1212aef6930SMark Murray 1222aef6930SMark Murray static void tli_cleanup(request) 1232aef6930SMark Murray struct request_info *request; 1242aef6930SMark Murray { 1252aef6930SMark Murray if (request->config != 0) 1262aef6930SMark Murray freenetconfigent(request->config); 1272aef6930SMark Murray if (request->client->unit != 0) 1282aef6930SMark Murray t_free((char *) request->client->unit, T_UNITDATA); 1292aef6930SMark Murray if (request->server->unit != 0) 1302aef6930SMark Murray t_free((char *) request->server->unit, T_UNITDATA); 1312aef6930SMark Murray } 1322aef6930SMark Murray 1332aef6930SMark Murray /* tli_endpoints - determine TLI client and server endpoint information */ 1342aef6930SMark Murray 1352aef6930SMark Murray static void tli_endpoints(request) 1362aef6930SMark Murray struct request_info *request; 1372aef6930SMark Murray { 1382aef6930SMark Murray struct t_unitdata *server; 1392aef6930SMark Murray struct t_unitdata *client; 1402aef6930SMark Murray int fd = request->fd; 1412aef6930SMark Murray int flags; 1422aef6930SMark Murray 1432aef6930SMark Murray /* 1442aef6930SMark Murray * Determine the client endpoint address. With unconnected services, peek 1452aef6930SMark Murray * at the sender address of the pending protocol data unit without 1462aef6930SMark Murray * popping it off the receive queue. This trick works because only the 1472aef6930SMark Murray * address member of the unitdata structure has been allocated. 1482aef6930SMark Murray * 1492aef6930SMark Murray * Beware of successful returns with zero-length netbufs (for example, 1502aef6930SMark Murray * Solaris 2.3 with ticlts transport). The netdir(3) routines can't 1512aef6930SMark Murray * handle that. Assume connection-less transport when TI_GETPEERNAME 1522aef6930SMark Murray * produces no usable result, even when t_rcvudata() is unable to figure 1532aef6930SMark Murray * out the peer address. Better to hang than to loop. 1542aef6930SMark Murray */ 1552aef6930SMark Murray 1562aef6930SMark Murray if ((client = (struct t_unitdata *) t_alloc(fd, T_UNITDATA, T_ADDR)) == 0) { 1572aef6930SMark Murray tcpd_warn("t_alloc: %s", tli_error()); 1582aef6930SMark Murray return; 1592aef6930SMark Murray } 1602aef6930SMark Murray if (ioctl(fd, TI_GETPEERNAME, &client->addr) < 0 || client->addr.len == 0) { 1612aef6930SMark Murray request->sink = tli_sink; 1622aef6930SMark Murray if (t_rcvudata(fd, client, &flags) < 0 || client->addr.len == 0) { 1632aef6930SMark Murray tcpd_warn("can't get client address: %s", tli_error()); 1642aef6930SMark Murray t_free((void *) client, T_UNITDATA); 1652aef6930SMark Murray return; 1662aef6930SMark Murray } 1672aef6930SMark Murray } 1682aef6930SMark Murray request->client->unit = client; 1692aef6930SMark Murray 1702aef6930SMark Murray /* 1712aef6930SMark Murray * Look up the server endpoint address. This can be used for filtering on 1722aef6930SMark Murray * server address or name, or to look up the client user. 1732aef6930SMark Murray */ 1742aef6930SMark Murray 1752aef6930SMark Murray if ((server = (struct t_unitdata *) t_alloc(fd, T_UNITDATA, T_ADDR)) == 0) { 1762aef6930SMark Murray tcpd_warn("t_alloc: %s", tli_error()); 1772aef6930SMark Murray return; 1782aef6930SMark Murray } 1792aef6930SMark Murray if (ioctl(fd, TI_GETMYNAME, &server->addr) < 0) { 1802aef6930SMark Murray tcpd_warn("TI_GETMYNAME: %m"); 1812aef6930SMark Murray t_free((void *) server, T_UNITDATA); 1822aef6930SMark Murray return; 1832aef6930SMark Murray } 1842aef6930SMark Murray request->server->unit = server; 1852aef6930SMark Murray } 1862aef6930SMark Murray 1872aef6930SMark Murray /* tli_transport - find out TLI transport type */ 1882aef6930SMark Murray 1892aef6930SMark Murray static struct netconfig *tli_transport(fd) 1902aef6930SMark Murray int fd; 1912aef6930SMark Murray { 1922aef6930SMark Murray struct stat from_client; 1932aef6930SMark Murray struct stat from_config; 1942aef6930SMark Murray void *handlep; 1952aef6930SMark Murray struct netconfig *config; 1962aef6930SMark Murray 1972aef6930SMark Murray /* 1982aef6930SMark Murray * Assuming that the network device is a clone device, we must compare 1992aef6930SMark Murray * the major device number of stdin to the minor device number of the 2002aef6930SMark Murray * devices listed in the netconfig table. 2012aef6930SMark Murray */ 2022aef6930SMark Murray 2032aef6930SMark Murray if (fstat(fd, &from_client) != 0) { 2042aef6930SMark Murray tcpd_warn("fstat(fd %d): %m", fd); 2052aef6930SMark Murray return (0); 2062aef6930SMark Murray } 2072aef6930SMark Murray if ((handlep = setnetconfig()) == 0) { 2082aef6930SMark Murray tcpd_warn("setnetconfig: %m"); 2092aef6930SMark Murray return (0); 2102aef6930SMark Murray } 2112aef6930SMark Murray while (config = getnetconfig(handlep)) { 2122aef6930SMark Murray if (stat(config->nc_device, &from_config) == 0) { 2138053080cSYoshinobu Inoue #ifdef NO_CLONE_DEVICE 2148053080cSYoshinobu Inoue /* 2158053080cSYoshinobu Inoue * If the network devices are not cloned (as is the case for 2168053080cSYoshinobu Inoue * Solaris 8 Beta), we must compare the major device numbers. 2178053080cSYoshinobu Inoue */ 2188053080cSYoshinobu Inoue if (major(from_config.st_rdev) == major(from_client.st_rdev)) 2198053080cSYoshinobu Inoue #else 2202aef6930SMark Murray if (minor(from_config.st_rdev) == major(from_client.st_rdev)) 2218053080cSYoshinobu Inoue #endif 2222aef6930SMark Murray break; 2232aef6930SMark Murray } 2242aef6930SMark Murray } 2252aef6930SMark Murray if (config == 0) { 2262aef6930SMark Murray tcpd_warn("unable to identify transport protocol"); 2272aef6930SMark Murray return (0); 2282aef6930SMark Murray } 2292aef6930SMark Murray 2302aef6930SMark Murray /* 2312aef6930SMark Murray * Something else may clobber our getnetconfig() result, so we'd better 2322aef6930SMark Murray * acquire our private copy. 2332aef6930SMark Murray */ 2342aef6930SMark Murray 2352aef6930SMark Murray if ((config = getnetconfigent(config->nc_netid)) == 0) { 2362aef6930SMark Murray tcpd_warn("getnetconfigent(%s): %s", config->nc_netid, nc_sperror()); 2372aef6930SMark Murray return (0); 2382aef6930SMark Murray } 2392aef6930SMark Murray return (config); 2402aef6930SMark Murray } 2412aef6930SMark Murray 2422aef6930SMark Murray /* tli_hostaddr - map TLI transport address to printable address */ 2432aef6930SMark Murray 2442aef6930SMark Murray static void tli_hostaddr(host) 2452aef6930SMark Murray struct host_info *host; 2462aef6930SMark Murray { 2472aef6930SMark Murray struct request_info *request = host->request; 2482aef6930SMark Murray struct netconfig *config = request->config; 2492aef6930SMark Murray struct t_unitdata *unit = host->unit; 2502aef6930SMark Murray char *uaddr; 2512aef6930SMark Murray 2522aef6930SMark Murray if (config != 0 && unit != 0 2532aef6930SMark Murray && (uaddr = taddr2uaddr(config, &unit->addr)) != 0) { 2542aef6930SMark Murray STRN_CPY(host->addr, uaddr, sizeof(host->addr)); 2552aef6930SMark Murray free(uaddr); 2562aef6930SMark Murray } 2572aef6930SMark Murray } 2582aef6930SMark Murray 2592aef6930SMark Murray /* tli_hostname - map TLI transport address to hostname */ 2602aef6930SMark Murray 2612aef6930SMark Murray static void tli_hostname(host) 2622aef6930SMark Murray struct host_info *host; 2632aef6930SMark Murray { 2642aef6930SMark Murray struct request_info *request = host->request; 2652aef6930SMark Murray struct netconfig *config = request->config; 2662aef6930SMark Murray struct t_unitdata *unit = host->unit; 2672aef6930SMark Murray struct nd_hostservlist *servlist; 2682aef6930SMark Murray 2692aef6930SMark Murray if (config != 0 && unit != 0 2702aef6930SMark Murray && netdir_getbyaddr(config, &servlist, &unit->addr) == ND_OK) { 2712aef6930SMark Murray 2722aef6930SMark Murray struct nd_hostserv *service = servlist->h_hostservs; 2732aef6930SMark Murray struct nd_addrlist *addr_list; 2742aef6930SMark Murray int found = 0; 2752aef6930SMark Murray 2762aef6930SMark Murray if (netdir_getbyname(config, service, &addr_list) != ND_OK) { 2772aef6930SMark Murray 2782aef6930SMark Murray /* 2792aef6930SMark Murray * Unable to verify that the name matches the address. This may 2802aef6930SMark Murray * be a transient problem or a botched name server setup. We 2812aef6930SMark Murray * decide to play safe. 2822aef6930SMark Murray */ 2832aef6930SMark Murray 2842aef6930SMark Murray tcpd_warn("can't verify hostname: netdir_getbyname(%.*s) failed", 2852aef6930SMark Murray STRING_LENGTH, service->h_host); 2862aef6930SMark Murray 2872aef6930SMark Murray } else { 2882aef6930SMark Murray 2892aef6930SMark Murray /* 2902aef6930SMark Murray * Look up the host address in the address list we just got. The 2912aef6930SMark Murray * comparison is done on the textual representation, because the 2922aef6930SMark Murray * transport address is an opaque structure that may have holes 2932aef6930SMark Murray * with uninitialized garbage. This approach obviously loses when 2942aef6930SMark Murray * the address does not have a textual representation. 2952aef6930SMark Murray */ 2962aef6930SMark Murray 2972aef6930SMark Murray char *uaddr = eval_hostaddr(host); 2982aef6930SMark Murray char *ua; 2992aef6930SMark Murray int i; 3002aef6930SMark Murray 3012aef6930SMark Murray for (i = 0; found == 0 && i < addr_list->n_cnt; i++) { 3022aef6930SMark Murray if ((ua = taddr2uaddr(config, &(addr_list->n_addrs[i]))) != 0) { 3032aef6930SMark Murray found = !strcmp(ua, uaddr); 3042aef6930SMark Murray free(ua); 3052aef6930SMark Murray } 3062aef6930SMark Murray } 3072aef6930SMark Murray netdir_free((void *) addr_list, ND_ADDRLIST); 3082aef6930SMark Murray 3092aef6930SMark Murray /* 3102aef6930SMark Murray * When the host name does not map to the initial address, assume 3112aef6930SMark Murray * someone has compromised a name server. More likely someone 3122aef6930SMark Murray * botched it, but that could be dangerous, too. 3132aef6930SMark Murray */ 3142aef6930SMark Murray 3152aef6930SMark Murray if (found == 0) 3162aef6930SMark Murray tcpd_warn("host name/address mismatch: %s != %.*s", 3172aef6930SMark Murray host->addr, STRING_LENGTH, service->h_host); 3182aef6930SMark Murray } 3192aef6930SMark Murray STRN_CPY(host->name, found ? service->h_host : paranoid, 3202aef6930SMark Murray sizeof(host->name)); 3212aef6930SMark Murray netdir_free((void *) servlist, ND_HOSTSERVLIST); 3222aef6930SMark Murray } 3232aef6930SMark Murray } 3242aef6930SMark Murray 3252aef6930SMark Murray /* tli_error - convert tli error number to text */ 3262aef6930SMark Murray 3272aef6930SMark Murray static char *tli_error() 3282aef6930SMark Murray { 3292aef6930SMark Murray static char buf[40]; 3302aef6930SMark Murray 3312aef6930SMark Murray if (t_errno != TSYSERR) { 3322aef6930SMark Murray if (t_errno < 0 || t_errno >= t_nerr) { 3332aef6930SMark Murray sprintf(buf, "Unknown TLI error %d", t_errno); 3342aef6930SMark Murray return (buf); 3352aef6930SMark Murray } else { 3362aef6930SMark Murray return (t_errlist[t_errno]); 3372aef6930SMark Murray } 3382aef6930SMark Murray } else { 3392aef6930SMark Murray if (errno < 0 || errno >= sys_nerr) { 3402aef6930SMark Murray sprintf(buf, "Unknown UNIX error %d", errno); 3412aef6930SMark Murray return (buf); 3422aef6930SMark Murray } else { 3432aef6930SMark Murray return (sys_errlist[errno]); 3442aef6930SMark Murray } 3452aef6930SMark Murray } 3462aef6930SMark Murray } 3472aef6930SMark Murray 3482aef6930SMark Murray /* tli_sink - absorb unreceived datagram */ 3492aef6930SMark Murray 3502aef6930SMark Murray static void tli_sink(fd) 3512aef6930SMark Murray int fd; 3522aef6930SMark Murray { 3532aef6930SMark Murray struct t_unitdata *unit; 3542aef6930SMark Murray int flags; 3552aef6930SMark Murray 3562aef6930SMark Murray /* 3572aef6930SMark Murray * Something went wrong. Absorb the datagram to keep inetd from looping. 3582aef6930SMark Murray * Allocate storage for address, control and data. If that fails, sleep 3592aef6930SMark Murray * for a couple of seconds in an attempt to keep inetd from looping too 3602aef6930SMark Murray * fast. 3612aef6930SMark Murray */ 3622aef6930SMark Murray 3632aef6930SMark Murray if ((unit = (struct t_unitdata *) t_alloc(fd, T_UNITDATA, T_ALL)) == 0) { 3642aef6930SMark Murray tcpd_warn("t_alloc: %s", tli_error()); 3652aef6930SMark Murray sleep(5); 3662aef6930SMark Murray } else { 3672aef6930SMark Murray (void) t_rcvudata(fd, unit, &flags); 3682aef6930SMark Murray t_free((void *) unit, T_UNITDATA); 3692aef6930SMark Murray } 3702aef6930SMark Murray } 3712aef6930SMark Murray 3722aef6930SMark Murray #endif /* TLI */ 373