View Javadoc
1   /*
2    * Copyright 2019 the original author or authors.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package org.bremersee.dccon.repository.ldap.transcoder;
18  
19  import java.io.ByteArrayInputStream;
20  import java.io.DataInputStream;
21  import java.io.IOException;
22  import java.net.InetAddress;
23  import java.net.UnknownHostException;
24  import java.nio.charset.StandardCharsets;
25  import java.util.ArrayList;
26  import java.util.List;
27  import java.util.function.Supplier;
28  import lombok.extern.slf4j.Slf4j;
29  import org.apache.commons.io.IOUtils;
30  import org.bremersee.dccon.model.DnsRecord;
31  import org.bremersee.exception.ServiceException;
32  import org.ldaptive.io.Hex;
33  import org.springframework.util.StringUtils;
34  
35  /**
36   * The dns record data mapper.
37   *
38   * @author Christian Bremer
39   */
40  @Slf4j
41  public abstract class DnsRecordDataMapper {
42  
43    private DnsRecordDataMapper() {
44    }
45  
46    /**
47     * Parse a dns record.
48     *
49     * @param data the data
50     * @param dnsRecordSupplier the dns record supplier
51     * @return the dns record
52     */
53    public static DnsRecord parseA(final byte[] data, final Supplier<DnsRecord> dnsRecordSupplier) {
54      final DnsRecord dnsRecord = dnsRecordSupplier.get();
55      if (data.length >= 4) {
56        try (DataInputStream dis = new DataInputStream(new ByteArrayInputStream(data))) {
57          String ip = String.valueOf(dis.readUnsignedByte())
58              + '.'
59              + dis.readUnsignedByte()
60              + '.'
61              + dis.readUnsignedByte()
62              + '.'
63              + dis.readUnsignedByte();
64          dnsRecord.setRecordValue(ip);
65        } catch (IOException ioe) {
66          final ServiceException se = ServiceException.internalServerError(
67              "Parsing data of A record failed.",
68              "org.bremersee:dc-con-app:7279a7e9-69a8-4d30-b1c2-14c10a3a705f",
69              ioe);
70          log.error("msg=[Parsing data of A record failed.]", se);
71          throw se;
72        }
73      } else {
74        dnsRecord.setRecordValue(new String(Hex.encode(data)));
75      }
76      log.debug("msg=[A record parsed.] recordValue=[{}] correlatedRecordValue=[{}]",
77          dnsRecord.getRecordValue(), dnsRecord.getCorrelatedRecordValue());
78      return dnsRecord;
79    }
80  
81    /**
82     * Parse cname dns record.
83     *
84     * @param data the data
85     * @param dnsRecordSupplier the dns record supplier
86     * @return the dns record
87     */
88    public static DnsRecord parseCname(
89        final byte[] data,
90        final Supplier<DnsRecord> dnsRecordSupplier) {
91      return parsePtr(data, dnsRecordSupplier);
92    }
93  
94    /**
95     * Parse ptr dns record.
96     *
97     * @param data the data
98     * @param dnsRecordSupplier the dns record supplier
99     * @return the dns record
100    */
101   public static DnsRecord parsePtr(final byte[] data, final Supplier<DnsRecord> dnsRecordSupplier) {
102     final DnsRecord dnsRecord = dnsRecordSupplier.get();
103     if (data != null && data.length > 1) {
104       try (final DataInputStream dis = new DataInputStream(new ByteArrayInputStream(data))) {
105         int expectedLength = dis.readUnsignedByte();
106         int actualLength = 0;
107         final List<String> values = new ArrayList<>();
108         StringBuilder valueBuilder = new StringBuilder();
109         for (char c : IOUtils.toString(dis, StandardCharsets.UTF_8).toCharArray()) {
110           actualLength++;
111           if (c > 32) {
112             valueBuilder.append(c);
113           } else if (valueBuilder.length() > 0) {
114             values.add(valueBuilder.toString());
115             valueBuilder = new StringBuilder();
116           }
117         }
118         if (valueBuilder.length() > 0) {
119           values.add(valueBuilder.toString());
120         }
121         final String value = StringUtils.collectionToDelimitedString(values, ".");
122         log.debug("msg=[PTR record parsed.] ptrValue=[{}] expectedLength=[{}] actualLength=[{}]",
123             value, expectedLength, actualLength);
124 
125         try {
126           final InetAddress inetAddress = InetAddress.getByName(value);
127           dnsRecord.setRecordValue(inetAddress.getHostName());
128           dnsRecord.setCorrelatedRecordValue(inetAddress.getHostAddress());
129 
130         } catch (UnknownHostException e) {
131           dnsRecord.setRecordValue(value);
132         }
133 
134       } catch (IOException e) {
135         log.error("Parsing PTR record value failed.", e);
136       }
137     }
138     return dnsRecord;
139   }
140 }