/*
  Copyright (C) 2001-2023 Free Software Foundation, Inc.

  This file is part of GNU Inetutils.

  GNU Inetutils 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, either version 3 of the License, or (at
  your option) any later version.

  GNU Inetutils 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, see `http://www.gnu.org/licenses/'. */

/*
 * Structure of an icmp header.
 */
typedef struct icmp_header icmphdr_t;

struct icmp_header
{
  unsigned char icmp_type;	/* type of message, see below */
  unsigned char icmp_code;	/* type sub code */
  unsigned short icmp_cksum;	/* ones complement cksum of struct */
  union
  {
    unsigned char ih_pptr;	/* ICMP_PARAMPROB */
    struct in_addr ih_gwaddr;	/* ICMP_REDIRECT */
    struct ih_idseq
    {
      unsigned short icd_id;
      unsigned short icd_seq;
    } ih_idseq;
    int ih_void;

    /* ICMP_UNREACH_NEEDFRAG -- Path MTU discovery as per rfc 1191 */
    struct ih_pmtu
    {
      unsigned short ipm_void;
      unsigned short ipm_nextmtu;
    } ih_pmtu;

    /* ICMP_ROUTERADV -- RFC 1256 */
    struct ih_rtradv
    {
      unsigned char irt_num_addrs;	/* Number of addresses following the msg */
      unsigned char irt_wpa;	/* Address Entry Size (32-bit words) */
      unsigned short irt_lifetime;	/* Lifetime */
    } ih_rtradv;

  } icmp_hun;
#define icmp_pptr	icmp_hun.ih_pptr
#define icmp_gwaddr	icmp_hun.ih_gwaddr
#define icmp_id		icmp_hun.ih_idseq.icd_id
#define icmp_seq	icmp_hun.ih_idseq.icd_seq
#define icmp_void	icmp_hun.ih_void
#define icmp_pmvoid     icmp_hun.ih_pmtu.ipm_void
#define icmp_nextmtu    icmp_hun.ih_pmtu.ipm_nextmtu
#define icmp_num_addrs  icmp_hun.ih_rtradv.irt_num_addrs
#define icmp_wpa        icmp_hun.ih_rtradv.irt_wpa
#define icmp_lifetime   icmp_hun.ih_rtradv.irt_lifetime

  union
  {
    struct id_ts		/* ICMP_TIMESTAMP, ICMP_TIMESTAMPREPLY */
    {
      n_time its_otime;		/* Originate timestamp */
      n_time its_rtime;		/* Recieve timestamp */
      n_time its_ttime;		/* Transmit timestamp */
    } id_ts;
    struct id_ip		/* Original IP header */
    {
      struct ip idi_ip;
      /* options and then 64 bits of data */
    } id_ip;
    unsigned long id_mask;	/* ICMP_ADDRESS, ICMP_ADDRESSREPLY */
    char id_data[1];
  } icmp_dun;
#define icmp_otime	icmp_dun.id_ts.its_otime
#define icmp_rtime	icmp_dun.id_ts.its_rtime
#define icmp_ttime	icmp_dun.id_ts.its_ttime
#define icmp_ip		icmp_dun.id_ip.idi_ip
#define icmp_mask	icmp_dun.id_mask
#define icmp_data	icmp_dun.id_data
};

#define ICMP_ECHOREPLY		0	/* Echo Reply                   */
#define ICMP_DEST_UNREACH	3	/* Destination Unreachable      */
/* Codes for ICMP_DEST_UNREACH. */
#define ICMP_NET_UNREACH	0	/* Network Unreachable          */
#define ICMP_HOST_UNREACH	1	/* Host Unreachable             */
#define ICMP_PROT_UNREACH	2	/* Protocol Unreachable         */
#define ICMP_PORT_UNREACH	3	/* Port Unreachable             */
#define ICMP_FRAG_NEEDED	4	/* Fragmentation Needed/DF set  */
#define ICMP_SR_FAILED		5	/* Source Route failed          */
#define ICMP_NET_UNKNOWN	6
#define ICMP_HOST_UNKNOWN	7
#define ICMP_HOST_ISOLATED	8
#define ICMP_NET_ANO		9
#define ICMP_HOST_ANO		10
#define ICMP_NET_UNR_TOS	11
#define ICMP_HOST_UNR_TOS	12
#define ICMP_PKT_FILTERED	13	/* Packet filtered */
#define ICMP_PREC_VIOLATION	14	/* Precedence violation */
#define ICMP_PREC_CUTOFF	15	/* Precedence cut off */
#define NR_ICMP_UNREACH	15	/* total subcodes */

#define ICMP_SOURCE_QUENCH	4	/* Source Quench                */
#define ICMP_REDIRECT		5	/* Redirect (change route)      */
/* Codes for ICMP_REDIRECT. */
#define ICMP_REDIR_NET	0	/* Redirect Net                 */
#define ICMP_REDIR_HOST	1	/* Redirect Host                */
#define ICMP_REDIR_NETTOS	2	/* Redirect Net for TOS         */
#define ICMP_REDIR_HOSTTOS	3	/* Redirect Host for TOS        */

#define ICMP_ECHO		8	/* Echo Request                 */
#define ICMP_ROUTERADV          9	/* Router Advertisement -- RFC 1256 */
#define ICMP_ROUTERDISCOVERY    10	/* Router Discovery -- RFC 1256 */
#define ICMP_TIME_EXCEEDED	11	/* Time Exceeded                */
/* Codes for TIME_EXCEEDED. */
#define ICMP_EXC_TTL		0	/* TTL count exceeded           */
#define ICMP_EXC_FRAGTIME	1	/* Fragment Reass time exceeded */

#define ICMP_PARAMETERPROB	12	/* Parameter Problem            */
#define ICMP_TIMESTAMP		13	/* Timestamp Request            */
#define ICMP_TIMESTAMPREPLY	14	/* Timestamp Reply              */
#define ICMP_INFO_REQUEST	15	/* Information Request          */
#define ICMP_INFO_REPLY		16	/* Information Reply            */
#define ICMP_ADDRESS		17	/* Address Mask Request         */
#define ICMP_ADDRESSREPLY	18	/* Address Mask Reply           */
#define NR_ICMP_TYPES		18



#define MAXIPLEN	60
#define MAXICMPLEN	76
#define ICMP_MINLEN	8	/* abs minimum */
#define ICMP_TSLEN	(8 + 3 * sizeof (n_time))	/* timestamp */
#define ICMP_MASKLEN	12	/* address mask */
#define ICMP_ADVLENMIN	(8 + sizeof (struct ip) + 8)	/* min */
#define ICMP_ADVLEN(p)	(8 + ((p)->icmp_ip.ip_hl << 2) + 8)
	/* N.B.: must separately check that ip_hl >= 5 */

unsigned short icmp_cksum (unsigned char *addr, int len);
int icmp_generic_encode (unsigned char *buffer, size_t bufsize, int type,
			 int ident, int seqno);
int icmp_generic_decode (unsigned char *buffer, size_t bufsize,
			 struct ip **ipp, icmphdr_t ** icmpp);

int icmp_echo_encode (unsigned char *buffer, size_t bufsize, int ident,
		      int seqno);
int icmp_echo_decode (unsigned char *buffer, size_t bufsize, struct ip **ip,
		      icmphdr_t ** icmp);
int icmp_timestamp_encode (unsigned char *buffer, size_t bufsize, int ident,
			   int seqno);
int icmp_address_encode (unsigned char *buffer, size_t bufsize, int ident,
			 int seqno);
