17 #include "apr_arch_networkio.h" 22 #include "apr_private.h" 32 #if defined(HAVE_IF_INDEXTONAME) && defined(_MSC_VER) 36 #define APR_WANT_STRFUNC 50 #if !defined(NETWARE) && !defined(WIN32) 51 #ifdef HAVE_SET_H_ERRNO 52 #define SET_H_ERRNO(newval) set_h_errno(newval) 54 #define SET_H_ERRNO(newval) h_errno = (newval) 57 #define SET_H_ERRNO(newval) 60 #if APR_HAS_THREADS && !defined(GETHOSTBYNAME_IS_THREAD_SAFE) && \ 61 defined(HAVE_GETHOSTBYNAME_R) 66 #define GETHOSTBYNAME_BUFLEN 512 73 #define AIX_SERVNAME_HACK 1 75 #define AIX_SERVNAME_HACK 0 82 static void *getservbyname(
const char *
name,
const char *proto)
128 &&
buflen > strlen(
"::ffff:")) {
134 strlen(
buf + strlen(
"::ffff:"))+1);
140 #ifdef HAVE_IF_INDEXTONAME 144 char scbuf[IF_NAMESIZE], *
p =
buf + strlen(
buf);
155 memcpy(
p, scbuf, strlen(scbuf) + 1);
180 #if AIX_SERVNAME_HACK 187 addr->
salen =
sizeof(
struct sockaddr_in);
193 else if (
family == APR_INET6) {
194 addr->
salen =
sizeof(
struct sockaddr_in6);
200 #if APR_HAVE_SOCKADDR_UN 202 addr->
salen =
sizeof(
struct sockaddr_un);
247 const char *ch, *lastchar;
258 ch = lastchar =
str + strlen(
str) - 1;
264 big_port = atoi(
str);
265 if (big_port < 1 || big_port > 65535) {
272 if (*ch ==
':' && ch < lastchar) {
276 big_port = atoi(ch + 1);
277 if (big_port < 1 || big_port > 65535) {
285 addrlen = lastchar -
str + 1;
293 const char *end_bracket =
memchr(
str,
']', addrlen);
294 struct in6_addr ipaddr;
295 const char *scope_delim;
297 if (!end_bracket || end_bracket != lastchar) {
305 if (scope_delim == end_bracket - 1) {
309 addrlen = scope_delim -
str - 1;
310 *
scope_id = apr_pstrmemdup(
p, scope_delim + 1, end_bracket - scope_delim - 1);
313 addrlen = addrlen - 2;
316 *
addr = apr_pstrmemdup(
p,
str + 1, addrlen);
330 *
addr = apr_pstrmemdup(
p,
str, addrlen);
335 #if defined(HAVE_GETADDRINFO) 342 struct addrinfo hints, *ai, *ai_list;
347 memset(&hints, 0,
sizeof(hints));
349 hints.ai_socktype = SOCK_STREAM;
350 #ifdef HAVE_GAI_ADDRCONFIG 355 hints.ai_flags = AI_ADDRCONFIG;
364 hints.ai_flags |= AI_ALL;
372 hints.ai_flags |= AI_PASSIVE;
384 #ifdef AI_NUMERICHOST 385 hints.ai_flags |= AI_NUMERICHOST;
388 #if AIX_SERVNAME_HACK 398 #ifdef HAVE_GAI_ADDRCONFIG 415 #ifdef EAI_ADDRFAMILY
416 || error == EAI_ADDRFAMILY
419 hints.ai_flags &= ~AI_ADDRCONFIG;
427 if (error == EAI_SYSTEM) {
437 #if defined(NEGATIVE_EAI) 454 if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6) {
456 if (ai->ai_family != AF_INET) {
465 memcpy(&new_sa->
sa, ai->ai_addr, ai->ai_addrlen);
476 prev_sa->
next = new_sa;
482 freeaddrinfo(ai_list);
484 if (prev_sa == NULL) {
537 #if APR_HAS_THREADS && !defined(GETHOSTBYNAME_IS_THREAD_SAFE) && \ 538 defined(HAVE_GETHOSTBYNAME_R) && !defined(BEOS) 539 #ifdef GETHOSTBYNAME_R_HOSTENT_DATA 540 struct hostent_data hd;
544 char tmp[GETHOSTBYNAME_BUFLEN];
551 const char *orig_hostname =
hostname;
562 addr_list[0] = (
char *)&ipaddr;
564 hs.h_addr_list = (
char **)addr_list;
568 #if APR_HAS_THREADS && !defined(GETHOSTBYNAME_IS_THREAD_SAFE) && \ 569 defined(HAVE_GETHOSTBYNAME_R) && !defined(BEOS) 570 #if defined(GETHOSTBYNAME_R_HOSTENT_DATA) 572 gethostbyname_r(
hostname, &hs, &hd);
575 #if defined(GETHOSTBYNAME_R_GLIBC2) 577 gethostbyname_r(
hostname, &hs, tmp, GETHOSTBYNAME_BUFLEN - 1,
581 hp = gethostbyname_r(
hostname, &hs, tmp, GETHOSTBYNAME_BUFLEN - 1,
603 while (hp->h_addr_list[curaddr]) {
607 new_sa->
sa.
sin.sin_addr = *(
struct in_addr *)hp->h_addr_list[curaddr];
612 new_sa->
hostname = apr_pstrdup(
p, orig_hostname);
618 prev_sa->
next = new_sa;
625 if (prev_sa == NULL) {
659 #if APR_HAVE_SOCKADDR_UN 663 apr_cpystrn((*sa)->sa.unx.sun_path,
hostname,
664 sizeof((*sa)->sa.unx.sun_path));
665 (*sa)->hostname = apr_pstrdup(
p,
hostname);
667 (*sa)->sa.unx.sun_family =
APR_UNIX;
668 (*sa)->salen =
sizeof(
struct sockaddr_un);
669 (*sa)->addr_str_len =
sizeof((*sa)->sa.unx.sun_path);
670 (*sa)->ipaddr_ptr = &((*sa)->sa.unx.sun_path);
671 (*sa)->ipaddr_len = (*sa)->addr_str_len;
703 for (*dst = d = NULL,
s =
src;
s;
s =
s->next) {
705 *dst = d = apr_pmemdup(
p,
s,
sizeof *
s);
708 d = d->
next = apr_pmemdup(
p,
s,
sizeof *
s);
711 if (
s ==
src ||
s->hostname !=
src->hostname) {
719 if (
s ==
src ||
s->servname !=
src->servname) {
736 #if defined(HAVE_GETNAMEINFO) 738 #if defined(NI_MAXHOST) 739 char tmphostname[NI_MAXHOST];
741 char tmphostname[256];
757 IN6_IS_ADDR_V4MAPPED(&
sockaddr->
sa.sin6.sin6_addr)) {
758 struct sockaddr_in tmpsa;
759 tmpsa.sin_family = AF_INET;
763 tmpsa.sin_len =
sizeof(tmpsa);
766 rc = getnameinfo((
const struct sockaddr *)&tmpsa,
sizeof(tmpsa),
767 tmphostname,
sizeof(tmphostname), NULL, 0,
770 #if APR_HAVE_SOCKADDR_UN 779 tmphostname,
sizeof(tmphostname), NULL, 0,
786 if (rc == EAI_SYSTEM) {
799 #if defined(NEGATIVE_EAI) 800 if (rc < 0) rc = -rc;
809 #if APR_HAS_THREADS && !defined(GETHOSTBYADDR_IS_THREAD_SAFE) && \ 810 defined(HAVE_GETHOSTBYADDR_R) && !defined(BEOS) 811 #ifdef GETHOSTBYNAME_R_HOSTENT_DATA 812 struct hostent_data hd;
814 char tmp[GETHOSTBYNAME_BUFLEN];
817 struct hostent hs, *hptr;
819 #if defined(GETHOSTBYNAME_R_HOSTENT_DATA) 822 sizeof(
struct in_addr), AF_INET, &hs, &hd);
825 #if defined(GETHOSTBYNAME_R_GLIBC2) 828 sizeof(
struct in_addr), AF_INET,
829 &hs, tmp, GETHOSTBYNAME_BUFLEN - 1, &hptr, &hosterror);
833 sizeof(
struct in_addr), AF_INET,
834 &hs, tmp, GETHOSTBYNAME_BUFLEN, &hosterror);
842 struct hostent *hptr;
844 sizeof(
struct in_addr), AF_INET);
865 #if APR_HAS_THREADS && !defined(GETSERVBYNAME_IS_THREAD_SAFE) && \ 866 defined(HAVE_GETSERVBYNAME_R) && \ 867 (defined(GETSERVBYNAME_R_GLIBC2) || defined(GETSERVBYNAME_R_SOLARIS) || \ 868 defined(GETSERVBYNAME_R_OSF1)) 870 #if defined(GETSERVBYNAME_R_OSF1) 871 struct servent_data sed;
873 memset(&sed, 0,
sizeof(sed));
875 #if defined(GETSERVBYNAME_R_GLIBC2) 887 #if APR_HAS_THREADS && !defined(GETSERVBYNAME_IS_THREAD_SAFE) && \ 888 defined(HAVE_GETSERVBYNAME_R) && \ 889 (defined(GETSERVBYNAME_R_GLIBC2) || defined(GETSERVBYNAME_R_SOLARIS) || \ 890 defined(GETSERVBYNAME_R_OSF1)) 891 #if defined(GETSERVBYNAME_R_GLIBC2) 893 &se,
buf,
sizeof(
buf), &res) == 0 && res != NULL) {
899 #elif defined(GETSERVBYNAME_R_SOLARIS) 900 if (getservbyname_r(
servname, NULL, &se,
buf,
sizeof(
buf)) != NULL) {
906 #elif defined(GETSERVBYNAME_R_OSF1) 907 if (getservbyname_r(
servname, NULL, &se, &sed) == 0) {
915 if ((se = getservbyname(
servname, NULL)) != NULL){
925 #define V4MAPPED_EQUAL(a,b) \ 926 ((a)->sa.sin.sin_family == AF_INET && \ 927 (b)->sa.sin.sin_family == AF_INET6 && \ 928 IN6_IS_ADDR_V4MAPPED((struct in6_addr *)(b)->ipaddr_ptr) && \ 929 !memcmp((a)->ipaddr_ptr, \ 930 &((struct in6_addr *)(b)->ipaddr_ptr)->s6_addr[12], \ 934 #define SCOPE_OR_ZERO(sa_) ((sa_)->family != AF_INET6 ? 0 : \ 935 ((sa_)->sa.sin6.sin6_scope_id)) 937 #define SCOPE_OR_ZERO(sa_) (0) 961 static const char inaddr_any[
963 sizeof(
struct in6_addr)
979 if (!memcmp(inaddr_any, v4,
sizeof *v4)) {
994 char buf[
sizeof "255.255.255.255"];
996 if (strlen(network) <
sizeof buf) {
997 strcpy(
buf, network);
1026 if (octet < 0 || octet > 255) {
1029 ipsub->
sub[0] |= octet << shift;
1030 ipsub->
mask[0] |= 0xFFUL << shift;
1034 ipsub->
sub[0] = ntohl(ipsub->
sub[0]);
1035 ipsub->
mask[0] = ntohl(ipsub->
mask[0]);
1065 if (IN6_IS_ADDR_V4MAPPED((
struct in6_addr *)ipsub->
sub)) {
1072 ipsub->
family = AF_INET6;
1083 if (network_allowed) {
1095 if (strlen(
ipstr) == 0) {
1099 if (strchr(
ipstr,
':')) {
1107 return (*
ipstr ==
'\0');
1117 for (i = 0; i <
sizeof ipsub->
mask /
sizeof(apr_int32_t); i++) {
1118 ipsub->
sub[i] &= ipsub->
mask[i];
1128 long bits, maxbits = 32;
1142 memset((*ipsub)->mask, 0xFF, sizeof (*ipsub)->mask);
1151 if ((*ipsub)->family == AF_INET6) {
1156 if (*endptr ==
'\0' && bits > 0 && bits <= maxbits) {
1159 apr_int32_t cur_bit_value;
1161 memset((*ipsub)->mask, 0, sizeof (*ipsub)->mask);
1163 (*ipsub)->mask[cur_entry] = 0xFFFFFFFF;
1167 cur_bit_value = 0x80000000;
1169 (*ipsub)->mask[cur_entry] |= cur_bit_value;
1173 (*ipsub)->mask[cur_entry] = htonl((*ipsub)->mask[cur_entry]);
1176 (*ipsub)->family == AF_INET) {
1196 if (ipsub->
family == AF_INET &&
1197 ((
sa->
sa.
sin.sin_addr.s_addr & ipsub->
mask[0]) == ipsub->
sub[0])) {
1201 else if (IN6_IS_ADDR_V4MAPPED((
struct in6_addr *)
sa->
ipaddr_ptr)) {
1202 if (ipsub->
family == AF_INET &&
1210 if ((
addr[0] & ipsub->
mask[0]) == ipsub->
sub[0] &&
1218 if ((
sa->
sa.
sin.sin_addr.s_addr & ipsub->
mask[0]) == ipsub->
sub[0]) {
1228 #if !APR_HAVE_IPV6 || !defined(HAVE_IF_NAMETOINDEX) 1234 || !IN6_IS_ADDR_LINKLOCAL((
struct in6_addr *)
sa->
ipaddr_ptr)) {
1240 sa->
sa.sin6.sin6_scope_id = idx;
1244 if (errno != ENODEV) {
1249 apr_int64_t i = apr_strtoi64(
zone_id, &endptr, 10);
1251 if (*endptr !=
'\0' || errno || i < 1 || i > APR_INT16_MAX) {
1255 sa->
sa.sin6.sin6_scope_id = (
unsigned int) i;
1266 #if !APR_HAVE_IPV6 || !defined(HAVE_IF_INDEXTONAME) 1269 if (
sa->
family != APR_INET6 || !
sa->
sa.sin6.sin6_scope_id) {
1274 char *
buf = apr_palloc(
p, IF_NAMESIZE);
1280 if (
id) *
id =
sa->
sa.sin6.sin6_scope_id;