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