📄 record.java
字号:
// Copyright (c) 1999-2004 Brian Wellington (bwelling@xbill.org)package org.xbill.DNS;import java.io.*;import java.text.*;import java.lang.reflect.*;import java.util.*;import org.xbill.DNS.utils.*;/** * A generic DNS resource record. The specific record types extend this class. * A record contains a name, type, class, and rdata. * * @author Brian Wellington */public abstract class Record implements Cloneable, Comparable {protected Name name;protected int type, dclass;protected long ttl;private static final Record [] knownRecords = new Record[256];private static final Record unknownRecord = new UNKRecord();private static final Class [] emptyClassArray = new Class[0];private static final Object [] emptyObjectArray = new Object[0];private static final DecimalFormat byteFormat = new DecimalFormat();static { byteFormat.setMinimumIntegerDigits(3);}protectedRecord() {}Record(Name name, int type, int dclass, long ttl) { if (!name.isAbsolute()) throw new RelativeNameException(name); Type.check(type); DClass.check(dclass); TTL.check(ttl); this.name = name; this.type = type; this.dclass = dclass; this.ttl = ttl;}/** * Creates an empty record of the correct type; must be overriden */abstract RecordgetObject();private static final RecordgetTypedObject(int type) { if (type < 0 || type > knownRecords.length) return unknownRecord.getObject(); if (knownRecords[type] != null) return knownRecords[type]; /* Construct the class name by putting the type before "Record". */ String s = Record.class.getPackage().getName() + "." + Type.string(type).replace('-', '_') + "Record"; try { Class c = Class.forName(s); Constructor m = c.getDeclaredConstructor(emptyClassArray); knownRecords[type] = (Record) m.newInstance(emptyObjectArray); } catch (ClassNotFoundException e) { /* This is normal; do nothing */ } catch (Exception e) { if (Options.check("verbose")) System.err.println(e); } if (knownRecords[type] == null) knownRecords[type] = unknownRecord.getObject(); return knownRecords[type];}private static final RecordgetEmptyRecord(Name name, int type, int dclass, long ttl, boolean hasData) { Record rec; if (hasData) rec = getTypedObject(type).getObject(); else rec = new EmptyRecord(); rec.name = name; rec.type = type; rec.dclass = dclass; rec.ttl = ttl; return rec;}/** * Converts the type-specific RR to wire format - must be overriden */abstract voidrrFromWire(DNSInput in) throws IOException;private static RecordnewRecord(Name name, int type, int dclass, long ttl, int length, DNSInput in)throws IOException{ Record rec; int recstart; rec = getEmptyRecord(name, type, dclass, ttl, in != null); if (in != null) { if (in.remaining() < length) throw new WireParseException("truncated record"); in.setActive(length); rec.rrFromWire(in); if (in.remaining() > 0) throw new WireParseException("invalid record length"); in.clearActive(); } return rec;}/** * Creates a new record, with the given parameters. * @param name The owner name of the record. * @param type The record's type. * @param dclass The record's class. * @param ttl The record's time to live. * @param length The length of the record's data. * @param data The rdata of the record, in uncompressed DNS wire format. Only * the first length bytes are used. */public static RecordnewRecord(Name name, int type, int dclass, long ttl, int length, byte [] data) { if (!name.isAbsolute()) throw new RelativeNameException(name); Type.check(type); DClass.check(dclass); TTL.check(ttl); DNSInput in; if (data != null) in = new DNSInput(data); else in = null; try { return newRecord(name, type, dclass, ttl, length, in); } catch (IOException e) { return null; }}/** * Creates a new record, with the given parameters. * @param name The owner name of the record. * @param type The record's type. * @param dclass The record's class. * @param ttl The record's time to live. * @param data The complete rdata of the record, in uncompressed DNS wire * format. */public static RecordnewRecord(Name name, int type, int dclass, long ttl, byte [] data) { return newRecord(name, type, dclass, ttl, data.length, data);}/** * Creates a new empty record, with the given parameters. * @param name The owner name of the record. * @param type The record's type. * @param dclass The record's class. * @param ttl The record's time to live. * @return An object of a subclass of Record */public static RecordnewRecord(Name name, int type, int dclass, long ttl) { if (!name.isAbsolute()) throw new RelativeNameException(name); Type.check(type); DClass.check(dclass); TTL.check(ttl); return getEmptyRecord(name, type, dclass, ttl, false);}/** * Creates a new empty record, with the given parameters. This method is * designed to create records that will be added to the QUERY section * of a message. * @param name The owner name of the record. * @param type The record's type. * @param dclass The record's class. * @return An object of a subclass of Record */public static RecordnewRecord(Name name, int type, int dclass) { return newRecord(name, type, dclass, 0);}static RecordfromWire(DNSInput in, int section, boolean isUpdate) throws IOException { int type, dclass; long ttl; int length; Name name; Record rec; name = new Name(in); type = in.readU16(); dclass = in.readU16(); if (section == Section.QUESTION) return newRecord(name, type, dclass); ttl = in.readU32(); length = in.readU16(); if (length == 0 && isUpdate) return newRecord(name, type, dclass, ttl); rec = newRecord(name, type, dclass, ttl, length, in); return rec;}static RecordfromWire(DNSInput in, int section) throws IOException { return fromWire(in, section, false);}/** * Builds a Record from DNS uncompressed wire format. */public static RecordfromWire(byte [] b, int section) throws IOException { return fromWire(new DNSInput(b), section, false);}voidtoWire(DNSOutput out, int section, Compression c) { name.toWire(out, c); out.writeU16(type); out.writeU16(dclass); if (section == Section.QUESTION) return; out.writeU32(ttl); int lengthPosition = out.current(); out.writeU16(0); /* until we know better */ rrToWire(out, c, false); int rrlength = out.current() - lengthPosition - 2; out.save(); out.jump(lengthPosition); out.writeU16(rrlength); out.restore();}/** * Converts a Record into DNS uncompressed wire format. */public byte []toWire(int section) { DNSOutput out = new DNSOutput(); toWire(out, section, null); return out.toByteArray();}private voidtoWireCanonical(DNSOutput out, boolean noTTL) { name.toWireCanonical(out); out.writeU16(type); out.writeU16(dclass); if (noTTL) { out.writeU32(0); } else { out.writeU32(ttl); } int lengthPosition = out.current(); out.writeU16(0); /* until we know better */ rrToWire(out, null, true); int rrlength = out.current() - lengthPosition - 2; out.save(); out.jump(lengthPosition); out.writeU16(rrlength); out.restore();}/* * Converts a Record into canonical DNS uncompressed wire format (all names are * converted to lowercase), optionally ignoring the TTL. */private byte []toWireCanonical(boolean noTTL) { DNSOutput out = new DNSOutput(); toWireCanonical(out, noTTL); return out.toByteArray();}/** * Converts a Record into canonical DNS uncompressed wire format (all names are * converted to lowercase). */public byte []toWireCanonical() { return toWireCanonical(false);}/** * Converts the rdata in a Record into canonical DNS uncompressed wire format * (all names are converted to lowercase). */public byte []rdataToWireCanonical() { DNSOutput out = new DNSOutput(); rrToWire(out, null, true); return out.toByteArray();}/** * Converts the type-specific RR to text format - must be overriden */abstract String rrToString();/** * Converts the rdata portion of a Record into a String representation */public StringrdataToString() { return rrToString();}/** * Converts a Record into a String representation */public StringtoString() { StringBuffer sb = new StringBuffer(); sb.append(name); if (sb.length() < 8) sb.append("\t"); if (sb.length() < 16) sb.append("\t"); sb.append("\t"); if (Options.check("BINDTTL")) sb.append(TTL.format(ttl)); else sb.append(ttl); sb.append("\t"); if (dclass != DClass.IN || !Options.check("noPrintIN")) { sb.append(DClass.string(dclass)); sb.append("\t"); } sb.append(Type.string(type)); String rdata = rrToString(); if (!rdata.equals("")) { sb.append("\t"); sb.append(rdata); } return sb.toString();}/** * Converts the text format of an RR to the internal format - must be overriden */abstract voidrdataFromString(Tokenizer st, Name origin) throws IOException;/** * Converts a String into a byte array. */protected static byte []byteArrayFromString(String s) throws TextParseException { byte [] array = s.getBytes(); boolean escaped = false; boolean hasEscapes = false; for (int i = 0; i < array.length; i++) { if (array[i] == '\\') { hasEscapes = true; break; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -