PageRenderTime 46ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/tags/release_2_14/dnrd/src/query.c

#
C | 192 lines | 94 code | 17 blank | 81 comment | 18 complexity | f88e8ce748642aabb39d88d43102f7f9 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 "query.h"
  34. #include "common.h"
  35. #include "lib.h"
  36. /*
  37. * This is the data structure used to store DNS queries that haven't been
  38. * answered yet.
  39. */
  40. struct dnsq_t {
  41. unsigned short local_qid; /* network byte-ordered */
  42. unsigned short client_qid; /* network byte-ordered */
  43. struct dnsq_t * next;
  44. struct sockaddr_in client;
  45. time_t recvtime;
  46. };
  47. typedef struct dnsq_t dnsquery;
  48. /*
  49. * Static variables.
  50. */
  51. static dnsquery * head = 0;
  52. static dnsquery * tail = 0;
  53. static unsigned short qidcount = 0;
  54. /*
  55. * dnsquery_add() - add a DNS query to our list.
  56. *
  57. * In: client - the host that sent us the query.
  58. * len - the length of the DNS query
  59. * In/Out: msg - the DNS query
  60. *
  61. * Returns: 1 on success, 0 on failure.
  62. *
  63. * Abstract: This function takes the query msg and adds it to the end
  64. * of our list. In addition, it generates a new query id
  65. * and updates msg accordingly. If the query msg is already
  66. * in our list (a retransmission), then we'll act as if we're
  67. * adding it, but we won't actually add it again.
  68. */
  69. int dnsquery_add(const struct sockaddr_in* client, char* msg, unsigned len)
  70. {
  71. unsigned short client_qid;
  72. dnsquery *ptr;
  73. dnsquery *query;
  74. memcpy(&client_qid, msg, 2);
  75. /* If entry already exists, then don't actually add it again */
  76. for (ptr = head; ptr != 0; ptr = ptr->next) {
  77. if (ptr->client_qid == client_qid) {
  78. memcpy(msg, &(ptr->local_qid), 2);
  79. return 1;
  80. }
  81. }
  82. /* Create the new dnsquery entry */
  83. query = (dnsquery*)allocate(sizeof(dnsquery));
  84. query->local_qid = htons(qidcount++);
  85. query->client_qid = client_qid;
  86. query->next = 0;
  87. memcpy(&(query->client), client, sizeof(struct sockaddr_in));
  88. query->recvtime = time(0);
  89. /* Update the query number in msg */
  90. memcpy(msg, &(query->local_qid), 2);
  91. /* Update our dnsquery list */
  92. tail ? (tail->next = query) : (head = query);
  93. tail = query;
  94. return 1;
  95. }
  96. /*
  97. * dnsquery_find() - find the client to whom this reply should be sent.
  98. *
  99. * In/Out: reply - the DNS reply
  100. * Out: client - a buffer where the client to whom this reply
  101. * should be sent will be copied.
  102. *
  103. * Returns: 1 on success, 0 on failure.
  104. *
  105. * Abstract: This function finds the client to whom this reply should be
  106. * sent. In addition, it finds the client's original query id
  107. * and updates reply accordingly. Once found, the dnsquery is
  108. * removed from our list.
  109. *
  110. * Assumptions: reply is at least 2 bytes long.
  111. */
  112. int dnsquery_find(char* reply, struct sockaddr_in* client)
  113. {
  114. unsigned short qid;
  115. dnsquery * ptr;
  116. dnsquery * last = 0;
  117. memcpy(&qid, reply, 2);
  118. for (ptr = head; ptr != 0; ptr = ptr->next) {
  119. if (qid == ptr->local_qid) {
  120. memcpy(client, &(ptr->client), sizeof(struct sockaddr_in));
  121. memcpy(reply, &(ptr->client_qid), 2);
  122. last ? (last->next = ptr->next) : (head = ptr->next);
  123. if (tail == ptr) tail = last;
  124. free(ptr);
  125. return 1;
  126. }
  127. last = ptr;
  128. }
  129. return 0;
  130. }
  131. /*
  132. * dnsquery_timeout() - Remove queries that are too old.
  133. *
  134. * In: age - remove all entries older than this many seconds.
  135. *
  136. * Returns: The number of entries that were removed.
  137. *
  138. * Abstract: This function is used to remove queries that have timed out.
  139. * This should prevent our query list from having memory leaks.
  140. */
  141. int dnsquery_timeout(time_t age)
  142. {
  143. int count = 0;
  144. dnsquery * ptr;
  145. time_t tval;
  146. tval = time(0) - age;
  147. for (ptr = head; (ptr != 0) && (ptr->recvtime < tval); ptr = head) {
  148. head = ptr->next;
  149. if (tail == ptr) tail = 0;
  150. free(ptr);
  151. count++;
  152. }
  153. if (count) log_debug("dnsquery_timeout: removed %d entries", count);
  154. return count;
  155. }
  156. #ifdef DEBUG
  157. /*
  158. * dnsquery_dump() - Display the current state of the query queue.
  159. *
  160. * Abstract: This function is used for debugging purposes only.
  161. */
  162. void dnsquery_dump()
  163. {
  164. dnsquery * ptr;
  165. printf("Current queue:\n");
  166. printf(" head = %p, tail = %p\n", head, tail);
  167. printf(" my_qid h_qid from_addr\n");
  168. printf(" ------ ------ ---------------\n");
  169. for (ptr = head; ptr != 0; ptr = ptr->next) {
  170. printf(" %-6d %-6d %s\n", ntohs(ptr->local_qid), ptr->client_qid,
  171. inet_ntoa(ptr->client.sin_addr));
  172. }
  173. printf("\n");
  174. }
  175. #endif /* DEBUG */