You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
924 lines
32 KiB
924 lines
32 KiB
diff -up bind-9.9.4/bin/named/config.c.CVE-2014-8500 bind-9.9.4/bin/named/config.c |
|
--- bind-9.9.4/bin/named/config.c.CVE-2014-8500 2013-09-05 07:09:08.000000000 +0200 |
|
+++ bind-9.9.4/bin/named/config.c 2014-12-10 14:56:24.959552559 +0100 |
|
@@ -160,6 +160,8 @@ options {\n\ |
|
dnssec-accept-expired no;\n\ |
|
clients-per-query 10;\n\ |
|
max-clients-per-query 100;\n\ |
|
+ max-recursion-depth 7;\n\ |
|
+ max-recursion-queries 50;\n\ |
|
zero-no-soa-ttl-cache no;\n\ |
|
nsec3-test-zone no;\n\ |
|
allow-new-zones no;\n\ |
|
diff -up bind-9.9.4/bin/named/query.c.CVE-2014-8500 bind-9.9.4/bin/named/query.c |
|
--- bind-9.9.4/bin/named/query.c.CVE-2014-8500 2014-12-10 14:56:24.945552543 +0100 |
|
+++ bind-9.9.4/bin/named/query.c 2014-12-10 14:56:24.960552560 +0100 |
|
@@ -3872,12 +3872,11 @@ query_recurse(ns_client_t *client, dns_r |
|
peeraddr = &client->peeraddr; |
|
else |
|
peeraddr = NULL; |
|
- result = dns_resolver_createfetch2(client->view->resolver, |
|
+ result = dns_resolver_createfetch3(client->view->resolver, |
|
qname, qtype, qdomain, nameservers, |
|
NULL, peeraddr, client->message->id, |
|
- client->query.fetchoptions, |
|
- client->task, |
|
- query_resume, client, |
|
+ client->query.fetchoptions, 0, NULL, |
|
+ client->task, query_resume, client, |
|
rdataset, sigrdataset, |
|
&client->query.fetch); |
|
|
|
diff -up bind-9.9.4/bin/named/server.c.CVE-2014-8500 bind-9.9.4/bin/named/server.c |
|
--- bind-9.9.4/bin/named/server.c.CVE-2014-8500 2014-12-10 14:56:24.913552507 +0100 |
|
+++ bind-9.9.4/bin/named/server.c 2014-12-10 14:56:24.961552561 +0100 |
|
@@ -3205,6 +3205,16 @@ configure_view(dns_view_t *view, cfg_obj |
|
cfg_obj_asuint32(obj), |
|
max_clients_per_query); |
|
|
|
+ obj = NULL; |
|
+ result = ns_config_get(maps, "max-recursion-depth", &obj); |
|
+ INSIST(result == ISC_R_SUCCESS); |
|
+ dns_resolver_setmaxdepth(view->resolver, cfg_obj_asuint32(obj)); |
|
+ |
|
+ obj = NULL; |
|
+ result = ns_config_get(maps, "max-recursion-queries", &obj); |
|
+ INSIST(result == ISC_R_SUCCESS); |
|
+ dns_resolver_setmaxqueries(view->resolver, cfg_obj_asuint32(obj)); |
|
+ |
|
#ifdef ALLOW_FILTER_AAAA_ON_V4 |
|
obj = NULL; |
|
result = ns_config_get(maps, "filter-aaaa-on-v4", &obj); |
|
diff -up bind-9.9.4/doc/arm/Bv9ARM-book.xml.CVE-2014-8500 bind-9.9.4/doc/arm/Bv9ARM-book.xml |
|
--- bind-9.9.4/doc/arm/Bv9ARM-book.xml.CVE-2014-8500 2014-12-10 14:56:24.957552556 +0100 |
|
+++ bind-9.9.4/doc/arm/Bv9ARM-book.xml 2014-12-10 15:00:53.108931629 +0100 |
|
@@ -4874,6 +4874,8 @@ badresp:1,adberr:0,findfail:0,valfail:0] |
|
<optional> max-acache-size <replaceable>size_spec</replaceable> ; </optional> |
|
<optional> clients-per-query <replaceable>number</replaceable> ; </optional> |
|
<optional> max-clients-per-query <replaceable>number</replaceable> ; </optional> |
|
+ <optional> max-recursion-depth <replaceable>number</replaceable> ; </optional> |
|
+ <optional> max-recursion-queries <replaceable>number</replaceable> ; </optional> |
|
<optional> masterfile-format (<constant>text</constant>|<constant>raw</constant>) ; </optional> |
|
<optional> empty-server <replaceable>name</replaceable> ; </optional> |
|
<optional> empty-contact <replaceable>name</replaceable> ; </optional> |
|
@@ -8623,6 +8625,35 @@ avoid-v6-udp-ports { 40000; range 50000 |
|
</para> |
|
</listitem> |
|
</varlistentry> |
|
+ |
|
+ <varlistentry id="max-recursion-depth"> |
|
+ <term><command>max-recursion-depth</command></term> |
|
+ <listitem> |
|
+ <para> |
|
+ Sets the maximum number of levels of recursion |
|
+ that are permitted at any one time while servicing |
|
+ a recursive query. Resolving a name may require |
|
+ looking up a name server address, which in turn |
|
+ requires resolving another name, etc; if the number |
|
+ of indirections exceeds this value, the recursive |
|
+ query is terminated and returns SERVFAIL. The |
|
+ default is 7. |
|
+ </para> |
|
+ </listitem> |
|
+ </varlistentry> |
|
+ |
|
+ <varlistentry id="max-recursion-queries"> |
|
+ <term><command>max-recursion-queries</command></term> |
|
+ <listitem> |
|
+ <para> |
|
+ Sets the maximum number of iterative queries that |
|
+ may be sent while servicing a recursive query. |
|
+ If more queries are sent, the recursive query |
|
+ is terminated and returns SERVFAIL. The default |
|
+ is 50. |
|
+ </para> |
|
+ </listitem> |
|
+ </varlistentry> |
|
|
|
<varlistentry> |
|
<term><command>notify-delay</command></term> |
|
diff -up bind-9.9.4/doc/misc/options.CVE-2014-8500 bind-9.9.4/doc/misc/options |
|
--- bind-9.9.4/doc/misc/options.CVE-2014-8500 2013-09-05 07:09:08.000000000 +0200 |
|
+++ bind-9.9.4/doc/misc/options 2014-12-10 14:56:24.964552564 +0100 |
|
@@ -162,6 +162,8 @@ options { |
|
max-ixfr-log-size <size>; // obsolete |
|
max-journal-size <size_no_default>; |
|
max-ncache-ttl <integer>; |
|
+ max-recursion-depth <integer>; |
|
+ max-recursion-queries <integer>; |
|
max-refresh-time <integer>; |
|
max-retry-time <integer>; |
|
max-rsa-exponent-size <integer>; |
|
@@ -385,6 +387,8 @@ view <string> <optional_class> { |
|
max-ixfr-log-size <size>; // obsolete |
|
max-journal-size <size_no_default>; |
|
max-ncache-ttl <integer>; |
|
+ max-recursion-depth <integer>; |
|
+ max-recursion-queries <integer>; |
|
max-refresh-time <integer>; |
|
max-retry-time <integer>; |
|
max-transfer-idle-in <integer>; |
|
diff -up bind-9.9.4/lib/dns/adb.c.CVE-2014-8500 bind-9.9.4/lib/dns/adb.c |
|
--- bind-9.9.4/lib/dns/adb.c.CVE-2014-8500 2013-09-05 07:09:08.000000000 +0200 |
|
+++ bind-9.9.4/lib/dns/adb.c 2014-12-10 14:56:24.965552566 +0100 |
|
@@ -201,6 +201,7 @@ struct dns_adbfetch { |
|
unsigned int magic; |
|
dns_fetch_t *fetch; |
|
dns_rdataset_t rdataset; |
|
+ unsigned int depth; |
|
}; |
|
|
|
/*% |
|
@@ -300,8 +301,7 @@ static inline isc_boolean_t dec_entry_re |
|
static inline void violate_locking_hierarchy(isc_mutex_t *, isc_mutex_t *); |
|
static isc_boolean_t clean_namehooks(dns_adb_t *, dns_adbnamehooklist_t *); |
|
static void clean_target(dns_adb_t *, dns_name_t *); |
|
-static void clean_finds_at_name(dns_adbname_t *, isc_eventtype_t, |
|
- unsigned int); |
|
+static void clean_finds_at_name(dns_adbname_t *, isc_eventtype_t, unsigned int); |
|
static isc_boolean_t check_expire_namehooks(dns_adbname_t *, isc_stdtime_t); |
|
static isc_boolean_t check_expire_entry(dns_adb_t *, dns_adbentry_t **, |
|
isc_stdtime_t); |
|
@@ -309,6 +309,7 @@ static void cancel_fetches_at_name(dns_a |
|
static isc_result_t dbfind_name(dns_adbname_t *, isc_stdtime_t, |
|
dns_rdatatype_t); |
|
static isc_result_t fetch_name(dns_adbname_t *, isc_boolean_t, |
|
+ unsigned int, isc_counter_t *qc, |
|
dns_rdatatype_t); |
|
static inline void check_exit(dns_adb_t *); |
|
static void destroy(dns_adb_t *); |
|
@@ -2770,6 +2771,19 @@ dns_adb_createfind(dns_adb_t *adb, isc_t |
|
isc_stdtime_t now, dns_name_t *target, |
|
in_port_t port, dns_adbfind_t **findp) |
|
{ |
|
+ return (dns_adb_createfind2(adb, task, action, arg, name, |
|
+ qname, qtype, options, now, |
|
+ target, port, 0, NULL, findp)); |
|
+} |
|
+ |
|
+isc_result_t |
|
+dns_adb_createfind2(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action, |
|
+ void *arg, dns_name_t *name, dns_name_t *qname, |
|
+ dns_rdatatype_t qtype, unsigned int options, |
|
+ isc_stdtime_t now, dns_name_t *target, |
|
+ in_port_t port, unsigned int depth, isc_counter_t *qc, |
|
+ dns_adbfind_t **findp) |
|
+{ |
|
dns_adbfind_t *find; |
|
dns_adbname_t *adbname; |
|
int bucket; |
|
@@ -3000,7 +3014,7 @@ dns_adb_createfind(dns_adb_t *adb, isc_t |
|
* Start V4. |
|
*/ |
|
if (WANT_INET(wanted_fetches) && |
|
- fetch_name(adbname, start_at_zone, |
|
+ fetch_name(adbname, start_at_zone, depth, qc, |
|
dns_rdatatype_a) == ISC_R_SUCCESS) { |
|
DP(DEF_LEVEL, |
|
"dns_adb_createfind: started A fetch for name %p", |
|
@@ -3011,7 +3025,7 @@ dns_adb_createfind(dns_adb_t *adb, isc_t |
|
* Start V6. |
|
*/ |
|
if (WANT_INET6(wanted_fetches) && |
|
- fetch_name(adbname, start_at_zone, |
|
+ fetch_name(adbname, start_at_zone, depth, qc, |
|
dns_rdatatype_aaaa) == ISC_R_SUCCESS) { |
|
DP(DEF_LEVEL, |
|
"dns_adb_createfind: " |
|
@@ -3754,6 +3768,12 @@ fetch_callback(isc_task_t *task, isc_eve |
|
DP(DEF_LEVEL, "adb: fetch of '%s' %s failed: %s", |
|
buf, address_type == DNS_ADBFIND_INET ? "A" : "AAAA", |
|
dns_result_totext(dev->result)); |
|
+ /* |
|
+ * Don't record a failure unless this is the initial |
|
+ * fetch of a chain. |
|
+ */ |
|
+ if (fetch->depth > 1) |
|
+ goto out; |
|
/* XXXMLG Don't pound on bad servers. */ |
|
if (address_type == DNS_ADBFIND_INET) { |
|
name->expire_v4 = ISC_MIN(name->expire_v4, now + 300); |
|
@@ -3791,9 +3811,8 @@ fetch_callback(isc_task_t *task, isc_eve |
|
} |
|
|
|
static isc_result_t |
|
-fetch_name(dns_adbname_t *adbname, |
|
- isc_boolean_t start_at_zone, |
|
- dns_rdatatype_t type) |
|
+fetch_name(dns_adbname_t *adbname, isc_boolean_t start_at_zone, |
|
+ unsigned int depth, isc_counter_t *qc, dns_rdatatype_t type) |
|
{ |
|
isc_result_t result; |
|
dns_adbfetch_t *fetch = NULL; |
|
@@ -3838,12 +3857,14 @@ fetch_name(dns_adbname_t *adbname, |
|
result = ISC_R_NOMEMORY; |
|
goto cleanup; |
|
} |
|
+ fetch->depth = depth; |
|
|
|
- result = dns_resolver_createfetch(adb->view->resolver, &adbname->name, |
|
- type, name, nameservers, NULL, |
|
- options, adb->task, fetch_callback, |
|
- adbname, &fetch->rdataset, NULL, |
|
- &fetch->fetch); |
|
+ result = dns_resolver_createfetch3(adb->view->resolver, &adbname->name, |
|
+ type, name, nameservers, NULL, |
|
+ NULL, 0, options, depth, qc, |
|
+ adb->task, fetch_callback, adbname, |
|
+ &fetch->rdataset, NULL, |
|
+ &fetch->fetch); |
|
if (result != ISC_R_SUCCESS) |
|
goto cleanup; |
|
|
|
diff -up bind-9.9.4/lib/dns/include/dns/adb.h.CVE-2014-8500 bind-9.9.4/lib/dns/include/dns/adb.h |
|
--- bind-9.9.4/lib/dns/include/dns/adb.h.CVE-2014-8500 2013-09-05 07:09:08.000000000 +0200 |
|
+++ bind-9.9.4/lib/dns/include/dns/adb.h 2014-12-10 14:56:24.965552566 +0100 |
|
@@ -334,6 +334,13 @@ dns_adb_createfind(dns_adb_t *adb, isc_t |
|
dns_rdatatype_t qtype, unsigned int options, |
|
isc_stdtime_t now, dns_name_t *target, |
|
in_port_t port, dns_adbfind_t **find); |
|
+isc_result_t |
|
+dns_adb_createfind2(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action, |
|
+ void *arg, dns_name_t *name, dns_name_t *qname, |
|
+ dns_rdatatype_t qtype, unsigned int options, |
|
+ isc_stdtime_t now, dns_name_t *target, in_port_t port, |
|
+ unsigned int depth, isc_counter_t *qc, |
|
+ dns_adbfind_t **find); |
|
/*%< |
|
* Main interface for clients. The adb will look up the name given in |
|
* "name" and will build up a list of found addresses, and perhaps start |
|
diff -up bind-9.9.4/lib/dns/include/dns/resolver.h.CVE-2014-8500 bind-9.9.4/lib/dns/include/dns/resolver.h |
|
--- bind-9.9.4/lib/dns/include/dns/resolver.h.CVE-2014-8500 2013-09-05 07:09:08.000000000 +0200 |
|
+++ bind-9.9.4/lib/dns/include/dns/resolver.h 2014-12-10 14:56:24.965552566 +0100 |
|
@@ -274,6 +274,18 @@ dns_resolver_createfetch2(dns_resolver_t |
|
dns_rdataset_t *rdataset, |
|
dns_rdataset_t *sigrdataset, |
|
dns_fetch_t **fetchp); |
|
+isc_result_t |
|
+dns_resolver_createfetch3(dns_resolver_t *res, dns_name_t *name, |
|
+ dns_rdatatype_t type, |
|
+ dns_name_t *domain, dns_rdataset_t *nameservers, |
|
+ dns_forwarders_t *forwarders, |
|
+ isc_sockaddr_t *client, isc_uint16_t id, |
|
+ unsigned int options, unsigned int depth, |
|
+ isc_counter_t *qc, isc_task_t *task, |
|
+ isc_taskaction_t action, void *arg, |
|
+ dns_rdataset_t *rdataset, |
|
+ dns_rdataset_t *sigrdataset, |
|
+ dns_fetch_t **fetchp); |
|
/*%< |
|
* Recurse to answer a question. |
|
* |
|
@@ -573,6 +585,30 @@ dns_resolver_printbadcache(dns_resolver_ |
|
* |
|
* Requires: |
|
* \li resolver to be valid. |
|
+ */ |
|
+ |
|
+void |
|
+dns_resolver_setmaxdepth(dns_resolver_t *resolver, unsigned int maxdepth); |
|
+unsigned int |
|
+dns_resolver_getmaxdepth(dns_resolver_t *resolver); |
|
+/*% |
|
+ * Get and set how many NS indirections will be followed when looking for |
|
+ * nameserver addresses. |
|
+ * |
|
+ * Requires: |
|
+ * \li resolver to be valid. |
|
+ */ |
|
+ |
|
+void |
|
+dns_resolver_setmaxqueries(dns_resolver_t *resolver, unsigned int queries); |
|
+unsigned int |
|
+dns_resolver_getmaxqueries(dns_resolver_t *resolver); |
|
+/*% |
|
+ * Get and set how many iterative queries will be allowed before |
|
+ * terminating a recursive query. |
|
+ * |
|
+ * Requires: |
|
+ * \li resolver to be valid. |
|
*/ |
|
|
|
ISC_LANG_ENDDECLS |
|
diff -up bind-9.9.4/lib/dns/resolver.c.CVE-2014-8500 bind-9.9.4/lib/dns/resolver.c |
|
--- bind-9.9.4/lib/dns/resolver.c.CVE-2014-8500 2014-12-10 14:56:24.952552551 +0100 |
|
+++ bind-9.9.4/lib/dns/resolver.c 2014-12-10 15:01:56.855970646 +0100 |
|
@@ -21,6 +21,7 @@ |
|
|
|
#include <config.h> |
|
|
|
+#include <isc/counter.h> |
|
#include <isc/log.h> |
|
#include <isc/platform.h> |
|
#include <isc/print.h> |
|
@@ -130,6 +131,16 @@ |
|
#define MAXIMUM_QUERY_TIMEOUT 30 /* The maximum time in seconds for the whole query to live. */ |
|
#endif |
|
|
|
+/* The default maximum number of recursions to follow before giving up. */ |
|
+#ifndef DEFAULT_RECURSION_DEPTH |
|
+#define DEFAULT_RECURSION_DEPTH 7 |
|
+#endif |
|
+ |
|
+/* The default maximum number of iterative queries to allow before giving up. */ |
|
+#ifndef DEFAULT_MAX_QUERIES |
|
+#define DEFAULT_MAX_QUERIES 50 |
|
+#endif |
|
+ |
|
/*% |
|
* Maximum EDNS0 input packet size. |
|
*/ |
|
@@ -233,12 +244,13 @@ struct fetchctx { |
|
isc_sockaddrlist_t edns; |
|
isc_sockaddrlist_t edns512; |
|
isc_sockaddrlist_t bad_edns; |
|
- dns_validator_t *validator; |
|
+ dns_validator_t * validator; |
|
ISC_LIST(dns_validator_t) validators; |
|
dns_db_t * cache; |
|
dns_adb_t * adb; |
|
isc_boolean_t ns_ttl_ok; |
|
isc_uint32_t ns_ttl; |
|
+ isc_counter_t * qc; |
|
|
|
/*% |
|
* The number of events we're waiting for. |
|
@@ -306,6 +318,7 @@ struct fetchctx { |
|
isc_boolean_t timeout; |
|
dns_adbaddrinfo_t *addrinfo; |
|
isc_sockaddr_t *client; |
|
+ unsigned int depth; |
|
}; |
|
|
|
#define FCTX_MAGIC ISC_MAGIC('F', '!', '!', '!') |
|
@@ -418,6 +431,8 @@ struct dns_resolver { |
|
isc_timer_t * spillattimer; |
|
isc_boolean_t zero_no_soa_ttl; |
|
unsigned int query_timeout; |
|
+ unsigned int maxdepth; |
|
+ unsigned int maxqueries; |
|
|
|
/* Locked by lock. */ |
|
unsigned int references; |
|
@@ -1533,6 +1548,7 @@ fctx_query(fetchctx_t *fctx, dns_adbaddr |
|
if (result != ISC_R_SUCCESS) |
|
goto cleanup_dispatch; |
|
} |
|
+ |
|
fctx->querysent++; |
|
|
|
ISC_LIST_APPEND(fctx->queries, query, link); |
|
@@ -2186,9 +2202,9 @@ fctx_finddone(isc_task_t *task, isc_even |
|
*/ |
|
INSIST(!SHUTTINGDOWN(fctx)); |
|
fctx->attributes &= ~FCTX_ATTR_ADDRWAIT; |
|
- if (event->ev_type == DNS_EVENT_ADBMOREADDRESSES) |
|
+ if (event->ev_type == DNS_EVENT_ADBMOREADDRESSES) { |
|
want_try = ISC_TRUE; |
|
- else { |
|
+ } else { |
|
fctx->findfail++; |
|
if (fctx->pending == 0) { |
|
/* |
|
@@ -2471,12 +2487,13 @@ findname(fetchctx_t *fctx, dns_name_t *n |
|
* See what we know about this address. |
|
*/ |
|
find = NULL; |
|
- result = dns_adb_createfind(fctx->adb, |
|
- res->buckets[fctx->bucketnum].task, |
|
- fctx_finddone, fctx, name, |
|
- &fctx->name, fctx->type, |
|
- options, now, NULL, |
|
- res->view->dstport, &find); |
|
+ result = dns_adb_createfind2(fctx->adb, |
|
+ res->buckets[fctx->bucketnum].task, |
|
+ fctx_finddone, fctx, name, |
|
+ &fctx->name, fctx->type, |
|
+ options, now, NULL, |
|
+ res->view->dstport, |
|
+ fctx->depth + 1, fctx->qc, &find); |
|
if (result != ISC_R_SUCCESS) { |
|
if (result == DNS_R_ALIAS) { |
|
/* |
|
@@ -2584,6 +2601,14 @@ fctx_getaddresses(fetchctx_t *fctx, isc_ |
|
|
|
res = fctx->res; |
|
|
|
+ if (fctx->depth > res->maxdepth) { |
|
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER, |
|
+ DNS_LOGMODULE_RESOLVER, ISC_LOG_DEBUG(3), |
|
+ "too much NS indirection resolving '%s'", |
|
+ fctx->info); |
|
+ return (DNS_R_SERVFAIL); |
|
+ } |
|
+ |
|
/* |
|
* Forwarders. |
|
*/ |
|
@@ -3059,6 +3084,16 @@ fctx_try(fetchctx_t *fctx, isc_boolean_t |
|
} |
|
} |
|
|
|
+ result = isc_counter_increment(fctx->qc); |
|
+ if (result != ISC_R_SUCCESS) { |
|
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER, |
|
+ DNS_LOGMODULE_RESOLVER, ISC_LOG_DEBUG(3), |
|
+ "exceeded max queries resolving '%s'", |
|
+ fctx->info); |
|
+ fctx_done(fctx, DNS_R_SERVFAIL, __LINE__); |
|
+ return; |
|
+ } |
|
+ |
|
result = fctx_query(fctx, addrinfo, fctx->options); |
|
if (result != ISC_R_SUCCESS) |
|
fctx_done(fctx, result, __LINE__); |
|
@@ -3157,6 +3192,7 @@ fctx_destroy(fetchctx_t *fctx) { |
|
isc_mem_put(fctx->mctx, sa, sizeof(*sa)); |
|
} |
|
|
|
+ isc_counter_detach(&fctx->qc); |
|
isc_timer_detach(&fctx->timer); |
|
dns_message_destroy(&fctx->rmessage); |
|
dns_message_destroy(&fctx->qmessage); |
|
@@ -3485,7 +3521,8 @@ log_ns_ttl(fetchctx_t *fctx, const char |
|
static isc_result_t |
|
fctx_create(dns_resolver_t *res, dns_name_t *name, dns_rdatatype_t type, |
|
dns_name_t *domain, dns_rdataset_t *nameservers, |
|
- unsigned int options, unsigned int bucketnum, fetchctx_t **fctxp) |
|
+ unsigned int options, unsigned int bucketnum, unsigned int depth, |
|
+ isc_counter_t *qc, fetchctx_t **fctxp) |
|
{ |
|
fetchctx_t *fctx; |
|
isc_result_t result; |
|
@@ -3507,6 +3544,21 @@ fctx_create(dns_resolver_t *res, dns_nam |
|
fctx = isc_mem_get(mctx, sizeof(*fctx)); |
|
if (fctx == NULL) |
|
return (ISC_R_NOMEMORY); |
|
+ |
|
+ fctx->qc = NULL; |
|
+ if (qc != NULL) { |
|
+ isc_counter_attach(qc, &fctx->qc); |
|
+ } else { |
|
+ result = isc_counter_create(res->mctx, |
|
+ res->maxqueries, &fctx->qc); |
|
+ if (result != ISC_R_SUCCESS) |
|
+ goto cleanup_fetch; |
|
+ } |
|
+ |
|
+ /* |
|
+ * Make fctx->info point to a copy of a formatted string |
|
+ * "name/type". |
|
+ */ |
|
dns_name_format(name, buf, sizeof(buf)); |
|
dns_rdatatype_format(type, typebuf, sizeof(typebuf)); |
|
strcat(buf, "/"); /* checked */ |
|
@@ -3514,7 +3566,7 @@ fctx_create(dns_resolver_t *res, dns_nam |
|
fctx->info = isc_mem_strdup(mctx, buf); |
|
if (fctx->info == NULL) { |
|
result = ISC_R_NOMEMORY; |
|
- goto cleanup_fetch; |
|
+ goto cleanup_counter; |
|
} |
|
FCTXTRACE("create"); |
|
dns_name_init(&fctx->name, NULL); |
|
@@ -3537,6 +3589,7 @@ fctx_create(dns_resolver_t *res, dns_nam |
|
fctx->state = fetchstate_init; |
|
fctx->want_shutdown = ISC_FALSE; |
|
fctx->cloned = ISC_FALSE; |
|
+ fctx->depth = depth; |
|
ISC_LIST_INIT(fctx->queries); |
|
ISC_LIST_INIT(fctx->finds); |
|
ISC_LIST_INIT(fctx->altfinds); |
|
@@ -3742,6 +3795,9 @@ fctx_create(dns_resolver_t *res, dns_nam |
|
cleanup_info: |
|
isc_mem_free(mctx, fctx->info); |
|
|
|
+ cleanup_counter: |
|
+ isc_counter_detach(&fctx->qc); |
|
+ |
|
cleanup_fetch: |
|
isc_mem_put(mctx, fctx, sizeof(*fctx)); |
|
|
|
@@ -5655,7 +5711,7 @@ noanswer_response(fetchctx_t *fctx, dns_ |
|
char qbuf[DNS_NAME_FORMATSIZE]; |
|
char nbuf[DNS_NAME_FORMATSIZE]; |
|
char tbuf[DNS_RDATATYPE_FORMATSIZE]; |
|
- dns_rdatatype_format(fctx->type, tbuf, |
|
+ dns_rdatatype_format(type, tbuf, |
|
sizeof(tbuf)); |
|
dns_name_format(name, nbuf, |
|
sizeof(nbuf)); |
|
@@ -5664,7 +5720,7 @@ noanswer_response(fetchctx_t *fctx, dns_ |
|
log_formerr(fctx, |
|
"unrelated %s %s in " |
|
"%s authority section", |
|
- tbuf, qbuf, nbuf); |
|
+ tbuf, nbuf, qbuf); |
|
return (DNS_R_FORMERR); |
|
} |
|
if (type == dns_rdatatype_ns) { |
|
@@ -7725,6 +7781,8 @@ dns_resolver_create(dns_view_t *view, |
|
res->spillattimer = NULL; |
|
res->zero_no_soa_ttl = ISC_FALSE; |
|
res->query_timeout = DEFAULT_QUERY_TIMEOUT; |
|
+ res->maxdepth = DEFAULT_RECURSION_DEPTH; |
|
+ res->maxqueries = DEFAULT_MAX_QUERIES; |
|
res->nbuckets = ntasks; |
|
res->activebuckets = ntasks; |
|
res->buckets = isc_mem_get(view->mctx, |
|
@@ -8163,9 +8221,9 @@ dns_resolver_createfetch(dns_resolver_t |
|
dns_rdataset_t *sigrdataset, |
|
dns_fetch_t **fetchp) |
|
{ |
|
- return (dns_resolver_createfetch2(res, name, type, domain, |
|
+ return (dns_resolver_createfetch3(res, name, type, domain, |
|
nameservers, forwarders, NULL, 0, |
|
- options, task, action, arg, |
|
+ options, 0, NULL, task, action, arg, |
|
rdataset, sigrdataset, fetchp)); |
|
} |
|
|
|
@@ -8181,6 +8239,25 @@ dns_resolver_createfetch2(dns_resolver_t |
|
dns_rdataset_t *sigrdataset, |
|
dns_fetch_t **fetchp) |
|
{ |
|
+ return (dns_resolver_createfetch3(res, name, type, domain, |
|
+ nameservers, forwarders, client, id, |
|
+ options, 0, NULL, task, action, arg, |
|
+ rdataset, sigrdataset, fetchp)); |
|
+} |
|
+ |
|
+isc_result_t |
|
+dns_resolver_createfetch3(dns_resolver_t *res, dns_name_t *name, |
|
+ dns_rdatatype_t type, |
|
+ dns_name_t *domain, dns_rdataset_t *nameservers, |
|
+ dns_forwarders_t *forwarders, |
|
+ isc_sockaddr_t *client, dns_messageid_t id, |
|
+ unsigned int options, unsigned int depth, |
|
+ isc_counter_t *qc, isc_task_t *task, |
|
+ isc_taskaction_t action, void *arg, |
|
+ dns_rdataset_t *rdataset, |
|
+ dns_rdataset_t *sigrdataset, |
|
+ dns_fetch_t **fetchp) |
|
+{ |
|
dns_fetch_t *fetch; |
|
fetchctx_t *fctx = NULL; |
|
isc_result_t result = ISC_R_SUCCESS; |
|
@@ -8269,11 +8346,12 @@ dns_resolver_createfetch2(dns_resolver_t |
|
|
|
if (fctx == NULL) { |
|
result = fctx_create(res, name, type, domain, nameservers, |
|
- options, bucketnum, &fctx); |
|
+ options, bucketnum, depth, qc, &fctx); |
|
if (result != ISC_R_SUCCESS) |
|
goto unlock; |
|
new_fctx = ISC_TRUE; |
|
- } |
|
+ } else if (fctx->depth > depth) |
|
+ fctx->depth = depth; |
|
|
|
result = fctx_join(fctx, task, client, id, action, arg, |
|
rdataset, sigrdataset, fetch); |
|
@@ -9045,3 +9123,27 @@ dns_resolver_settimeout(dns_resolver_t * |
|
|
|
resolver->query_timeout = seconds; |
|
} |
|
+ |
|
+void |
|
+dns_resolver_setmaxdepth(dns_resolver_t *resolver, unsigned int maxdepth) { |
|
+ REQUIRE(VALID_RESOLVER(resolver)); |
|
+ resolver->maxdepth = maxdepth; |
|
+} |
|
+ |
|
+unsigned int |
|
+dns_resolver_getmaxdepth(dns_resolver_t *resolver) { |
|
+ REQUIRE(VALID_RESOLVER(resolver)); |
|
+ return (resolver->maxdepth); |
|
+} |
|
+ |
|
+void |
|
+dns_resolver_setmaxqueries(dns_resolver_t *resolver, unsigned int queries) { |
|
+ REQUIRE(VALID_RESOLVER(resolver)); |
|
+ resolver->maxqueries = queries; |
|
+} |
|
+ |
|
+unsigned int |
|
+dns_resolver_getmaxqueries(dns_resolver_t *resolver) { |
|
+ REQUIRE(VALID_RESOLVER(resolver)); |
|
+ return (resolver->maxqueries); |
|
+} |
|
diff -up bind-9.9.4/lib/export/isc/Makefile.in.CVE-2014-8500 bind-9.9.4/lib/export/isc/Makefile.in |
|
--- bind-9.9.4/lib/export/isc/Makefile.in.CVE-2014-8500 2014-12-10 14:56:24.907552500 +0100 |
|
+++ bind-9.9.4/lib/export/isc/Makefile.in 2014-12-10 14:56:24.967552568 +0100 |
|
@@ -63,7 +63,7 @@ WIN32OBJS = win32/condition.@O@ win32/d |
|
# Alphabetically |
|
OBJS = @ISC_EXTRA_OBJS@ \ |
|
assertions.@O@ backtrace.@O@ backtrace-emptytbl.@O@ base32.@O@ \ |
|
- base64.@O@ buffer.@O@ bufferlist.@O@ \ |
|
+ base64.@O@ buffer.@O@ bufferlist.@O@ counter.@O@ \ |
|
error.@O@ event.@O@ \ |
|
hash.@O@ hex.@O@ hmacmd5.@O@ hmacsha.@O@ \ |
|
inet_aton.@O@ iterated_hash.@O@ lex.@O@ lfsr.@O@ log.@O@ \ |
|
@@ -85,7 +85,7 @@ ISCDRIVERSRCS = mem.c task.c lib.c timer |
|
|
|
SRCS = @ISC_EXTRA_SRCS@ \ |
|
assertions.c backtrace.c backtrace-emptytbl.c base32.c \ |
|
- base64.c buffer.c bufferlist.c \ |
|
+ base64.c buffer.c bufferlist.c counter.c \ |
|
error.c event.c \ |
|
hash.c hex.c hmacmd5.c hmacsha.c \ |
|
inet_aton.c iterated_hash.c lex.c log.c lfsr.c \ |
|
diff -up bind-9.9.4/lib/isccfg/namedconf.c.CVE-2014-8500 bind-9.9.4/lib/isccfg/namedconf.c |
|
--- bind-9.9.4/lib/isccfg/namedconf.c.CVE-2014-8500 2014-12-10 14:56:24.969552570 +0100 |
|
+++ bind-9.9.4/lib/isccfg/namedconf.c 2014-12-10 15:04:14.636091707 +0100 |
|
@@ -1421,6 +1421,8 @@ view_clauses[] = { |
|
{ "max-cache-ttl", &cfg_type_uint32, 0 }, |
|
{ "max-clients-per-query", &cfg_type_uint32, 0 }, |
|
{ "max-ncache-ttl", &cfg_type_uint32, 0 }, |
|
+ { "max-recursion-depth", &cfg_type_uint32, 0 }, |
|
+ { "max-recursion-queries", &cfg_type_uint32, 0 }, |
|
{ "max-udp-size", &cfg_type_uint32, 0 }, |
|
{ "min-roots", &cfg_type_uint32, CFG_CLAUSEFLAG_NOTIMP }, |
|
{ "minimal-responses", &cfg_type_boolean, 0 }, |
|
diff -up bind-9.9.4/lib/isc/counter.c.CVE-2014-8500 bind-9.9.4/lib/isc/counter.c |
|
--- bind-9.9.4/lib/isc/counter.c.CVE-2014-8500 2014-12-10 14:56:24.968552569 +0100 |
|
+++ bind-9.9.4/lib/isc/counter.c 2014-12-10 14:56:24.968552569 +0100 |
|
@@ -0,0 +1,138 @@ |
|
+/* |
|
+ * Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC") |
|
+ * |
|
+ * Permission to use, copy, modify, and/or distribute this software for any |
|
+ * purpose with or without fee is hereby granted, provided that the above |
|
+ * copyright notice and this permission notice appear in all copies. |
|
+ * |
|
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH |
|
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY |
|
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, |
|
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM |
|
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE |
|
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR |
|
+ * PERFORMANCE OF THIS SOFTWARE. |
|
+ */ |
|
+ |
|
+/*! \file */ |
|
+ |
|
+#include <config.h> |
|
+ |
|
+#include <stddef.h> |
|
+ |
|
+#include <isc/counter.h> |
|
+#include <isc/magic.h> |
|
+#include <isc/mem.h> |
|
+#include <isc/util.h> |
|
+ |
|
+#define COUNTER_MAGIC ISC_MAGIC('C', 'n', 't', 'r') |
|
+#define VALID_COUNTER(r) ISC_MAGIC_VALID(r, COUNTER_MAGIC) |
|
+ |
|
+struct isc_counter { |
|
+ unsigned int magic; |
|
+ isc_mem_t *mctx; |
|
+ isc_mutex_t lock; |
|
+ unsigned int references; |
|
+ unsigned int limit; |
|
+ unsigned int used; |
|
+}; |
|
+ |
|
+isc_result_t |
|
+isc_counter_create(isc_mem_t *mctx, int limit, isc_counter_t **counterp) { |
|
+ isc_result_t result; |
|
+ isc_counter_t *counter; |
|
+ |
|
+ REQUIRE(counterp != NULL && *counterp == NULL); |
|
+ |
|
+ counter = isc_mem_get(mctx, sizeof(*counter)); |
|
+ if (counter == NULL) |
|
+ return (ISC_R_NOMEMORY); |
|
+ |
|
+ result = isc_mutex_init(&counter->lock); |
|
+ if (result != ISC_R_SUCCESS) { |
|
+ isc_mem_put(mctx, counter, sizeof(*counter)); |
|
+ return (result); |
|
+ } |
|
+ |
|
+ counter->mctx = NULL; |
|
+ isc_mem_attach(mctx, &counter->mctx); |
|
+ |
|
+ counter->references = 1; |
|
+ counter->limit = limit; |
|
+ counter->used = 0; |
|
+ |
|
+ counter->magic = COUNTER_MAGIC; |
|
+ *counterp = counter; |
|
+ return (ISC_R_SUCCESS); |
|
+} |
|
+ |
|
+isc_result_t |
|
+isc_counter_increment(isc_counter_t *counter) { |
|
+ isc_result_t result = ISC_R_SUCCESS; |
|
+ |
|
+ LOCK(&counter->lock); |
|
+ counter->used++; |
|
+ if (counter->limit != 0 && counter->used >= counter->limit) |
|
+ result = ISC_R_QUOTA; |
|
+ UNLOCK(&counter->lock); |
|
+ |
|
+ return (result); |
|
+} |
|
+ |
|
+unsigned int |
|
+isc_counter_used(isc_counter_t *counter) { |
|
+ REQUIRE(VALID_COUNTER(counter)); |
|
+ |
|
+ return (counter->used); |
|
+} |
|
+ |
|
+void |
|
+isc_counter_setlimit(isc_counter_t *counter, int limit) { |
|
+ REQUIRE(VALID_COUNTER(counter)); |
|
+ |
|
+ LOCK(&counter->lock); |
|
+ counter->limit = limit; |
|
+ UNLOCK(&counter->lock); |
|
+} |
|
+ |
|
+void |
|
+isc_counter_attach(isc_counter_t *source, isc_counter_t **targetp) { |
|
+ REQUIRE(VALID_COUNTER(source)); |
|
+ REQUIRE(targetp != NULL && *targetp == NULL); |
|
+ |
|
+ LOCK(&source->lock); |
|
+ source->references++; |
|
+ INSIST(source->references > 0); |
|
+ UNLOCK(&source->lock); |
|
+ |
|
+ *targetp = source; |
|
+} |
|
+ |
|
+static void |
|
+destroy(isc_counter_t *counter) { |
|
+ counter->magic = 0; |
|
+ isc_mutex_destroy(&counter->lock); |
|
+ isc_mem_putanddetach(&counter->mctx, counter, sizeof(*counter)); |
|
+} |
|
+ |
|
+void |
|
+isc_counter_detach(isc_counter_t **counterp) { |
|
+ isc_counter_t *counter; |
|
+ isc_boolean_t want_destroy = ISC_FALSE; |
|
+ |
|
+ REQUIRE(counterp != NULL && *counterp != NULL); |
|
+ counter = *counterp; |
|
+ REQUIRE(VALID_COUNTER(counter)); |
|
+ |
|
+ *counterp = NULL; |
|
+ |
|
+ LOCK(&counter->lock); |
|
+ INSIST(counter->references > 0); |
|
+ counter->references--; |
|
+ if (counter->references == 0) |
|
+ want_destroy = ISC_TRUE; |
|
+ UNLOCK(&counter->lock); |
|
+ |
|
+ if (want_destroy) |
|
+ destroy(counter); |
|
+} |
|
diff -up bind-9.9.4/lib/isc/include/isc/counter.h.CVE-2014-8500 bind-9.9.4/lib/isc/include/isc/counter.h |
|
--- bind-9.9.4/lib/isc/include/isc/counter.h.CVE-2014-8500 2014-12-10 14:56:24.968552569 +0100 |
|
+++ bind-9.9.4/lib/isc/include/isc/counter.h 2014-12-10 14:56:24.968552569 +0100 |
|
@@ -0,0 +1,90 @@ |
|
+/* |
|
+ * Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC") |
|
+ * |
|
+ * Permission to use, copy, modify, and/or distribute this software for any |
|
+ * purpose with or without fee is hereby granted, provided that the above |
|
+ * copyright notice and this permission notice appear in all copies. |
|
+ * |
|
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH |
|
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY |
|
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, |
|
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM |
|
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE |
|
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR |
|
+ * PERFORMANCE OF THIS SOFTWARE. |
|
+ */ |
|
+ |
|
+#ifndef ISC_COUNTER_H |
|
+#define ISC_COUNTER_H 1 |
|
+ |
|
+/***** |
|
+ ***** Module Info |
|
+ *****/ |
|
+ |
|
+/*! \file isc/counter.h |
|
+ * |
|
+ * \brief The isc_counter_t object is a simplified version of the |
|
+ * isc_quota_t object; it tracks the consumption of limited |
|
+ * resources, returning an error condition when the quota is |
|
+ * exceeded. However, unlike isc_quota_t, attaching and detaching |
|
+ * from a counter object does not increment or decrement the counter. |
|
+ */ |
|
+ |
|
+/*** |
|
+ *** Imports. |
|
+ ***/ |
|
+ |
|
+#include <isc/lang.h> |
|
+#include <isc/mutex.h> |
|
+#include <isc/types.h> |
|
+ |
|
+/***** |
|
+ ***** Types. |
|
+ *****/ |
|
+ |
|
+ISC_LANG_BEGINDECLS |
|
+ |
|
+isc_result_t |
|
+isc_counter_create(isc_mem_t *mctx, int limit, isc_counter_t **counterp); |
|
+/*%< |
|
+ * Allocate and initialize a counter object. |
|
+ */ |
|
+ |
|
+isc_result_t |
|
+isc_counter_increment(isc_counter_t *counter); |
|
+/*%< |
|
+ * Increment the counter. |
|
+ * |
|
+ * If the counter limit is nonzero and has been reached, then |
|
+ * return ISC_R_QUOTA, otherwise ISC_R_SUCCESS. (The counter is |
|
+ * incremented regardless of return value.) |
|
+ */ |
|
+ |
|
+unsigned int |
|
+isc_counter_used(isc_counter_t *counter); |
|
+/*%< |
|
+ * Return the current counter value. |
|
+ */ |
|
+ |
|
+void |
|
+isc_counter_setlimit(isc_counter_t *counter, int limit); |
|
+/*%< |
|
+ * Set the counter limit. |
|
+ */ |
|
+ |
|
+void |
|
+isc_counter_attach(isc_counter_t *source, isc_counter_t **targetp); |
|
+/*%< |
|
+ * Attach to a counter object, increasing its reference counter. |
|
+ */ |
|
+ |
|
+void |
|
+isc_counter_detach(isc_counter_t **counterp); |
|
+/*%< |
|
+ * Detach (and destroy if reference counter has dropped to zero) |
|
+ * a counter object. |
|
+ */ |
|
+ |
|
+ISC_LANG_ENDDECLS |
|
+ |
|
+#endif /* ISC_COUNTER_H */ |
|
diff -up bind-9.9.4/lib/isc/include/isc/Makefile.in.CVE-2014-8500 bind-9.9.4/lib/isc/include/isc/Makefile.in |
|
--- bind-9.9.4/lib/isc/include/isc/Makefile.in.CVE-2014-8500 2014-12-10 15:02:34.811005903 +0100 |
|
+++ bind-9.9.4/lib/isc/include/isc/Makefile.in 2014-12-10 15:03:01.099030322 +0100 |
|
@@ -27,7 +27,7 @@ top_srcdir = @top_srcdir@ |
|
# install target below. |
|
# |
|
HEADERS = app.h assertions.h base64.h bind9.h bitstring.h boolean.h \ |
|
- buffer.h bufferlist.h commandline.h entropy.h error.h event.h \ |
|
+ buffer.h bufferlist.h commandline.h counter.h entropy.h error.h event.h \ |
|
eventclass.h file.h formatcheck.h fsaccess.h \ |
|
hash.h heap.h hex.h hmacmd5.h hmacsha.h \ |
|
httpd.h \ |
|
diff -up bind-9.9.4/lib/isc/include/isc/types.h.CVE-2014-8500 bind-9.9.4/lib/isc/include/isc/types.h |
|
--- bind-9.9.4/lib/isc/include/isc/types.h.CVE-2014-8500 2013-09-05 07:09:08.000000000 +0200 |
|
+++ bind-9.9.4/lib/isc/include/isc/types.h 2014-12-10 14:56:24.968552569 +0100 |
|
@@ -50,6 +50,7 @@ typedef struct isc_buffer isc_buffer_t; |
|
typedef ISC_LIST(isc_buffer_t) isc_bufferlist_t; /*%< Buffer List */ |
|
typedef struct isc_constregion isc_constregion_t; /*%< Const region */ |
|
typedef struct isc_consttextregion isc_consttextregion_t; /*%< Const Text Region */ |
|
+typedef struct isc_counter isc_counter_t; /*%< Counter */ |
|
typedef struct isc_entropy isc_entropy_t; /*%< Entropy */ |
|
typedef struct isc_entropysource isc_entropysource_t; /*%< Entropy Source */ |
|
typedef struct isc_event isc_event_t; /*%< Event */ |
|
diff -up bind-9.9.4/lib/isc/Makefile.in.CVE-2014-8500 bind-9.9.4/lib/isc/Makefile.in |
|
--- bind-9.9.4/lib/isc/Makefile.in.CVE-2014-8500 2014-12-10 14:56:24.860552447 +0100 |
|
+++ bind-9.9.4/lib/isc/Makefile.in 2014-12-10 14:56:24.968552569 +0100 |
|
@@ -53,7 +53,7 @@ WIN32OBJS = win32/condition.@O@ win32/d |
|
OBJS = @ISC_EXTRA_OBJS@ \ |
|
assertions.@O@ backtrace.@O@ base32.@O@ base64.@O@ \ |
|
bitstring.@O@ buffer.@O@ bufferlist.@O@ commandline.@O@ \ |
|
- error.@O@ event.@O@ \ |
|
+ counter.@O@ error.@O@ event.@O@ \ |
|
hash.@O@ heap.@O@ hex.@O@ hmacmd5.@O@ hmacsha.@O@ \ |
|
httpd.@O@ inet_aton.@O@ iterated_hash.@O@ \ |
|
lex.@O@ lfsr.@O@ lib.@O@ log.@O@ \ |
|
@@ -70,8 +70,8 @@ SYMTBLOBJS = backtrace-emptytbl.@O@ |
|
# Alphabetically |
|
SRCS = @ISC_EXTRA_SRCS@ \ |
|
assertions.c backtrace.c base32.c base64.c bitstring.c \ |
|
- buffer.c bufferlist.c commandline.c error.c event.c \ |
|
- heap.c hex.c hmacmd5.c hmacsha.c \ |
|
+ buffer.c bufferlist.c commandline.c counter.c \ |
|
+ error.c event.c heap.c hex.c hmacmd5.c hmacsha.c \ |
|
httpd.c inet_aton.c iterated_hash.c \ |
|
lex.c lfsr.c lib.c log.c \ |
|
md5.c mem.c mutexblock.c \
|
|
|