You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
285 lines
8.2 KiB
285 lines
8.2 KiB
commit e05e5889b8a307fe4be55b03bcbd7a1c62fc2f2d |
|
Author: Siddhesh Poyarekar <siddhesh@sourceware.org> |
|
Date: Thu Feb 10 13:27:11 2022 +0530 |
|
|
|
gaih_inet: Simplify service resolution |
|
|
|
Refactor the code to split out the service resolution code into a |
|
separate function. Allocate the service tuples array just once to the |
|
size of the typeproto array, thus avoiding the unnecessary pointer |
|
chasing and stack allocations. |
|
|
|
Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org> |
|
Reviewed-by: DJ Delorie <dj@redhat.com> |
|
(cherry picked from commit 8d6cf99f2fb81a097f9334c125e5c23604af1a98) |
|
|
|
diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c |
|
index ed70e6cb3944d219..8c78ef9570fe0f58 100644 |
|
--- a/sysdeps/posix/getaddrinfo.c |
|
+++ b/sysdeps/posix/getaddrinfo.c |
|
@@ -100,14 +100,12 @@ struct gaih_service |
|
|
|
struct gaih_servtuple |
|
{ |
|
- struct gaih_servtuple *next; |
|
int socktype; |
|
int protocol; |
|
int port; |
|
+ bool set; |
|
}; |
|
|
|
-static const struct gaih_servtuple nullserv; |
|
- |
|
|
|
struct gaih_typeproto |
|
{ |
|
@@ -180,11 +178,11 @@ gaih_inet_serv (const char *servicename, const struct gaih_typeproto *tp, |
|
} |
|
while (r); |
|
|
|
- st->next = NULL; |
|
st->socktype = tp->socktype; |
|
st->protocol = ((tp->protoflag & GAI_PROTO_PROTOANY) |
|
? req->ai_protocol : tp->protocol); |
|
st->port = s->s_port; |
|
+ st->set = true; |
|
|
|
return 0; |
|
} |
|
@@ -375,20 +373,11 @@ process_canonname (const struct addrinfo *req, const char *orig_name, |
|
} |
|
|
|
static int |
|
-gaih_inet (const char *name, const struct gaih_service *service, |
|
- const struct addrinfo *req, struct addrinfo **pai, |
|
- unsigned int *naddrs, struct scratch_buffer *tmpbuf) |
|
+get_servtuples (const struct gaih_service *service, const struct addrinfo *req, |
|
+ struct gaih_servtuple *st, struct scratch_buffer *tmpbuf) |
|
{ |
|
+ int i; |
|
const struct gaih_typeproto *tp = gaih_inet_typeproto; |
|
- struct gaih_servtuple *st = (struct gaih_servtuple *) &nullserv; |
|
- struct gaih_addrtuple *at = NULL; |
|
- bool got_ipv6 = false; |
|
- char *canon = NULL; |
|
- const char *orig_name = name; |
|
- |
|
- /* Reserve stack memory for the scratch buffer in the getaddrinfo |
|
- function. */ |
|
- size_t alloca_used = sizeof (struct scratch_buffer); |
|
|
|
if (req->ai_protocol || req->ai_socktype) |
|
{ |
|
@@ -410,98 +399,88 @@ gaih_inet (const char *name, const struct gaih_service *service, |
|
} |
|
} |
|
|
|
- int port = 0; |
|
- if (service != NULL) |
|
+ if (service != NULL && (tp->protoflag & GAI_PROTO_NOSERVICE) != 0) |
|
+ return -EAI_SERVICE; |
|
+ |
|
+ if (service == NULL || service->num >= 0) |
|
{ |
|
- if ((tp->protoflag & GAI_PROTO_NOSERVICE) != 0) |
|
- return -EAI_SERVICE; |
|
+ int port = service != NULL ? htons (service->num) : 0; |
|
|
|
- if (service->num < 0) |
|
+ if (req->ai_socktype || req->ai_protocol) |
|
{ |
|
- if (tp->name[0]) |
|
- { |
|
- st = (struct gaih_servtuple *) |
|
- alloca_account (sizeof (struct gaih_servtuple), alloca_used); |
|
- |
|
- int rc = gaih_inet_serv (service->name, tp, req, st, tmpbuf); |
|
- if (__glibc_unlikely (rc != 0)) |
|
- return rc; |
|
- } |
|
- else |
|
- { |
|
- struct gaih_servtuple **pst = &st; |
|
- for (tp++; tp->name[0]; tp++) |
|
- { |
|
- struct gaih_servtuple *newp; |
|
+ st[0].socktype = tp->socktype; |
|
+ st[0].protocol = ((tp->protoflag & GAI_PROTO_PROTOANY) |
|
+ ? req->ai_protocol : tp->protocol); |
|
+ st[0].port = port; |
|
+ st[0].set = true; |
|
|
|
- if ((tp->protoflag & GAI_PROTO_NOSERVICE) != 0) |
|
- continue; |
|
+ return 0; |
|
+ } |
|
|
|
- if (req->ai_socktype != 0 |
|
- && req->ai_socktype != tp->socktype) |
|
- continue; |
|
- if (req->ai_protocol != 0 |
|
- && !(tp->protoflag & GAI_PROTO_PROTOANY) |
|
- && req->ai_protocol != tp->protocol) |
|
- continue; |
|
+ /* Neither socket type nor protocol is set. Return all socket types |
|
+ we know about. */ |
|
+ for (i = 0, ++tp; tp->name[0]; ++tp) |
|
+ if (tp->defaultflag) |
|
+ { |
|
+ st[i].socktype = tp->socktype; |
|
+ st[i].protocol = tp->protocol; |
|
+ st[i].port = port; |
|
+ st[i++].set = true; |
|
+ } |
|
|
|
- newp = (struct gaih_servtuple *) |
|
- alloca_account (sizeof (struct gaih_servtuple), |
|
- alloca_used); |
|
+ return 0; |
|
+ } |
|
|
|
- if (gaih_inet_serv (service->name, |
|
- tp, req, newp, tmpbuf) != 0) |
|
- continue; |
|
+ if (tp->name[0]) |
|
+ return gaih_inet_serv (service->name, tp, req, st, tmpbuf); |
|
|
|
- *pst = newp; |
|
- pst = &(newp->next); |
|
- } |
|
- if (st == (struct gaih_servtuple *) &nullserv) |
|
- return -EAI_SERVICE; |
|
- } |
|
- } |
|
- else |
|
- { |
|
- port = htons (service->num); |
|
- goto got_port; |
|
- } |
|
- } |
|
- else |
|
+ for (i = 0, tp++; tp->name[0]; tp++) |
|
{ |
|
- got_port: |
|
+ if ((tp->protoflag & GAI_PROTO_NOSERVICE) != 0) |
|
+ continue; |
|
|
|
- if (req->ai_socktype || req->ai_protocol) |
|
- { |
|
- st = alloca_account (sizeof (struct gaih_servtuple), alloca_used); |
|
- st->next = NULL; |
|
- st->socktype = tp->socktype; |
|
- st->protocol = ((tp->protoflag & GAI_PROTO_PROTOANY) |
|
- ? req->ai_protocol : tp->protocol); |
|
- st->port = port; |
|
- } |
|
- else |
|
- { |
|
- /* Neither socket type nor protocol is set. Return all socket types |
|
- we know about. */ |
|
- struct gaih_servtuple **lastp = &st; |
|
- for (++tp; tp->name[0]; ++tp) |
|
- if (tp->defaultflag) |
|
- { |
|
- struct gaih_servtuple *newp; |
|
+ if (req->ai_socktype != 0 |
|
+ && req->ai_socktype != tp->socktype) |
|
+ continue; |
|
+ if (req->ai_protocol != 0 |
|
+ && !(tp->protoflag & GAI_PROTO_PROTOANY) |
|
+ && req->ai_protocol != tp->protocol) |
|
+ continue; |
|
|
|
- newp = alloca_account (sizeof (struct gaih_servtuple), |
|
- alloca_used); |
|
- newp->next = NULL; |
|
- newp->socktype = tp->socktype; |
|
- newp->protocol = tp->protocol; |
|
- newp->port = port; |
|
+ if (gaih_inet_serv (service->name, |
|
+ tp, req, &st[i], tmpbuf) != 0) |
|
+ continue; |
|
|
|
- *lastp = newp; |
|
- lastp = &newp->next; |
|
- } |
|
- } |
|
+ i++; |
|
} |
|
|
|
+ if (!st[0].set) |
|
+ return -EAI_SERVICE; |
|
+ |
|
+ return 0; |
|
+} |
|
+ |
|
+static int |
|
+gaih_inet (const char *name, const struct gaih_service *service, |
|
+ const struct addrinfo *req, struct addrinfo **pai, |
|
+ unsigned int *naddrs, struct scratch_buffer *tmpbuf) |
|
+{ |
|
+ struct gaih_servtuple st[sizeof (gaih_inet_typeproto) |
|
+ / sizeof (struct gaih_typeproto)] = {0}; |
|
+ |
|
+ struct gaih_addrtuple *at = NULL; |
|
+ bool got_ipv6 = false; |
|
+ char *canon = NULL; |
|
+ const char *orig_name = name; |
|
+ |
|
+ /* Reserve stack memory for the scratch buffer in the getaddrinfo |
|
+ function. */ |
|
+ size_t alloca_used = sizeof (struct scratch_buffer); |
|
+ |
|
+ int rc; |
|
+ if ((rc = get_servtuples (service, req, st, tmpbuf)) != 0) |
|
+ return rc; |
|
+ |
|
bool malloc_name = false; |
|
struct gaih_addrtuple *addrmem = NULL; |
|
int result = 0; |
|
@@ -1083,7 +1062,6 @@ gaih_inet (const char *name, const struct gaih_service *service, |
|
if ((result = process_canonname (req, orig_name, &canon)) != 0) |
|
goto free_and_return; |
|
|
|
- struct gaih_servtuple *st2; |
|
struct gaih_addrtuple *at2 = at; |
|
size_t socklen; |
|
sa_family_t family; |
|
@@ -1109,7 +1087,7 @@ gaih_inet (const char *name, const struct gaih_service *service, |
|
else |
|
socklen = sizeof (struct sockaddr_in); |
|
|
|
- for (st2 = st; st2 != NULL; st2 = st2->next) |
|
+ for (int i = 0; st[i].set; i++) |
|
{ |
|
struct addrinfo *ai; |
|
ai = *pai = malloc (sizeof (struct addrinfo) + socklen); |
|
@@ -1121,8 +1099,8 @@ gaih_inet (const char *name, const struct gaih_service *service, |
|
|
|
ai->ai_flags = req->ai_flags; |
|
ai->ai_family = family; |
|
- ai->ai_socktype = st2->socktype; |
|
- ai->ai_protocol = st2->protocol; |
|
+ ai->ai_socktype = st[i].socktype; |
|
+ ai->ai_protocol = st[i].protocol; |
|
ai->ai_addrlen = socklen; |
|
ai->ai_addr = (void *) (ai + 1); |
|
|
|
@@ -1144,7 +1122,7 @@ gaih_inet (const char *name, const struct gaih_service *service, |
|
struct sockaddr_in6 *sin6p = |
|
(struct sockaddr_in6 *) ai->ai_addr; |
|
|
|
- sin6p->sin6_port = st2->port; |
|
+ sin6p->sin6_port = st[i].port; |
|
sin6p->sin6_flowinfo = 0; |
|
memcpy (&sin6p->sin6_addr, |
|
at2->addr, sizeof (struct in6_addr)); |
|
@@ -1154,7 +1132,7 @@ gaih_inet (const char *name, const struct gaih_service *service, |
|
{ |
|
struct sockaddr_in *sinp = |
|
(struct sockaddr_in *) ai->ai_addr; |
|
- sinp->sin_port = st2->port; |
|
+ sinp->sin_port = st[i].port; |
|
memcpy (&sinp->sin_addr, |
|
at2->addr, sizeof (struct in_addr)); |
|
memset (sinp->sin_zero, '\0', sizeof (sinp->sin_zero));
|
|
|