This is the mail archive of the libc-hacker@sourceware.cygnus.com mailing list for the glibc project.
Note that libc-hacker is a closed list. You may look at the archives of this list, but subscription and posting are not open.
Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|
Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |
I've seen a few of complaints that 'reorder on' in /etc/host.conf doesn't work at all. The code was proteced by an #ifdef but since the needed define was never included the code was not compiled into glibc - and it couldn't have worked at all since it didn't even compile.:-( I've gone over the code and enabled the reordering also for gethstbyname2. Please note that the code works only for IPv4. Andreas 1999-09-16 Andreas Jaeger <aj@suse.de> * inet/gethstbynm2_r.c: Reorder addresses. * resolv/res_hconf.c: Add missing includes to get all prototypes. (_res_hconf_reorder_addrs): Rewrite. This never worked before. Reported by John DiMarco <jdd@cs.toronto.edu>. (_res_hconf_reorder_addrs): Made thread safe. (free_mem): New function, needed for malloc debugging. --- resolv/res_hconf.c.~1~ Thu Apr 29 20:59:23 1999 +++ resolv/res_hconf.c Wed Sep 15 12:45:01 1999 @@ -17,9 +17,9 @@ Boston, MA 02111-1307, USA. */ /* This file provides a Linux /etc/host.conf compatible front end to -the various name resolvers (/etc/hosts, named, NIS server, etc.). -Though mostly compatibly, the following differences exist compared -to the original implementation: + the various name resolvers (/etc/hosts, named, NIS server, etc.). + Though mostly compatibly, the following differences exist compared + to the original implementation: - new command "spoof" takes an arguments like RESOLV_SPOOF_CHECK environment variable (i.e., `off', `nowarn', or `warn'). @@ -27,12 +27,18 @@ - line comments can appear anywhere (not just at the beginning of a line) */ + +#include <errno.h> #include <ctype.h> #include <memory.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <net/if.h> +#include <sys/ioctl.h> +#include <unistd.h> +#include <netinet/in.h> +#include <bits/libc-lock.h> #include "res_hconf.h" @@ -374,30 +380,44 @@ } +/* List of known interfaces. */ +static struct netaddr +{ + int addrtype; + union + { + struct + { + u_int32_t addr; + u_int32_t mask; + } ipv4; + } u; +} *ifaddrs; + +/* We need to protect the dynamic buffer handling. */ +__libc_lock_define_initialized (static, lock); + /* Reorder addresses returned in a hostent such that the first address is an address on the local subnet, if there is such an address. - Otherwise, nothing is changed. */ + Otherwise, nothing is changed. + + Note that this function currently only handles IPv4 addresses. */ void _res_hconf_reorder_addrs (struct hostent *hp) { #if defined SIOCGIFCONF && defined SIOCGIFNETMASK - static int num_ifs = -1; /* number of interfaces */ - static struct netaddr - { - int addrtype; - union - { - struct - { - u_int32_t addr; - u_int32_t mask; - } ipv4 - } u; - } *ifaddrs; + int i, j; + /* Number of interfaces. */ + static int num_ifs = -1; + /* Only reorder if we're supposed to. */ + if ((_res_hconf.flags & HCONF_FLAG_REORDER) == 0) + return; + + /* Can't deal with anything but IPv4 for now... */ if (hp->h_addrtype != AF_INET) - return; /* can't deal with anything but IPv4 for now... */ + return; if (num_ifs <= 0) { @@ -405,8 +425,10 @@ struct ifreq *ifr; size_t size, num; int sd; - - /* initialize interface table: */ + /* Save errno. */ + int save = errno; + + /* Initialize interface table. */ num_ifs = 0; @@ -414,73 +436,83 @@ if (sd < 0) return; - /* Now get list of interfaces. Since we don't know how many + /* Get lock. */ + __libc_lock_lock (lock); + + /* Now get a list of interfaces. Since we don't know how many interfaces there are, we keep increasing the buffer size until we have at least sizeof(struct ifreq) too many bytes. - That implies that the ioctl() return because it ran out of - interfaces, not memory */ + That implies that the ioctl() returns because it ran out of + interfaces, not memory. */ size = 0; - ifs.ifc_buf = 0; + ifs.ifc_buf = NULL; do { size += 4 * sizeof (struct ifreq); - ifs.ifc_buf = realloc (ifs.ifs_buf, size); + ifs.ifc_buf = realloc (ifs.ifc_buf, size); if (ifs.ifc_buf == NULL) - { - close (sd); - return; - } + goto cleanup1; + ifs.ifc_len = size; if (__ioctl (sd, SIOCGIFCONF, &ifs) < 0) goto cleanup; } - while (size - ifs.ifc_len < sizeof (struct ifreq)); + while (size < sizeof (struct ifreq) + ifs.ifc_len); + /* Number of interfaces. */ num = ifs.ifc_len / sizeof (struct ifreq); ifaddrs = malloc (num * sizeof (ifaddrs[0])); if (!ifaddrs) goto cleanup; + /* Copy usable interfaces in ifaddrs structure. */ ifr = ifs.ifc_req; - for (i = 0; i < num; ++i) + for (i = 0; i < num; ++i, ifr++) { if (ifr->ifr_addr.sa_family != AF_INET) continue; + ifaddrs[num_ifs].addrtype = AF_INET; + ifaddrs[num_ifs].u.ipv4.addr = + ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr; - memcpy (&ifaddrs[num_ifs].u.ipv4.addr, - &((struct sockaddr_in *)ifr->ifr_addr)->sin_addr, 4); - - if (__ioctl (sd, SIOCGIFNETMASK, if) < 0) + if (__ioctl (sd, SIOCGIFNETMASK, ifr) < 0) continue; - memcpy (&ifaddrs[num_ifs].u.ipv4.mask, - ((struct sockaddr_in *)ifr->ifr_mask)->sin_addr, 4); - ++num_ifs; /* now we're committed to this entry */ + ifaddrs[num_ifs].u.ipv4.mask = + ((struct sockaddr_in *) &ifr->ifr_netmask)->sin_addr.s_addr; + + /* Now we're committed to this entry. */ + ++num_ifs; } - /* just keep enough memory to hold all the interfaces we want: */ + /* Just keep enough memory to hold all the interfaces we want. */ ifaddrs = realloc (ifaddrs, num_ifs * sizeof (ifaddrs[0])); cleanup: - close (sd); free (ifs.ifc_buf); + + cleanup1: + /* Release lock, preserve error value, and close socket. */ + save = errno; + __libc_lock_unlock (lock); + close (sd); } if (num_ifs == 0) return; - /* find an address for which we have a direct connection: */ + /* Find an address for which we have a direct connection. */ for (i = 0; hp->h_addr_list[i]; ++i) { - h_addr = (struct in_addr *) hp->h_addr_list[i]; + struct in_addr *haddr = (struct in_addr *) hp->h_addr_list[i]; for (j = 0; j < num_ifs; ++j) { - if_addr = ifaddrs[j].u.ipv4.addr; - if_netmask = ifaddrs[j].u.ipv4.mask; + u_int32_t if_addr = ifaddrs[j].u.ipv4.addr; + u_int32_t if_netmask = ifaddrs[j].u.ipv4.mask; - if (((h_addr->s_addr ^ if_addr) & if_netmask) == 0) + if (((haddr->s_addr ^ if_addr) & if_netmask) == 0) { void *tmp; @@ -537,3 +569,14 @@ for (i = 0; hp->h_aliases[i]; ++i) _res_hconf_trim_domain (hp->h_aliases[i]); } + + +/* Free all resources if necessary. */ +static void __attribute__ ((unused)) +free_mem (void) +{ + if (ifaddrs != NULL) + free (ifaddrs); +} + +text_set_element (__libc_subfreeres, free_mem); --- inet/gethstbynm2_r.c~ Sat Jan 17 10:57:09 1998 +++ inet/gethstbynm2_r.c Thu Sep 16 15:06:27 1999 @@ -31,6 +31,10 @@ #define ADD_PARAMS const char *name, int af #define ADD_VARIABLES name, af #define NEED_H_ERRNO 1 +#define NEED__RES_HCONF 1 +#define POSTPROCESS \ + if (status == NSS_STATUS_SUCCESS) \ + _res_hconf_reorder_addrs (resbuf); #define HANDLE_DIGITS_DOTS 1 #define HAVE_LOOKUP_BUFFER 1 -- Andreas Jaeger aj@arthur.rhein-neckar.de aj@suse.de for pgp-key finger ajaeger@aixd1.rhrk.uni-kl.de
Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|
Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |