jdk/src/share/classes/com/sun/jndi/dns/ResourceRecord.java
changeset 22992 e7fcc52b1b29
parent 5506 202f599c92aa
child 24969 afa6934dd8e8
equal deleted inserted replaced
22991:ed73cb1663a5 22992:e7fcc52b1b29
     1 /*
     1 /*
     2  * Copyright (c) 2000, 2002, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     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
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     7  * published by the Free Software Foundation.  Oracle designates this
    23  * questions.
    23  * questions.
    24  */
    24  */
    25 
    25 
    26 package com.sun.jndi.dns;
    26 package com.sun.jndi.dns;
    27 
    27 
       
    28 import javax.naming.CommunicationException;
    28 import javax.naming.InvalidNameException;
    29 import javax.naming.InvalidNameException;
       
    30 
       
    31 import java.io.IOException;
       
    32 
       
    33 import java.nio.charset.StandardCharsets;
    29 
    34 
    30 
    35 
    31 /**
    36 /**
    32  * The ResourceRecord class represents a DNS resource record.
    37  * The ResourceRecord class represents a DNS resource record.
    33  * The string format is based on the master file representation in
    38  * The string format is based on the master file representation in
    82      */
    87      */
    83     static final String rrClassNames[] = {
    88     static final String rrClassNames[] = {
    84         null, "IN", null, null, "HS"
    89         null, "IN", null, null, "HS"
    85     };
    90     };
    86 
    91 
       
    92     /*
       
    93      * Maximum number of compression references in labels.
       
    94      * Used to detect compression loops.
       
    95      */
       
    96     private static final int MAXIMUM_COMPRESSION_REFERENCES = 16;
    87 
    97 
    88     byte[] msg;                 // DNS message
    98     byte[] msg;                 // DNS message
    89     int msgLen;                 // msg size (in octets)
    99     int msgLen;                 // msg size (in octets)
    90     boolean qSection;           // true if this RR is part of question section
   100     boolean qSection;           // true if this RR is part of question section
    91                                 // and therefore has no ttl or rdata
   101                                 // and therefore has no ttl or rdata
   108      * not a true resource record in that case, but is treated as if it
   118      * not a true resource record in that case, but is treated as if it
   109      * were a shortened one (with no ttl or rdata).  If decodeRdata is
   119      * were a shortened one (with no ttl or rdata).  If decodeRdata is
   110      * false, the rdata is not decoded (and getRdata() will return null)
   120      * false, the rdata is not decoded (and getRdata() will return null)
   111      * unless this is an SOA record.
   121      * unless this is an SOA record.
   112      *
   122      *
   113      * @throws InvalidNameException if a decoded domain name isn't valid.
   123      * @throws CommunicationException if a decoded domain name isn't valid.
   114      * @throws ArrayIndexOutOfBoundsException given certain other corrupt data.
   124      * @throws ArrayIndexOutOfBoundsException given certain other corrupt data.
   115      */
   125      */
   116     ResourceRecord(byte[] msg, int msgLen, int offset,
   126     ResourceRecord(byte[] msg, int msgLen, int offset,
   117                    boolean qSection, boolean decodeRdata)
   127                    boolean qSection, boolean decodeRdata)
   118             throws InvalidNameException {
   128             throws CommunicationException {
   119 
   129 
   120         this.msg = msg;
   130         this.msg = msg;
   121         this.msgLen = msgLen;
   131         this.msgLen = msgLen;
   122         this.offset = offset;
   132         this.offset = offset;
   123         this.qSection = qSection;
   133         this.qSection = qSection;
   233 
   243 
   234     /*
   244     /*
   235      * Decodes the binary format of the RR.
   245      * Decodes the binary format of the RR.
   236      * May throw ArrayIndexOutOfBoundsException given corrupt data.
   246      * May throw ArrayIndexOutOfBoundsException given corrupt data.
   237      */
   247      */
   238     private void decode(boolean decodeRdata) throws InvalidNameException {
   248     private void decode(boolean decodeRdata) throws CommunicationException {
   239         int pos = offset;       // index of next unread octet
   249         int pos = offset;       // index of next unread octet
   240 
   250 
   241         name = new DnsName();                           // NAME
   251         name = new DnsName();                           // NAME
   242         pos = decodeName(pos, name);
   252         pos = decodeName(pos, name);
   243 
   253 
   314     }
   324     }
   315 
   325 
   316     /*
   326     /*
   317      * Returns the name encoded at msg[pos], including the root label.
   327      * Returns the name encoded at msg[pos], including the root label.
   318      */
   328      */
   319     private DnsName decodeName(int pos) throws InvalidNameException {
   329     private DnsName decodeName(int pos) throws CommunicationException {
   320         DnsName n = new DnsName();
   330         DnsName n = new DnsName();
   321         decodeName(pos, n);
   331         decodeName(pos, n);
   322         return n;
   332         return n;
   323     }
   333     }
   324 
   334 
   325     /*
   335     /*
   326      * Prepends to "n" the domain name encoded at msg[pos], including the root
   336      * Prepends to "n" the domain name encoded at msg[pos], including the root
   327      * label.  Returns the index into "msg" following the name.
   337      * label.  Returns the index into "msg" following the name.
   328      */
   338      */
   329     private int decodeName(int pos, DnsName n) throws InvalidNameException {
   339     private int decodeName(int pos, DnsName n) throws CommunicationException {
   330         if (msg[pos] == 0) {                            // end of name
   340         int endPos = -1;
   331             n.add(0, "");
   341         int level = 0;
   332             return (pos + 1);
   342         try {
   333         } else if ((msg[pos] & 0xC0) != 0) {            // name compression
   343             while (true) {
   334             decodeName(getUShort(pos) & 0x3FFF, n);
   344                 if (level > MAXIMUM_COMPRESSION_REFERENCES)
   335             return (pos + 2);
   345                     throw new IOException("Too many compression references");
   336         } else {                                        // append a label
   346                 int typeAndLen = msg[pos] & 0xFF;
   337             int len = msg[pos++];
   347                 if (typeAndLen == 0) {                  // end of name
   338             try {
   348                     ++pos;
   339                 n.add(0, new String(msg, pos, len, "ISO-8859-1"));
   349                     n.add(0, "");
   340             } catch (java.io.UnsupportedEncodingException e) {
   350                     break;
   341                 // assert false : "ISO-Latin-1 charset unavailable";
   351                 } else if (typeAndLen <= 63) {          // regular label
   342             }
   352                     ++pos;
   343             return decodeName(pos + len, n);
   353                     n.add(0, new String(msg, pos, typeAndLen,
   344         }
   354                         StandardCharsets.ISO_8859_1));
       
   355                     pos += typeAndLen;
       
   356                 } else if ((typeAndLen & 0xC0) == 0xC0) { // name compression
       
   357                     ++level;
       
   358                     endPos = pos + 2;
       
   359                     pos = getUShort(pos) & 0x3FFF;
       
   360                 } else
       
   361                     throw new IOException("Invalid label type: " + typeAndLen);
       
   362             }
       
   363         } catch (IOException | InvalidNameException e) {
       
   364             CommunicationException ce =new CommunicationException(
       
   365                 "DNS error: malformed packet");
       
   366             ce.initCause(e);
       
   367             throw ce;
       
   368         }
       
   369         if (endPos == -1)
       
   370             endPos = pos;
       
   371         return endPos;
   345     }
   372     }
   346 
   373 
   347     /*
   374     /*
   348      * Returns the rdata encoded at msg[pos].  The format is dependent
   375      * Returns the rdata encoded at msg[pos].  The format is dependent
   349      * on the rrtype and rrclass values, which have already been set.
   376      * on the rrtype and rrclass values, which have already been set.
   350      * The length of the encoded data is rdlen, which has already been
   377      * The length of the encoded data is rdlen, which has already been
   351      * set.
   378      * set.
   352      * The rdata of records with unknown type/class combinations is
   379      * The rdata of records with unknown type/class combinations is
   353      * returned in a newly-allocated byte array.
   380      * returned in a newly-allocated byte array.
   354      */
   381      */
   355     private Object decodeRdata(int pos) throws InvalidNameException {
   382     private Object decodeRdata(int pos) throws CommunicationException {
   356         if (rrclass == CLASS_INTERNET) {
   383         if (rrclass == CLASS_INTERNET) {
   357             switch (rrtype) {
   384             switch (rrtype) {
   358             case TYPE_A:
   385             case TYPE_A:
   359                 return decodeA(pos);
   386                 return decodeA(pos);
   360             case TYPE_AAAA:
   387             case TYPE_AAAA:
   384     }
   411     }
   385 
   412 
   386     /*
   413     /*
   387      * Returns the rdata of an MX record that is encoded at msg[pos].
   414      * Returns the rdata of an MX record that is encoded at msg[pos].
   388      */
   415      */
   389     private String decodeMx(int pos) throws InvalidNameException {
   416     private String decodeMx(int pos) throws CommunicationException {
   390         int preference = getUShort(pos);
   417         int preference = getUShort(pos);
   391         pos += 2;
   418         pos += 2;
   392         DnsName name = decodeName(pos);
   419         DnsName name = decodeName(pos);
   393         return (preference + " " + name);
   420         return (preference + " " + name);
   394     }
   421     }
   395 
   422 
   396     /*
   423     /*
   397      * Returns the rdata of an SOA record that is encoded at msg[pos].
   424      * Returns the rdata of an SOA record that is encoded at msg[pos].
   398      */
   425      */
   399     private String decodeSoa(int pos) throws InvalidNameException {
   426     private String decodeSoa(int pos) throws CommunicationException {
   400         DnsName mname = new DnsName();
   427         DnsName mname = new DnsName();
   401         pos = decodeName(pos, mname);
   428         pos = decodeName(pos, mname);
   402         DnsName rname = new DnsName();
   429         DnsName rname = new DnsName();
   403         pos = decodeName(pos, rname);
   430         pos = decodeName(pos, rname);
   404 
   431 
   419 
   446 
   420     /*
   447     /*
   421      * Returns the rdata of an SRV record that is encoded at msg[pos].
   448      * Returns the rdata of an SRV record that is encoded at msg[pos].
   422      * See RFC 2782.
   449      * See RFC 2782.
   423      */
   450      */
   424     private String decodeSrv(int pos) throws InvalidNameException {
   451     private String decodeSrv(int pos) throws CommunicationException {
   425         int priority = getUShort(pos);
   452         int priority = getUShort(pos);
   426         pos += 2;
   453         pos += 2;
   427         int weight =   getUShort(pos);
   454         int weight =   getUShort(pos);
   428         pos += 2;
   455         pos += 2;
   429         int port =     getUShort(pos);
   456         int port =     getUShort(pos);
   434 
   461 
   435     /*
   462     /*
   436      * Returns the rdata of an NAPTR record that is encoded at msg[pos].
   463      * Returns the rdata of an NAPTR record that is encoded at msg[pos].
   437      * See RFC 2915.
   464      * See RFC 2915.
   438      */
   465      */
   439     private String decodeNaptr(int pos) throws InvalidNameException {
   466     private String decodeNaptr(int pos) throws CommunicationException {
   440         int order = getUShort(pos);
   467         int order = getUShort(pos);
   441         pos += 2;
   468         pos += 2;
   442         int preference = getUShort(pos);
   469         int preference = getUShort(pos);
   443         pos += 2;
   470         pos += 2;
   444         StringBuffer flags = new StringBuffer();
   471         StringBuffer flags = new StringBuffer();