main.cc 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. // Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC")
  2. //
  3. // Permission to use, copy, modify, and/or distribute this software for any
  4. // purpose with or without fee is hereby granted, provided that the above
  5. // copyright notice and this permission notice appear in all copies.
  6. //
  7. // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
  8. // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  9. // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
  10. // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  11. // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  12. // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  13. // PERFORMANCE OF THIS SOFTWARE.
  14. // $Id$
  15. #include <sys/types.h>
  16. #include <sys/socket.h>
  17. #include <netdb.h>
  18. #include <stdlib.h>
  19. #include <set>
  20. #include <iostream>
  21. #include <dns/buffer.h>
  22. #include <dns/name.h>
  23. #include <dns/rrset.h>
  24. #include <dns/message.h>
  25. #include "common.h"
  26. #include "zoneset.h"
  27. using namespace std;
  28. using namespace isc::dns;
  29. using namespace isc::dns::Rdata::IN;
  30. using namespace isc::dns::Rdata::Generic;
  31. const string PROGRAM = "parkinglot";
  32. const int DNSPORT = 53;
  33. class ParkingLot {
  34. public:
  35. explicit ParkingLot(int port);
  36. virtual ~ParkingLot() {};
  37. int getSocket() { return(sock); }
  38. void processMessage();
  39. private:
  40. Rdata::RdataPtr ns1, ns2, ns3, a, aaaa, soa;
  41. ZoneSet zones;
  42. int sock;
  43. };
  44. static void init_zones(ZoneSet& zones) {
  45. zones.serve("jinmei.org");
  46. zones.serve("nuthaven.org");
  47. zones.serve("isc.org");
  48. zones.serve("sisotowbell.org");
  49. zones.serve("flame.org");
  50. }
  51. ParkingLot::ParkingLot(int port) {
  52. init_zones(zones);
  53. ns1 = Rdata::RdataPtr(new NS("ns1.parking.com"));
  54. ns2 = Rdata::RdataPtr(new NS("ns2.parking.com"));
  55. ns3 = Rdata::RdataPtr(new NS("ns3.parking.com"));
  56. a = Rdata::RdataPtr(new A("127.0.0.1"));
  57. aaaa = Rdata::RdataPtr(new AAAA("::1"));
  58. soa = Rdata::RdataPtr(new SOA("parking.com", "noc.parking.com",
  59. 1, 1800, 900, 604800, TTL(86400)));
  60. int s = socket(AF_INET, SOCK_DGRAM, 0);
  61. if (s < 0)
  62. throw FatalError("failed to open socket");
  63. struct sockaddr_in sin;
  64. sin.sin_family = AF_INET;
  65. sin.sin_addr.s_addr = INADDR_ANY;
  66. sin.sin_port = htons(port);
  67. socklen_t sa_len = sizeof(sin);
  68. #ifdef HAVE_SIN_LEN
  69. sin.sin_len = sa_len;
  70. #endif
  71. if (bind(s, (struct sockaddr *)&sin, sa_len) < 0)
  72. throw FatalError("could not bind socket");
  73. sock = s;
  74. }
  75. void
  76. ParkingLot::processMessage() {
  77. Message msg;
  78. struct sockaddr_storage ss;
  79. socklen_t sa_len = sizeof(ss);
  80. struct sockaddr* sa = static_cast<struct sockaddr*>((void*)&ss);
  81. int s = sock;
  82. Name authors_name("authors.bind");
  83. if (msg.getBuffer().recvFrom(s, sa, &sa_len) > 0) {
  84. try {
  85. msg.fromWire();
  86. } catch (...) {
  87. cerr << "parse failed" << endl;
  88. return;
  89. }
  90. cout << "received a message:\n" << msg.toText() << endl;
  91. if (msg.getSection(SECTION_QUESTION).size() != 1)
  92. return;
  93. msg.makeResponse();
  94. msg.setAA(true);
  95. RRsetPtr query = msg.getSection(SECTION_QUESTION)[0];
  96. string name = query->getName().toText(true);
  97. if (query->getName() == authors_name &&
  98. query->getClass() == RRClass::CH,
  99. query->getType() == RRType::TXT) {
  100. msg.setRcode(Message::RCODE_NOERROR);
  101. msg.addRR(SECTION_ANSWER, RR(authors_name, RRClass::CH,
  102. RRType::TXT, TTL(0),
  103. TXT("JINMEI Tatuya")));
  104. msg.addRR(SECTION_ANSWER, RR(authors_name, RRClass::CH,
  105. RRType::TXT, TTL(0),
  106. TXT("Evan Hunt")));
  107. msg.addRR(SECTION_ANSWER, RR(authors_name, RRClass::CH,
  108. RRType::TXT, TTL(0),
  109. TXT("Jeremy C. Reed")));
  110. // add others name here!!
  111. msg.addRR(SECTION_AUTHORITY, RR(authors_name, RRClass::CH,
  112. RRType::NS, TTL(0),
  113. NS("authors.bind")));
  114. } else if (zones.contains(name)) {
  115. msg.setRcode(Message::RCODE_NOERROR);
  116. RRset* nsset = new RRset(query->getName(), RRClass::IN,
  117. RRType::NS, TTL(3600));
  118. nsset->addRdata(ns1);
  119. nsset->addRdata(ns2);
  120. nsset->addRdata(ns3);
  121. if (query->getType() == RRType::NS)
  122. msg.addRRset(SECTION_ANSWER, RRsetPtr(nsset));
  123. else if (query->getType() == RRType::A) {
  124. msg.addRRset(SECTION_AUTHORITY, RRsetPtr(nsset));
  125. RR arr(query->getName(), RRClass::IN, RRType::A, TTL(3600), a);
  126. msg.addRR(SECTION_ANSWER, arr);
  127. } else if (query->getType() == RRType::AAAA) {
  128. msg.addRRset(SECTION_AUTHORITY, RRsetPtr(nsset));
  129. RR aaaarr(query->getName(), RRClass::IN, RRType::AAAA,
  130. TTL(3600), aaaa);
  131. msg.addRR(SECTION_ANSWER, aaaarr);
  132. } else {
  133. RR soarr(query->getName(), RRClass::IN, RRType::SOA,
  134. TTL(3600), soa);
  135. msg.addRR(SECTION_AUTHORITY, soarr);
  136. }
  137. } else {
  138. msg.setRcode(Message::RCODE_NXDOMAIN);
  139. }
  140. msg.toWire();
  141. cout << "sending a response (" <<
  142. boost::lexical_cast<string>(msg.getBuffer().getSize())
  143. << " bytes):\n" << msg.toText() << endl;
  144. msg.getBuffer().sendTo(s, *sa, sa_len);
  145. }
  146. }
  147. static void
  148. usage() {
  149. cerr << "Usage: parkinglot [-p port]" << endl;
  150. exit(1);
  151. }
  152. int
  153. main(int argc, char* argv[]) {
  154. Message msg;
  155. int ch;
  156. int port = DNSPORT;
  157. while ((ch = getopt(argc, argv, "p:")) != -1) {
  158. switch (ch) {
  159. case 'p':
  160. port = atoi(optarg);
  161. break;
  162. case '?':
  163. default:
  164. usage();
  165. }
  166. }
  167. if (argc - optind > 0)
  168. usage();
  169. // initialize parking lot
  170. ParkingLot plot(port);
  171. // initialize command channel
  172. // ISC::CC::Session session;
  173. // session.establish();
  174. // session.subscribe("parkinglot");
  175. // main server loop
  176. cout << "server running" << endl;
  177. while (true)
  178. plot.processMessage();
  179. return (0);
  180. }