1 /* Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache License, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "apr_arch_networkio.h"
18 #include "apr_strings.h"
19 #include "apr.h"
20 #include "apr_lib.h"
21 #include "apr_strings.h"
22 #include "apr_private.h"
23
24 #if APR_HAVE_STDLIB_H
25 #include <stdlib.h>
26 #endif
27
28 #define APR_WANT_STRFUNC
29 #include "apr_want.h"
30
31 struct apr_ipsubnet_t {
32 int family;
33 #if APR_HAVE_IPV6
34 apr_uint32_t sub[4]; /* big enough for IPv4 and IPv6 addresses */
35 apr_uint32_t mask[4];
36 #else
37 apr_uint32_t sub[1];
38 apr_uint32_t mask[1];
39 #endif
40 };
41
42 #if !defined(NETWARE) && !defined(WIN32)
43 #ifdef HAVE_SET_H_ERRNO
44 #define SET_H_ERRNO(newval) set_h_errno(newval)
45 #else
46 #define SET_H_ERRNO(newval) h_errno = (newval)
47 #endif
48 #else
49 #define SET_H_ERRNO(newval)
50 #endif
51
52 #if APR_HAS_THREADS && !defined(GETHOSTBYNAME_IS_THREAD_SAFE) && \
53 defined(HAVE_GETHOSTBYNAME_R)
54 /* This is the maximum size that may be returned from the reentrant
55 * gethostbyname_r function. If the system tries to use more, it
56 * should return ERANGE.
57 */
58 #define GETHOSTBYNAME_BUFLEN 512
59 #endif
60
61 #ifdef _AIX
62 /* Some levels of AIX getaddrinfo() don't like servname = "0", so
63 * set servname to "1" when port is 0 and fix it up later.
64 */
65 #define AIX_SERVNAME_HACK 1
66 #else
67 #define AIX_SERVNAME_HACK 0
68 #endif
69
70 #ifdef _WIN32_WCE
71 /* XXX: BS solution. Need an HAVE_GETSERVBYNAME and actually
72 * do something here, to provide the obvious proto mappings.
73 */
getservbyname(const char * name,const char * proto)74 static void *getservbyname(const char *name, const char *proto)
75 {
76 return NULL;
77 }
78 #endif
79
get_local_addr(apr_socket_t * sock)80 static apr_status_t get_local_addr(apr_socket_t *sock)
81 {
82 sock->local_addr->salen = sizeof(sock->local_addr->sa);
83 if (getsockname(sock->socketdes, (struct sockaddr *)&sock->local_addr->sa,
84 &sock->local_addr->salen) < 0) {
85 return apr_get_netos_error();
86 }
87 else {
88 sock->local_port_unknown = sock->local_interface_unknown = 0;
89 /* XXX assumes sin_port and sin6_port at same offset */
90 sock->local_addr->port = ntohs(sock->local_addr->sa.sin.sin_port);
91 return APR_SUCCESS;
92 }
93 }
94
get_remote_addr(apr_socket_t * sock)95 static apr_status_t get_remote_addr(apr_socket_t *sock)
96 {
97 sock->remote_addr->salen = sizeof(sock->remote_addr->sa);
98 if (getpeername(sock->socketdes, (struct sockaddr *)&sock->remote_addr->sa,
99 &sock->remote_addr->salen) < 0) {
100 return apr_get_netos_error();
101 }
102 else {
103 sock->remote_addr_unknown = 0;
104 /* XXX assumes sin_port and sin6_port at same offset */
105 sock->remote_addr->port = ntohs(sock->remote_addr->sa.sin.sin_port);
106 return APR_SUCCESS;
107 }
108 }
109
apr_sockaddr_ip_getbuf(char * buf,apr_size_t buflen,apr_sockaddr_t * sockaddr)110 APR_DECLARE(apr_status_t) apr_sockaddr_ip_getbuf(char *buf, apr_size_t buflen,
111 apr_sockaddr_t *sockaddr)
112 {
113 if (!apr_inet_ntop(sockaddr->family, sockaddr->ipaddr_ptr, buf, buflen)) {
114 return APR_ENOSPC;
115 }
116
117 #if APR_HAVE_IPV6
118 if (sockaddr->family == AF_INET6
119 && IN6_IS_ADDR_V4MAPPED((struct in6_addr *)sockaddr->ipaddr_ptr)
120 && buflen > strlen("::ffff:")) {
121 /* This is an IPv4-mapped IPv6 address; drop the leading
122 * part of the address string so we're left with the familiar
123 * IPv4 format.
124 */
125 memmove(buf, buf + strlen("::ffff:"),
126 strlen(buf + strlen("::ffff:"))+1);
127 }
128 #endif
129 /* ensure NUL termination if the buffer is too short */
130 buf[buflen-1] = '\0';
131 return APR_SUCCESS;
132 }
133
apr_sockaddr_ip_get(char ** addr,apr_sockaddr_t * sockaddr)134 APR_DECLARE(apr_status_t) apr_sockaddr_ip_get(char **addr,
135 apr_sockaddr_t *sockaddr)
136 {
137 *addr = apr_palloc(sockaddr->pool, sockaddr->addr_str_len);
138 return apr_sockaddr_ip_getbuf(*addr, sockaddr->addr_str_len, sockaddr);
139 }
140
apr_sockaddr_vars_set(apr_sockaddr_t * addr,int family,apr_port_t port)141 void apr_sockaddr_vars_set(apr_sockaddr_t *addr, int family, apr_port_t port)
142 {
143 addr->family = family;
144 addr->sa.sin.sin_family = family;
145 if (port) {
146 /* XXX IPv6: assumes sin_port and sin6_port at same offset */
147 addr->sa.sin.sin_port = htons(port);
148 addr->port = port;
149 }
150 #if AIX_SERVNAME_HACK
151 else {
152 addr->sa.sin.sin_port = htons(port);
153 }
154 #endif
155
156 if (family == APR_INET) {
157 addr->salen = sizeof(struct sockaddr_in);
158 addr->addr_str_len = 16;
159 addr->ipaddr_ptr = &(addr->sa.sin.sin_addr);
160 addr->ipaddr_len = sizeof(struct in_addr);
161 }
162 #if APR_HAVE_IPV6
163 else if (family == APR_INET6) {
164 addr->salen = sizeof(struct sockaddr_in6);
165 addr->addr_str_len = 46;
166 addr->ipaddr_ptr = &(addr->sa.sin6.sin6_addr);
167 addr->ipaddr_len = sizeof(struct in6_addr);
168 }
169 #endif
170 }
171
apr_socket_addr_get(apr_sockaddr_t ** sa,apr_interface_e which,apr_socket_t * sock)172 APR_DECLARE(apr_status_t) apr_socket_addr_get(apr_sockaddr_t **sa,
173 apr_interface_e which,
174 apr_socket_t *sock)
175 {
176 if (which == APR_LOCAL) {
177 if (sock->local_interface_unknown || sock->local_port_unknown) {
178 apr_status_t rv = get_local_addr(sock);
179
180 if (rv != APR_SUCCESS) {
181 return rv;
182 }
183 }
184 *sa = sock->local_addr;
185 }
186 else if (which == APR_REMOTE) {
187 if (sock->remote_addr_unknown) {
188 apr_status_t rv = get_remote_addr(sock);
189
190 if (rv != APR_SUCCESS) {
191 return rv;
192 }
193 }
194 *sa = sock->remote_addr;
195 }
196 else {
197 *sa = NULL;
198 return APR_EINVAL;
199 }
200 return APR_SUCCESS;
201 }
202
apr_parse_addr_port(char ** addr,char ** scope_id,apr_port_t * port,const char * str,apr_pool_t * p)203 APR_DECLARE(apr_status_t) apr_parse_addr_port(char **addr,
204 char **scope_id,
205 apr_port_t *port,
206 const char *str,
207 apr_pool_t *p)
208 {
209 const char *ch, *lastchar;
210 int big_port;
211 apr_size_t addrlen;
212
213 *addr = NULL; /* assume not specified */
214 *scope_id = NULL; /* assume not specified */
215 *port = 0; /* assume not specified */
216
217 /* First handle the optional port number. That may be all that
218 * is specified in the string.
219 */
220 ch = lastchar = str + strlen(str) - 1;
221 while (ch >= str && apr_isdigit(*ch)) {
222 --ch;
223 }
224
225 if (ch < str) { /* Entire string is the port. */
226 big_port = atoi(str);
227 if (big_port < 1 || big_port > 65535) {
228 return APR_EINVAL;
229 }
230 *port = big_port;
231 return APR_SUCCESS;
232 }
233
234 if (*ch == ':' && ch < lastchar) { /* host and port number specified */
235 if (ch == str) { /* string starts with ':' -- bad */
236 return APR_EINVAL;
237 }
238 big_port = atoi(ch + 1);
239 if (big_port < 1 || big_port > 65535) {
240 return APR_EINVAL;
241 }
242 *port = big_port;
243 lastchar = ch - 1;
244 }
245
246 /* now handle the hostname */
247 addrlen = lastchar - str + 1;
248
249 /* XXX we don't really have to require APR_HAVE_IPV6 for this;
250 * just pass char[] for ipaddr (so we don't depend on struct in6_addr)
251 * and always define APR_INET6
252 */
253 #if APR_HAVE_IPV6
254 if (*str == '[') {
255 const char *end_bracket = memchr(str, ']', addrlen);
256 struct in6_addr ipaddr;
257 const char *scope_delim;
258
259 if (!end_bracket || end_bracket != lastchar) {
260 *port = 0;
261 return APR_EINVAL;
262 }
263
264 /* handle scope id; this is the only context where it is allowed */
265 scope_delim = memchr(str, '%', addrlen);
266 if (scope_delim) {
267 if (scope_delim == end_bracket - 1) { /* '%' without scope id */
268 *port = 0;
269 return APR_EINVAL;
270 }
271 addrlen = scope_delim - str - 1;
272 *scope_id = apr_palloc(p, end_bracket - scope_delim);
273 memcpy(*scope_id, scope_delim + 1, end_bracket - scope_delim - 1);
274 (*scope_id)[end_bracket - scope_delim - 1] = '\0';
275 }
276 else {
277 addrlen = addrlen - 2; /* minus 2 for '[' and ']' */
278 }
279
280 *addr = apr_palloc(p, addrlen + 1);
281 memcpy(*addr,
282 str + 1,
283 addrlen);
284 (*addr)[addrlen] = '\0';
285 if (apr_inet_pton(AF_INET6, *addr, &ipaddr) != 1) {
286 *addr = NULL;
287 *scope_id = NULL;
288 *port = 0;
289 return APR_EINVAL;
290 }
291 }
292 else
293 #endif
294 {
295 /* XXX If '%' is not a valid char in a DNS name, we *could* check
296 * for bogus scope ids first.
297 */
298 *addr = apr_palloc(p, addrlen + 1);
299 memcpy(*addr, str, addrlen);
300 (*addr)[addrlen] = '\0';
301 }
302 return APR_SUCCESS;
303 }
304
305 #if defined(HAVE_GETADDRINFO)
306
call_resolver(apr_sockaddr_t ** sa,const char * hostname,apr_int32_t family,apr_port_t port,apr_int32_t flags,apr_pool_t * p)307 static apr_status_t call_resolver(apr_sockaddr_t **sa,
308 const char *hostname, apr_int32_t family,
309 apr_port_t port, apr_int32_t flags,
310 apr_pool_t *p)
311 {
312 struct addrinfo hints, *ai, *ai_list;
313 apr_sockaddr_t *prev_sa;
314 int error;
315 char *servname = NULL;
316
317 memset(&hints, 0, sizeof(hints));
318 hints.ai_family = family;
319 hints.ai_socktype = SOCK_STREAM;
320 #ifdef HAVE_GAI_ADDRCONFIG
321 if (family == APR_UNSPEC) {
322 /* By default, only look up addresses using address types for
323 * which a local interface is configured, i.e. no IPv6 if no
324 * IPv6 interfaces configured. */
325 hints.ai_flags = AI_ADDRCONFIG;
326 }
327 #endif
328
329 #ifdef __MVS__
330 /* z/OS will not return IPv4 address under AF_UNSPEC if any IPv6 results
331 * are returned, w/o AI_ALL.
332 */
333 if (family == APR_UNSPEC) {
334 hints.ai_flags |= AI_ALL;
335 }
336 #endif
337
338 if(hostname == NULL) {
339 #ifdef AI_PASSIVE
340 /* If hostname is NULL, assume we are trying to bind to all
341 * interfaces. */
342 hints.ai_flags |= AI_PASSIVE;
343 #endif
344 /* getaddrinfo according to RFC 2553 must have either hostname
345 * or servname non-NULL.
346 */
347 #ifdef OSF1
348 /* The Tru64 5.0 getaddrinfo() can only resolve services given
349 * by the name listed in /etc/services; a numeric or unknown
350 * servname gets an EAI_SERVICE error. So just resolve the
351 * appropriate anyaddr and fill in the port later. */
352 hostname = family == AF_INET6 ? "::" : "0.0.0.0";
353 servname = NULL;
354 #ifdef AI_NUMERICHOST
355 hints.ai_flags |= AI_NUMERICHOST;
356 #endif
357 #else
358 #if AIX_SERVNAME_HACK
359 if (!port) {
360 servname = "1";
361 }
362 else
363 #endif /* AIX_SERVNAME_HACK */
364 servname = apr_itoa(p, port);
365 #endif /* OSF1 */
366 }
367 error = getaddrinfo(hostname, servname, &hints, &ai_list);
368 #ifdef HAVE_GAI_ADDRCONFIG
369 /*
370 * Using AI_ADDRCONFIG involves some unfortunate guesswork because it
371 * does not consider loopback addresses when trying to determine if
372 * IPv4 or IPv6 is configured on a system (see RFC 3493).
373 * This is a problem if one actually wants to listen on or connect to
374 * the loopback address of a protocol family that is not otherwise
375 * configured on the system. See PR 52709.
376 * To work around some of the problems, retry without AI_ADDRCONFIG
377 * in case of EAI_ADDRFAMILY.
378 * XXX: apr_sockaddr_info_get() should really accept a flag to determine
379 * XXX: if AI_ADDRCONFIG's guesswork is wanted and if the address is
380 * XXX: to be used for listen() or connect().
381 *
382 * In case of EAI_BADFLAGS, AI_ADDRCONFIG is not supported.
383 */
384 if ((family == APR_UNSPEC) && (error == EAI_BADFLAGS
385 #ifdef EAI_ADDRFAMILY
386 || error == EAI_ADDRFAMILY
387 #endif
388 )) {
389 hints.ai_flags &= ~AI_ADDRCONFIG;
390 error = getaddrinfo(hostname, servname, &hints, &ai_list);
391 }
392 #endif
393 if (error) {
394 #if defined(WIN32)
395 return apr_get_netos_error();
396 #else
397 if (error == EAI_SYSTEM) {
398 return errno ? errno : APR_EGENERAL;
399 }
400 else
401 {
402 /* issues with representing this with APR's error scheme:
403 * glibc uses negative values for these numbers, perhaps so
404 * they don't conflict with h_errno values... Tru64 uses
405 * positive values which conflict with h_errno values
406 */
407 #if defined(NEGATIVE_EAI)
408 error = -error;
409 #endif
410 return error + APR_OS_START_EAIERR;
411 }
412 #endif /* WIN32 */
413 }
414
415 prev_sa = NULL;
416 ai = ai_list;
417 while (ai) { /* while more addresses to report */
418 apr_sockaddr_t *new_sa;
419
420 /* Ignore anything bogus: getaddrinfo in some old versions of
421 * glibc will return AF_UNIX entries for APR_UNSPEC+AI_PASSIVE
422 * lookups. */
423 #if APR_HAVE_IPV6
424 if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6) {
425 #else
426 if (ai->ai_family != AF_INET) {
427 #endif
428 ai = ai->ai_next;
429 continue;
430 }
431
432 new_sa = apr_pcalloc(p, sizeof(apr_sockaddr_t));
433
434 new_sa->pool = p;
435 memcpy(&new_sa->sa, ai->ai_addr, ai->ai_addrlen);
436 apr_sockaddr_vars_set(new_sa, ai->ai_family, port);
437
438 if (!prev_sa) { /* first element in new list */
439 if (hostname) {
440 new_sa->hostname = apr_pstrdup(p, hostname);
441 }
442 *sa = new_sa;
443 }
444 else {
445 new_sa->hostname = prev_sa->hostname;
446 prev_sa->next = new_sa;
447 }
448
449 prev_sa = new_sa;
450 ai = ai->ai_next;
451 }
452 freeaddrinfo(ai_list);
453
454 if (prev_sa == NULL) {
455 /*
456 * getaddrinfo returned only useless entries and *sa is still empty.
457 * This should be treated as an error.
458 */
459 return APR_EGENERAL;
460 }
461
462 return APR_SUCCESS;
463 }
464
465 static apr_status_t find_addresses(apr_sockaddr_t **sa,
466 const char *hostname, apr_int32_t family,
467 apr_port_t port, apr_int32_t flags,
468 apr_pool_t *p)
469 {
470 if (flags & APR_IPV4_ADDR_OK) {
471 apr_status_t error = call_resolver(sa, hostname, AF_INET, port, flags, p);
472
473 #if APR_HAVE_IPV6
474 if (error) {
475 family = AF_INET6; /* try again */
476 }
477 else
478 #endif
479 return error;
480 }
481 #if APR_HAVE_IPV6
482 else if (flags & APR_IPV6_ADDR_OK) {
483 apr_status_t error = call_resolver(sa, hostname, AF_INET6, port, flags, p);
484
485 if (error) {
486 family = AF_INET; /* try again */
487 }
488 else {
489 return APR_SUCCESS;
490 }
491 }
492 #endif
493
494 return call_resolver(sa, hostname, family, port, flags, p);
495 }
496
497 #else /* end of HAVE_GETADDRINFO code */
498
499 static apr_status_t find_addresses(apr_sockaddr_t **sa,
500 const char *hostname, apr_int32_t family,
501 apr_port_t port, apr_int32_t flags,
502 apr_pool_t *p)
503 {
504 struct hostent *hp;
505 apr_sockaddr_t *prev_sa;
506 int curaddr;
507 #if APR_HAS_THREADS && !defined(GETHOSTBYNAME_IS_THREAD_SAFE) && \
508 defined(HAVE_GETHOSTBYNAME_R) && !defined(BEOS)
509 #ifdef GETHOSTBYNAME_R_HOSTENT_DATA
510 struct hostent_data hd;
511 #else
512 /* If you see ERANGE, that means GETHOSBYNAME_BUFLEN needs to be
513 * bumped. */
514 char tmp[GETHOSTBYNAME_BUFLEN];
515 #endif
516 int hosterror;
517 #endif
518 struct hostent hs;
519 struct in_addr ipaddr;
520 char *addr_list[2];
521 const char *orig_hostname = hostname;
522
523 if (hostname == NULL) {
524 /* if we are given a NULL hostname, assume '0.0.0.0' */
525 hostname = "0.0.0.0";
526 }
527
528 if (*hostname >= '0' && *hostname <= '9' &&
529 strspn(hostname, "0123456789.") == strlen(hostname)) {
530
531 ipaddr.s_addr = inet_addr(hostname);
532 addr_list[0] = (char *)&ipaddr;
533 addr_list[1] = NULL; /* just one IP in list */
534 hs.h_addr_list = (char **)addr_list;
535 hp = &hs;
536 }
537 else {
538 #if APR_HAS_THREADS && !defined(GETHOSTBYNAME_IS_THREAD_SAFE) && \
539 defined(HAVE_GETHOSTBYNAME_R) && !defined(BEOS)
540 #if defined(GETHOSTBYNAME_R_HOSTENT_DATA)
541 /* AIX, HP/UX, D/UX et alia */
542 gethostbyname_r(hostname, &hs, &hd);
543 hp = &hs;
544 #else
545 #if defined(GETHOSTBYNAME_R_GLIBC2)
546 /* Linux glibc2+ */
547 gethostbyname_r(hostname, &hs, tmp, GETHOSTBYNAME_BUFLEN - 1,
548 &hp, &hosterror);
549 #else
550 /* Solaris, Irix et alia */
551 hp = gethostbyname_r(hostname, &hs, tmp, GETHOSTBYNAME_BUFLEN - 1,
552 &hosterror);
553 #endif /* !defined(GETHOSTBYNAME_R_GLIBC2) */
554 if (!hp) {
555 return (hosterror + APR_OS_START_SYSERR);
556 }
557 #endif /* !defined(GETHOSTBYNAME_R_HOSTENT_DATA) */
558 #else
559 hp = gethostbyname(hostname);
560 #endif
561
562 if (!hp) {
563 #ifdef WIN32
564 return apr_get_netos_error();
565 #else
566 return (h_errno + APR_OS_START_SYSERR);
567 #endif
568 }
569 }
570
571 prev_sa = NULL;
572 curaddr = 0;
573 while (hp->h_addr_list[curaddr]) {
574 apr_sockaddr_t *new_sa = apr_pcalloc(p, sizeof(apr_sockaddr_t));
575
576 new_sa->pool = p;
577 new_sa->sa.sin.sin_addr = *(struct in_addr *)hp->h_addr_list[curaddr];
578 apr_sockaddr_vars_set(new_sa, AF_INET, port);
579
580 if (!prev_sa) { /* first element in new list */
581 if (orig_hostname) {
582 new_sa->hostname = apr_pstrdup(p, orig_hostname);
583 }
584 *sa = new_sa;
585 }
586 else {
587 new_sa->hostname = prev_sa->hostname;
588 prev_sa->next = new_sa;
589 }
590
591 prev_sa = new_sa;
592 ++curaddr;
593 }
594
595 if (prev_sa == NULL) {
596 /* this should not happen but no result should be treated as error */
597 return APR_EGENERAL;
598 }
599
600 return APR_SUCCESS;
601 }
602
603 #endif /* end of !HAVE_GETADDRINFO code */
604
605 APR_DECLARE(apr_status_t) apr_sockaddr_info_get(apr_sockaddr_t **sa,
606 const char *hostname,
607 apr_int32_t family, apr_port_t port,
608 apr_int32_t flags, apr_pool_t *p)
609 {
610 apr_int32_t masked;
611 *sa = NULL;
612
613 if ((masked = flags & (APR_IPV4_ADDR_OK | APR_IPV6_ADDR_OK))) {
614 if (!hostname ||
615 family != APR_UNSPEC ||
616 masked == (APR_IPV4_ADDR_OK | APR_IPV6_ADDR_OK)) {
617 return APR_EINVAL;
618 }
619 #if !APR_HAVE_IPV6
620 if (flags & APR_IPV6_ADDR_OK) {
621 return APR_ENOTIMPL;
622 }
623 #endif
624 }
625 #if !APR_HAVE_IPV6
626 /* What may happen is that APR is not IPv6-enabled, but we're still
627 * going to call getaddrinfo(), so we have to tell the OS we only
628 * want IPv4 addresses back since we won't know what to do with
629 * IPv6 addresses.
630 */
631 if (family == APR_UNSPEC) {
632 family = APR_INET;
633 }
634 #endif
635
636 return find_addresses(sa, hostname, family, port, flags, p);
637 }
638
639 APR_DECLARE(apr_status_t) apr_getnameinfo(char **hostname,
640 apr_sockaddr_t *sockaddr,
641 apr_int32_t flags)
642 {
643 #if defined(HAVE_GETNAMEINFO)
644 int rc;
645 #if defined(NI_MAXHOST)
646 char tmphostname[NI_MAXHOST];
647 #else
648 char tmphostname[256];
649 #endif
650
651 /* don't know if it is portable for getnameinfo() to set h_errno;
652 * clear it then see if it was set */
653 SET_H_ERRNO(0);
654
655 /* default flags are NI_NAMREQD; otherwise, getnameinfo() will return
656 * a numeric address string if it fails to resolve the host name;
657 * that is *not* what we want here
658 *
659 * For IPv4-mapped IPv6 addresses, drop down to IPv4 before calling
660 * getnameinfo() to avoid getnameinfo bugs (MacOS X, glibc).
661 */
662 #if APR_HAVE_IPV6
663 if (sockaddr->family == AF_INET6 &&
664 IN6_IS_ADDR_V4MAPPED(&sockaddr->sa.sin6.sin6_addr)) {
665 struct sockaddr_in tmpsa;
666 tmpsa.sin_family = AF_INET;
667 tmpsa.sin_port = 0;
668 tmpsa.sin_addr.s_addr = ((apr_uint32_t *)sockaddr->ipaddr_ptr)[3];
669 #ifdef SIN6_LEN
670 tmpsa.sin_len = sizeof(tmpsa);
671 #endif
672
673 rc = getnameinfo((const struct sockaddr *)&tmpsa, sizeof(tmpsa),
674 tmphostname, sizeof(tmphostname), NULL, 0,
675 flags != 0 ? flags : NI_NAMEREQD);
676 }
677 else
678 #endif
679 rc = getnameinfo((const struct sockaddr *)&sockaddr->sa, sockaddr->salen,
680 tmphostname, sizeof(tmphostname), NULL, 0,
681 flags != 0 ? flags : NI_NAMEREQD);
682 if (rc != 0) {
683 *hostname = NULL;
684
685 #ifndef WIN32
686 /* something went wrong. Look at the EAI_ error code */
687 if (rc == EAI_SYSTEM) {
688 /* EAI_SYSTEM System error returned in errno. */
689 /* IMHO, Implementations that set h_errno a simply broken. */
690 if (h_errno) { /* for broken implementations which set h_errno */
691 return h_errno + APR_OS_START_SYSERR;
692 }
693 else { /* "normal" case */
694 return errno + APR_OS_START_SYSERR;
695 }
696 }
697 else
698 #endif
699 {
700 #if defined(NEGATIVE_EAI)
701 if (rc < 0) rc = -rc;
702 #endif
703 return rc + APR_OS_START_EAIERR; /* return the EAI_ error */
704 }
705 }
706 *hostname = sockaddr->hostname = apr_pstrdup(sockaddr->pool,
707 tmphostname);
708 return APR_SUCCESS;
709 #else
710 #if APR_HAS_THREADS && !defined(GETHOSTBYADDR_IS_THREAD_SAFE) && \
711 defined(HAVE_GETHOSTBYADDR_R) && !defined(BEOS)
712 #ifdef GETHOSTBYNAME_R_HOSTENT_DATA
713 struct hostent_data hd;
714 #else
715 char tmp[GETHOSTBYNAME_BUFLEN];
716 #endif
717 int hosterror;
718 struct hostent hs, *hptr;
719
720 #if defined(GETHOSTBYNAME_R_HOSTENT_DATA)
721 /* AIX, HP/UX, D/UX et alia */
722 gethostbyaddr_r((char *)&sockaddr->sa.sin.sin_addr,
723 sizeof(struct in_addr), AF_INET, &hs, &hd);
724 hptr = &hs;
725 #else
726 #if defined(GETHOSTBYNAME_R_GLIBC2)
727 /* Linux glibc2+ */
728 gethostbyaddr_r((char *)&sockaddr->sa.sin.sin_addr,
729 sizeof(struct in_addr), AF_INET,
730 &hs, tmp, GETHOSTBYNAME_BUFLEN - 1, &hptr, &hosterror);
731 #else
732 /* Solaris, Irix et alia */
733 hptr = gethostbyaddr_r((char *)&sockaddr->sa.sin.sin_addr,
734 sizeof(struct in_addr), AF_INET,
735 &hs, tmp, GETHOSTBYNAME_BUFLEN, &hosterror);
736 #endif /* !defined(GETHOSTBYNAME_R_GLIBC2) */
737 if (!hptr) {
738 *hostname = NULL;
739 return hosterror + APR_OS_START_SYSERR;
740 }
741 #endif /* !defined(GETHOSTBYNAME_R_HOSTENT_DATA) */
742 #else
743 struct hostent *hptr;
744 hptr = gethostbyaddr((char *)&sockaddr->sa.sin.sin_addr,
745 sizeof(struct in_addr), AF_INET);
746 #endif
747
748 if (hptr) {
749 *hostname = sockaddr->hostname = apr_pstrdup(sockaddr->pool, hptr->h_name);
750 return APR_SUCCESS;
751 }
752 *hostname = NULL;
753 #if defined(WIN32)
754 return apr_get_netos_error();
755 #elif defined(OS2)
756 return h_errno;
757 #else
758 return h_errno + APR_OS_START_SYSERR;
759 #endif
760 #endif
761 }
762
763 APR_DECLARE(apr_status_t) apr_getservbyname(apr_sockaddr_t *sockaddr,
764 const char *servname)
765 {
766 #if APR_HAS_THREADS && !defined(GETSERVBYNAME_IS_THREAD_SAFE) && \
767 defined(HAVE_GETSERVBYNAME_R) && \
768 (defined(GETSERVBYNAME_R_GLIBC2) || defined(GETSERVBYNAME_R_SOLARIS) || \
769 defined(GETSERVBYNAME_R_OSF1))
770 struct servent se;
771 #if defined(GETSERVBYNAME_R_OSF1)
772 struct servent_data sed;
773
774 memset(&sed, 0, sizeof(sed)); /* must zero fill before use */
775 #else
776 #if defined(GETSERVBYNAME_R_GLIBC2)
777 struct servent *res;
778 #endif
779 char buf[1024];
780 #endif
781 #else
782 struct servent *se;
783 #endif
784
785 if (servname == NULL)
786 return APR_EINVAL;
787
788 #if APR_HAS_THREADS && !defined(GETSERVBYNAME_IS_THREAD_SAFE) && \
789 defined(HAVE_GETSERVBYNAME_R) && \
790 (defined(GETSERVBYNAME_R_GLIBC2) || defined(GETSERVBYNAME_R_SOLARIS) || \
791 defined(GETSERVBYNAME_R_OSF1))
792 #if defined(GETSERVBYNAME_R_GLIBC2)
793 if (getservbyname_r(servname, NULL,
794 &se, buf, sizeof(buf), &res) == 0 && res != NULL) {
795 sockaddr->port = ntohs(res->s_port);
796 sockaddr->servname = apr_pstrdup(sockaddr->pool, servname);
797 sockaddr->sa.sin.sin_port = res->s_port;
798 return APR_SUCCESS;
799 }
800 #elif defined(GETSERVBYNAME_R_SOLARIS)
801 if (getservbyname_r(servname, NULL, &se, buf, sizeof(buf)) != NULL) {
802 sockaddr->port = ntohs(se.s_port);
803 sockaddr->servname = apr_pstrdup(sockaddr->pool, servname);
804 sockaddr->sa.sin.sin_port = se.s_port;
805 return APR_SUCCESS;
806 }
807 #elif defined(GETSERVBYNAME_R_OSF1)
808 if (getservbyname_r(servname, NULL, &se, &sed) == 0) {
809 sockaddr->port = ntohs(se.s_port);
810 sockaddr->servname = apr_pstrdup(sockaddr->pool, servname);
811 sockaddr->sa.sin.sin_port = se.s_port;
812 return APR_SUCCESS;
813 }
814 #endif
815 #else
816 if ((se = getservbyname(servname, NULL)) != NULL){
817 sockaddr->port = ntohs(se->s_port);
818 sockaddr->servname = apr_pstrdup(sockaddr->pool, servname);
819 sockaddr->sa.sin.sin_port = se->s_port;
820 return APR_SUCCESS;
821 }
822 #endif
823 return APR_ENOENT;
824 }
825
826 #define V4MAPPED_EQUAL(a,b) \
827 ((a)->sa.sin.sin_family == AF_INET && \
828 (b)->sa.sin.sin_family == AF_INET6 && \
829 IN6_IS_ADDR_V4MAPPED((struct in6_addr *)(b)->ipaddr_ptr) && \
830 !memcmp((a)->ipaddr_ptr, \
831 &((struct in6_addr *)(b)->ipaddr_ptr)->s6_addr[12], \
832 (a)->ipaddr_len))
833
834 APR_DECLARE(int) apr_sockaddr_equal(const apr_sockaddr_t *addr1,
835 const apr_sockaddr_t *addr2)
836 {
837 if (addr1->ipaddr_len == addr2->ipaddr_len &&
838 !memcmp(addr1->ipaddr_ptr, addr2->ipaddr_ptr, addr1->ipaddr_len)) {
839 return 1;
840 }
841 #if APR_HAVE_IPV6
842 if (V4MAPPED_EQUAL(addr1, addr2)) {
843 return 1;
844 }
845 if (V4MAPPED_EQUAL(addr2, addr1)) {
846 return 1;
847 }
848 #endif
849 return 0; /* not equal */
850 }
851
852 APR_DECLARE(int) apr_sockaddr_is_wildcard(const apr_sockaddr_t *addr)
853 {
854 static const char inaddr_any[
855 #if APR_HAVE_IPV6
856 sizeof(struct in6_addr)
857 #else
858 sizeof(struct in_addr)
859 #endif
860 ] = {0};
861
862 if (addr->ipaddr_ptr /* IP address initialized */
863 && addr->ipaddr_len <= sizeof inaddr_any) { /* else bug elsewhere? */
864 if (!memcmp(inaddr_any, addr->ipaddr_ptr, addr->ipaddr_len)) {
865 return 1;
866 }
867 #if APR_HAVE_IPV6
868 if (addr->family == AF_INET6
869 && IN6_IS_ADDR_V4MAPPED((struct in6_addr *)addr->ipaddr_ptr)) {
870 struct in_addr *v4 = (struct in_addr *)&((apr_uint32_t *)addr->ipaddr_ptr)[3];
871
872 if (!memcmp(inaddr_any, v4, sizeof *v4)) {
873 return 1;
874 }
875 }
876 #endif
877 }
878 return 0;
879 }
880
881 static apr_status_t parse_network(apr_ipsubnet_t *ipsub, const char *network)
882 {
883 /* legacy syntax for ip addrs: a.b.c. ==> a.b.c.0/24 for example */
884 int shift;
885 char *s, *t;
886 int octet;
887 char buf[sizeof "255.255.255.255"];
888
889 if (strlen(network) < sizeof buf) {
890 strcpy(buf, network);
891 }
892 else {
893 return APR_EBADIP;
894 }
895
896 /* parse components */
897 s = buf;
898 ipsub->sub[0] = 0;
899 ipsub->mask[0] = 0;
900 shift = 24;
901 while (*s) {
902 t = s;
903 if (!apr_isdigit(*t)) {
904 return APR_EBADIP;
905 }
906 while (apr_isdigit(*t)) {
907 ++t;
908 }
909 if (*t == '.') {
910 *t++ = 0;
911 }
912 else if (*t) {
913 return APR_EBADIP;
914 }
915 if (shift < 0) {
916 return APR_EBADIP;
917 }
918 octet = atoi(s);
919 if (octet < 0 || octet > 255) {
920 return APR_EBADIP;
921 }
922 ipsub->sub[0] |= octet << shift;
923 ipsub->mask[0] |= 0xFFUL << shift;
924 s = t;
925 shift -= 8;
926 }
927 ipsub->sub[0] = ntohl(ipsub->sub[0]);
928 ipsub->mask[0] = ntohl(ipsub->mask[0]);
929 ipsub->family = AF_INET;
930 return APR_SUCCESS;
931 }
932
933 /* return values:
934 * APR_EINVAL not an IP address; caller should see if it is something else
935 * APR_BADIP IP address portion is is not valid
936 * APR_BADMASK mask portion is not valid
937 */
938
939 static apr_status_t parse_ip(apr_ipsubnet_t *ipsub, const char *ipstr, int network_allowed)
940 {
941 /* supported flavors of IP:
942 *
943 * . IPv6 numeric address string (e.g., "fe80::1")
944 *
945 * IMPORTANT: Don't store IPv4-mapped IPv6 address as an IPv6 address.
946 *
947 * . IPv4 numeric address string (e.g., "127.0.0.1")
948 *
949 * . IPv4 network string (e.g., "9.67")
950 *
951 * IMPORTANT: This network form is only allowed if network_allowed is on.
952 */
953 int rc;
954
955 #if APR_HAVE_IPV6
956 rc = apr_inet_pton(AF_INET6, ipstr, ipsub->sub);
957 if (rc == 1) {
958 if (IN6_IS_ADDR_V4MAPPED((struct in6_addr *)ipsub->sub)) {
959 /* apr_ipsubnet_test() assumes that we don't create IPv4-mapped IPv6
960 * addresses; this of course forces the user to specify IPv4 addresses
961 * in a.b.c.d style instead of ::ffff:a.b.c.d style.
962 */
963 return APR_EBADIP;
964 }
965 ipsub->family = AF_INET6;
966 }
967 else
968 #endif
969 {
970 rc = apr_inet_pton(AF_INET, ipstr, ipsub->sub);
971 if (rc == 1) {
972 ipsub->family = AF_INET;
973 }
974 }
975 if (rc != 1) {
976 if (network_allowed) {
977 return parse_network(ipsub, ipstr);
978 }
979 else {
980 return APR_EBADIP;
981 }
982 }
983 return APR_SUCCESS;
984 }
985
986 static int looks_like_ip(const char *ipstr)
987 {
988 if (strchr(ipstr, ':')) {
989 /* definitely not a hostname; assume it is intended to be an IPv6 address */
990 return 1;
991 }
992
993 /* simple IPv4 address string check */
994 while ((*ipstr == '.') || apr_isdigit(*ipstr))
995 ipstr++;
996 return (*ipstr == '\0');
997 }
998
999 static void fix_subnet(apr_ipsubnet_t *ipsub)
1000 {
1001 /* in case caller specified more bits in network address than are
1002 * valid according to the mask, turn off the extra bits
1003 */
1004 int i;
1005
1006 for (i = 0; i < sizeof ipsub->mask / sizeof(apr_int32_t); i++) {
1007 ipsub->sub[i] &= ipsub->mask[i];
1008 }
1009 }
1010
1011 /* be sure not to store any IPv4 address as a v4-mapped IPv6 address */
1012 APR_DECLARE(apr_status_t) apr_ipsubnet_create(apr_ipsubnet_t **ipsub, const char *ipstr,
1013 const char *mask_or_numbits, apr_pool_t *p)
1014 {
1015 apr_status_t rv;
1016 char *endptr;
1017 long bits, maxbits = 32;
1018
1019 /* filter out stuff which doesn't look remotely like an IP address; this helps
1020 * callers like mod_access which have a syntax allowing hostname or IP address;
1021 * APR_EINVAL tells the caller that it was probably not intended to be an IP
1022 * address
1023 */
1024 if (!looks_like_ip(ipstr)) {
1025 return APR_EINVAL;
1026 }
1027
1028 *ipsub = apr_pcalloc(p, sizeof(apr_ipsubnet_t));
1029
1030 /* assume ipstr is an individual IP address, not a subnet */
1031 memset((*ipsub)->mask, 0xFF, sizeof (*ipsub)->mask);
1032
1033 rv = parse_ip(*ipsub, ipstr, mask_or_numbits == NULL);
1034 if (rv != APR_SUCCESS) {
1035 return rv;
1036 }
1037
1038 if (mask_or_numbits) {
1039 #if APR_HAVE_IPV6
1040 if ((*ipsub)->family == AF_INET6) {
1041 maxbits = 128;
1042 }
1043 #endif
1044 bits = strtol(mask_or_numbits, &endptr, 10);
1045 if (*endptr == '\0' && bits > 0 && bits <= maxbits) {
1046 /* valid num-bits string; fill in mask appropriately */
1047 int cur_entry = 0;
1048 apr_int32_t cur_bit_value;
1049
1050 memset((*ipsub)->mask, 0, sizeof (*ipsub)->mask);
1051 while (bits > 32) {
1052 (*ipsub)->mask[cur_entry] = 0xFFFFFFFF; /* all 32 bits */
1053 bits -= 32;
1054 ++cur_entry;
1055 }
1056 cur_bit_value = 0x80000000;
1057 while (bits) {
1058 (*ipsub)->mask[cur_entry] |= cur_bit_value;
1059 --bits;
1060 cur_bit_value /= 2;
1061 }
1062 (*ipsub)->mask[cur_entry] = htonl((*ipsub)->mask[cur_entry]);
1063 }
1064 else if (apr_inet_pton(AF_INET, mask_or_numbits, (*ipsub)->mask) == 1 &&
1065 (*ipsub)->family == AF_INET) {
1066 /* valid IPv4 netmask */
1067 }
1068 else {
1069 return APR_EBADMASK;
1070 }
1071 }
1072
1073 fix_subnet(*ipsub);
1074
1075 return APR_SUCCESS;
1076 }
1077
1078 APR_DECLARE(int) apr_ipsubnet_test(apr_ipsubnet_t *ipsub, apr_sockaddr_t *sa)
1079 {
1080 #if APR_HAVE_IPV6
1081 /* XXX This line will segv on Win32 build with APR_HAVE_IPV6,
1082 * but without the IPV6 drivers installed.
1083 */
1084 if (sa->family == AF_INET) {
1085 if (ipsub->family == AF_INET &&
1086 ((sa->sa.sin.sin_addr.s_addr & ipsub->mask[0]) == ipsub->sub[0])) {
1087 return 1;
1088 }
1089 }
1090 else if (IN6_IS_ADDR_V4MAPPED((struct in6_addr *)sa->ipaddr_ptr)) {
1091 if (ipsub->family == AF_INET &&
1092 (((apr_uint32_t *)sa->ipaddr_ptr)[3] & ipsub->mask[0]) == ipsub->sub[0]) {
1093 return 1;
1094 }
1095 }
1096 else if (sa->family == AF_INET6 && ipsub->family == AF_INET6) {
1097 apr_uint32_t *addr = (apr_uint32_t *)sa->ipaddr_ptr;
1098
1099 if ((addr[0] & ipsub->mask[0]) == ipsub->sub[0] &&
1100 (addr[1] & ipsub->mask[1]) == ipsub->sub[1] &&
1101 (addr[2] & ipsub->mask[2]) == ipsub->sub[2] &&
1102 (addr[3] & ipsub->mask[3]) == ipsub->sub[3]) {
1103 return 1;
1104 }
1105 }
1106 #else
1107 if ((sa->sa.sin.sin_addr.s_addr & ipsub->mask[0]) == ipsub->sub[0]) {
1108 return 1;
1109 }
1110 #endif /* APR_HAVE_IPV6 */
1111 return 0; /* no match */
1112 }
1113