Deleted Added
full compact
sockaddr.c (302408) sockaddr.c (362181)
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

--- 11 unchanged lines hidden (view full) ---

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
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

--- 11 unchanged lines hidden (view full) ---

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)
33#include "arch/win32/apr_arch_misc.h"
34#endif
35
28#define APR_WANT_STRFUNC
29#include "apr_want.h"
30
31struct 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];

--- 84 unchanged lines hidden (view full) ---

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 }
36#define APR_WANT_STRFUNC
37#include "apr_want.h"
38
39struct apr_ipsubnet_t {
40 int family;
41#if APR_HAVE_IPV6
42 apr_uint32_t sub[4]; /* big enough for IPv4 and IPv6 addresses */
43 apr_uint32_t mask[4];

--- 84 unchanged lines hidden (view full) ---

128 && buflen > strlen("::ffff:")) {
129 /* This is an IPv4-mapped IPv6 address; drop the leading
130 * part of the address string so we're left with the familiar
131 * IPv4 format.
132 */
133 memmove(buf, buf + strlen("::ffff:"),
134 strlen(buf + strlen("::ffff:"))+1);
135 }
128#endif
136
129 /* ensure NUL termination if the buffer is too short */
130 buf[buflen-1] = '\0';
137 /* ensure NUL termination if the buffer is too short */
138 buf[buflen-1] = '\0';
139
140#ifdef HAVE_IF_INDEXTONAME
141 /* Append scope name for link-local addresses. */
142 if (sockaddr->family == AF_INET6
143 && IN6_IS_ADDR_LINKLOCAL((struct in6_addr *)sockaddr->ipaddr_ptr)) {
144 char scbuf[IF_NAMESIZE], *p = buf + strlen(buf);
145
146 if (if_indextoname(sockaddr->sa.sin6.sin6_scope_id, scbuf) == scbuf) {
147 /* Space check, need room for buf + '%' + scope + '\0'.
148 * Assert: buflen >= strlen(buf) + strlen(scbuf) + 2
149 * Equiv: buflen >= (p-buf) + strlen(buf) + 2
150 * Thus, fail in inverse condition: */
151 if (buflen < strlen(scbuf) + (p - buf) + 2) {
152 return APR_ENOSPC;
153 }
154 *p++ = '%';
155 memcpy(p, scbuf, strlen(scbuf) + 1);
156 }
157 }
158#endif /* HAVE_IF_INDEXTONAME */
159#endif /* APR_HAVE_IPV6 */
160
131 return APR_SUCCESS;
132}
133
134APR_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);

--- 23 unchanged lines hidden (view full) ---

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
161 return APR_SUCCESS;
162}
163
164APR_DECLARE(apr_status_t) apr_sockaddr_ip_get(char **addr,
165 apr_sockaddr_t *sockaddr)
166{
167 *addr = apr_palloc(sockaddr->pool, sockaddr->addr_str_len);
168 return apr_sockaddr_ip_getbuf(*addr, sockaddr->addr_str_len, sockaddr);

--- 23 unchanged lines hidden (view full) ---

192#if APR_HAVE_IPV6
193 else if (family == APR_INET6) {
194 addr->salen = sizeof(struct sockaddr_in6);
195 addr->addr_str_len = 46;
196 addr->ipaddr_ptr = &(addr->sa.sin6.sin6_addr);
197 addr->ipaddr_len = sizeof(struct in6_addr);
198 }
199#endif
200#if APR_HAVE_SOCKADDR_UN
201 else if (family == APR_UNIX) {
202 addr->salen = sizeof(struct sockaddr_un);
203 addr->addr_str_len = sizeof(addr->sa.unx.sun_path);;
204 addr->ipaddr_ptr = &(addr->sa.unx.sun_path);
205 addr->ipaddr_len = addr->addr_str_len;
206 }
207#endif
170}
171
172APR_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) {

--- 86 unchanged lines hidden (view full) ---

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;
208}
209
210APR_DECLARE(apr_status_t) apr_socket_addr_get(apr_sockaddr_t **sa,
211 apr_interface_e which,
212 apr_socket_t *sock)
213{
214 if (which == APR_LOCAL) {
215 if (sock->local_interface_unknown || sock->local_port_unknown) {

--- 86 unchanged lines hidden (view full) ---

302 /* handle scope id; this is the only context where it is allowed */
303 scope_delim = memchr(str, '%', addrlen);
304 if (scope_delim) {
305 if (scope_delim == end_bracket - 1) { /* '%' without scope id */
306 *port = 0;
307 return APR_EINVAL;
308 }
309 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';
310 *scope_id = apr_pstrmemdup(p, scope_delim + 1, end_bracket - scope_delim - 1);
275 }
276 else {
277 addrlen = addrlen - 2; /* minus 2 for '[' and ']' */
278 }
279
311 }
312 else {
313 addrlen = addrlen - 2; /* minus 2 for '[' and ']' */
314 }
315
280 *addr = apr_palloc(p, addrlen + 1);
281 memcpy(*addr,
282 str + 1,
283 addrlen);
284 (*addr)[addrlen] = '\0';
316 *addr = apr_pstrmemdup(p, str + 1, addrlen);
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 */
317 if (apr_inet_pton(AF_INET6, *addr, &ipaddr) != 1) {
318 *addr = NULL;
319 *scope_id = NULL;
320 *port = 0;
321 return APR_EINVAL;
322 }
323 }
324 else
325#endif
326 {
327 /* XXX If '%' is not a valid char in a DNS name, we *could* check
328 * for bogus scope ids first.
329 */
298 *addr = apr_palloc(p, addrlen + 1);
299 memcpy(*addr, str, addrlen);
300 (*addr)[addrlen] = '\0';
330 *addr = apr_pstrmemdup(p, str, addrlen);
301 }
302 return APR_SUCCESS;
303}
304
305#if defined(HAVE_GETADDRINFO)
306
307static apr_status_t call_resolver(apr_sockaddr_t **sa,
308 const char *hostname, apr_int32_t family,

--- 308 unchanged lines hidden (view full) ---

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 }
331 }
332 return APR_SUCCESS;
333}
334
335#if defined(HAVE_GETADDRINFO)
336
337static apr_status_t call_resolver(apr_sockaddr_t **sa,
338 const char *hostname, apr_int32_t family,

--- 308 unchanged lines hidden (view full) ---

647 return APR_EINVAL;
648 }
649#if !APR_HAVE_IPV6
650 if (flags & APR_IPV6_ADDR_OK) {
651 return APR_ENOTIMPL;
652 }
653#endif
654 }
655 if (family == APR_UNSPEC && hostname && *hostname == '/') {
656 family = APR_UNIX;
657 }
658 if (family == APR_UNIX) {
659#if APR_HAVE_SOCKADDR_UN
660 if (hostname && *hostname == '/') {
661 *sa = apr_pcalloc(p, sizeof(apr_sockaddr_t));
662 (*sa)->pool = p;
663 apr_cpystrn((*sa)->sa.unx.sun_path, hostname,
664 sizeof((*sa)->sa.unx.sun_path));
665 (*sa)->hostname = apr_pstrdup(p, hostname);
666 (*sa)->family = APR_UNIX;
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;
672
673 return APR_SUCCESS;
674 }
675 else
676#endif
677 {
678 *sa = NULL;
679 return APR_ENOTIMPL;
680 }
681 }
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
682#if !APR_HAVE_IPV6
683 /* What may happen is that APR is not IPv6-enabled, but we're still
684 * going to call getaddrinfo(), so we have to tell the OS we only
685 * want IPv4 addresses back since we won't know what to do with
686 * IPv6 addresses.
687 */
688 if (family == APR_UNSPEC) {
689 family = APR_INET;
690 }
691#endif
692
693 return find_addresses(sa, hostname, family, port, flags, p);
694}
695
696APR_DECLARE(apr_status_t) apr_sockaddr_info_copy(apr_sockaddr_t **dst,
697 const apr_sockaddr_t *src,
698 apr_pool_t *p)
699{
700 apr_sockaddr_t *d;
701 const apr_sockaddr_t *s;
702
703 for (*dst = d = NULL, s = src; s; s = s->next) {
704 if (!d) {
705 *dst = d = apr_pmemdup(p, s, sizeof *s);
706 }
707 else {
708 d = d->next = apr_pmemdup(p, s, sizeof *s);
709 }
710 if (s->hostname) {
711 if (s == src || s->hostname != src->hostname) {
712 d->hostname = apr_pstrdup(p, s->hostname);
713 }
714 else {
715 d->hostname = (*dst)->hostname;
716 }
717 }
718 if (s->servname) {
719 if (s == src || s->servname != src->servname) {
720 d->servname = apr_pstrdup(p, s->servname);
721 }
722 else {
723 d->servname = (*dst)->servname;
724 }
725 }
726 d->pool = p;
727 apr_sockaddr_vars_set(d, s->family, s->port);
728 }
729 return APR_SUCCESS;
730}
731
639APR_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];

--- 22 unchanged lines hidden (view full) ---

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 }
732APR_DECLARE(apr_status_t) apr_getnameinfo(char **hostname,
733 apr_sockaddr_t *sockaddr,
734 apr_int32_t flags)
735{
736#if defined(HAVE_GETNAMEINFO)
737 int rc;
738#if defined(NI_MAXHOST)
739 char tmphostname[NI_MAXHOST];

--- 22 unchanged lines hidden (view full) ---

762#ifdef SIN6_LEN
763 tmpsa.sin_len = sizeof(tmpsa);
764#endif
765
766 rc = getnameinfo((const struct sockaddr *)&tmpsa, sizeof(tmpsa),
767 tmphostname, sizeof(tmphostname), NULL, 0,
768 flags != 0 ? flags : NI_NAMEREQD);
769 }
770#if APR_HAVE_SOCKADDR_UN
771 else if (sockaddr->family == APR_UNIX) {
772 *hostname = sockaddr->hostname;
773 return APR_SUCCESS;
774 }
775#endif
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

--- 141 unchanged lines hidden (view full) ---

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
776 else
777#endif
778 rc = getnameinfo((const struct sockaddr *)&sockaddr->sa, sockaddr->salen,
779 tmphostname, sizeof(tmphostname), NULL, 0,
780 flags != 0 ? flags : NI_NAMEREQD);
781 if (rc != 0) {
782 *hostname = NULL;
783

--- 141 unchanged lines hidden (view full) ---

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], \
931 (a)->ipaddr_len))
932
933#if APR_HAVE_IPV6
934#define SCOPE_OR_ZERO(sa_) ((sa_)->family != AF_INET6 ? 0 : \
935 ((sa_)->sa.sin6.sin6_scope_id))
936#else
937#define SCOPE_OR_ZERO(sa_) (0)
938#endif
939
834APR_DECLARE(int) apr_sockaddr_equal(const apr_sockaddr_t *addr1,
835 const apr_sockaddr_t *addr2)
836{
940APR_DECLARE(int) apr_sockaddr_equal(const apr_sockaddr_t *addr1,
941 const apr_sockaddr_t *addr2)
942{
837 if (addr1->ipaddr_len == addr2->ipaddr_len &&
838 !memcmp(addr1->ipaddr_ptr, addr2->ipaddr_ptr, addr1->ipaddr_len)) {
943 if (addr1->ipaddr_len == addr2->ipaddr_len
944 && !memcmp(addr1->ipaddr_ptr, addr2->ipaddr_ptr, addr1->ipaddr_len)
945 && SCOPE_OR_ZERO(addr1) == SCOPE_OR_ZERO(addr2)) {
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;

--- 133 unchanged lines hidden (view full) ---

980 return APR_EBADIP;
981 }
982 }
983 return APR_SUCCESS;
984}
985
986static int looks_like_ip(const char *ipstr)
987{
946 return 1;
947 }
948#if APR_HAVE_IPV6
949 if (V4MAPPED_EQUAL(addr1, addr2)) {
950 return 1;
951 }
952 if (V4MAPPED_EQUAL(addr2, addr1)) {
953 return 1;

--- 133 unchanged lines hidden (view full) ---

1087 return APR_EBADIP;
1088 }
1089 }
1090 return APR_SUCCESS;
1091}
1092
1093static int looks_like_ip(const char *ipstr)
1094{
1095 if (strlen(ipstr) == 0) {
1096 return 0;
1097 }
1098
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++;

--- 109 unchanged lines hidden (view full) ---

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}
1099 if (strchr(ipstr, ':')) {
1100 /* definitely not a hostname; assume it is intended to be an IPv6 address */
1101 return 1;
1102 }
1103
1104 /* simple IPv4 address string check */
1105 while ((*ipstr == '.') || apr_isdigit(*ipstr))
1106 ipstr++;

--- 109 unchanged lines hidden (view full) ---

1216 }
1217#else
1218 if ((sa->sa.sin.sin_addr.s_addr & ipsub->mask[0]) == ipsub->sub[0]) {
1219 return 1;
1220 }
1221#endif /* APR_HAVE_IPV6 */
1222 return 0; /* no match */
1223}
1224
1225APR_DECLARE(apr_status_t) apr_sockaddr_zone_set(apr_sockaddr_t *sa,
1226 const char *zone_id)
1227{
1228#if !APR_HAVE_IPV6 || !defined(HAVE_IF_NAMETOINDEX)
1229 return APR_ENOTIMPL;
1230#else
1231 unsigned int idx;
1232
1233 if (sa->family != APR_INET6
1234 || !IN6_IS_ADDR_LINKLOCAL((struct in6_addr *)sa->ipaddr_ptr)) {
1235 return APR_EBADIP;
1236 }
1237
1238 idx = if_nametoindex(zone_id);
1239 if (idx) {
1240 sa->sa.sin6.sin6_scope_id = idx;
1241 return APR_SUCCESS;
1242 }
1243
1244 if (errno != ENODEV) {
1245 return errno;
1246 }
1247 else {
1248 char *endptr;
1249 apr_int64_t i = apr_strtoi64(zone_id, &endptr, 10);
1250
1251 if (*endptr != '\0' || errno || i < 1 || i > APR_INT16_MAX) {
1252 return APR_EGENERAL;
1253 }
1254
1255 sa->sa.sin6.sin6_scope_id = (unsigned int) i;
1256 return APR_SUCCESS;
1257 }
1258#endif
1259}
1260
1261APR_DECLARE(apr_status_t) apr_sockaddr_zone_get(const apr_sockaddr_t *sa,
1262 const char **name,
1263 apr_uint32_t *id,
1264 apr_pool_t *p)
1265{
1266#if !APR_HAVE_IPV6 || !defined(HAVE_IF_INDEXTONAME)
1267 return APR_ENOTIMPL;
1268#else
1269 if (sa->family != APR_INET6 || !sa->sa.sin6.sin6_scope_id) {
1270 return APR_EBADIP;
1271 }
1272
1273 if (name) {
1274 char *buf = apr_palloc(p, IF_NAMESIZE);
1275 if (if_indextoname(sa->sa.sin6.sin6_scope_id, buf) == NULL)
1276 return errno;
1277 *name = buf;
1278 }
1279
1280 if (id) *id = sa->sa.sin6.sin6_scope_id;
1281
1282 return APR_SUCCESS;
1283#endif
1284}