001: /* VirtualDNS - A modular DNS server.
002: * Copyright (C) 2000 Eric Kidd
003: * Copyright (C) 1999 Brian Wellington
004: *
005: * This library is free software; you can redistribute it and/or
006: * modify it under the terms of the GNU Lesser General Public
007: * License as published by the Free Software Foundation; either
008: * version 2.1 of the License, or (at your option) any later version.
009: *
010: * This library is distributed in the hope that it will be useful,
011: * but WITHOUT ANY WARRANTY; without even the implied warranty of
012: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
013: * Lesser General Public License for more details.
014: *
015: * You should have received a copy of the GNU Lesser General Public
016: * License along with this library; if not, write to the Free Software
017: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
018: */
019:
020: package CustomDNS.VirtualDNS;
021:
022: import java.io.*;
023: import java.util.*;
024: import org.xbill.DNS.*;
025:
026: /*************************************************************************
027: * A subclass of DNS.Message with extra methods for building responses.
028: *************************************************************************
029: * Much of this code was adapted from Brian Wellington's jnamed code.
030: * @see org.xbill.DNS.Message
031: */
032:
033: public class Response extends Message {
034:
035: /** Create a new Response object. */
036: public Response() {
037: super ();
038: }
039:
040: /*********************************************************************
041: * Figure out how large this response will be when we send it.
042: *********************************************************************
043: * Calling this function is fairly expensive.
044: * @return The size of this response packet, in bytes.
045: */
046: public int wireLength() throws IOException {
047: byte[] out = this .toWire();
048: return out.length;
049: }
050:
051: /*********************************************************************
052: * Truncate the response to fit within the available packet size.
053: *********************************************************************
054: * This function was adapted from Brian Wellington's jnamed code.
055: *
056: * XXX - It's not actually clear that we always produce a small
057: * enough packet. This should be investigated.
058: *
059: * @param maxLength Maximum permissible packet size.
060: */
061: public void truncate(int maxLength) throws IOException {
062:
063: // Calculate the current length.
064: int length = this .wireLength();
065:
066: // Reserve space for our signature records. This is leftover code
067: // somehow related to Secure DNS support.
068: //TSIGRecord tsig = this.getTSIG();
069: //if (tsig != null)
070: // maxLength -= tsig.getWireLength();
071:
072: // Try throwing out the data in the ADDITIONAL section first.
073: length -= truncateSection(maxLength, length, Section.ADDITIONAL);
074: if (length < maxLength)
075: return;
076:
077: // Mark the response as truncated. Presumably everything from
078: // here onwards involves throwing out important data.
079: this .getHeader().setFlag(Flags.TC);
080:
081: // More signature-related code.
082: //if (tsig != null) {
083: // this.removeAllRecords(Section.ANSWER);
084: // this.removeAllRecords(Section.AUTHORITY);
085: // return;
086: //}
087:
088: // Chop information out of the AUTHORIY and ANSWER sections.
089: length -= truncateSection(maxLength, length, Section.AUTHORITY);
090: if (length < maxLength)
091: return;
092: length -= truncateSection(maxLength, length, Section.ANSWER);
093: }
094:
095: // Try to make a section fit.
096: // This function was adapted from Brian Wellington's jnamed code, and
097: // I haven't looked at it yet.
098: private int truncateSection(int maxLength, int length, int section) {
099: int removed = 0;
100: Record[] records = this .getSectionArray(section);
101: for (int i = records.length - 1; i >= 0; i--) {
102: Record r = records[i];
103: removed += r.getWireLength();
104: length -= r.getWireLength();
105: this .removeRecord(r, section);
106: if (length > maxLength)
107: continue;
108: else {
109: for (int j = i - 1; j >= 0; j--) {
110: Record r2 = records[j];
111: if (!r.getName().equals(r2.getName())
112: || r.getType() != r2.getType()
113: || r.getDClass() != r2.getDClass())
114: break;
115: removed += r2.getWireLength();
116: length -= r2.getWireLength();
117: this .removeRecord(r2, section);
118: }
119: return removed;
120: }
121: }
122: return removed;
123: }
124:
125: /*********************************************************************
126: * Add the answer records for a given name, expanding any wildcards.
127: *********************************************************************
128: * If a name matches any wildcard records, we need to replace the
129: * wildcard with the actual name before returning the records.
130: *
131: * This function was adapted from Brian Wellington's jnamed code.
132: * All the signature-related code was removed. We're probably not
133: * seeing any wildcard matches in our current application.
134: *
135: * @param name The DNS name associated with these records.
136: * @param rrset A list of answer records.
137: */
138: public void addRRset(Name name, RRset rrset) {
139: Enumeration e;
140: e = rrset.rrs();
141: while (e.hasMoreElements()) {
142: Record r = (Record) e.nextElement();
143: if (!name.isWild() && r.getName().isWild())
144: r = r.withName(name);
145: this.addRecord(r, Section.ANSWER);
146: }
147: }
148: }
|