PageRenderTime 51ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/tags/start/dnrd/src/query.c

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