summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSøren Sandmann <sandmann@redhat.com>2008-05-26 18:21:35 -0400
committerSøren Sandmann <sandmann@redhat.com>2008-05-26 18:21:35 -0400
commitb36819e254f4a712e1d8f5f0023f5974456d9431 (patch)
tree1b4b418f737b1e5a2457b53b056e573c8d4a0c89
parentb3c1cfea79de92bc5b37b9978ec4858074ee88fe (diff)
Work around router bug
-rw-r--r--src/lacdns-nameserver.c94
-rw-r--r--src/lachttp.c2
2 files changed, 94 insertions, 2 deletions
diff --git a/src/lacdns-nameserver.c b/src/lacdns-nameserver.c
index 2725a8f..ba2473b 100644
--- a/src/lacdns-nameserver.c
+++ b/src/lacdns-nameserver.c
@@ -236,6 +236,57 @@ run_callbacks (GQueue *callbacks)
}
}
+static DomainName *
+extract_domain_name (Message *message)
+{
+ if (g_queue_get_length (message->question_entries) == 1)
+ {
+ QuestionEntry *entry = message->question_entries->head->data;
+
+ if (entry->domain_name)
+ return domain_name_copy (entry->domain_name);
+ }
+ return NULL;
+}
+
+typedef struct
+{
+ DomainName *reply_name;
+ Query *query;
+} ForeachData;
+
+static void
+find_match (gpointer key, gpointer value, gpointer data)
+{
+ ForeachData *foreach = data;
+ Query *query = value;
+ Message *question;
+ guchar *in;
+ gssize len;
+
+ if (foreach->query)
+ return;
+
+ in = query->msg;
+ len = query->msg_len;
+ question = message_new_parsed (&in, &len, query->msg);
+
+ if (question)
+ {
+ DomainName *query_name = extract_domain_name (question);
+
+ if (query_name)
+ {
+ if (domain_name_equal (query_name, foreach->reply_name))
+ foreach->query = query;
+
+ domain_name_free (query_name);
+ }
+
+ message_free (question);
+ }
+}
+
static void
handle_reply (GHashTable *queries, const guchar *input, gsize len, GQueue *callbacks)
{
@@ -256,6 +307,41 @@ handle_reply (GHashTable *queries, const guchar *input, gsize len, GQueue *callb
{
query = g_hash_table_lookup (queries, &(reply->id));
+ if (!query)
+ {
+ /* A Linksys router (WGR54G2) is producing replies with
+ * id 0 regardless of the question id whenever there is
+ * a name error. It does however repeat the question, so
+ * we have a way of finding it in the table of outstanding
+ * queries.
+ *
+ * Workaround:
+ *
+ * - We never send a question with id 0
+ *
+ * - If a reply comes back with id 0, and
+ * matches an outstanding query, use that.
+ */
+
+ if (reply->id == 0)
+ {
+ ForeachData data;
+
+ data.query = NULL;
+ data.reply_name = extract_domain_name (reply);
+
+ if (data.reply_name)
+ {
+ g_hash_table_foreach (queries, find_match, &data);
+
+ if (data.query)
+ query = data.query;
+
+ domain_name_free (data.reply_name);
+ }
+ }
+ }
+
if (query)
{
g_queue_push_tail (callbacks, query->callback);
@@ -265,9 +351,15 @@ handle_reply (GHashTable *queries, const guchar *input, gsize len, GQueue *callb
g_hash_table_remove (queries, &(query->id));
}
- else
+ else
{
+ /* Silently ignore spurious responses */
+#if 0
+ g_print ("dumping message\n");
+ g_print (message_dump (reply));
+
spurious_response (reply->id);
+#endif
}
}
else
diff --git a/src/lachttp.c b/src/lachttp.c
index c054d15..b936270 100644
--- a/src/lachttp.c
+++ b/src/lachttp.c
@@ -2326,7 +2326,7 @@ http_transport_handle_read (HttpTransport *transport,
if (!transport->pipelining)
{
- /* FIXME return outstanding */
+ http_transport_return_outstanding_requests (transport);
http_host_transport_will_close_notify (
transport->host, transport);
lac_connection_close (transport->connection);