#include <u.h>
#include <libc.h>
#include <ip.h>


typedef struct Icmp Icmp;
struct Icmp
{
       uchar   vihl;           /* Version and header length */
       uchar   tos;            /* Type of service */
       uchar   length[2];      /* packet length */
       uchar   id[2];          /* Identification */
       uchar   frag[2];        /* Fragment information */
       uchar   ttl;            /* Time to live */
       uchar   proto;          /* Protocol */
       uchar   ipcksum[2];     /* Header checksum */
       uchar   src[4];         /* Ip source */
       uchar   dst[4];         /* Ip destination */
       uchar   type;
       uchar   code;
       uchar   cksum[2];
       uchar   icmpid[2];
       uchar   seq[2];
       uchar   data[1];
};

enum
{                       /* Packet Types */
       EchoReply       = 0,
       Unreachable     = 3,
       SrcQuench       = 4,
       EchoRequest     = 8,
       TimeExceed      = 11,
       Timestamp       = 13,
       TimestampReply  = 14,
       InfoRequest     = 15,
       InfoReply       = 16,

       ICMP_IPSIZE     = 20,
       ICMP_HDRSIZE    = 8,
};

static void
catch(void *a, char *msg)
{
       USED(a);
       if(strstr(msg, "alarm"))
               noted(NCONT);
       else
               noted(NDFLT);
}

#define MSG "dhcp probe"

/*
*  make sure noone is using the address
*/
int
icmpecho(uchar *a)
{
       int fd;
       char buf[512];
       Icmp *ip;
       int i, n, len;
       ushort sseq, x;
       int rv;

       rv = 0;

       sprint(buf, "%I", a);
       fd = dial(netmkaddr(buf, "icmp", "1"), 0, 0, 0);
       if(fd < 0){
               return 0;
       }

       sseq = getpid()*time(0);

       ip = (Icmp*)buf;
       notify(catch);
       for(i = 0; i < 3; i++){
               ip->type = EchoRequest;
               ip->code = 0;
               strcpy((char*)ip->data, MSG);
               ip->seq[0] = sseq;
               ip->seq[1] = sseq>>8;
               len = ICMP_IPSIZE+ICMP_HDRSIZE+sizeof(MSG);

               /* send a request */
               if(write(fd, buf, len) < len)
                       break;

               /* wait 1/10th second for a reply and try again */
               alarm(100);
               n = read(fd, buf, sizeof(buf));
               alarm(0);
               if(n <= 0)
                       continue;

               /* an answer to our echo request? */
               x = (ip->seq[1]<<8)|ip->seq[0];
               if(n >= len)
               if(ip->type == EchoReply)
               if(x == sseq)
               if(strcmp((char*)ip->data, MSG) == 0){
                       rv = 1;
                       break;
               }
       }
       close(fd);
       return rv;
}