15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <arpa/inet.h> 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <errno.h> 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <netinet/in.h> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <signal.h> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdio.h> 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdlib.h> 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string.h> 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/socket.h> 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/types.h> 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <unistd.h> 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string> 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/posix/eintr_wrapper.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/safe_strerror_posix.h" 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/big_endian.h" 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_util.h" 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/dns/dns_protocol.h" 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "tools/android/common/daemon.h" 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "tools/android/common/net.h" 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Mininum request size: 1 question containing 1 QNAME, 1 TYPE and 1 CLASS. 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const size_t kMinRequestSize = sizeof(net::dns_protocol::Header) + 6; 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The name reference in the answer pointing to the name in the query. 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Its format is: highest two bits set to 1, then the offset of the name 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// which just follows the header. 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const uint16 kPointerToQueryName = 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<uint16>(0xc000 | sizeof(net::dns_protocol::Header)); 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const uint32 kTTL = 86400; // One day. 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PError(const char* msg) { 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int current_errno = errno; 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "ERROR: " << msg << ": " << safe_strerror(current_errno); 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SendTo(int sockfd, const void* buf, size_t len, int flags, 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const sockaddr* dest_addr, socklen_t addrlen) { 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (HANDLE_EINTR(sendto(sockfd, buf, len, flags, dest_addr, addrlen)) == -1) 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PError("sendto()"); 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloseFileDescriptor(int fd) { 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int old_errno = errno; 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (void) HANDLE_EINTR(close(fd)); 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) errno = old_errno; 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SendRefusedResponse(int sock, const sockaddr_in& client_addr, uint16 id) { 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::dns_protocol::Header response; 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) response.id = htons(id); 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) response.flags = htons(net::dns_protocol::kFlagResponse | 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::dns_protocol::kFlagAA | 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::dns_protocol::kFlagRD | 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::dns_protocol::kFlagRA | 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::dns_protocol::kRcodeREFUSED); 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) response.qdcount = 0; 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) response.ancount = 0; 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) response.nscount = 0; 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) response.arcount = 0; 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SendTo(sock, &response, sizeof(response), 0, 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<const sockaddr*>(&client_addr), sizeof(client_addr)); 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SendResponse(int sock, const sockaddr_in& client_addr, uint16 id, 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint16 qtype, const char* question, size_t question_length) { 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::dns_protocol::Header header; 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) header.id = htons(id); 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) header.flags = htons(net::dns_protocol::kFlagResponse | 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::dns_protocol::kFlagAA | 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::dns_protocol::kFlagRD | 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::dns_protocol::kFlagRA | 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::dns_protocol::kRcodeNOERROR); 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) header.qdcount = htons(1); 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) header.ancount = htons(1); 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) header.nscount = 0; 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) header.arcount = 0; 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Size of RDATA which is a IPv4 or IPv6 address. 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t rdata_size = qtype == net::dns_protocol::kTypeA ? 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::kIPv4AddressSize : net::kIPv6AddressSize; 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Size of the whole response which contains the header, the question and 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the answer. 12 is the sum of sizes of the compressed name reference, TYPE, 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // CLASS, TTL and RDLENGTH. 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t response_size = sizeof(header) + question_length + 12 + rdata_size; 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (response_size > net::dns_protocol::kMaxUDPSize) { 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Response is too large: " << response_size; 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SendRefusedResponse(sock, client_addr, id); 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char response[net::dns_protocol::kMaxUDPSize]; 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::BigEndianWriter writer(response, arraysize(response)); 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) writer.WriteBytes(&header, sizeof(header)); 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Repeat the question in the response. Some clients (e.g. ping) needs this. 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) writer.WriteBytes(question, question_length); 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Construct the answer. 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) writer.WriteU16(kPointerToQueryName); 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) writer.WriteU16(qtype); 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) writer.WriteU16(net::dns_protocol::kClassIN); 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) writer.WriteU32(kTTL); 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) writer.WriteU16(rdata_size); 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (qtype == net::dns_protocol::kTypeA) 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) writer.WriteU32(INADDR_LOOPBACK); 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) writer.WriteBytes(&in6addr_loopback, sizeof(in6_addr)); 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(writer.ptr() - response == response_size); 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SendTo(sock, response, response_size, 0, 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<const sockaddr*>(&client_addr), sizeof(client_addr)); 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HandleRequest(int sock, const char* request, size_t size, 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const sockaddr_in& client_addr) { 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (size < kMinRequestSize) { 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Request is too small " << size 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "\n" << tools::DumpBinary(request, size); 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::BigEndianReader reader(request, size); 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::dns_protocol::Header header; 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reader.ReadBytes(&header, sizeof(header)); 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint16 id = ntohs(header.id); 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint16 flags = ntohs(header.flags); 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint16 qdcount = ntohs(header.qdcount); 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint16 ancount = ntohs(header.ancount); 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint16 nscount = ntohs(header.nscount); 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint16 arcount = ntohs(header.arcount); 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const uint16 kAllowedFlags = 0x07ff; 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((flags & ~kAllowedFlags) || 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) qdcount != 1 || ancount || nscount || arcount) { 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Unsupported request: FLAGS=" << flags 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " QDCOUNT=" << qdcount 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " ANCOUNT=" << ancount 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " NSCOUNT=" << nscount 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " ARCOUNT=" << arcount 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "\n" << tools::DumpBinary(request, size); 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SendRefusedResponse(sock, client_addr, id); 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // request[size - 5] should be the end of the QNAME (a zero byte). 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We don't care about the validity of QNAME because we don't parse it. 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* qname_end = &request[size - 5]; 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (*qname_end) { 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Error parsing QNAME\n" << tools::DumpBinary(request, size); 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SendRefusedResponse(sock, client_addr, id); 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reader.Skip(qname_end - reader.ptr() + 1); 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint16 qtype; 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint16 qclass; 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reader.ReadU16(&qtype); 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reader.ReadU16(&qclass); 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((qtype != net::dns_protocol::kTypeA && 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) qtype != net::dns_protocol::kTypeAAAA) || 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) qclass != net::dns_protocol::kClassIN) { 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Unsupported query: QTYPE=" << qtype << " QCLASS=" << qclass 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "\n" << tools::DumpBinary(request, size); 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SendRefusedResponse(sock, client_addr, id); 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SendResponse(sock, client_addr, id, qtype, 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request + sizeof(header), size - sizeof(header)); 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int main(int argc, char** argv) { 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf("Fake DNS server\n"); 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CommandLine command_line(argc, argv); 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (tools::HasHelpSwitch(command_line) || command_line.GetArgs().size()) { 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tools::ShowHelp(argv[0], "", ""); 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int sock = socket(AF_INET, SOCK_DGRAM, 0); 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (sock < 0) { 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PError("create socket"); 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 1; 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sockaddr_in addr; 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memset(&addr, 0, sizeof(addr)); 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) addr.sin_family = AF_INET; 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) addr.sin_port = htons(53); 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int reuse_addr = 1; 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (HANDLE_EINTR(bind(sock, reinterpret_cast<sockaddr*>(&addr), 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sizeof(addr))) < 0) { 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PError("server bind"); 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CloseFileDescriptor(sock); 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 1; 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!tools::HasNoSpawnDaemonSwitch(command_line)) 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tools::SpawnDaemon(0); 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (true) { 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sockaddr_in client_addr; 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) socklen_t client_addr_len = sizeof(client_addr); 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char request[net::dns_protocol::kMaxUDPSize]; 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int size = HANDLE_EINTR(recvfrom(sock, request, sizeof(request), 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MSG_WAITALL, 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<sockaddr*>(&client_addr), 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &client_addr_len)); 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (size < 0) { 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Unrecoverable error, can only exit. 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Failed to receive a request: " << strerror(errno); 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CloseFileDescriptor(sock); 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 1; 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (size > 0) 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HandleRequest(sock, request, size, client_addr); 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 239