[bill@kayhay.com] libc/1625: resolver ignores "multi on" in /etc/host.conf
H . J . Lu
hjl@lucon.org
Fri Mar 3 19:06:00 GMT 2000
On Fri, Mar 03, 2000 at 09:29:16AM +0100, Andreas Jaeger wrote:
>
> Hi glibc folks,
>
> we received the appended bug report. IMHO we cannot support "multi on"
> at all with glibc (at least not in /etc/hosts) - and should remove the
> support for parsing "multi on" from res_hconf.c. We parse this
> correctly - but never use it at all.
>
> Does somebody see a way to fix this?
>
Here is a patch. It seems to work for me.
H.J.
-----
2000-03-03 H.J. Lu <hjl@gnu.org>
* nss/nss_db/db-XXX.c (DB_LOOKUP): Add byname.
* nss/nss_files/files-XXX.c (internal_getent): Add bufused,
return the size of buffer used.
(DB_LOOKUP): Add byname. Used by gethostbyname.
* nss/nss_files/files-ethers.c: Pass byname == 0 to DB_LOOKUP.
* nss/nss_files/files-grp.c: Likewise.
* nss/nss_files/files-network.c: Likewise.
* nss/nss_files/files-proto.c: Likewise.
* nss/nss_files/files-pwd.c: Likewise.
* nss/nss_files/files-rpc.c: Likewise.
* nss/nss_files/files-service.c: Likewise.
* nss/nss_files/files-spwd.c: Likewise.
* nss/nss_files/files-hosts.c (GETHOSTNAME): New.
Pass byname == (_res_hconf.flags & HCONF_FLAG_MULTI) to
DB_LOOKUP and replace LOOKUP_NAME_CASE with GETHOSTNAME.
Index: nss/nss_db/db-XXX.c
===================================================================
RCS file: /work/cvs/gnu/glibc-2.1/nss/nss_db/db-XXX.c,v
retrieving revision 1.1.1.11
diff -u -p -r1.1.1.11 db-XXX.c
--- nss/nss_db/db-XXX.c 1998/11/19 18:45:50 1.1.1.11
+++ nss/nss_db/db-XXX.c 2000/03/04 01:57:00
@@ -250,6 +250,8 @@ lookup (DBT *key, struct STRUCTURE *resu
NAME is the name of the lookup; e.g. `pwnam'.
+ BYNAME ignored here but used by ../nss_files/files-XXX.c.
+
KEYPATTERN gives `printf' args to construct a key string;
e.g. `(".%s", name)'.
@@ -261,7 +263,7 @@ lookup (DBT *key, struct STRUCTURE *resu
BREAK_IF_MATCH is ignored, but used by ../nss_files/files-XXX.c. */
-#define DB_LOOKUP(name, keysize, keypattern, break_if_match, proto...) \
+#define DB_LOOKUP(name, byname, keysize, keypattern, break_if_match, proto...) \
enum nss_status \
_nss_db_get##name##_r (proto, \
struct STRUCTURE *result, \
Index: nss/nss_files/files-XXX.c
===================================================================
RCS file: /work/cvs/gnu/glibc-2.1/nss/nss_files/files-XXX.c,v
retrieving revision 1.1.1.13
diff -u -p -r1.1.1.13 files-XXX.c
--- nss/nss_files/files-XXX.c 1999/02/14 17:07:28 1.1.1.13
+++ nss/nss_files/files-XXX.c 2000/03/04 02:56:59
@@ -161,7 +161,8 @@ CONCAT(_nss_files_end,ENTNAME) (void)
static enum nss_status
internal_getent (struct STRUCTURE *result,
- char *buffer, size_t buflen, int *errnop H_ERRNO_PROTO)
+ char *buffer, size_t buflen, size_t *bufused,
+ int *errnop H_ERRNO_PROTO)
{
char *p;
struct parser_data *data = (void *) buffer;
@@ -197,6 +198,9 @@ internal_getent (struct STRUCTURE *resul
return NSS_STATUS_TRYAGAIN;
}
+ if (bufused)
+ *bufused = sizeof *data + strlen (data->linebuffer) + 1;
+
/* Skip leading blanks. */
while (isspace (*p))
++p;
@@ -248,8 +252,8 @@ CONCAT(_nss_files_get,ENTNAME_r) (struct
if (status == NSS_STATUS_SUCCESS)
{
- status = internal_getent (result, buffer, buflen, errnop
- H_ERRNO_ARG);
+ status = internal_getent (result, buffer, buflen, NULL,
+ errnop H_ERRNO_ARG);
/* Remember this position if we were successful. If the
operation failed we give the user a chance to repeat the
@@ -271,6 +275,8 @@ CONCAT(_nss_files_get,ENTNAME_r) (struct
NAME is the name of the lookup; e.g. `hostbyname'.
+ BYNAME indicates if it is a gethostbyname function.
+
KEYSIZE and KEYPATTERN are ignored here but used by ../nss_db/db-XXX.c.
PROTO describes the arguments for the lookup key;
@@ -279,13 +285,18 @@ CONCAT(_nss_files_get,ENTNAME_r) (struct
BREAK_IF_MATCH is a block of code which compares `struct STRUCTURE *result'
to the lookup key arguments and does `break;' if they match. */
-#define DB_LOOKUP(name, keysize, keypattern, break_if_match, proto...) \
+#define DB_LOOKUP(name, byname, keysize, keypattern, break_if_match, proto...) \
enum nss_status \
_nss_files_get##name##_r (proto, \
struct STRUCTURE *result, char *buffer, \
size_t buflen, int *errnop H_ERRNO_PROTO) \
{ \
enum nss_status status; \
+ struct STRUCTURE entry; \
+ char *bufend __attribute__ ((unused)) = buffer + buflen; \
+ \
+ if (byname) \
+ memset (&entry, 0, sizeof entry); \
\
__libc_lock_lock (lock); \
\
@@ -294,13 +305,22 @@ _nss_files_get##name##_r (proto,
\
if (status == NSS_STATUS_SUCCESS) \
{ \
+ enum nss_status ever = NSS_STATUS_NOTFOUND; \
+ size_t bufused; \
+ \
/* Tell getent function that we have repositioned the file pointer. */ \
last_use = getby; \
\
- while ((status = internal_getent (result, buffer, buflen, errnop \
- H_ERRNO_ARG)) \
+ while ((status = internal_getent (result, buffer, buflen, &bufused, \
+ errnop H_ERRNO_ARG)) \
== NSS_STATUS_SUCCESS) \
{ break_if_match } \
+ \
+ if (byname && ever == NSS_STATUS_SUCCESS) \
+ { \
+ status = ever; \
+ *result = entry; \
+ } \
\
if (! keep_stream) \
internal_endent (); \
Index: nss/nss_files/files-ethers.c
===================================================================
RCS file: /work/cvs/gnu/glibc-2.1/nss/nss_files/files-ethers.c,v
retrieving revision 1.1.1.1
diff -u -p -r1.1.1.1 files-ethers.c
--- nss/nss_files/files-ethers.c 1997/02/25 17:48:12 1.1.1.1
+++ nss/nss_files/files-ethers.c 2000/03/04 02:20:17
@@ -58,13 +58,13 @@ LINE_PARSER
#include GENERIC
-DB_LOOKUP (hostton, 1 + strlen (name), (".%s", name),
+DB_LOOKUP (hostton, 0, 1 + strlen (name), (".%s", name),
{
if (strcmp (result->e_name, name) == 0)
break;
}, const char *name)
-DB_LOOKUP (ntohost, 18, ("=%x:%x:%x:%x:%x:%x",
+DB_LOOKUP (ntohost, 0, 18, ("=%x:%x:%x:%x:%x:%x",
addr->ether_addr_octet[0], addr->ether_addr_octet[1],
addr->ether_addr_octet[2], addr->ether_addr_octet[3],
addr->ether_addr_octet[4], addr->ether_addr_octet[5]),
Index: nss/nss_files/files-grp.c
===================================================================
RCS file: /work/cvs/gnu/glibc-2.1/nss/nss_files/files-grp.c,v
retrieving revision 1.1.1.1
diff -u -p -r1.1.1.1 files-grp.c
--- nss/nss_files/files-grp.c 1997/02/25 17:48:12 1.1.1.1
+++ nss/nss_files/files-grp.c 2000/03/04 02:22:47
@@ -30,14 +30,14 @@ struct grent_data {};
#include "files-parse.c"
#include GENERIC
-DB_LOOKUP (grnam, 1 + strlen (name), (".%s", name),
+DB_LOOKUP (grnam, 0, 1 + strlen (name), (".%s", name),
{
if (name[0] != '-' && name[0] != '+'
&& ! strcmp (name, result->gr_name))
break;
}, const char *name)
-DB_LOOKUP (grgid, 20, ("=%lu", (unsigned long int) gid),
+DB_LOOKUP (grgid, 0, 20, ("=%lu", (unsigned long int) gid),
{
if (result->gr_gid == gid && result->gr_name[0] != '+'
&& result->gr_name[0] != '-')
Index: nss/nss_files/files-hosts.c
===================================================================
RCS file: /work/cvs/gnu/glibc-2.1/nss/nss_files/files-hosts.c,v
retrieving revision 1.1.1.6
diff -u -p -r1.1.1.6 files-hosts.c
--- nss/nss_files/files-hosts.c 1998/01/21 18:33:22 1.1.1.6
+++ nss/nss_files/files-hosts.c 2000/03/04 03:01:14
@@ -22,6 +22,7 @@
#include <arpa/nameser.h>
#include <netdb.h>
#include <resolv.h>
+#include <resolv/res_hconf.h>
/* Get implementation for some internal functions. */
@@ -35,7 +36,7 @@
#define ENTDATA hostent_data
struct hostent_data
{
- unsigned char host_addr[16]; /* IPv4 or IPv6 address. */
+ unsigned char host_addr[IN6ADDRSZ]; /* IPv4 or IPv6 address. */
char *h_addr_ptrs[2]; /* Points to that and null terminator. */
};
@@ -82,24 +83,98 @@ LINE_PARSER
STRING_FIELD (result->h_name, isspace, 1);
})
+#define GETHOSTNAME \
+ if (_res_hconf.flags & HCONF_FLAG_MULTI) \
+ { \
+ int match = 1; \
+ while (1) \
+ { \
+ LOOKUP_NAME_CASE (h_name, h_aliases) \
+ match = 0; \
+ break; \
+ } \
+ if (match) \
+ { \
+ buffer += bufused; \
+ buflen -= bufused; \
+ if (buflen <= 0) \
+ { \
+ memory: \
+ *errnop = ERANGE; \
+ H_ERRNO_SET (NETDB_INTERNAL); \
+ return NSS_STATUS_TRYAGAIN; \
+ } \
+ \
+ if (entry.h_addr_list == NULL) \
+ { \
+ entry = *result; \
+ ever = status; \
+ } \
+ else \
+ { \
+ int i, n; \
+ char **h_addr_ptrs; \
+ \
+ for (n = 0; entry.h_addr_list [n] != NULL; n++); \
+ \
+ if (n == 1) \
+ { \
+ /* It is the first time. We have to copy it to the \
+ buffer. It takes IN6ADDRSZ bytes for address and \
+ space for 2 pointers. */ \
+ bufend -= IN6ADDRSZ + sizeof (char *) * 2; \
+ buflen -= IN6ADDRSZ + sizeof (char *) * 2; \
+ if (buflen <= 0) \
+ goto memory; \
+ h_addr_ptrs = (char **) &bufend [IN6ADDRSZ]; \
+ memcpy (bufend, entry.h_addr_list [0], IN6ADDRSZ); \
+ h_addr_ptrs [0] = bufend; \
+ h_addr_ptrs [1] = NULL; \
+ } \
+ \
+ /* Allocate space in buffer for host address. It is \
+ IN6ADDRSZ bytes + a pointer. */ \
+ bufend -= IN6ADDRSZ + sizeof (char *); \
+ buflen -= IN6ADDRSZ + sizeof (char *); \
+ if (buflen <= 0) \
+ goto memory; \
+ \
+ n++; \
+ memcpy (bufend, result->h_addr_list [0], IN6ADDRSZ); \
+ for (i = 1; i < n; i++) \
+ memmove (&bufend [IN6ADDRSZ * i], \
+ entry.h_addr_list [i - 1], IN6ADDRSZ); \
+ \
+ h_addr_ptrs = (char **) &bufend [IN6ADDRSZ * n]; \
+ for (i = 0; i < n; i++) \
+ h_addr_ptrs [i] = &bufend [IN6ADDRSZ * i]; \
+ entry.h_addr_list = h_addr_ptrs; \
+ } \
+ } \
+ } \
+ else \
+ LOOKUP_NAME_CASE (h_name, h_aliases)
+
#include "files-XXX.c"
-DB_LOOKUP (hostbyname, ,,
+DB_LOOKUP (hostbyname,
+ (_res_hconf.flags & HCONF_FLAG_MULTI), ,,
{
if (result->h_addrtype != ((_res.options & RES_USE_INET6)
? AF_INET6 : AF_INET))
continue;
- LOOKUP_NAME_CASE (h_name, h_aliases)
+ GETHOSTNAME
}, const char *name)
-DB_LOOKUP (hostbyname2, ,,
+DB_LOOKUP (hostbyname2,
+ (_res_hconf.flags & HCONF_FLAG_MULTI), ,,
{
if (result->h_addrtype != af)
continue;
- LOOKUP_NAME_CASE (h_name, h_aliases)
+ GETHOSTNAME
}, const char *name, int af)
-DB_LOOKUP (hostbyaddr, ,,
+DB_LOOKUP (hostbyaddr, NULL, ,,
{
if (result->h_addrtype == type && result->h_length == len &&
! memcmp (addr, result->h_addr_list[0], len))
Index: nss/nss_files/files-network.c
===================================================================
RCS file: /work/cvs/gnu/glibc-2.1/nss/nss_files/files-network.c,v
retrieving revision 1.1.1.3
diff -u -p -r1.1.1.3 files-network.c
--- nss/nss_files/files-network.c 1998/01/27 18:53:30 1.1.1.3
+++ nss/nss_files/files-network.c 2000/03/04 02:22:57
@@ -44,11 +44,11 @@ LINE_PARSER
#include "files-XXX.c"
-DB_LOOKUP (netbyname, ,,
+DB_LOOKUP (netbyname, 0, ,,
LOOKUP_NAME_CASE (n_name, n_aliases),
const char *name)
-DB_LOOKUP (netbyaddr, ,,
+DB_LOOKUP (netbyaddr, 0, ,,
{
if (result->n_addrtype == type && result->n_net == net)
/* Bingo! */
Index: nss/nss_files/files-proto.c
===================================================================
RCS file: /work/cvs/gnu/glibc-2.1/nss/nss_files/files-proto.c,v
retrieving revision 1.1.1.1
diff -u -p -r1.1.1.1 files-proto.c
--- nss/nss_files/files-proto.c 1997/02/25 17:48:12 1.1.1.1
+++ nss/nss_files/files-proto.c 2000/03/04 02:23:07
@@ -36,11 +36,11 @@ LINE_PARSER
#include GENERIC
-DB_LOOKUP (protobyname, 1 + strlen (name), (".%s", name),
+DB_LOOKUP (protobyname, 0, 1 + strlen (name), (".%s", name),
LOOKUP_NAME (p_name, p_aliases),
const char *name)
-DB_LOOKUP (protobynumber, 20, ("=%d", proto),
+DB_LOOKUP (protobynumber, 0, 20, ("=%d", proto),
{
if (result->p_proto == proto)
break;
Index: nss/nss_files/files-pwd.c
===================================================================
RCS file: /work/cvs/gnu/glibc-2.1/nss/nss_files/files-pwd.c,v
retrieving revision 1.1.1.1
diff -u -p -r1.1.1.1 files-pwd.c
--- nss/nss_files/files-pwd.c 1997/02/25 17:48:12 1.1.1.1
+++ nss/nss_files/files-pwd.c 2000/03/04 02:23:19
@@ -30,14 +30,14 @@ struct pwent_data {};
#include "files-parse.c"
#include GENERIC
-DB_LOOKUP (pwnam, 1 + strlen (name), (".%s", name),
+DB_LOOKUP (pwnam, 0, 1 + strlen (name), (".%s", name),
{
if (name[0] != '+' && name[0] != '-'
&& ! strcmp (name, result->pw_name))
break;
}, const char *name)
-DB_LOOKUP (pwuid, 20, ("=%lu", (unsigned long int) uid),
+DB_LOOKUP (pwuid, 0, 20, ("=%lu", (unsigned long int) uid),
{
if (result->pw_uid == uid && result->pw_name[0] != '+'
&& result->pw_name[0] != '-')
Index: nss/nss_files/files-rpc.c
===================================================================
RCS file: /work/cvs/gnu/glibc-2.1/nss/nss_files/files-rpc.c,v
retrieving revision 1.1.1.1
diff -u -p -r1.1.1.1 files-rpc.c
--- nss/nss_files/files-rpc.c 1997/02/25 17:48:12 1.1.1.1
+++ nss/nss_files/files-rpc.c 2000/03/04 02:23:28
@@ -36,11 +36,11 @@ LINE_PARSER
#include GENERIC
-DB_LOOKUP (rpcbyname, 1 + strlen (name), (".%s", name),
+DB_LOOKUP (rpcbyname, 0, 1 + strlen (name), (".%s", name),
LOOKUP_NAME (r_name, r_aliases),
const char *name)
-DB_LOOKUP (rpcbynumber, 20, ("=%d", number),
+DB_LOOKUP (rpcbynumber, 0, 20, ("=%d", number),
{
if (result->r_number == number)
break;
Index: nss/nss_files/files-service.c
===================================================================
RCS file: /work/cvs/gnu/glibc-2.1/nss/nss_files/files-service.c,v
retrieving revision 1.1.1.5
diff -u -p -r1.1.1.5 files-service.c
--- nss/nss_files/files-service.c 1998/02/01 23:56:55 1.1.1.5
+++ nss/nss_files/files-service.c 2000/03/04 02:23:38
@@ -39,7 +39,7 @@ LINE_PARSER
#include GENERIC
-DB_LOOKUP (servbyname, 2 + strlen (name) + (proto ? strlen (proto) : 0),
+DB_LOOKUP (servbyname, 0, 2 + strlen (name) + (proto ? strlen (proto) : 0),
(".%s/%s", name, proto ?: ""),
{
/* Must match both protocol (if specified) and name. */
@@ -49,7 +49,7 @@ DB_LOOKUP (servbyname, 2 + strlen (name)
},
const char *name, const char *proto)
-DB_LOOKUP (servbyport, 21 + (proto ? strlen (proto) : 0),
+DB_LOOKUP (servbyport, 0, 21 + (proto ? strlen (proto) : 0),
("=%d/%s", ntohs (port), proto ?: ""),
{
/* Must match both port and protocol. */
Index: nss/nss_files/files-spwd.c
===================================================================
RCS file: /work/cvs/gnu/glibc-2.1/nss/nss_files/files-spwd.c,v
retrieving revision 1.1.1.1
diff -u -p -r1.1.1.1 files-spwd.c
--- nss/nss_files/files-spwd.c 1997/02/25 17:48:12 1.1.1.1
+++ nss/nss_files/files-spwd.c 2000/03/04 02:23:43
@@ -30,7 +30,7 @@ struct spent_data {};
#include "files-parse.c"
#include GENERIC
-DB_LOOKUP (spnam, 1 + strlen (name), (".%s", name),
+DB_LOOKUP (spnam, 0, 1 + strlen (name), (".%s", name),
{
if (name[0] != '+' && name[0] != '-'
&& ! strcmp (name, result->sp_namp))
More information about the Libc-alpha
mailing list