1:  /*
   2:   * Workarounds for known system software bugs. This module provides wrappers
   3:   * around library functions and system calls that are known to have problems
   4:   * on some systems. Most of these workarounds won't do any harm on regular
   5:   * systems.
   6:   *
   7:   * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
   8:   */
   9: 
  10: #ifndef lint
  11: char    sccsid[] = "@(#) workarounds.c 1.4 95/01/08 21:08:00";
  12: #endif
  13: 
  14: #include <sys/types.h>
  15: #include <sys/param.h>
  16: #include <sys/socket.h>
  17: #include <netinet/in.h>
  18: #include <arpa/inet.h>
  19: #include <netdb.h>
  20: #include <errno.h>
  21: #include <stdio.h>
  22: #include <syslog.h>
  23: 
  24: extern int errno;
  25: 
  26: #include "tcpd.h"
  27: 
  28:  /*
  29:   * Some AIX versions advertise a too small MAXHOSTNAMELEN value (32).
  30:   * Result: long hostnames would be truncated, and connections would be
  31:   * dropped because of host name verification failures. Adrian van Bloois
  32:   * (A.vanBloois@info.nic.surfnet.nl) figured out what was the problem.
  33:   */
  34: 
  35: #if (MAXHOSTNAMELEN < 64)
  36: #undef MAXHOSTNAMELEN
  37: #endif
  38: 
  39: /* In case not defined in <sys/param.h>. */
  40: 
  41: #ifndef MAXHOSTNAMELEN
  42: #define MAXHOSTNAMELEN  256             /* storage for host name */
  43: #endif
  44: 
  45:  /*
  46:   * Some DG/UX inet_addr() versions return a struct/union instead of a long.
  47:   * You have this problem when the compiler complains about illegal lvalues
  48:   * or something like that. The following code fixes this mutant behaviour.
  49:   * It should not be enabled on "normal" systems.
  50:   *
  51:   * Bug reported by ben@piglet.cr.usgs.gov (Rev. Ben A. Mesander).
  52:   */
  53: 
  54: #ifdef INET_ADDR_BUG
  55: 
  56: #undef inet_addr
  57: 
  58: long    fix_inet_addr(string)
  59: char   *string;
  60: {
  61:     return (inet_addr(string).s_addr);
  62: }
  63: 
  64: #endif /* INET_ADDR_BUG */
  65: 
  66:  /*
  67:   * With some System-V versions, the fgets() library function does not
  68:   * account for partial reads from e.g. sockets. The result is that fgets()
  69:   * gives up too soon, causing username lookups to fail. Problem first
  70:   * reported for IRIX 4.0.5, by Steve Kotsopoulos <steve@ecf.toronto.edu>.
  71:   * The following code works around the problem. It does no harm on "normal"
  72:   * systems.
  73:   */
  74: 
  75: #ifdef BROKEN_FGETS
  76: 
  77: #undef fgets
  78: 
  79: char   *fix_fgets(buf, len, fp)
  80: char   *buf;
  81: int     len;
  82: FILE   *fp;
  83: {
  84:     char   *cp = buf;
  85:     int     c;
  86: 
  87:     /*
  88:      * Copy until the buffer fills up, until EOF, or until a newline is
  89:      * found.
  90:      */
  91:     while (len > 1 && (c = getc(fp)) != EOF) {
  92:     len--;
  93:     *cp++ = c;
  94:     if (c == '\n')
  95:         break;
  96:     }
  97: 
  98:     /*
  99:      * Return 0 if nothing was read. This is correct even when a silly buffer
 100:      * length was specified.
 101:      */
 102:     if (cp > buf) {
 103:     *cp = 0;
 104:     return (buf);
 105:     } else {
 106:     return (0);
 107:     }
 108: }
 109: 
 110: #endif /* BROKEN_FGETS */
 111: 
 112:  /*
 113:   * With early SunOS 5 versions, recvfrom() does not completely fill in the
 114:   * source address structure when doing a non-destructive read. The following
 115:   * code works around the problem. It does no harm on "normal" systems.
 116:   */
 117: 
 118: #ifdef RECVFROM_BUG
 119: 
 120: #undef recvfrom
 121: 
 122: int     fix_recvfrom(sock, buf, buflen, flags, from, fromlen)
 123: int     sock;
 124: char   *buf;
 125: int     buflen;
 126: int     flags;
 127: struct sockaddr *from;
 128: int    *fromlen;
 129: {
 130:     int     ret;
 131: 
 132:     /* Assume that both ends of a socket belong to the same address family. */
 133: 
 134:     if ((ret = recvfrom(sock, buf, buflen, flags, from, fromlen)) >= 0) {
 135:     if (from->sa_family == 0) {
 136:         struct sockaddr my_addr;
 137:         int     my_addr_len = sizeof(my_addr);
 138: 
 139:         if (getsockname(0, &my_addr, &my_addr_len)) {
 140:         tcpd_warn("getsockname: %m");
 141:         } else {
 142:         from->sa_family = my_addr.sa_family;
 143:         }
 144:     }
 145:     }
 146:     return (ret);
 147: }
 148: 
 149: #endif /* RECVFROM_BUG */
 150: 
 151:  /*
 152:   * The Apollo SR10.3 and some SYSV4 getpeername(2) versions do not return an
 153:   * error in case of a datagram-oriented socket. Instead, they claim that all
 154:   * UDP requests come from address 0.0.0.0. The following code works around
 155:   * the problem. It does no harm on "normal" systems.
 156:   */
 157: 
 158: #ifdef GETPEERNAME_BUG
 159: 
 160: #undef getpeername
 161: 
 162: int     fix_getpeername(sock, sa, len)
 163: int     sock;
 164: struct sockaddr *sa;
 165: int    *len;
 166: {
 167:     int     ret;
 168:     struct sockaddr_in *sin = (struct sockaddr_in *) sa;
 169: 
 170:     if ((ret = getpeername(sock, sa, len)) >= 0
 171:     && sa->sa_family == AF_INET
 172:     && sin->sin_addr.s_addr == 0) {
 173:     errno = ENOTCONN;
 174:     return (-1);
 175:     } else {
 176:     return (ret);
 177:     }
 178: }
 179: 
 180: #endif /* GETPEERNAME_BUG */
 181: 
 182:  /*
 183:   * According to Karl Vogel (vogelke@c-17igp.wpafb.af.mil) some Pyramid
 184:   * versions have no yp_default_domain() function. We use getdomainname()
 185:   * instead.
 186:   */
 187: 
 188: #ifdef USE_GETDOMAIN
 189: 
 190: int     yp_get_default_domain(ptr)
 191: char  **ptr;
 192: {
 193:     static char mydomain[MAXHOSTNAMELEN];
 194: 
 195:     *ptr = mydomain;
 196:     return (getdomainname(mydomain, MAXHOSTNAMELEN));
 197: }
 198: 
 199: #endif /* USE_GETDOMAIN */
 200: 
 201: #ifndef INADDR_NONE
 202: #define INADDR_NONE 0xffffffff
 203: #endif
 204: 
 205:  /*
 206:   * Solaris 2.4 gethostbyname() has problems with multihomed hosts. When
 207:   * doing DNS through NIS, only one host address ends up in the address list.
 208:   * All other addresses end up in the hostname alias list, interspersed with
 209:   * copies of the official host name. This would wreak havoc with tcpd's
 210:   * hostname double checks. Below is a workaround that should do no harm when
 211:   * accidentally left in. A side effect of the workaround is that address
 212:   * list members are no longer properly aligned for structure access.
 213:   */
 214: 
 215: #ifdef SOLARIS_24_GETHOSTBYNAME_BUG
 216: 
 217: #undef gethostbyname
 218: 
 219: struct hostent *fix_gethostbyname(name)
 220: char   *name;
 221: {
 222:     struct hostent *hp;
 223:     struct in_addr addr;
 224:     char  **o_addr_list;
 225:     char  **o_aliases;
 226:     char  **n_addr_list;
 227:     int     broken_gethostbyname = 0;
 228: 
 229:     if ((hp = gethostbyname(name)) && !hp->h_addr_list[1] && hp->h_aliases[1]) {
 230:     for (o_aliases = n_addr_list = hp->h_aliases; *o_aliases; o_aliases++) {
 231:         if ((addr.s_addr = inet_addr(*o_aliases)) != INADDR_NONE) {
 232:         memcpy(*n_addr_list++, (char *) &addr, hp->h_length);
 233:         broken_gethostbyname = 1;
 234:         }
 235:     }
 236:     if (broken_gethostbyname) {
 237:         o_addr_list = hp->h_addr_list;
 238:         memcpy(*n_addr_list++, *o_addr_list, hp->h_length);
 239:         *n_addr_list = 0;
 240:         hp->h_addr_list = hp->h_aliases;
 241:         hp->h_aliases = o_addr_list + 1;
 242:     }
 243:     }
 244:     return (hp);
 245: }
 246: 
 247: #endif /* SOLARIS_24_GETHOSTBYNAME_BUG */

Defined functions

fix_fgets defined in line 79; used 1 times
fix_gethostbyname defined in line 219; used 1 times
fix_getpeername defined in line 162; used 1 times
fix_inet_addr defined in line 58; used 1 times
fix_recvfrom defined in line 122; used 1 times
yp_get_default_domain defined in line 190; used 1 times

Defined variables

sccsid defined in line 11; never used

Defined macros

INADDR_NONE defined in line 202; used 2 times
MAXHOSTNAMELEN defined in line 42; used 5 times
Last modified: 1995-01-08
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2814
Valid CSS Valid XHTML 1.0 Strict