Package org.apache.directory.server.dhcp.protocol

Source Code of org.apache.directory.server.dhcp.protocol.DhcpProtocolHandler

/*
*  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.dhcp.protocol;

import java.net.InetAddress;
import java.net.InetSocketAddress;

import org.apache.directory.server.dhcp.messages.DhcpMessage;
import org.apache.directory.server.dhcp.messages.MessageType;
import org.apache.directory.server.dhcp.service.DhcpService;
import org.apache.mina.core.service.IoHandler;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* Implementation of a DHCP protocol handler which delegates the work of
* generating replys to a DhcpService implementation.
*
* @see org.apache.directory.server.dhcp.service.DhcpService
* @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
* @version $Rev: 725712 $, $Date: 2008-12-11 16:32:04 +0100 (Jeu, 11 déc 2008) $
*/
public class DhcpProtocolHandler implements IoHandler {
    private static final Logger logger = LoggerFactory
            .getLogger(DhcpProtocolHandler.class);

    /**
     * Default DHCP client port
     */
    public static final int CLIENT_PORT = 68;

    /**
     * Default DHCP server port
     */
    public static final int SERVER_PORT = 67;

    /**
     * The DHCP service implementation. The implementation is supposed to be
     * thread-safe.
     */
    private final DhcpService dhcpService;

    /**
     *
     */
    public DhcpProtocolHandler(DhcpService service) {
        this.dhcpService = service;
    }

    public void sessionCreated(IoSession session) throws Exception {
        logger.debug("{} CREATED", session.getLocalAddress());
        session.getFilterChain().addFirst("codec",
                new ProtocolCodecFilter(new DhcpProtocolCodecFactory()));
    }

    public void sessionOpened(IoSession session) {
        logger.debug("{} -> {} OPENED", session.getRemoteAddress(), session
                .getLocalAddress());
    }

    public void sessionClosed(IoSession session) {
        logger.debug("{} -> {} CLOSED", session.getRemoteAddress(), session
                .getLocalAddress());
    }

    public void sessionIdle(IoSession session, IdleStatus status) {
        // ignore
    }

    public void exceptionCaught(IoSession session, Throwable cause) {
        logger.error("EXCEPTION CAUGHT ", cause);
        cause.printStackTrace(System.out);

        session.close( true );
    }

    public void messageReceived(IoSession session, Object message)
            throws Exception {
        if (logger.isDebugEnabled())
            logger.debug("{} -> {} RCVD: {} " + message, session.getRemoteAddress(),
                    session.getLocalAddress());

        final DhcpMessage request = (DhcpMessage) message;

        final DhcpMessage reply = dhcpService.getReplyFor(
                (InetSocketAddress) session.getServiceAddress(),
                (InetSocketAddress) session.getRemoteAddress(), request);

        if (null != reply) {
            final InetSocketAddress isa = determineMessageDestination(request, reply);
            session.write(reply, isa);
        }
    }

    /**
     * Determine where to send the message: <br>
     * If the 'giaddr' field in a DHCP message from a client is non-zero, the
     * server sends any return messages to the 'DHCP server' port on the BOOTP
     * relay agent whose address appears in 'giaddr'. If the 'giaddr' field is
     * zero and the 'ciaddr' field is nonzero, then the server unicasts DHCPOFFER
     * and DHCPACK messages to the address in 'ciaddr'. If 'giaddr' is zero and
     * 'ciaddr' is zero, and the broadcast bit is set, then the server broadcasts
     * DHCPOFFER and DHCPACK messages to 0xffffffff. If the broadcast bit is not
     * set and 'giaddr' is zero and 'ciaddr' is zero, then the server unicasts
     * DHCPOFFER and DHCPACK messages to the client's hardware address and
     * 'yiaddr' address. In all cases, when 'giaddr' is zero, the server
     * broadcasts any DHCPNAK messages to 0xffffffff.
     *
     * @param request
     * @param reply
     * @return
     */
    private InetSocketAddress determineMessageDestination(DhcpMessage request,
            DhcpMessage reply) {

        final MessageType mt = reply.getMessageType();
        if (!isNullAddress(request.getRelayAgentAddress()))
            // send to agent, if received via agent.
            return new InetSocketAddress(request.getRelayAgentAddress(), SERVER_PORT);
        else if (null != mt && mt == MessageType.DHCPNAK)
            // force broadcast for DHCPNAKs
            return new InetSocketAddress("255.255.255.255", 68);
        else // not a NAK...
        if (!isNullAddress(request.getCurrentClientAddress()))
            // have a current address? unicast to it.
            return new InetSocketAddress(request.getCurrentClientAddress(),
                    CLIENT_PORT);
        else
            return new InetSocketAddress("255.255.255.255", 68);
    }

    /**
     * Determine, whether the given address ist actually the null address
     * "0.0.0.0".
     *
     * @param relayAgentAddress
     * @return
     */
    private boolean isNullAddress(InetAddress addr) {
        final byte a[] = addr.getAddress();
        for (int i = 0; i < a.length; i++)
            if (a[i] != 0)
                return false;
        return true;
    }

    public void messageSent(IoSession session, Object message) {
        if (logger.isDebugEnabled())
            logger.debug("{} -> {} SENT: " + message, session.getRemoteAddress(),
                    session.getLocalAddress());
    }
}
TOP

Related Classes of org.apache.directory.server.dhcp.protocol.DhcpProtocolHandler

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.