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