@Test public void itLogsServerErrors() throws Exception { header.setRcode(Rcode.REFUSED); Name name = Name.fromString("John Wayne."); Record question = Record.newRecord(name, 65530, 43210); Message query = Message.newQuery(question); Message response = mock(Message.class); when(response.getHeader()).thenReturn(header); when(response.getSectionArray(Section.ANSWER)).thenReturn(null); when(response.getQuestion()).thenReturn(question); when(nameServer.query( any(Message.class), any(InetAddress.class), any(DNSAccessRecord.Builder.class))) .thenThrow(new RuntimeException("Aw snap!")); FakeAbstractProtocol abstractProtocol = new FakeAbstractProtocol(client, query.toWire()); abstractProtocol.setNameServer(nameServer); abstractProtocol.run(); verify(accessLogger) .info( "144140678.000 qtype=DNS chi=192.168.23.45 ttms=345.123 xn=65535 fqdn=John\\032Wayne. type=TYPE65530 class=CLASS43210 rcode=SERVFAIL rtype=- rloc=\"-\" rdtl=- rerr=\"Server Error:RuntimeException:Aw snap!\" ttl=\"-\" ans=\"-\""); }
private void sendQuery() { Header queryHeader = new Header(); // If we set the RA (Recursion Available) flag and our message ID to 0 // then the packet matches the real mDNS query packet as displayed in Wireshark queryHeader.setFlag(org.xbill.DNS.Flags.RA); queryHeader.setID(0); Record question = null; try { // We need to create our "Question" DNS query that is a pointer record to // the mDNS Query "Name" question = Record.newRecord(new Name(NvmDNS.MDNS_QUERY), Type.PTR, DClass.IN); } catch (TextParseException e) { Log.e("NvmDNS Query", e.getMessage()); return; } // We combine our header and our question into a single message Message query = new Message(); query.setHeader(queryHeader); query.addRecord(question, Section.QUESTION); // Convert the message into Network Byte Order byte[] wireQuery = query.toWire(); Log.i("NvmDNS Query", query.toString()); // Convert our byte array into a Packet DatagramPacket transmitPacket = new DatagramPacket(wireQuery, wireQuery.length); transmitPacket.setAddress(NvmDNS.MDNS_MULTICAST_ADDRESS); transmitPacket.setPort(NvmDNS.MDNS_PORT); // And (attempt) to send the packet try { Log.d("NvmDNS Query", "Blocking on this.nvstream_socket.send(transmitPacket)"); this.socket.send(transmitPacket); Log.d("NvmDNS Query", "Passed this.nvstream_socket.send(transmitPacket)"); } catch (IOException e) { Log.e("NvmDNS Query", "There was an error sending the DNS query."); Log.e("NvmDNS Query", e.getMessage()); } }
@Before public void before() throws Exception { // force the xn field in the request Random random = mock(Random.class); Mockito.when(random.nextInt(0xffff)).thenReturn(65535); whenNew(Random.class).withNoArguments().thenReturn(random); mockStatic(System.class); when(System.currentTimeMillis()).thenReturn(144140678000L).thenReturn(144140678345L); when(System.nanoTime()).thenReturn(100000000L, 100000000L + 345123000L); mockStatic(Logger.class); when(Logger.getLogger("com.comcast.cdn.traffic_control.traffic_router.core.access")) .thenReturn(accessLogger); header = new Header(); header.setID(65535); header.setFlag(Flags.QR); client = Inet4Address.getByAddress(new byte[] {(byte) 192, (byte) 168, 23, 45}); nameServer = mock(NameServer.class); }
@Test public void itLogsARecordQueries() throws Exception { header.setRcode(Rcode.NOERROR); Name name = Name.fromString("www.example.com."); Record question = Record.newRecord(name, Type.A, DClass.IN, 0L); Message query = Message.newQuery(question); query.getHeader().getRcode(); byte[] queryBytes = query.toWire(); whenNew(Message.class).withArguments(queryBytes).thenReturn(query); InetAddress resolvedAddress = Inet4Address.getByName("192.168.8.9"); Record answer = new ARecord(name, DClass.IN, 3600L, resolvedAddress); Record[] answers = new Record[] {answer}; Message response = mock(Message.class); when(response.getHeader()).thenReturn(header); when(response.getSectionArray(Section.ANSWER)).thenReturn(answers); when(response.getQuestion()).thenReturn(question); InetAddress client = Inet4Address.getByName("192.168.23.45"); when(nameServer.query( any(Message.class), any(InetAddress.class), any(DNSAccessRecord.Builder.class))) .thenReturn(response); FakeAbstractProtocol abstractProtocol = new FakeAbstractProtocol(client, queryBytes); abstractProtocol.setNameServer(nameServer); abstractProtocol.run(); verify(accessLogger) .info( "144140678.000 qtype=DNS chi=192.168.23.45 ttms=345.123 xn=65535 fqdn=www.example.com. type=A class=IN rcode=NOERROR rtype=- rloc=\"-\" rdtl=- rerr=\"-\" ttl=\"3600\" ans=\"192.168.8.9\""); }
/** {@inheritDoc} */ @SuppressWarnings("unchecked") @Override public Message get(Message request) throws DNSException { LOGGER.trace("get(Message) Entered"); /* for testing time out cases try { Thread.sleep(1000000); } catch (Exception e) { } */ if (request == null) throw new DNSException(DNSError.newError(Rcode.FORMERR)); Header header = request.getHeader(); if (header.getFlag(Flags.QR) || header.getRcode() != Rcode.NOERROR) throw new DNSException(DNSError.newError(Rcode.FORMERR)); if (header.getOpcode() != Opcode.QUERY) throw new DNSException(DNSError.newError(Rcode.NOTIMP)); Record question = request.getQuestion(); if (question == null || question.getDClass() != DClass.IN) { throw new DNSException(DNSError.newError(Rcode.NOTIMP)); } Record queryRecord = request.getQuestion(); Name name = queryRecord.getName(); int type = queryRecord.getType(); if (LOGGER.isDebugEnabled()) { StringBuilder builder = new StringBuilder("Recieved Query Request:"); builder.append("\r\n\tName: " + name.toString()); builder.append("\r\n\tType: " + type); builder.append("\r\n\tDClass: " + queryRecord.getDClass()); LOGGER.debug(builder.toString()); } Collection<Record> lookupRecords = null; switch (question.getType()) { case Type.A: case Type.MX: case Type.SOA: case Type.SRV: case Type.NS: case Type.CNAME: { try { final RRset set = processGenericRecordRequest(name.toString(), type); if (set != null) { lookupRecords = new ArrayList<Record>(); Iterator<Record> iter = set.rrs(); while (iter.hasNext()) lookupRecords.add(iter.next()); } } catch (Exception e) { throw new DNSException( DNSError.newError(Rcode.SERVFAIL), "DNS service proxy call failed: " + e.getMessage(), e); } break; } case Type.CERT: { final RRset set = processCERTRecordRequest(name.toString()); if (set != null) { lookupRecords = new ArrayList<Record>(); Iterator<Record> iter = set.rrs(); while (iter.hasNext()) lookupRecords.add(iter.next()); } break; } case Type.ANY: { Collection<Record> genRecs = processGenericANYRecordRequest(name.toString()); RRset certRecs = processCERTRecordRequest(name.toString()); if (genRecs != null || certRecs != null) { lookupRecords = new ArrayList<Record>(); if (genRecs != null) lookupRecords.addAll(genRecs); if (certRecs != null) { Iterator<Record> iter = certRecs.rrs(); while (iter.hasNext()) lookupRecords.add(iter.next()); } } break; } default: { LOGGER.debug("Query Type " + type + " not implemented"); throw new DNSException( DNSError.newError(Rcode.NOTIMP), "Query Type " + type + " not implemented"); } } if (lookupRecords == null || lookupRecords.size() == 0) { LOGGER.debug("No records found."); return null; } final Message response = new Message(request.getHeader().getID()); response.getHeader().setFlag(Flags.QR); if (request.getHeader().getFlag(Flags.RD)) response.getHeader().setFlag(Flags.RD); response.addRecord(queryRecord, Section.QUESTION); final Iterator<Record> iter = lookupRecords.iterator(); while (iter.hasNext()) response.addRecord(iter.next(), Section.ANSWER); // we are authoritative only response.getHeader().setFlag(Flags.AA); // look for an SOA record final Record soaRecord = checkForSoaRecord(name.toString()); if (soaRecord != null) response.addRecord(soaRecord, Section.AUTHORITY); LOGGER.trace("get(Message) Exit"); return response; }