blob: b279666e1b180009a8bc4ea9a364b905e60f2d40 [file] [log] [blame]
/*
* Copyright (c) 2000, 2002, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.jndi.dns;
import javax.naming.*;
/**
* The Header class represents the header of a DNS message.
*
* @author Scott Seligman
*/
class Header {
static final int HEADER_SIZE = 12; // octets in a DNS header
// Masks and shift amounts for DNS header flag fields.
static final short QR_BIT = (short) 0x8000;
static final short OPCODE_MASK = (short) 0x7800;
static final int OPCODE_SHIFT = 11;
static final short AA_BIT = (short) 0x0400;
static final short TC_BIT = (short) 0x0200;
static final short RD_BIT = (short) 0x0100;
static final short RA_BIT = (short) 0x0080;
static final short RCODE_MASK = (short) 0x000F;
int xid; // ID: 16-bit query identifier
boolean query; // QR: true if query, false if response
int opcode; // OPCODE: 4-bit opcode
boolean authoritative; // AA
boolean truncated; // TC
boolean recursionDesired; // RD
boolean recursionAvail; // RA
int rcode; // RCODE: 4-bit response code
int numQuestions;
int numAnswers;
int numAuthorities;
int numAdditionals;
/*
* Returns a representation of a decoded DNS message header.
* Does not modify or store a reference to the msg array.
*/
Header(byte[] msg, int msgLen) throws NamingException {
decode(msg, msgLen);
}
/*
* Decodes a DNS message header. Does not modify or store a
* reference to the msg array.
*/
private void decode(byte[] msg, int msgLen) throws NamingException {
try {
int pos = 0; // current offset into msg
if (msgLen < HEADER_SIZE) {
throw new CommunicationException(
"DNS error: corrupted message header");
}
xid = getShort(msg, pos);
pos += 2;
// Flags
short flags = (short) getShort(msg, pos);
pos += 2;
query = (flags & QR_BIT) == 0;
opcode = (flags & OPCODE_MASK) >>> OPCODE_SHIFT;
authoritative = (flags & AA_BIT) != 0;
truncated = (flags & TC_BIT) != 0;
recursionDesired = (flags & RD_BIT) != 0;
recursionAvail = (flags & RA_BIT) != 0;
rcode = (flags & RCODE_MASK);
// RR counts
numQuestions = getShort(msg, pos);
pos += 2;
numAnswers = getShort(msg, pos);
pos += 2;
numAuthorities = getShort(msg, pos);
pos += 2;
numAdditionals = getShort(msg, pos);
pos += 2;
} catch (IndexOutOfBoundsException e) {
throw new CommunicationException(
"DNS error: corrupted message header");
}
}
/*
* Returns the 2-byte unsigned value at msg[pos]. The high
* order byte comes first.
*/
private static int getShort(byte[] msg, int pos) {
return (((msg[pos] & 0xFF) << 8) |
(msg[pos + 1] & 0xFF));
}
}