xref: /plan9-contrib/sys/src/cmd/ip/dhcpd/ping.c (revision ec59a3ddbfceee0efe34584c2c9981a5e5ff1ec4)
1 #include <u.h>
2 #include <libc.h>
3 #include <ip.h>
4 
5 
6 typedef struct Icmp Icmp;
7 struct Icmp
8 {
9 	uchar	vihl;		/* Version and header length */
10 	uchar	tos;		/* Type of service */
11 	uchar	length[2];	/* packet length */
12 	uchar	id[2];		/* Identification */
13 	uchar	frag[2];	/* Fragment information */
14 	uchar	ttl;		/* Time to live */
15 	uchar	proto;		/* Protocol */
16 	uchar	ipcksum[2];	/* Header checksum */
17 	uchar	src[4];		/* Ip source */
18 	uchar	dst[4];		/* Ip destination */
19 	uchar	type;
20 	uchar	code;
21 	uchar	cksum[2];
22 	uchar	icmpid[2];
23 	uchar	seq[2];
24 	uchar	data[1];
25 };
26 
27 enum
28 {			/* Packet Types */
29 	EchoReply	= 0,
30 	Unreachable	= 3,
31 	SrcQuench	= 4,
32 	EchoRequest	= 8,
33 	TimeExceed	= 11,
34 	Timestamp	= 13,
35 	TimestampReply	= 14,
36 	InfoRequest	= 15,
37 	InfoReply	= 16,
38 
39 	ICMP_IPSIZE	= 20,
40 	ICMP_HDRSIZE	= 8,
41 };
42 
43 static void
44 catch(void *a, char *msg)
45 {
46 	USED(a);
47 	if(strstr(msg, "alarm"))
48 		noted(NCONT);
49 	else
50 		noted(NDFLT);
51 }
52 
53 #define MSG "dhcp probe"
54 
55 /*
56  *  make sure noone is using the address
57  */
58 int
59 icmpecho(uchar *a)
60 {
61 	int fd;
62 	char buf[512];
63 	Icmp *ip;
64 	int i, n, len;
65 	ushort sseq, x;
66 	int rv;
67 
68 	rv = 0;
69 
70 	sprint(buf, "%I", a);
71 	fd = dial(netmkaddr(buf, "icmp", "1"), 0, 0, 0);
72 	if(fd < 0){
73 		return 0;
74 	}
75 
76 	sseq = getpid()*time(0);
77 
78 	ip = (Icmp*)buf;
79 	notify(catch);
80 	for(i = 0; i < 3; i++){
81 		ip->type = EchoRequest;
82 		ip->code = 0;
83 		strcpy((char*)ip->data, MSG);
84 		ip->seq[0] = sseq;
85 		ip->seq[1] = sseq>>8;
86 		len = ICMP_IPSIZE+ICMP_HDRSIZE+sizeof(MSG);
87 
88 		/* send a request */
89 		if(write(fd, buf, len) < len)
90 			break;
91 
92 		/* wait 1/10th second for a reply and try again */
93 		alarm(100);
94 		n = read(fd, buf, sizeof(buf));
95 		alarm(0);
96 		if(n <= 0)
97 			continue;
98 
99 		/* an answer to our echo request? */
100 		x = (ip->seq[1]<<8)|ip->seq[0];
101 		if(n >= len)
102 		if(ip->type == EchoReply)
103 		if(x == sseq)
104 		if(strcmp((char*)ip->data, MSG) == 0){
105 			rv = 1;
106 			break;
107 		}
108 	}
109 	close(fd);
110 	return rv;
111 }
112