/* * $Id$ * * Copyright (C) 2003-2015 JNode.org * * 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.jnode.net.ipv4.bootp; import org.jnode.net.HardwareAddress; import org.jnode.net.SocketBuffer; import org.jnode.net.ethernet.EthernetAddress; import org.jnode.net.ipv4.IPv4Address; import java.io.UnsupportedEncodingException; import java.net.DatagramPacket; import java.net.Inet4Address; /** * @author epr * @author markhale */ public class BOOTPHeader { /** * Size of the BOOTP header (236 bytes) */ public static final int SIZE = 236; /** * Client to server message */ public static final int BOOTREQUEST = 1; /** * Server to client message */ public static final int BOOTREPLY = 2; private final int opcode; private final int hwType; private final int hopCount; private final int transactionID; private final int secondsElapsed; private final int flags; private final HardwareAddress clientHwAddress; private final Inet4Address clientIPAddress; private final Inet4Address yourIPAddress; private final Inet4Address serverIPAddress; private final Inet4Address gatewayIPAddress; private String serverHostName; private String bootFileName; private static String asciiBytesToString(byte[] asciiBytes) { try { return new String(asciiBytes, "US-ASCII"); } catch (UnsupportedEncodingException ex) { throw new RuntimeException(ex); } } private static byte[] stringToAsciiBytes(String str) { try { return str.getBytes("US-ASCII"); } catch (UnsupportedEncodingException ex) { throw new RuntimeException(ex); } } /** * Create a new header and read it from the given buffer * * @param skbuf */ public BOOTPHeader(SocketBuffer skbuf) { this.opcode = skbuf.get(0); this.hwType = skbuf.get(1); this.hopCount = skbuf.get(3); this.transactionID = skbuf.get32(4); this.secondsElapsed = skbuf.get16(8); this.flags = skbuf.get16(10); this.clientIPAddress = IPv4Address.readFrom(skbuf, 12); this.yourIPAddress = IPv4Address.readFrom(skbuf, 16); this.serverIPAddress = IPv4Address.readFrom(skbuf, 20); this.gatewayIPAddress = IPv4Address.readFrom(skbuf, 24); if (hwType == 1) { clientHwAddress = new EthernetAddress(skbuf, 28); } else { clientHwAddress = null; } byte[] tmp = new byte[128]; skbuf.get(tmp, 0, 32, 64); serverHostName = asciiBytesToString(tmp).trim(); skbuf.get(tmp, 0, 96, 128); bootFileName = asciiBytesToString(tmp).trim(); } /** * Create a new header and read it from the given packet * * @param packet */ public BOOTPHeader(DatagramPacket packet) { this(new SocketBuffer(packet.getData(), packet.getOffset(), packet.getLength())); } /** * Create a new header (for client usage) * * @param opcode * @param transactionID * @param secsElapsed * @param clientIPAddress * @param clientHwAddress */ public BOOTPHeader(int opcode, int transactionID, int secsElapsed, Inet4Address clientIPAddress, HardwareAddress clientHwAddress) { this.opcode = opcode; this.hwType = clientHwAddress.getType(); this.hopCount = 0; this.transactionID = transactionID; this.secondsElapsed = secsElapsed; this.flags = 0; this.clientIPAddress = clientIPAddress; this.yourIPAddress = null; this.serverIPAddress = null; this.gatewayIPAddress = null; this.clientHwAddress = clientHwAddress; } /** * Create a new header (for server usage) * * @param opcode * @param transactionID * @param secsElapsed * @param clientIPAddress * @param yourIPAddress * @param serverIPAddress * @param clientHwAddress */ public BOOTPHeader(int opcode, int transactionID, int secsElapsed, Inet4Address clientIPAddress, Inet4Address yourIPAddress, Inet4Address serverIPAddress, HardwareAddress clientHwAddress) { this.opcode = opcode; this.hwType = clientHwAddress.getType(); this.hopCount = 0; this.transactionID = transactionID; this.secondsElapsed = secsElapsed; this.flags = 0; this.clientIPAddress = clientIPAddress; this.yourIPAddress = yourIPAddress; this.serverIPAddress = serverIPAddress; this.gatewayIPAddress = null; this.clientHwAddress = clientHwAddress; } /** * Prefix this header to the given buffer * * @param skbuf */ public void prefixTo(SocketBuffer skbuf) { skbuf.insert(SIZE); skbuf.set(0, opcode); skbuf.set(1, hwType); skbuf.set(2, clientHwAddress.getLength()); skbuf.set(3, hopCount); skbuf.set32(4, transactionID); skbuf.set16(8, secondsElapsed); skbuf.set16(10, flags); if (clientIPAddress != null) { IPv4Address.writeTo(skbuf, 12, clientIPAddress); } if (yourIPAddress != null) { IPv4Address.writeTo(skbuf, 16, yourIPAddress); } if (serverIPAddress != null) { IPv4Address.writeTo(skbuf, 20, serverIPAddress); } if (gatewayIPAddress != null) { IPv4Address.writeTo(skbuf, 24, gatewayIPAddress); } if (clientHwAddress != null) { clientHwAddress.writeTo(skbuf, 28); } if (serverHostName != null) { skbuf.set(32, stringToAsciiBytes(serverHostName), 0, serverHostName.length()); } if (bootFileName != null) { skbuf.set(96, stringToAsciiBytes(bootFileName), 0, bootFileName.length()); } } /** * The server host name should not exceed 63 characters (bytes). */ public void setServerHostName(String sname) { if (sname != null && sname.length() > 63) throw new IllegalArgumentException( "Server host name is too long, " + sname.length() + " > 63."); serverHostName = sname; } public String getServerHostName() { return serverHostName; } /** * The boot file name should not exceed 127 characters (bytes). */ public void setBootFileName(String file) { if (file != null && file.length() > 127) throw new IllegalArgumentException("Boot file name is too long, " + file.length() + " > 127."); bootFileName = file; } public String getBootFileName() { return bootFileName; } /** * Gets the client hardware address */ public HardwareAddress getClientHwAddress() { return clientHwAddress; } /** * Gets the client IP address */ public Inet4Address getClientIPAddress() { return clientIPAddress; } /** * Gets the gateway IP address */ public Inet4Address getGatewayIPAddress() { return gatewayIPAddress; } /** * Gets the hop count */ public int getHopCount() { return hopCount; } /** * Gets the hardware type */ public int getHwType() { return hwType; } /** * Gets the opcode */ public int getOpcode() { return opcode; } /** * Gets the server IP address */ public Inet4Address getServerIPAddress() { return serverIPAddress; } /** * Gets the transaction ID */ public int getTransactionID() { return transactionID; } /** * Gets the seconds elapsed since the client began the address acquisition or renewal process */ public int getTimeElapsedSecs() { return secondsElapsed; } /** * Gets <em>your</em> IP address */ public Inet4Address getYourIPAddress() { return yourIPAddress; } }