All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jvnet.hudson.proxy_dhcp.DHCPPacket Maven / Gradle / Ivy

The newest version!
package org.jvnet.hudson.proxy_dhcp;

import static org.jvnet.hudson.proxy_dhcp.DHCPOption.*;
import org.jvnet.hudson.pxeboot.DataInputStream2;
import org.jvnet.hudson.pxeboot.DataOutputStream2;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.Inet4Address;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * Represents a DHCP packet.
 *
 * @author Kohsuke Kawaguchi
 * @see RFC 2131 (http://www.ietf.org/rfc/rfc2131.txt)
 */
public class DHCPPacket {
    public byte op;        // message opcode
    public byte htype;
    public byte hlen;
    public byte hops;
    public int xid;
    public short secs;
    public short flags;

    public Inet4Address ciaddr; // 4 bytes each
    public Inet4Address yiaddr;
    public Inet4Address siaddr;
    public Inet4Address giaddr;

    public byte[] chaddr;   // 16 bytes
    public String sname;    // null-terminated 64 bytes
    public String file;     // null-terminated 128 bytes

    // 4 magic bytes here. see OPTIONS_COOKIE

    public List options = new ArrayList();

    /**
     * First 4 bytes of the options field  is this value
     */
    private static final byte[] OPTIONS_COOKIE = {99, (byte)130, 83, 99};

    public static final byte OP_BOOTREQUEST = 1;
    public static final byte OP_BOOTREPLY = 2;

    /**
     * Creates an empty packet.
     */
    public DHCPPacket() {
    }

    /**
     * Populates a packet from {@link DatagramPacket}.
     *
     * @throws IllegalArgumentException
     *      If the packet is not a DHCP packet.
     */
    public DHCPPacket(DatagramPacket p) throws IOException {
        DataInputStream2 di = new DataInputStream2(p);
        op = di.readByte();
        htype = di.readByte();
        hlen = di.readByte();
        hops = di.readByte();

        xid = di.readInt();
        secs = di.readShort();
        flags = di.readShort();

        ciaddr = di.readInet4Address();
        yiaddr = di.readInet4Address();
        siaddr = di.readInet4Address();
        giaddr = di.readInet4Address();

        chaddr = new byte[16];
        di.readFully(chaddr);

        sname = di.readFixedLengthNullTerminatedString(64);
        file = di.readFixedLengthNullTerminatedString(128);

        byte[] magic = di.readByteArray(4);
        if(!Arrays.equals(magic,OPTIONS_COOKIE))
            throw new IllegalArgumentException("Not a valid DHCP packet: incorrect magic value");

        while(di.available()>0) {   // available() isn't guaranteed to work on InputStream level, but ByteArrayInputStream implements it correctly
            DHCPOption opt = new DHCPOption(di);
            if(opt.isEnd())     return;
            options.add(opt);
        }
    }

    /**
     * Finds a DHCP option of the given tag
     */
    public DHCPOption getOption(byte tag) {
        for (DHCPOption option : options)
            if(option.tag==tag)
                return option;
        return null;
    }

    /**
     * Is this a DHCP message of the given type.
     */
    public boolean is(DHCPMessageType type) {
        DHCPOption o = getOption(OPTION_DHCP_MESSAGE_TYPE);
        return o!=null && type.code==o.data[0];
    }

    public String getVendorClassIdentifier() {
        DHCPOption o = getOption(OPTION_VENDOR_CLASS_IDENTIFIER);
        if(o==null) return null;
        return o.getDataAsString();
    }

    public DHCPPacket createResponse() {
        DHCPPacket that = new DHCPPacket();
        that.op = OP_BOOTREPLY;
        that.htype = this.htype;
        that.hlen = this.hlen;
        that.xid = this.xid;
        that.flags = this.flags;

        return that;
    }

    /**
     * Package a packet into {@link DatagramPacket}
     */
    public DatagramPacket pack() throws IOException {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        DataOutputStream2 o = new DataOutputStream2(baos);

        o.writeByte(op);
        o.writeByte(htype);
        o.writeByte(hlen);
        o.writeByte(hops);

        o.writeInt(xid);
        o.writeShort(secs);
        o.writeShort(flags);

        o.writeAddress(ciaddr);
        o.writeAddress(yiaddr);
        o.writeAddress(siaddr);
        o.writeAddress(giaddr);

        o.write(chaddr);

        o.writeFixedLengthNullTerminatedString(sname,64);
        o.writeFixedLengthNullTerminatedString(file,128);

        o.write(OPTIONS_COOKIE);

        for (DHCPOption opt : options)
            opt.writeTo(o);

        // end with the end option
        o.writeByte(OPTION_END);


        byte[] buf = baos.toByteArray();
        return new DatagramPacket(buf,buf.length);
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy