blob: 3499a437a5e979ddf68209fe6bd2fa642e2e8961 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
package org.apache.directory.server.dns.service;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import org.apache.directory.server.dns.DnsException;
import org.apache.directory.server.dns.messages.DnsMessage;
import org.apache.directory.server.dns.messages.DnsMessageModifier;
import org.apache.directory.server.dns.messages.MessageType;
import org.apache.directory.server.dns.messages.OpCode;
import org.apache.directory.server.dns.messages.QuestionRecord;
import org.apache.directory.server.dns.messages.ResourceRecord;
import org.apache.directory.server.dns.messages.ResponseCode;
import org.apache.directory.server.dns.store.RecordStore;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Domain Name Service (DNS) Protocol (RFC 1034, 1035)
*
* @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
* @version $Rev$, $Date$
*/
public class DomainNameService
{
/** the log for this class */
private static final Logger LOG = LoggerFactory.getLogger( DomainNameService.class );
/**
* Creates a new instance of DomainNameService.
*/
public static void execute( DnsContext dnsContext, DnsMessage request ) throws Exception
{
if ( LOG.isDebugEnabled() )
{
monitorRequest( request );
}
getResourceRecords( dnsContext, request );
if ( LOG.isDebugEnabled() )
{
monitorContext( dnsContext );
}
buildReply( dnsContext, request );
if ( LOG.isDebugEnabled() )
{
monitorReply( dnsContext );
}
}
private static void monitorRequest( DnsMessage request ) throws Exception
{
try
{
LOG.debug( monitorMessage( request, "request" ) );
}
catch ( Exception e )
{
// This is a monitor. No exceptions should bubble up.
LOG.error( "Error in request monitor", e );
}
}
private static void getResourceRecords( DnsContext dnsContext, DnsMessage request ) throws Exception
{
RecordStore store = dnsContext.getStore();
List<QuestionRecord> questions = request.getQuestionRecords();
Iterator<QuestionRecord> it = questions.iterator();
while ( it.hasNext() )
{
dnsContext.addResourceRecords( getEntry( store, it.next() ) );
}
}
/**
* Returns a set of {@link ResourceRecord}s from a {@link RecordStore}, given a DNS {@link QuestionRecord}.
*
* @param store
* @param question
* @return The set of {@link ResourceRecord}s.
* @throws DNSException
*/
private static Set<ResourceRecord> getEntry( RecordStore store, QuestionRecord question ) throws DnsException
{
Set<ResourceRecord> records = null;
records = store.getRecords( question );
if ( records == null || records.isEmpty() )
{
LOG.debug( "The domain name referenced in the query does not exist." );
throw new DnsException( ResponseCode.NAME_ERROR );
}
return records;
}
private static void monitorContext( DnsContext dnsContext ) throws Exception
{
try
{
RecordStore store = dnsContext.getStore();
List<ResourceRecord> records = dnsContext.getResourceRecords();
StringBuffer sb = new StringBuffer();
sb.append( "Monitoring context:" );
sb.append( "\n\t" + "store: " + store );
sb.append( "\n\t" + "records: " + records );
LOG.debug( sb.toString() );
}
catch ( Exception e )
{
// This is a monitor. No exceptions should bubble up.
LOG.error( "Error in context monitor", e );
}
}
private static void buildReply( DnsContext dnsContext, DnsMessage request ) throws Exception
{
List<ResourceRecord> records = dnsContext.getResourceRecords();
DnsMessageModifier modifier = new DnsMessageModifier();
modifier.setTransactionId( request.getTransactionId() );
modifier.setMessageType( MessageType.RESPONSE );
modifier.setOpCode( OpCode.QUERY );
modifier.setAuthoritativeAnswer( false );
modifier.setTruncated( false );
modifier.setRecursionDesired( request.isRecursionDesired() );
modifier.setRecursionAvailable( false );
modifier.setReserved( false );
modifier.setAcceptNonAuthenticatedData( false );
modifier.setResponseCode( ResponseCode.NO_ERROR );
modifier.setQuestionRecords( request.getQuestionRecords() );
modifier.setAnswerRecords( records );
modifier.setAuthorityRecords( new ArrayList<ResourceRecord>() );
modifier.setAdditionalRecords( new ArrayList<ResourceRecord>() );
dnsContext.setReply( modifier.getDnsMessage() );
}
private static void monitorReply( DnsContext dnsContext ) throws Exception
{
try
{
DnsMessage reply = dnsContext.getReply();
LOG.debug( monitorMessage( reply, "reply" ) );
}
catch ( Exception e )
{
// This is a monitor. No exceptions should bubble up.
LOG.error( "Error in reply monitor", e );
}
}
private static String monitorMessage( DnsMessage message, String direction )
{
MessageType messageType = message.getMessageType();
OpCode opCode = message.getOpCode();
ResponseCode responseCode = message.getResponseCode();
int transactionId = message.getTransactionId();
StringBuffer sb = new StringBuffer();
sb.append( "Monitoring " + direction + ":" );
sb.append( "\n\t" + "messageType " + messageType );
sb.append( "\n\t" + "opCode " + opCode );
sb.append( "\n\t" + "responseCode " + responseCode );
sb.append( "\n\t" + "transactionId " + transactionId );
sb.append( "\n\t" + "authoritativeAnswer " + message.isAuthoritativeAnswer() );
sb.append( "\n\t" + "truncated " + message.isTruncated() );
sb.append( "\n\t" + "recursionDesired " + message.isRecursionDesired() );
sb.append( "\n\t" + "recursionAvailable " + message.isRecursionAvailable() );
sb.append( "\n\t" + "reserved " + message.isReserved() );
sb.append( "\n\t" + "acceptNonAuthenticatedData " + message.isAcceptNonAuthenticatedData() );
List<QuestionRecord> questions = message.getQuestionRecords();
sb.append( "\n\t" + "questions: " + questions );
return sb.toString();
}
}