1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License, Version 1.0 only
   6  * (the "License").  You may not use this file except in compliance
   7  * with the License.
   8  *
   9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  10  * or http://www.opensolaris.org/os/licensing.
  11  * See the License for the specific language governing permissions
  12  * and limitations under the License.
  13  *
  14  * When distributing Covered Code, include this CDDL HEADER in each
  15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  16  * If applicable, add the following below this CDDL HEADER, with the
  17  * fields enclosed by brackets "[]" replaced with your own identifying
  18  * information: Portions Copyright [yyyy] [name of copyright owner]
  19  *
  20  * CDDL HEADER END
  21  */
  22 /*
  23  * Copyright 2002-2003 Sun Microsystems, Inc.  All rights reserved.
  24  * Use is subject to license terms.
  25  */
  26 
  27 #pragma ident   "%Z%%M% %I%     %E% SMI"
  28 
  29 #include <sys/salib.h>
  30 #include <sys/types.h>
  31 #include <sys/socket.h>
  32 #include <sys/bootvfs.h>
  33 #include <netinet/in.h>
  34 
  35 /*
  36  * This structure defines the static area where gethostbyname()
  37  * stores the hostent data that it returns to the caller.
  38  */
  39 static struct {
  40         struct hostent  he;
  41         in_addr_t       *ha_list[2];
  42         in_addr_t       ha_addr;
  43         char            ha_name[MAXHOSTNAMELEN+1];
  44 } hostinfo;
  45 
  46 int h_errno;
  47 
  48 static in_addr_t inet_addr(const char *);
  49 static in_addr_t nam2addr(const char *);
  50 
  51 /* Very stripped-down gethostbyname() */
  52 struct hostent *
  53 gethostbyname(const char *nam)
  54 {
  55         bzero(&hostinfo, sizeof (hostinfo));
  56 
  57         hostinfo.ha_addr = inet_addr(nam);
  58         if ((int32_t)hostinfo.ha_addr == -1) {
  59                 if (get_default_fs() == NULL) {
  60                         h_errno = HOST_NOT_FOUND;
  61                         return (NULL);
  62                 }
  63                 hostinfo.ha_addr = nam2addr(nam);
  64                 if ((int32_t)hostinfo.ha_addr == -1) {
  65                         h_errno = HOST_NOT_FOUND;
  66                         return (NULL);
  67                 }
  68         }
  69 
  70         hostinfo.he.h_addrtype = AF_INET;
  71         (void) strlcpy(hostinfo.ha_name, nam, MAXHOSTNAMELEN);
  72         hostinfo.he.h_name = hostinfo.ha_name;
  73         hostinfo.he.h_length = sizeof (struct in_addr);
  74         hostinfo.ha_list[0] = &hostinfo.ha_addr;
  75         hostinfo.he.h_addr_list = (char **)&hostinfo.ha_list;
  76         return (&hostinfo.he);
  77 }
  78 
  79 #define SKIP_SPACE(_p)                                                  \
  80         {                                                               \
  81                 char    _c;                                             \
  82                 while ((_c = *(_p)) != '\0' && isspace(_c))             \
  83                         p++;                                            \
  84                 if (_c == '\0')                                         \
  85                         goto next_line;                                 \
  86         }
  87 
  88 #define SKIP_TOKEN(_p)                                                  \
  89         {                                                               \
  90                 char    _c;                                             \
  91                 while ((_c = *(_p)) != '\0' && !isspace(_c))            \
  92                         p++;                                            \
  93                 if (_c == '\0')                                         \
  94                         goto next_line;                                 \
  95         }
  96 
  97 #define TRIM_LINE(_l)                                                   \
  98         {                                                               \
  99                 char    _c, *_p = (_l);                                 \
 100                 while ((_c = *_p) != '#' && _c != '\n' && _c != '\0')   \
 101                         _p++;                                           \
 102                 *_p = '\0';                                             \
 103         }
 104 
 105 #define BUFSZ   1024
 106 #define HOSTDB  "/etc/inet/hosts"
 107 
 108 static in_addr_t
 109 nam2addr(const char *nam)
 110 {
 111         FILE *h;
 112         char c, buf[BUFSZ];
 113         char *l, *p, *s;
 114         boolean_t first_token;
 115 
 116         if ((h = fopen(HOSTDB, "r")) == NULL) {
 117                 return ((in_addr_t)-1);
 118         }
 119 
 120 next_line:
 121         if ((l = fgets(buf, BUFSZ, h)) == NULL) {
 122                 (void) fclose(h);
 123                 return ((in_addr_t)-1);
 124         }
 125         TRIM_LINE(l);
 126 
 127         p = l;
 128         first_token = B_TRUE;
 129 next_token:
 130         SKIP_SPACE(p);
 131 
 132         if (first_token) {
 133                 first_token = B_FALSE;
 134                 SKIP_TOKEN(p);
 135 
 136                 *p++ = '\0';
 137                 goto next_token;
 138         }
 139 
 140         s = (char *)nam;
 141         if (*p++ == *s++) {
 142                 while ((c = *s++) == *p && c != '\0')
 143                         p++;
 144                 if (c == '\0' && (isspace(*p) || *p == '\0'))
 145                         goto match;
 146         }
 147 
 148         SKIP_TOKEN(p);
 149         goto next_token;
 150 match:
 151         (void) fclose(h);
 152         return (inet_addr((const char *)l));
 153 }
 154 
 155 static in_addr_t
 156 inet_addr(const char *cp)
 157 {
 158         in_addr_t val;
 159         uint_t base, n;
 160         char c;
 161         in_addr_t parts[4], *pp = parts;
 162 
 163 again:
 164         /*
 165          * Collect number up to ``.''.
 166          * Values are specified as for C:
 167          * 0x=hex, 0=octal, other=decimal.
 168          */
 169         val = 0; base = 10;
 170         if (*cp == '0') {
 171                 if (*++cp == 'x' || *cp == 'X')
 172                         base = 16, cp++;
 173                 else
 174                         base = 8;
 175         }
 176 
 177         while ((c = *cp) != 0) {
 178                 if (isdigit(c)) {
 179                         if ((c - '0') >= base)
 180                                 break;
 181                         val = (val * base) + (c - '0');
 182                         cp++;
 183                         continue;
 184                 }
 185                 if (base == 16 && isxdigit(c)) {
 186                         val = (val << 4) + (c + 10 - (islower(c) ? 'a' : 'A'));
 187                         cp++;
 188                         continue;
 189                 }
 190                 break;
 191         }
 192         if (*cp == '.') {
 193                 /*
 194                  * Internet format:
 195                  *      a.b.c.d
 196                  *      a.b.c   (with c treated as 16-bits)
 197                  *      a.b     (with b treated as 24 bits)
 198                  */
 199                 if (pp >= parts + 4)
 200                         return ((in_addr_t)-1);
 201                 *pp++ = val, cp++;
 202                 goto again;
 203         }
 204         /*
 205          * Check for trailing characters.
 206          */
 207         if (*cp && !isspace(*cp))
 208                 return ((in_addr_t)-1);
 209         *pp++ = val;
 210         /*
 211          * Concoct the address according to
 212          * the number of parts specified.
 213          */
 214         n = pp - parts;
 215         switch (n) {
 216 
 217         case 1:                  /* a -- 32 bits */
 218                 val = parts[0];
 219                 break;
 220 
 221         case 2:                  /* a.b -- 8.24 bits */
 222                 val = (parts[0] << 24) | (parts[1] & 0xffffff);
 223                 break;
 224 
 225         case 3:                  /* a.b.c -- 8.8.16 bits */
 226                 val = (parts[0] << 24) | ((parts[1] & 0xff) << 16) |
 227                         (parts[2] & 0xffff);
 228                 break;
 229 
 230         case 4:                  /* a.b.c.d -- 8.8.8.8 bits */
 231                 val = (parts[0] << 24) | ((parts[1] & 0xff) << 16) |
 232                         ((parts[2] & 0xff) << 8) | (parts[3] & 0xff);
 233                 break;
 234 
 235         default:
 236                 return ((in_addr_t)-1);
 237         }
 238         val = htonl(val);
 239         return (val);
 240 }