PageRenderTime 59ms CodeModel.GetById 29ms RepoModel.GetById 0ms app.codeStats 0ms

/tags/release_2_16_2/dnrd/src/query.c

#
C | 226 lines | 115 code | 21 blank | 90 comment | 21 complexity | 456485582a5dfc13d1a25aaa16e2b37c MD5 | raw file
Possible License(s): GPL-2.0
  1. /*
  2. * query.c
  3. *
  4. * This file contains the data definitions, function definitions, and
  5. * variables used to implement our DNS query list.
  6. *
  7. * Assumptions: No multithreading.
  8. *
  9. * Copyright (C) 1998 Brad M. Garcia <garsh@home.com>
  10. *
  11. * This program is free software; you can redistribute it and/or modify
  12. * it under the terms of the GNU General Public License as published by
  13. * the Free Software Foundation; either version 2 of the License, or
  14. * (at your option) any later version.
  15. *
  16. * This program is distributed in the hope that it will be useful,
  17. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  19. * GNU General Public License for more details.
  20. *
  21. * You should have received a copy of the GNU General Public License
  22. * along with this program; if not, write to the Free Software
  23. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  24. */
  25. #include <stdlib.h>
  26. #include <string.h>
  27. #ifdef DEBUG
  28. #include <stdio.h>
  29. #include <sys/socket.h>
  30. #include <netinet/in.h>
  31. #include <arpa/inet.h>
  32. #endif /* DEBUG */
  33. #include "domnode.h"
  34. #include "query.h"
  35. #include "common.h"
  36. #include "lib.h"
  37. #include "qid.h"
  38. /*
  39. * This is the data structure used to store DNS queries that haven't been
  40. * answered yet.
  41. */
  42. struct dnsq_t {
  43. unsigned short local_qid; /* network byte-ordered */
  44. unsigned short client_qid; /* network byte-ordered */
  45. struct dnsq_t * next;
  46. struct sockaddr_in client;
  47. time_t recvtime;
  48. unsigned short retries; /* number of tries */
  49. };
  50. typedef struct dnsq_t dnsquery;
  51. /*
  52. * Static variables.
  53. */
  54. static dnsquery * head = 0;
  55. static dnsquery * tail = 0;
  56. static unsigned short qidcount = 0;
  57. /*
  58. * dnsquery_add() - add a DNS query to our list.
  59. *
  60. * In: client - the host that sent us the query.
  61. * len - the length of the DNS query
  62. * In/Out: msg - the DNS query
  63. *
  64. * Returns: 1 on success, 0 on failure.
  65. *
  66. * Abstract: This function takes the query msg and adds it to the end
  67. * of our list. In addition, it generates a new query id
  68. * and updates msg accordingly. If the query msg is already
  69. * in our list (a retransmission), then we'll act as if we're
  70. * adding it, but we won't actually add it again.
  71. */
  72. int dnsquery_add(const struct sockaddr_in* client, char* msg, unsigned len)
  73. {
  74. unsigned short client_qid;
  75. dnsquery *ptr;
  76. dnsquery *query;
  77. memcpy(&client_qid, msg, sizeof(client_qid));
  78. /* If entry already exists, then don't actually add it again */
  79. for (ptr = head; ptr != 0; ptr = ptr->next) {
  80. if (ptr->client_qid == client_qid) {
  81. memcpy(msg, &(ptr->local_qid), 2);
  82. ptr->retries++;
  83. log_debug("query %i from client already in list", client_qid);
  84. return 1;
  85. }
  86. }
  87. /* Create the new dnsquery entry */
  88. query = (dnsquery*)allocate(sizeof(dnsquery));
  89. query->local_qid = htons(qid_get());
  90. query->client_qid = client_qid;
  91. query->next = 0;
  92. memcpy(&(query->client), client, sizeof(struct sockaddr_in));
  93. query->recvtime = time(0);
  94. query->retries = 0;
  95. /* Update the query number in msg */
  96. memcpy(msg, &(query->local_qid), 2);
  97. /* Update our dnsquery list */
  98. tail ? (tail->next = query) : (head = query);
  99. tail = query;
  100. log_debug("Query local=%i, client=%i added",
  101. query->local_qid,
  102. query->client_qid);
  103. return 1;
  104. }
  105. /*
  106. * dnsquery_find() - find the client to whom this reply should be sent.
  107. *
  108. * In/Out: reply - the DNS reply
  109. * Out: client - a buffer where the client to whom this reply
  110. * should be sent will be copied.
  111. *
  112. * Returns: 1 on success, 0 on failure.
  113. *
  114. * Abstract: This function finds the client to whom this reply should be
  115. * sent. In addition, it finds the client's original query id
  116. * and updates reply accordingly. Once found, the dnsquery is
  117. * removed from our list.
  118. *
  119. * Assumptions: reply is at least 2 bytes long.
  120. */
  121. int dnsquery_find(char* reply, struct sockaddr_in* client)
  122. {
  123. unsigned short qid;
  124. dnsquery * ptr;
  125. dnsquery * last = 0;
  126. memcpy(&qid, reply, 2);
  127. for (ptr = head; ptr != 0; ptr = ptr->next) {
  128. if (qid == ptr->local_qid) {
  129. memcpy(client, &(ptr->client), sizeof(struct sockaddr_in));
  130. memcpy(reply, &(ptr->client_qid), 2);
  131. /* return the qid number to the qid pool */
  132. qid_return(ntohs(ptr->local_qid));
  133. last ? (last->next = ptr->next) : (head = ptr->next);
  134. if (tail == ptr) tail = last;
  135. free(ptr);
  136. return 1;
  137. }
  138. last = ptr;
  139. }
  140. return 0;
  141. }
  142. /*
  143. * dnsquery_timeout() - Remove queries that are too old.
  144. *
  145. * In: age - remove all entries older than this many seconds.
  146. *
  147. * Returns: The number of entries that were removed.
  148. *
  149. * Abstract: This function is used to remove queries that have timed out.
  150. * This should prevent our query list from having memory leaks.
  151. */
  152. int dnsquery_timeout(time_t age)
  153. {
  154. int count = 0;
  155. dnsquery * ptr;
  156. time_t tval;
  157. tval = time(0) - age;
  158. for (ptr = head; (ptr != 0) && (ptr->recvtime < tval); ptr = head) {
  159. /* return the qid number to the qid pool */
  160. qid_return(ntohs(ptr->local_qid));
  161. head = ptr->next;
  162. if (tail == ptr) tail = 0;
  163. free(ptr);
  164. count++;
  165. }
  166. if (count) log_debug("dnsquery_timeout: removed %d entries", count);
  167. return count;
  168. }
  169. /* dnsquery_retry */
  170. int dnsquery_retry(time_t age)
  171. {
  172. time_t tval;
  173. time_t now = time(0);
  174. dnsquery *p;
  175. tval = now - age;
  176. p = head;
  177. while ((p != NULL) && (p->recvtime < tval)) {
  178. /*
  179. send2current(p->dom, p->msg, p->len);
  180. p->sendtime = now;
  181. p=p->next;
  182. */
  183. }
  184. }
  185. #ifdef DEBUG
  186. /*
  187. * dnsquery_dump() - Display the current state of the query queue.
  188. *
  189. * Abstract: This function is used for debugging purposes only.
  190. */
  191. void dnsquery_dump()
  192. {
  193. dnsquery * ptr;
  194. printf("Current queue:\n");
  195. printf(" head = %p, tail = %p\n", head, tail);
  196. printf(" my_qid h_qid retr from_addr\n");
  197. printf(" ------ ------ ----- ---------------\n");
  198. for (ptr = head; ptr != 0; ptr = ptr->next) {
  199. printf(" %-6d %-6d %-6d %s\n", ntohs(ptr->local_qid), ptr->client_qid,
  200. inet_ntoa(ptr->client.sin_addr));
  201. }
  202. printf("\n");
  203. }
  204. #endif /* DEBUG */