View Javadoc
1   /*
2    *  Licensed to the Apache Software Foundation (ASF) under one
3    *  or more contributor license agreements.  See the NOTICE file
4    *  distributed with this work for additional information
5    *  regarding copyright ownership.  The ASF licenses this file
6    *  to you under the Apache License, Version 2.0 (the
7    *  "License"); you may not use this file except in compliance
8    *  with the License.  You may obtain a copy of the License at
9    *  
10   *    http://www.apache.org/licenses/LICENSE-2.0
11   *  
12   *  Unless required by applicable law or agreed to in writing,
13   *  software distributed under the License is distributed on an
14   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   *  KIND, either express or implied.  See the License for the
16   *  specific language governing permissions and limitations
17   *  under the License. 
18   *  
19   */
20  package org.apache.directory.server.dns.service;
21  
22  
23  import java.util.ArrayList;
24  import java.util.Iterator;
25  import java.util.List;
26  import java.util.Set;
27  
28  import org.apache.directory.server.dns.DnsException;
29  import org.apache.directory.server.dns.messages.DnsMessage;
30  import org.apache.directory.server.dns.messages.DnsMessageModifier;
31  import org.apache.directory.server.dns.messages.MessageType;
32  import org.apache.directory.server.dns.messages.OpCode;
33  import org.apache.directory.server.dns.messages.QuestionRecord;
34  import org.apache.directory.server.dns.messages.ResourceRecord;
35  import org.apache.directory.server.dns.messages.ResponseCode;
36  import org.apache.directory.server.dns.store.RecordStore;
37  import org.apache.directory.server.i18n.I18n;
38  import org.slf4j.Logger;
39  import org.slf4j.LoggerFactory;
40  
41  
42  /**
43   * Domain Name Service (DNS) Protocol (RFC 1034, 1035)
44   * 
45   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
46   */
47  public final class DomainNameService
48  {
49      /** the log for this class */
50      private static final Logger LOG = LoggerFactory.getLogger( DomainNameService.class );
51  
52  
53      private DomainNameService()
54      {
55      }
56  
57  
58      /**
59       * Creates a new instance of DomainNameService.
60       */
61      public static void execute( DnsContext dnsContext, DnsMessage request ) throws Exception
62      {
63          if ( LOG.isDebugEnabled() )
64          {
65              monitorRequest( request );
66          }
67  
68          getResourceRecords( dnsContext, request );
69  
70          if ( LOG.isDebugEnabled() )
71          {
72              monitorContext( dnsContext );
73          }
74  
75          buildReply( dnsContext, request );
76  
77          if ( LOG.isDebugEnabled() )
78          {
79              monitorReply( dnsContext );
80          }
81      }
82  
83  
84      private static void monitorRequest( DnsMessage request )
85      {
86          try
87          {
88              if ( LOG.isDebugEnabled() )
89              {
90                  LOG.debug( monitorMessage( request, "request" ) );
91              }
92          }
93          catch ( Exception e )
94          {
95              // This is a monitor.  No exceptions should bubble up.
96              LOG.error( I18n.err( I18n.ERR_153 ), e );
97          }
98      }
99  
100 
101     private static void getResourceRecords( DnsContext dnsContext, DnsMessage request ) throws DnsException
102     {
103         RecordStore store = dnsContext.getStore();
104 
105         List<QuestionRecord> questions = request.getQuestionRecords();
106 
107         Iterator<QuestionRecord> it = questions.iterator();
108 
109         while ( it.hasNext() )
110         {
111             dnsContext.addResourceRecords( getEntry( store, it.next() ) );
112         }
113     }
114 
115 
116     /**
117      * Returns a set of {@link ResourceRecord}s from a {@link RecordStore}, given a DNS {@link QuestionRecord}.
118      *
119      * @param store
120      * @param question
121      * @return The set of {@link ResourceRecord}s.
122      * @throws DNSException
123      */
124     private static Set<ResourceRecord> getEntry( RecordStore store, QuestionRecord question ) throws DnsException
125     {
126         Set<ResourceRecord> records = null;
127 
128         records = store.getRecords( question );
129 
130         if ( records == null || records.isEmpty() )
131         {
132             LOG.debug( "The domain name referenced in the query does not exist." );
133 
134             throw new DnsException( ResponseCode.NAME_ERROR );
135         }
136 
137         return records;
138     }
139 
140 
141     private static void monitorContext( DnsContext dnsContext )
142     {
143         try
144         {
145             RecordStore store = dnsContext.getStore();
146             List<ResourceRecord> records = dnsContext.getResourceRecords();
147 
148             StringBuilder sb = new StringBuilder();
149             sb.append( "Monitoring context:" );
150             sb.append( "\n\t" + "store:                     " + store );
151             sb.append( "\n\t" + "records:                   " + records );
152 
153             LOG.debug( sb.toString() );
154         }
155         catch ( Exception e )
156         {
157             // This is a monitor.  No exceptions should bubble up.
158             LOG.error( I18n.err( I18n.ERR_154 ), e );
159         }
160     }
161 
162 
163     private static void buildReply( DnsContext dnsContext, DnsMessage request ) 
164     {
165         List<ResourceRecord> records = dnsContext.getResourceRecords();
166 
167         DnsMessageModifierages/DnsMessageModifier.html#DnsMessageModifier">DnsMessageModifier modifier = new DnsMessageModifier();
168 
169         modifier.setTransactionId( request.getTransactionId() );
170         modifier.setMessageType( MessageType.RESPONSE );
171         modifier.setOpCode( OpCode.QUERY );
172         modifier.setAuthoritativeAnswer( false );
173         modifier.setTruncated( false );
174         modifier.setRecursionDesired( request.isRecursionDesired() );
175         modifier.setRecursionAvailable( false );
176         modifier.setReserved( false );
177         modifier.setAcceptNonAuthenticatedData( false );
178         modifier.setResponseCode( ResponseCode.NO_ERROR );
179         modifier.setQuestionRecords( request.getQuestionRecords() );
180 
181         modifier.setAnswerRecords( records );
182         modifier.setAuthorityRecords( new ArrayList<ResourceRecord>() );
183         modifier.setAdditionalRecords( new ArrayList<ResourceRecord>() );
184 
185         dnsContext.setReply( modifier.getDnsMessage() );
186     }
187 
188 
189     private static void monitorReply( DnsContext dnsContext )
190     {
191         try
192         {
193             DnsMessage reply = dnsContext.getReply();
194 
195             if ( LOG.isDebugEnabled() )
196             {
197                 LOG.debug( monitorMessage( reply, "reply" ) );
198             }
199         }
200         catch ( Exception e )
201         {
202             // This is a monitor.  No exceptions should bubble up.
203             LOG.error( I18n.err( I18n.ERR_155 ), e );
204         }
205     }
206 
207 
208     private static String monitorMessage( DnsMessage message, String direction )
209     {
210         MessageType messageType = message.getMessageType();
211         OpCode opCode = message.getOpCode();
212         ResponseCode responseCode = message.getResponseCode();
213         int transactionId = message.getTransactionId();
214 
215         StringBuilder sb = new StringBuilder();
216         sb.append( "Monitoring " + direction + ":" );
217         sb.append( "\n\t" + "messageType                " + messageType );
218         sb.append( "\n\t" + "opCode                     " + opCode );
219         sb.append( "\n\t" + "responseCode               " + responseCode );
220         sb.append( "\n\t" + "transactionId              " + transactionId );
221 
222         sb.append( "\n\t" + "authoritativeAnswer        " + message.isAuthoritativeAnswer() );
223         sb.append( "\n\t" + "truncated                  " + message.isTruncated() );
224         sb.append( "\n\t" + "recursionDesired           " + message.isRecursionDesired() );
225         sb.append( "\n\t" + "recursionAvailable         " + message.isRecursionAvailable() );
226         sb.append( "\n\t" + "reserved                   " + message.isReserved() );
227         sb.append( "\n\t" + "acceptNonAuthenticatedData " + message.isAcceptNonAuthenticatedData() );
228 
229         List<QuestionRecord> questions = message.getQuestionRecords();
230 
231         sb.append( "\n\t" + "questions:                 " + questions );
232 
233         return sb.toString();
234     }
235 }