diff options
Diffstat (limited to 'src/org/xbill/DNS/Header.java')
-rw-r--r-- | src/org/xbill/DNS/Header.java | 286 |
1 files changed, 286 insertions, 0 deletions
diff --git a/src/org/xbill/DNS/Header.java b/src/org/xbill/DNS/Header.java new file mode 100644 index 0000000..2a44d08 --- /dev/null +++ b/src/org/xbill/DNS/Header.java @@ -0,0 +1,286 @@ +// Copyright (c) 1999-2004 Brian Wellington (bwelling@xbill.org) + +package org.xbill.DNS; + +import java.io.*; +import java.util.*; + +/** + * A DNS message header + * @see Message + * + * @author Brian Wellington + */ + +public class Header implements Cloneable { + +private int id; +private int flags; +private int [] counts; + +private static Random random = new Random(); + +/** The length of a DNS Header in wire format. */ +public static final int LENGTH = 12; + +private void +init() { + counts = new int[4]; + flags = 0; + id = -1; +} + +/** + * Create a new empty header. + * @param id The message id + */ +public +Header(int id) { + init(); + setID(id); +} + +/** + * Create a new empty header with a random message id + */ +public +Header() { + init(); +} + +/** + * Parses a Header from a stream containing DNS wire format. + */ +Header(DNSInput in) throws IOException { + this(in.readU16()); + flags = in.readU16(); + for (int i = 0; i < counts.length; i++) + counts[i] = in.readU16(); +} + +/** + * Creates a new Header from its DNS wire format representation + * @param b A byte array containing the DNS Header. + */ +public +Header(byte [] b) throws IOException { + this(new DNSInput(b)); +} + +void +toWire(DNSOutput out) { + out.writeU16(getID()); + out.writeU16(flags); + for (int i = 0; i < counts.length; i++) + out.writeU16(counts[i]); +} + +public byte [] +toWire() { + DNSOutput out = new DNSOutput(); + toWire(out); + return out.toByteArray(); +} + +static private boolean +validFlag(int bit) { + return (bit >= 0 && bit <= 0xF && Flags.isFlag(bit)); +} + +static private void +checkFlag(int bit) { + if (!validFlag(bit)) + throw new IllegalArgumentException("invalid flag bit " + bit); +} + +/** + * Sets a flag to the supplied value + * @see Flags + */ +public void +setFlag(int bit) { + checkFlag(bit); + // bits are indexed from left to right + flags |= (1 << (15 - bit)); +} + +/** + * Sets a flag to the supplied value + * @see Flags + */ +public void +unsetFlag(int bit) { + checkFlag(bit); + // bits are indexed from left to right + flags &= ~(1 << (15 - bit)); +} + +/** + * Retrieves a flag + * @see Flags + */ +public boolean +getFlag(int bit) { + checkFlag(bit); + // bits are indexed from left to right + return (flags & (1 << (15 - bit))) != 0; +} + +boolean [] +getFlags() { + boolean [] array = new boolean[16]; + for (int i = 0; i < array.length; i++) + if (validFlag(i)) + array[i] = getFlag(i); + return array; +} + +/** + * Retrieves the message ID + */ +public int +getID() { + if (id >= 0) + return id; + synchronized (this) { + if (id < 0) + id = random.nextInt(0xffff); + return id; + } +} + +/** + * Sets the message ID + */ +public void +setID(int id) { + if (id < 0 || id > 0xffff) + throw new IllegalArgumentException("DNS message ID " + id + + " is out of range"); + this.id = id; +} + +/** + * Sets the message's rcode + * @see Rcode + */ +public void +setRcode(int value) { + if (value < 0 || value > 0xF) + throw new IllegalArgumentException("DNS Rcode " + value + + " is out of range"); + flags &= ~0xF; + flags |= value; +} + +/** + * Retrieves the mesasge's rcode + * @see Rcode + */ +public int +getRcode() { + return flags & 0xF; +} + +/** + * Sets the message's opcode + * @see Opcode + */ +public void +setOpcode(int value) { + if (value < 0 || value > 0xF) + throw new IllegalArgumentException("DNS Opcode " + value + + "is out of range"); + flags &= 0x87FF; + flags |= (value << 11); +} + +/** + * Retrieves the mesasge's opcode + * @see Opcode + */ +public int +getOpcode() { + return (flags >> 11) & 0xF; +} + +void +setCount(int field, int value) { + if (value < 0 || value > 0xFFFF) + throw new IllegalArgumentException("DNS section count " + + value + " is out of range"); + counts[field] = value; +} + +void +incCount(int field) { + if (counts[field] == 0xFFFF) + throw new IllegalStateException("DNS section count cannot " + + "be incremented"); + counts[field]++; +} + +void +decCount(int field) { + if (counts[field] == 0) + throw new IllegalStateException("DNS section count cannot " + + "be decremented"); + counts[field]--; +} + +/** + * Retrieves the record count for the given section + * @see Section + */ +public int +getCount(int field) { + return counts[field]; +} + +/** Converts the header's flags into a String */ +public String +printFlags() { + StringBuffer sb = new StringBuffer(); + + for (int i = 0; i < 16; i++) + if (validFlag(i) && getFlag(i)) { + sb.append(Flags.string(i)); + sb.append(" "); + } + return sb.toString(); +} + +String +toStringWithRcode(int newrcode) { + StringBuffer sb = new StringBuffer(); + + sb.append(";; ->>HEADER<<- "); + sb.append("opcode: " + Opcode.string(getOpcode())); + sb.append(", status: " + Rcode.string(newrcode)); + sb.append(", id: " + getID()); + sb.append("\n"); + + sb.append(";; flags: " + printFlags()); + sb.append("; "); + for (int i = 0; i < 4; i++) + sb.append(Section.string(i) + ": " + getCount(i) + " "); + return sb.toString(); +} + +/** Converts the header into a String */ +public String +toString() { + return toStringWithRcode(getRcode()); +} + +/* Creates a new Header identical to the current one */ +public Object +clone() { + Header h = new Header(); + h.id = id; + h.flags = flags; + System.arraycopy(counts, 0, h.counts, 0, counts.length); + return h; +} + +} |