1/*
2 * Copyright (c) 2000, 2011, 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
26package com.sun.jndi.dns;
27
28
29import java.util.Vector;
30import javax.naming.*;
31
32
33/**
34 * The ResourceRecords class represents the resource records in the
35 * four sections of a DNS message.
36 *
37 * The additional records section is currently ignored.
38 *
39 * @author Scott Seligman
40 */
41
42
43class ResourceRecords {
44
45    // Four sections:  question, answer, authority, additional.
46    // The question section is treated as being made up of (shortened)
47    // resource records, although this isn't technically how it's defined.
48    Vector<ResourceRecord> question = new Vector<>();
49    Vector<ResourceRecord> answer = new Vector<>();
50    Vector<ResourceRecord> authority = new Vector<>();
51    Vector<ResourceRecord> additional = new Vector<>();
52
53    /*
54     * True if these resource records are from a zone transfer.  In
55     * that case only answer records are read (as per
56     * draft-ietf-dnsext-axfr-clarify-02.txt).  Also, the rdata of
57     * those answer records is not decoded (for efficiency) except
58     * for SOA records.
59     */
60    boolean zoneXfer;
61
62    /*
63     * Returns a representation of the resource records in a DNS message.
64     * Does not modify or store a reference to the msg array.
65     */
66    ResourceRecords(byte[] msg, int msgLen, Header hdr, boolean zoneXfer)
67            throws NamingException {
68        if (zoneXfer) {
69            answer.ensureCapacity(8192);        // an arbitrary "large" number
70        }
71        this.zoneXfer = zoneXfer;
72        add(msg, msgLen, hdr);
73    }
74
75    /*
76     * Returns the type field of the first answer record, or -1 if
77     * there are no answer records.
78     */
79    int getFirstAnsType() {
80        if (answer.size() == 0) {
81            return -1;
82        }
83        return answer.firstElement().getType();
84    }
85
86    /*
87     * Returns the type field of the last answer record, or -1 if
88     * there are no answer records.
89     */
90    int getLastAnsType() {
91        if (answer.size() == 0) {
92            return -1;
93        }
94        return answer.lastElement().getType();
95    }
96
97    /*
98     * Decodes the resource records in a DNS message and adds
99     * them to this object.
100     * Does not modify or store a reference to the msg array.
101     */
102    void add(byte[] msg, int msgLen, Header hdr) throws NamingException {
103
104        ResourceRecord rr;
105        int pos = Header.HEADER_SIZE;   // current offset into msg
106
107        try {
108            for (int i = 0; i < hdr.numQuestions; i++) {
109                rr = new ResourceRecord(msg, msgLen, pos, true, false);
110                if (!zoneXfer) {
111                    question.addElement(rr);
112                }
113                pos += rr.size();
114            }
115
116            for (int i = 0; i < hdr.numAnswers; i++) {
117                rr = new ResourceRecord(
118                        msg, msgLen, pos, false, !zoneXfer);
119                answer.addElement(rr);
120                pos += rr.size();
121            }
122
123            if (zoneXfer) {
124                return;
125            }
126
127            for (int i = 0; i < hdr.numAuthorities; i++) {
128                rr = new ResourceRecord(msg, msgLen, pos, false, true);
129                authority.addElement(rr);
130                pos += rr.size();
131            }
132
133            // The additional records section is currently ignored.
134
135        } catch (IndexOutOfBoundsException e) {
136            throw new CommunicationException(
137                    "DNS error: corrupted message");
138        }
139    }
140}
141