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

Defined functions

tli_cleanup defined in line 97; used 3 times
tli_endpoints defined in line 110; used 2 times
tli_error defined in line 294; used 5 times
tli_hostaddr defined in line 211; used 2 times
tli_hostname defined in line 228; used 2 times
tli_sink defined in line 311; used 2 times
tli_transport defined in line 164; used 2 times

Defined variables

sccsid defined in line 18; never used
Last modified: 1996-03-24
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2755
Valid CSS Valid XHTML 1.0 Strict