xref: /illumos-gate/usr/src/lib/libwrap/tli.c (revision 55fea89d)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
37c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
47c478bd9Sstevel@tonic-gate  */
57c478bd9Sstevel@tonic-gate 
67c478bd9Sstevel@tonic-gate  /*
77c478bd9Sstevel@tonic-gate   * tli_host() determines the type of transport (connected, connectionless),
87c478bd9Sstevel@tonic-gate   * the transport address of a client host, and the transport address of a
97c478bd9Sstevel@tonic-gate   * server endpoint. In addition, it provides methods to map a transport
107c478bd9Sstevel@tonic-gate   * address to a printable host name or address. Socket address results are
117c478bd9Sstevel@tonic-gate   * in static memory; tli structures are allocated from the heap.
12*55fea89dSDan Cross   *
137c478bd9Sstevel@tonic-gate   * The result from the hostname lookup method is STRING_PARANOID when a host
147c478bd9Sstevel@tonic-gate   * pretends to have someone elses name, or when a host name is available but
157c478bd9Sstevel@tonic-gate   * could not be verified.
16*55fea89dSDan Cross   *
177c478bd9Sstevel@tonic-gate   * Diagnostics are reported through syslog(3).
18*55fea89dSDan Cross   *
197c478bd9Sstevel@tonic-gate   * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
207c478bd9Sstevel@tonic-gate   */
217c478bd9Sstevel@tonic-gate 
227c478bd9Sstevel@tonic-gate #ifndef lint
237c478bd9Sstevel@tonic-gate static char sccsid[] = "@(#) tli.c 1.15 97/03/21 19:27:25";
247c478bd9Sstevel@tonic-gate #endif
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate #ifdef TLI
277c478bd9Sstevel@tonic-gate 
287c478bd9Sstevel@tonic-gate /* System libraries. */
297c478bd9Sstevel@tonic-gate 
307c478bd9Sstevel@tonic-gate #include <sys/types.h>
317c478bd9Sstevel@tonic-gate #include <sys/param.h>
327c478bd9Sstevel@tonic-gate #include <sys/stream.h>
337c478bd9Sstevel@tonic-gate #include <sys/stat.h>
347c478bd9Sstevel@tonic-gate #include <sys/mkdev.h>
357c478bd9Sstevel@tonic-gate #include <sys/tiuser.h>
367c478bd9Sstevel@tonic-gate #include <sys/timod.h>
377c478bd9Sstevel@tonic-gate #include <sys/socket.h>
387c478bd9Sstevel@tonic-gate #include <netinet/in.h>
397c478bd9Sstevel@tonic-gate #include <stdio.h>
407c478bd9Sstevel@tonic-gate #include <stdlib.h>
417c478bd9Sstevel@tonic-gate #include <unistd.h>
427c478bd9Sstevel@tonic-gate #include <syslog.h>
437c478bd9Sstevel@tonic-gate #include <errno.h>
447c478bd9Sstevel@tonic-gate #include <netconfig.h>
457c478bd9Sstevel@tonic-gate #include <netdir.h>
467c478bd9Sstevel@tonic-gate #include <string.h>
477c478bd9Sstevel@tonic-gate 
487c478bd9Sstevel@tonic-gate extern char *nc_sperror();
497c478bd9Sstevel@tonic-gate extern int errno;
507c478bd9Sstevel@tonic-gate extern int t_errno;
517c478bd9Sstevel@tonic-gate extern char *t_errlist[];
527c478bd9Sstevel@tonic-gate extern int t_nerr;
537c478bd9Sstevel@tonic-gate 
547c478bd9Sstevel@tonic-gate /* Local stuff. */
557c478bd9Sstevel@tonic-gate 
567c478bd9Sstevel@tonic-gate #include "tcpd.h"
577c478bd9Sstevel@tonic-gate 
587c478bd9Sstevel@tonic-gate /* Forward declarations. */
597c478bd9Sstevel@tonic-gate 
607c478bd9Sstevel@tonic-gate static void tli_endpoints();
617c478bd9Sstevel@tonic-gate static struct netconfig *tli_transport();
627c478bd9Sstevel@tonic-gate static void tli_hostname();
637c478bd9Sstevel@tonic-gate static void tli_hostaddr();
647c478bd9Sstevel@tonic-gate static void tli_cleanup();
657c478bd9Sstevel@tonic-gate static char *tli_error();
667c478bd9Sstevel@tonic-gate static void tli_sink();
677c478bd9Sstevel@tonic-gate 
687c478bd9Sstevel@tonic-gate /* tli_host - look up endpoint addresses and install conversion methods */
697c478bd9Sstevel@tonic-gate 
tli_host(request)707c478bd9Sstevel@tonic-gate void    tli_host(request)
717c478bd9Sstevel@tonic-gate struct request_info *request;
727c478bd9Sstevel@tonic-gate {
737c478bd9Sstevel@tonic-gate     static struct sockaddr_gen client;
747c478bd9Sstevel@tonic-gate     static struct sockaddr_gen server;
757c478bd9Sstevel@tonic-gate 
767c478bd9Sstevel@tonic-gate     /*
777c478bd9Sstevel@tonic-gate      * If we discover that we are using an IP transport, pretend we never
787c478bd9Sstevel@tonic-gate      * were here. Otherwise, use the transport-independent method and stick
797c478bd9Sstevel@tonic-gate      * to generic network addresses. XXX hard-coded protocol family name.
807c478bd9Sstevel@tonic-gate      */
817c478bd9Sstevel@tonic-gate 
827c478bd9Sstevel@tonic-gate     tli_endpoints(request);
837c478bd9Sstevel@tonic-gate     if ((request->config = tli_transport(request->fd)) != 0
847c478bd9Sstevel@tonic-gate 	&& (STR_EQ(request->config->nc_protofmly, "inet")
857c478bd9Sstevel@tonic-gate #ifdef HAVE_IPV6
867c478bd9Sstevel@tonic-gate 	    || STR_EQ(request->config->nc_protofmly, "inet6")
877c478bd9Sstevel@tonic-gate #endif
887c478bd9Sstevel@tonic-gate 	)) {
897c478bd9Sstevel@tonic-gate 	if (request->client->unit != 0) {
907c478bd9Sstevel@tonic-gate 	    memcpy(&client, request->client->unit->addr.buf,
917c478bd9Sstevel@tonic-gate 		SGSOCKADDRSZ((struct sockaddr_gen*)
927c478bd9Sstevel@tonic-gate 				request->client->unit->addr.buf));
937c478bd9Sstevel@tonic-gate 	    request->client->sin = &client;
947c478bd9Sstevel@tonic-gate 	    sockgen_simplify(&client);
957c478bd9Sstevel@tonic-gate 	}
967c478bd9Sstevel@tonic-gate 	if (request->server->unit != 0) {
977c478bd9Sstevel@tonic-gate 	    memcpy(&server, request->server->unit->addr.buf,
987c478bd9Sstevel@tonic-gate 		SGSOCKADDRSZ((struct sockaddr_gen*)
997c478bd9Sstevel@tonic-gate 				request->server->unit->addr.buf));
1007c478bd9Sstevel@tonic-gate 	    request->server->sin = &server;
1017c478bd9Sstevel@tonic-gate 	    sockgen_simplify(&server);
1027c478bd9Sstevel@tonic-gate 	}
1037c478bd9Sstevel@tonic-gate 	tli_cleanup(request);
1047c478bd9Sstevel@tonic-gate 	sock_methods(request);
1057c478bd9Sstevel@tonic-gate     } else {
1067c478bd9Sstevel@tonic-gate 	request->hostname = tli_hostname;
1077c478bd9Sstevel@tonic-gate 	request->hostaddr = tli_hostaddr;
1087c478bd9Sstevel@tonic-gate 	request->cleanup = tli_cleanup;
1097c478bd9Sstevel@tonic-gate     }
1107c478bd9Sstevel@tonic-gate }
1117c478bd9Sstevel@tonic-gate 
1127c478bd9Sstevel@tonic-gate /* tli_cleanup - cleanup some dynamically-allocated data structures */
1137c478bd9Sstevel@tonic-gate 
tli_cleanup(request)1147c478bd9Sstevel@tonic-gate static void tli_cleanup(request)
1157c478bd9Sstevel@tonic-gate struct request_info *request;
1167c478bd9Sstevel@tonic-gate {
1177c478bd9Sstevel@tonic-gate     if (request->config != 0)
1187c478bd9Sstevel@tonic-gate 	freenetconfigent(request->config);
1197c478bd9Sstevel@tonic-gate     if (request->client->unit != 0)
1207c478bd9Sstevel@tonic-gate 	t_free((char *) request->client->unit, T_UNITDATA);
1217c478bd9Sstevel@tonic-gate     if (request->server->unit != 0)
1227c478bd9Sstevel@tonic-gate 	t_free((char *) request->server->unit, T_UNITDATA);
1237c478bd9Sstevel@tonic-gate }
1247c478bd9Sstevel@tonic-gate 
1257c478bd9Sstevel@tonic-gate /* tli_endpoints - determine TLI client and server endpoint information */
1267c478bd9Sstevel@tonic-gate 
tli_endpoints(request)1277c478bd9Sstevel@tonic-gate static void tli_endpoints(request)
1287c478bd9Sstevel@tonic-gate struct request_info *request;
1297c478bd9Sstevel@tonic-gate {
1307c478bd9Sstevel@tonic-gate     struct t_unitdata *server;
1317c478bd9Sstevel@tonic-gate     struct t_unitdata *client;
1327c478bd9Sstevel@tonic-gate     int     fd = request->fd;
1337c478bd9Sstevel@tonic-gate     int     flags;
1347c478bd9Sstevel@tonic-gate 
1357c478bd9Sstevel@tonic-gate     /*
1367c478bd9Sstevel@tonic-gate      * Determine the client endpoint address. With unconnected services, peek
1377c478bd9Sstevel@tonic-gate      * at the sender address of the pending protocol data unit without
1387c478bd9Sstevel@tonic-gate      * popping it off the receive queue. This trick works because only the
1397c478bd9Sstevel@tonic-gate      * address member of the unitdata structure has been allocated.
140*55fea89dSDan Cross      *
1417c478bd9Sstevel@tonic-gate      * Beware of successful returns with zero-length netbufs (for example,
1427c478bd9Sstevel@tonic-gate      * Solaris 2.3 with ticlts transport). The netdir(3) routines can't
1437c478bd9Sstevel@tonic-gate      * handle that. Assume connection-less transport when TI_GETPEERNAME
1447c478bd9Sstevel@tonic-gate      * produces no usable result, even when t_rcvudata() is unable to figure
1457c478bd9Sstevel@tonic-gate      * out the peer address. Better to hang than to loop.
1467c478bd9Sstevel@tonic-gate      */
1477c478bd9Sstevel@tonic-gate 
1487c478bd9Sstevel@tonic-gate     if ((client = (struct t_unitdata *) t_alloc(fd, T_UNITDATA, T_ADDR)) == 0) {
1497c478bd9Sstevel@tonic-gate 	tcpd_warn("t_alloc: %s", tli_error());
1507c478bd9Sstevel@tonic-gate 	return;
1517c478bd9Sstevel@tonic-gate     }
1527c478bd9Sstevel@tonic-gate     if (ioctl(fd, TI_GETPEERNAME, &client->addr) < 0 || client->addr.len == 0) {
1537c478bd9Sstevel@tonic-gate 	request->sink = tli_sink;
1547c478bd9Sstevel@tonic-gate 	if (t_rcvudata(fd, client, &flags) < 0 || client->addr.len == 0) {
1557c478bd9Sstevel@tonic-gate 	    tcpd_warn("can't get client address: %s", tli_error());
1567c478bd9Sstevel@tonic-gate 	    t_free((void *) client, T_UNITDATA);
1577c478bd9Sstevel@tonic-gate 	    return;
1587c478bd9Sstevel@tonic-gate 	}
1597c478bd9Sstevel@tonic-gate     }
1607c478bd9Sstevel@tonic-gate     request->client->unit = client;
1617c478bd9Sstevel@tonic-gate 
1627c478bd9Sstevel@tonic-gate     /*
1637c478bd9Sstevel@tonic-gate      * Look up the server endpoint address. This can be used for filtering on
1647c478bd9Sstevel@tonic-gate      * server address or name, or to look up the client user.
1657c478bd9Sstevel@tonic-gate      */
1667c478bd9Sstevel@tonic-gate 
1677c478bd9Sstevel@tonic-gate     if ((server = (struct t_unitdata *) t_alloc(fd, T_UNITDATA, T_ADDR)) == 0) {
1687c478bd9Sstevel@tonic-gate 	tcpd_warn("t_alloc: %s", tli_error());
1697c478bd9Sstevel@tonic-gate 	return;
1707c478bd9Sstevel@tonic-gate     }
1717c478bd9Sstevel@tonic-gate     if (ioctl(fd, TI_GETMYNAME, &server->addr) < 0) {
1727c478bd9Sstevel@tonic-gate 	tcpd_warn("TI_GETMYNAME: %m");
1737c478bd9Sstevel@tonic-gate 	t_free((void *) server, T_UNITDATA);
1747c478bd9Sstevel@tonic-gate 	return;
1757c478bd9Sstevel@tonic-gate     }
1767c478bd9Sstevel@tonic-gate     request->server->unit = server;
1777c478bd9Sstevel@tonic-gate }
1787c478bd9Sstevel@tonic-gate 
1797c478bd9Sstevel@tonic-gate /* tli_transport - find out TLI transport type */
1807c478bd9Sstevel@tonic-gate 
tli_transport(fd)1817c478bd9Sstevel@tonic-gate static struct netconfig *tli_transport(fd)
1827c478bd9Sstevel@tonic-gate int     fd;
1837c478bd9Sstevel@tonic-gate {
1847c478bd9Sstevel@tonic-gate     struct stat from_client;
1857c478bd9Sstevel@tonic-gate     struct stat from_config;
1867c478bd9Sstevel@tonic-gate     void   *handlep;
1877c478bd9Sstevel@tonic-gate     struct netconfig *config;
1887c478bd9Sstevel@tonic-gate 
1897c478bd9Sstevel@tonic-gate     /*
1907c478bd9Sstevel@tonic-gate      * Assuming that the network device is a clone device, we must compare
1917c478bd9Sstevel@tonic-gate      * the major device number of stdin to the minor device number of the
1927c478bd9Sstevel@tonic-gate      * devices listed in the netconfig table.
1937c478bd9Sstevel@tonic-gate      */
1947c478bd9Sstevel@tonic-gate 
1957c478bd9Sstevel@tonic-gate     if (fstat(fd, &from_client) != 0) {
1967c478bd9Sstevel@tonic-gate 	tcpd_warn("fstat(fd %d): %m", fd);
1977c478bd9Sstevel@tonic-gate 	return (0);
1987c478bd9Sstevel@tonic-gate     }
1997c478bd9Sstevel@tonic-gate     if ((handlep = setnetconfig()) == 0) {
2007c478bd9Sstevel@tonic-gate 	tcpd_warn("setnetconfig: %m");
2017c478bd9Sstevel@tonic-gate 	return (0);
2027c478bd9Sstevel@tonic-gate     }
2037c478bd9Sstevel@tonic-gate     while (config = getnetconfig(handlep)) {
2047c478bd9Sstevel@tonic-gate 	if (stat(config->nc_device, &from_config) == 0) {
2057c478bd9Sstevel@tonic-gate 	    if (minor(from_config.st_rdev) == major(from_client.st_rdev) ||
2067c478bd9Sstevel@tonic-gate 		/* XXX: Solaris 8 no longer has clone devices for IP */
2077c478bd9Sstevel@tonic-gate 		major(from_config.st_rdev) == major(from_client.st_rdev))
2087c478bd9Sstevel@tonic-gate 		break;
2097c478bd9Sstevel@tonic-gate 	}
2107c478bd9Sstevel@tonic-gate     }
2117c478bd9Sstevel@tonic-gate     if (config == 0) {
2127c478bd9Sstevel@tonic-gate 	tcpd_warn("unable to identify transport protocol");
2137c478bd9Sstevel@tonic-gate 	return (0);
2147c478bd9Sstevel@tonic-gate     }
2157c478bd9Sstevel@tonic-gate 
2167c478bd9Sstevel@tonic-gate     /*
2177c478bd9Sstevel@tonic-gate      * Something else may clobber our getnetconfig() result, so we'd better
2187c478bd9Sstevel@tonic-gate      * acquire our private copy.
2197c478bd9Sstevel@tonic-gate      */
2207c478bd9Sstevel@tonic-gate 
2217c478bd9Sstevel@tonic-gate     if ((config = getnetconfigent(config->nc_netid)) == 0) {
2227c478bd9Sstevel@tonic-gate 	tcpd_warn("getnetconfigent(%s): %s", config->nc_netid, nc_sperror());
2237c478bd9Sstevel@tonic-gate 	return (0);
2247c478bd9Sstevel@tonic-gate     }
2257c478bd9Sstevel@tonic-gate     return (config);
2267c478bd9Sstevel@tonic-gate }
2277c478bd9Sstevel@tonic-gate 
2287c478bd9Sstevel@tonic-gate /* tli_hostaddr - map TLI transport address to printable address */
2297c478bd9Sstevel@tonic-gate 
tli_hostaddr(host)2307c478bd9Sstevel@tonic-gate static void tli_hostaddr(host)
2317c478bd9Sstevel@tonic-gate struct host_info *host;
2327c478bd9Sstevel@tonic-gate {
2337c478bd9Sstevel@tonic-gate     struct request_info *request = host->request;
2347c478bd9Sstevel@tonic-gate     struct netconfig *config = request->config;
2357c478bd9Sstevel@tonic-gate     struct t_unitdata *unit = host->unit;
2367c478bd9Sstevel@tonic-gate     char   *uaddr;
2377c478bd9Sstevel@tonic-gate 
2387c478bd9Sstevel@tonic-gate     if (config != 0 && unit != 0
2397c478bd9Sstevel@tonic-gate 	&& (uaddr = taddr2uaddr(config, &unit->addr)) != 0) {
2407c478bd9Sstevel@tonic-gate 	STRN_CPY(host->addr, uaddr, sizeof(host->addr));
2417c478bd9Sstevel@tonic-gate 	free(uaddr);
2427c478bd9Sstevel@tonic-gate     }
2437c478bd9Sstevel@tonic-gate }
2447c478bd9Sstevel@tonic-gate 
2457c478bd9Sstevel@tonic-gate /* tli_hostname - map TLI transport address to hostname */
2467c478bd9Sstevel@tonic-gate 
tli_hostname(host)2477c478bd9Sstevel@tonic-gate static void tli_hostname(host)
2487c478bd9Sstevel@tonic-gate struct host_info *host;
2497c478bd9Sstevel@tonic-gate {
2507c478bd9Sstevel@tonic-gate     struct request_info *request = host->request;
2517c478bd9Sstevel@tonic-gate     struct netconfig *config = request->config;
2527c478bd9Sstevel@tonic-gate     struct t_unitdata *unit = host->unit;
2537c478bd9Sstevel@tonic-gate     struct nd_hostservlist *servlist;
2547c478bd9Sstevel@tonic-gate 
2557c478bd9Sstevel@tonic-gate     if (config != 0 && unit != 0
2567c478bd9Sstevel@tonic-gate 	&& netdir_getbyaddr(config, &servlist, &unit->addr) == ND_OK) {
2577c478bd9Sstevel@tonic-gate 
2587c478bd9Sstevel@tonic-gate 	struct nd_hostserv *service = servlist->h_hostservs;
2597c478bd9Sstevel@tonic-gate 	struct nd_addrlist *addr_list;
2607c478bd9Sstevel@tonic-gate 	int     found = 0;
2617c478bd9Sstevel@tonic-gate 
2627c478bd9Sstevel@tonic-gate 	if (netdir_getbyname(config, service, &addr_list) != ND_OK) {
2637c478bd9Sstevel@tonic-gate 
2647c478bd9Sstevel@tonic-gate 	    /*
2657c478bd9Sstevel@tonic-gate 	     * Unable to verify that the name matches the address. This may
2667c478bd9Sstevel@tonic-gate 	     * be a transient problem or a botched name server setup. We
2677c478bd9Sstevel@tonic-gate 	     * decide to play safe.
2687c478bd9Sstevel@tonic-gate 	     */
2697c478bd9Sstevel@tonic-gate 
2707c478bd9Sstevel@tonic-gate 	    tcpd_warn("can't verify hostname: netdir_getbyname(%.*s) failed",
2717c478bd9Sstevel@tonic-gate 		      STRING_LENGTH, service->h_host);
2727c478bd9Sstevel@tonic-gate 
2737c478bd9Sstevel@tonic-gate 	} else {
2747c478bd9Sstevel@tonic-gate 
2757c478bd9Sstevel@tonic-gate 	    /*
2767c478bd9Sstevel@tonic-gate 	     * Look up the host address in the address list we just got. The
2777c478bd9Sstevel@tonic-gate 	     * comparison is done on the textual representation, because the
2787c478bd9Sstevel@tonic-gate 	     * transport address is an opaque structure that may have holes
2797c478bd9Sstevel@tonic-gate 	     * with uninitialized garbage. This approach obviously loses when
2807c478bd9Sstevel@tonic-gate 	     * the address does not have a textual representation.
2817c478bd9Sstevel@tonic-gate 	     */
2827c478bd9Sstevel@tonic-gate 
2837c478bd9Sstevel@tonic-gate 	    char   *uaddr = eval_hostaddr(host);
2847c478bd9Sstevel@tonic-gate 	    char   *ua;
2857c478bd9Sstevel@tonic-gate 	    int     i;
2867c478bd9Sstevel@tonic-gate 
2877c478bd9Sstevel@tonic-gate 	    for (i = 0; found == 0 && i < addr_list->n_cnt; i++) {
2887c478bd9Sstevel@tonic-gate 		if ((ua = taddr2uaddr(config, &(addr_list->n_addrs[i]))) != 0) {
2897c478bd9Sstevel@tonic-gate 		    found = !strcmp(ua, uaddr);
2907c478bd9Sstevel@tonic-gate 		    free(ua);
2917c478bd9Sstevel@tonic-gate 		}
2927c478bd9Sstevel@tonic-gate 	    }
2937c478bd9Sstevel@tonic-gate 	    netdir_free((void *) addr_list, ND_ADDRLIST);
2947c478bd9Sstevel@tonic-gate 
2957c478bd9Sstevel@tonic-gate 	    /*
2967c478bd9Sstevel@tonic-gate 	     * When the host name does not map to the initial address, assume
2977c478bd9Sstevel@tonic-gate 	     * someone has compromised a name server. More likely someone
2987c478bd9Sstevel@tonic-gate 	     * botched it, but that could be dangerous, too.
2997c478bd9Sstevel@tonic-gate 	     */
3007c478bd9Sstevel@tonic-gate 
3017c478bd9Sstevel@tonic-gate 	    if (found == 0)
3027c478bd9Sstevel@tonic-gate 		tcpd_warn("host name/address mismatch: %s != %.*s",
3037c478bd9Sstevel@tonic-gate 			  host->addr, STRING_LENGTH, service->h_host);
3047c478bd9Sstevel@tonic-gate 	}
3057c478bd9Sstevel@tonic-gate 	STRN_CPY(host->name, found ? service->h_host : paranoid,
3067c478bd9Sstevel@tonic-gate 		 sizeof(host->name));
3077c478bd9Sstevel@tonic-gate 	netdir_free((void *) servlist, ND_HOSTSERVLIST);
3087c478bd9Sstevel@tonic-gate     }
3097c478bd9Sstevel@tonic-gate }
3107c478bd9Sstevel@tonic-gate 
3117c478bd9Sstevel@tonic-gate /* tli_error - convert tli error number to text */
3127c478bd9Sstevel@tonic-gate 
tli_error()3137c478bd9Sstevel@tonic-gate static char *tli_error()
3147c478bd9Sstevel@tonic-gate {
3157c478bd9Sstevel@tonic-gate     static char buf[40];
3167c478bd9Sstevel@tonic-gate 
3177c478bd9Sstevel@tonic-gate     if (t_errno != TSYSERR) {
3187c478bd9Sstevel@tonic-gate 	if (t_errno < 0 || t_errno >= t_nerr) {
3199584cebbSAlexander Pyhalov 	    snprintf(buf, sizeof (buf), "Unknown TLI error %d", t_errno);
3207c478bd9Sstevel@tonic-gate 	    return (buf);
3217c478bd9Sstevel@tonic-gate 	} else {
3227c478bd9Sstevel@tonic-gate 	    return (t_errlist[t_errno]);
3237c478bd9Sstevel@tonic-gate 	}
3247c478bd9Sstevel@tonic-gate     } else {
3259584cebbSAlexander Pyhalov 	STRN_CPY(buf, strerror(errno), sizeof (buf));
3269584cebbSAlexander Pyhalov 	return (buf);
3277c478bd9Sstevel@tonic-gate     }
3287c478bd9Sstevel@tonic-gate }
3297c478bd9Sstevel@tonic-gate 
3307c478bd9Sstevel@tonic-gate /* tli_sink - absorb unreceived datagram */
3317c478bd9Sstevel@tonic-gate 
tli_sink(fd)3327c478bd9Sstevel@tonic-gate static void tli_sink(fd)
3337c478bd9Sstevel@tonic-gate int     fd;
3347c478bd9Sstevel@tonic-gate {
3357c478bd9Sstevel@tonic-gate     struct t_unitdata *unit;
3367c478bd9Sstevel@tonic-gate     int     flags;
3377c478bd9Sstevel@tonic-gate 
3387c478bd9Sstevel@tonic-gate     /*
3397c478bd9Sstevel@tonic-gate      * Something went wrong. Absorb the datagram to keep inetd from looping.
3407c478bd9Sstevel@tonic-gate      * Allocate storage for address, control and data. If that fails, sleep
3417c478bd9Sstevel@tonic-gate      * for a couple of seconds in an attempt to keep inetd from looping too
3427c478bd9Sstevel@tonic-gate      * fast.
3437c478bd9Sstevel@tonic-gate      */
3447c478bd9Sstevel@tonic-gate 
3457c478bd9Sstevel@tonic-gate     if ((unit = (struct t_unitdata *) t_alloc(fd, T_UNITDATA, T_ALL)) == 0) {
3467c478bd9Sstevel@tonic-gate 	tcpd_warn("t_alloc: %s", tli_error());
3477c478bd9Sstevel@tonic-gate 	sleep(5);
3487c478bd9Sstevel@tonic-gate     } else {
3497c478bd9Sstevel@tonic-gate 	(void) t_rcvudata(fd, unit, &flags);
3507c478bd9Sstevel@tonic-gate 	t_free((void *) unit, T_UNITDATA);
3517c478bd9Sstevel@tonic-gate     }
3527c478bd9Sstevel@tonic-gate }
3537c478bd9Sstevel@tonic-gate 
3547c478bd9Sstevel@tonic-gate #endif /* TLI */
355