#include #include #include 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; }