1 /* 2 * Copyright (c) 2000, 2002, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package com.sun.jndi.dns; 27 28 29 import javax.naming.*; 30 31 32 /** 33 * The Header class represents the header of a DNS message. 34 * 35 * @author Scott Seligman 36 */ 37 38 39 class Header { 40 41 static final int HEADER_SIZE = 12; // octets in a DNS header 42 43 // Masks and shift amounts for DNS header flag fields. 44 static final short QR_BIT = (short) 0x8000; 45 static final short OPCODE_MASK = (short) 0x7800; 46 static final int OPCODE_SHIFT = 11; 47 static final short AA_BIT = (short) 0x0400; 48 static final short TC_BIT = (short) 0x0200; 49 static final short RD_BIT = (short) 0x0100; 50 static final short RA_BIT = (short) 0x0080; 51 static final short RCODE_MASK = (short) 0x000F; 52 53 int xid; // ID: 16-bit query identifier 54 boolean query; // QR: true if query, false if response 55 int opcode; // OPCODE: 4-bit opcode 56 boolean authoritative; // AA 57 boolean truncated; // TC 58 boolean recursionDesired; // RD 59 boolean recursionAvail; // RA 60 int rcode; // RCODE: 4-bit response code 61 int numQuestions; 62 int numAnswers; 63 int numAuthorities; 64 int numAdditionals; 65 66 /* 67 * Returns a representation of a decoded DNS message header. 68 * Does not modify or store a reference to the msg array. 69 */ Header(byte[] msg, int msgLen)70 Header(byte[] msg, int msgLen) throws NamingException { 71 decode(msg, msgLen); 72 } 73 74 /* 75 * Decodes a DNS message header. Does not modify or store a 76 * reference to the msg array. 77 */ decode(byte[] msg, int msgLen)78 private void decode(byte[] msg, int msgLen) throws NamingException { 79 80 try { 81 int pos = 0; // current offset into msg 82 83 if (msgLen < HEADER_SIZE) { 84 throw new CommunicationException( 85 "DNS error: corrupted message header"); 86 } 87 88 xid = getShort(msg, pos); 89 pos += 2; 90 91 // Flags 92 short flags = (short) getShort(msg, pos); 93 pos += 2; 94 query = (flags & QR_BIT) == 0; 95 opcode = (flags & OPCODE_MASK) >>> OPCODE_SHIFT; 96 authoritative = (flags & AA_BIT) != 0; 97 truncated = (flags & TC_BIT) != 0; 98 recursionDesired = (flags & RD_BIT) != 0; 99 recursionAvail = (flags & RA_BIT) != 0; 100 rcode = (flags & RCODE_MASK); 101 102 // RR counts 103 numQuestions = getShort(msg, pos); 104 pos += 2; 105 numAnswers = getShort(msg, pos); 106 pos += 2; 107 numAuthorities = getShort(msg, pos); 108 pos += 2; 109 numAdditionals = getShort(msg, pos); 110 pos += 2; 111 112 } catch (IndexOutOfBoundsException e) { 113 throw new CommunicationException( 114 "DNS error: corrupted message header"); 115 } 116 } 117 118 /* 119 * Returns the 2-byte unsigned value at msg[pos]. The high 120 * order byte comes first. 121 */ getShort(byte[] msg, int pos)122 private static int getShort(byte[] msg, int pos) { 123 return (((msg[pos] & 0xFF) << 8) | 124 (msg[pos + 1] & 0xFF)); 125 } 126 } 127