main.cc 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776
  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 "config.h"
  16. #include <sys/types.h>
  17. #include <sys/socket.h>
  18. #include <sys/select.h>
  19. #include <netdb.h>
  20. #include <netinet/in.h>
  21. #include <stdlib.h>
  22. #include <errno.h>
  23. #include <cassert>
  24. #include <iostream>
  25. #include <boost/foreach.hpp>
  26. #ifdef HAVE_BOOST_SYSTEM
  27. #include <boost/bind.hpp>
  28. #include <boost/asio.hpp>
  29. #endif // HAVE_BOOST_SYSTEM
  30. #include <exceptions/exceptions.h>
  31. #include <dns/buffer.h>
  32. #include <dns/message.h>
  33. #include <dns/messagerenderer.h>
  34. #include <cc/session.h>
  35. #include <cc/data.h>
  36. #include <config/ccsession.h>
  37. #if defined(HAVE_BOOST_SYSTEM) && defined(HAVE_BOOST_PYTHON)
  38. #define USE_XFROUT
  39. #include <xfr/xfrout_client.h>
  40. #endif
  41. #include "spec_config.h"
  42. #include "common.h"
  43. #include "auth_srv.h"
  44. using namespace std;
  45. #ifdef USE_XFROUT
  46. using namespace isc::xfr;
  47. #endif
  48. #ifdef HAVE_BOOST_SYSTEM
  49. using namespace boost::asio;
  50. using ip::udp;
  51. using ip::tcp;
  52. #endif // HAVE_BOOST_SYSTEM
  53. using namespace isc::data;
  54. using namespace isc::cc;
  55. using namespace isc::config;
  56. using namespace isc::dns;
  57. namespace {
  58. bool verbose_mode = false;
  59. const string PROGRAM = "Auth";
  60. const char* DNSPORT = "5300";
  61. /* need global var for config/command handlers.
  62. * todo: turn this around, and put handlers in the authserver
  63. * class itself? */
  64. AuthSrv *auth_server;
  65. #ifdef HAVE_BOOST_SYSTEM
  66. // TODO: this should be a property of AuthSrv, and AuthSrv needs
  67. // a stop() method (so the shutdown command can be handled)
  68. boost::asio::io_service io_service_;
  69. #else
  70. bool running;
  71. #endif // HAVE_BOOST_SYSTEM
  72. ElementPtr
  73. my_config_handler(ElementPtr new_config) {
  74. return auth_server->updateConfig(new_config);
  75. }
  76. ElementPtr
  77. my_command_handler(const string& command, const ElementPtr args) {
  78. ElementPtr answer = createAnswer();
  79. if (command == "print_message") {
  80. cout << args << endl;
  81. /* let's add that message to our answer as well */
  82. answer->get("result")->add(args);
  83. } else if (command == "shutdown") {
  84. #ifdef HAVE_BOOST_SYSTEM
  85. io_service_.stop();
  86. #else
  87. running = false;
  88. #endif // HAVE_BOOST_SYSTEM
  89. }
  90. return answer;
  91. }
  92. #ifdef USE_XFROUT
  93. //TODO. The sample way for checking axfr query, the code should be merged to auth server class
  94. static bool
  95. check_axfr_query(char *msg_data, uint16_t msg_len)
  96. {
  97. if (msg_len < 15)
  98. return false;
  99. uint16_t query_type = *(uint16_t *)(msg_data + (msg_len - 4));
  100. if ( query_type == 0xFC00)
  101. return true;
  102. return false;
  103. }
  104. //TODO. Send the xfr query to xfrout module, the code should be merged to auth server class
  105. static void
  106. dispatch_axfr_query(int tcp_sock, char axfr_query[], uint16_t query_len)
  107. {
  108. std::string path = string(UNIX_SOCKET_FILE);
  109. XfroutClient xfr_client(path);
  110. try {
  111. xfr_client.connect();
  112. xfr_client.sendXfroutRequestInfo(tcp_sock, (uint8_t *)axfr_query, query_len);
  113. xfr_client.disconnect();
  114. }
  115. catch (const std::exception & err) {
  116. //if (verbose_mode)
  117. cerr << "error handle xfr query:" << err.what() << endl;
  118. }
  119. }
  120. #endif
  121. #ifdef HAVE_BOOST_SYSTEM
  122. //
  123. // Helper classes for asynchronous I/O using boost::asio
  124. //
  125. class TCPClient {
  126. public:
  127. TCPClient(io_service& io_service) :
  128. socket_(io_service),
  129. response_buffer_(0),
  130. responselen_buffer_(TCP_MESSAGE_LENGTHSIZE),
  131. response_renderer_(response_buffer_),
  132. dns_message_(Message::PARSE)
  133. {}
  134. void start() {
  135. async_read(socket_, boost::asio::buffer(data_, TCP_MESSAGE_LENGTHSIZE),
  136. boost::bind(&TCPClient::headerRead, this,
  137. placeholders::error,
  138. placeholders::bytes_transferred));
  139. }
  140. tcp::socket& getSocket() { return (socket_); }
  141. void headerRead(const boost::system::error_code& error,
  142. size_t bytes_transferred)
  143. {
  144. if (!error) {
  145. InputBuffer dnsbuffer(data_, bytes_transferred);
  146. uint16_t msglen = dnsbuffer.readUint16();
  147. async_read(socket_, boost::asio::buffer(data_, msglen),
  148. boost::bind(&TCPClient::requestRead, this,
  149. placeholders::error,
  150. placeholders::bytes_transferred));
  151. } else {
  152. delete this;
  153. }
  154. }
  155. void requestRead(const boost::system::error_code& error,
  156. size_t bytes_transferred)
  157. {
  158. if (!error) {
  159. InputBuffer dnsbuffer(data_, bytes_transferred);
  160. #ifdef USE_XFROUT
  161. if (check_axfr_query(data_, bytes_transferred)) {
  162. dispatch_axfr_query(socket_.native(), data_, bytes_transferred);
  163. // start to get new query ?
  164. start();
  165. } else {
  166. #endif
  167. if (auth_server->processMessage(dnsbuffer, dns_message_,
  168. response_renderer_, false)) {
  169. responselen_buffer_.writeUint16(response_buffer_.getLength());
  170. async_write(socket_,
  171. boost::asio::buffer(
  172. responselen_buffer_.getData(),
  173. responselen_buffer_.getLength()),
  174. boost::bind(&TCPClient::responseWrite, this,
  175. placeholders::error));
  176. } else {
  177. delete this;
  178. }
  179. #ifdef USE_XFROUT
  180. }
  181. #endif
  182. } else {
  183. delete this;
  184. }
  185. }
  186. void responseWrite(const boost::system::error_code& error) {
  187. if (!error) {
  188. async_write(socket_,
  189. boost::asio::buffer(response_buffer_.getData(),
  190. response_buffer_.getLength()),
  191. boost::bind(&TCPClient::handleWrite, this,
  192. placeholders::error));
  193. } else {
  194. delete this;
  195. }
  196. }
  197. void handleWrite(const boost::system::error_code& error) {
  198. if (!error) {
  199. start(); // handle next request, if any.
  200. } else {
  201. delete this;
  202. }
  203. }
  204. private:
  205. tcp::socket socket_;
  206. OutputBuffer response_buffer_;
  207. OutputBuffer responselen_buffer_;
  208. MessageRenderer response_renderer_;
  209. Message dns_message_;
  210. enum { MAX_LENGTH = 65535 };
  211. static const size_t TCP_MESSAGE_LENGTHSIZE = 2;
  212. char data_[MAX_LENGTH];
  213. };
  214. class TCPServer {
  215. public:
  216. TCPServer(io_service& io_service, int af, short port) :
  217. io_service_(io_service), acceptor_(io_service_),
  218. listening_(new TCPClient(io_service_))
  219. {
  220. tcp::endpoint endpoint(af == AF_INET6 ? tcp::v6() : tcp::v4(), port);
  221. acceptor_.open(endpoint.protocol());
  222. // Set v6-only (we use a different instantiation for v4,
  223. // otherwise asio will bind to both v4 and v6
  224. if (af == AF_INET6) {
  225. acceptor_.set_option(ip::v6_only(true));
  226. }
  227. acceptor_.set_option(tcp::acceptor::reuse_address(true));
  228. acceptor_.bind(endpoint);
  229. acceptor_.listen();
  230. acceptor_.async_accept(listening_->getSocket(),
  231. boost::bind(&TCPServer::handleAccept, this,
  232. listening_, placeholders::error));
  233. }
  234. ~TCPServer() { delete listening_; }
  235. void handleAccept(TCPClient* new_client,
  236. const boost::system::error_code& error)
  237. {
  238. if (!error) {
  239. assert(new_client == listening_);
  240. new_client->start();
  241. listening_ = new TCPClient(io_service_);
  242. acceptor_.async_accept(listening_->getSocket(),
  243. boost::bind(&TCPServer::handleAccept,
  244. this, listening_,
  245. placeholders::error));
  246. } else {
  247. delete new_client;
  248. }
  249. }
  250. private:
  251. io_service& io_service_;
  252. tcp::acceptor acceptor_;
  253. TCPClient* listening_;
  254. };
  255. class UDPServer {
  256. public:
  257. UDPServer(io_service& io_service, int af, short port) :
  258. io_service_(io_service),
  259. socket_(io_service, af == AF_INET6 ? udp::v6() : udp::v4()),
  260. response_buffer_(0),
  261. response_renderer_(response_buffer_),
  262. dns_message_(Message::PARSE)
  263. {
  264. // Set v6-only (we use a different instantiation for v4,
  265. // otherwise asio will bind to both v4 and v6
  266. if (af == AF_INET6) {
  267. socket_.set_option(boost::asio::ip::v6_only(true));
  268. socket_.bind(udp::endpoint(udp::v6(), port));
  269. } else {
  270. socket_.bind(udp::endpoint(udp::v4(), port));
  271. }
  272. startReceive();
  273. }
  274. void handleRequest(const boost::system::error_code& error,
  275. size_t bytes_recvd)
  276. {
  277. if (!error && bytes_recvd > 0) {
  278. InputBuffer request_buffer(data_, bytes_recvd);
  279. dns_message_.clear(Message::PARSE);
  280. response_renderer_.clear();
  281. if (auth_server->processMessage(request_buffer, dns_message_,
  282. response_renderer_, true)) {
  283. socket_.async_send_to(
  284. boost::asio::buffer(response_buffer_.getData(),
  285. response_buffer_.getLength()),
  286. sender_endpoint_,
  287. boost::bind(&UDPServer::sendCompleted,
  288. this,
  289. placeholders::error,
  290. placeholders::bytes_transferred));
  291. } else {
  292. startReceive();
  293. }
  294. } else {
  295. startReceive();
  296. }
  297. }
  298. void sendCompleted(const boost::system::error_code& error UNUSED_PARAM,
  299. size_t bytes_sent UNUSED_PARAM)
  300. {
  301. // Even if error occurred there's nothing to do. Simply handle
  302. // the next request.
  303. startReceive();
  304. }
  305. private:
  306. void startReceive() {
  307. socket_.async_receive_from(
  308. boost::asio::buffer(data_, MAX_LENGTH), sender_endpoint_,
  309. boost::bind(&UDPServer::handleRequest, this,
  310. placeholders::error,
  311. placeholders::bytes_transferred));
  312. }
  313. private:
  314. io_service& io_service_;
  315. udp::socket socket_;
  316. OutputBuffer response_buffer_;
  317. MessageRenderer response_renderer_;
  318. Message dns_message_;
  319. udp::endpoint sender_endpoint_;
  320. enum { MAX_LENGTH = 4096 };
  321. char data_[MAX_LENGTH];
  322. };
  323. struct ServerSet {
  324. ServerSet() : udp4_server(NULL), udp6_server(NULL),
  325. tcp4_server(NULL), tcp6_server(NULL)
  326. {}
  327. ~ServerSet() {
  328. delete udp4_server;
  329. delete udp6_server;
  330. delete tcp4_server;
  331. delete tcp6_server;
  332. }
  333. UDPServer* udp4_server;
  334. UDPServer* udp6_server;
  335. TCPServer* tcp4_server;
  336. TCPServer* tcp6_server;
  337. };
  338. void
  339. run_server(const char* port, const bool use_ipv4, const bool use_ipv6,
  340. AuthSrv* srv UNUSED_PARAM)
  341. {
  342. ServerSet servers;
  343. short portnum = atoi(port);
  344. if (use_ipv4) {
  345. servers.udp4_server = new UDPServer(io_service_, AF_INET, portnum);
  346. servers.tcp4_server = new TCPServer(io_service_, AF_INET, portnum);
  347. }
  348. if (use_ipv6) {
  349. servers.udp6_server = new UDPServer(io_service_, AF_INET6, portnum);
  350. servers.tcp6_server = new TCPServer(io_service_, AF_INET6, portnum);
  351. }
  352. cout << "Server started." << endl;
  353. io_service_.run();
  354. }
  355. #else // !HAVE_BOOST_SYSTEM
  356. struct SocketSet {
  357. SocketSet() : ups4(-1), tps4(-1), ups6(-1), tps6(-1) {}
  358. ~SocketSet() {
  359. if (ups4 >= 0) {
  360. close(ups4);
  361. }
  362. if (tps4 >= 0) {
  363. close(tps4);
  364. }
  365. if (ups6 >= 0) {
  366. close(ups6);
  367. }
  368. if (tps4 >= 0) {
  369. close(tps6);
  370. }
  371. }
  372. int ups4, tps4, ups6, tps6;
  373. };
  374. int
  375. getUDPSocket(int af, const char* port) {
  376. struct addrinfo hints, *res;
  377. memset(&hints, 0, sizeof(hints));
  378. hints.ai_family = af;
  379. hints.ai_socktype = SOCK_DGRAM;
  380. hints.ai_flags = AI_PASSIVE;
  381. hints.ai_protocol = IPPROTO_UDP;
  382. int error = getaddrinfo(NULL, port, &hints, &res);
  383. if (error != 0) {
  384. isc_throw(FatalError, "getaddrinfo failed: " << gai_strerror(error));
  385. }
  386. int s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
  387. if (s < 0) {
  388. isc_throw(FatalError, "failed to open socket");
  389. }
  390. if (af == AF_INET6) {
  391. int on = 1;
  392. if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) < 0) {
  393. cerr << "couldn't set IPV6_V6ONLY socket option" << endl;
  394. // proceed anyway
  395. }
  396. }
  397. if (bind(s, res->ai_addr, res->ai_addrlen) < 0) {
  398. isc_throw(FatalError, "binding socket failure");
  399. }
  400. return (s);
  401. }
  402. int
  403. getTCPSocket(int af, const char* port) {
  404. struct addrinfo hints, *res;
  405. memset(&hints, 0, sizeof(hints));
  406. hints.ai_family = af;
  407. hints.ai_socktype = SOCK_STREAM;
  408. hints.ai_flags = AI_PASSIVE;
  409. hints.ai_protocol = IPPROTO_TCP;
  410. int error = getaddrinfo(NULL, port, &hints, &res);
  411. if (error != 0) {
  412. isc_throw(FatalError, "getaddrinfo failed: " << gai_strerror(error));
  413. }
  414. int s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
  415. if (s < 0) {
  416. isc_throw(FatalError, "failed to open socket");
  417. }
  418. int on = 1;
  419. if (af == AF_INET6) {
  420. if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) < 0) {
  421. cerr << "couldn't set IPV6_V6ONLY socket option" << endl;
  422. }
  423. // proceed anyway
  424. }
  425. if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) {
  426. cerr << "couldn't set SO_REUSEADDR socket option" << endl;
  427. }
  428. if (bind(s, res->ai_addr, res->ai_addrlen) < 0) {
  429. isc_throw(FatalError, "binding socket failure");
  430. }
  431. if (listen(s, 100) < 0) {
  432. isc_throw(FatalError, "failed to listen on a TCP socket");
  433. }
  434. return (s);
  435. }
  436. void
  437. processMessageUDP(const int fd, Message& dns_message,
  438. MessageRenderer& response_renderer)
  439. {
  440. struct sockaddr_storage ss;
  441. socklen_t sa_len = sizeof(ss);
  442. struct sockaddr* sa = static_cast<struct sockaddr*>((void*)&ss);
  443. char recvbuf[4096];
  444. int cc;
  445. dns_message.clear(Message::PARSE);
  446. response_renderer.clear();
  447. if ((cc = recvfrom(fd, recvbuf, sizeof(recvbuf), 0, sa, &sa_len)) > 0) {
  448. InputBuffer buffer(recvbuf, cc);
  449. if (auth_server->processMessage(buffer, dns_message, response_renderer,
  450. true)) {
  451. cc = sendto(fd, response_renderer.getData(),
  452. response_renderer.getLength(), 0, sa, sa_len);
  453. if (cc != response_renderer.getLength()) {
  454. cerr << "UDP send error" << endl;
  455. }
  456. }
  457. } else if (verbose_mode) {
  458. cerr << "UDP receive error" << endl;
  459. }
  460. }
  461. // XXX: this function does not handle partial reads or partial writes,
  462. // and is VERY UNSAFE - will probably be removed or rewritten
  463. void
  464. processMessageTCP(const int fd, Message& dns_message,
  465. MessageRenderer& response_renderer)
  466. {
  467. struct sockaddr_storage ss;
  468. socklen_t sa_len = sizeof(ss);
  469. struct sockaddr* sa = static_cast<struct sockaddr*>((void*)&ss);
  470. char sizebuf[2];
  471. int cc;
  472. int ts = accept(fd, sa, &sa_len);
  473. if (ts < 0) {
  474. if (verbose_mode) {
  475. cerr << "[XX] TCP accept failure:" << endl;
  476. return;
  477. }
  478. }
  479. if (verbose_mode) {
  480. cerr << "[XX] process TCP" << endl;
  481. }
  482. cc = recv(ts, sizebuf, 2, 0);
  483. if (cc < 0) {
  484. if (verbose_mode) {
  485. cerr << "[XX] TCP recv failure:" << endl;
  486. }
  487. close(ts);
  488. return;
  489. }
  490. if (verbose_mode) {
  491. cerr << "[XX] got: " << cc << endl;
  492. }
  493. uint16_t size, size_n;
  494. memcpy(&size_n, sizebuf, 2);
  495. size = ntohs(size_n);
  496. if (verbose_mode) {
  497. cerr << "[XX] got: " << size << endl;
  498. }
  499. vector<char> message_buffer;
  500. message_buffer.reserve(size);
  501. cc = 0;
  502. while (cc < size) {
  503. if (verbose_mode) {
  504. cerr << "[XX] cc now: " << cc << " of " << size << endl;
  505. }
  506. const int cc0 = recv(ts, &message_buffer[0] + cc, size - cc, 0);
  507. if (cc0 < 0) {
  508. if (verbose_mode) {
  509. cerr << "TCP receive error" << endl;
  510. close(ts);
  511. return;
  512. }
  513. }
  514. if (cc0 == 0) {
  515. // client closed connection
  516. close(ts);
  517. return;
  518. }
  519. cc += cc0;
  520. }
  521. InputBuffer buffer(&message_buffer[0], size);
  522. dns_message.clear(Message::PARSE);
  523. response_renderer.clear();
  524. if (auth_server->processMessage(buffer, dns_message, response_renderer,
  525. false)) {
  526. size = response_renderer.getLength();
  527. size_n = htons(size);
  528. if (send(ts, &size_n, 2, 0) == 2) {
  529. cc = send(ts, response_renderer.getData(),
  530. response_renderer.getLength(), 0);
  531. if (cc == -1) {
  532. if (verbose_mode) {
  533. cerr << "[AuthSrv] error in sending TCP response message" <<
  534. endl;
  535. }
  536. } else {
  537. if (verbose_mode) {
  538. cerr << "[XX] sent TCP response: " << cc << " bytes"
  539. << endl;
  540. }
  541. }
  542. } else {
  543. if (verbose_mode) {
  544. cerr << "TCP send error" << endl;
  545. }
  546. }
  547. }
  548. // TODO: we don't check for more queries on the stream atm
  549. close(ts);
  550. }
  551. void
  552. run_server(const char* port, const bool use_ipv4, const bool use_ipv6,
  553. AuthSrv* srv)
  554. {
  555. SocketSet socket_set;
  556. fd_set fds_base;
  557. int nfds = -1;
  558. FD_ZERO(&fds_base);
  559. if (use_ipv4) {
  560. socket_set.ups4 = getUDPSocket(AF_INET, port);
  561. FD_SET(socket_set.ups4, &fds_base);
  562. nfds = max(nfds, socket_set.ups4);
  563. socket_set.tps4 = getTCPSocket(AF_INET, port);
  564. FD_SET(socket_set.tps4, &fds_base);
  565. nfds = max(nfds, socket_set.tps4);
  566. }
  567. if (use_ipv6) {
  568. socket_set.ups6 = getUDPSocket(AF_INET6, port);
  569. FD_SET(socket_set.ups6, &fds_base);
  570. nfds = max(nfds, socket_set.ups6);
  571. socket_set.tps6 = getTCPSocket(AF_INET6, port);
  572. FD_SET(socket_set.tps6, &fds_base);
  573. nfds = max(nfds, socket_set.tps6);
  574. }
  575. ++nfds;
  576. cout << "Server started." << endl;
  577. if (srv->configSession() == NULL) {
  578. isc_throw(FatalError, "Config session not initalized");
  579. }
  580. int ss = srv->configSession()->getSocket();
  581. Message dns_message(Message::PARSE);
  582. OutputBuffer resonse_buffer(0);
  583. MessageRenderer response_renderer(resonse_buffer);
  584. running = true;
  585. while (running) {
  586. fd_set fds = fds_base;
  587. FD_SET(ss, &fds);
  588. ++nfds;
  589. if (srv->configSession()->hasQueuedMsgs()) {
  590. srv->configSession()->checkCommand();
  591. }
  592. int n = select(nfds, &fds, NULL, NULL, NULL);
  593. if (n < 0) {
  594. if (errno != EINTR) {
  595. isc_throw(FatalError, "select error");
  596. }
  597. continue;
  598. }
  599. if (socket_set.ups4 >= 0 && FD_ISSET(socket_set.ups4, &fds)) {
  600. processMessageUDP(socket_set.ups4, dns_message, response_renderer);
  601. }
  602. if (socket_set.ups6 >= 0 && FD_ISSET(socket_set.ups6, &fds)) {
  603. processMessageUDP(socket_set.ups6, dns_message, response_renderer);
  604. }
  605. if (socket_set.tps4 >= 0 && FD_ISSET(socket_set.tps4, &fds)) {
  606. processMessageTCP(socket_set.tps4, dns_message, response_renderer);
  607. }
  608. if (socket_set.tps6 >= 0 && FD_ISSET(socket_set.tps6, &fds)) {
  609. processMessageTCP(socket_set.tps6, dns_message, response_renderer);
  610. }
  611. if (FD_ISSET(ss, &fds)) {
  612. srv->configSession()->checkCommand();
  613. }
  614. }
  615. }
  616. #endif // HAVE_BOOST_SYSTEM
  617. void
  618. usage() {
  619. cerr << "Usage: b10-auth [-p port] [-4|-6]" << endl;
  620. exit(1);
  621. }
  622. } // end of anonymous namespace
  623. int
  624. main(int argc, char* argv[]) {
  625. int ch;
  626. const char* port = DNSPORT;
  627. bool use_ipv4 = true, use_ipv6 = true;
  628. while ((ch = getopt(argc, argv, "46p:v")) != -1) {
  629. switch (ch) {
  630. case '4':
  631. // Note that -4 means "ipv4 only", we need to set "use_ipv6" here,
  632. // not "use_ipv4". We could use something like "ipv4_only", but
  633. // we found the negatively named variable could confuse the code
  634. // logic.
  635. use_ipv6 = false;
  636. break;
  637. case '6':
  638. // The same note as -4 applies.
  639. use_ipv4 = false;
  640. break;
  641. case 'p':
  642. port = optarg;
  643. break;
  644. case 'v':
  645. verbose_mode = true;
  646. break;
  647. case '?':
  648. default:
  649. usage();
  650. }
  651. }
  652. if (argc - optind > 0) {
  653. usage();
  654. }
  655. if (!use_ipv4 && !use_ipv6) {
  656. cerr << "-4 and -6 can't coexist" << endl;
  657. usage();
  658. }
  659. // initialize command channel
  660. int ret = 0;
  661. try {
  662. string specfile;
  663. if (getenv("B10_FROM_SOURCE")) {
  664. specfile = string(getenv("B10_FROM_SOURCE")) +
  665. "/src/bin/auth/auth.spec";
  666. } else {
  667. specfile = string(AUTH_SPECFILE_LOCATION);
  668. }
  669. auth_server = new AuthSrv;
  670. auth_server->setVerbose(verbose_mode);
  671. #ifdef HAVE_BOOST_SYSTEM
  672. ModuleCCSession cs(specfile, io_service_, my_config_handler,
  673. my_command_handler);
  674. #else
  675. ModuleCCSession cs(specfile, my_config_handler, my_command_handler);
  676. #endif
  677. auth_server->setConfigSession(&cs);
  678. auth_server->updateConfig(ElementPtr());
  679. run_server(port, use_ipv4, use_ipv6, auth_server);
  680. } catch (const std::exception& ex) {
  681. cerr << ex.what() << endl;
  682. ret = 1;
  683. }
  684. delete auth_server;
  685. return (ret);
  686. }