summaryrefslogtreecommitdiff
path: root/ares_query.c
diff options
context:
space:
mode:
authorDaniel Stenberg <daniel@haxx.se>2007-05-30 21:11:10 +0000
committerDaniel Stenberg <daniel@haxx.se>2007-05-30 21:11:10 +0000
commit7a77f24d26f755421b91a0ea3852b6348d637861 (patch)
tree9c844a8c94f38eadb15c554e570db4e0daebf638 /ares_query.c
parentf1440b240528afe3dfc03256d92b49acb4ef8537 (diff)
downloadc-ares-7a77f24d26f755421b91a0ea3852b6348d637861.tar.gz
c-ares-7a77f24d26f755421b91a0ea3852b6348d637861.tar.bz2
c-ares-7a77f24d26f755421b91a0ea3852b6348d637861.zip
Shmulik Regev brought cryptographically secure transaction IDs
Diffstat (limited to 'ares_query.c')
-rw-r--r--ares_query.c61
1 files changed, 60 insertions, 1 deletions
diff --git a/ares_query.c b/ares_query.c
index 742e873..4ca4cf9 100644
--- a/ares_query.c
+++ b/ares_query.c
@@ -39,6 +39,64 @@ struct qquery {
static void qcallback(void *arg, int status, unsigned char *abuf, int alen);
+void ares__rc4(rc4_key* key, unsigned char *buffer_ptr, int buffer_len)
+{
+ unsigned char x;
+ unsigned char y;
+ unsigned char* state;
+ unsigned char xorIndex;
+ short counter;
+
+ x = key->x;
+ y = key->y;
+
+ state = &key->state[0];
+ for(counter = 0; counter < buffer_len; counter ++)
+ {
+ x = (x + 1) % 256;
+ y = (state[x] + y) % 256;
+ ARES_SWAP_BYTE(&state[x], &state[y]);
+
+ xorIndex = (state[x] + state[y]) % 256;
+
+ buffer_ptr[counter] ^= state[xorIndex];
+ }
+ key->x = x;
+ key->y = y;
+}
+
+static struct query* find_query_by_id(ares_channel channel, int id)
+{
+ int qid;
+ struct query* q;
+ DNS_HEADER_SET_QID(((unsigned char*)&qid), id);
+
+ /* Find the query corresponding to this packet. */
+ for (q = channel->queries; q; q = q->next)
+ {
+ if (q->qid == qid)
+ return q;
+ }
+ return NULL;
+}
+
+
+/* a unique query id is generated using an rc4 key. Since the id may already
+ be used by a running query (as infrequent as it may be), a lookup is
+ performed per id generation. In practice this search should happen only
+ once per newly generated id
+*/
+static int generate_unique_id(ares_channel channel)
+{
+ int id;
+
+ do {
+ id = ares__generate_new_id(&channel->id_key);
+ } while (find_query_by_id(channel,id));
+
+ return id;
+}
+
void ares_query(ares_channel channel, const char *name, int dnsclass,
int type, ares_callback callback, void *arg)
{
@@ -50,7 +108,8 @@ void ares_query(ares_channel channel, const char *name, int dnsclass,
rd = !(channel->flags & ARES_FLAG_NORECURSE);
status = ares_mkquery(name, dnsclass, type, channel->next_id, rd, &qbuf,
&qlen);
- channel->next_id++;
+ channel->next_id = generate_unique_id(channel);
+
if (status != ARES_SUCCESS)
{
callback(arg, status, NULL, 0);