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 021package org.apache.directory.server.dns.protocol; 022 023 024import java.util.ArrayList; 025 026import org.apache.directory.server.dns.DnsServer; 027import org.apache.directory.server.dns.DnsException; 028import org.apache.directory.server.dns.messages.DnsMessage; 029import org.apache.directory.server.dns.messages.DnsMessageModifier; 030import org.apache.directory.server.dns.messages.MessageType; 031import org.apache.directory.server.dns.messages.OpCode; 032import org.apache.directory.server.dns.messages.ResourceRecord; 033import org.apache.directory.server.dns.messages.ResponseCode; 034import org.apache.directory.server.dns.service.DnsContext; 035import org.apache.directory.server.dns.service.DomainNameService; 036import org.apache.directory.server.dns.store.RecordStore; 037import org.apache.mina.core.service.IoHandlerAdapter; 038import org.apache.mina.core.session.IdleStatus; 039import org.apache.mina.core.session.IoSession; 040import org.apache.mina.filter.codec.ProtocolCodecFilter; 041import org.slf4j.Logger; 042import org.slf4j.LoggerFactory; 043 044 045/** 046 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 047 */ 048public class DnsProtocolHandler extends IoHandlerAdapter 049{ 050 private static final Logger LOG = LoggerFactory.getLogger( DnsProtocolHandler.class ); 051 052 private DnsServer config; 053 private RecordStore store; 054 private String contextKey = "context"; 055 056 057 /** 058 * Creates a new instance of DnsProtocolHandler. 059 * 060 * @param config 061 * @param store 062 */ 063 public DnsProtocolHandler( DnsServer config, RecordStore store ) 064 { 065 this.config = config; 066 this.store = store; 067 } 068 069 070 @Override 071 public void sessionCreated( IoSession session ) throws Exception 072 { 073 if ( LOG.isDebugEnabled() ) 074 { 075 LOG.debug( "{} CREATED: {}", session.getRemoteAddress(), session.getTransportMetadata() ); 076 } 077 078 if ( session.getTransportMetadata().isConnectionless() ) 079 { 080 session.getFilterChain().addFirst( "codec", 081 new ProtocolCodecFilter( DnsProtocolUdpCodecFactory.getInstance() ) ); 082 } 083 else 084 { 085 session.getFilterChain().addFirst( "codec", 086 new ProtocolCodecFilter( DnsProtocolTcpCodecFactory.getInstance() ) ); 087 } 088 } 089 090 091 @Override 092 public void sessionOpened( IoSession session ) 093 { 094 LOG.debug( "{} OPENED", session.getRemoteAddress() ); 095 } 096 097 098 @Override 099 public void sessionClosed( IoSession session ) 100 { 101 LOG.debug( "{} CLOSED", session.getRemoteAddress() ); 102 } 103 104 105 @Override 106 public void sessionIdle( IoSession session, IdleStatus status ) 107 { 108 LOG.debug( "{} IDLE ({})", session.getRemoteAddress(), status ); 109 } 110 111 112 @Override 113 public void exceptionCaught( IoSession session, Throwable cause ) 114 { 115 LOG.error( session.getRemoteAddress() + " EXCEPTION", cause ); 116 session.closeNow(); 117 } 118 119 120 @Override 121 public void messageReceived( IoSession session, Object message ) 122 { 123 LOG.debug( "{} RCVD: {}", session.getRemoteAddress(), message ); 124 125 try 126 { 127 DnsContext dnsContext = new DnsContext(); 128 dnsContext.setConfig( config ); 129 dnsContext.setStore( store ); 130 session.setAttribute( getContextKey(), dnsContext ); 131 132 DomainNameService.execute( dnsContext, ( DnsMessage ) message ); 133 134 DnsMessage response = dnsContext.getReply(); 135 136 session.write( response ); 137 } 138 catch ( Exception e ) 139 { 140 LOG.error( e.getLocalizedMessage(), e ); 141 142 DnsMessage request = ( DnsMessage ) message; 143 DnsException de = ( DnsException ) e; 144 145 DnsMessageModifier modifier = new DnsMessageModifier(); 146 147 modifier.setTransactionId( request.getTransactionId() ); 148 modifier.setMessageType( MessageType.RESPONSE ); 149 modifier.setOpCode( OpCode.QUERY ); 150 modifier.setAuthoritativeAnswer( false ); 151 modifier.setTruncated( false ); 152 modifier.setRecursionDesired( request.isRecursionDesired() ); 153 modifier.setRecursionAvailable( false ); 154 modifier.setReserved( false ); 155 modifier.setAcceptNonAuthenticatedData( false ); 156 modifier.setResponseCode( ResponseCode.convert( ( byte ) de.getResponseCode() ) ); 157 modifier.setQuestionRecords( request.getQuestionRecords() ); 158 modifier.setAnswerRecords( new ArrayList<ResourceRecord>() ); 159 modifier.setAuthorityRecords( new ArrayList<ResourceRecord>() ); 160 modifier.setAdditionalRecords( new ArrayList<ResourceRecord>() ); 161 162 session.write( modifier.getDnsMessage() ); 163 } 164 } 165 166 167 @Override 168 public void messageSent( IoSession session, Object message ) 169 { 170 LOG.debug( "{} SENT: {}", session.getRemoteAddress(), message ); 171 } 172 173 174 protected String getContextKey() 175 { 176 return ( this.contextKey ); 177 } 178 179 180 @Override 181 public void inputClosed( IoSession session ) 182 { 183 } 184}