--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.dns.client/share/classes/jdk/dns/client/internal/Header.java Thu Oct 31 16:16:21 2019 +0000
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2019, 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 jdk.dns.client.internal;
+
+import jdk.dns.client.ex.DnsResolverException;
+
+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 DnsResolverException {
+ 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 DnsResolverException {
+
+ try {
+ int pos = 0; // current offset into msg
+
+ if (msgLen < HEADER_SIZE) {
+ throw new DnsResolverException(
+ "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 DnsResolverException("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));
+ }
+}