lh | 9ed821d | 2023-04-07 01:36:19 -0700 | [diff] [blame] | 1 | The resolver in the GNU C Library |
| 2 | ********************************* |
| 3 | |
| 4 | Starting with version 2.2, the resolver in the GNU C Library comes |
| 5 | from BIND 8. Only a subset of the src/lib/resolv part of libbind is |
| 6 | included here; basically the parts that are needed to provide the |
| 7 | functionality present in the resolver from BIND 4.9.7 that was |
| 8 | included in the previous release of the GNU C Library, augmented by |
| 9 | the parts needed to provide thread-safety. This means that support |
| 10 | for things as dynamic DNS updates and TSIG keys isn't included. If |
| 11 | you need those facilities, please take a look at the full BIND |
| 12 | distribution. |
| 13 | |
| 14 | |
| 15 | Differences |
| 16 | =========== |
| 17 | |
| 18 | The resolver in the GNU C Library still differs from what's in BIND |
| 19 | 8.2.3-T5B: |
| 20 | |
| 21 | * The resolver in glibc strictly adheres to the recommendations in RFC |
| 22 | 1535. BIND 8.2.3-T5B seems to relax those rules a bit (see the code |
| 23 | that's wrapped in `#ifndef RFC1535'). |
| 24 | |
| 25 | * The RES_DEBUG option (`options debug' in /etc/resolv.conf) has been |
| 26 | disabled. |
| 27 | |
| 28 | * The resolver in glibc allows underscores in domain names. |
| 29 | |
| 30 | * The <resolv.h> header in glibc includes <netinet/in.h> and |
| 31 | <arpa/nameser.h> to make it self-contained. |
| 32 | |
| 33 | * The `res_close' function in glibc only tries to close open files |
| 34 | referenced through `_res' if the RES_INIT bit is set in |
| 35 | `_res.options'. This fixes a potential security bug with programs |
| 36 | that bogusly call `res_close' without initialising the resolver |
| 37 | state first. Note that the thread-safe `res_nclose' still doesn't |
| 38 | check the RES_INIT bit. By the way, you're not really supposed to |
| 39 | call `res_close/res_nclose' directly. |
| 40 | |
| 41 | * The resolver in glibc can connect to a nameserver over IPv6. Just |
| 42 | specify the IPv6 address in /etc/resolv.conf. You cannot change the |
| 43 | address of an IPv6 nameserver dynamically in your program though. |
| 44 | |
| 45 | |
| 46 | Using the resolver in multi-threaded code |
| 47 | ========================================= |
| 48 | |
| 49 | The traditional resolver interfaces `res_query', `res_search', |
| 50 | `res_mkquery', `res_send' and `res_init', used a static (global) |
| 51 | resolver state stored in the `_res' structure. Therefore, these |
| 52 | interfaces are not thread-safe. Therefore, BIND 8.2 introduced a set |
| 53 | of "new" interfaces `res_nquery', `res_nsearch', `res_nmkquery', |
| 54 | `res_nsend' and `res_ninit' that take a `res_state' as their first |
| 55 | argument, so you can use a per-thread resolver state. In glibc, when |
| 56 | you link with -lpthread, such a per-thread resolver state is already |
| 57 | present. It can be accessed using `_res', which has been redefined as |
| 58 | a macro, in a similar way to what has been done for the `errno' and |
| 59 | `h_errno' variables. This per-thread resolver state is also used for |
| 60 | the `gethostby*' family of functions, which means that for example |
| 61 | `gethostbyname_r' is now fully thread-safe and re-entrant. The |
| 62 | traditional resolver interfaces however, continue to use a single |
| 63 | resolver state and are therefore still thread-unsafe. The resolver |
| 64 | state is the same resolver state that is used for the initial ("main") |
| 65 | thread. |
| 66 | |
| 67 | This has the following consequences for existing binaries and source |
| 68 | code: |
| 69 | |
| 70 | * Single-threaded programs will continue to work. There should be no |
| 71 | user-visible changes when you recompile them. |
| 72 | |
| 73 | * Multi-threaded programs that use the traditional resolver interfaces |
| 74 | in the "main" thread should continue to work, except that they no |
| 75 | longer see any changes in the global resolver state caused by calls |
| 76 | to, for example, `gethostbyname' in other threads. Again there |
| 77 | should be no user-visible changes when you recompile these programs. |
| 78 | |
| 79 | * Multi-threaded programs that use the traditional resolver interfaces |
| 80 | in more than one thread should be just as buggy as before (there are |
| 81 | no problems if you use proper locking of course). If you recompile |
| 82 | these programs, manipulating the _res structure in threads other |
| 83 | than the "main" thread will seem to have no effect though. |
| 84 | |
| 85 | * In Multi-threaded that manipulate the _res structure, calls to |
| 86 | functions like `gethostbyname' in threads other than the "main" |
| 87 | thread won't be influenced by the those changes anymore. So if you |
| 88 | set RES_USE_INET6, a call to `gethostbyname' won't return any IPv6 |
| 89 | hosts anymore. If you recompile such programs, manipulating the |
| 90 | _res structure will affect the thread in which you do so instead of |
| 91 | the "main" thread. |
| 92 | |
| 93 | We recommend to use the new thread-safe interfaces in new code, since |
| 94 | the traditional interfaces have been deprecated by the BIND folks. |
| 95 | For compatibility with other (older) systems you might want to |
| 96 | continue to use those interfaces though. |
| 97 | |
| 98 | |
| 99 | Using the resolver in C++ code |
| 100 | ============================== |
| 101 | |
| 102 | There resolver contains some hooks which will allow the user to |
| 103 | install some callback functions that make it possible to filter DNS |
| 104 | requests and responses. Although we do not encourage you to make use |
| 105 | of this facility at all, C++ developers should realise that it isn't |
| 106 | safe to throw exceptions from such callback functions. |
| 107 | |
| 108 | |
| 109 | Source code |
| 110 | =========== |
| 111 | |
| 112 | The following files come from the BIND distribution (currently version |
| 113 | 8.2.3-T5B): |
| 114 | |
| 115 | src/include/ |
| 116 | arpa/nameser.h |
| 117 | arpa/nameser_compat.h |
| 118 | resolv.h |
| 119 | |
| 120 | src/lib/resolv/ |
| 121 | herror.c |
| 122 | res_comp.c |
| 123 | res_data.c |
| 124 | res_debug.c |
| 125 | res_debug.h |
| 126 | res_init.c |
| 127 | res_mkquery.c |
| 128 | res_query.c |
| 129 | res_send.c |
| 130 | |
| 131 | src/lib/nameser/ |
| 132 | ns_name.c |
| 133 | ns_netint.c |
| 134 | ns_parse.c |
| 135 | ns_print.c |
| 136 | ns_samedomain.c |
| 137 | ns_ttl.c |
| 138 | |
| 139 | src/lib/inet/ |
| 140 | inet_addr.c |
| 141 | inet_net_ntop.c |
| 142 | inet_net_pton.c |
| 143 | inet_neta.c |
| 144 | inet_ntop.c |
| 145 | inet_pton.c |
| 146 | nsap_addr.c |
| 147 | |
| 148 | src/lib/isc/ |
| 149 | base64.c |
| 150 | |
| 151 | Some of these files have been optimised a bit, and adaptations have |
| 152 | been made to make them fit in with the rest of glibc. The more |
| 153 | non-obvious changes are wrapped in something like `#ifdef _LIBC'. |
| 154 | |
| 155 | res_libc.c is home-brewn, although parts of it are taken from res_data.c. |
| 156 | |
| 157 | res_hconf.c and res_hconf.h were contributed by David Mosberger, and |
| 158 | do not come from BIND. |
| 159 | |
| 160 | The files gethnamaddr.c, mapv4v6addr.h and mapv4v6hostent.h are |
| 161 | leftovers from BIND 4.9.7. |