xref: /onnv-gate/usr/src/cmd/tcpd/tli-sequent.c (revision 0:68f95e015346)
1*0Sstevel@tonic-gate  /*
2*0Sstevel@tonic-gate   * Warning - this relies heavily on the TLI implementation in PTX 2.X and will
3*0Sstevel@tonic-gate   * probably not work under PTX 4.
4*0Sstevel@tonic-gate   *
5*0Sstevel@tonic-gate   * Author: Tim Wright, Sequent Computer Systems Ltd., UK.
6*0Sstevel@tonic-gate   *
7*0Sstevel@tonic-gate   * Modified slightly to conform to the new internal interfaces - Wietse
8*0Sstevel@tonic-gate   */
9*0Sstevel@tonic-gate 
10*0Sstevel@tonic-gate #ifndef lint
11*0Sstevel@tonic-gate static char sccsid[] = "@(#) tli-sequent.c 1.1 94/12/28 17:42:51";
12*0Sstevel@tonic-gate #endif
13*0Sstevel@tonic-gate 
14*0Sstevel@tonic-gate #ifdef TLI_SEQUENT
15*0Sstevel@tonic-gate 
16*0Sstevel@tonic-gate /* System libraries. */
17*0Sstevel@tonic-gate 
18*0Sstevel@tonic-gate #include <sys/types.h>
19*0Sstevel@tonic-gate #include <sys/param.h>
20*0Sstevel@tonic-gate #include <sys/stat.h>
21*0Sstevel@tonic-gate #include <sys/tiuser.h>
22*0Sstevel@tonic-gate #include <sys/stream.h>
23*0Sstevel@tonic-gate #include <sys/stropts.h>
24*0Sstevel@tonic-gate #include <sys/tihdr.h>
25*0Sstevel@tonic-gate #include <sys/timod.h>
26*0Sstevel@tonic-gate #include <sys/socket.h>
27*0Sstevel@tonic-gate #include <netinet/in.h>
28*0Sstevel@tonic-gate #include <stdio.h>
29*0Sstevel@tonic-gate #include <syslog.h>
30*0Sstevel@tonic-gate #include <errno.h>
31*0Sstevel@tonic-gate #include <string.h>
32*0Sstevel@tonic-gate 
33*0Sstevel@tonic-gate extern int errno;
34*0Sstevel@tonic-gate extern char *sys_errlist[];
35*0Sstevel@tonic-gate extern int sys_nerr;
36*0Sstevel@tonic-gate extern int t_errno;
37*0Sstevel@tonic-gate extern char *t_errlist[];
38*0Sstevel@tonic-gate extern int t_nerr;
39*0Sstevel@tonic-gate 
40*0Sstevel@tonic-gate /* Local stuff. */
41*0Sstevel@tonic-gate 
42*0Sstevel@tonic-gate #include "tcpd.h"
43*0Sstevel@tonic-gate #include "tli-sequent.h"
44*0Sstevel@tonic-gate 
45*0Sstevel@tonic-gate /* Forward declarations. */
46*0Sstevel@tonic-gate 
47*0Sstevel@tonic-gate static char *tli_error();
48*0Sstevel@tonic-gate static void tli_sink();
49*0Sstevel@tonic-gate 
50*0Sstevel@tonic-gate /* tli_host - determine endpoint info */
51*0Sstevel@tonic-gate 
tli_host(request)52*0Sstevel@tonic-gate int     tli_host(request)
53*0Sstevel@tonic-gate struct request_info *request;
54*0Sstevel@tonic-gate {
55*0Sstevel@tonic-gate     static struct sockaddr_in client;
56*0Sstevel@tonic-gate     static struct sockaddr_in server;
57*0Sstevel@tonic-gate     struct _ti_user *tli_state_ptr;
58*0Sstevel@tonic-gate     union T_primitives *TSI_prim_ptr;
59*0Sstevel@tonic-gate     struct strpeek peek;
60*0Sstevel@tonic-gate     int     len;
61*0Sstevel@tonic-gate 
62*0Sstevel@tonic-gate     /*
63*0Sstevel@tonic-gate      * Use DNS and socket routines for name and address conversions.
64*0Sstevel@tonic-gate      */
65*0Sstevel@tonic-gate 
66*0Sstevel@tonic-gate     sock_methods(request);
67*0Sstevel@tonic-gate 
68*0Sstevel@tonic-gate     /*
69*0Sstevel@tonic-gate      * Find out the client address using getpeerinaddr(). This call is the
70*0Sstevel@tonic-gate      * TLI equivalent to getpeername() under Dynix/ptx.
71*0Sstevel@tonic-gate      */
72*0Sstevel@tonic-gate 
73*0Sstevel@tonic-gate     len = sizeof(client);
74*0Sstevel@tonic-gate     t_sync(request->fd);
75*0Sstevel@tonic-gate     if (getpeerinaddr(request->fd, &client, len) < 0) {
76*0Sstevel@tonic-gate 	tcpd_warn("can't get client address: %s", tli_error());
77*0Sstevel@tonic-gate 	return;
78*0Sstevel@tonic-gate     }
79*0Sstevel@tonic-gate     request->client->sin = &client;
80*0Sstevel@tonic-gate 
81*0Sstevel@tonic-gate     /* Call TLI utility routine to get information on endpoint */
82*0Sstevel@tonic-gate     if ((tli_state_ptr = _t_checkfd(request->fd)) == NULL)
83*0Sstevel@tonic-gate 	return;
84*0Sstevel@tonic-gate 
85*0Sstevel@tonic-gate     if (tli_state_ptr->ti_servtype == T_CLTS) {
86*0Sstevel@tonic-gate 	/* UDP - may need to get address the hard way */
87*0Sstevel@tonic-gate 	if (client.sin_addr.s_addr == 0) {
88*0Sstevel@tonic-gate 	    /* The UDP endpoint is not connected so we didn't get the */
89*0Sstevel@tonic-gate 	    /* remote address - get it the hard way ! */
90*0Sstevel@tonic-gate 
91*0Sstevel@tonic-gate 	    /* Look at the control part of the top message on the stream */
92*0Sstevel@tonic-gate 	    /* we don't want to remove it from the stream so we use I_PEEK */
93*0Sstevel@tonic-gate 	    peek.ctlbuf.maxlen = tli_state_ptr->ti_ctlsize;
94*0Sstevel@tonic-gate 	    peek.ctlbuf.len = 0;
95*0Sstevel@tonic-gate 	    peek.ctlbuf.buf = tli_state_ptr->ti_ctlbuf;
96*0Sstevel@tonic-gate 	    /* Don't even look at the data */
97*0Sstevel@tonic-gate 	    peek.databuf.maxlen = -1;
98*0Sstevel@tonic-gate 	    peek.databuf.len = 0;
99*0Sstevel@tonic-gate 	    peek.databuf.buf = 0;
100*0Sstevel@tonic-gate 	    peek.flags = 0;
101*0Sstevel@tonic-gate 
102*0Sstevel@tonic-gate 	    switch (ioctl(request->fd, I_PEEK, &peek)) {
103*0Sstevel@tonic-gate 	    case -1:
104*0Sstevel@tonic-gate 		tcpd_warn("can't peek at endpoint: %s", tli_error());
105*0Sstevel@tonic-gate 		return;
106*0Sstevel@tonic-gate 	    case 0:
107*0Sstevel@tonic-gate 		/* No control part - we're hosed */
108*0Sstevel@tonic-gate 		tcpd_warn("can't get UDP info: %s", tli_error());
109*0Sstevel@tonic-gate 		return;
110*0Sstevel@tonic-gate 	    default:
111*0Sstevel@tonic-gate 		/* FALL THROUGH */
112*0Sstevel@tonic-gate 		;
113*0Sstevel@tonic-gate 	    }
114*0Sstevel@tonic-gate 	    /* Can we even check the PRIM_type ? */
115*0Sstevel@tonic-gate 	    if (peek.ctlbuf.len < sizeof(long)) {
116*0Sstevel@tonic-gate 		tcpd_warn("UDP control info garbage");
117*0Sstevel@tonic-gate 		return;
118*0Sstevel@tonic-gate 	    }
119*0Sstevel@tonic-gate 	    TSI_prim_ptr = (union T_primitives *) peek.ctlbuf.buf;
120*0Sstevel@tonic-gate 	    if (TSI_prim_ptr->type != T_UNITDATA_IND) {
121*0Sstevel@tonic-gate 		tcpd_warn("wrong type for UDP control info");
122*0Sstevel@tonic-gate 		return;
123*0Sstevel@tonic-gate 	    }
124*0Sstevel@tonic-gate 	    /* Validate returned unitdata indication packet */
125*0Sstevel@tonic-gate 	    if ((peek.ctlbuf.len < sizeof(struct T_unitdata_ind)) ||
126*0Sstevel@tonic-gate 		((TSI_prim_ptr->unitdata_ind.OPT_length != 0) &&
127*0Sstevel@tonic-gate 		 (peek.ctlbuf.len <
128*0Sstevel@tonic-gate 		  TSI_prim_ptr->unitdata_ind.OPT_length +
129*0Sstevel@tonic-gate 		  TSI_prim_ptr->unitdata_ind.OPT_offset))) {
130*0Sstevel@tonic-gate 		tcpd_warn("UDP control info garbaged");
131*0Sstevel@tonic-gate 		return;
132*0Sstevel@tonic-gate 	    }
133*0Sstevel@tonic-gate 	    /* Extract the address */
134*0Sstevel@tonic-gate 	    memcpy(&client,
135*0Sstevel@tonic-gate 		   peek.ctlbuf.buf + TSI_prim_ptr->unitdata_ind.SRC_offset,
136*0Sstevel@tonic-gate 		   TSI_prim_ptr->unitdata_ind.SRC_length);
137*0Sstevel@tonic-gate 	}
138*0Sstevel@tonic-gate 	request->sink = tli_sink;
139*0Sstevel@tonic-gate     }
140*0Sstevel@tonic-gate     if (getmyinaddr(request->fd, &server, len) < 0)
141*0Sstevel@tonic-gate 	tcpd_warn("can't get local address: %s", tli_error());
142*0Sstevel@tonic-gate     else
143*0Sstevel@tonic-gate 	request->server->sin = &server;
144*0Sstevel@tonic-gate }
145*0Sstevel@tonic-gate 
146*0Sstevel@tonic-gate /* tli_error - convert tli error number to text */
147*0Sstevel@tonic-gate 
tli_error()148*0Sstevel@tonic-gate static char *tli_error()
149*0Sstevel@tonic-gate {
150*0Sstevel@tonic-gate     static char buf[40];
151*0Sstevel@tonic-gate 
152*0Sstevel@tonic-gate     if (t_errno != TSYSERR) {
153*0Sstevel@tonic-gate 	if (t_errno < 0 || t_errno >= t_nerr) {
154*0Sstevel@tonic-gate 	    sprintf(buf, "Unknown TLI error %d", t_errno);
155*0Sstevel@tonic-gate 	    return (buf);
156*0Sstevel@tonic-gate 	} else {
157*0Sstevel@tonic-gate 	    return (t_errlist[t_errno]);
158*0Sstevel@tonic-gate 	}
159*0Sstevel@tonic-gate     } else {
160*0Sstevel@tonic-gate 	if (errno < 0 || errno >= sys_nerr) {
161*0Sstevel@tonic-gate 	    sprintf(buf, "Unknown UNIX error %d", errno);
162*0Sstevel@tonic-gate 	    return (buf);
163*0Sstevel@tonic-gate 	} else {
164*0Sstevel@tonic-gate 	    return (sys_errlist[errno]);
165*0Sstevel@tonic-gate 	}
166*0Sstevel@tonic-gate     }
167*0Sstevel@tonic-gate }
168*0Sstevel@tonic-gate 
169*0Sstevel@tonic-gate /* tli_sink - absorb unreceived datagram */
170*0Sstevel@tonic-gate 
tli_sink(fd)171*0Sstevel@tonic-gate static void tli_sink(fd)
172*0Sstevel@tonic-gate int     fd;
173*0Sstevel@tonic-gate {
174*0Sstevel@tonic-gate     struct t_unitdata *unit;
175*0Sstevel@tonic-gate     int     flags;
176*0Sstevel@tonic-gate 
177*0Sstevel@tonic-gate     /*
178*0Sstevel@tonic-gate      * Something went wrong. Absorb the datagram to keep inetd from looping.
179*0Sstevel@tonic-gate      * Allocate storage for address, control and data. If that fails, sleep
180*0Sstevel@tonic-gate      * for a couple of seconds in an attempt to keep inetd from looping too
181*0Sstevel@tonic-gate      * fast.
182*0Sstevel@tonic-gate      */
183*0Sstevel@tonic-gate 
184*0Sstevel@tonic-gate     if ((unit = (struct t_unitdata *) t_alloc(fd, T_UNITDATA, T_ALL)) == 0) {
185*0Sstevel@tonic-gate 	tcpd_warn("t_alloc: %s", tli_error());
186*0Sstevel@tonic-gate 	sleep(5);
187*0Sstevel@tonic-gate     } else {
188*0Sstevel@tonic-gate 	(void) t_rcvudata(fd, unit, &flags);
189*0Sstevel@tonic-gate 	t_free((void *) unit, T_UNITDATA);
190*0Sstevel@tonic-gate     }
191*0Sstevel@tonic-gate }
192*0Sstevel@tonic-gate 
193*0Sstevel@tonic-gate #endif /* TLI_SEQUENT */
194