001: // Copyright (c) 1999-2004 Brian Wellington (bwelling@xbill.org)
002:
003: package org.xbill.DNS;
004:
005: import java.io.*;
006: import java.util.*;
007: import org.xbill.DNS.utils.*;
008:
009: /**
010: * Options - describes Extended DNS (EDNS) properties of a Message.
011: * No specific options are defined other than those specified in the
012: * header. An OPT should be generated by Resolver.
013: *
014: * EDNS is a method to extend the DNS protocol while providing backwards
015: * compatibility and not significantly changing the protocol. This
016: * implementation of EDNS is mostly complete at level 0.
017: *
018: * @see Message
019: * @see Resolver
020: *
021: * @author Brian Wellington
022: */
023:
024: public class OPTRecord extends Record {
025:
026: public static class Option {
027: public final int code;
028: public final byte[] data;
029:
030: /**
031: * Creates an option with the given option code and data.
032: */
033: public Option(int code, byte[] data) {
034: this .code = checkU8("option code", code);
035: this .data = data;
036: }
037:
038: public String toString() {
039: return "{" + code + " <" + base16.toString(data) + ">}";
040: }
041: }
042:
043: private List options;
044:
045: OPTRecord() {
046: }
047:
048: Record getObject() {
049: return new OPTRecord();
050: }
051:
052: /**
053: * Creates an OPT Record. This is normally called by SimpleResolver, but can
054: * also be called by a server.
055: * @param payloadSize The size of a packet that can be reassembled on the
056: * sending host.
057: * @param xrcode The value of the extended rcode field. This is the upper
058: * 16 bits of the full rcode.
059: * @param flags Additional message flags.
060: * @param version The EDNS version that this DNS implementation supports.
061: * This should be 0 for dnsjava.
062: * @param options The list of options that comprise the data field. There
063: * are currently no defined options.
064: * @see ExtendedFlags
065: */
066: public OPTRecord(int payloadSize, int xrcode, int version,
067: int flags, List options) {
068: super (Name.root, Type.OPT, payloadSize, 0);
069: checkU16("payloadSize", payloadSize);
070: checkU8("xrcode", xrcode);
071: checkU8("version", version);
072: checkU16("flags", flags);
073: ttl = ((long) xrcode << 24) + ((long) version << 16) + flags;
074: if (options != null) {
075: this .options = new ArrayList(options);
076: }
077: }
078:
079: /**
080: * Creates an OPT Record with no data. This is normally called by
081: * SimpleResolver, but can also be called by a server.
082: * @param payloadSize The size of a packet that can be reassembled on the
083: * sending host.
084: * @param xrcode The value of the extended rcode field. This is the upper
085: * 16 bits of the full rcode.
086: * @param flags Additional message flags.
087: * @param version The EDNS version that this DNS implementation supports.
088: * This should be 0 for dnsjava.
089: * @see ExtendedFlags
090: */
091: public OPTRecord(int payloadSize, int xrcode, int version, int flags) {
092: this (payloadSize, xrcode, version, flags, null);
093: }
094:
095: /**
096: * Creates an OPT Record with no data. This is normally called by
097: * SimpleResolver, but can also be called by a server.
098: */
099: public OPTRecord(int payloadSize, int xrcode, int version) {
100: this (payloadSize, xrcode, version, 0, null);
101: }
102:
103: void rrFromWire(DNSInput in) throws IOException {
104: if (in.remaining() > 0)
105: options = new ArrayList();
106: while (in.remaining() > 0) {
107: int code = in.readU16();
108: int len = in.readU16();
109: byte[] data = in.readByteArray(len);
110: options.add(new Option(code, data));
111: }
112: }
113:
114: void rdataFromString(Tokenizer st, Name origin) throws IOException {
115: throw st.exception("no text format defined for OPT");
116: }
117:
118: /** Converts rdata to a String */
119: String rrToString() {
120: StringBuffer sb = new StringBuffer();
121: if (options != null) {
122: sb.append(options);
123: sb.append(" ");
124: }
125: sb.append(" ; payload ");
126: sb.append(getPayloadSize());
127: sb.append(", xrcode ");
128: sb.append(getExtendedRcode());
129: sb.append(", version ");
130: sb.append(getVersion());
131: sb.append(", flags ");
132: sb.append(getFlags());
133: return sb.toString();
134: }
135:
136: /** Returns the maximum allowed payload size. */
137: public int getPayloadSize() {
138: return dclass;
139: }
140:
141: /**
142: * Returns the extended Rcode
143: * @see Rcode
144: */
145: public int getExtendedRcode() {
146: return (int) (ttl >>> 24);
147: }
148:
149: /** Returns the highest supported EDNS version */
150: public int getVersion() {
151: return (int) ((ttl >>> 16) & 0xFF);
152: }
153:
154: /** Returns the EDNS flags */
155: public int getFlags() {
156: return (int) (ttl & 0xFFFF);
157: }
158:
159: void rrToWire(DNSOutput out, Compression c, boolean canonical) {
160: if (options == null)
161: return;
162: Iterator it = options.iterator();
163: while (it.hasNext()) {
164: Option opt = (Option) it.next();
165: out.writeU16(opt.code);
166: out.writeU16(opt.data.length);
167: out.writeByteArray(opt.data);
168: }
169: }
170:
171: /**
172: * Gets all options in the OPTRecord. This returns a list of Options.
173: */
174: public List getOptions() {
175: if (options == null)
176: return Collections.EMPTY_LIST;
177: return Collections.unmodifiableList(options);
178: }
179:
180: /**
181: * Gets all options in the OPTRecord with a specific code. This returns a
182: * list of byte arrays.
183: */
184: public List getOptions(int code) {
185: if (options == null)
186: return Collections.EMPTY_LIST;
187: List list = null;
188: for (Iterator it = options.iterator(); it.hasNext();) {
189: Option opt = (Option) it.next();
190: if (opt.code == code) {
191: if (list == null)
192: list = new ArrayList();
193: list.add(opt.data);
194: }
195: }
196: if (list == null)
197: return Collections.EMPTY_LIST;
198: return list;
199: }
200:
201: }
|