1 #include "syshdrs.h"
2 
3 #if (defined(WIN32) || defined(_WINDOWS)) && !defined(__CYGWIN__)
4 #define _CRT_SECURE_NO_WARNINGS 1
5 #endif
6 
7 #ifdef PRAGMA_HDRSTOP
8 #	pragma hdrstop
9 #endif
10 
11 #ifndef INADDR_ANY
12 #	define INADDR_ANY              ((unsigned long int) 0x00000000)
13 #endif
14 
15 #ifndef INADDR_NONE
16 #	define INADDR_NONE             ((unsigned long int) 0xffffffff)
17 #endif
18 
19 /* Linux libc 5.3.x has a bug that causes isalnum() to not work! */
20 #define ISALNUM(c) ( (((c) >= 'A') && ((c) <= 'Z')) || (((c) >= 'a') && ((c) <= 'z')) || (((c) >= '0') && ((c) <= '9')) )
21 
22 #if (defined(WIN32) || defined(_WINDOWS)) && !defined(__CYGWIN__)
23 #	pragma warning(disable : 4711)	// warning: function 'ServiceNameToPortNumber' selected for automatic inline expansion
24 #endif
25 unsigned int
ServiceNameToPortNumber(const char * const s,const int proto)26 ServiceNameToPortNumber(const char *const s, const int proto)
27 {
28 	char str[64];
29 	char *cp;
30 #if defined(HAVE_GETSERVBYNAME_R) && (defined(AIX) || defined(TRU64UNIX) || defined(DIGITAL_UNIX))
31 	struct servent *sp;
32 #elif defined(HAVE_GETSERVBYNAME_R) && (defined(LINUX) || defined(SOLARIS) || defined(IRIX) || defined(BSDOS))
33 	struct servent se, *sp;
34 	char spbuf[256];
35 #else
36 	struct servent *sp;
37 #endif
38 	strncpy(str, s, sizeof(str) - 1);
39 	str[sizeof(str) - 1] = '\0';
40 	cp = str;
41 	if (isdigit((int) *cp)) {
42 		while (isdigit((int) *cp))
43 			cp++;
44 		*cp = '\0';
45 		return ((unsigned int) atoi(str));
46 	}
47 	for (;; cp++) {
48 		if ((*cp == '\0')
49 			|| ((!ISALNUM(*cp)) && (*cp != '-') && (*cp != '_')))
50 				break;
51 	}
52 	*cp = '\0';
53 
54 	sp = NULL;
55 #if defined(HAVE_GETSERVBYNAME_R) && (defined(SOLARIS) || defined(IRIX) || defined(BSDOS))
56 	if ((sp == NULL) && ((proto == 0) || (proto == 't'))) {
57 		memset(spbuf, 0, sizeof(spbuf));
58 		sp = getservbyname_r(str, "tcp", &se, spbuf, sizeof(spbuf));
59 	}
60 	if ((sp == NULL) && ((proto == 0) || (proto == 'u'))) {
61 		memset(spbuf, 0, sizeof(spbuf));
62 		sp = getservbyname_r(str, "udp", &se, spbuf, sizeof(spbuf));
63 	}
64 #elif defined(HAVE_GETSERVBYNAME_R) && defined(LINUX)
65 	if ((sp == NULL) && ((proto == 0) || (proto == 't'))) {
66 		memset(spbuf, 0, sizeof(spbuf));
67 		if (getservbyname_r(str, "tcp", &se, spbuf, sizeof(spbuf), &sp) != 0)
68 			sp = NULL;
69 	}
70 	if ((sp == NULL) && ((proto == 0) || (proto == 'u'))) {
71 		memset(spbuf, 0, sizeof(spbuf));
72 		if (getservbyname_r(str, "udp", &se, spbuf, sizeof(spbuf), &sp) != 0)
73 			sp = NULL;
74 	}
75 #elif defined(HAVE_GETSERVBYNAME_R) && defined(AIX)
76 	{
77 		struct servent_data sed;
78 		if ((sp == NULL) && ((proto == 0) || (proto == 't'))) {
79 			memset(&sed, 0, sizeof(sed));
80 			if (getservbyname_r(str, "tcp", sp, &sed) != 0)
81 				sp = NULL;
82 		}
83 		if ((sp == NULL) && ((proto == 0) || (proto == 'u'))) {
84 			memset(&sed, 0, sizeof(sed));
85 			if (getservbyname_r(str, "udp", sp, &sed) != 0)
86 				sp = NULL;
87 		}
88 	}
89 #else
90 	/* Note: getservbyname is already threadsafe on: HP-UX, Tru64 */
91 	if ((sp == NULL) && ((proto == 0) || (proto == 't'))) {
92 		sp = getservbyname(str, "tcp");
93 	}
94 	if ((sp == NULL) && ((proto == 0) || (proto == 'u'))) {
95 		sp = getservbyname(str, "udp");
96 	}
97 #endif
98 
99 	if (sp != NULL) {
100 		return ((unsigned int) ntohs((unsigned short) sp->s_port));
101 	}
102 	return (0);	/* error */
103 }	/* ServiceNameToPortNumber */
104 
105 
106 
107 
108 int
ServicePortNumberToName(unsigned short port,char * const dst,const size_t dsize,const int proto)109 ServicePortNumberToName(unsigned short port, char *const dst, const size_t dsize, const int proto)
110 {
111 #if defined(HAVE_GETSERVBYNAME_R) && (defined(AIX) || defined(TRU64UNIX) || defined(DIGITAL_UNIX))
112 	struct servent *sp;
113 #elif defined(HAVE_GETSERVBYNAME_R) && (defined(LINUX) || defined(SOLARIS) || defined(IRIX) || defined(BSDOS))
114 	struct servent se, *sp;
115 	char spbuf[256];
116 #else
117 	struct servent *sp;
118 #endif
119 
120 	sp = NULL;
121 #if defined(HAVE_GETSERVBYPORT_R) && (defined(SOLARIS) || defined(IRIX) || defined(BSDOS))
122 	if ((sp == NULL) && ((proto == 0) || (proto == 't'))) {
123 		memset(spbuf, 0, sizeof(spbuf));
124 		sp = getservbyport_r((int) htons(port), "tcp", &se, spbuf, sizeof(spbuf));
125 	}
126 	if ((sp == NULL) && ((proto == 0) || (proto == 'u'))) {
127 		memset(spbuf, 0, sizeof(spbuf));
128 		sp = getservbyport_r((int) htons(port), "udp", &se, spbuf, sizeof(spbuf));
129 	}
130 #elif defined(HAVE_GETSERVBYPORT_R) && defined(LINUX)
131 	if ((sp == NULL) && ((proto == 0) || (proto == 't'))) {
132 		memset(spbuf, 0, sizeof(spbuf));
133 		if (getservbyport_r((int) htons(port), "tcp", &se, spbuf, sizeof(spbuf), &sp) != 0)
134 			sp = NULL;
135 	}
136 	if ((sp == NULL) && ((proto == 0) || (proto == 'u'))) {
137 		memset(spbuf, 0, sizeof(spbuf));
138 		if (getservbyport_r((int) htons(port), "udp", &se, spbuf, sizeof(spbuf), &sp) != 0)
139 			sp = NULL;
140 	}
141 #elif defined(HAVE_GETSERVBYPORT_R) && defined(AIX)
142 	{
143 		struct servent_data sed;
144 		if ((sp == NULL) && ((proto == 0) || (proto == 't'))) {
145 			memset(&sed, 0, sizeof(sed));
146 			if (getservbyport_r((int) htons(port), "tcp", sp, &sed) != 0)
147 				sp = NULL;
148 		}
149 		if ((sp == NULL) && ((proto == 0) || (proto == 'u'))) {
150 			memset(&sed, 0, sizeof(sed));
151 			if (getservbyport_r((int) htons(port), "udp", sp, &sed) != 0)
152 				sp = NULL;
153 		}
154 	}
155 #else
156 	/* Note: getservbyport is already threadsafe on: HP-UX, Tru64 */
157 	if ((sp == NULL) && ((proto == 0) || (proto == 't'))) {
158 		sp = getservbyport((int) htons(port), "tcp");
159 	}
160 	if ((sp == NULL) && ((proto == 0) || (proto == 'u'))) {
161 		sp = getservbyport((int) htons(port), "ucp");
162 	}
163 #endif
164 
165 	if (sp != NULL) {
166 		strncpy(dst, sp->s_name, dsize);
167 		dst[dsize - 1] = '\0';
168 		return (1);
169 	}
170 
171 #ifdef HAVE_SNPRINTF
172 	snprintf(dst, dsize, "%u", (unsigned int) port);
173 #else
174 	sprintf(dst, "%u", (unsigned int) port);
175 #endif
176 
177 	return (0);	/* error */
178 }	/* ServicePortNumberToName */
179 
180 
181 
182 
183 void
InetNtoA(char * dst,struct in_addr * ia,unsigned int siz)184 InetNtoA(char *dst, struct in_addr *ia, unsigned int siz)
185 {
186 #if defined(HAVE_INET_NTOP) && !defined(MACOSX)
187 	/* Mostly to workaround bug in IRIX 6.5's inet_ntoa */
188 	/* For OS X, don't use inet_ntop yet since it was just introduced
189 	 * for 10.2.
190 	 */
191 	memset(dst, 0, siz);
192 	(void) inet_ntop(AF_INET, ia, dst, siz - 1);
193 #else
194 	char *cp;
195 	memset(dst, 0, (size_t) siz);
196 	cp = inet_ntoa(*ia);
197 	if ((cp != (char *) 0) && (cp != (char *) -1) && (cp[0] != '\0')) {
198 		(void) strncpy(dst, cp, (size_t) siz - 1);
199 	}
200 #endif
201 }	/* InetNtoA */
202 
203 
204 
205 
206 int
AddrStrToAddr(const char * const s,struct sockaddr_in * const sa,const int defaultport)207 AddrStrToAddr(const char * const s, struct sockaddr_in * const sa, const int defaultport)
208 {
209 	char portstr[128];
210 	unsigned int ipnum;
211 	unsigned int port;
212 	struct hostent *hp;
213 	char *hostcp, *atsign, *colon, *cp, *p2;
214 
215 	memset(sa, 0, sizeof(struct sockaddr_in));
216 	strncpy(portstr, s, sizeof(portstr));
217 	portstr[sizeof(portstr) - 1] = '\0';
218 
219 	if ((colon = strchr(portstr, ':')) != NULL) {
220 		/* Does it look like a URL?  http://host ? */
221 		if ((colon[1] == '/') && (colon[2] == '/')) {
222 			*colon = '\0';
223 			port = 0;
224 			hostcp = colon + 3;
225 			for (cp = hostcp; *cp != '\0'; cp++) {
226 				if ((!ISALNUM(*cp)) && (*cp != '.')) {
227 					/* http://host:port */
228 					if ((*cp == ':') && (isdigit((int) cp[1]))) {
229 						*cp++ = '\0';
230 						p2 = cp;
231 						while (isdigit((int) *cp))
232 							cp++;
233 						*cp = '\0';
234 						port = (unsigned int) atoi(p2);
235 					}
236 					*cp = '\0';
237 					break;
238 				}
239 			}
240 			if (port == 0)
241 				port = ServiceNameToPortNumber(portstr, 0);
242 		} else {
243 			/* Look for host.name.domain:port */
244 			*colon = '\0';
245 			hostcp = portstr;
246 			port = (unsigned int) atoi(colon + 1);
247 		}
248 	} else if ((atsign = strchr(portstr, '@')) != NULL) {
249 		/* Look for port@host.name.domain */
250 		*atsign = '\0';
251 		hostcp = atsign + 1;
252 		port = (unsigned int) atoi(portstr);
253 	} else if (defaultport > 0) {
254 		/* Have just host.name.domain, use that w/ default port. */
255 		port = (unsigned int) defaultport;
256 		hostcp = portstr;
257 	} else {
258 		/* If defaultport <= 0, they must supply a port number
259 		 * in the host/port string.
260 		 */
261 		errno = EADDRNOTAVAIL;
262 		return (kAddrStrToAddrMiscErr);
263 	}
264 
265 	sa->sin_port = htons((short) port);
266 
267 	ipnum = inet_addr(hostcp);
268 	if (ipnum != INADDR_NONE) {
269 		sa->sin_family = AF_INET;
270 		sa->sin_addr.s_addr = ipnum;
271 	} else {
272 #ifdef DNSSEC_LOCAL_VALIDATION
273 		val_status_t val_status;
274 		errno = 0;
275 		hp = val_gethostbyname(NULL,hostcp,&val_status);
276 		if ((hp != NULL) && (!val_istrusted(val_status)))
277 			hp = NULL;
278 #else
279 		errno = 0;
280 		hp = gethostbyname(hostcp);
281 #endif
282 		if (hp == NULL) {
283 			if (errno == 0)
284 				errno = ENOENT;
285 			return (kAddrStrToAddrBadHost);
286 		}
287 		sa->sin_family = (sa_family_t) hp->h_addrtype;
288 		memcpy(&sa->sin_addr.s_addr, hp->h_addr_list[0],
289 			(size_t) hp->h_length);
290 	}
291 	return (0);
292 }	/* AddrStrToAddr */
293 
294 
295 
296 
297 char *
AddrToAddrStr(char * const dst,size_t dsize,struct sockaddr_in * const saddrp,int dns,const char * fmt)298 AddrToAddrStr(char *const dst, size_t dsize, struct sockaddr_in * const saddrp, int dns, const char *fmt)
299 {
300 	char addrName[128];
301 	const char *addrNamePtr;
302 	struct hostent *hp;
303 	char str[128];
304 	char s_name[64];
305 	char *dlim, *dp;
306 	const char *cp;
307 
308 	if (dsize == 0)
309 		return NULL;
310 	memset(dst, 0, dsize);
311 
312 	addrNamePtr = NULL;
313 	if (dns == 0) {
314 		InetNtoA(addrName, &saddrp->sin_addr, sizeof(addrName));
315 		addrNamePtr = addrName;
316 	} else {
317 #ifdef DNSSEC_LOCAL_VALIDATION
318 		val_status_t val_status;
319 		hp = val_gethostbyaddr(NULL, (const char*)&saddrp->sin_addr, sizeof(struct in_addr), AF_INET, &val_status);
320 		if ((hp != NULL) && (!val_istrusted(val_status)))
321 			hp = NULL;
322 #else
323 		hp = gethostbyaddr((gethost_addrptr_t) &saddrp->sin_addr, sizeof(struct in_addr), AF_INET);
324 #endif
325 		if ((hp != NULL) && (hp->h_name != NULL) && (hp->h_name[0] != '\0')) {
326 			addrNamePtr = hp->h_name;
327 		} else {
328 			InetNtoA(addrName, &saddrp->sin_addr, sizeof(addrName));
329 			addrNamePtr = addrName;
330 		}
331 	}
332 	if (fmt == NULL)
333 		fmt = "%h:%p";
334 	for (dp = dst, dlim = dp + dsize - 1; ; fmt++) {
335 		if (*fmt == '\0') {
336 			break;	/* done */
337 		} else if (*fmt == '%') {
338 			fmt++;
339 			if (*fmt == '%') {
340 				if (dp < dlim)
341 					*dp++ = '%';
342 			} else if (*fmt == 'p') {
343 				sprintf(str, "%u", (unsigned int) ntohs(saddrp->sin_port));
344 				for (cp = str; *cp != '\0'; cp++)
345 					if (dp < dlim)
346 						*dp++ = *cp;
347 				*dp = '\0';
348 			} else if (*fmt == 'h') {
349 				if (addrNamePtr != NULL) {
350 					cp = addrNamePtr;
351 				} else {
352 					cp = "unknown";
353 				}
354 				for ( ; *cp != '\0'; cp++)
355 					if (dp < dlim)
356 						*dp++ = *cp;
357 				*dp = '\0';
358 			} else if (*fmt == 's') {
359 				cp = s_name;
360 				(void) ServicePortNumberToName(ntohs(saddrp->sin_port), s_name, sizeof(s_name), 0);
361 				for ( ; *cp != '\0'; cp++)
362 					if (dp < dlim)
363 						*dp++ = *cp;
364 				/* endservent(); */
365 				*dp = '\0';
366 			} else if ((*fmt == 't') || (*fmt == 'u')) {
367 				cp = s_name;
368 				(void) ServicePortNumberToName(ntohs(saddrp->sin_port), s_name, sizeof(s_name), (int) *fmt);
369 				for ( ; *cp != '\0'; cp++)
370 					if (dp < dlim)
371 						*dp++ = *cp;
372 				/* endservent(); */
373 				*dp = '\0';
374 			} else if (*fmt == '\0') {
375 				break;
376 			} else {
377 				if (dp < dlim)
378 					*dp++ = *fmt;
379 			}
380 		} else if (dp < dlim) {
381 			*dp++ = *fmt;
382 		}
383 	}
384 	*dp = '\0';
385 	return (dst);
386 }	/* AddrToAddrStr */
387 
388 
389 
390 
391 char *
AddrStrToIPStr(char * const dst,size_t dsize,const char * const src,const int defaultport)392 AddrStrToIPStr(char *const dst, size_t dsize, const char *const src, const int defaultport)
393 {
394 	int rc;
395 	struct sockaddr_in sa;
396 
397 	if (dsize == 0)
398 		return NULL;
399 	memset(dst, 0, dsize);
400 
401 	rc = AddrStrToAddr(src, &sa, (defaultport <= 0) ? 21 : defaultport);
402 	if (rc < 0)
403 		return (NULL);
404 
405 	AddrToAddrStr(dst, dsize, &sa, 0, (defaultport <= 0) ? "%h" : "%h:%p");
406 	return (dst);
407 }	/* AddrStrToIPStr */
408