backport to buster
[hcoop/debian/openafs.git] / src / util / hostparse.c
CommitLineData
805e021f
CE
1/*
2 * Copyright 2000, International Business Machines Corporation and others.
3 * All Rights Reserved.
4 *
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
8 */
9
10/*
11 * ALL RIGHTS RESERVED
12 */
13
14#include <afsconfig.h>
15#include <afs/param.h>
16
17#include <roken.h>
18
19#ifdef AFS_NT40_ENV
20#include <direct.h>
21#else
22#include <ctype.h>
23#endif
24
25#include "afsutil.h"
26
27/* also parse a.b.c.d addresses */
28struct hostent *
29hostutil_GetHostByName(char *ahost)
30{
31 int tc;
32 static struct hostent thostent;
33 static char *addrp[2];
34 static char addr[4];
35 char *ptr = ahost;
36 afs_uint32 tval, numeric = 0;
37 int dots = 0;
38
39 tc = *ahost; /* look at the first char */
40 if (tc >= '0' && tc <= '9') {
41 numeric = 1;
42 while ((tc = *ptr++)) {
43 if (tc == '.') {
44 if (dots >= 3) {
45 numeric = 0;
46 break;
47 }
48 dots++;
49 } else if (tc > '9' || tc < '0') {
50 numeric = 0;
51 break;
52 }
53 }
54 }
55 if (numeric) {
56 /* decimal address, return fake hostent with only hostaddr field good */
57 tval = 0;
58 dots = 0;
59 memset(addr, 0, sizeof(addr));
60 while ((tc = *ahost++)) {
61 if (tc == '.') {
62 if (dots >= 3)
63 return NULL; /* too many dots */
64 addr[dots++] = tval;
65 tval = 0;
66 } else if (tc > '9' || tc < '0')
67 return NULL;
68 else {
69 tval *= 10;
70 tval += tc - '0';
71 }
72 }
73 addr[dots] = tval;
74#ifdef h_addr
75 /* 4.3 system */
76 addrp[0] = addr;
77 addrp[1] = NULL;
78 thostent.h_addr_list = &addrp[0];
79#else /* h_addr */
80 /* 4.2 and older systems */
81 thostent.h_addr = addr;
82#endif /* h_addr */
83 return &thostent;
84 } else {
85#ifdef AFS_NT40_ENV
86 if (afs_winsockInit() < 0)
87 return NULL;
88#endif
89 return gethostbyname(ahost);
90 }
91}
92
93/* Translate an internet address into a nice printable string. The
94 * variable addr is in network byte order.
95 */
96char *
97hostutil_GetNameByINet(afs_uint32 addr)
98{
99 struct hostent *th;
100 static char tbuffer[256];
101
102#ifdef AFS_NT40_ENV
103 if (afs_winsockInit() < 0)
104 return NULL;
105#endif
106 th = gethostbyaddr((void *)&addr, sizeof(addr), AF_INET);
107 if (th && strlen(th->h_name) < sizeof(tbuffer)) {
108 strlcpy(tbuffer, th->h_name, sizeof(tbuffer));
109 } else {
110 addr = ntohl(addr);
111 sprintf(tbuffer, "%d.%d.%d.%d", (int)((addr >> 24) & 0xff),
112 (int)((addr >> 16) & 0xff), (int)((addr >> 8) & 0xff),
113 (int)(addr & 0xff));
114 }
115
116 return tbuffer;
117}
118
119/* the parameter is a pointer to a buffer containing a string of
120** bytes of the form
121** w.x.y.z # machineName
122** returns the network interface in network byte order
123*/
124
125#define MAXBYTELEN 32
126afs_uint32
127extractAddr(char *line, int maxSize)
128{
129 char byte1[MAXBYTELEN], byte2[MAXBYTELEN];
130 char byte3[MAXBYTELEN], byte4[MAXBYTELEN];
131 int i = 0;
132 char *endPtr;
133 afs_uint32 val1, val2, val3, val4;
134 afs_uint32 val = 0;
135
136 /* skip empty spaces */
137 while (isspace(*line) && maxSize) {
138 line++;
139 maxSize--;
140 }
141
142 /* skip empty lines */
143 if (!maxSize || !*line)
144 return AFS_IPINVALIDIGNORE;
145
146 while ((*line != '.') && maxSize) { /* extract first byte */
147 if (!isdigit(*line))
148 return AFS_IPINVALID;
149 if (i >= MAXBYTELEN-1)
150 return AFS_IPINVALID; /* no space */
151 byte1[i++] = *line++;
152 maxSize--;
153 }
154 if (!maxSize)
155 return AFS_IPINVALID;
156 byte1[i] = 0;
157
158 i = 0, line++;
159 while ((*line != '.') && maxSize) { /* extract second byte */
160 if (!isdigit(*line))
161 return AFS_IPINVALID;
162 if (i >= MAXBYTELEN-1)
163 return AFS_IPINVALID; /* no space */
164 byte2[i++] = *line++;
165 maxSize--;
166 }
167 if (!maxSize)
168 return AFS_IPINVALID;
169 byte2[i] = 0;
170
171 i = 0, line++;
172 while ((*line != '.') && maxSize) {
173 if (!isdigit(*line))
174 return AFS_IPINVALID;
175 if (i >= MAXBYTELEN-1)
176 return AFS_IPINVALID; /* no space */
177 byte3[i++] = *line++;
178 maxSize--;
179 }
180 if (!maxSize)
181 return AFS_IPINVALID;
182 byte3[i] = 0;
183
184 i = 0, line++;
185 while (*line && !isspace(*line) && maxSize) {
186 if (!isdigit(*line))
187 return AFS_IPINVALID;
188 if (i >= MAXBYTELEN-1)
189 return AFS_IPINVALID; /* no space */
190 byte4[i++] = *line++;
191 maxSize--;
192 }
193 if (!maxSize)
194 return AFS_IPINVALID;
195 byte4[i] = 0;
196
197 errno = 0;
198 val1 = strtol(byte1, &endPtr, 10);
199 if ((val1 == 0) && (errno != 0 || byte1 == endPtr))
200 return AFS_IPINVALID;
201
202 errno = 0;
203 val2 = strtol(byte2, &endPtr, 10);
204 if ((val2 == 0) && (errno != 0 || byte2 == endPtr)) /* no conversion */
205 return AFS_IPINVALID;
206
207 errno = 0;
208 val3 = strtol(byte3, &endPtr, 10);
209 if ((val3 == 0) && (errno != 0 || byte3 == endPtr)) /* no conversion */
210 return AFS_IPINVALID;
211
212 errno = 0;
213 val4 = strtol(byte4, &endPtr, 10);
214 if ((val4 == 0) && (errno != 0 || byte4 == endPtr)) /* no conversion */
215 return AFS_IPINVALID;
216
217 val = (val1 << 24) | (val2 << 16) | (val3 << 8) | val4;
218 val = htonl(val);
219 return val;
220}
221
222/* same as inet_ntoa, but to a non-static buffer, must be freed by called */
223char *
224afs_inet_ntoa_r(afs_uint32 addr, char *buf)
225{
226 int temp;
227
228 temp = ntohl(addr);
229 sprintf(buf, "%d.%d.%d.%d", (temp >> 24) & 0xff, (temp >> 16) & 0xff,
230 (temp >> 8) & 0xff, (temp) & 0xff);
231 return buf;
232}
233
234/*
235 * gettmpdir() -- Returns pointer to global temporary directory string.
236 * Always succeeds. Never attempt to deallocate directory string.
237 */
238
239char *
240gettmpdir(void)
241{
242 char *tmpdirp = NULL;
243
244#ifdef AFS_NT40_ENV
245 static char *saveTmpDir = NULL;
246
247 if (saveTmpDir == NULL) {
248 /* initialize global temporary directory string */
249 char *dirp = malloc(MAX_PATH+1);
250 int freeDirp = 1;
251
252 if (dirp != NULL) {
253 DWORD pathLen = GetTempPath(MAX_PATH+1, dirp);
254
255 if (pathLen == 0 || pathLen > MAX_PATH) {
256 /* can't get tmp path; get cur work dir */
257 pathLen = GetCurrentDirectory(MAX_PATH, dirp);
258 if (pathLen == 0 || pathLen > MAX_PATH) {
259 free(dirp);
260 dirp = NULL;
261 }
262 }
263
264 if (dirp != NULL) {
265 /* Have a valid dir path; check that actually exists. */
266 DWORD fileAttr = GetFileAttributes(dirp);
267
268 if ((fileAttr == 0xFFFFFFFF)
269 || ((fileAttr & FILE_ATTRIBUTE_DIRECTORY) == 0)) {
270 free(dirp);
271 dirp = NULL;
272 }
273 }
274 }
275
276 if (dirp != NULL) {
277 FilepathNormalize(dirp);
278 } else {
279 /* most likely TMP or TEMP env vars specify a non-existent dir */
280 dirp = "/";
281 freeDirp = 0;
282 }
283
284 /* atomically initialize shared buffer pointer IF still null */
285 if (InterlockedCompareExchangePointer(&saveTmpDir, dirp, NULL) != NULL) {
286 /* shared buffer pointer already initialized by another thread */
287 if (freeDirp)
288 free(dirp);
289 }
290 }
291 /* if (!saveTmpDir) */
292 tmpdirp = saveTmpDir;
293#else
294 tmpdirp = "/tmp";
295#endif /* AFS_NT40_ENV */
296
297 return tmpdirp;
298}