Ejemplo n.º 1
0
  /**
   * Constructor. Establishes a TCP socket connection with the DHCP client daemon on port 5818.
   *
   * @throws IOException if unable to establish the connection with the DHCP client daemon.
   */
  private Poller(long timeout) throws IOException {
    DhcpdConfigFactory dcf = DhcpdConfigFactory.getInstance();
    try {
      LOG.debug(
          "Poller.ctor: opening socket connection with DHCP client daemon on port {}",
          dcf.getPort());
      m_connection = new Socket(InetAddressUtils.addr("127.0.0.1"), dcf.getPort());

      LOG.debug("Poller.ctor: setting socket timeout to {}", timeout);
      m_connection.setSoTimeout((int) timeout);

      // Establish input/output object streams
      m_ins = new ObjectInputStream(m_connection.getInputStream());
      m_outs = new ObjectOutputStream(m_connection.getOutputStream());
      m_outs.reset();
      m_outs.flush();
    } catch (IOException ex) {
      LOG.error("IO Exception during socket connection establishment with DHCP client daemon.", ex);
      if (m_connection != null) {
        try {
          m_ins.close();
          m_outs.close();
          m_connection.close();
        } catch (Throwable t) {
        }
      }
      throw ex;
    } catch (Throwable t) {
      LOG.error(
          "Unexpected exception during socket connection establishment with DHCP client daemon.",
          t);
      if (m_connection != null) {
        try {
          m_ins.close();
          m_outs.close();
          m_connection.close();
        } catch (Throwable tx) {
        }
      }
      throw new UndeclaredThrowableException(t);
    }
  }
Ejemplo n.º 2
0
  /**
   * This method actually tests the remote host to determine if it is running a functional DHCP
   * server.
   *
   * <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>If a response is received from the DHCP daemon it is validated to ensure that:
   *
   * <ul>
   *   <li>The DHCP response packet was sent from the remote host to which the original request
   *       packet was directed.
   *   <li>The XID of the DHCP response packet matches the XID of the original DHCP request packet.
   * </ul>
   *
   * <p>If the response validates 'true' is returned. Otherwise the request is resent until max
   * retry count is exceeded.
   *
   * <p>Before returning, a client disconnect message (remote host field set to zero) is sent to the
   * DHCP daemon.
   *
   * @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);
    }

    // Return response time if the remote box IS a DHCP
    // server or -1 if the remote box is NOT a DHCP server.
    if (isDhcpServer) {
      return responseTime;
    } else {
      return -1;
    }
  }