@SuppressWarnings("unchecked")
  private static void addRRset(
      Name name, final Message response, Record[] records, final int section) {
    Multimap<RequestType, Record> rrsets = ArrayListMultimap.create();
    for (Record r : records) {
      RequestType type = RequestType.typeOf(r.getType());
      rrsets.get(type).addAll(Collections2.filter(Arrays.asList(records), type));
    }
    Predicate<Record> checkNewRecord =
        new Predicate<Record>() {

          @Override
          public boolean apply(Record input) {
            for (int s = 1; s <= section; s++) {
              if (response.findRecord(input, s)) {
                return false;
              }
            }
            return true;
          }
        };
    if (rrsets.containsKey(RequestType.CNAME)) {
      for (Record cnames : Iterables.filter(rrsets.removeAll(RequestType.CNAME), checkNewRecord)) {
        response.addRecord(cnames, section);
      }
    }
    for (Record sectionRecord : Iterables.filter(rrsets.values(), checkNewRecord)) {
      response.addRecord(sectionRecord, section);
    }
  }
 /** Test of getRecord method, of class DNSJavaDecoder. */
 @Test
 public void testGetRecord() {
   System.out.println("getRecord");
   String recstr = ". A IN";
   DNSJavaDecoder instance = new DNSJavaDecoder();
   Record result = instance.getRecord(recstr);
   assertTrue(result.toString().endsWith("A"));
 }
  protected static long getMaximumTTL(final List<Record> records) {
    long maximumTTL = 0;

    for (Record record : records) {
      if (record.getTTL() > maximumTTL) {
        maximumTTL = record.getTTL();
      }
    }

    return maximumTTL;
  }
 /**
  * This resolver works when it is: 1. Enabled 2. The query is absolute 3. The name/address is not
  * in a Eucalyptus controlled subdomain
  *
  * @see com.eucalyptus.util.dns.DnsResolvers.DnsResolver#checkAccepts(Record, org.xbill.DNS.Name,
  *     InetAddress)
  */
 @Override
 public boolean checkAccepts(Record query, InetAddress source) {
   if (!Bootstrap.isOperational() || !enabled) {
     return false;
   } else if ((RequestType.A.apply(query) || RequestType.AAAA.apply(query))
       && query.getName().isAbsolute()
       && !DomainNames.isSystemSubdomain(query.getName())) {
     return true;
   } else if (RequestType.PTR.apply(query)
       && !Subnets.isSystemManagedAddress(
           DomainNameRecords.inAddrArpaToInetAddress(query.getName()))) {
     return true;
   }
   return false;
 }
  /*
   * Look for SOA records corresponding to the request
   * TODO: Add cache coherency to SOA records?
   */
  protected synchronized Record checkForSoaRecord(String questionName) {
    if (!questionName.endsWith(".")) questionName += ".";

    if (soaRecords == null) {
      DnsRecord[] getRecs = null;
      // load all SOA records...
      try {
        getRecs = proxy.getDNSByType(Type.SOA);

        if (getRecs == null || getRecs.length == 0) soaRecords = Collections.emptyMap();
        else {
          soaRecords = new HashMap<String, Record>();

          for (DnsRecord rec : getRecs) {
            Record newRec =
                Record.newRecord(
                    Name.fromString(rec.getName()),
                    Type.SOA,
                    rec.getDclass(),
                    rec.getTtl(),
                    rec.getData());

            soaRecords.put(newRec.getName().toString(), newRec);
          }
        }
      } catch (Exception e) {
        LOGGER.error("Failed to load SOA records from config service.");
      }
    }

    Record retVal = null;
    if (soaRecords.size() > 0) {
      // look for the record by question name

      retVal = soaRecords.get(questionName);
      if (retVal == null) {
        // start taking apart the question name . by .
        int index = -1;
        while ((index = questionName.indexOf(".")) > 0 && index < (questionName.length() - 1)) {
          questionName = questionName.substring(index + 1);
          retVal = soaRecords.get(questionName);
          if (retVal != null) break;
        }
      }
    }

    return retVal;
  }
  @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 Message makeQuery(DNSRequest request, int id) throws TextParseException {
    Name name = Name.fromString(request.getHostname(), Name.root);

    int type;
    switch (request.getRecordType()) {
      case DNSRequest.A:
        type = Type.A;
        break;
      case DNSRequest.AAAA:
        type = Type.AAAA;
        break;
      case DNSRequest.MX:
        type = Type.MX;
        break;
      case DNSRequest.PTR:
        type = Type.PTR;
        break;
      case DNSRequest.SPF:
        type = Type.SPF;
        break;
      case DNSRequest.TXT:
        type = Type.TXT;
        break;
      default:
        throw new UnsupportedOperationException("Unknown query type: " + request.getRecordType());
    }

    Record question = Record.newRecord(name, type, DClass.ANY);
    Message query = Message.newQuery(question);
    query.getHeader().setID(id);
    return query;
  }
  private static String createQuery(final Record query) {
    if (query != null && query.getName() != null) {
      final String qname = query.getName().toString();
      final String qtype = Type.string(query.getType());
      final String qclass = DClass.string(query.getDClass());

      return new StringBuilder()
          .append("fqdn=")
          .append(qname)
          .append(" type=")
          .append(qtype)
          .append(" class=")
          .append(qclass)
          .toString();
    }
    return "";
  }
  private void parseRecord(Message message, InetAddress address) {
    // We really only care about the ADDITIONAL section (specifically the text records)
    Record[] responses = message.getSectionArray(Section.ADDITIONAL);
    // We only want to process records that actually have a length, have an ANSWER
    // section that has stuff in it and that the ANSWER to our query is what we sent
    if (responses.length != 0
        && message.getSectionArray(Section.ANSWER).length != 0
        && message
            .getSectionArray(Section.ANSWER)[0]
            .getName()
            .toString()
            .equals(NvmDNS.MDNS_QUERY)) {

      Log.v("NvmDNS Response", "Got a packet from " + address.getCanonicalHostName());
      Log.v(
          "NvmDNS Response",
          "Question: " + message.getSectionArray(Section.ANSWER)[0].getName().toString());
      Log.v("NvmDNS Response", "Response: " + responses[0].getName().toString());

      // TODO: The DNS entry we get is "XENITH._nvstream._tcp.local."
      // And the .'s in there are not actually periods. Or something.
      String hostname = responses[0].getName().toString();

      // The records can be returned in any order, so we need to figure out which one is the
      // TXTRecord
      // We get three records back: A TXTRecord, a SRVRecord and an ARecord
      TXTRecord txtRecord = null;

      for (Record record : responses) {
        Log.v(
            "NvmDNS Response",
            "We recieved a DNS repsonse with a " + record.getClass().getName() + " record.");
        if (record instanceof TXTRecord) {
          txtRecord = (TXTRecord) record;
        }
      }

      if (txtRecord == null) {
        Log.e("NvmDNS Response", "We recieved a malformed DNS repsonse with no TXTRecord");
        return;
      }

      this.parseTXTRecord(txtRecord, address, hostname);
    }
  }
  private static String createTTLandAnswer(final Message dnsMessage) {
    if (dnsMessage.getSectionArray(Section.ANSWER) == null
        || dnsMessage.getSectionArray(Section.ANSWER).length == 0) {
      return "ttl=\"-\" ans=\"-\"";
    }

    final StringBuilder answerStringBuilder = new StringBuilder();
    final StringBuilder ttlStringBuilder = new StringBuilder();
    for (final Record record : dnsMessage.getSectionArray(Section.ANSWER)) {
      final String s = record.rdataToString() + " ";
      final String ttl = record.getTTL() + " ";
      answerStringBuilder.append(s);
      ttlStringBuilder.append(ttl);
    }

    return "ttl=\""
        + ttlStringBuilder.toString().trim()
        + "\" ans=\""
        + answerStringBuilder.toString().trim()
        + "\"";
  }
 public static SetResponse findRecords(
     final Message response, final Record queryRecord, final InetAddress source) {
   final Name name = queryRecord.getName();
   final int type = queryRecord.getType();
   try {
     if (!enabled || !Bootstrap.isOperational()) {
       return SetResponse.ofType(SetResponse.UNKNOWN);
     } else {
       final Iterable<DnsResolver> resolverList = DnsResolvers.resolversFor(queryRecord, source);
       LOG.debug("DnsResolvers.findRecords(): resolvers for " + name + " are: " + resolverList);
       if (Iterables.isEmpty(resolverList)) {
         return SetResponse.ofType(SetResponse.UNKNOWN);
       } else {
         return DnsResolvers.lookupRecords(response, queryRecord, source);
       }
     }
   } catch (final Exception ex) {
     LOG.error(ex);
     LOG.trace(ex, ex);
   }
   return SetResponse.ofType(SetResponse.UNKNOWN);
 }
 private static SetResponse lookupRecords(
     final Message response, final Record query, final InetAddress source) {
   final Name name = query.getName();
   final int type = query.getType();
   response.getHeader().setFlag(Flags.RA); // always mark the response w/ the recursion available
   // bit
   LOG.debug("DnsResolver: " + RequestType.typeOf(type) + " " + name);
   for (final DnsResolver r : DnsResolvers.resolversFor(query, source)) {
     try {
       final DnsResponse reply = r.lookupRecords(query);
       if (reply == null) {
         LOG.debug("DnsResolver: returned null " + name + " using " + r);
         continue;
       }
       if (reply.isAuthoritative()) { // mark
         response.getHeader().setFlag(Flags.AA);
       }
       if (reply.isNxdomain()) {
         addRRset(name, response, new Record[] {DomainNameRecords.sourceOfAuthority(name)}, type);
         response.getHeader().setRcode(Rcode.NXDOMAIN);
         return SetResponse.ofType(SetResponse.NXDOMAIN);
       } else if (reply.hasAnswer()) {
         for (ResponseSection s : ResponseSection.values()) {
           Record[] records = reply.section(s);
           if (records != null) {
             addRRset(name, response, records, s.section());
           }
         }
         return SetResponse.ofType(SetResponse.SUCCESSFUL);
       }
     } catch (final Exception ex) {
       LOG.debug(
           "DnsResolver: failed for " + name + " using " + r + " because of: " + ex.getMessage(),
           ex);
     }
   }
   return SetResponse.ofType(SetResponse.UNKNOWN); // no dice, return unknown
 }
Exemple #13
0
  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());
    }
  }
  @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\"");
  }
  protected Collection<Record> processGenericANYRecordRequest(String name) throws DNSException {
    DnsRecord records[];

    try {
      records = proxy.getDNSByNameAndType(name, Type.ANY);
    } catch (Exception e) {
      throw new DNSException(
          DNSError.newError(Rcode.SERVFAIL),
          "DNS service proxy call for DNS records failed: " + e.getMessage(),
          e);
    }

    if (records == null || records.length == 0) return null;

    Collection<Record> retVal = new ArrayList<Record>();
    try {
      for (DnsRecord record : records) {
        Record rec =
            Record.newRecord(
                Name.fromString(record.getName()),
                record.getType(),
                record.getDclass(),
                record.getTtl(),
                record.getData());

        retVal.add(rec);
      }
    } catch (Exception e) {
      throw new DNSException(
          DNSError.newError(Rcode.SERVFAIL),
          "Failure while parsing generic record data: " + e.getMessage(),
          e);
    }

    return retVal;
  }
  @SuppressWarnings("unchecked")
  public void execute() throws Exception {
    // Read in the zone
    List<Record> records = ZoneUtils.readZoneFile(state.inputfile, null);
    if (records == null || records.size() == 0) {
      System.err.println("error: empty RRset file");
      state.usage();
    }
    // Construct the RRset. Complain if the records in the input file
    // consist of more than one RRset.
    RRset rrset = null;

    for (Record r : records) {
      // skip RRSIGs
      if (r.getType() == Type.RRSIG || r.getType() == Type.SIG) {
        continue;
      }

      // Handle the first record.
      if (rrset == null) {
        rrset = new RRset();
        rrset.addRR(r);
        continue;
      }
      // Ensure that the remaining records all belong to the same rrset.
      if (rrset.getName().equals(r.getName())
          && rrset.getType() == r.getType()
          && rrset.getDClass() == r.getDClass()) {
        rrset.addRR(r);
      } else {
        System.err.println("Records do not all belong to the same RRset.");
        state.usage();
      }
    }

    if (rrset.size() == 0) {
      System.err.println("No records found in inputfile.");
      state.usage();
    }

    // Load the key pairs.

    if (state.keyFiles.length == 0) {
      System.err.println("error: at least one keyfile must be specified");
      state.usage();
    }

    List<DnsKeyPair> keypairs = getKeys(state.keyFiles, 0, state.keyDirectory);

    // Make sure that all the keypairs have the same name.
    // This will be used as the zone name, too.

    Name keysetName = null;
    for (DnsKeyPair pair : keypairs) {
      if (keysetName == null) {
        keysetName = pair.getDNSKEYName();
        continue;
      }
      if (!pair.getDNSKEYName().equals(keysetName)) {
        System.err.println("Keys do not all have the same name.");
        state.usage();
      }
    }

    // default the output file, if not set.
    if (state.outputfile == null && !state.inputfile.equals("-")) {
      state.outputfile = state.inputfile + ".signed";
    }

    JCEDnsSecSigner signer = new JCEDnsSecSigner();

    List<RRSIGRecord> sigs = signer.signRRset(rrset, keypairs, state.start, state.expire);
    for (RRSIGRecord s : sigs) {
      rrset.addRR(s);
    }

    // write out the signed RRset
    List<Record> signed_records = new ArrayList<Record>();
    for (Iterator<Record> i = rrset.rrs(); i.hasNext(); ) {
      signed_records.add(i.next());
    }
    for (Iterator<Record> i = rrset.sigs(); i.hasNext(); ) {
      signed_records.add(i.next());
    }

    // write out the signed zone
    ZoneUtils.writeZoneFile(signed_records, state.outputfile);

    if (state.verifySigs) {
      log.fine("verifying generated signatures");
      boolean res = verifySigs(keysetName, signed_records, keypairs);

      if (res) {
        System.out.println("Generated signatures verified");
        // log.info("Generated signatures verified");
      } else {
        System.out.println("Generated signatures did not verify.");
        // log.warn("Generated signatures did not verify.");
      }
    }
  }
 @Override
 public DnsResponse lookupRecords(final Record query) {
   final Name name = query.getName();
   final int type = query.getType();
   final Cache cache = new Cache();
   Lookup aLookup = new Lookup(name, type);
   aLookup.setCache(cache);
   Record[] found = aLookup.run();
   List<Record> queriedrrs = Arrays.asList(found != null ? found : new Record[] {});
   List<Name> cnames =
       (List<Name>)
           (aLookup.getAliases().length > 0
               ? Arrays.asList(aLookup.getAliases())
               : Lists.newArrayList());
   List<Record> answer = Lists.newArrayList();
   List<Record> authority = Lists.newArrayList();
   List<Record> additional = Lists.newArrayList();
   for (Name cnameRec : cnames) {
     SetResponse sr = cache.lookupRecords(cnameRec, Type.CNAME, Credibility.ANY);
     if (sr != null && sr.isSuccessful() && sr.answers() != null) {
       for (RRset result : sr.answers()) {
         Iterator rrs = result.rrs(false);
         if (rrs != null) {
           for (Object record : ImmutableSet.copyOf(rrs)) {
             answer.add((Record) record);
           }
         }
       }
     }
   }
   for (Record queriedRec : queriedrrs) {
     SetResponse sr =
         cache.lookupRecords(queriedRec.getName(), queriedRec.getType(), Credibility.ANY);
     if (sr != null && sr.isSuccessful() && sr.answers() != null) {
       for (RRset result : sr.answers()) {
         Iterator rrs = result.rrs(false);
         if (rrs != null) {
           for (Object record : ImmutableSet.copyOf(rrs)) {
             answer.add((Record) record);
           }
         }
       }
     }
   }
   for (Record aRec : queriedrrs) {
     List<Record> nsRecs = lookupNSRecords(aRec.getName(), cache);
     for (Record nsRec : nsRecs) {
       authority.add(nsRec);
       Lookup nsLookup = new Lookup(((NSRecord) nsRec).getTarget(), Type.A);
       nsLookup.setCache(cache);
       Record[] nsAnswers = nsLookup.run();
       if (nsAnswers != null) {
         additional.addAll(Arrays.asList(nsAnswers));
       }
     }
   }
   return DnsResponse.forName(query.getName())
       .recursive()
       .withAuthority(authority)
       .withAdditional(additional)
       .answer(answer);
 }
  /** {@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;
  }
 /*
  * converts a configuration service DnsRecord to a dnsjava Record
  */
 private Record toRecord(DnsRecord rec) {
   return Record.newRecord(
       nameFromString(rec.getName()), rec.getType(), rec.getDclass(), rec.getTtl(), rec.getData());
 }
 @Override
 public boolean apply(Record input) {
   return input.getType() == this.type;
 }