001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 * 019 */ 020 package org.apache.directory.server.dns.service; 021 022 023 import java.util.ArrayList; 024 import java.util.Iterator; 025 import java.util.List; 026 import java.util.Set; 027 028 import org.apache.directory.server.dns.DnsException; 029 import org.apache.directory.server.dns.messages.DnsMessage; 030 import org.apache.directory.server.dns.messages.DnsMessageModifier; 031 import org.apache.directory.server.dns.messages.MessageType; 032 import org.apache.directory.server.dns.messages.OpCode; 033 import org.apache.directory.server.dns.messages.QuestionRecord; 034 import org.apache.directory.server.dns.messages.ResourceRecord; 035 import org.apache.directory.server.dns.messages.ResponseCode; 036 import org.apache.directory.server.dns.store.RecordStore; 037 import org.apache.directory.server.i18n.I18n; 038 import org.slf4j.Logger; 039 import org.slf4j.LoggerFactory; 040 041 042 /** 043 * Domain Name Service (DNS) Protocol (RFC 1034, 1035) 044 * 045 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 046 * @version $Rev: 901657 $, $Date: 2010-01-21 12:27:15 +0100 (Thu, 21 Jan 2010) $ 047 */ 048 public class DomainNameService 049 { 050 /** the log for this class */ 051 private static final Logger LOG = LoggerFactory.getLogger( DomainNameService.class ); 052 053 054 /** 055 * Creates a new instance of DomainNameService. 056 */ 057 public static void execute( DnsContext dnsContext, DnsMessage request ) throws Exception 058 { 059 if ( LOG.isDebugEnabled() ) 060 { 061 monitorRequest( request ); 062 } 063 064 getResourceRecords( dnsContext, request ); 065 066 if ( LOG.isDebugEnabled() ) 067 { 068 monitorContext( dnsContext ); 069 } 070 071 buildReply( dnsContext, request ); 072 073 if ( LOG.isDebugEnabled() ) 074 { 075 monitorReply( dnsContext ); 076 } 077 } 078 079 private static void monitorRequest( DnsMessage request ) throws Exception 080 { 081 try 082 { 083 LOG.debug( monitorMessage( request, "request" ) ); 084 } 085 catch ( Exception e ) 086 { 087 // This is a monitor. No exceptions should bubble up. 088 LOG.error( I18n.err( I18n.ERR_153 ), e ); 089 } 090 } 091 092 093 private static void getResourceRecords( DnsContext dnsContext, DnsMessage request ) throws Exception 094 { 095 RecordStore store = dnsContext.getStore(); 096 097 List<QuestionRecord> questions = request.getQuestionRecords(); 098 099 Iterator<QuestionRecord> it = questions.iterator(); 100 101 while ( it.hasNext() ) 102 { 103 dnsContext.addResourceRecords( getEntry( store, it.next() ) ); 104 } 105 } 106 107 108 /** 109 * Returns a set of {@link ResourceRecord}s from a {@link RecordStore}, given a DNS {@link QuestionRecord}. 110 * 111 * @param store 112 * @param question 113 * @return The set of {@link ResourceRecord}s. 114 * @throws DNSException 115 */ 116 private static Set<ResourceRecord> getEntry( RecordStore store, QuestionRecord question ) throws DnsException 117 { 118 Set<ResourceRecord> records = null; 119 120 records = store.getRecords( question ); 121 122 if ( records == null || records.isEmpty() ) 123 { 124 LOG.debug( "The domain name referenced in the query does not exist." ); 125 126 throw new DnsException( ResponseCode.NAME_ERROR ); 127 } 128 129 return records; 130 } 131 132 133 private static void monitorContext( DnsContext dnsContext ) throws Exception 134 { 135 try 136 { 137 RecordStore store = dnsContext.getStore(); 138 List<ResourceRecord> records = dnsContext.getResourceRecords(); 139 140 StringBuffer sb = new StringBuffer(); 141 sb.append( "Monitoring context:" ); 142 sb.append( "\n\t" + "store: " + store ); 143 sb.append( "\n\t" + "records: " + records ); 144 145 LOG.debug( sb.toString() ); 146 } 147 catch ( Exception e ) 148 { 149 // This is a monitor. No exceptions should bubble up. 150 LOG.error( I18n.err( I18n.ERR_154 ), e ); 151 } 152 } 153 154 155 private static void buildReply( DnsContext dnsContext, DnsMessage request ) throws Exception 156 { 157 List<ResourceRecord> records = dnsContext.getResourceRecords(); 158 159 DnsMessageModifier modifier = new DnsMessageModifier(); 160 161 modifier.setTransactionId( request.getTransactionId() ); 162 modifier.setMessageType( MessageType.RESPONSE ); 163 modifier.setOpCode( OpCode.QUERY ); 164 modifier.setAuthoritativeAnswer( false ); 165 modifier.setTruncated( false ); 166 modifier.setRecursionDesired( request.isRecursionDesired() ); 167 modifier.setRecursionAvailable( false ); 168 modifier.setReserved( false ); 169 modifier.setAcceptNonAuthenticatedData( false ); 170 modifier.setResponseCode( ResponseCode.NO_ERROR ); 171 modifier.setQuestionRecords( request.getQuestionRecords() ); 172 173 modifier.setAnswerRecords( records ); 174 modifier.setAuthorityRecords( new ArrayList<ResourceRecord>() ); 175 modifier.setAdditionalRecords( new ArrayList<ResourceRecord>() ); 176 177 dnsContext.setReply( modifier.getDnsMessage() ); 178 } 179 180 181 private static void monitorReply( DnsContext dnsContext ) throws Exception 182 { 183 try 184 { 185 DnsMessage reply = dnsContext.getReply(); 186 187 LOG.debug( monitorMessage( reply, "reply" ) ); 188 } 189 catch ( Exception e ) 190 { 191 // This is a monitor. No exceptions should bubble up. 192 LOG.error( I18n.err( I18n.ERR_155 ), e ); 193 } 194 } 195 196 197 private static String monitorMessage( DnsMessage message, String direction ) 198 { 199 MessageType messageType = message.getMessageType(); 200 OpCode opCode = message.getOpCode(); 201 ResponseCode responseCode = message.getResponseCode(); 202 int transactionId = message.getTransactionId(); 203 204 StringBuffer sb = new StringBuffer(); 205 sb.append( "Monitoring " + direction + ":" ); 206 sb.append( "\n\t" + "messageType " + messageType ); 207 sb.append( "\n\t" + "opCode " + opCode ); 208 sb.append( "\n\t" + "responseCode " + responseCode ); 209 sb.append( "\n\t" + "transactionId " + transactionId ); 210 211 sb.append( "\n\t" + "authoritativeAnswer " + message.isAuthoritativeAnswer() ); 212 sb.append( "\n\t" + "truncated " + message.isTruncated() ); 213 sb.append( "\n\t" + "recursionDesired " + message.isRecursionDesired() ); 214 sb.append( "\n\t" + "recursionAvailable " + message.isRecursionAvailable() ); 215 sb.append( "\n\t" + "reserved " + message.isReserved() ); 216 sb.append( "\n\t" + "acceptNonAuthenticatedData " + message.isAcceptNonAuthenticatedData() ); 217 218 List<QuestionRecord> questions = message.getQuestionRecords(); 219 220 sb.append( "\n\t" + "questions: " + questions ); 221 222 return sb.toString(); 223 } 224 }