Apache HTTPD
sockaddr.c
Go to the documentation of this file.
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#ifdef HAVE_NET_IF_H
29#include <net/if.h>
30#endif
31
32#if defined(HAVE_IF_INDEXTONAME) && defined(_MSC_VER)
34#endif
35
36#define APR_WANT_STRFUNC
37#include "apr_want.h"
38
40 int family;
41#if APR_HAVE_IPV6
42 apr_uint32_t sub[4]; /* big enough for IPv4 and IPv6 addresses */
44#else
47#endif
48};
49
50#if !defined(NETWARE) && !defined(WIN32)
51#ifdef HAVE_SET_H_ERRNO
52#define SET_H_ERRNO(newval) set_h_errno(newval)
53#else
54#define SET_H_ERRNO(newval) h_errno = (newval)
55#endif
56#else
57#define SET_H_ERRNO(newval)
58#endif
59
60#if APR_HAS_THREADS && !defined(GETHOSTBYNAME_IS_THREAD_SAFE) && \
61 defined(HAVE_GETHOSTBYNAME_R)
62/* This is the maximum size that may be returned from the reentrant
63 * gethostbyname_r function. If the system tries to use more, it
64 * should return ERANGE.
65 */
66#define GETHOSTBYNAME_BUFLEN 512
67#endif
68
69#ifdef _AIX
70/* Some levels of AIX getaddrinfo() don't like servname = "0", so
71 * set servname to "1" when port is 0 and fix it up later.
72 */
73#define AIX_SERVNAME_HACK 1
74#else
75#define AIX_SERVNAME_HACK 0
76#endif
77
78#ifdef _WIN32_WCE
79/* XXX: BS solution. Need an HAVE_GETSERVBYNAME and actually
80 * do something here, to provide the obvious proto mappings.
81 */
82static void *getservbyname(const char *name, const char *proto)
83{
84 return NULL;
85}
86#endif
87
89{
90 sock->local_addr->salen = sizeof(sock->local_addr->sa);
92 &sock->local_addr->salen) < 0) {
93 return apr_get_netos_error();
94 }
95 else {
97 /* XXX assumes sin_port and sin6_port at same offset */
98 sock->local_addr->port = ntohs(sock->local_addr->sa.sin.sin_port);
99 return APR_SUCCESS;
100 }
101}
102
104{
105 sock->remote_addr->salen = sizeof(sock->remote_addr->sa);
107 &sock->remote_addr->salen) < 0) {
108 return apr_get_netos_error();
109 }
110 else {
112 /* XXX assumes sin_port and sin6_port at same offset */
114 return APR_SUCCESS;
115 }
116}
117
120{
121#if APR_HAVE_SOCKADDR_UN
122 if (sockaddr->family == APR_UNIX) {
123 const char *ptr = sockaddr->ipaddr_ptr;
125 /* assumes that sockaddr->ipaddr_ptr is nul terminated */
126 return ptr[len] ? APR_ENOSPC : APR_SUCCESS;
127 }
128#endif
129
131 return APR_ENOSPC;
132 }
133
134#if APR_HAVE_IPV6
135 if (sockaddr->family == AF_INET6
137 && buflen > strlen("::ffff:")) {
138 /* This is an IPv4-mapped IPv6 address; drop the leading
139 * part of the address string so we're left with the familiar
140 * IPv4 format.
141 */
142 memmove(buf, buf + strlen("::ffff:"),
143 strlen(buf + strlen("::ffff:"))+1);
144 }
145
146 /* ensure NUL termination if the buffer is too short */
147 buf[buflen-1] = '\0';
148
149#ifdef HAVE_IF_INDEXTONAME
150 /* Append scope name for link-local addresses. */
151 if (sockaddr->family == AF_INET6
153 char scbuf[IF_NAMESIZE], *p = buf + strlen(buf);
154
155 if (if_indextoname(sockaddr->sa.sin6.sin6_scope_id, scbuf) == scbuf) {
156 /* Space check, need room for buf + '%' + scope + '\0'.
157 * Assert: buflen >= strlen(buf) + strlen(scbuf) + 2
158 * Equiv: buflen >= (p-buf) + strlen(buf) + 2
159 * Thus, fail in inverse condition: */
160 if (buflen < strlen(scbuf) + (p - buf) + 2) {
161 return APR_ENOSPC;
162 }
163 *p++ = '%';
164 memcpy(p, scbuf, strlen(scbuf) + 1);
165 }
166 }
167#endif /* HAVE_IF_INDEXTONAME */
168#endif /* APR_HAVE_IPV6 */
169
170 return APR_SUCCESS;
171}
172
175{
178}
179
181{
182 addr->family = family;
183 addr->sa.sin.sin_family = family;
184 if (port) {
185 /* XXX IPv6: assumes sin_port and sin6_port at same offset */
186 addr->sa.sin.sin_port = htons(port);
187 addr->port = port;
188 }
189#if AIX_SERVNAME_HACK
190 else {
191 addr->sa.sin.sin_port = htons(port);
192 }
193#endif
194
195 if (family == APR_INET) {
196 addr->salen = sizeof(struct sockaddr_in);
197 addr->addr_str_len = 16;
198 addr->ipaddr_ptr = &(addr->sa.sin.sin_addr);
199 addr->ipaddr_len = sizeof(struct in_addr);
200 }
201#if APR_HAVE_IPV6
202 else if (family == APR_INET6) {
203 addr->salen = sizeof(struct sockaddr_in6);
204 addr->addr_str_len = 46;
205 addr->ipaddr_ptr = &(addr->sa.sin6.sin6_addr);
206 addr->ipaddr_len = sizeof(struct in6_addr);
207 }
208#endif
209#if APR_HAVE_SOCKADDR_UN
210 else if (family == APR_UNIX) {
211 addr->salen = sizeof(struct sockaddr_un);
212 addr->addr_str_len = sizeof(addr->sa.unx.sun_path);;
213 addr->ipaddr_ptr = &(addr->sa.unx.sun_path);
215 }
216#endif
217}
218
222{
223 if (which == APR_LOCAL) {
226
227 if (rv != APR_SUCCESS) {
228 return rv;
229 }
230 }
231 *sa = sock->local_addr;
232 }
233 else if (which == APR_REMOTE) {
236
237 if (rv != APR_SUCCESS) {
238 return rv;
239 }
240 }
241 *sa = sock->remote_addr;
242 }
243 else {
244 *sa = NULL;
245 return APR_EINVAL;
246 }
247 return APR_SUCCESS;
248}
249
251 char **scope_id,
253 const char *str,
254 apr_pool_t *p)
255{
256 const char *ch, *lastchar;
257 int big_port;
259
260 *addr = NULL; /* assume not specified */
261 *scope_id = NULL; /* assume not specified */
262 *port = 0; /* assume not specified */
263
264 /* First handle the optional port number. That may be all that
265 * is specified in the string.
266 */
267 ch = lastchar = str + strlen(str) - 1;
268 while (ch >= str && apr_isdigit(*ch)) {
269 --ch;
270 }
271
272 if (ch < str) { /* Entire string is the port. */
273 big_port = atoi(str);
274 if (big_port < 1 || big_port > 65535) {
275 return APR_EINVAL;
276 }
277 *port = big_port;
278 return APR_SUCCESS;
279 }
280
281 if (*ch == ':' && ch < lastchar) { /* host and port number specified */
282 if (ch == str) { /* string starts with ':' -- bad */
283 return APR_EINVAL;
284 }
285 big_port = atoi(ch + 1);
286 if (big_port < 1 || big_port > 65535) {
287 return APR_EINVAL;
288 }
289 *port = big_port;
290 lastchar = ch - 1;
291 }
292
293 /* now handle the hostname */
294 addrlen = lastchar - str + 1;
295
296/* XXX we don't really have to require APR_HAVE_IPV6 for this;
297 * just pass char[] for ipaddr (so we don't depend on struct in6_addr)
298 * and always define APR_INET6
299 */
300#if APR_HAVE_IPV6
301 if (*str == '[') {
302 const char *end_bracket = memchr(str, ']', addrlen);
303 struct in6_addr ipaddr;
304 const char *scope_delim;
305
306 if (!end_bracket || end_bracket != lastchar) {
307 *port = 0;
308 return APR_EINVAL;
309 }
310
311 /* handle scope id; this is the only context where it is allowed */
312 scope_delim = memchr(str, '%', addrlen);
313 if (scope_delim) {
314 if (scope_delim == end_bracket - 1) { /* '%' without scope id */
315 *port = 0;
316 return APR_EINVAL;
317 }
318 addrlen = scope_delim - str - 1;
320 }
321 else {
322 addrlen = addrlen - 2; /* minus 2 for '[' and ']' */
323 }
324
325 *addr = apr_pstrmemdup(p, str + 1, addrlen);
326 if (apr_inet_pton(AF_INET6, *addr, &ipaddr) != 1) {
327 *addr = NULL;
328 *scope_id = NULL;
329 *port = 0;
330 return APR_EINVAL;
331 }
332 }
333 else
334#endif
335 {
336 /* XXX If '%' is not a valid char in a DNS name, we *could* check
337 * for bogus scope ids first.
338 */
340 }
341 return APR_SUCCESS;
342}
343
344#if defined(HAVE_GETADDRINFO)
345
347 const char *hostname, apr_int32_t family,
349 apr_pool_t *p)
350{
351 struct addrinfo hints, *ai, *ai_list;
353 int error;
354 char *servname = NULL;
355
356 memset(&hints, 0, sizeof(hints));
357 hints.ai_family = family;
358 hints.ai_socktype = SOCK_STREAM;
359#ifdef HAVE_GAI_ADDRCONFIG
360 if (family == APR_UNSPEC) {
361 /* By default, only look up addresses using address types for
362 * which a local interface is configured, i.e. no IPv6 if no
363 * IPv6 interfaces configured. */
364 hints.ai_flags = AI_ADDRCONFIG;
365 }
366#endif
367
368#ifdef __MVS__
369 /* z/OS will not return IPv4 address under AF_UNSPEC if any IPv6 results
370 * are returned, w/o AI_ALL.
371 */
372 if (family == APR_UNSPEC) {
373 hints.ai_flags |= AI_ALL;
374 }
375#endif
376
377 if(hostname == NULL) {
378#ifdef AI_PASSIVE
379 /* If hostname is NULL, assume we are trying to bind to all
380 * interfaces. */
381 hints.ai_flags |= AI_PASSIVE;
382#endif
383 /* getaddrinfo according to RFC 2553 must have either hostname
384 * or servname non-NULL.
385 */
386#ifdef OSF1
387 /* The Tru64 5.0 getaddrinfo() can only resolve services given
388 * by the name listed in /etc/services; a numeric or unknown
389 * servname gets an EAI_SERVICE error. So just resolve the
390 * appropriate anyaddr and fill in the port later. */
391 hostname = family == AF_INET6 ? "::" : "0.0.0.0";
392 servname = NULL;
393#ifdef AI_NUMERICHOST
394 hints.ai_flags |= AI_NUMERICHOST;
395#endif
396#else
397#if AIX_SERVNAME_HACK
398 if (!port) {
399 servname = "1";
400 }
401 else
402#endif /* AIX_SERVNAME_HACK */
404#endif /* OSF1 */
405 }
407#ifdef HAVE_GAI_ADDRCONFIG
408 /*
409 * Using AI_ADDRCONFIG involves some unfortunate guesswork because it
410 * does not consider loopback addresses when trying to determine if
411 * IPv4 or IPv6 is configured on a system (see RFC 3493).
412 * This is a problem if one actually wants to listen on or connect to
413 * the loopback address of a protocol family that is not otherwise
414 * configured on the system. See PR 52709.
415 * To work around some of the problems, retry without AI_ADDRCONFIG
416 * in case of EAI_ADDRFAMILY.
417 * XXX: apr_sockaddr_info_get() should really accept a flag to determine
418 * XXX: if AI_ADDRCONFIG's guesswork is wanted and if the address is
419 * XXX: to be used for listen() or connect().
420 *
421 * In case of EAI_BADFLAGS, AI_ADDRCONFIG is not supported.
422 */
423 if ((family == APR_UNSPEC) && (error == EAI_BADFLAGS
426#endif
427 )) {
428 hints.ai_flags &= ~AI_ADDRCONFIG;
430 }
431#endif
432 if (error) {
433#if defined(WIN32)
434 return apr_get_netos_error();
435#else
436 if (error == EAI_SYSTEM) {
437 return errno ? errno : APR_EGENERAL;
438 }
439 else
440 {
441 /* issues with representing this with APR's error scheme:
442 * glibc uses negative values for these numbers, perhaps so
443 * they don't conflict with h_errno values... Tru64 uses
444 * positive values which conflict with h_errno values
445 */
446#if defined(NEGATIVE_EAI)
447 error = -error;
448#endif
449 return error + APR_OS_START_EAIERR;
450 }
451#endif /* WIN32 */
452 }
453
454 prev_sa = NULL;
455 ai = ai_list;
456 while (ai) { /* while more addresses to report */
458
459 /* Ignore anything bogus: getaddrinfo in some old versions of
460 * glibc will return AF_UNIX entries for APR_UNSPEC+AI_PASSIVE
461 * lookups. */
462#if APR_HAVE_IPV6
463 if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6) {
464#else
465 if (ai->ai_family != AF_INET) {
466#endif
467 ai = ai->ai_next;
468 continue;
469 }
470
472
473 new_sa->pool = p;
474 memcpy(&new_sa->sa, ai->ai_addr, ai->ai_addrlen);
475 apr_sockaddr_vars_set(new_sa, ai->ai_family, port);
476
477 if (!prev_sa) { /* first element in new list */
478 if (hostname) {
479 new_sa->hostname = apr_pstrdup(p, hostname);
480 }
481 *sa = new_sa;
482 }
483 else {
484 new_sa->hostname = prev_sa->hostname;
485 prev_sa->next = new_sa;
486 }
487
488 prev_sa = new_sa;
489 ai = ai->ai_next;
490 }
492
493 if (prev_sa == NULL) {
494 /*
495 * getaddrinfo returned only useless entries and *sa is still empty.
496 * This should be treated as an error.
497 */
498 return APR_EGENERAL;
499 }
500
501 return APR_SUCCESS;
502}
503
505 const char *hostname, apr_int32_t family,
507 apr_pool_t *p)
508{
509 if (flags & APR_IPV4_ADDR_OK) {
511
512#if APR_HAVE_IPV6
513 if (error) {
514 family = AF_INET6; /* try again */
515 }
516 else
517#endif
518 return error;
519 }
520#if APR_HAVE_IPV6
521 else if (flags & APR_IPV6_ADDR_OK) {
523
524 if (error) {
525 family = AF_INET; /* try again */
526 }
527 else {
528 return APR_SUCCESS;
529 }
530 }
531#endif
532
534}
535
536#else /* end of HAVE_GETADDRINFO code */
537
539 const char *hostname, apr_int32_t family,
541 apr_pool_t *p)
542{
543 struct hostent *hp;
545 int curaddr;
546#if APR_HAS_THREADS && !defined(GETHOSTBYNAME_IS_THREAD_SAFE) && \
547 defined(HAVE_GETHOSTBYNAME_R) && !defined(BEOS)
548#ifdef GETHOSTBYNAME_R_HOSTENT_DATA
549 struct hostent_data hd;
550#else
551 /* If you see ERANGE, that means GETHOSBYNAME_BUFLEN needs to be
552 * bumped. */
553 char tmp[GETHOSTBYNAME_BUFLEN];
554#endif
555 int hosterror;
556#endif
557 struct hostent hs;
558 struct in_addr ipaddr;
559 char *addr_list[2];
560 const char *orig_hostname = hostname;
561
562 if (hostname == NULL) {
563 /* if we are given a NULL hostname, assume '0.0.0.0' */
564 hostname = "0.0.0.0";
565 }
566
567 if (*hostname >= '0' && *hostname <= '9' &&
568 strspn(hostname, "0123456789.") == strlen(hostname)) {
569
571 addr_list[0] = (char *)&ipaddr;
572 addr_list[1] = NULL; /* just one IP in list */
573 hs.h_addr_list = (char **)addr_list;
574 hp = &hs;
575 }
576 else {
577#if APR_HAS_THREADS && !defined(GETHOSTBYNAME_IS_THREAD_SAFE) && \
578 defined(HAVE_GETHOSTBYNAME_R) && !defined(BEOS)
579#if defined(GETHOSTBYNAME_R_HOSTENT_DATA)
580 /* AIX, HP/UX, D/UX et alia */
582 hp = &hs;
583#else
584#if defined(GETHOSTBYNAME_R_GLIBC2)
585 /* Linux glibc2+ */
587 &hp, &hosterror);
588#else
589 /* Solaris, Irix et alia */
591 &hosterror);
592#endif /* !defined(GETHOSTBYNAME_R_GLIBC2) */
593 if (!hp) {
595 }
596#endif /* !defined(GETHOSTBYNAME_R_HOSTENT_DATA) */
597#else
599#endif
600
601 if (!hp) {
602#ifdef WIN32
603 return apr_get_netos_error();
604#else
605 return (h_errno + APR_OS_START_SYSERR);
606#endif
607 }
608 }
609
610 prev_sa = NULL;
611 curaddr = 0;
612 while (hp->h_addr_list[curaddr]) {
614
615 new_sa->pool = p;
616 new_sa->sa.sin.sin_addr = *(struct in_addr *)hp->h_addr_list[curaddr];
618
619 if (!prev_sa) { /* first element in new list */
620 if (orig_hostname) {
621 new_sa->hostname = apr_pstrdup(p, orig_hostname);
622 }
623 *sa = new_sa;
624 }
625 else {
626 new_sa->hostname = prev_sa->hostname;
627 prev_sa->next = new_sa;
628 }
629
630 prev_sa = new_sa;
631 ++curaddr;
632 }
633
634 if (prev_sa == NULL) {
635 /* this should not happen but no result should be treated as error */
636 return APR_EGENERAL;
637 }
638
639 return APR_SUCCESS;
640}
641
642#endif /* end of !HAVE_GETADDRINFO code */
643
645 const char *hostname,
648{
650 *sa = NULL;
651
653 if (!hostname ||
654 family != APR_UNSPEC ||
656 return APR_EINVAL;
657 }
658#if !APR_HAVE_IPV6
659 if (flags & APR_IPV6_ADDR_OK) {
660 return APR_ENOTIMPL;
661 }
662#endif
663 }
664 if (family == APR_UNSPEC && hostname && *hostname == '/') {
666 }
667 if (family == APR_UNIX) {
668#if APR_HAVE_SOCKADDR_UN
669 if (hostname && *hostname == '/') {
670 *sa = apr_pcalloc(p, sizeof(apr_sockaddr_t));
671 (*sa)->pool = p;
672 apr_cpystrn((*sa)->sa.unx.sun_path, hostname,
673 sizeof((*sa)->sa.unx.sun_path));
674 (*sa)->hostname = apr_pstrdup(p, hostname);
675 (*sa)->family = APR_UNIX;
676 (*sa)->sa.unx.sun_family = APR_UNIX;
677 (*sa)->salen = sizeof(struct sockaddr_un);
678 (*sa)->addr_str_len = sizeof((*sa)->sa.unx.sun_path);
679 (*sa)->ipaddr_ptr = &((*sa)->sa.unx.sun_path);
680 (*sa)->ipaddr_len = (*sa)->addr_str_len;
681
682 return APR_SUCCESS;
683 }
684 else
685#endif
686 {
687 *sa = NULL;
688 return APR_ENOTIMPL;
689 }
690 }
691#if !APR_HAVE_IPV6
692 /* What may happen is that APR is not IPv6-enabled, but we're still
693 * going to call getaddrinfo(), so we have to tell the OS we only
694 * want IPv4 addresses back since we won't know what to do with
695 * IPv6 addresses.
696 */
697 if (family == APR_UNSPEC) {
699 }
700#endif
701
703}
704
706 const apr_sockaddr_t *src,
707 apr_pool_t *p)
708{
710 const apr_sockaddr_t *s;
711
712 for (*dst = d = NULL, s = src; s; s = s->next) {
713 if (!d) {
714 *dst = d = apr_pmemdup(p, s, sizeof *s);
715 }
716 else {
717 d = d->next = apr_pmemdup(p, s, sizeof *s);
718 }
719 if (s->hostname) {
720 if (s == src || s->hostname != src->hostname) {
721 d->hostname = apr_pstrdup(p, s->hostname);
722 }
723 else {
724 d->hostname = (*dst)->hostname;
725 }
726 }
727 if (s->servname) {
728 if (s == src || s->servname != src->servname) {
729 d->servname = apr_pstrdup(p, s->servname);
730 }
731 else {
732 d->servname = (*dst)->servname;
733 }
734 }
735 d->pool = p;
736 apr_sockaddr_vars_set(d, s->family, s->port);
737 }
738 return APR_SUCCESS;
739}
740
744{
745#if defined(HAVE_GETNAMEINFO)
746 int rc;
747#if defined(NI_MAXHOST)
749#else
750 char tmphostname[256];
751#endif
752
753 /* don't know if it is portable for getnameinfo() to set h_errno;
754 * clear it then see if it was set */
755 SET_H_ERRNO(0);
756
757 /* default flags are NI_NAMREQD; otherwise, getnameinfo() will return
758 * a numeric address string if it fails to resolve the host name;
759 * that is *not* what we want here
760 *
761 * For IPv4-mapped IPv6 addresses, drop down to IPv4 before calling
762 * getnameinfo() to avoid getnameinfo bugs (MacOS X, glibc).
763 */
764#if APR_HAVE_IPV6
765 if (sockaddr->family == AF_INET6 &&
766 IN6_IS_ADDR_V4MAPPED(&sockaddr->sa.sin6.sin6_addr)) {
767 struct sockaddr_in tmpsa;
768 tmpsa.sin_family = AF_INET;
769 tmpsa.sin_port = 0;
770 tmpsa.sin_addr.s_addr = ((apr_uint32_t *)sockaddr->ipaddr_ptr)[3];
771#ifdef SIN6_LEN
772 tmpsa.sin_len = sizeof(tmpsa);
773#endif
774
775 rc = getnameinfo((const struct sockaddr *)&tmpsa, sizeof(tmpsa),
776 tmphostname, sizeof(tmphostname), NULL, 0,
777 flags != 0 ? flags : NI_NAMEREQD);
778 }
779#if APR_HAVE_SOCKADDR_UN
780 else if (sockaddr->family == APR_UNIX) {
782 return APR_SUCCESS;
783 }
784#endif
785 else
786#endif
787 rc = getnameinfo((const struct sockaddr *)&sockaddr->sa, sockaddr->salen,
788 tmphostname, sizeof(tmphostname), NULL, 0,
789 flags != 0 ? flags : NI_NAMEREQD);
790 if (rc != 0) {
791 *hostname = NULL;
792
793#ifndef WIN32
794 /* something went wrong. Look at the EAI_ error code */
795 if (rc == EAI_SYSTEM) {
796 /* EAI_SYSTEM System error returned in errno. */
797 /* IMHO, Implementations that set h_errno a simply broken. */
798 if (h_errno) { /* for broken implementations which set h_errno */
800 }
801 else { /* "normal" case */
802 return errno + APR_OS_START_SYSERR;
803 }
804 }
805 else
806#endif
807 {
808#if defined(NEGATIVE_EAI)
809 if (rc < 0) rc = -rc;
810#endif
811 return rc + APR_OS_START_EAIERR; /* return the EAI_ error */
812 }
813 }
816 return APR_SUCCESS;
817#else
818#if APR_HAS_THREADS && !defined(GETHOSTBYADDR_IS_THREAD_SAFE) && \
819 defined(HAVE_GETHOSTBYADDR_R) && !defined(BEOS)
820#ifdef GETHOSTBYNAME_R_HOSTENT_DATA
821 struct hostent_data hd;
822#else
823 char tmp[GETHOSTBYNAME_BUFLEN];
824#endif
825 int hosterror;
826 struct hostent hs, *hptr;
827
828#if defined(GETHOSTBYNAME_R_HOSTENT_DATA)
829 /* AIX, HP/UX, D/UX et alia */
830 gethostbyaddr_r((char *)&sockaddr->sa.sin.sin_addr,
831 sizeof(struct in_addr), AF_INET, &hs, &hd);
832 hptr = &hs;
833#else
834#if defined(GETHOSTBYNAME_R_GLIBC2)
835 /* Linux glibc2+ */
836 gethostbyaddr_r((char *)&sockaddr->sa.sin.sin_addr,
837 sizeof(struct in_addr), AF_INET,
838 &hs, tmp, GETHOSTBYNAME_BUFLEN - 1, &hptr, &hosterror);
839#else
840 /* Solaris, Irix et alia */
841 hptr = gethostbyaddr_r((char *)&sockaddr->sa.sin.sin_addr,
842 sizeof(struct in_addr), AF_INET,
843 &hs, tmp, GETHOSTBYNAME_BUFLEN, &hosterror);
844#endif /* !defined(GETHOSTBYNAME_R_GLIBC2) */
845 if (!hptr) {
846 *hostname = NULL;
848 }
849#endif /* !defined(GETHOSTBYNAME_R_HOSTENT_DATA) */
850#else
851 struct hostent *hptr;
852 hptr = gethostbyaddr((char *)&sockaddr->sa.sin.sin_addr,
853 sizeof(struct in_addr), AF_INET);
854#endif
855
856 if (hptr) {
858 return APR_SUCCESS;
859 }
860 *hostname = NULL;
861#if defined(WIN32)
862 return apr_get_netos_error();
863#elif defined(OS2)
864 return h_errno;
865#else
867#endif
868#endif
869}
870
872 const char *servname)
873{
874#if APR_HAS_THREADS && !defined(GETSERVBYNAME_IS_THREAD_SAFE) && \
875 defined(HAVE_GETSERVBYNAME_R) && \
876 (defined(GETSERVBYNAME_R_GLIBC2) || defined(GETSERVBYNAME_R_SOLARIS) || \
877 defined(GETSERVBYNAME_R_OSF1))
878 struct servent se;
879#if defined(GETSERVBYNAME_R_OSF1)
880 struct servent_data sed;
881
882 memset(&sed, 0, sizeof(sed)); /* must zero fill before use */
883#else
884#if defined(GETSERVBYNAME_R_GLIBC2)
885 struct servent *res;
886#endif
887 char buf[1024];
888#endif
889#else
890 struct servent *se;
891#endif
892
893 if (servname == NULL)
894 return APR_EINVAL;
895
896#if APR_HAS_THREADS && !defined(GETSERVBYNAME_IS_THREAD_SAFE) && \
897 defined(HAVE_GETSERVBYNAME_R) && \
898 (defined(GETSERVBYNAME_R_GLIBC2) || defined(GETSERVBYNAME_R_SOLARIS) || \
899 defined(GETSERVBYNAME_R_OSF1))
900#if defined(GETSERVBYNAME_R_GLIBC2)
902 &se, buf, sizeof(buf), &res) == 0 && res != NULL) {
903 sockaddr->port = ntohs(res->s_port);
905 sockaddr->sa.sin.sin_port = res->s_port;
906 return APR_SUCCESS;
907 }
908#elif defined(GETSERVBYNAME_R_SOLARIS)
909 if (getservbyname_r(servname, NULL, &se, buf, sizeof(buf)) != NULL) {
910 sockaddr->port = ntohs(se.s_port);
912 sockaddr->sa.sin.sin_port = se.s_port;
913 return APR_SUCCESS;
914 }
915#elif defined(GETSERVBYNAME_R_OSF1)
916 if (getservbyname_r(servname, NULL, &se, &sed) == 0) {
917 sockaddr->port = ntohs(se.s_port);
919 sockaddr->sa.sin.sin_port = se.s_port;
920 return APR_SUCCESS;
921 }
922#endif
923#else
924 if ((se = getservbyname(servname, NULL)) != NULL){
925 sockaddr->port = ntohs(se->s_port);
927 sockaddr->sa.sin.sin_port = se->s_port;
928 return APR_SUCCESS;
929 }
930#endif
931 return APR_ENOENT;
932}
933
934#define V4MAPPED_EQUAL(a,b) \
935((a)->sa.sin.sin_family == AF_INET && \
936 (b)->sa.sin.sin_family == AF_INET6 && \
937 IN6_IS_ADDR_V4MAPPED((struct in6_addr *)(b)->ipaddr_ptr) && \
938 !memcmp((a)->ipaddr_ptr, \
939 &((struct in6_addr *)(b)->ipaddr_ptr)->s6_addr[12], \
940 (a)->ipaddr_len))
941
942#if APR_HAVE_IPV6
943#define SCOPE_OR_ZERO(sa_) ((sa_)->family != AF_INET6 ? 0 : \
944 ((sa_)->sa.sin6.sin6_scope_id))
945#else
946#define SCOPE_OR_ZERO(sa_) (0)
947#endif
948
950 const apr_sockaddr_t *addr2)
951{
952 if (addr1->ipaddr_len == addr2->ipaddr_len
953 && !memcmp(addr1->ipaddr_ptr, addr2->ipaddr_ptr, addr1->ipaddr_len)
955 return 1;
956 }
957#if APR_HAVE_IPV6
958 if (V4MAPPED_EQUAL(addr1, addr2)) {
959 return 1;
960 }
961 if (V4MAPPED_EQUAL(addr2, addr1)) {
962 return 1;
963 }
964#endif
965 return 0; /* not equal */
966}
967
969{
970 static const char inaddr_any[
971#if APR_HAVE_IPV6
972 sizeof(struct in6_addr)
973#else
975#endif
976 ] = {0};
977
978 if (addr->ipaddr_ptr /* IP address initialized */
979 && addr->ipaddr_len <= sizeof inaddr_any) { /* else bug elsewhere? */
981 return 1;
982 }
983#if APR_HAVE_IPV6
984 if (addr->family == AF_INET6
986 struct in_addr *v4 = (struct in_addr *)&((apr_uint32_t *)addr->ipaddr_ptr)[3];
987
988 if (!memcmp(inaddr_any, v4, sizeof *v4)) {
989 return 1;
990 }
991 }
992#endif
993 }
994 return 0;
995}
996
998{
999 /* legacy syntax for ip addrs: a.b.c. ==> a.b.c.0/24 for example */
1000 int shift;
1001 char *s, *t;
1002 int octet;
1003 char buf[sizeof "255.255.255.255"];
1004
1005 if (strlen(network) < sizeof buf) {
1006 strcpy(buf, network);
1007 }
1008 else {
1009 return APR_EBADIP;
1010 }
1011
1012 /* parse components */
1013 s = buf;
1014 ipsub->sub[0] = 0;
1015 ipsub->mask[0] = 0;
1016 shift = 24;
1017 while (*s) {
1018 t = s;
1019 if (!apr_isdigit(*t)) {
1020 return APR_EBADIP;
1021 }
1022 while (apr_isdigit(*t)) {
1023 ++t;
1024 }
1025 if (*t == '.') {
1026 *t++ = 0;
1027 }
1028 else if (*t) {
1029 return APR_EBADIP;
1030 }
1031 if (shift < 0) {
1032 return APR_EBADIP;
1033 }
1034 octet = atoi(s);
1035 if (octet < 0 || octet > 255) {
1036 return APR_EBADIP;
1037 }
1038 ipsub->sub[0] |= octet << shift;
1039 ipsub->mask[0] |= 0xFFUL << shift;
1040 s = t;
1041 shift -= 8;
1042 }
1043 ipsub->sub[0] = ntohl(ipsub->sub[0]);
1044 ipsub->mask[0] = ntohl(ipsub->mask[0]);
1045 ipsub->family = AF_INET;
1046 return APR_SUCCESS;
1047}
1048
1049/* return values:
1050 * APR_EINVAL not an IP address; caller should see if it is something else
1051 * APR_BADIP IP address portion is is not valid
1052 * APR_BADMASK mask portion is not valid
1053 */
1054
1056{
1057 /* supported flavors of IP:
1058 *
1059 * . IPv6 numeric address string (e.g., "fe80::1")
1060 *
1061 * IMPORTANT: Don't store IPv4-mapped IPv6 address as an IPv6 address.
1062 *
1063 * . IPv4 numeric address string (e.g., "127.0.0.1")
1064 *
1065 * . IPv4 network string (e.g., "9.67")
1066 *
1067 * IMPORTANT: This network form is only allowed if network_allowed is on.
1068 */
1069 int rc;
1070
1071#if APR_HAVE_IPV6
1073 if (rc == 1) {
1074 if (IN6_IS_ADDR_V4MAPPED((struct in6_addr *)ipsub->sub)) {
1075 /* apr_ipsubnet_test() assumes that we don't create IPv4-mapped IPv6
1076 * addresses; this of course forces the user to specify IPv4 addresses
1077 * in a.b.c.d style instead of ::ffff:a.b.c.d style.
1078 */
1079 return APR_EBADIP;
1080 }
1081 ipsub->family = AF_INET6;
1082 }
1083 else
1084#endif
1085 {
1087 if (rc == 1) {
1088 ipsub->family = AF_INET;
1089 }
1090 }
1091 if (rc != 1) {
1092 if (network_allowed) {
1093 return parse_network(ipsub, ipstr);
1094 }
1095 else {
1096 return APR_EBADIP;
1097 }
1098 }
1099 return APR_SUCCESS;
1100}
1101
1102static int looks_like_ip(const char *ipstr)
1103{
1104 if (strlen(ipstr) == 0) {
1105 return 0;
1106 }
1107
1108 if (strchr(ipstr, ':')) {
1109 /* definitely not a hostname; assume it is intended to be an IPv6 address */
1110 return 1;
1111 }
1112
1113 /* simple IPv4 address string check */
1114 while ((*ipstr == '.') || apr_isdigit(*ipstr))
1115 ipstr++;
1116 return (*ipstr == '\0');
1117}
1118
1120{
1121 /* in case caller specified more bits in network address than are
1122 * valid according to the mask, turn off the extra bits
1123 */
1124 int i;
1125
1126 for (i = 0; i < sizeof ipsub->mask / sizeof(apr_int32_t); i++) {
1127 ipsub->sub[i] &= ipsub->mask[i];
1128 }
1129}
1130
1131/* be sure not to store any IPv4 address as a v4-mapped IPv6 address */
1133 const char *mask_or_numbits, apr_pool_t *p)
1134{
1135 apr_status_t rv;
1136 char *endptr;
1137 long bits, maxbits = 32;
1138
1139 /* filter out stuff which doesn't look remotely like an IP address; this helps
1140 * callers like mod_access which have a syntax allowing hostname or IP address;
1141 * APR_EINVAL tells the caller that it was probably not intended to be an IP
1142 * address
1143 */
1144 if (!looks_like_ip(ipstr)) {
1145 return APR_EINVAL;
1146 }
1147
1148 *ipsub = apr_pcalloc(p, sizeof(apr_ipsubnet_t));
1149
1150 /* assume ipstr is an individual IP address, not a subnet */
1151 memset((*ipsub)->mask, 0xFF, sizeof (*ipsub)->mask);
1152
1154 if (rv != APR_SUCCESS) {
1155 return rv;
1156 }
1157
1158 if (mask_or_numbits) {
1159#if APR_HAVE_IPV6
1160 if ((*ipsub)->family == AF_INET6) {
1161 maxbits = 128;
1162 }
1163#endif
1164 bits = strtol(mask_or_numbits, &endptr, 10);
1165 if (*endptr == '\0' && bits > 0 && bits <= maxbits) {
1166 /* valid num-bits string; fill in mask appropriately */
1167 int cur_entry = 0;
1169
1170 memset((*ipsub)->mask, 0, sizeof (*ipsub)->mask);
1171 while (bits > 32) {
1172 (*ipsub)->mask[cur_entry] = 0xFFFFFFFF; /* all 32 bits */
1173 bits -= 32;
1174 ++cur_entry;
1175 }
1176 cur_bit_value = 0x80000000;
1177 while (bits) {
1178 (*ipsub)->mask[cur_entry] |= cur_bit_value;
1179 --bits;
1180 cur_bit_value /= 2;
1181 }
1182 (*ipsub)->mask[cur_entry] = htonl((*ipsub)->mask[cur_entry]);
1183 }
1184 else if (apr_inet_pton(AF_INET, mask_or_numbits, (*ipsub)->mask) == 1 &&
1185 (*ipsub)->family == AF_INET) {
1186 /* valid IPv4 netmask */
1187 }
1188 else {
1189 return APR_EBADMASK;
1190 }
1191 }
1192
1193 fix_subnet(*ipsub);
1194
1195 return APR_SUCCESS;
1196}
1197
1199{
1200#if APR_HAVE_IPV6
1201 /* XXX This line will segv on Win32 build with APR_HAVE_IPV6,
1202 * but without the IPV6 drivers installed.
1203 */
1204 if (sa->family == AF_INET) {
1205 if (ipsub->family == AF_INET &&
1206 ((sa->sa.sin.sin_addr.s_addr & ipsub->mask[0]) == ipsub->sub[0])) {
1207 return 1;
1208 }
1209 }
1210 else if (IN6_IS_ADDR_V4MAPPED((struct in6_addr *)sa->ipaddr_ptr)) {
1211 if (ipsub->family == AF_INET &&
1212 (((apr_uint32_t *)sa->ipaddr_ptr)[3] & ipsub->mask[0]) == ipsub->sub[0]) {
1213 return 1;
1214 }
1215 }
1216 else if (sa->family == AF_INET6 && ipsub->family == AF_INET6) {
1218
1219 if ((addr[0] & ipsub->mask[0]) == ipsub->sub[0] &&
1220 (addr[1] & ipsub->mask[1]) == ipsub->sub[1] &&
1221 (addr[2] & ipsub->mask[2]) == ipsub->sub[2] &&
1222 (addr[3] & ipsub->mask[3]) == ipsub->sub[3]) {
1223 return 1;
1224 }
1225 }
1226#else
1227 if ((sa->sa.sin.sin_addr.s_addr & ipsub->mask[0]) == ipsub->sub[0]) {
1228 return 1;
1229 }
1230#endif /* APR_HAVE_IPV6 */
1231 return 0; /* no match */
1232}
1233
1235 const char *zone_id)
1236{
1237#if !APR_HAVE_IPV6 || !defined(HAVE_IF_NAMETOINDEX)
1238 return APR_ENOTIMPL;
1239#else
1240 unsigned int idx;
1241
1242 if (sa->family != APR_INET6
1243 || !IN6_IS_ADDR_LINKLOCAL((struct in6_addr *)sa->ipaddr_ptr)) {
1244 return APR_EBADIP;
1245 }
1246
1248 if (idx) {
1249 sa->sa.sin6.sin6_scope_id = idx;
1250 return APR_SUCCESS;
1251 }
1252
1253 if (errno != ENODEV) {
1254 return errno;
1255 }
1256 else {
1257 char *endptr;
1259
1260 if (*endptr != '\0' || errno || i < 1 || i > APR_INT16_MAX) {
1261 return APR_EGENERAL;
1262 }
1263
1264 sa->sa.sin6.sin6_scope_id = (unsigned int) i;
1265 return APR_SUCCESS;
1266 }
1267#endif
1268}
1269
1271 const char **name,
1272 apr_uint32_t *id,
1273 apr_pool_t *p)
1274{
1275#if !APR_HAVE_IPV6 || !defined(HAVE_IF_INDEXTONAME)
1276 return APR_ENOTIMPL;
1277#else
1278 if (sa->family != APR_INET6 || !sa->sa.sin6.sin6_scope_id) {
1279 return APR_EBADIP;
1280 }
1281
1282 if (name) {
1283 char *buf = apr_palloc(p, IF_NAMESIZE);
1284 if (if_indextoname(sa->sa.sin6.sin6_scope_id, buf) == NULL)
1285 return errno;
1286 *name = buf;
1287 }
1288
1289 if (id) *id = sa->sa.sin6.sin6_scope_id;
1290
1291 return APR_SUCCESS;
1292#endif
1293}
const char apr_size_t len
Definition ap_regex.h:187
#define getpeername
#define getsockname
APR general purpose library routines.
apr_size_t const unsigned char unsigned int unsigned int d
Definition apr_siphash.h:72
APR Strings library.
APR Standard Headers Support.
const char * hostname
const unsigned char * buf
Definition util_md5.h:50
const char apr_port_t port
Definition http_vhost.h:125
#define APR_EGENERAL
Definition apr_errno.h:313
#define APR_ENOSPC
Definition apr_errno.h:676
#define APR_EBADMASK
Definition apr_errno.h:319
#define APR_ENOTIMPL
Definition apr_errno.h:476
#define APR_EBADIP
Definition apr_errno.h:317
#define APR_ENOENT
Definition apr_errno.h:662
#define APR_EINVAL
Definition apr_errno.h:711
apr_pool_t const char apr_dbd_t const char ** error
Definition apr_dbd.h:143
apr_pool_t apr_dbd_t apr_dbd_results_t ** res
Definition apr_dbd.h:287
const char * src
Definition apr_encode.h:167
const char apr_ssize_t int flags
Definition apr_encode.h:168
apr_redis_t * rc
Definition apr_redis.h:173
const void apr_status_t(*) apr_status_t(* APR_DECLARE)(void) apr_pool_pre_cleanup_register(apr_pool_t *p
Definition apr_pools.h:646
apr_size_t size
#define apr_isdigit(c)
Definition apr_lib.h:209
#define APR_OS_START_EAIERR
Definition apr_errno.h:180
#define apr_get_netos_error()
Definition apr_errno.h:1222
#define APR_SUCCESS
Definition apr_errno.h:225
#define APR_OS_START_SYSERR
Definition apr_errno.h:185
int apr_status_t
Definition apr_errno.h:44
void * memchr(const void *s, int c, size_t n)
#define memmove(a, b, c)
apr_sockaddr_t * addr
const char * ipstr
apr_sockaddr_t * sockaddr
apr_interface_e
int family
apr_interface_e which
apr_socket_t * sock
const apr_sockaddr_t * addr2
#define APR_IPV4_ADDR_OK
const char * servname
apr_sockaddr_t * sa
apr_interval_time_t t
apr_size_t buflen
#define APR_UNIX
apr_uint16_t apr_port_t
#define APR_UNSPEC
#define APR_INET
char ** scope_id
const char const char * mask_or_numbits
#define APR_IPV6_ADDR_OK
const char * zone_id
@ APR_LOCAL
@ APR_REMOTE
#define apr_pcalloc(p, size)
Definition apr_pools.h:465
const char * s
Definition apr_strings.h:95
apr_pool_t * p
Definition md_event.c:32
return NULL
Definition mod_so.c:359
int i
Definition mod_so.c:347
const char * apr_inet_ntop(int af, const void *src, char *dst, apr_size_t size)
Definition inet_ntop.c:74
int apr_inet_pton(int af, const char *src, void *dst)
Definition inet_pton.c:79
char * name
apr_uint32_t sub[1]
Definition sockaddr.c:45
apr_uint32_t mask[1]
Definition sockaddr.c:46
union apr_sockaddr_t::@55 sa
apr_pool_t * pool
struct sockaddr_in sin
apr_int32_t family
apr_socklen_t salen
apr_sockaddr_t * remote_addr
apr_sockaddr_t * local_addr
apr_uint32_t s_addr
#define SET_H_ERRNO(newval)
Definition sockaddr.c:54
static apr_status_t parse_ip(apr_ipsubnet_t *ipsub, const char *ipstr, int network_allowed)
Definition sockaddr.c:1055
#define V4MAPPED_EQUAL(a, b)
Definition sockaddr.c:934
static apr_status_t find_addresses(apr_sockaddr_t **sa, const char *hostname, apr_int32_t family, apr_port_t port, apr_int32_t flags, apr_pool_t *p)
Definition sockaddr.c:538
static void fix_subnet(apr_ipsubnet_t *ipsub)
Definition sockaddr.c:1119
void apr_sockaddr_vars_set(apr_sockaddr_t *addr, int family, apr_port_t port)
Definition sockaddr.c:180
static apr_status_t get_remote_addr(apr_socket_t *sock)
Definition sockaddr.c:103
#define SCOPE_OR_ZERO(sa_)
Definition sockaddr.c:946
static apr_status_t parse_network(apr_ipsubnet_t *ipsub, const char *network)
Definition sockaddr.c:997
static int looks_like_ip(const char *ipstr)
Definition sockaddr.c:1102
static apr_status_t get_local_addr(apr_socket_t *sock)
Definition sockaddr.c:88
#define str
typedef int(WSAAPI *apr_winapi_fpt_WSAPoll)(IN OUT LPWSAPOLLFD fdArray