/* Copyright (c) 1999 by Inria Lorraine.  All Rights Reserved */

/***
   NAME
     IcmpPacket
   PURPOSE
     
   NOTES
     
   HISTORY
     chelius - Jul 25, 1999: Created.
     $Log: IcmpPacket.java,v $
     Revision 1.1  2000/04/27 13:24:12  sdalu
     ajout jdk1.1

     Revision 1.2  2000/04/03 08:05:33  chelius
     Javadoc

     Revision 1.1.1.1  2000/02/08 16:31:58  chelius
     Initial import

     Revision 1.1.1.1  2000/02/01 11:10:47  chelius
     Mise sous CVS des sources de libnet6 for jdk1.2.*

     Revision 1.1.1.1  1999/07/25 15:01:56  chelius
     First release of the ipv6 packages for java

***/
package java.net;


import java.io.FileDescriptor;
import java.io.IOException;
import java.io.InterruptedIOException;

/**
 * This class represents an ICMP packet. 
 * <p>
 * ICMP packets are used to implement a connectionless ICMP packet 
 * delivery service. Each message is routed from one machine to 
 * another based solely on information contained within that packet. 
 * Multiple packets sent from one machine to another might be routed 
 * differently, and might arrive in any order. 
 *
 * @author  Guillaume Chelius (IPv6 modifications)
 * @version 1.0, 02/04/2000
 * @since   JDK1.2
 */
public final 
class IcmpPacket extends RawPacket {

    /*
     * The fields of this class are package-private since RawPacket 
     * classes needs to access them.
     */
    byte code;
    byte type;

    /**
     * Constructs an <code>IcmpPacket</code> for receiving packets of 
     * length <code>ilength</code>. 
     * <p>
     * The <code>length</code> argument must be less than or equal to 
     * <code>ibuf.length</code>. 
     *
     * @param   ibuf      buffer for holding the incoming datagram.
     * @param   ilength   the number of bytes to read.
     * @param   tvalue    the ICMP type of the packet
     * @since   JDK1.2
     */
    public IcmpPacket(byte ibuf[], int ilength, int tvalue) {
	super(ibuf, ilength);
	setType(tvalue);
    }

    /**
     * Constructs an <code>IcmpPacket</code> for receiving packets of 
     * length <code>ilength</code>. 
     * <p>
     * The <code>length</code> argument must be less than or equal to 
     * <code>ibuf.length</code>. 
     *
     * @param   ibuf      buffer for holding the incoming datagram.
     * @param   ilength   the number of bytes to read.
     * @param   tvalue    the ICMP type of the packet
     * @param   cvalue    the ICMP code of the packet
     * @since   JDK1.2
     */
    public IcmpPacket(byte ibuf[], int ilength, int tvalue, int cvalue) {
	super(ibuf, ilength);
	setType(tvalue, cvalue);
    }
    
    /**
     * Constructs an ICMP packet for sending packets of length 
     * <code>ilength</code> with the specified type on the specified 
     * host. The <code>length</code> argument must be less than or equal 
     * to <code>ibuf.length</code>. 
     *
     * @param   ibuf      the packet data.
     * @param   ilength   the packet length.
     * @param   iaddr     the destination address.
     * @param   tvalue    the type of the packet.
     * @see     java.net.InetAddress
     * @since   JDK1.2
     */
    public IcmpPacket(byte ibuf[], int ilength,
			  InetAddress iaddr, int tvalue) {
	super(ibuf, ilength, iaddr);
    	setType(tvalue);
    }

    /**
     * Constructs an ICMP packet for sending packets of length 
     * <code>ilength</code> with the specified type and code on the specified 
     * host. The <code>length</code> argument must be less than or equal 
     * to <code>ibuf.length</code>. 
     *
     * @param   ibuf      the packet data.
     * @param   ilength   the packet length.
     * @param   iaddr     the destination address.
     * @param   tvalue    the type of the packet.
     * @param   cvalue    the code of the packet.
     * @see     java.net.InetAddress
     * @since   JDK1.2
     */
    public IcmpPacket(byte ibuf[], int ilength,
		       InetAddress iaddr, int tvalue, int cvalue) {
	super(ibuf, ilength, iaddr);
       	setType(tvalue, cvalue);
    }

    /**
     * Set the ICMP type of the packet.
     *
     * @param value the type of the packet
     */
    public synchronized void setType(int value) {
	if (value == 1 || value ==  4 || value == 3)
	    throw new IllegalArgumentException("you must give a code value");
	else if ((value < 128 || value > 137) && value != 2) 
	    throw new IllegalArgumentException("illegal type");	
	 
	type = (byte) value;
    }

    /**
     * Return the ICMP code of the packet.
     *
     * @return the code of the packet
     */    
    public synchronized byte getCode() {
	return code;
    }

    /**
     * Set the ICMP type and code of the packet.
     *
     * @param tvalue the type of the packet
     * @param cvalue the code of the packet
     */
    public synchronized void setType(int tvalue, int cvalue) {
	if (tvalue == 1 && (cvalue < 0 || cvalue > 4))
	    throw new IllegalArgumentException("illegal code");
	else if (tvalue == 2 && cvalue != 0)
	    throw new IllegalArgumentException("illegal code");
	else if (tvalue == 3 && (cvalue != 0 || cvalue != 1))
	    throw new IllegalArgumentException("illegal code");
	else if (tvalue == 1 && (cvalue < 0 || cvalue > 2))
	    throw new IllegalArgumentException("illegal code");
	else if (cvalue != 0 && (tvalue >= 128 || tvalue <= 137))
	    throw new IllegalArgumentException("illegal code");	
	else if (tvalue < 0 || tvalue > 137 || (tvalue > 4 || tvalue < 128))
	    throw new IllegalArgumentException("illegal type");	
	
	type = (byte) tvalue;
	code = (byte) cvalue; 
    }

    /**
     * Return the ICMP type of the packet.
     *
     * @return the type of the packet
     */   
    public synchronized byte getType() {
	return type;
    }

}
