diff options
author | Jakub Jelinek <jakub@redhat.com> | 2006-04-24 08:55:46 +0000 |
---|---|---|
committer | Jakub Jelinek <jakub@redhat.com> | 2006-04-24 08:55:46 +0000 |
commit | d0145e03799e484f3a53d79de3b3f34162ee9d3c (patch) | |
tree | d8c51a0952204f9015de0db3319d4c820e8646e0 /sysdeps/posix | |
parent | f5ce81c94cc27035f44d37bffa7f7e08dbce7631 (diff) |
Updated to fedora-glibc-20060424T0820
Diffstat (limited to 'sysdeps/posix')
-rw-r--r-- | sysdeps/posix/getaddrinfo.c | 184 | ||||
-rw-r--r-- | sysdeps/posix/sigset.c | 23 | ||||
-rw-r--r-- | sysdeps/posix/tempname.c | 10 |
3 files changed, 167 insertions, 50 deletions
diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c index 46c66a8f7e..843e60bba3 100644 --- a/sysdeps/posix/getaddrinfo.c +++ b/sysdeps/posix/getaddrinfo.c @@ -68,7 +68,7 @@ extern int __idna_to_unicode_lzlz (const char *input, char **output, #define GAIH_EAI ~(GAIH_OKIFUNSPEC) #ifndef UNIX_PATH_MAX -#define UNIX_PATH_MAX 108 +# define UNIX_PATH_MAX 108 #endif struct gaih_service @@ -177,9 +177,9 @@ gaih_local (const char *name, const struct gaih_service *service, if (! tp->name[0]) { if (req->ai_socktype) - return (GAIH_OKIFUNSPEC | -EAI_SOCKTYPE); + return GAIH_OKIFUNSPEC | -EAI_SOCKTYPE; else - return (GAIH_OKIFUNSPEC | -EAI_SERVICE); + return GAIH_OKIFUNSPEC | -EAI_SERVICE; } } @@ -249,9 +249,10 @@ gaih_local (const char *name, const struct gaih_service *service, } #endif /* 0 */ + static int gaih_inet_serv (const char *servicename, const struct gaih_typeproto *tp, - const struct addrinfo *req, struct gaih_servtuple *st) + const struct addrinfo *req, struct gaih_servtuple *st) { struct servent *s; size_t tmpbuflen = 1024; @@ -362,6 +363,7 @@ typedef enum nss_status (*nss_getcanonname_r) int *errnop, int *h_errnop); extern service_user *__nss_hosts_database attribute_hidden; + static int gaih_inet (const char *name, const struct gaih_service *service, const struct addrinfo *req, struct addrinfo **pai, @@ -389,9 +391,9 @@ gaih_inet (const char *name, const struct gaih_service *service, if (! tp->name[0]) { if (req->ai_socktype) - return (GAIH_OKIFUNSPEC | -EAI_SOCKTYPE); + return GAIH_OKIFUNSPEC | -EAI_SOCKTYPE; else - return (GAIH_OKIFUNSPEC | -EAI_SERVICE); + return GAIH_OKIFUNSPEC | -EAI_SERVICE; } } @@ -399,7 +401,7 @@ gaih_inet (const char *name, const struct gaih_service *service, if (service != NULL) { if ((tp->protoflag & GAI_PROTO_NOSERVICE) != 0) - return (GAIH_OKIFUNSPEC | -EAI_SERVICE); + return GAIH_OKIFUNSPEC | -EAI_SERVICE; if (service->num < 0) { @@ -443,7 +445,7 @@ gaih_inet (const char *name, const struct gaih_service *service, pst = &(newp->next); } if (st == (struct gaih_servtuple *) &nullserv) - return (GAIH_OKIFUNSPEC | -EAI_SERVICE); + return GAIH_OKIFUNSPEC | -EAI_SERVICE; } } else @@ -538,16 +540,10 @@ gaih_inet (const char *name, const struct gaih_service *service, else return -EAI_ADDRFAMILY; - dupname: if (req->ai_flags & AI_CANONNAME) - { - canon = strdup (name); - if (canon == NULL) - return -EAI_MEMORY; - } + canon = name; } - - if (at->family == AF_UNSPEC) + else if (at->family == AF_UNSPEC) { char *namebuf = (char *) name; char *scope_delim = strchr (name, SCOPE_DELIMITER); @@ -595,7 +591,8 @@ gaih_inet (const char *name, const struct gaih_service *service, } } - goto dupname; + if (req->ai_flags & AI_CANONNAME) + canon = name; } } @@ -689,7 +686,7 @@ gaih_inet (const char *name, const struct gaih_service *service, } /* We made requests but they turned out no data. The name is known, though. */ - return (GAIH_OKIFUNSPEC | -EAI_NODATA); + return GAIH_OKIFUNSPEC | -EAI_NODATA; } goto process_list; @@ -756,7 +753,7 @@ gaih_inet (const char *name, const struct gaih_service *service, free (air); if (at->family == AF_UNSPEC) - return (GAIH_OKIFUNSPEC | -EAI_NONAME); + return GAIH_OKIFUNSPEC | -EAI_NONAME; goto process_list; } @@ -898,13 +895,13 @@ gaih_inet (const char *name, const struct gaih_service *service, /* We made requests but they turned out no data. The name is known, though. */ - return (GAIH_OKIFUNSPEC | -EAI_NODATA); + return GAIH_OKIFUNSPEC | -EAI_NODATA; } } process_list: if (at->family == AF_UNSPEC) - return (GAIH_OKIFUNSPEC | -EAI_NONAME); + return GAIH_OKIFUNSPEC | -EAI_NONAME; } else { @@ -1098,6 +1095,7 @@ gaih_inet (const char *name, const struct gaih_service *service, return 0; } +#if 0 static const struct gaih gaih[] = { { PF_INET6, gaih_inet }, @@ -1107,6 +1105,7 @@ static const struct gaih gaih[] = #endif { PF_UNSPEC, NULL } }; +#endif struct sort_result { @@ -1114,6 +1113,7 @@ struct sort_result struct sockaddr_storage source_addr; uint8_t source_addr_len; bool got_source_addr; + uint8_t source_addr_flags; }; @@ -1204,7 +1204,7 @@ static const struct prefixlist default_precedence[] = 96, 20 }, { { .in6_u = { .u6_addr16 = { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0x0000, 0x0000 } } }, - 96, 10 }, + 96, 100 }, { { .in6_u = { .u6_addr16 = { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 } } }, 0, 40 } @@ -1336,8 +1336,16 @@ rfc3484_sort (const void *p1, const void *p2) } - /* Rule 3: Avoid deprecated addresses. - That's something only the kernel could decide. */ + /* Rule 3: Avoid deprecated addresses. */ + if (a1->got_source_addr) + { + if (!(a1->source_addr_flags & in6ai_deprecated) + && (a2->source_addr_flags & in6ai_deprecated)) + return -1; + if ((a1->source_addr_flags & in6ai_deprecated) + && !(a2->source_addr_flags & in6ai_deprecated)) + return 1; + } /* Rule 4: Prefer home addresses. Another thing only the kernel can decide. */ @@ -1372,8 +1380,18 @@ rfc3484_sort (const void *p1, const void *p2) return 1; - /* Rule 7: Prefer native transport. - XXX How to recognize tunnels? */ + /* Rule 7: Prefer native transport. */ + if (a1->got_source_addr) + { + if (!(a1->source_addr_flags & in6ai_temporary) + && (a1->source_addr_flags & in6ai_temporary)) + return -1; + if ((a1->source_addr_flags & in6ai_temporary) + && !(a1->source_addr_flags & in6ai_temporary)) + return -1; + + /* XXX Do we need to check anything beside temporary addresses? */ + } /* Rule 8: Prefer smaller scope. */ @@ -1454,15 +1472,23 @@ rfc3484_sort (const void *p1, const void *p2) } +static int +in6aicmp (const void *p1, const void *p2) +{ + struct in6addrinfo *a1 = (struct in6addrinfo *) p1; + struct in6addrinfo *a2 = (struct in6addrinfo *) p2; + + return memcmp (a1->addr, a2->addr, sizeof (a1->addr)); +} + + int getaddrinfo (const char *name, const char *service, const struct addrinfo *hints, struct addrinfo **pai) { - int i = 0, j = 0, last_i = 0; + int i = 0, last_i = 0; int nresults = 0; - struct addrinfo *p = NULL, **end; - const struct gaih *g = gaih; - const struct gaih *pg = NULL; + struct addrinfo *p = NULL; struct gaih_service gaih_service, *pservice; struct addrinfo local_hints; @@ -1490,15 +1516,23 @@ getaddrinfo (const char *name, const char *service, if ((hints->ai_flags & AI_CANONNAME) && name == NULL) return EAI_BADFLAGS; + struct in6addrinfo *in6ai; + size_t in6ailen; + bool seen_ipv4 = false; + bool seen_ipv6 = false; + /* We might need information about what kind of interfaces are available. + But even if AI_ADDRCONFIG is not used, if the user requested IPv6 + addresses we have to know whether an address is deprecated or + temporary. */ + if ((hints->ai_flags & AI_ADDRCONFIG) || hints->ai_family == PF_UNSPEC + || hints->ai_family == PF_INET6) + /* Determine whether we have IPv4 or IPv6 interfaces or both. We + cannot cache the results since new interfaces could be added at + any time. */ + __check_pf (&seen_ipv4, &seen_ipv6, &in6ai, &in6ailen); + if (hints->ai_flags & AI_ADDRCONFIG) { - /* Determine whether we have IPv4 or IPv6 interfaces or both. - We cannot cache the results since new interfaces could be - added at any time. */ - bool seen_ipv4; - bool seen_ipv6; - __check_pf (&seen_ipv4, &seen_ipv6); - /* Now make a decision on what we return, if anything. */ if (hints->ai_family == PF_UNSPEC && (seen_ipv4 || seen_ipv6)) { @@ -1513,8 +1547,11 @@ getaddrinfo (const char *name, const char *service, } else if ((hints->ai_family == PF_INET && ! seen_ipv4) || (hints->ai_family == PF_INET6 && ! seen_ipv6)) - /* We cannot possibly return a valid answer. */ - return EAI_NONAME; + { + /* We cannot possibly return a valid answer. */ + free (in6ai); + return EAI_NONAME; + } } if (service && service[0]) @@ -1525,7 +1562,10 @@ getaddrinfo (const char *name, const char *service, if (*c != '\0') { if (hints->ai_flags & AI_NUMERICSERV) - return EAI_NONAME; + { + free (in6ai); + return EAI_NONAME; + } gaih_service.num = -1; } @@ -1535,12 +1575,21 @@ getaddrinfo (const char *name, const char *service, else pservice = NULL; + struct addrinfo **end; if (pai) end = &p; else end = NULL; unsigned int naddrs = 0; +#if 0 + /* If we would support more protocols than just IPv4 and IPv6 we + would iterate over a table with appropriate callback functions. + Since we currently only handle IPv4 and IPv6 this is not + necessary. */ + const struct gaih *g = gaih; + const struct gaih *pg = NULL; + int j = 0; while (g->gaih) { if (hints->ai_family == g->family || hints->ai_family == AF_UNSPEC) @@ -1564,6 +1613,7 @@ getaddrinfo (const char *name, const char *service, } freeaddrinfo (p); + free (in6ai); return -(i & GAIH_EAI); } @@ -1579,7 +1629,35 @@ getaddrinfo (const char *name, const char *service, } if (j == 0) - return EAI_FAMILY; + { + free (in6ai); + return EAI_FAMILY; + } +#else + if (hints->ai_family == AF_UNSPEC || hints->ai_family == AF_INET + || hints->ai_family == AF_INET6) + { + last_i = gaih_inet (name, pservice, hints, end, &naddrs); + if (last_i != 0) + { + freeaddrinfo (p); + free (in6ai); + + return -(i & GAIH_EAI); + } + if (end) + while (*end) + { + end = &((*end)->ai_next); + ++nresults; + } + } + else + { + free (in6ai); + return EAI_FAMILY; + } +#endif if (naddrs > 1) { @@ -1589,6 +1667,11 @@ getaddrinfo (const char *name, const char *service, struct addrinfo *last = NULL; char *canonname = NULL; + /* If we have information about deprecated and temporary address + sort the array now. */ + if (in6ai != NULL) + qsort (in6ai, in6ailen, sizeof (*in6ai), in6aicmp); + for (i = 0, q = p; q != NULL; ++i, last = q, q = q->ai_next) { results[i].dest_addr = q; @@ -1603,9 +1686,12 @@ getaddrinfo (const char *name, const char *service, results[i - 1].source_addr_len); results[i].source_addr_len = results[i - 1].source_addr_len; results[i].got_source_addr = results[i - 1].got_source_addr; + results[i].source_addr_flags = results[i - 1].source_addr_flags; } else { + results[i].source_addr_flags = 0; + /* We overwrite the type with SOCK_DGRAM since we do not want connect() to connect to the other side. If we cannot determine the source address remember this @@ -1620,6 +1706,20 @@ getaddrinfo (const char *name, const char *service, { results[i].source_addr_len = sl; results[i].got_source_addr = true; + + if (q->ai_family == PF_INET6 && in6ai != NULL) + { + /* See whether the address is the list of deprecated + or temporary addresses. */ + struct in6addrinfo tmp; + memcpy (tmp.addr, q->ai_addr, IN6ADDRSZ); + + struct in6addrinfo *found + = bsearch (&tmp, in6ai, in6ailen, sizeof (*in6ai), + in6aicmp); + if (found != NULL) + results[i].source_addr_flags = found->flags; + } } else /* Just make sure that if we have to process the same @@ -1653,6 +1753,8 @@ getaddrinfo (const char *name, const char *service, p->ai_canonname = canonname; } + free (in6ai); + if (p) { *pai = p; diff --git a/sysdeps/posix/sigset.c b/sysdeps/posix/sigset.c index 31e39d78b5..8f96e3d610 100644 --- a/sysdeps/posix/sigset.c +++ b/sysdeps/posix/sigset.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1998, 2000, 2005 Free Software Foundation, Inc. +/* Copyright (C) 1998, 2000, 2005, 2006 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -29,8 +29,10 @@ sigset (sig, disp) int sig; __sighandler_t disp; { - struct sigaction act, oact; + struct sigaction act; + struct sigaction oact; sigset_t set; + sigset_t oset; #ifdef SIG_HOLD /* Handle SIG_HOLD first. */ @@ -45,10 +47,18 @@ sigset (sig, disp) return SIG_ERR; /* Add the signal set to the current signal mask. */ - if (__sigprocmask (SIG_BLOCK, &set, NULL) < 0) + if (__sigprocmask (SIG_BLOCK, &set, &oset) < 0) return SIG_ERR; - return SIG_HOLD; + /* If the signal was already blocked signal this to the caller. */ + if (__sigismember (&oset, sig)) + return SIG_HOLD; + + /* We need to determine whether a specific handler is installed. */ + if (__sigaction (sig, NULL, &oact) < 0) + return SIG_ERR; + + return oact.sa_handler; } #endif /* SIG_HOLD */ @@ -75,8 +85,9 @@ sigset (sig, disp) return SIG_ERR; /* Remove the signal set from the current signal mask. */ - if (__sigprocmask (SIG_UNBLOCK, &set, NULL) < 0) + if (__sigprocmask (SIG_UNBLOCK, &set, &oset) < 0) return SIG_ERR; - return oact.sa_handler; + /* If the signal was already blocked return SIG_HOLD. */ + return __sigismember (&oset, sig) ? SIG_HOLD : oact.sa_handler; } diff --git a/sysdeps/posix/tempname.c b/sysdeps/posix/tempname.c index 0d4bbc418a..c8973a0852 100644 --- a/sysdeps/posix/tempname.c +++ b/sysdeps/posix/tempname.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-1999, 2000, 2001 Free Software Foundation, Inc. +/* Copyright (C) 1991-1999, 2000, 2001, 2006 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -242,11 +242,15 @@ __gen_tempname (char *tmpl, int kind) necessary to try all these combinations. Instead if a reasonable number of names is tried (we define reasonable as 62**3) fail to give the system administrator the chance to remove the problems. */ - unsigned int attempts_min = 62 * 62 * 62; +#define ATTEMPTS_MIN (62 * 62 * 62) /* The number of times to attempt to generate a temporary file. To conform to POSIX, this must be no smaller than TMP_MAX. */ - unsigned int attempts = attempts_min < TMP_MAX ? TMP_MAX : attempts_min; +#if ATTEMPTS_MIN < TMP_MAX + unsigned int attempts = TMP_MAX; +#else + unsigned int attempts = ATTEMPTS_MIN; +#endif len = strlen (tmpl); if (len < 6 || strcmp (&tmpl[len - 6], "XXXXXX")) |