ipv4header.java

来自「纯java操作系统jnode,安装简单和操作简单的个人使用的Java操作系统」· Java 代码 · 共 377 行

JAVA
377
字号
/*
 * $Id: IPv4Header.java,v 1.1 2003/11/25 11:52:24 epr Exp $
 */
package org.jnode.net.ipv4;

import org.jnode.net.NetworkLayerHeader;
import org.jnode.net.ProtocolAddress;
import org.jnode.net.SocketBuffer;

/**
 * @author epr
 */
public class IPv4Header implements NetworkLayerHeader, IPv4Constants {

	/** IP version */
	private int version;
	/** Length of header in bytes */
	private int hdrlength;
	/** Type of service */
	private int tos;
	/** Length of message data in bytes (without this IP header) */
	private int dataLength;
	/** Identification */
	private int identification;
	/** Fragment offset */
	private int fragmentOffset;
	/** Time to live */
	private int ttl;
	/** Protocol ID */
	private int protocol;
	/** Source address */
	private IPv4Address srcAddress;
	/** Destination address */
	private IPv4Address dstAddress;
	/** Checksum is ok */
	private final boolean checksumOk;

	/**
	 * Create a new instance
	 * @param tos
	 * @param ttl
	 * @param protocol
	 * @param dstAddress
	 */
	public IPv4Header(int tos, int ttl, int protocol, IPv4Address dstAddress, int dataLength) {
		if (dstAddress == null) {
			throw new IllegalArgumentException("dstAddress cannot be null");
		}
		this.version = 4;
		this.tos = tos;
		this.ttl = ttl;
		this.protocol = protocol;
		this.dstAddress = dstAddress;
		this.hdrlength = 20;
		this.dataLength = dataLength;
		this.checksumOk = true; // For this constructor not relevant
	}
	
	/**
	 * Create a new instance, read the header from the given buffer
	 * @param skbuf
	 */
	public IPv4Header(SocketBuffer skbuf) {
		final int b0 = skbuf.get(0);
		this.version = (b0 >> 4) & 0x0f;
		this.hdrlength = (b0 & 0x0f) * 4;
		this.tos = skbuf.get(1);
		this.dataLength = skbuf.get16(2) - hdrlength;
		this.identification = skbuf.get16(4);
		this.fragmentOffset = skbuf.get16(6);
		this.ttl = skbuf.get(8);
		this.protocol = skbuf.get(9);
		//final int checksum = skbuf.get16(10);
		this.srcAddress = new IPv4Address(skbuf, 12);
		this.dstAddress = new IPv4Address(skbuf, 16);
		
		final int ccs = IPv4Utils.calcChecksum(skbuf, 0, hdrlength);
		checksumOk = (ccs == 0/*0xFFFF*/);
		//Syslog.debug("TEST: ccs=0x" + NumberUtils.hex(ccs, 4));
	}
	
	/**
	 * Create a clone of the given header
	 * @param src
	 */
	public IPv4Header(IPv4Header src) {
		this.version = src.version;
		this.hdrlength = src.hdrlength;
		this.tos = src.tos;
		this.dataLength = src.dataLength;
		this.identification = src.identification;
		this.fragmentOffset = src.fragmentOffset;
		this.ttl = src.ttl;
		this.protocol = src.protocol;
		this.srcAddress = src.srcAddress;
		this.dstAddress = src.dstAddress;
		this.checksumOk = src.checksumOk;
	}


	/**
	 * Prefix this header to the front of the given buffer
	 * @param skbuf
	 */
	public void prefixTo(SocketBuffer skbuf) {
		skbuf.insert(hdrlength);
		skbuf.set(0, ((version << 4) & 0xf0) | ((hdrlength / 4) & 0xf));
		skbuf.set(1, tos);
		skbuf.set16(2, dataLength + hdrlength);
		skbuf.set16(4, identification);
		skbuf.set16(6, fragmentOffset);
		skbuf.set(8, ttl);
		skbuf.set(9, protocol);
		skbuf.set(10, 0); // checksum, calculate and set later
		srcAddress.writeTo(skbuf, 12);
		dstAddress.writeTo(skbuf, 16);
		// calculate and set checksum
		final int ccs = IPv4Utils.calcChecksum(skbuf, 0, hdrlength);
		if (ccs == 0) {
			skbuf.set(10, 0xffff);
		} else {
			skbuf.set16(10, ccs);
		}

		//final int ccs2 = IPv4Utils.calcChecksum(skbuf, 0, hdrlength);
		//Syslog.debug("TEST: ccs=0x" + NumberUtils.hex(ccs, 4) + ", ccs2=0x" + NumberUtils.hex(ccs2, 4) + ", hdrlength=" + hdrlength);
	}
	
	
	/**
	 * Finalize the header in the given buffer.
	 * This method is called when all layers have set their header data
	 * and can be used e.g. to update checksum values.
	 * 
	 * @param skbuf The buffer
	 * @param offset The offset to the first byte (in the buffer) of this header (since low layer headers are already prefixed)
	 */
	public void finalizeHeader(SocketBuffer skbuf, int offset) {
		// Nothing to do
	}

	/**
	 * Gets the source address of the packet described in this header 
	 */
	public ProtocolAddress getSourceAddress() {
		return srcAddress;
	}

	/**
	 * Gets the source address of the packet described in this header 
	 */
	public ProtocolAddress getDestinationAddress() {
		return dstAddress;
	}
	
	/**
	 * Gets the destination
	 */
	public IPv4Address getDestination() {
		return dstAddress;
	}

	/**
	 * Is the don't fragment flag set?
	 */
	public boolean isDontFragment() {
		return ((fragmentOffset & IP_DF) != 0);
	}

	/**
	 * Is the more fragments flag set?
	 */
	public boolean hasMoreFragments() {
		return ((fragmentOffset & IP_MF) != 0);
	}

	/**
	 * Is this a fragment. That is, the MF flag is set, or fragment offset
	 * is greater then 0.
	 */
	public boolean isFragment() {
		return (((fragmentOffset & IP_MF) != 0) ||
				 ((fragmentOffset & IP_FRAGOFS_MASK) != 0));
	}

	/**
	 * Gets the offset of this fragment in the IP packet
	 */
	public int getFragmentOffset() {
		return (fragmentOffset & 0x1FFF) << 3;
	}
	
	/**
	 * Gets the key used to find the correct fragment list.
	 * This key contains:
	 * identification, protocol, srcAddress, dstAddress
	 */
	public Object getFragmentListKey() {
		final StringBuffer b = new StringBuffer();
		b.append(identification);
		b.append('-');
		b.append(protocol);
		b.append('-');
		b.append(srcAddress);
		b.append('-');
		b.append(dstAddress);
		return b.toString();
	}

	/**
	 * Set the fragment offset (not the DF & MF bits)
	 * @param i
	 */
	public void setFragmentOffset(int i) {
		fragmentOffset &= ~IP_FRAGOFS_MASK;
		fragmentOffset |= ((i >> 3) & IP_FRAGOFS_MASK);
	}
	
	/**
	 * Sets the don't fragment flag
	 */
	public void setDontFragment(boolean on) {
		if (on) {
			fragmentOffset |= IP_DF;
		} else {
			fragmentOffset &= ~IP_DF;
		}
	}

	/**
	 * Sets the more fragments flag
	 */
	public void setMoreFragments(boolean on) {
		if (on) {
			fragmentOffset |= IP_MF;
		} else {
			fragmentOffset &= ~IP_MF;
		}
	}

	/**
	 * Get the header length
	 */
	public int getLength() {
		return hdrlength;
	}

	/**
	 * Gets the identification number
	 */
	public int getIdentification() {
		return identification;
	}

	/**
	 * Gets the length of the header and data
	 */
	public int getTotalLength() {
		return dataLength + hdrlength;
	}

	/**
	 * Gets the length of the data (without the IP header)
	 */
	public int getDataLength() {
		return dataLength;
	}

	/**
	 * Gets the protocol
	 */
	public int getProtocol() {
		return protocol;
	}

	/**
	 * Gets the source address
	 */
	public IPv4Address getSource() {
		return srcAddress;
	}

	/**
	 * Gets the type of service attribute
	 */
	public int getTos() {
		return tos;
	}

	/**
	 * Gets the time to live attribute
	 */
	public int getTtl() {
		return ttl;
	}

	/**
	 * Gets the IP version
	 */
	public int getVersion() {
		return version;
	}

	/**
	 * Sets the destination address
	 * @param address
	 */
	public void setDestination(IPv4Address address) {
		dstAddress = address;
	}

	/**
	 * Sets the identification number
	 * @param i
	 */
	public void setIdentification(int i) {
		identification = i;
	}

	/**
	 * Sets the length of the data in bytes
	 * @param i
	 */
	public void setDataLength(int i) {
		dataLength = i;
	}

	/**
	 * Sets the protocol
	 * @param i
	 */
	public void setProtocol(int i) {
		protocol = i;
	}

	/**
	 * Sets the source address
	 * @param address
	 */
	public void setSource(IPv4Address address) {
		srcAddress = address;
	}

	/**
	 * Sets the type of service
	 * @param i
	 */
	public void setTos(int i) {
		tos = i;
	}

	/**
	 * Sets the time to live
	 * @param i
	 */
	public void setTtl(int i) {
		ttl = i;
	}

	/**
	 * Is the checksum valid
	 */
	public boolean isChecksumOk() {
		return checksumOk;
	}
	
	/**
	 * Swap the source and destination address
	 */
	public void swapAddresses() {
		final IPv4Address tmp = dstAddress;
		this.dstAddress = this.srcAddress;
		this.srcAddress = tmp;
	}

}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?