/** * getRanges * * @return a {@link java.util.List} object. */ public List<IPPollRange> getRanges() { final List<IPPollRange> includes = new LinkedList<IPPollRange>(); getReadLock().lock(); try { Long defaultTimeout = null; Integer defaultRetries = null; if (getConfiguration().hasTimeout()) defaultTimeout = getConfiguration().getTimeout(); if (getConfiguration().hasRetries()) defaultRetries = getConfiguration().getRetries(); for (final IncludeRange ir : getConfiguration().getIncludeRangeCollection()) { // Validate IP range; if invalid, then log and discard this range try { InetAddressUtils.toIpAddrBytes(ir.getBegin()); } catch (Throwable e) { LogUtils.warnf( this, "Begin address of discovery range is invalid, discarding: %s", ir.getBegin()); continue; } try { InetAddressUtils.toIpAddrBytes(ir.getEnd()); } catch (Throwable e) { LogUtils.warnf( this, "End address of discovery range is invalid, discarding: %s", ir.getEnd()); continue; } long timeout = 800L; if (ir.hasTimeout()) { timeout = ir.getTimeout(); } else if (defaultTimeout != null) { timeout = defaultTimeout; } int retries = 3; if (ir.hasRetries()) { retries = ir.getRetries(); } else if (defaultRetries != null) { retries = defaultRetries; } try { includes.add(new IPPollRange(ir.getBegin(), ir.getEnd(), timeout, retries)); } catch (final UnknownHostException uhE) { LogUtils.warnf( this, uhE, "Failed to convert address range (%s, %s)", ir.getBegin(), ir.getEnd()); } } return includes; } finally { getReadLock().unlock(); } }
/** * 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; } }