# 2.11BSD#431 - /usr/src/libexec/tcpd/workarounds.c

##### Functions

    fix_fgets         X
    fix_gethostbyname X
    fix_getpeername   X
    fix_inet_addr     X
    fix_recvfrom      X
    yp_get_default_domainX

##### Variables

    sccsid            X

##### Macros

    INADDR_NONE       X
    MAXHOSTNAMELEN    X

       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

- in /usr/src/libexec/tcpd/tcpd.h line 192

fix_gethostbyname defined in line 219; used 1 times

- in /usr/src/libexec/tcpd/tcpd.h line 207

fix_getpeername defined in line 162; used 1 times

- in /usr/src/libexec/tcpd/tcpd.h line 202

fix_inet_addr defined in line 58; used 1 times

- in /usr/src/libexec/tcpd/tcpd.h line 187

fix_recvfrom defined in line 122; used 1 times

- in /usr/src/libexec/tcpd/tcpd.h line 197

yp_get_default_domain defined in line 190; used 1 times

- in /usr/src/libexec/tcpd/hosts_access.c line 255

#### Defined variables

sccsid defined in line 11; never used

#### Defined macros

INADDR_NONE defined in line 202; used 2 times

- in line 201, 231

MAXHOSTNAMELEN defined in line 42; used 5 times

- in line 35-41(3), 193-196(2)

Last modified: 1995-01-08 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 830 |