📄 dhcpresponsefactory.java
字号:
/*
* This file is part of dhcp4java, a DHCP API for the Java language.
* (c) 2006 Stephan Hadinger
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package org.dhcp4java;
import static org.dhcp4java.DHCPConstants.*;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.util.logging.Logger;
/**
* This class provides some standard factories for DHCP responses.
*
* <p>This simplifies DHCP Server development as basic behaviour is already usable
* as-is.
*
* @author Stephan Hadinger
* @version 1.00
*
*/
public final class DHCPResponseFactory {
// Suppresses default constructor, ensuring non-instantiability.
private DHCPResponseFactory() {
throw new UnsupportedOperationException();
}
@SuppressWarnings("unused")
private static final Logger logger = Logger.getLogger(DHCPResponseFactory.class.getName().toLowerCase());
/**
* Create a populated DHCPOFFER response.
*
* <p>Reponse is populated according to the DHCP request received (must be
* DHCPDISCOVER), the proposed client address and a set of pre-set options.
*
* <p>Note: <tt>getDefaultSocketAddress</tt> is called internally to populate
* address and port number to which response should be sent.
*
* @param request
* @param offeredAddress
* @param options
* @return the newly created OFFER Packet
*/
public static final DHCPPacket makeDHCPOffer(
DHCPPacket request,
InetAddress offeredAddress,
int leaseTime,
InetAddress serverIdentifier,
String message,
DHCPOption[] options) {
// check request
if (request == null) {
throw new NullPointerException("request is null");
}
if (!request.isDhcp()) {
throw new DHCPBadPacketException("request is BOOTP");
}
Byte requestMessageType = request.getDHCPMessageType();
if (requestMessageType == null) {
throw new DHCPBadPacketException("request has no message type");
}
if (requestMessageType != DHCPDISCOVER) {
throw new DHCPBadPacketException("request is not DHCPDISCOVER");
}
// check offeredAddress
if (offeredAddress == null) {
throw new IllegalArgumentException("offeredAddress must not be null");
}
if (!(offeredAddress instanceof Inet4Address)) {
throw new IllegalArgumentException("offeredAddress must be IPv4");
}
DHCPPacket resp = new DHCPPacket();
resp.setOp(BOOTREPLY);
resp.setHtype(request.getHtype());
resp.setHlen(request.getHlen());
// Hops is left to 0
resp.setXid(request.getXid());
// Secs is left to 0
resp.setFlags(request.getFlags());
// Ciaddr is left to 0.0.0.0
resp.setYiaddr(offeredAddress);
// Siaddr ?
resp.setGiaddrRaw(request.getGiaddrRaw());
resp.setChaddr(request.getChaddr());
// sname left empty
// file left empty
// we set the DHCPOFFER type
resp.setDHCPMessageType(DHCPOFFER);
// set standard options
resp.setOptionAsInt(DHO_DHCP_LEASE_TIME, leaseTime);
resp.setOptionAsInetAddress(DHO_DHCP_SERVER_IDENTIFIER, serverIdentifier);
resp.setOptionAsString(DHO_DHCP_MESSAGE, message); // if null, it is removed
if (options != null) {
for (DHCPOption opt : options) {
resp.setOption(opt.applyOption(request));
}
}
// we set address/port according to rfc
resp.setAddrPort(getDefaultSocketAddress(request, DHCPOFFER));
return resp;
}
/**
* Create a populated DHCPACK response.
*
* <p>Reponse is populated according to the DHCP request received (must be
* DHCPREQUEST), the proposed client address and a set of pre-set options.
*
* <p>Note: <tt>getDefaultSocketAddress</tt> is called internally to populate
* address and port number to which response should be sent.
*
* @param request
* @param offeredAddress
* @param options
* @return the newly created ACK Packet
*/
public static final DHCPPacket makeDHCPAck(
DHCPPacket request,
InetAddress offeredAddress,
int leaseTime,
InetAddress serverIdentifier,
String message,
DHCPOption[] options) {
// check request
if (request == null) {
throw new NullPointerException("request is null");
}
if (!request.isDhcp()) {
throw new DHCPBadPacketException("request is BOOTP");
}
Byte requestMessageType = request.getDHCPMessageType();
if (requestMessageType == null) {
throw new DHCPBadPacketException("request has no message type");
}
if ((requestMessageType != DHCPREQUEST) &&
(requestMessageType != DHCPINFORM)) {
throw new DHCPBadPacketException("request is not DHCPREQUEST/DHCPINFORM");
}
// check offered address
if (offeredAddress == null) {
throw new IllegalArgumentException("offeredAddress must not be null");
}
if (!(offeredAddress instanceof Inet4Address)) {
throw new IllegalArgumentException("offeredAddress must be IPv4");
}
DHCPPacket resp = new DHCPPacket();
resp.setOp(BOOTREPLY);
resp.setHtype(request.getHtype());
resp.setHlen(request.getHlen());
// Hops is left to 0
resp.setXid(request.getXid());
// Secs is left to 0
resp.setFlags(request.getFlags());
resp.setCiaddrRaw(request.getCiaddrRaw());
if (requestMessageType != DHCPINFORM) {
resp.setYiaddr(offeredAddress);
}
// Siaddr ?
resp.setGiaddrRaw(request.getGiaddrRaw());
resp.setChaddr(request.getChaddr());
// sname left empty
// file left empty
// we set the DHCPOFFER type
resp.setDHCPMessageType(DHCPACK);
// set standard options
if (requestMessageType == DHCPREQUEST) { // rfc 2131
resp.setOptionAsInt(DHO_DHCP_LEASE_TIME, leaseTime);
}
resp.setOptionAsInetAddress(DHO_DHCP_SERVER_IDENTIFIER, serverIdentifier);
resp.setOptionAsString(DHO_DHCP_MESSAGE, message); // if null, it is removed
if (options != null) {
for (DHCPOption opt : options) {
resp.setOption(opt.applyOption(request));
}
}
// we set address/port according to rfc
resp.setAddrPort(getDefaultSocketAddress(request, DHCPACK));
return resp;
}
/**
* Create a populated DHCPNAK response.
*
* <p>Reponse is populated according to the DHCP request received (must be
* DHCPREQUEST), the proposed client address and a set of pre-set options.
*
* <p>Note: <tt>getDefaultSocketAddress</tt> is called internally to populate
* address and port number to which response should be sent.
*
* @param request
* @param serverIdentifier
* @param message
* @return the newly created NAK Packet
*/
public static final DHCPPacket makeDHCPNak(
DHCPPacket request,
InetAddress serverIdentifier,
String message) {
// check request
if (request == null) {
throw new NullPointerException("request is null");
}
if (!request.isDhcp()) {
throw new DHCPBadPacketException("request is BOOTP");
}
Byte requestMessageType = request.getDHCPMessageType();
if (requestMessageType == null) {
throw new DHCPBadPacketException("request has no message type");
}
if (requestMessageType != DHCPREQUEST) {
throw new DHCPBadPacketException("request is not DHCPREQUEST");
}
DHCPPacket resp = new DHCPPacket();
resp.setOp(BOOTREPLY);
resp.setHtype(request.getHtype());
resp.setHlen(request.getHlen());
// Hops is left to 0
resp.setXid(request.getXid());
// Secs is left to 0
resp.setFlags(request.getFlags());
// ciaddr left to 0
// yiaddr left to 0
// Siaddr ?
resp.setGiaddrRaw(request.getGiaddrRaw());
resp.setChaddr(request.getChaddr());
// sname left empty
// file left empty
// we set the DHCPOFFER type
resp.setDHCPMessageType(DHCPNAK);
// set standard options
resp.setOptionAsInetAddress(DHO_DHCP_SERVER_IDENTIFIER, serverIdentifier);
resp.setOptionAsString(DHO_DHCP_MESSAGE, message); // if null, it is removed
// we do not set other options for this type of message
// we set address/port according to rfc
resp.setAddrPort(getDefaultSocketAddress(request, DHCPNAK));
return resp;
}
/**
* Calculates the addres/port to which the response must be sent, according to
* rfc 2131, section 4.1.
*
* <p>This is a method ready to use for *standard* behaviour for any RFC
* compliant DHCP Server.
*
* <p>If <tt>giaddr</tt> is null, it is the client's addres/68, otherwise
* giaddr/67.
*
* <p>Standard behaviour is to set the response packet as follows:
* <pre>
* response.setAddrPort(getDefaultSocketAddress(request), response.getOp());
* </pre>
*
* @param request the client DHCP request
* @param responseType the DHCP Message Type the servers wants to send (DHCPOFFER,
* DHCPACK, DHCPNAK)
* @return the ip/port to send back the response
* @throws IllegalArgumentException if request is <tt>null</tt>.
* @throws IllegalArgumentException if responseType is not valid.
*/
public static InetSocketAddress getDefaultSocketAddress(DHCPPacket request, byte responseType) {
if (request == null) {
throw new IllegalArgumentException("request is null");
}
InetSocketAddress sockAdr;
InetAddress giaddr = request.getGiaddr();
InetAddress ciaddr = request.getCiaddr();
// check whether there is a giaddr
switch (responseType) {
case DHCPOFFER:
case DHCPACK:
if (INADDR_ANY.equals(giaddr)) {
if (INADDR_ANY.equals(ciaddr)) { // broadcast to LAN
sockAdr = new InetSocketAddress(INADDR_BROADCAST, 68);
} else {
sockAdr = new InetSocketAddress(ciaddr, 68);
}
} else { // unicast to relay
sockAdr = new InetSocketAddress(giaddr, 67);
}
break;
case DHCPNAK:
if (INADDR_ANY.equals(giaddr)) { // always broadcast
sockAdr = new InetSocketAddress(INADDR_BROADCAST, 68);
} else { // unicast to relay
sockAdr = new InetSocketAddress(giaddr, 67);
}
break;
default:
throw new IllegalArgumentException("responseType not valid");
}
return sockAdr;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -