/** * 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; }
@Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } Join other = (Join) obj; if (!table.equals(other.table)) { return false; } if (alias == null) { if (other.alias != null) { return false; } } else if (!alias.equals(other.alias)) { return false; } if (!condition.equals(other.condition)) { return false; } return true; }
/** * Finds and returns name matching the specified symbol, if such name already exists in the table. * If not, will return null. * * <p>Note: separate methods to optimize common case of relatively short element/attribute names * (8 or less ascii characters) * * @param q1 int32 containing first 4 bytes of the name. * @param q2 int32 containing bytes 5 through 8 of the name; if less than 8 bytes, padded with up * to 3 zero bytes in front (zero MSBs, ie. right aligned) * @return Name matching the symbol passed (or constructed for it) */ public Name findName(int q1, int q2) { int hash = (q2 == 0) ? calcHash(q1) : calcHash(q1, q2); int ix = (hash & _hashMask); int val = _hash[ix]; /* High 24 bits of the value are low 24 bits of hash (low 8 bits * are bucket index)... match? */ if ((((val >> 8) ^ hash) << 8) == 0) { // match // Ok, but do we have an actual match? Name name = _mainNames[ix]; if (name == null) { // main slot empty; can't find return null; } if (name.equals(q1, q2)) { return name; } } else if (val == 0) { // empty slot? no match return null; } // Maybe a spill-over? val &= 0xFF; if (val > 0) { // 0 means 'empty' val -= 1; // to convert from 1-based to 0... Bucket bucket = _collList[val]; if (bucket != null) { return bucket.find(hash, q1, q2); } } // Nope, no match whatsoever return null; }
/** * Finds and returns name matching the specified symbol, if such name already exists in the table; * or if not, creates name object, adds to the table, and returns it. * * <p>Note: this is the general purpose method that can be called for names of any length. * However, if name is less than 9 bytes long, it is preferable to call the version optimized for * short names. * * @param q Array of int32s, each of which contain 4 bytes of encoded name * @param qlen Number of int32s, starting from index 0, in quads parameter * @return Name matching the symbol passed (or constructed for it) */ public Name findName(int[] q, int qlen) { if (qlen < 3) { // another sanity check return findName(q[0], (qlen < 2) ? 0 : q[1]); } int hash = calcHash(q, qlen); // (for rest of comments regarding logic, see method above) int ix = (hash & _hashMask); int val = _hash[ix]; if ((((val >> 8) ^ hash) << 8) == 0) { Name name = _mainNames[ix]; if (name == null // main slot empty; no collision list then either || name.equals(q, qlen)) { // should be match, let's verify return name; } } else if (val == 0) { // empty slot? no match return null; } val &= 0xFF; if (val > 0) { // 0 means 'empty' val -= 1; // to convert from 1-based to 0... Bucket bucket = _collList[val]; if (bucket != null) { return bucket.find(hash, q, qlen); } } return null; }
public Name find(int h, int[] quads, int qlen) { if (hash == h) { if (name.equals(quads, qlen)) { return name; } } for (Bucket curr = next; curr != null; curr = curr.next) { if (curr.hash == h) { Name currName = curr.name; if (currName.equals(quads, qlen)) { return currName; } } } return null; }
public Name find(int h, int firstQuad, int secondQuad) { if (hash == h) { if (name.equals(firstQuad, secondQuad)) { return name; } } for (Bucket curr = next; curr != null; curr = curr.next) { if (curr.hash == h) { Name currName = curr.name; if (currName.equals(firstQuad, secondQuad)) { return currName; } } } return null; }
/** * @see Name * @see Inequality * <p>Inverse of the Unifying Method, receives two WellFormedNames and tries to find a list of * Substitutions that will make both names syntatically different. * @param n1 - The first Name * @param n2 - The second Name * @return A list of substitutions (Inequalities) if the names can be made different, otherwise * returns null */ public static boolean Disunify(Name n1, Name n2, ArrayList<Substitution> bindings) { Name aux1; Name aux2; ArrayList<Substitution> bindAux; if (n1 == null || n2 == null) return false; // parto do principio que a lista de bindings está consistente aux1 = (Name) n1.clone(); aux2 = (Name) n2.clone(); aux1.makeGround(bindings); aux2.makeGround(bindings); if (aux1.isGrounded() && aux2.isGrounded()) { return !aux1.equals(aux2); } bindAux = FindSubst(aux1, aux2); if (bindAux != null) { for (Substitution s : bindAux) { bindings.add(new Inequality(s)); } } return true; }
/** * Determines if an RRset with the given name and type is already present in the given section. * * @see RRset * @see Section */ public boolean findRRset(Name name, int type, int section) { if (sections[section] == null) return false; for (int i = 0; i < sections[section].size(); i++) { Record r = (Record) sections[section].get(i); if (r.getType() == type && name.equals(r.getName())) return true; } return false; }
/** * Determines if two Records are identical. This compares the name, type, class, and rdata (with * names canonicalized). The TTLs are not compared. * * @param arg The record to compare to * @return true if the records are equal, false otherwise. */ public boolean equals(Object arg) { if (arg == null || !(arg instanceof Record)) return false; Record r = (Record) arg; if (type != r.type || dclass != r.dclass || !name.equals(r.name)) return false; byte[] array1 = rdataToWireCanonical(); byte[] array2 = r.rdataToWireCanonical(); return Arrays.equals(array1, array2); }
private final void maybeAddRecord(Record record) throws IOException { int rtype = record.getType(); Name name = record.getName(); if (rtype == Type.SOA && !name.equals(origin)) { throw new IOException("SOA owner " + name + " does not match zone origin " + origin); } if (name.subdomain(origin)) addRecord(record); }
/** Returns the contents of the Zone in master file format. */ public String toMasterFile() { Iterator zentries = data.entrySet().iterator(); StringBuffer sb = new StringBuffer(); nodeToString(sb, originNode); while (zentries.hasNext()) { Map.Entry entry = (Map.Entry) zentries.next(); if (!origin.equals(entry.getKey())) nodeToString(sb, entry.getValue()); } return sb.toString(); }
@Override public boolean equals(Object o) { if (o == this) return true; if (!(o instanceof Name)) return false; Name name = (Name) o; if (!_label.equals(name.getLabel())) return false; if (hasChild()) return name.hasChild() && _child.equals(name.getChild()); else return !name.hasChild(); }
private final void maybeAddRecord(Record record, Cache cache, Object source) throws IOException { int type = record.getType(); Name name = record.getName(); if (type == Type.SOA) { if (!name.equals(origin)) throw new IOException("SOA owner " + name + " does not match zone origin " + origin); else { setOrigin(origin); dclass = record.getDClass(); } } if (origin == null && type != Type.SOA) throw new IOException("non-SOA record seen at " + name + " with no origin set"); if (name.subdomain(origin)) addRecord(record); else if (cache != null) cache.addRecord(record, Credibility.GLUE, source); }
@Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Profile profile = (Profile) o; if (name != null ? !name.equals(profile.name) : profile.name != null) return false; if (email != null ? !email.equals(profile.email) : profile.email != null) return false; if (hexColor != null ? !hexColor.equals(profile.hexColor) : profile.hexColor != null) return false; if (avatar != null ? !avatar.equals(profile.avatar) : profile.avatar != null) return false; if (dateOfBirth != null ? !dateOfBirth.equals(profile.dateOfBirth) : profile.dateOfBirth != null) return false; return !(bio != null ? !bio.equals(profile.bio) : profile.bio != null); }
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; }
/** * Adds all data from a Message into the Cache. Each record is added with the appropriate * credibility, and negative answers are cached as such. * * @param in The Message to be added * @see Message */ public void addMessage(Message in) { boolean isAuth = in.getHeader().getFlag(Flags.AA); Name qname = in.getQuestion().getName(); Name curname = qname; short qtype = in.getQuestion().getType(); short qclass = in.getQuestion().getDClass(); byte cred; short rcode = in.getHeader().getRcode(); boolean haveAnswer = false; boolean completed = false; boolean restart = false; RRset[] answers, auth, addl; if (rcode != Rcode.NOERROR && rcode != Rcode.NXDOMAIN) return; if (secure) { Cache c = new Cache(dclass); c.addMessage(in); verifyRecords(c); return; } answers = in.getSectionRRsets(Section.ANSWER); for (int i = 0; i < answers.length; i++) { if (answers[i].getDClass() != qclass) continue; short type = answers[i].getType(); Name name = answers[i].getName(); cred = getCred(Section.ANSWER, isAuth); if (type == Type.CNAME && name.equals(curname)) { CNAMERecord cname; addRRset(answers[i], cred); cname = (CNAMERecord) answers[i].first(); curname = cname.getTarget(); restart = true; haveAnswer = true; } else if (type == Type.DNAME && curname.subdomain(name)) { DNAMERecord dname; addRRset(answers[i], cred); dname = (DNAMERecord) answers[i].first(); try { curname = curname.fromDNAME(dname); } catch (NameTooLongException e) { break; } restart = true; haveAnswer = true; } else if ((type == qtype || qtype == Type.ANY) && name.equals(curname)) { addRRset(answers[i], cred); completed = true; haveAnswer = true; } if (restart) { restart = false; i = 0; } } auth = in.getSectionRRsets(Section.AUTHORITY); if (!completed) { /* This is a negative response or a referral. */ RRset soa = null, ns = null; for (int i = 0; i < auth.length; i++) { if (auth[i].getType() == Type.SOA && curname.subdomain(auth[i].getName())) soa = auth[i]; else if (auth[i].getType() == Type.NS && curname.subdomain(auth[i].getName())) ns = auth[i]; } short cachetype = (rcode == Rcode.NXDOMAIN) ? (short) 0 : qtype; if (soa != null || ns == null) { /* Negative response */ cred = getCred(Section.AUTHORITY, isAuth); SOARecord soarec = null; if (soa != null) soarec = (SOARecord) soa.first(); addNegative(curname, cachetype, soarec, cred); /* NXT records are not cached yet. */ } else { /* Referral response */ cred = getCred(Section.AUTHORITY, isAuth); addRRset(ns, cred); } } addl = in.getSectionRRsets(Section.ADDITIONAL); for (int i = 0; i < addl.length; i++) { short type = addl[i].getType(); if (type != Type.A && type != Type.AAAA && type != Type.A6) continue; /* XXX check the name */ Name name = addl[i].getName(); cred = getCred(Section.ADDITIONAL, isAuth); addRRset(addl[i], cred); } }
/** * 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; }
/** * Determines if two Records could be part of the same RRset. This compares the name, type, and * class of the Records; the ttl and rdata are not compared. */ public boolean sameRRset(Record rec) { return (getRRsetType() == rec.getRRsetType() && dclass == rec.dclass && name.equals(rec.name)); }