Click here to Skip to main content
15,892,059 members
Articles / Programming Languages / C#

Network Stuff (easy socket v3)

Rate me:
Please Sign up or sign in to vote.
4.87/5 (52 votes)
2 Jun 2005 216.8K   6.1K   137  
A class with event handlers for TCP, UDP or ICMP sockets; includes ping, traceroute, whois, ARP, and IPHelper functions and raw packets forging/ capturing.
/*
Copyright (C) 2004 Jacquelin POTIER <jacquelin.potier@free.fr>
Dynamic aspect ratio code Copyright (C) 2004 Jacquelin POTIER <jacquelin.potier@free.fr>

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.

This program 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 General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*/
using System;

namespace easy_socket.icmp
{
    #region events and events arg
    public class EventArgs_ipv4header_ReceiveData:EventArgs
    {
        public readonly easy_socket.ip_header.ipv4_header ipv4header;
        public EventArgs_ipv4header_ReceiveData(easy_socket.ip_header.ipv4_header ipv4h)
        {
            this.ipv4header=ipv4h;
        }
    }
    /// <summary>
    /// used to raise Exception
    /// contains exception
    /// </summary>
    public class EventArgs_Exception:EventArgs
    {
        public readonly Exception exception;
        public EventArgs_Exception(Exception e)
        {
            this.exception=e;
        }
    }
    public delegate void Socket_Error_EventHandler(icmp sender, EventArgs_Exception e);
    public delegate void TimeOut_EventHandler(icmp sender, EventArgs e);//e=null
    public delegate void icmp_echo_reply_Data_Arrival_EventHandler(icmp_echo_reply sender, EventArgs_ipv4header_ReceiveData e);
    public delegate void icmp_destination_unreachable_Data_Arrival_EventHandler(icmp_destination_unreachable sender, EventArgs_ipv4header_ReceiveData e);
    public delegate void icmp_source_quench_Data_Arrival_EventHandler(icmp_source_quench sender, EventArgs_ipv4header_ReceiveData e);
    public delegate void icmp_redirect_Data_Arrival_EventHandler(icmp_redirect sender, EventArgs_ipv4header_ReceiveData e);
    public delegate void icmp_echo_Data_Arrival_EventHandler(icmp_echo sender, EventArgs_ipv4header_ReceiveData e);
    public delegate void icmp_time_exceeded_message_Data_Arrival_EventHandler(icmp_time_exceeded_message sender, EventArgs_ipv4header_ReceiveData e);
    public delegate void icmp_parameter_problem_Data_Arrival_EventHandler(icmp_parameter_problem sender, EventArgs_ipv4header_ReceiveData e);
    public delegate void icmp_timestamp_Data_Arrival_EventHandler(icmp_timestamp sender, EventArgs_ipv4header_ReceiveData e);
    public delegate void icmp_timestamp_reply_Data_Arrival_EventHandler(icmp_timestamp_reply sender, EventArgs_ipv4header_ReceiveData e);
    public delegate void icmp_information_request_Data_Arrival_EventHandler(icmp_information_request sender, EventArgs_ipv4header_ReceiveData e);
    public delegate void icmp_information_reply_Data_Arrival_EventHandler(icmp_information_reply sender, EventArgs_ipv4header_ReceiveData e);
    #endregion

    /// <summary>
    /// Summary description for icmp.
    /// </summary>
    public class icmp
    {
        
        #region members
        protected byte type;
        public byte Type
        {
            get
            {
                return this.type;
            }
        }
        public byte code;
        public bool b_comput_checksum;
        /// <summary>
        /// checksum in network order
        /// </summary>
        public UInt16 checksum;
        /// <summary>
        /// checksum in host order
        /// </summary>
        public UInt16 Checksum
        {
            set
            {
                this.checksum=easy_socket.network_convert.switch_ushort(value);
                this.b_comput_checksum=false;
            }
            get
            {
                return easy_socket.network_convert.switch_ushort(this.checksum);
            }
        }

        public const byte error_success=0;
        public const byte error_datagram_null=1;
        //public const byte error_datagram_internet_header_length_too_small=2;
        //public const byte error_datagram_total_length_too_small=3;
        public const byte error_datagram_not_complete=4;
        public const byte error_datagram_checksum=6;

        public const byte EchoReply                    =0;
        public const byte DestinationUnreachable    =3;
        public const byte SourceQuench                =4;
        public const byte Redirect                    =5;
        public const byte Echo                        =8;
        public const byte TimeExceeded                =11;
        public const byte ParameterProblem            =12;
        public const byte Timestamp                    =13;
        public const byte TimestampReply            =14;
        public const byte InformationRequest        =15;
        public const byte InformationReply            =16;


        #endregion
        public icmp()
        {
            this.code=0;
            this.checksum=0;
            this.b_comput_checksum=true;
        }
        virtual public byte decode(byte[] data){return error_success;}
        virtual public byte[] encode(){return null;}
        public static string[] get_available_codes(){return new string[]{"0"};}
    }

    public class icmp_client:icmp
    {
        // events
        public event Socket_Error_EventHandler event_Socket_Error;

        // protected members
        protected easy_socket.ip_header.ipv4_header_client ipv4header;

        public icmp_client()
        {
            this.ipv4header=new easy_socket.ip_header.ipv4_header_client();
            this.ipv4header.event_Socket_Error+=new easy_socket.ip_header.Socket_Error_EventHandler(socket_error);
        }
        protected void socket_error(easy_socket.ip_header.ipv4_header sender,easy_socket.ip_header.EventArgs_Exception e)
        {
            if (this.event_Socket_Error!=null)
                event_Socket_Error(this,new EventArgs_Exception(e.exception));
        }
        #region send + broadcast
        public void broadcast(byte ttl)
        {
            this.ipv4header.b_allow_broadcast=true;
            this.ipv4header.send_without_forging("255.255.255.255",System.Net.Sockets.ProtocolType.Icmp,ttl,this.encode());
        }
        public void send(string ip)
        {
            this.send(ip,255);
        }
        public void send(string ip,byte ttl)
        {
            if (ip=="255.255.255.255")
                this.ipv4header.b_allow_broadcast=true;
            this.ipv4header.send_without_forging(ip,System.Net.Sockets.ProtocolType.Icmp,ttl,this.encode());
        }
        public void send(easy_socket.ip_header.ipv4_header_client ipv4h)
        {
            // adding icmp data
            ipv4h.data=this.encode();
            // set icmp type
            ipv4h.protocol=easy_socket.ip_header.ipv4_header.protocol_icmp;
            // allow broadcast by default
            ipv4h.b_allow_broadcast=true;
            // send data
            ipv4h.send();
        }
        #endregion

    }
    public class icmp_client_with_identifier_and_sequence_number:icmp_client
    {
        #region members
        /// <summary>
        /// identifier in network order
        /// </summary>
        public UInt16 identifier;
        /// <summary>
        /// identifier in host order
        /// </summary>
        public UInt16 Identifier
        {
            set
            {
                this.identifier=easy_socket.network_convert.switch_ushort(value);
            }
            get
            {
                return easy_socket.network_convert.switch_ushort(this.identifier);
            }
        }
        /// <summary>
        /// sequence_number in network order
        /// </summary>
        public UInt16 sequence_number;
        /// <summary>
        /// sequence_number in host order
        /// </summary>
        public UInt16 SequenceNumber
        {
            set
            {
                this.sequence_number=easy_socket.network_convert.switch_ushort(value);
            }
            get
            {
                return easy_socket.network_convert.switch_ushort(this.sequence_number);
            }
        }
        #endregion
        public icmp_client_with_identifier_and_sequence_number()
        {
            this.identifier=0;
            this.sequence_number=0;
        }
    }
    public class icmp_server:icmp
    {
        #region events
        //events
        public event Socket_Error_EventHandler event_Socket_Error;
        public event TimeOut_EventHandler event_TimeOut;
        public event icmp_echo_reply_Data_Arrival_EventHandler event_icmp_echo_reply_Data_Arrival;
        public event icmp_destination_unreachable_Data_Arrival_EventHandler event_icmp_destination_unreachable_Data_Arrival;
        public event icmp_source_quench_Data_Arrival_EventHandler event_icmp_source_quench_Data_Arrival;
        public event icmp_redirect_Data_Arrival_EventHandler event_icmp_redirect_Data_Arrival;
        public event icmp_echo_Data_Arrival_EventHandler event_icmp_echo_Data_Arrival;
        public event icmp_time_exceeded_message_Data_Arrival_EventHandler event_icmp_time_exceeded_message_Data_Arrival;
        public event icmp_parameter_problem_Data_Arrival_EventHandler event_icmp_parameter_problem_Data_Arrival;
        public event icmp_timestamp_Data_Arrival_EventHandler event_icmp_timestamp_Data_Arrival;
        public event icmp_timestamp_reply_Data_Arrival_EventHandler event_icmp_timestamp_reply_Data_Arrival;
        public event icmp_information_request_Data_Arrival_EventHandler event_icmp_information_request_Data_Arrival;
        public event icmp_information_reply_Data_Arrival_EventHandler event_icmp_information_reply_Data_Arrival;
        #endregion

        // protected members
        protected easy_socket.ip_header.ipv4_header_icmp_server ipv4header;
        protected const UInt16 remote_port=0;// just for creating IPEndPoint 

        protected System.Timers.Timer timer;

        public icmp_server()
        {
            this.ipv4header=new easy_socket.ip_header.ipv4_header_icmp_server();
            this.ipv4header.event_Socket_Error+=new easy_socket.ip_header.Socket_Error_EventHandler(socket_error);
            this.ipv4header.event_Socket_Data_Arrival+=new easy_socket.ip_header.Socket_Data_Arrival_EventHandler(socket_data_arrival);
            this.timer=new System.Timers.Timer();
            this.timer.Elapsed+=new System.Timers.ElapsedEventHandler(timer_event);
            this.timer.AutoReset=false;
        }

        /// <summary>
        /// start an icmp server. icmp server spy all incoming icmp messages.
        /// you MUST call stop method to avoid remaing runing thread after having close your application.
        /// </summary>
        public void start()
        {
            this.ipv4header.start();
        }

        #region timeout
        private void timer_event(object sender,System.Timers.ElapsedEventArgs e)
        {
            if (this.event_TimeOut!=null)
                this.event_TimeOut(this,null);
        }
        /// <summary>
        /// raise event event_TimeOut in "time_out_for_replies_in_ms" ms (if >=0).
        /// event_TimeOut is raised only one time. Call this method again to raise other event_TimeOut.
        /// </summary>
        /// <param name="time_out_for_replies_in_ms"></param>
        public void set_wait_timeout(int time_out_for_replies_in_ms)
        {
            this.clear_wait_timeout();// stop previous timer if there is one
            this.timer.Interval=time_out_for_replies_in_ms;
            this.timer.Start();
        }
        /// <summary>
        /// Cancel the raising of event_TimeOut
        /// </summary>
        public void clear_wait_timeout()
        {
            this.timer.Stop();
        }
        #endregion

        #region stop
        /// <summary>
        /// stop icmp server
        /// </summary>
        public void stop()
        {
            // clear wait_timeout
            this.clear_wait_timeout();
            // close socket
            this.ipv4header.stop();
        }
        #endregion    

        #region events management
        protected void socket_data_arrival(easy_socket.ip_header.ipv4_header sender,easy_socket.ip_header.EventArgs_FullPacket e)
        {
            // get only icmp message
            if (sender.protocol!=easy_socket.ip_header.ipv4_header.protocol_icmp)
                return;
            icmp_client ret;
            switch (sender.data[0])// switch type
            {
                case icmp.EchoReply:
                    ret=new icmp_echo_reply();
                    if (event_icmp_echo_reply_Data_Arrival!=null)
                        if (ret.decode(sender.data)==icmp.error_success)
                            event_icmp_echo_reply_Data_Arrival((icmp_echo_reply)ret,new EventArgs_ipv4header_ReceiveData(sender));
                    break;
                case icmp.DestinationUnreachable:
                    ret=new icmp_destination_unreachable();
                    if (event_icmp_destination_unreachable_Data_Arrival!=null)
                        if (ret.decode(sender.data)==icmp.error_success)
                            event_icmp_destination_unreachable_Data_Arrival((icmp_destination_unreachable)ret,new EventArgs_ipv4header_ReceiveData(sender));
                    break;
                case icmp.SourceQuench:
                    ret=new icmp_source_quench();
                    if (event_icmp_source_quench_Data_Arrival!=null)
                        if (ret.decode(sender.data)==icmp.error_success)
                            event_icmp_source_quench_Data_Arrival((icmp_source_quench)ret,new EventArgs_ipv4header_ReceiveData(sender));
                    break;
                case icmp.Redirect:
                    ret=new icmp_redirect();
                    if (event_icmp_redirect_Data_Arrival!=null)
                        if (ret.decode(sender.data)==icmp.error_success)
                            event_icmp_redirect_Data_Arrival((icmp_redirect)ret,new EventArgs_ipv4header_ReceiveData(sender));
                    break;
                case icmp.Echo:
                    ret=new icmp_echo();
                    if (event_icmp_echo_Data_Arrival!=null)
                        if (ret.decode(sender.data)==icmp.error_success)
                            event_icmp_echo_Data_Arrival((icmp_echo)ret,new EventArgs_ipv4header_ReceiveData(sender));
                    break;
                case icmp.TimeExceeded:
                    ret=new icmp_time_exceeded_message();
                    if (event_icmp_time_exceeded_message_Data_Arrival!=null)
                        if (ret.decode(sender.data)==icmp.error_success)
                            event_icmp_time_exceeded_message_Data_Arrival((icmp_time_exceeded_message)ret,new EventArgs_ipv4header_ReceiveData(sender));
                    break;
                case icmp.ParameterProblem:
                    ret=new icmp_parameter_problem();
                    if (event_icmp_parameter_problem_Data_Arrival!=null)
                        if (ret.decode(sender.data)==icmp.error_success)
                            event_icmp_parameter_problem_Data_Arrival((icmp_parameter_problem)ret,new EventArgs_ipv4header_ReceiveData(sender));
                    break;
                case icmp.Timestamp:
                    ret=new icmp_timestamp();
                    if (event_icmp_timestamp_Data_Arrival!=null)
                        if (ret.decode(sender.data)==icmp.error_success)
                            event_icmp_timestamp_Data_Arrival((icmp_timestamp)ret,new EventArgs_ipv4header_ReceiveData(sender));
                    break;
                case icmp.TimestampReply:
                    ret=new icmp_timestamp_reply();
                    if (event_icmp_timestamp_reply_Data_Arrival!=null)
                        if (ret.decode(sender.data)==icmp.error_success)
                            event_icmp_timestamp_reply_Data_Arrival((icmp_timestamp_reply)ret,new EventArgs_ipv4header_ReceiveData(sender));
                    break;
                case icmp.InformationRequest:
                    ret=new icmp_information_request();
                    if (event_icmp_information_request_Data_Arrival!=null)
                        if (ret.decode(sender.data)==icmp.error_success)
                            event_icmp_information_request_Data_Arrival((icmp_information_request)ret,new EventArgs_ipv4header_ReceiveData(sender));
                    break;
                case icmp.InformationReply:
                    ret=new icmp_information_reply();
                    if (event_icmp_information_reply_Data_Arrival!=null)
                        if (ret.decode(sender.data)==icmp.error_success)
                            event_icmp_information_reply_Data_Arrival((icmp_information_reply)ret,new EventArgs_ipv4header_ReceiveData(sender));
                    break;
                default:
                    break;
            }
            
        }
        protected void socket_error(easy_socket.ip_header.ipv4_header sender,easy_socket.ip_header.EventArgs_Exception e)
        {
            // cancel our time out
            this.clear_wait_timeout();
            if (this.event_Socket_Error!=null)
                event_Socket_Error(this,new EventArgs_Exception(e.exception));
        }
        #endregion    
    }

    #region destination unreachable
    public class icmp_destination_unreachable:icmp_client
    {
        #region members
        //code: 0-->5
        public const byte code_net_unreachable=0;
        public const byte code_host_unreachable=1;
        public const byte code_protocol_unreachable=2;
        public const byte code_port_unreachable=3;
        public const byte code_fragmentation_needed_and_DF_set=4;
        public const byte code_source_route_failed=5;
        /// <summary>
        /// return code message
        /// </summary>
        public string Code
        {
            get
            {
                switch (this.code)
                {
                    case 0:
                        return "net unreachable";
                    case 1:
                        return "host unreachable";
                    case 2:
                        return "protocol unreachable";
                    case 3:
                        return "port unreachable";
                    case 4:
                        return "fragmentation needed and DF set";
                    case 5:
                        return "source route failed";
                    default: 
                        return "Unknown ("+this.code+")";
                }        
            }
        }
        public UInt32 unused;
        public byte[] ih_and_original_dd;
        #endregion

        public icmp_destination_unreachable()
        {
            this.type=3;
            this.unused=0;
            this.code=icmp_destination_unreachable.code_net_unreachable;
        }
        public static string[] get_available_codes()
        {
            return new string[]{"0 = net unreachable",
                                "1 = host unreachable",
                                "2 = protocol unreachable",
                                "3 = port unreachable",
                                "4 = fragmentation needed and DF set",
                                "5 = source route failed"
                               };
        }

        #region encode/decode
        public override byte[] encode()
        {
            int ih_and_original_dd_size=0;
            if (this.ih_and_original_dd!=null)
                ih_and_original_dd_size=this.ih_and_original_dd.Length;
            byte[] ret=new byte[8+ih_and_original_dd_size];

            ret[0]=this.type;
            ret[1]=this.code;
            if (!this.b_comput_checksum)
            {
                System.Array.Copy(System.BitConverter.GetBytes(this.checksum),0,ret,2,2);
            }
            else
            {
                // checksum to 0
                ret[2]=0;
                ret[3]=0;
            }

            // unused (4 bytes)
            System.Array.Copy(System.BitConverter.GetBytes(this.unused),0,ret,4,4);
            if (ih_and_original_dd_size>0)
                System.Array.Copy(this.ih_and_original_dd,0,ret,8,ih_and_original_dd_size);
            if (this.b_comput_checksum)
            {
                // comput checksum
                this.checksum=Cchecksum.checksum(ret,true);
                System.Array.Copy(System.BitConverter.GetBytes(this.checksum),0,ret,2,2);
            }
            return ret;
        }
        public override byte decode(byte[] data)
        {
            if (data==null)
                return icmp.error_datagram_null;
            if (data.Length<8)
                return icmp.error_datagram_not_complete;
            // this.type=data[0]; // already known
            this.code=data[1];
            this.checksum=System.BitConverter.ToUInt16(data,2);
            this.ih_and_original_dd=null;
            int size=data.Length-8;
            if (size>0)
            {
                this.ih_and_original_dd=new byte[size];
                System.Array.Copy(data,8,this.ih_and_original_dd,0,size);
            }
            // verify checksum
            byte b2=data[2];
            byte b3=data[3];
            data[2]=0;
            data[3]=0;
            UInt16 ui_computed_checksum=easy_socket.Cchecksum.checksum(data,true);
            // restore data
            data[2]=b2;
            data[3]=b3;
            if (this.checksum!=ui_computed_checksum)
                return icmp.error_datagram_checksum;

            // no error
            return icmp.error_success;
        }
        #endregion
    }
    #endregion
    #region time exceeded
    public class icmp_time_exceeded_message:icmp_client
    {
        #region members
        public const byte code_time_to_live_exceeded_in_transit=0;
        public const byte code_fragment_reassembly_time_exceeded=1;
        /// <summary>
        /// return code message
        /// </summary>
        public string Code
        {
            get
            {
                switch (this.code)
                {
                    case 0:
                        return "time to live exceeded in transit";
                    case 1:
                        return "fragment reassembly time exceeded";
                    default: 
                        return "Unknown ("+this.code+")";
                }        
            }
        }
        public UInt32 unused;
        public byte[] ih_and_original_dd;
        #endregion

        public icmp_time_exceeded_message()
        {
            this.type=11;
            this.code=icmp_time_exceeded_message.code_time_to_live_exceeded_in_transit;
            this.unused=0;
        }
        public static string[] get_available_codes()
        {
            return new string[]{"0 = time to live exceeded in transit",
                                "1 = fragment reassembly time exceeded"
                               };
        }
        #region encode/decode
        public override byte[] encode()
        {
            int ih_and_original_dd_size=0;
            if (this.ih_and_original_dd!=null)
                ih_and_original_dd_size=this.ih_and_original_dd.Length;
            byte[] ret=new byte[8+ih_and_original_dd_size];

            ret[0]=this.type;
            ret[1]=this.code;
            if (!this.b_comput_checksum)
            {
                System.Array.Copy(System.BitConverter.GetBytes(this.checksum),0,ret,2,2);
            }
            else
            {
                // checksum to 0
                ret[2]=0;
                ret[3]=0;
            }

            // unused
            System.Array.Copy(System.BitConverter.GetBytes(this.unused),0,ret,4,4);
            if (ih_and_original_dd_size>0)
                System.Array.Copy(this.ih_and_original_dd,0,ret,8,ih_and_original_dd_size);
            if (this.b_comput_checksum)
            {
                // comput checksum
                this.checksum=Cchecksum.checksum(ret,true);
                System.Array.Copy(System.BitConverter.GetBytes(this.checksum),0,ret,2,2);
            }
            return ret;
        }
        public override byte decode(byte[] data)
        {
            if (data==null)
                return icmp.error_datagram_null;
            if (data.Length<8)
                return icmp.error_datagram_not_complete;
            // this.type=data[0]; // already known
            this.code=data[1];
            this.checksum=System.BitConverter.ToUInt16(data,2);
            //unused
            this.ih_and_original_dd=null;
            int size=data.Length-8;
            if (size>0)
            {
                this.ih_and_original_dd=new byte[size];
                System.Array.Copy(data,8,this.ih_and_original_dd,0,size);
            }
            // verify checksum
            byte b2=data[2];
            byte b3=data[3];
            data[2]=0;
            data[3]=0;
            UInt16 ui_computed_checksum=easy_socket.Cchecksum.checksum(data,true);
            // restore data
            data[2]=b2;
            data[3]=b3;
            if (this.checksum!=ui_computed_checksum)
                return icmp.error_datagram_checksum;

            // no error
            return icmp.error_success;
        }
        #endregion
    }
    #endregion
    #region parameter problem
    public class icmp_parameter_problem:icmp_client
    {
        #region members
        public byte pointer;
        public UInt32 unused; // 3 bytes only
        public byte[] ih_and_original_dd;
        #endregion
        public icmp_parameter_problem()
        {
            this.type=12;
            this.pointer=0;
            this.unused=0;
        }
        #region encode/decode
        public override byte[] encode()
        {
            int ih_and_original_dd_size=0;
            if (this.ih_and_original_dd!=null)
                ih_and_original_dd_size=this.ih_and_original_dd.Length;
            byte[] ret=new byte[8+ih_and_original_dd_size];

            ret[0]=this.type;
            ret[1]=this.code;
            if (!this.b_comput_checksum)
            {
                System.Array.Copy(System.BitConverter.GetBytes(this.checksum),0,ret,2,2);
            }
            else
            {
                // checksum to 0
                ret[2]=0;
                ret[3]=0;
            }

            ret[4]=this.pointer;
            // unused
            System.Array.Copy(System.BitConverter.GetBytes(this.unused),1,ret,5,3);
            if (ih_and_original_dd_size>0)
                System.Array.Copy(this.ih_and_original_dd,0,ret,8,ih_and_original_dd_size);
            if (this.b_comput_checksum)
            {
                // comput checksum
                this.checksum=Cchecksum.checksum(ret,true);
                System.Array.Copy(System.BitConverter.GetBytes(this.checksum),0,ret,2,2);
            }
            return ret;
        }
        public override byte decode(byte[] data)
        {
            if (data==null)
                return icmp.error_datagram_null;
            if (data.Length<8)
                return icmp.error_datagram_not_complete;
            // this.type=data[0]; // already known
            this.code=data[1];
            this.checksum=System.BitConverter.ToUInt16(data,2);
            this.pointer=data[4];
            this.ih_and_original_dd=null;
            int size=data.Length-8;
            if (size>0)
            {
                this.ih_and_original_dd=new byte[size];
                System.Array.Copy(data,8,this.ih_and_original_dd,0,size);
            }
            // verify checksum
            byte b2=data[2];
            byte b3=data[3];
            data[2]=0;
            data[3]=0;
            UInt16 ui_computed_checksum=easy_socket.Cchecksum.checksum(data,true);
            // restore data
            data[2]=b2;
            data[3]=b3;
            if (this.checksum!=ui_computed_checksum)
                return icmp.error_datagram_checksum;

            // no error
            return icmp.error_success;
        }
        #endregion
    }
    #endregion
    #region source quench
    public class icmp_source_quench:icmp_client
    {
        #region members
        public UInt32 unused;
        public byte[] ih_and_original_dd;
        #endregion
        public icmp_source_quench()
        {
            this.unused=0;
            this.type=4;
        }
        #region encode/decode
        public override byte[] encode()
        {
            int ih_and_original_dd_size=0;
            if (this.ih_and_original_dd!=null)
                ih_and_original_dd_size=this.ih_and_original_dd.Length;
            byte[] ret=new byte[8+ih_and_original_dd_size];

            ret[0]=this.type;
            ret[1]=this.code;
            if (!this.b_comput_checksum)
            {
                System.Array.Copy(System.BitConverter.GetBytes(this.checksum),0,ret,2,2);
            }
            else
            {
                // checksum to 0
                ret[2]=0;
                ret[3]=0;
            }

            // unused
            System.Array.Copy(System.BitConverter.GetBytes(this.unused),0,ret,4,4);
            if (ih_and_original_dd_size>0)
                System.Array.Copy(this.ih_and_original_dd,0,ret,8,ih_and_original_dd_size);
            if (this.b_comput_checksum)
            {
                // comput checksum
                this.checksum=Cchecksum.checksum(ret,true);
                System.Array.Copy(System.BitConverter.GetBytes(this.checksum),0,ret,2,2);
            }
            return ret;
        }
        public override byte decode(byte[] data)
        {
            if (data==null)
                return icmp.error_datagram_null;
            if (data.Length<8)
                return icmp.error_datagram_not_complete;
            // this.type=data[0]; // already known
            this.code=data[1];
            this.checksum=System.BitConverter.ToUInt16(data,2);
            this.ih_and_original_dd=null;
            int size=data.Length-8;
            if (size>0)
            {
                this.ih_and_original_dd=new byte[size];
                System.Array.Copy(data,8,this.ih_and_original_dd,0,size);
            }
            // verify checksum
            byte b2=data[2];
            byte b3=data[3];
            data[2]=0;
            data[3]=0;
            UInt16 ui_computed_checksum=easy_socket.Cchecksum.checksum(data,true);
            // restore data
            data[2]=b2;
            data[3]=b3;
            if (this.checksum!=ui_computed_checksum)
                return icmp.error_datagram_checksum;

            // no error
            return icmp.error_success;
        }
        #endregion
    }
    #endregion
    #region redirect
    public class icmp_redirect:icmp_client
    {
        #region members
        public const byte code_redirect_datagram_for_network=0;
        public const byte code_redirect_datagram_for_host=1;
        public const byte code_redirect_datagram_for_type_of_service_and_network=2;
        public const byte code_redirect_datagram_for_type_of_service_and_host=3;
        /// <summary>
        /// return code message
        /// </summary>
        public string Code
        {
            get
            {
                switch (this.code)
                {
                    case 0:
                        return "for the Network";
                    case 1:
                        return "for the Host";
                    case 2:
                        return "for the Type of Service and Network";
                    case 3:
                        return "for the Type of Service and Host";
                    default: 
                        return "Unknown ("+this.code+")";
                }        
            }
        }
        public UInt32 gateway_internet_address;
        public string GatewayInternetAddress
        {
            set
            {
                try
                {
                    this.gateway_internet_address=(UInt32)System.Net.IPAddress.Parse(value).Address;
                }
                catch
                {
                    this.gateway_internet_address=(UInt32)System.Net.IPAddress.Parse("127.0.0.1").Address;
                }
            }
            get
            {
                return new System.Net.IPAddress(this.gateway_internet_address).ToString();
            }
        }
        public byte[] ih_and_original_dd;
        #endregion
        public icmp_redirect()
        {
            this.code=icmp_redirect.code_redirect_datagram_for_network;
            this.type=5;
            this.gateway_internet_address=0;
        }
        public static string[] get_available_codes()
        {
            return new string[]{"0 = Redirect datagrams for the Network",
                                 "1 = Redirect datagrams for the Host",
                                 "2 = Redirect datagrams for the Type of Service and Network",
                                 "3 = Redirect datagrams for the Type of Service and Host"};

        }

        #region encode/decode
        public override byte[] encode()
        {
            int ih_and_original_dd_size=0;
            if (this.ih_and_original_dd!=null)
                ih_and_original_dd_size=this.ih_and_original_dd.Length;
            byte[] ret=new byte[8+ih_and_original_dd_size];

            ret[0]=this.type;
            ret[1]=this.code;
            if (!this.b_comput_checksum)
            {
                System.Array.Copy(System.BitConverter.GetBytes(this.checksum),0,ret,2,2);
            }
            else
            {
                // checksum to 0
                ret[2]=0;
                ret[3]=0;
            }

            System.Array.Copy(System.BitConverter.GetBytes(this.gateway_internet_address),0,ret,4,4);
            if (ih_and_original_dd_size>0)
                System.Array.Copy(this.ih_and_original_dd,0,ret,8,ih_and_original_dd_size);
            if (this.b_comput_checksum)
            {
                // comput checksum
                this.checksum=Cchecksum.checksum(ret,true);
                System.Array.Copy(System.BitConverter.GetBytes(this.checksum),0,ret,2,2);
            }

            return ret;
        }
        public override byte decode(byte[] data)
        {
            if (data==null)
                return icmp.error_datagram_null;
            if (data.Length<8)
                return icmp.error_datagram_not_complete;
            // this.type=data[0]; // already known
            this.code=data[1];
            this.checksum=System.BitConverter.ToUInt16(data,2);
            this.gateway_internet_address=System.BitConverter.ToUInt32(data,4);
            this.ih_and_original_dd=null;
            int size=data.Length-8;
            if (size>0)
            {
                this.ih_and_original_dd=new byte[size];
                System.Array.Copy(data,8,this.ih_and_original_dd,0,size);
            }
            // verify checksum
            byte b2=data[2];
            byte b3=data[3];
            data[2]=0;
            data[3]=0;
            UInt16 ui_computed_checksum=easy_socket.Cchecksum.checksum(data,true);
            // restore data
            data[2]=b2;
            data[3]=b3;
            if (this.checksum!=ui_computed_checksum)
                return icmp.error_datagram_checksum;

            // no error
            return icmp.error_success;
        }
        #endregion
    }
    #endregion
    #region echo
    public class icmp_echo:icmp_client_with_identifier_and_sequence_number
    {
        #region members
        public byte[] data;
        /// <summary>
        /// set or get data in ASCII format
        /// </summary>
        public string Data
        {
            set
            {
                this.data=System.Text.Encoding.ASCII.GetBytes(value);
            }
            get
            {
                if (this.data==null)
                    return "";
                return System.Text.Encoding.ASCII.GetString(this.data, 0,this.data.Length);
            }
        }
        #endregion
        public icmp_echo()
        {
            this.type=8;
        }
        #region encode/decode
        public override byte[] encode()
        {
            int data_size=0;
            if (this.data!=null)
                data_size=this.data.Length;
            byte[] ret=new byte[8+data_size];

            ret[0]=this.type;
            ret[1]=this.code;
            if (!this.b_comput_checksum)
            {
                System.Array.Copy(System.BitConverter.GetBytes(this.checksum),0,ret,2,2);
            }
            else
            {
                // checksum to 0
                ret[2]=0;
                ret[3]=0;
            }
            System.Array.Copy(System.BitConverter.GetBytes(this.identifier),0,ret,4,2);
            System.Array.Copy(System.BitConverter.GetBytes(this.sequence_number),0,ret,6,2);
            if (data_size>0)
                System.Array.Copy(this.data,0,ret,8,data_size);

            if (this.b_comput_checksum)
            {
                // comput checksum
                this.checksum=Cchecksum.checksum(ret,true);
                System.Array.Copy(System.BitConverter.GetBytes(this.checksum),0,ret,2,2);
            }
            return ret;
        }
        public override byte decode(byte[] data)
        {
            if (data==null)
                return icmp.error_datagram_null;
            if (data.Length<8)
                return icmp.error_datagram_not_complete;
            // this.type=data[0]; // already known
            this.code=data[1];
            this.checksum=System.BitConverter.ToUInt16(data,2);
            this.identifier=System.BitConverter.ToUInt16(data,4);
            this.sequence_number=System.BitConverter.ToUInt16(data,6);

            this.data=null;
            int size=data.Length-8;
            if (size>0)
            {
                this.data=new byte[size];
                System.Array.Copy(data,8,this.data,0,size);
            }
            // verify checksum
            byte b2=data[2];
            byte b3=data[3];
            data[2]=0;
            data[3]=0;
            UInt16 ui_computed_checksum=easy_socket.Cchecksum.checksum(data,true);
            // restore data
            data[2]=b2;
            data[3]=b3;
            if (this.checksum!=ui_computed_checksum)
                return icmp.error_datagram_checksum;

            // no error
            return icmp.error_success;
        }
        #endregion
    }
    public class icmp_echo_reply:icmp_echo
    {
        public icmp_echo_reply()
        {
            this.type=0;
        }
    }
    #endregion
    #region timestamp
    public class icmp_timestamp:icmp_client_with_identifier_and_sequence_number
    {
        #region members
        /// <summary>
        /// originate_timestamp in network order
        /// </summary>
        public UInt32 originate_timestamp;
        /// <summary>
        /// originate_timestamp in host order
        /// </summary>
        public UInt32 OriginateTimestamp
        {
            set
            {
                this.originate_timestamp=easy_socket.network_convert.switch_UInt32(value);
            }
            get
            {
                return easy_socket.network_convert.switch_UInt32(this.originate_timestamp);
            }
        }
        /// <summary>
        /// receive_timestamp in network order
        /// </summary>
        public UInt32 receive_timestamp;
        /// <summary>
        /// receive_timestamp in host order
        /// </summary>
        public UInt32 ReceiveTimestamp
        {
            set
            {
                this.receive_timestamp=easy_socket.network_convert.switch_UInt32(value);
            }
            get
            {
                return easy_socket.network_convert.switch_UInt32(this.receive_timestamp);
            }
        }
        /// <summary>
        /// transmit_timestamp in network order
        /// </summary>
        public UInt32 transmit_timestamp;
        /// <summary>
        /// transmit_timestamp in host order
        /// </summary>
        public UInt32 TransmitTimestamp
        {
            set
            {
                this.transmit_timestamp=easy_socket.network_convert.switch_UInt32(value);
            }
            get
            {
                return easy_socket.network_convert.switch_UInt32(this.transmit_timestamp);
            }
        }
        #endregion
        public icmp_timestamp()
        {
            this.type=13;
            this.originate_timestamp=0;
            this.receive_timestamp=0;
            this.transmit_timestamp=0;
        }
        #region encode/decode
        public override byte[] encode()
        {
            byte[] ret=new byte[20];
            ret[0]=this.type;
            ret[1]=this.code;
            if (!this.b_comput_checksum)
            {
                System.Array.Copy(System.BitConverter.GetBytes(this.checksum),0,ret,2,2);
            }
            else
            {
                // checksum to 0
                ret[2]=0;
                ret[3]=0;
            }


            System.Array.Copy(System.BitConverter.GetBytes(this.identifier),0,ret,4,2);
            System.Array.Copy(System.BitConverter.GetBytes(this.sequence_number),0,ret,6,2);
            System.Array.Copy(System.BitConverter.GetBytes(this.originate_timestamp),0,ret,8,4);
            System.Array.Copy(System.BitConverter.GetBytes(this.receive_timestamp),0,ret,12,4);
            System.Array.Copy(System.BitConverter.GetBytes(this.transmit_timestamp),0,ret,16,4);

            if (this.b_comput_checksum)
            {
                // comput checksum
                this.checksum=Cchecksum.checksum(ret,true);
                System.Array.Copy(System.BitConverter.GetBytes(this.checksum),0,ret,2,2);
            }
            return ret;
        }
        public override byte decode(byte[] data)
        {
            if (data==null)
                return icmp.error_datagram_null;
            if (data.Length<20)
                return icmp.error_datagram_not_complete;
            // this.type=data[0]; // already known
            this.code=data[1];
            this.checksum=System.BitConverter.ToUInt16(data,2);
            int size=data.Length-8;
            this.identifier=System.BitConverter.ToUInt16(data,4);
            this.sequence_number=System.BitConverter.ToUInt16(data,6);

            this.originate_timestamp=System.BitConverter.ToUInt32(data,8);
            this.receive_timestamp=System.BitConverter.ToUInt32(data,12);
            this.transmit_timestamp=System.BitConverter.ToUInt32(data,16);

            // verify checksum
            byte b2=data[2];
            byte b3=data[3];
            data[2]=0;
            data[3]=0;
            UInt16 ui_computed_checksum=easy_socket.Cchecksum.checksum(data,true);
            // restore data
            data[2]=b2;
            data[3]=b3;
            if (this.checksum!=ui_computed_checksum)
                return icmp.error_datagram_checksum;

            // no error
            return icmp.error_success;
        }
        #endregion
    }
    public class icmp_timestamp_reply:icmp_timestamp
    {
        public icmp_timestamp_reply()
        {
            this.type=14;
        }
    }
    #endregion
    #region information
    public class icmp_information_request:icmp_client_with_identifier_and_sequence_number
    {
        public icmp_information_request()
        {
            this.type=15;
        }
        #region encode/decode
        public override byte[] encode()
        {
            byte[] ret=new byte[8];

            ret[0]=this.type;
            ret[1]=this.code;
            if (!this.b_comput_checksum)
            {
                System.Array.Copy(System.BitConverter.GetBytes(this.checksum),0,ret,2,2);
            }
            else
            {
                // checksum to 0
                ret[2]=0;
                ret[3]=0;
            }

            System.Array.Copy(System.BitConverter.GetBytes(this.identifier),0,ret,4,2);
            System.Array.Copy(System.BitConverter.GetBytes(this.sequence_number),0,ret,6,2);

            if (this.b_comput_checksum)
            {
                // comput checksum
                this.checksum=Cchecksum.checksum(ret,true);
                System.Array.Copy(System.BitConverter.GetBytes(this.checksum),0,ret,2,2);
            }
            
            System.Array.Copy(System.BitConverter.GetBytes(this.checksum),0,ret,2,2);
            return ret;
        }
        public override byte decode(byte[] data)
        {
            if (data==null)
                return icmp.error_datagram_null;
            if (data.Length<8)
                return icmp.error_datagram_not_complete;
            // this.type=data[0]; // already known
            this.code=data[1];
            this.checksum=System.BitConverter.ToUInt16(data,2);
            this.identifier=System.BitConverter.ToUInt16(data,4);
            this.sequence_number=System.BitConverter.ToUInt16(data,6);

            // verify checksum
            byte b2=data[2];
            byte b3=data[3];
            data[2]=0;
            data[3]=0;
            UInt16 ui_computed_checksum=easy_socket.Cchecksum.checksum(data,true);
            // restore data
            data[2]=b2;
            data[3]=b3;
            if (this.checksum!=ui_computed_checksum)
                return icmp.error_datagram_checksum;

            // no error
            return icmp.error_success;
        }
        #endregion
    }

    public class icmp_information_reply:icmp_information_request
    {
        public icmp_information_reply()
        {
            this.type=16;
        }
    }
    #endregion

}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
France France

Comments and Discussions