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