xref: /titanic_54/usr/src/lib/libwrap/tli.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
3*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
4*7c478bd9Sstevel@tonic-gate  */
5*7c478bd9Sstevel@tonic-gate 
6*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
7*7c478bd9Sstevel@tonic-gate 
8*7c478bd9Sstevel@tonic-gate  /*
9*7c478bd9Sstevel@tonic-gate   * tli_host() determines the type of transport (connected, connectionless),
10*7c478bd9Sstevel@tonic-gate   * the transport address of a client host, and the transport address of a
11*7c478bd9Sstevel@tonic-gate   * server endpoint. In addition, it provides methods to map a transport
12*7c478bd9Sstevel@tonic-gate   * address to a printable host name or address. Socket address results are
13*7c478bd9Sstevel@tonic-gate   * in static memory; tli structures are allocated from the heap.
14*7c478bd9Sstevel@tonic-gate   *
15*7c478bd9Sstevel@tonic-gate   * The result from the hostname lookup method is STRING_PARANOID when a host
16*7c478bd9Sstevel@tonic-gate   * pretends to have someone elses name, or when a host name is available but
17*7c478bd9Sstevel@tonic-gate   * could not be verified.
18*7c478bd9Sstevel@tonic-gate   *
19*7c478bd9Sstevel@tonic-gate   * Diagnostics are reported through syslog(3).
20*7c478bd9Sstevel@tonic-gate   *
21*7c478bd9Sstevel@tonic-gate   * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
22*7c478bd9Sstevel@tonic-gate   */
23*7c478bd9Sstevel@tonic-gate 
24*7c478bd9Sstevel@tonic-gate #ifndef lint
25*7c478bd9Sstevel@tonic-gate static char sccsid[] = "@(#) tli.c 1.15 97/03/21 19:27:25";
26*7c478bd9Sstevel@tonic-gate #endif
27*7c478bd9Sstevel@tonic-gate 
28*7c478bd9Sstevel@tonic-gate #ifdef TLI
29*7c478bd9Sstevel@tonic-gate 
30*7c478bd9Sstevel@tonic-gate /* System libraries. */
31*7c478bd9Sstevel@tonic-gate 
32*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
33*7c478bd9Sstevel@tonic-gate #include <sys/param.h>
34*7c478bd9Sstevel@tonic-gate #include <sys/stream.h>
35*7c478bd9Sstevel@tonic-gate #include <sys/stat.h>
36*7c478bd9Sstevel@tonic-gate #include <sys/mkdev.h>
37*7c478bd9Sstevel@tonic-gate #include <sys/tiuser.h>
38*7c478bd9Sstevel@tonic-gate #include <sys/timod.h>
39*7c478bd9Sstevel@tonic-gate #include <sys/socket.h>
40*7c478bd9Sstevel@tonic-gate #include <netinet/in.h>
41*7c478bd9Sstevel@tonic-gate #include <stdio.h>
42*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
43*7c478bd9Sstevel@tonic-gate #include <unistd.h>
44*7c478bd9Sstevel@tonic-gate #include <syslog.h>
45*7c478bd9Sstevel@tonic-gate #include <errno.h>
46*7c478bd9Sstevel@tonic-gate #include <netconfig.h>
47*7c478bd9Sstevel@tonic-gate #include <netdir.h>
48*7c478bd9Sstevel@tonic-gate #include <string.h>
49*7c478bd9Sstevel@tonic-gate 
50*7c478bd9Sstevel@tonic-gate extern char *nc_sperror();
51*7c478bd9Sstevel@tonic-gate extern int errno;
52*7c478bd9Sstevel@tonic-gate extern char *sys_errlist[];
53*7c478bd9Sstevel@tonic-gate extern int sys_nerr;
54*7c478bd9Sstevel@tonic-gate extern int t_errno;
55*7c478bd9Sstevel@tonic-gate extern char *t_errlist[];
56*7c478bd9Sstevel@tonic-gate extern int t_nerr;
57*7c478bd9Sstevel@tonic-gate 
58*7c478bd9Sstevel@tonic-gate /* Local stuff. */
59*7c478bd9Sstevel@tonic-gate 
60*7c478bd9Sstevel@tonic-gate #include "tcpd.h"
61*7c478bd9Sstevel@tonic-gate 
62*7c478bd9Sstevel@tonic-gate /* Forward declarations. */
63*7c478bd9Sstevel@tonic-gate 
64*7c478bd9Sstevel@tonic-gate static void tli_endpoints();
65*7c478bd9Sstevel@tonic-gate static struct netconfig *tli_transport();
66*7c478bd9Sstevel@tonic-gate static void tli_hostname();
67*7c478bd9Sstevel@tonic-gate static void tli_hostaddr();
68*7c478bd9Sstevel@tonic-gate static void tli_cleanup();
69*7c478bd9Sstevel@tonic-gate static char *tli_error();
70*7c478bd9Sstevel@tonic-gate static void tli_sink();
71*7c478bd9Sstevel@tonic-gate 
72*7c478bd9Sstevel@tonic-gate /* tli_host - look up endpoint addresses and install conversion methods */
73*7c478bd9Sstevel@tonic-gate 
74*7c478bd9Sstevel@tonic-gate void    tli_host(request)
75*7c478bd9Sstevel@tonic-gate struct request_info *request;
76*7c478bd9Sstevel@tonic-gate {
77*7c478bd9Sstevel@tonic-gate     static struct sockaddr_gen client;
78*7c478bd9Sstevel@tonic-gate     static struct sockaddr_gen server;
79*7c478bd9Sstevel@tonic-gate 
80*7c478bd9Sstevel@tonic-gate     /*
81*7c478bd9Sstevel@tonic-gate      * If we discover that we are using an IP transport, pretend we never
82*7c478bd9Sstevel@tonic-gate      * were here. Otherwise, use the transport-independent method and stick
83*7c478bd9Sstevel@tonic-gate      * to generic network addresses. XXX hard-coded protocol family name.
84*7c478bd9Sstevel@tonic-gate      */
85*7c478bd9Sstevel@tonic-gate 
86*7c478bd9Sstevel@tonic-gate     tli_endpoints(request);
87*7c478bd9Sstevel@tonic-gate     if ((request->config = tli_transport(request->fd)) != 0
88*7c478bd9Sstevel@tonic-gate 	&& (STR_EQ(request->config->nc_protofmly, "inet")
89*7c478bd9Sstevel@tonic-gate #ifdef HAVE_IPV6
90*7c478bd9Sstevel@tonic-gate 	    || STR_EQ(request->config->nc_protofmly, "inet6")
91*7c478bd9Sstevel@tonic-gate #endif
92*7c478bd9Sstevel@tonic-gate 	)) {
93*7c478bd9Sstevel@tonic-gate 	if (request->client->unit != 0) {
94*7c478bd9Sstevel@tonic-gate 	    memcpy(&client, request->client->unit->addr.buf,
95*7c478bd9Sstevel@tonic-gate 		SGSOCKADDRSZ((struct sockaddr_gen*)
96*7c478bd9Sstevel@tonic-gate 				request->client->unit->addr.buf));
97*7c478bd9Sstevel@tonic-gate 	    request->client->sin = &client;
98*7c478bd9Sstevel@tonic-gate 	    sockgen_simplify(&client);
99*7c478bd9Sstevel@tonic-gate 	}
100*7c478bd9Sstevel@tonic-gate 	if (request->server->unit != 0) {
101*7c478bd9Sstevel@tonic-gate 	    memcpy(&server, request->server->unit->addr.buf,
102*7c478bd9Sstevel@tonic-gate 		SGSOCKADDRSZ((struct sockaddr_gen*)
103*7c478bd9Sstevel@tonic-gate 				request->server->unit->addr.buf));
104*7c478bd9Sstevel@tonic-gate 	    request->server->sin = &server;
105*7c478bd9Sstevel@tonic-gate 	    sockgen_simplify(&server);
106*7c478bd9Sstevel@tonic-gate 	}
107*7c478bd9Sstevel@tonic-gate 	tli_cleanup(request);
108*7c478bd9Sstevel@tonic-gate 	sock_methods(request);
109*7c478bd9Sstevel@tonic-gate     } else {
110*7c478bd9Sstevel@tonic-gate 	request->hostname = tli_hostname;
111*7c478bd9Sstevel@tonic-gate 	request->hostaddr = tli_hostaddr;
112*7c478bd9Sstevel@tonic-gate 	request->cleanup = tli_cleanup;
113*7c478bd9Sstevel@tonic-gate     }
114*7c478bd9Sstevel@tonic-gate }
115*7c478bd9Sstevel@tonic-gate 
116*7c478bd9Sstevel@tonic-gate /* tli_cleanup - cleanup some dynamically-allocated data structures */
117*7c478bd9Sstevel@tonic-gate 
118*7c478bd9Sstevel@tonic-gate static void tli_cleanup(request)
119*7c478bd9Sstevel@tonic-gate struct request_info *request;
120*7c478bd9Sstevel@tonic-gate {
121*7c478bd9Sstevel@tonic-gate     if (request->config != 0)
122*7c478bd9Sstevel@tonic-gate 	freenetconfigent(request->config);
123*7c478bd9Sstevel@tonic-gate     if (request->client->unit != 0)
124*7c478bd9Sstevel@tonic-gate 	t_free((char *) request->client->unit, T_UNITDATA);
125*7c478bd9Sstevel@tonic-gate     if (request->server->unit != 0)
126*7c478bd9Sstevel@tonic-gate 	t_free((char *) request->server->unit, T_UNITDATA);
127*7c478bd9Sstevel@tonic-gate }
128*7c478bd9Sstevel@tonic-gate 
129*7c478bd9Sstevel@tonic-gate /* tli_endpoints - determine TLI client and server endpoint information */
130*7c478bd9Sstevel@tonic-gate 
131*7c478bd9Sstevel@tonic-gate static void tli_endpoints(request)
132*7c478bd9Sstevel@tonic-gate struct request_info *request;
133*7c478bd9Sstevel@tonic-gate {
134*7c478bd9Sstevel@tonic-gate     struct t_unitdata *server;
135*7c478bd9Sstevel@tonic-gate     struct t_unitdata *client;
136*7c478bd9Sstevel@tonic-gate     int     fd = request->fd;
137*7c478bd9Sstevel@tonic-gate     int     flags;
138*7c478bd9Sstevel@tonic-gate 
139*7c478bd9Sstevel@tonic-gate     /*
140*7c478bd9Sstevel@tonic-gate      * Determine the client endpoint address. With unconnected services, peek
141*7c478bd9Sstevel@tonic-gate      * at the sender address of the pending protocol data unit without
142*7c478bd9Sstevel@tonic-gate      * popping it off the receive queue. This trick works because only the
143*7c478bd9Sstevel@tonic-gate      * address member of the unitdata structure has been allocated.
144*7c478bd9Sstevel@tonic-gate      *
145*7c478bd9Sstevel@tonic-gate      * Beware of successful returns with zero-length netbufs (for example,
146*7c478bd9Sstevel@tonic-gate      * Solaris 2.3 with ticlts transport). The netdir(3) routines can't
147*7c478bd9Sstevel@tonic-gate      * handle that. Assume connection-less transport when TI_GETPEERNAME
148*7c478bd9Sstevel@tonic-gate      * produces no usable result, even when t_rcvudata() is unable to figure
149*7c478bd9Sstevel@tonic-gate      * out the peer address. Better to hang than to loop.
150*7c478bd9Sstevel@tonic-gate      */
151*7c478bd9Sstevel@tonic-gate 
152*7c478bd9Sstevel@tonic-gate     if ((client = (struct t_unitdata *) t_alloc(fd, T_UNITDATA, T_ADDR)) == 0) {
153*7c478bd9Sstevel@tonic-gate 	tcpd_warn("t_alloc: %s", tli_error());
154*7c478bd9Sstevel@tonic-gate 	return;
155*7c478bd9Sstevel@tonic-gate     }
156*7c478bd9Sstevel@tonic-gate     if (ioctl(fd, TI_GETPEERNAME, &client->addr) < 0 || client->addr.len == 0) {
157*7c478bd9Sstevel@tonic-gate 	request->sink = tli_sink;
158*7c478bd9Sstevel@tonic-gate 	if (t_rcvudata(fd, client, &flags) < 0 || client->addr.len == 0) {
159*7c478bd9Sstevel@tonic-gate 	    tcpd_warn("can't get client address: %s", tli_error());
160*7c478bd9Sstevel@tonic-gate 	    t_free((void *) client, T_UNITDATA);
161*7c478bd9Sstevel@tonic-gate 	    return;
162*7c478bd9Sstevel@tonic-gate 	}
163*7c478bd9Sstevel@tonic-gate     }
164*7c478bd9Sstevel@tonic-gate     request->client->unit = client;
165*7c478bd9Sstevel@tonic-gate 
166*7c478bd9Sstevel@tonic-gate     /*
167*7c478bd9Sstevel@tonic-gate      * Look up the server endpoint address. This can be used for filtering on
168*7c478bd9Sstevel@tonic-gate      * server address or name, or to look up the client user.
169*7c478bd9Sstevel@tonic-gate      */
170*7c478bd9Sstevel@tonic-gate 
171*7c478bd9Sstevel@tonic-gate     if ((server = (struct t_unitdata *) t_alloc(fd, T_UNITDATA, T_ADDR)) == 0) {
172*7c478bd9Sstevel@tonic-gate 	tcpd_warn("t_alloc: %s", tli_error());
173*7c478bd9Sstevel@tonic-gate 	return;
174*7c478bd9Sstevel@tonic-gate     }
175*7c478bd9Sstevel@tonic-gate     if (ioctl(fd, TI_GETMYNAME, &server->addr) < 0) {
176*7c478bd9Sstevel@tonic-gate 	tcpd_warn("TI_GETMYNAME: %m");
177*7c478bd9Sstevel@tonic-gate 	t_free((void *) server, T_UNITDATA);
178*7c478bd9Sstevel@tonic-gate 	return;
179*7c478bd9Sstevel@tonic-gate     }
180*7c478bd9Sstevel@tonic-gate     request->server->unit = server;
181*7c478bd9Sstevel@tonic-gate }
182*7c478bd9Sstevel@tonic-gate 
183*7c478bd9Sstevel@tonic-gate /* tli_transport - find out TLI transport type */
184*7c478bd9Sstevel@tonic-gate 
185*7c478bd9Sstevel@tonic-gate static struct netconfig *tli_transport(fd)
186*7c478bd9Sstevel@tonic-gate int     fd;
187*7c478bd9Sstevel@tonic-gate {
188*7c478bd9Sstevel@tonic-gate     struct stat from_client;
189*7c478bd9Sstevel@tonic-gate     struct stat from_config;
190*7c478bd9Sstevel@tonic-gate     void   *handlep;
191*7c478bd9Sstevel@tonic-gate     struct netconfig *config;
192*7c478bd9Sstevel@tonic-gate 
193*7c478bd9Sstevel@tonic-gate     /*
194*7c478bd9Sstevel@tonic-gate      * Assuming that the network device is a clone device, we must compare
195*7c478bd9Sstevel@tonic-gate      * the major device number of stdin to the minor device number of the
196*7c478bd9Sstevel@tonic-gate      * devices listed in the netconfig table.
197*7c478bd9Sstevel@tonic-gate      */
198*7c478bd9Sstevel@tonic-gate 
199*7c478bd9Sstevel@tonic-gate     if (fstat(fd, &from_client) != 0) {
200*7c478bd9Sstevel@tonic-gate 	tcpd_warn("fstat(fd %d): %m", fd);
201*7c478bd9Sstevel@tonic-gate 	return (0);
202*7c478bd9Sstevel@tonic-gate     }
203*7c478bd9Sstevel@tonic-gate     if ((handlep = setnetconfig()) == 0) {
204*7c478bd9Sstevel@tonic-gate 	tcpd_warn("setnetconfig: %m");
205*7c478bd9Sstevel@tonic-gate 	return (0);
206*7c478bd9Sstevel@tonic-gate     }
207*7c478bd9Sstevel@tonic-gate     while (config = getnetconfig(handlep)) {
208*7c478bd9Sstevel@tonic-gate 	if (stat(config->nc_device, &from_config) == 0) {
209*7c478bd9Sstevel@tonic-gate 	    if (minor(from_config.st_rdev) == major(from_client.st_rdev) ||
210*7c478bd9Sstevel@tonic-gate 		/* XXX: Solaris 8 no longer has clone devices for IP */
211*7c478bd9Sstevel@tonic-gate 		major(from_config.st_rdev) == major(from_client.st_rdev))
212*7c478bd9Sstevel@tonic-gate 		break;
213*7c478bd9Sstevel@tonic-gate 	}
214*7c478bd9Sstevel@tonic-gate     }
215*7c478bd9Sstevel@tonic-gate     if (config == 0) {
216*7c478bd9Sstevel@tonic-gate 	tcpd_warn("unable to identify transport protocol");
217*7c478bd9Sstevel@tonic-gate 	return (0);
218*7c478bd9Sstevel@tonic-gate     }
219*7c478bd9Sstevel@tonic-gate 
220*7c478bd9Sstevel@tonic-gate     /*
221*7c478bd9Sstevel@tonic-gate      * Something else may clobber our getnetconfig() result, so we'd better
222*7c478bd9Sstevel@tonic-gate      * acquire our private copy.
223*7c478bd9Sstevel@tonic-gate      */
224*7c478bd9Sstevel@tonic-gate 
225*7c478bd9Sstevel@tonic-gate     if ((config = getnetconfigent(config->nc_netid)) == 0) {
226*7c478bd9Sstevel@tonic-gate 	tcpd_warn("getnetconfigent(%s): %s", config->nc_netid, nc_sperror());
227*7c478bd9Sstevel@tonic-gate 	return (0);
228*7c478bd9Sstevel@tonic-gate     }
229*7c478bd9Sstevel@tonic-gate     return (config);
230*7c478bd9Sstevel@tonic-gate }
231*7c478bd9Sstevel@tonic-gate 
232*7c478bd9Sstevel@tonic-gate /* tli_hostaddr - map TLI transport address to printable address */
233*7c478bd9Sstevel@tonic-gate 
234*7c478bd9Sstevel@tonic-gate static void tli_hostaddr(host)
235*7c478bd9Sstevel@tonic-gate struct host_info *host;
236*7c478bd9Sstevel@tonic-gate {
237*7c478bd9Sstevel@tonic-gate     struct request_info *request = host->request;
238*7c478bd9Sstevel@tonic-gate     struct netconfig *config = request->config;
239*7c478bd9Sstevel@tonic-gate     struct t_unitdata *unit = host->unit;
240*7c478bd9Sstevel@tonic-gate     char   *uaddr;
241*7c478bd9Sstevel@tonic-gate 
242*7c478bd9Sstevel@tonic-gate     if (config != 0 && unit != 0
243*7c478bd9Sstevel@tonic-gate 	&& (uaddr = taddr2uaddr(config, &unit->addr)) != 0) {
244*7c478bd9Sstevel@tonic-gate 	STRN_CPY(host->addr, uaddr, sizeof(host->addr));
245*7c478bd9Sstevel@tonic-gate 	free(uaddr);
246*7c478bd9Sstevel@tonic-gate     }
247*7c478bd9Sstevel@tonic-gate }
248*7c478bd9Sstevel@tonic-gate 
249*7c478bd9Sstevel@tonic-gate /* tli_hostname - map TLI transport address to hostname */
250*7c478bd9Sstevel@tonic-gate 
251*7c478bd9Sstevel@tonic-gate static void tli_hostname(host)
252*7c478bd9Sstevel@tonic-gate struct host_info *host;
253*7c478bd9Sstevel@tonic-gate {
254*7c478bd9Sstevel@tonic-gate     struct request_info *request = host->request;
255*7c478bd9Sstevel@tonic-gate     struct netconfig *config = request->config;
256*7c478bd9Sstevel@tonic-gate     struct t_unitdata *unit = host->unit;
257*7c478bd9Sstevel@tonic-gate     struct nd_hostservlist *servlist;
258*7c478bd9Sstevel@tonic-gate 
259*7c478bd9Sstevel@tonic-gate     if (config != 0 && unit != 0
260*7c478bd9Sstevel@tonic-gate 	&& netdir_getbyaddr(config, &servlist, &unit->addr) == ND_OK) {
261*7c478bd9Sstevel@tonic-gate 
262*7c478bd9Sstevel@tonic-gate 	struct nd_hostserv *service = servlist->h_hostservs;
263*7c478bd9Sstevel@tonic-gate 	struct nd_addrlist *addr_list;
264*7c478bd9Sstevel@tonic-gate 	int     found = 0;
265*7c478bd9Sstevel@tonic-gate 
266*7c478bd9Sstevel@tonic-gate 	if (netdir_getbyname(config, service, &addr_list) != ND_OK) {
267*7c478bd9Sstevel@tonic-gate 
268*7c478bd9Sstevel@tonic-gate 	    /*
269*7c478bd9Sstevel@tonic-gate 	     * Unable to verify that the name matches the address. This may
270*7c478bd9Sstevel@tonic-gate 	     * be a transient problem or a botched name server setup. We
271*7c478bd9Sstevel@tonic-gate 	     * decide to play safe.
272*7c478bd9Sstevel@tonic-gate 	     */
273*7c478bd9Sstevel@tonic-gate 
274*7c478bd9Sstevel@tonic-gate 	    tcpd_warn("can't verify hostname: netdir_getbyname(%.*s) failed",
275*7c478bd9Sstevel@tonic-gate 		      STRING_LENGTH, service->h_host);
276*7c478bd9Sstevel@tonic-gate 
277*7c478bd9Sstevel@tonic-gate 	} else {
278*7c478bd9Sstevel@tonic-gate 
279*7c478bd9Sstevel@tonic-gate 	    /*
280*7c478bd9Sstevel@tonic-gate 	     * Look up the host address in the address list we just got. The
281*7c478bd9Sstevel@tonic-gate 	     * comparison is done on the textual representation, because the
282*7c478bd9Sstevel@tonic-gate 	     * transport address is an opaque structure that may have holes
283*7c478bd9Sstevel@tonic-gate 	     * with uninitialized garbage. This approach obviously loses when
284*7c478bd9Sstevel@tonic-gate 	     * the address does not have a textual representation.
285*7c478bd9Sstevel@tonic-gate 	     */
286*7c478bd9Sstevel@tonic-gate 
287*7c478bd9Sstevel@tonic-gate 	    char   *uaddr = eval_hostaddr(host);
288*7c478bd9Sstevel@tonic-gate 	    char   *ua;
289*7c478bd9Sstevel@tonic-gate 	    int     i;
290*7c478bd9Sstevel@tonic-gate 
291*7c478bd9Sstevel@tonic-gate 	    for (i = 0; found == 0 && i < addr_list->n_cnt; i++) {
292*7c478bd9Sstevel@tonic-gate 		if ((ua = taddr2uaddr(config, &(addr_list->n_addrs[i]))) != 0) {
293*7c478bd9Sstevel@tonic-gate 		    found = !strcmp(ua, uaddr);
294*7c478bd9Sstevel@tonic-gate 		    free(ua);
295*7c478bd9Sstevel@tonic-gate 		}
296*7c478bd9Sstevel@tonic-gate 	    }
297*7c478bd9Sstevel@tonic-gate 	    netdir_free((void *) addr_list, ND_ADDRLIST);
298*7c478bd9Sstevel@tonic-gate 
299*7c478bd9Sstevel@tonic-gate 	    /*
300*7c478bd9Sstevel@tonic-gate 	     * When the host name does not map to the initial address, assume
301*7c478bd9Sstevel@tonic-gate 	     * someone has compromised a name server. More likely someone
302*7c478bd9Sstevel@tonic-gate 	     * botched it, but that could be dangerous, too.
303*7c478bd9Sstevel@tonic-gate 	     */
304*7c478bd9Sstevel@tonic-gate 
305*7c478bd9Sstevel@tonic-gate 	    if (found == 0)
306*7c478bd9Sstevel@tonic-gate 		tcpd_warn("host name/address mismatch: %s != %.*s",
307*7c478bd9Sstevel@tonic-gate 			  host->addr, STRING_LENGTH, service->h_host);
308*7c478bd9Sstevel@tonic-gate 	}
309*7c478bd9Sstevel@tonic-gate 	STRN_CPY(host->name, found ? service->h_host : paranoid,
310*7c478bd9Sstevel@tonic-gate 		 sizeof(host->name));
311*7c478bd9Sstevel@tonic-gate 	netdir_free((void *) servlist, ND_HOSTSERVLIST);
312*7c478bd9Sstevel@tonic-gate     }
313*7c478bd9Sstevel@tonic-gate }
314*7c478bd9Sstevel@tonic-gate 
315*7c478bd9Sstevel@tonic-gate /* tli_error - convert tli error number to text */
316*7c478bd9Sstevel@tonic-gate 
317*7c478bd9Sstevel@tonic-gate static char *tli_error()
318*7c478bd9Sstevel@tonic-gate {
319*7c478bd9Sstevel@tonic-gate     static char buf[40];
320*7c478bd9Sstevel@tonic-gate 
321*7c478bd9Sstevel@tonic-gate     if (t_errno != TSYSERR) {
322*7c478bd9Sstevel@tonic-gate 	if (t_errno < 0 || t_errno >= t_nerr) {
323*7c478bd9Sstevel@tonic-gate 	    sprintf(buf, "Unknown TLI error %d", t_errno);
324*7c478bd9Sstevel@tonic-gate 	    return (buf);
325*7c478bd9Sstevel@tonic-gate 	} else {
326*7c478bd9Sstevel@tonic-gate 	    return (t_errlist[t_errno]);
327*7c478bd9Sstevel@tonic-gate 	}
328*7c478bd9Sstevel@tonic-gate     } else {
329*7c478bd9Sstevel@tonic-gate 	if (errno < 0 || errno >= sys_nerr) {
330*7c478bd9Sstevel@tonic-gate 	    sprintf(buf, "Unknown UNIX error %d", errno);
331*7c478bd9Sstevel@tonic-gate 	    return (buf);
332*7c478bd9Sstevel@tonic-gate 	} else {
333*7c478bd9Sstevel@tonic-gate 	    return (sys_errlist[errno]);
334*7c478bd9Sstevel@tonic-gate 	}
335*7c478bd9Sstevel@tonic-gate     }
336*7c478bd9Sstevel@tonic-gate }
337*7c478bd9Sstevel@tonic-gate 
338*7c478bd9Sstevel@tonic-gate /* tli_sink - absorb unreceived datagram */
339*7c478bd9Sstevel@tonic-gate 
340*7c478bd9Sstevel@tonic-gate static void tli_sink(fd)
341*7c478bd9Sstevel@tonic-gate int     fd;
342*7c478bd9Sstevel@tonic-gate {
343*7c478bd9Sstevel@tonic-gate     struct t_unitdata *unit;
344*7c478bd9Sstevel@tonic-gate     int     flags;
345*7c478bd9Sstevel@tonic-gate 
346*7c478bd9Sstevel@tonic-gate     /*
347*7c478bd9Sstevel@tonic-gate      * Something went wrong. Absorb the datagram to keep inetd from looping.
348*7c478bd9Sstevel@tonic-gate      * Allocate storage for address, control and data. If that fails, sleep
349*7c478bd9Sstevel@tonic-gate      * for a couple of seconds in an attempt to keep inetd from looping too
350*7c478bd9Sstevel@tonic-gate      * fast.
351*7c478bd9Sstevel@tonic-gate      */
352*7c478bd9Sstevel@tonic-gate 
353*7c478bd9Sstevel@tonic-gate     if ((unit = (struct t_unitdata *) t_alloc(fd, T_UNITDATA, T_ALL)) == 0) {
354*7c478bd9Sstevel@tonic-gate 	tcpd_warn("t_alloc: %s", tli_error());
355*7c478bd9Sstevel@tonic-gate 	sleep(5);
356*7c478bd9Sstevel@tonic-gate     } else {
357*7c478bd9Sstevel@tonic-gate 	(void) t_rcvudata(fd, unit, &flags);
358*7c478bd9Sstevel@tonic-gate 	t_free((void *) unit, T_UNITDATA);
359*7c478bd9Sstevel@tonic-gate     }
360*7c478bd9Sstevel@tonic-gate }
361*7c478bd9Sstevel@tonic-gate 
362*7c478bd9Sstevel@tonic-gate #endif /* TLI */
363