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:
008: /**
009: * Next SECure name - this record contains the following name in an
010: * ordered list of names in the zone, and a set of types for which
011: * records exist for this name. The presence of this record in a response
012: * signifies a negative response from a DNSSEC-signed zone.
013: *
014: * This replaces the NXT record.
015: *
016: * @author Brian Wellington
017: * @author David Blacka
018: */
019:
020: public class NSECRecord extends Record {
021:
022: private Name next;
023: private int types[];
024:
025: NSECRecord() {
026: }
027:
028: Record getObject() {
029: return new NSECRecord();
030: }
031:
032: /**
033: * Creates an NSEC Record from the given data.
034: * @param next The following name in an ordered list of the zone
035: * @param types An array containing the types present.
036: */
037: public NSECRecord(Name name, int dclass, long ttl, Name next,
038: int[] types) {
039: super (name, Type.NSEC, dclass, ttl);
040: this .next = checkName("next", next);
041: for (int i = 0; i < types.length; i++) {
042: Type.check(types[i]);
043: }
044: this .types = new int[types.length];
045: System.arraycopy(types, 0, this .types, 0, types.length);
046: Arrays.sort(this .types);
047: }
048:
049: private int[] listToArray(List list) {
050: int size = list.size();
051: int[] array = new int[size];
052: for (int i = 0; i < size; i++) {
053: array[i] = ((Integer) list.get(i)).intValue();
054: }
055: return array;
056: }
057:
058: void rrFromWire(DNSInput in) throws IOException {
059: next = new Name(in);
060:
061: int lastbase = -1;
062: List list = new ArrayList();
063: while (in.remaining() > 0) {
064: if (in.remaining() < 2)
065: throw new WireParseException(
066: "invalid bitmap descriptor");
067: int mapbase = in.readU8();
068: if (mapbase < lastbase)
069: throw new WireParseException("invalid ordering");
070: int maplength = in.readU8();
071: if (maplength > in.remaining())
072: throw new WireParseException("invalid bitmap");
073: for (int i = 0; i < maplength; i++) {
074: int current = in.readU8();
075: if (current == 0)
076: continue;
077: for (int j = 0; j < 8; j++) {
078: if ((current & (1 << (7 - j))) == 0)
079: continue;
080: int typecode = mapbase * 256 + +i * 8 + j;
081: list.add(Mnemonic.toInteger(typecode));
082: }
083: }
084: }
085: types = listToArray(list);
086: }
087:
088: void rdataFromString(Tokenizer st, Name origin) throws IOException {
089: next = st.getName(origin);
090: List list = new ArrayList();
091: while (true) {
092: Tokenizer.Token t = st.get();
093: if (!t.isString())
094: break;
095: int typecode = Type.value(t.value);
096: if (typecode < 0) {
097: throw st.exception("Invalid type: " + t.value);
098: }
099: list.add(Mnemonic.toInteger(typecode));
100: }
101: st.unget();
102: types = listToArray(list);
103: Arrays.sort(types);
104: }
105:
106: /** Converts rdata to a String */
107: String rrToString() {
108: StringBuffer sb = new StringBuffer();
109: sb.append(next);
110: for (int i = 0; i < types.length; i++) {
111: sb.append(" ");
112: sb.append(Type.string(types[i]));
113: }
114: return sb.toString();
115: }
116:
117: /** Returns the next name */
118: public Name getNext() {
119: return next;
120: }
121:
122: /** Returns the set of types defined for this name */
123: public int[] getTypes() {
124: int[] array = new int[types.length];
125: System.arraycopy(types, 0, array, 0, types.length);
126: return array;
127: }
128:
129: /** Returns whether a specific type is in the set of types. */
130: public boolean hasType(int type) {
131: return (Arrays.binarySearch(types, type) >= 0);
132: }
133:
134: static void mapToWire(DNSOutput out, int[] array, int mapbase,
135: int mapstart, int mapend) {
136: int mapmax = array[mapend - 1] & 0xFF;
137: int maplength = (mapmax / 8) + 1;
138: int[] map = new int[maplength];
139: out.writeU8(mapbase);
140: out.writeU8(maplength);
141: for (int j = mapstart; j < mapend; j++) {
142: int typecode = array[j];
143: map[(typecode & 0xFF) / 8] |= (1 << (7 - typecode % 8));
144: }
145: for (int j = 0; j < maplength; j++) {
146: out.writeU8(map[j]);
147: }
148: }
149:
150: void rrToWire(DNSOutput out, Compression c, boolean canonical) {
151: next.toWire(out, null, canonical);
152:
153: if (types.length == 0)
154: return;
155: int mapbase = -1;
156: int mapstart = -1;
157: for (int i = 0; i < types.length; i++) {
158: int base = types[i] >> 8;
159: if (base == mapbase)
160: continue;
161: if (mapstart >= 0) {
162: mapToWire(out, types, mapbase, mapstart, i);
163: }
164: mapbase = base;
165: mapstart = i;
166: }
167: mapToWire(out, types, mapbase, mapstart, types.length);
168: }
169:
170: }
|