From 97a8f9f4dc1f94060b74943d9887cffed268b21b Mon Sep 17 00:00:00 2001 From: Denis Vlasenko Date: Fri, 14 Nov 2008 00:35:40 +0000 Subject: fixing resolver part 2: make _res structure members configurable. we don't use most of it anyway. --- extra/Configs/Config.in | 19 +++++++++++++- include/resolv.h | 66 +++++++++++++++++++++++++++++-------------------- libc/inet/resolv.c | 28 ++++++++++++--------- 3 files changed, 74 insertions(+), 39 deletions(-) diff --git a/extra/Configs/Config.in b/extra/Configs/Config.in index 9e2112c84..4979d5822 100644 --- a/extra/Configs/Config.in +++ b/extra/Configs/Config.in @@ -772,7 +772,7 @@ config UCLIBC_HAS_OBSOLETE_BSD_SIGNAL bool "BSD obsolete signal functions" default n help - These functions are provided as a compatibility interface for + These functions are provided as a compatibility interface for programs that make use of the historical System V signal API. This API is obsolete: new applications should use the POSIX signal API (sigaction(2), @@ -1066,6 +1066,23 @@ config UCLIBC_HAS_BSD_RES_CLOSE Most people will say N. +config UCLIBC_HAS_COMPAT_RES_STATE + bool "Use compatible but bloated _res" + default y + help + Answer Y if you build network utilities and they muck with resolver + internals a lot (_res global structure). uclibc does not use most + of _res.XXX fields, and with this option OFF they won't even exist. + Which will make e.g. dig build fail. + Answering N saves around 400 bytes in bss. + +config UCLIBC_HAS_EXTRA_COMPAT_RES_STATE + bool "Use extra compatible but extra bloated _res" + default n + help + Answer Y if selecting UCLIBC_HAS_COMPAT_RES_STATE is not enough. + As far as I can say, this should never be needed. + endif diff --git a/include/resolv.h b/include/resolv.h index 3434f5d8c..6651dded9 100644 --- a/include/resolv.h +++ b/include/resolv.h @@ -101,53 +101,64 @@ typedef res_sendhookact (*res_send_rhook) (const struct sockaddr_in *ns, # define RES_DFLRETRY 2 /* Default #/tries. */ # define RES_MAXTIME 65535 /* Infinity, in milliseconds. */ +/* _res (an instance of this structure) uses 0.5kb in bss + * in "ordinary" libc's (glibc, xBSD). We want to be less wasteful. + * We (1) shuffle and shrink some integer fields, + * and (2) can switch off stuff we don't support. + * Everything inside __UCLIBC_HAS_COMPAT_RES_STATE__ + * is not actually used by uclibc and can be configured off. + * However, this will prevent some programs from building. + * Really obscure stuff with no observed users in the wild is under + * __UCLIBC_HAS_EXTRA_COMPAT_RES_STATE__. + * I guess it's safe to set that to N. + */ struct __res_state { - int retrans; /* retransmition time interval */ +#ifdef __UCLIBC_HAS_COMPAT_RES_STATE__ + int retrans; /* retransmission time interval */ int retry; /* number of times to retransmit */ - u_long options; /* option flags - see below. */ - int nscount; /* number of name servers */ +#endif + u_int32_t options; /* (was: ulong) option flags - see below. */ struct sockaddr_in nsaddr_list[MAXNS]; /* address of name server */ -# define nsaddr nsaddr_list[0] /* for backward compatibility */ - u_short id; /* current message id */ +#define nsaddr nsaddr_list[0] /* for backward compatibility */ char *dnsrch[MAXDNSRCH+1]; /* components of domain to search */ +#ifdef __UCLIBC_HAS_COMPAT_RES_STATE__ + /* googling for "_res.defdname" says it's still sometimes used. + * Pity. It's huge, I want to move it to EXTRA_COMPAT... */ char defdname[256]; /* default domain (deprecated) */ - u_long pfcode; /* RES_PRF_ flags - see below. */ - unsigned ndots:4; /* threshold for initial abs. query */ - unsigned nsort:4; /* number of elements in sort_list[] */ - char unused[3]; +#endif + u_int8_t nscount; /* (was: int) number of name servers */ + u_int8_t ndots; /* (was: unsigned:4) threshold for initial abs. query */ +#ifdef __UCLIBC_HAS_COMPAT_RES_STATE__ + u_int8_t nsort; /* (was: unsigned:4) number of elements in sort_list[] */ + u_int16_t pfcode; /* (was: ulong) RES_PRF_ flags. Used by dig. */ + unsigned short id; /* current message id */ + int res_h_errno; /* last one set for this context */ struct { struct in_addr addr; u_int32_t mask; } sort_list[MAXRESOLVSORT]; - res_send_qhook qhook; /* query hook */ - res_send_rhook rhook; /* response hook */ - int res_h_errno; /* last one set for this context */ - int _vcsock; /* PRIVATE: for res_send VC i/o */ - u_int _flags; /* PRIVATE: see below */ union { - char pad[52]; /* On an i386 this means 512b total. */ struct { u_int16_t nscount; -#if 0 - u_int16_t nsmap[MAXNS]; -#else u_int16_t nstimes[MAXNS]; /* ms. */ -#endif int nssocks[MAXNS]; + /* below: not in xBSD. glibc only? */ u_int16_t nscount6; u_int16_t nsinit; struct sockaddr_in6 *nsaddrs[MAXNS]; -#if 0 -#ifdef _LIBC - unsigned long long int initstamp - __attribute__((packed)); -#else - unsigned int _initstamp[2]; -#endif -#endif } _ext; } _u; +#endif +#ifdef __UCLIBC_HAS_EXTRA_COMPAT_RES_STATE__ + /* Truly obscure stuff. + * Googling for "_res.XXX" for these members + * turned up basically empty */ + res_send_qhook qhook; /* query hook */ + res_send_rhook rhook; /* response hook */ + int _vcsock; /* PRIVATE: for res_send VC i/o */ + unsigned _flags; /* PRIVATE: see below */ +#endif }; typedef struct __res_state *res_state; @@ -196,6 +207,7 @@ struct res_sym { /* * Resolver options (keep these in synch with res_debug.c, please) + * (which of these do we really implement??) */ #define RES_INIT 0x00000001 /* address initialized */ #define RES_DEBUG 0x00000002 /* print debug messages */ diff --git a/libc/inet/resolv.c b/libc/inet/resolv.c index 7ef2fba45..b7ab27690 100644 --- a/libc/inet/resolv.c +++ b/libc/inet/resolv.c @@ -1255,20 +1255,26 @@ int res_init(void) __UCLIBC_MUTEX_LOCK(__resolv_lock); /* must be a recursive lock! */ __close_nameservers(); __open_nameservers(); + memset(rp, 0, sizeof(*rp)); + rp->options = RES_INIT; +#ifdef __UCLIBC_HAS_COMPAT_RES_STATE__ rp->retrans = RES_TIMEOUT; rp->retry = 4; - rp->options = RES_INIT; - rp->id = (u_int) random(); - rp->nsaddr.sin_addr.s_addr = INADDR_ANY; - rp->nsaddr.sin_family = AF_INET; - rp->nsaddr.sin_port = htons(NAMESERVER_PORT); + rp->id = random(); +#endif + /* man resolv.conf says: + * "On a normally configured system this file should not be necessary. + * The only name server to be queried will be on the local machine; + * the domain name is determined from the host name + * and the domain search path is constructed from the domain name" */ + rp->nscount = 1; + rp->nsaddr_list[0].sin_addr.s_addr = INADDR_ANY; + rp->nsaddr_list[0].sin_family = AF_INET; + rp->nsaddr_list[0].sin_port = htons(NAMESERVER_PORT); rp->ndots = 1; - /** rp->pfcode = 0; **/ +#ifdef __UCLIBC_HAS_EXTRA_COMPAT_RES_STATE__ rp->_vcsock = -1; - /** rp->_flags = 0; **/ - /** rp->qhook = NULL; **/ - /** rp->rhook = NULL; **/ - /** rp->_u._ext.nsinit = 0; **/ +#endif if (__searchdomains) { int i; @@ -1286,8 +1292,8 @@ int res_init(void) rp->nsaddr_list[i].sin_port = htons(NAMESERVER_PORT); } } + rp->nscount = __nameservers; } - rp->nscount = __nameservers; __UCLIBC_MUTEX_UNLOCK(__resolv_lock); return 0; -- cgit v1.2.3