Home | History | Annotate | Download | only in DNS
      1 // Copyright (c) 1999-2004 Brian Wellington (bwelling (at) xbill.org)
      2 package org.xbill.DNS;
      3 
      4 import java.io.*;
      5 import java.util.Arrays;
      6 
      7 /**
      8  * DNS extension options, as described in RFC 2671.  The rdata of an OPT record
      9  * is defined as a list of options; this represents a single option.
     10  *
     11  * @author Brian Wellington
     12  * @author Ming Zhou <mizhou (at) bnivideo.com>, Beaumaris Networks
     13  */
     14 public abstract class EDNSOption {
     15 
     16 public static class Code {
     17 	private Code() {}
     18 
     19 	/** Name Server Identifier, RFC 5001 */
     20 	public final static int NSID = 3;
     21 
     22 	/** Client Subnet, defined in draft-vandergaast-edns-client-subnet-00 */
     23 	public final static int CLIENT_SUBNET = 20730;
     24 
     25 	private static Mnemonic codes = new Mnemonic("EDNS Option Codes",
     26 						     Mnemonic.CASE_UPPER);
     27 
     28 	static {
     29 		codes.setMaximum(0xFFFF);
     30 		codes.setPrefix("CODE");
     31 		codes.setNumericAllowed(true);
     32 
     33 		codes.add(NSID, "NSID");
     34 		codes.add(CLIENT_SUBNET, "CLIENT_SUBNET");
     35 	}
     36 
     37 	/**
     38 	 * Converts an EDNS Option Code into its textual representation
     39 	 */
     40 	public static String
     41 	string(int code) {
     42 		return codes.getText(code);
     43 	}
     44 
     45 	/**
     46 	 * Converts a textual representation of an EDNS Option Code into its
     47 	 * numeric value.
     48 	 * @param s The textual representation of the option code
     49 	 * @return The option code, or -1 on error.
     50 	 */
     51 	public static int
     52 	value(String s) {
     53 		return codes.getValue(s);
     54 	}
     55 }
     56 
     57 private final int code;
     58 
     59 /**
     60  *
     61  * Creates an option with the given option code and data.
     62  */
     63 public
     64 EDNSOption(int code) {
     65 	this.code = Record.checkU16("code", code);
     66 }
     67 
     68 public String
     69 toString() {
     70 	StringBuffer sb = new StringBuffer();
     71 
     72 	sb.append("{");
     73 	sb.append(EDNSOption.Code.string(code));
     74 	sb.append(": ");
     75 	sb.append(optionToString());
     76 	sb.append("}");
     77 
     78 	return sb.toString();
     79 }
     80 
     81 /**
     82  * Returns the EDNS Option's code.
     83  *
     84  * @return the option code
     85  */
     86 public int
     87 getCode() {
     88 	return code;
     89 }
     90 
     91 /**
     92  * Returns the EDNS Option's data, as a byte array.
     93  *
     94  * @return the option data
     95  */
     96 byte []
     97 getData() {
     98 	DNSOutput out = new DNSOutput();
     99 	optionToWire(out);
    100 	return out.toByteArray();
    101 }
    102 
    103 /**
    104  * Converts the wire format of an EDNS Option (the option data only) into the
    105  * type-specific format.
    106  * @param in The input Stream.
    107  */
    108 abstract void
    109 optionFromWire(DNSInput in) throws IOException;
    110 
    111 /**
    112  * Converts the wire format of an EDNS Option (including code and length) into
    113  * the type-specific format.
    114  * @param out The input stream.
    115  */
    116 static EDNSOption
    117 fromWire(DNSInput in) throws IOException {
    118 	int code, length;
    119 
    120 	code = in.readU16();
    121 	length = in.readU16();
    122 	if (in.remaining() < length)
    123 		throw new WireParseException("truncated option");
    124 	int save = in.saveActive();
    125 	in.setActive(length);
    126 	EDNSOption option;
    127 	switch (code) {
    128 	case Code.NSID:
    129 		option = new NSIDOption();
    130 		break;
    131 	case Code.CLIENT_SUBNET:
    132 		option = new ClientSubnetOption();
    133 		break;
    134 	default:
    135 		option = new GenericEDNSOption(code);
    136 		break;
    137 	}
    138 	option.optionFromWire(in);
    139 	in.restoreActive(save);
    140 
    141 	return option;
    142 }
    143 
    144 /**
    145  * Converts the wire format of an EDNS Option (including code and length) into
    146  * the type-specific format.
    147  * @return The option, in wire format.
    148  */
    149 public static EDNSOption
    150 fromWire(byte [] b) throws IOException {
    151 	return fromWire(new DNSInput(b));
    152 }
    153 
    154 /**
    155  * Converts an EDNS Option (the type-specific option data only) into wire format.
    156  * @param out The output stream.
    157  */
    158 abstract void
    159 optionToWire(DNSOutput out);
    160 
    161 /**
    162  * Converts an EDNS Option (including code and length) into wire format.
    163  * @param out The output stream.
    164  */
    165 void
    166 toWire(DNSOutput out) {
    167 	out.writeU16(code);
    168 	int lengthPosition = out.current();
    169 	out.writeU16(0); /* until we know better */
    170 	optionToWire(out);
    171 	int length = out.current() - lengthPosition - 2;
    172 	out.writeU16At(length, lengthPosition);
    173 }
    174 
    175 /**
    176  * Converts an EDNS Option (including code and length) into wire format.
    177  * @return The option, in wire format.
    178  */
    179 public byte []
    180 toWire() throws IOException {
    181 	DNSOutput out = new DNSOutput();
    182 	toWire(out);
    183 	return out.toByteArray();
    184 }
    185 
    186 /**
    187  * Determines if two EDNS Options are identical.
    188  * @param arg The option to compare to
    189  * @return true if the options are equal, false otherwise.
    190  */
    191 public boolean
    192 equals(Object arg) {
    193 	if (arg == null || !(arg instanceof EDNSOption))
    194 		return false;
    195 	EDNSOption opt = (EDNSOption) arg;
    196 	if (code != opt.code)
    197 		return false;
    198 	return Arrays.equals(getData(), opt.getData());
    199 }
    200 
    201 /**
    202  * Generates a hash code based on the EDNS Option's data.
    203  */
    204 public int
    205 hashCode() {
    206 	byte [] array = getData();
    207 	int hashval = 0;
    208 	for (int i = 0; i < array.length; i++)
    209 		hashval += ((hashval << 3) + (array[i] & 0xFF));
    210 	return hashval;
    211 }
    212 
    213 abstract String optionToString();
    214 
    215 }
    216