Search in sources :

Example 1 with DhcpdConfigFactory

use of org.opennms.netmgt.config.dhcpd.DhcpdConfigFactory in project opennms by OpenNMS.

the class Poller method isServer.

/**
     * <p>
     * This method actually tests the remote host to determine if it is
     * running a functional DHCP server.
     * </p>
     * <p>
     * Formats a DHCP query and encodes it in a client request message which
     * is sent to the DHCP daemon over the established TCP socket connection.
     * If a matching DHCP response packet is not received from the DHCP daemon
     * within the specified timeout the client request message will be re-sent
     * up to the specified number of retries.
     * </p>
     * <p>
     * If a response is received from the DHCP daemon it is validated to
     * ensure that:
     * </p>
     * <ul>
     * <li>The DHCP response packet was sent from the remote host to which the
     * original request packet was directed.</li>
     * <li>The XID of the DHCP response packet matches the XID of the original
     * DHCP request packet.</li>
     * </ul>
     * <p>
     * If the response validates 'true' is returned. Otherwise the request is
     * resent until max retry count is exceeded.
     * </p>
     * <p>
     * Before returning, a client disconnect message (remote host field set to
     * zero) is sent to the DHCP daemon.
     * </p>
     * 
     * @return response time in milliseconds if the specified host responded
     *         with a valid DHCP offer datagram within the context of the
     *         specified timeout and retry values or negative one (-1)
     *         otherwise.
     */
static long isServer(InetAddress host, long timeout, int retries) throws IOException {
    boolean isDhcpServer = false;
    // List of DHCP queries to try. The default when extended
    // mode = false must be listed first. (DISCOVER)
    byte[] typeList = { (byte) DHCPMessage.DISCOVER, (byte) DHCPMessage.INFORM, (byte) DHCPMessage.REQUEST };
    String[] typeName = { "DISCOVER", "INFORM", "REQUEST" };
    DhcpdConfigFactory dcf = DhcpdConfigFactory.getInstance();
    if (!paramsChecked) {
        String s_extendedMode = dcf.getExtendedMode();
        if (s_extendedMode == null) {
            extendedMode = false;
        } else {
            extendedMode = Boolean.parseBoolean(s_extendedMode);
        }
        LOG.debug("isServer: DHCP extended mode is {}", extendedMode);
        String hwAddressStr = dcf.getMacAddress();
        LOG.debug("isServer: DHCP query hardware/MAC address is {}", hwAddressStr);
        setHwAddress(hwAddressStr);
        String myIpStr = dcf.getMyIpAddress();
        LOG.debug("isServer: DHCP relay agent address is {}", myIpStr);
        if (myIpStr == null || myIpStr.equals("") || myIpStr.equalsIgnoreCase("broadcast")) {
        // do nothing
        } else {
            try {
                InetAddressUtils.toIpAddrBytes(myIpStr);
                s_myIpAddress = setIpAddress(myIpStr);
                relayMode = true;
            } catch (IllegalArgumentException e) {
                LOG.warn("isServer: DHCP relay agent address is invalid: {}", myIpStr);
            }
        }
        if (extendedMode == true) {
            String requestStr = dcf.getRequestIpAddress();
            LOG.debug("isServer: REQUEST query target is {}", requestStr);
            if (requestStr == null || requestStr.equals("") || requestStr.equalsIgnoreCase("targetSubnet")) {
            // do nothing
            } else if (requestStr.equalsIgnoreCase("targetHost")) {
                targetOffset = false;
            } else {
                try {
                    InetAddressUtils.toIpAddrBytes(requestStr);
                    s_requestIpAddress = setIpAddress(requestStr);
                    reqTargetIp = false;
                    targetOffset = false;
                } catch (IllegalArgumentException e) {
                    LOG.warn("isServer: REQUEST query target is invalid: {}", requestStr);
                }
            }
            LOG.debug("REQUEST query options are: reqTargetIp = {}, targetOffset = {}", reqTargetIp, targetOffset);
        }
        paramsChecked = true;
    }
    int j = 1;
    if (extendedMode == true) {
        j = typeList.length;
    }
    if (timeout < 500) {
        timeout = 500;
    }
    Poller p = new Poller(timeout);
    long responseTime = -1;
    try {
        pollit: for (int i = 0; i < j; i++) {
            Message ping = getPollingRequest(host, (byte) typeList[i]);
            int rt = retries;
            while (rt >= 0 && !isDhcpServer) {
                LOG.debug("isServer: sending DHCP {} query to host {} with Xid: {}", typeName[i], InetAddressUtils.str(host), ping.getMessage().getXid());
                long start = System.currentTimeMillis();
                p.m_outs.writeObject(ping);
                long end;
                do {
                    Message resp = null;
                    try {
                        resp = (Message) p.m_ins.readObject();
                    } catch (InterruptedIOException ex) {
                        resp = null;
                    }
                    if (resp != null) {
                        responseTime = System.currentTimeMillis() - start;
                        // DEBUG only
                        LOG.debug("isServer: got a DHCP response from host {} with Xid: {}", InetAddressUtils.str(resp.getAddress()), resp.getMessage().getXid());
                        if (host.equals(resp.getAddress()) && ping.getMessage().getXid() == resp.getMessage().getXid()) {
                            // Inspect response message to see if it is a valid DHCP response
                            byte[] type = resp.getMessage().getOption(MESSAGE_TYPE);
                            if (type[0] == DHCPMessage.OFFER) {
                                LOG.debug("isServer: got a DHCP OFFER response, validating...");
                            } else if (type[0] == DHCPMessage.ACK) {
                                LOG.debug("isServer: got a DHCP ACK response, validating...");
                            } else if (type[0] == DHCPMessage.NAK) {
                                LOG.debug("isServer: got a DHCP NAK response, validating...");
                            }
                            // accept offer or ACK or NAK
                            if (type[0] == DHCPMessage.OFFER || (extendedMode == true && (type[0] == DHCPMessage.ACK || type[0] == DHCPMessage.NAK))) {
                                LOG.debug("isServer: got a valid DHCP response. responseTime= {}ms", responseTime);
                                isDhcpServer = true;
                                break pollit;
                            }
                        }
                    }
                    end = System.currentTimeMillis();
                } while ((end - start) < timeout);
                if (!isDhcpServer) {
                    LOG.debug("Timed out waiting for DHCP response, remaining retries: {}", rt);
                }
                --rt;
            }
        }
        LOG.debug("Sending disconnect request");
        p.m_outs.writeObject(getDisconnectRequest());
        LOG.debug("wait half a sec before closing connection");
        Thread.sleep(500);
        p.close();
    } catch (IOException ex) {
        LOG.error("IO Exception caught.", ex);
        p.close();
        throw ex;
    } catch (Throwable t) {
        LOG.error("Unexpected Exception caught.", t);
        p.close();
        throw new UndeclaredThrowableException(t);
    }
    // server or -1 if the remote box is NOT a DHCP server.
    if (isDhcpServer) {
        return responseTime;
    } else {
        return -1;
    }
}
Also used : InterruptedIOException(java.io.InterruptedIOException) DHCPMessage(edu.bucknell.net.JDHCP.DHCPMessage) DhcpdConfigFactory(org.opennms.netmgt.config.dhcpd.DhcpdConfigFactory) IOException(java.io.IOException) InterruptedIOException(java.io.InterruptedIOException) UndeclaredThrowableException(java.lang.reflect.UndeclaredThrowableException)

Example 2 with DhcpdConfigFactory

use of org.opennms.netmgt.config.dhcpd.DhcpdConfigFactory in project opennms by OpenNMS.

the class Dhcpd method onStart.

/**
     * <p>onStart</p>
     */
@Override
protected void onStart() {
    boolean relayMode = false;
    LOG.debug("start: DHCP client daemon starting...");
    // Only allow start to be called once.
    if (m_worker != null && m_worker.isAlive()) {
        throw new IllegalStateException("The server is already running");
    }
    // Unless the worker has died, then stop and continue
    if (m_worker != null) {
        stop();
    }
    // the client list
    m_clients = Collections.synchronizedList(new LinkedList<Client>());
    // load the dhcpd configuration
    DhcpdConfigFactory dFactory = null;
    try {
        DhcpdConfigFactory.reload();
        dFactory = DhcpdConfigFactory.getInstance();
    } catch (Exception ex) {
        LOG.error("Failed to load dhcpd configuration", ex);
        throw new UndeclaredThrowableException(ex);
    }
    //
    try {
        LOG.debug("start: listening on TCP port {} for incoming client requests.", dFactory.getPort());
        m_server = new ServerSocket(dFactory.getPort(), 0, InetAddressUtils.addr("127.0.0.1"));
    } catch (IOException ex) {
        if (ex instanceof java.net.BindException) {
            LOG.error("Failed to listen on DHCP port, perhaps something else is already listening?", ex);
            LOG.error("Failed to listen on DHCP port, perhaps something else is already listening?", ex);
        } else {
            LOG.error("Failed to initialize DHCP socket", ex);
        }
        throw new UndeclaredThrowableException(ex);
    }
    // see if we have a valid relay address
    String myIpStr = DhcpdConfigFactory.getInstance().getMyIpAddress();
    LOG.debug("Checking string \"{}\" to see if we have an IP address", myIpStr);
    if (myIpStr != null && !myIpStr.equals("") && !myIpStr.equalsIgnoreCase("broadcast")) {
        try {
            InetAddressUtils.toIpAddrBytes(myIpStr);
            relayMode = true;
        } catch (IllegalArgumentException e) {
            LOG.warn("Invalid format for IP address: {}", myIpStr);
        }
    }
    LOG.debug("Setting relay mode {}", relayMode);
    // open the receiver socket(s)
    if (!relayMode || (dFactory.getExtendedMode() != null && dFactory.getExtendedMode().equalsIgnoreCase("true"))) {
        try {
            LOG.debug("start: starting receiver thread for port 68");
            m_listener = new Receiver(m_clients);
            m_listener.start();
        } catch (IOException ex) {
            try {
                m_server.close();
            } catch (IOException ex1) {
            }
            throw new UndeclaredThrowableException(ex);
        }
    }
    if (relayMode) {
        try {
            LOG.debug("start: starting receiver thread for port 67");
            m_listener2 = new Receiver2(m_clients);
            m_listener2.start();
        } catch (IOException ex) {
            try {
                m_server.close();
            } catch (IOException ex1) {
            }
            throw new UndeclaredThrowableException(ex);
        }
    }
    m_worker = new Thread(this, getName());
    m_worker.start();
}
Also used : DhcpdConfigFactory(org.opennms.netmgt.config.dhcpd.DhcpdConfigFactory) ServerSocket(java.net.ServerSocket) IOException(java.io.IOException) InterruptedIOException(java.io.InterruptedIOException) LinkedList(java.util.LinkedList) IOException(java.io.IOException) InterruptedIOException(java.io.InterruptedIOException) UndeclaredThrowableException(java.lang.reflect.UndeclaredThrowableException) UndeclaredThrowableException(java.lang.reflect.UndeclaredThrowableException)

Aggregations

IOException (java.io.IOException)2 InterruptedIOException (java.io.InterruptedIOException)2 UndeclaredThrowableException (java.lang.reflect.UndeclaredThrowableException)2 DhcpdConfigFactory (org.opennms.netmgt.config.dhcpd.DhcpdConfigFactory)2 DHCPMessage (edu.bucknell.net.JDHCP.DHCPMessage)1 ServerSocket (java.net.ServerSocket)1 LinkedList (java.util.LinkedList)1