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