summaryrefslogtreecommitdiff
path: root/sys/src/cmd/ip/dhcpd/ping.c
blob: 003f6c60893efa98c78316c0151334d68a7f39af (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
#include <u.h>
#include <libc.h>
#include <ip.h>
#include "../icmp.h"

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
 *  TODO: ipv6 ping
 */
int
icmpecho(uchar *a)
{
	int fd, i, n, len, rv;
	ushort sseq, x;
	char buf[512];
	Icmphdr *ip;

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

	sseq = getpid()*time(0);

	ip = (Icmphdr *)(buf + IPV4HDR_LEN);
	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 = IPV4HDR_LEN + 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 && ip->type == EchoReply && x == sseq &&
		    strcmp((char*)ip->data, MSG) == 0){
			rv = 1;
			break;
		}
	}
	close(fd);
	return rv;
}