]>
git.proxmox.com Git - ceph.git/blob - ceph/src/c-ares/ares_query.c
2 /* Copyright 1998 by the Massachusetts Institute of Technology.
4 * Permission to use, copy, modify, and distribute this
5 * software and its documentation for any purpose and without
6 * fee is hereby granted, provided that the above copyright
7 * notice appear in all copies and that both that copyright
8 * notice and this permission notice appear in supporting
9 * documentation, and that the name of M.I.T. not be used in
10 * advertising or publicity pertaining to distribution of the
11 * software without specific, written prior permission.
12 * M.I.T. makes no representations about the suitability of
13 * this software for any purpose. It is provided "as is"
14 * without express or implied warranty.
17 #include "ares_setup.h"
19 #ifdef HAVE_NETINET_IN_H
20 # include <netinet/in.h>
22 #ifdef HAVE_ARPA_NAMESER_H
23 # include <arpa/nameser.h>
27 #ifdef HAVE_ARPA_NAMESER_COMPAT_H
28 # include <arpa/nameser_compat.h>
33 #include "ares_private.h"
36 ares_callback callback
;
40 static void qcallback(void *arg
, int status
, int timeouts
, unsigned char *abuf
, int alen
);
42 static void rc4(rc4_key
* key
, unsigned char *buffer_ptr
, int buffer_len
)
47 unsigned char xorIndex
;
53 state
= &key
->state
[0];
54 for(counter
= 0; counter
< buffer_len
; counter
++)
56 x
= (unsigned char)((x
+ 1) % 256);
57 y
= (unsigned char)((state
[x
] + y
) % 256);
58 ARES_SWAP_BYTE(&state
[x
], &state
[y
]);
60 xorIndex
= (unsigned char)((state
[x
] + state
[y
]) % 256);
62 buffer_ptr
[counter
] = (unsigned char)(buffer_ptr
[counter
]^state
[xorIndex
]);
68 static struct query
* find_query_by_id(ares_channel channel
, unsigned short id
)
71 struct list_node
* list_head
;
72 struct list_node
* list_node
;
73 DNS_HEADER_SET_QID(((unsigned char*)&qid
), id
);
75 /* Find the query corresponding to this packet. */
76 list_head
= &(channel
->queries_by_qid
[qid
% ARES_QID_TABLE_SIZE
]);
77 for (list_node
= list_head
->next
; list_node
!= list_head
;
78 list_node
= list_node
->next
)
80 struct query
*q
= list_node
->data
;
88 /* a unique query id is generated using an rc4 key. Since the id may already
89 be used by a running query (as infrequent as it may be), a lookup is
90 performed per id generation. In practice this search should happen only
91 once per newly generated id
93 static unsigned short generate_unique_id(ares_channel channel
)
98 id
= ares__generate_new_id(&channel
->id_key
);
99 } while (find_query_by_id(channel
, id
));
101 return (unsigned short)id
;
104 unsigned short ares__generate_new_id(rc4_key
* key
)
107 rc4(key
, (unsigned char *)&r
, sizeof(r
));
111 void ares_query(ares_channel channel
, const char *name
, int dnsclass
,
112 int type
, ares_callback callback
, void *arg
)
114 struct qquery
*qquery
;
116 int qlen
, rd
, status
;
118 /* Compose the query. */
119 rd
= !(channel
->flags
& ARES_FLAG_NORECURSE
);
120 status
= ares_create_query(name
, dnsclass
, type
, channel
->next_id
, rd
, &qbuf
,
121 &qlen
, (channel
->flags
& ARES_FLAG_EDNS
) ? channel
->ednspsz
: 0);
122 if (status
!= ARES_SUCCESS
)
124 if (qbuf
!= NULL
) ares_free(qbuf
);
125 callback(arg
, status
, 0, NULL
, 0);
129 channel
->next_id
= generate_unique_id(channel
);
131 /* Allocate and fill in the query structure. */
132 qquery
= ares_malloc(sizeof(struct qquery
));
135 ares_free_string(qbuf
);
136 callback(arg
, ARES_ENOMEM
, 0, NULL
, 0);
139 qquery
->callback
= callback
;
142 /* Send it off. qcallback will be called when we get an answer. */
143 ares_send(channel
, qbuf
, qlen
, qcallback
, qquery
);
144 ares_free_string(qbuf
);
147 static void qcallback(void *arg
, int status
, int timeouts
, unsigned char *abuf
, int alen
)
149 struct qquery
*qquery
= (struct qquery
*) arg
;
150 unsigned int ancount
;
153 if (status
!= ARES_SUCCESS
)
154 qquery
->callback(qquery
->arg
, status
, timeouts
, abuf
, alen
);
157 /* Pull the response code and answer count from the packet. */
158 rcode
= DNS_HEADER_RCODE(abuf
);
159 ancount
= DNS_HEADER_ANCOUNT(abuf
);
161 /* Convert errors. */
165 status
= (ancount
> 0) ? ARES_SUCCESS
: ARES_ENODATA
;
168 status
= ARES_EFORMERR
;
171 status
= ARES_ESERVFAIL
;
174 status
= ARES_ENOTFOUND
;
177 status
= ARES_ENOTIMP
;
180 status
= ARES_EREFUSED
;
183 qquery
->callback(qquery
->arg
, status
, timeouts
, abuf
, alen
);