/** * Looks up Records in the Zone. This follows CNAMEs and wildcards. * * @param name The name to look up * @param type The type to look up * @return A SetResponse object * @see SetResponse */ public SetResponse findRecords(Name name, short type) { SetResponse zr = null; Object o = findSets(name, type); if (o == null) { /* The name does not exist */ if (name.isWild()) return SetResponse.ofType(SetResponse.NXDOMAIN); int labels = name.labels() - origin.labels(); if (labels == 0) return SetResponse.ofType(SetResponse.NXDOMAIN); if (hasWild) { SetResponse sr; Name tname = name; do { sr = findRecords(tname.wild(1), type); if (!sr.isNXDOMAIN()) return sr; tname = new Name(tname, 1); } while (labels-- >= 1); return sr; } else return SetResponse.ofType(SetResponse.NXDOMAIN); } if (o instanceof TypeMap) { /* The name exists but the type does not. */ return SetResponse.ofType(SetResponse.NXRRSET); } Object[] objects; RRset rrset; if (o instanceof RRset) { objects = null; rrset = (RRset) o; } else { objects = (Object[]) o; rrset = (RRset) objects[0]; } if (name.equals(rrset.getName())) { if (type != Type.CNAME && type != Type.ANY && rrset.getType() == Type.CNAME) zr = new SetResponse(SetResponse.CNAME, rrset); else if (rrset.getType() == Type.NS && !name.equals(origin)) zr = new SetResponse(SetResponse.DELEGATION, rrset); else { zr = new SetResponse(SetResponse.SUCCESSFUL); zr.addRRset(rrset); if (objects != null) { for (int i = 1; i < objects.length; i++) zr.addRRset((RRset) objects[i]); } } } else { if (rrset.getType() == Type.CNAME) return SetResponse.ofType(SetResponse.NXDOMAIN); else if (rrset.getType() == Type.DNAME) { zr = new SetResponse(SetResponse.DNAME, rrset); } else if (rrset.getType() == Type.NS) { zr = new SetResponse(SetResponse.DELEGATION, rrset); } } return zr; }
private synchronized void addRRset(Name name, RRset rrset) { if (!hasWild && name.isWild()) hasWild = true; Object types = data.get(name); if (types == null) { data.put(name, rrset); return; } int rtype = rrset.getType(); if (types instanceof List) { List list = (List) types; for (int i = 0; i < list.size(); i++) { RRset set = (RRset) list.get(i); if (set.getType() == rtype) { list.set(i, rrset); return; } } list.add(rrset); } else { RRset set = (RRset) types; if (set.getType() == rtype) data.put(name, rrset); else { LinkedList list = new LinkedList(); list.add(set); list.add(rrset); data.put(name, list); } } }
private synchronized RRset oneRRset(Object types, int type) { if (type == Type.ANY) throw new IllegalArgumentException("oneRRset(ANY)"); if (types instanceof List) { List list = (List) types; for (int i = 0; i < list.size(); i++) { RRset set = (RRset) list.get(i); if (set.getType() == type) return set; } } else { RRset set = (RRset) types; if (set.getType() == type) return set; } return null; }
/** * Returns an array containing all records in the given section grouped into RRsets. * * @see RRset * @see Section */ public RRset[] getSectionRRsets(int section) { if (sections[section] == null) return emptyRRsetArray; List sets = new LinkedList(); Record[] recs = getSectionArray(section); Set hash = new HashSet(); for (int i = 0; i < recs.length; i++) { Name name = recs[i].getName(); boolean newset = true; if (hash.contains(name)) { for (int j = sets.size() - 1; j >= 0; j--) { RRset set = (RRset) sets.get(j); if (set.getType() == recs[i].getRRsetType() && set.getDClass() == recs[i].getDClass() && set.getName().equals(name)) { set.addRR(recs[i]); newset = false; break; } } } if (newset) { RRset set = new RRset(recs[i]); sets.add(set); hash.add(name); } } return (RRset[]) sets.toArray(new RRset[sets.size()]); }
/** * Adds an RRset to the Cache. * * @param r The RRset to be added * @param cred The credibility of these records * @param o The source of this RRset (this could be a Message, for example) * @see RRset */ public void addRRset(RRset rrset, byte cred) { Name name = rrset.getName(); short type = rrset.getType(); if (verifier != null) rrset.setSecurity(verifier.verify(rrset, this)); if (secure && rrset.getSecurity() < DNSSEC.Secure) return; Element element = (Element) findExactSet(name, type); if (element == null || cred > element.credibility) addSet(name, type, new PositiveElement(rrset, cred)); }
private synchronized void removeRRset(Name name, int type) { Object types = data.get(name); if (types == null) { return; } if (types instanceof List) { List list = (List) types; for (int i = 0; i < list.size(); i++) { RRset set = (RRset) list.get(i); if (set.getType() == type) { list.remove(i); if (list.size() == 0) data.remove(name); return; } } } else { RRset set = (RRset) types; if (set.getType() != type) return; data.remove(name); } }
public Object next() { if (sentLastSOA) return null; if (!sentFirstSOA) { sentFirstSOA = true; return (RRset) findExactSet(origin, Type.SOA); } if (!sentNS) { sentNS = true; return getNS(); } if (!sentOrigin) { if (currentName == null) { currentName = getOrigin(); TypeMap tm = findName(currentName); current = (Object[]) tm.getAll(); count = 0; } while (count < current.length) { RRset rrset = (RRset) current[count]; if (rrset.getType() != Type.SOA && rrset.getType() != Type.NS) return current[count++]; count++; } current = null; sentOrigin = true; } if (current != null && count < current.length) return current[count++]; while (znames.hasNext()) { Name currentName = (Name) znames.next(); if (currentName.equals(getOrigin())) continue; TypeMap tm = findName(currentName); current = (Object[]) tm.getAll(); count = 0; if (count < current.length) return current[count++]; } sentLastSOA = true; RRset rrset = new RRset(); rrset.addRR(getSOA()); return rrset; }
private void verifyRecords(Cache tcache) { Iterator it; it = tcache.names(); while (it.hasNext()) { Name name = (Name) it.next(); Object[] elements = findExactSets(name); for (int i = 0; i < elements.length; i++) { Element element = (Element) elements[i]; if (element instanceof PositiveElement) continue; RRset rrset = ((PositiveElement) element).rrset; /* for now, ignore negative cache entries */ if (rrset == null) continue; if (verifier != null) rrset.setSecurity(verifier.verify(rrset, this)); if (rrset.getSecurity() < DNSSEC.Secure) continue; addSet(name, rrset.getType(), element); } } }
public short getType() { return rrset.getType(); }
/** * Looks up Records in the Cache. This follows CNAMEs and handles negatively cached data. * * @param name The name to look up * @param type The type to look up * @param minCred The minimum acceptable credibility * @return A SetResponse object * @see SetResponse * @see Credibility */ public SetResponse lookupRecords(Name name, short type, byte minCred) { SetResponse cr = null; boolean verbose = Options.check("verbosecache"); Object o = lookup(name, type); if (verbose) logLookup(name, type, "Starting"); if (o == null || o == NXRRSET) { /* * The name exists, but the type was not found. Or, the * name does not exist and no parent does either. Punt. */ if (verbose) logLookup(name, type, "no information found"); return SetResponse.ofType(SetResponse.UNKNOWN); } Object[] objects; if (o instanceof Element) objects = new Object[] {o}; else objects = (Object[]) o; int nelements = 0; for (int i = 0; i < objects.length; i++) { Element element = (Element) objects[i]; if (element.expired()) { if (verbose) { logLookup(name, type, element.toString()); logLookup(name, type, "expired: ignoring"); } removeSet(name, type, element); objects[i] = null; } else if (element.credibility < minCred) { if (verbose) { logLookup(name, type, element.toString()); logLookup(name, type, "not credible: ignoring"); } objects[i] = null; } else { nelements++; } } if (nelements == 0) { /* We have data, but can't use it. Punt. */ if (verbose) logLookup(name, type, "no useful data found"); return SetResponse.ofType(SetResponse.UNKNOWN); } /* * We have something at the name. It could be the answer, * a CNAME, DNAME, or NS, or a negative cache entry. * * Ignore wildcards, since it's pretty unlikely that any will be * cached. The occasional extra query is easily balanced by the * reduced number of lookups. */ for (int i = 0; i < objects.length; i++) { if (objects[i] == null) continue; Element element = (Element) objects[i]; if (verbose) logLookup(name, type, element.toString()); RRset rrset = null; if (element instanceof PositiveElement) rrset = ((PositiveElement) element).rrset; /* Is this a negatively cached entry? */ if (rrset == null) { /* * If this is an NXDOMAIN entry, return NXDOMAIN. */ if (element.getType() == 0) { if (verbose) logLookup(name, type, "NXDOMAIN"); return SetResponse.ofType(SetResponse.NXDOMAIN); } /* * If we're not looking for type ANY, return NXRRSET. * Otherwise ignore this. */ if (type != Type.ANY) { if (verbose) logLookup(name, type, "NXRRSET"); return SetResponse.ofType(SetResponse.NXRRSET); } else { if (verbose) logLookup(name, type, "ANY query; " + "ignoring NXRRSET"); continue; } } short rtype = rrset.getType(); Name rname = rrset.getName(); if (name.equals(rname)) { if (type != Type.CNAME && type != Type.ANY && rtype == Type.CNAME) { if (verbose) logLookup(name, type, "cname"); return new SetResponse(SetResponse.CNAME, rrset); } else if (type != Type.NS && type != Type.ANY && rtype == Type.NS) { if (verbose) logLookup(name, type, "exact delegation"); return new SetResponse(SetResponse.DELEGATION, rrset); } else { if (verbose) logLookup(name, type, "exact match"); if (cr == null) cr = new SetResponse(SetResponse.SUCCESSFUL); cr.addRRset(rrset); } } else if (name.subdomain(rname)) { if (rtype == Type.DNAME) { if (verbose) logLookup(name, type, "dname"); return new SetResponse(SetResponse.DNAME, rrset); } else if (rtype == Type.NS) { if (verbose) logLookup(name, type, "parent delegation"); return new SetResponse(SetResponse.DELEGATION, rrset); } else { if (verbose) logLookup(name, type, "ignoring rrset (" + rname + " " + Type.string(rtype) + ")"); } } else { if (verbose) logLookup(name, type, "ignoring rrset (" + rname + " " + Type.string(rtype) + ")"); } } /* * As far as I can tell, the only legitimate time cr will be null is * if we queried for ANY and only saw negative responses, but not an * NXDOMAIN. Return UNKNOWN. */ if (cr == null && type == Type.ANY) return SetResponse.ofType(SetResponse.UNKNOWN); else if (cr == null) throw new IllegalStateException( "looking up (" + name + " " + Type.string(type) + "): " + "cr == null."); return cr; }