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 }