Warning: Attempt to read property "date" on null in /usr/local/www/websvn.planix.org/blame.php on line 247

Warning: Attempt to read property "msg" on null in /usr/local/www/websvn.planix.org/blame.php on line 247
WebSVN – planix.SVN – Blame – /os/branches/feature_unix/sys/src/cmd/cifs/ping.c – Rev 2

Subversion Repositories planix.SVN

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include <u.h>
2
#include <libc.h>
3
#include <fcall.h>
4
#include <thread.h>
5
#include <libsec.h>
6
#include <9p.h>
7
 
8
extern char *Debug;
9
 
10
typedef struct Pingcache Pingcache;
11
struct Pingcache {
12
	Pingcache*next;
13
	long	rtt;
14
	char	*host;
15
	long	expire;
16
};
17
 
18
typedef struct {
19
	uchar	vihl;		/* Version and header length */
20
	uchar	tos;		/* Type of service */
21
	uchar	length[2];	/* packet length */
22
	uchar	id[2];		/* Identification */
23
	uchar	frag[2];	/* Fragment information */
24
	uchar	ttl;		/* Time to live */
25
	uchar	proto;		/* Protocol */
26
	uchar	ipcksum[2];	/* Header checksum */
27
	uchar	src[4];		/* Ip source */
28
	uchar	dst[4];		/* Ip destination */
29
	uchar	type;
30
	uchar	code;
31
	uchar	cksum[2];
32
	uchar	icmpid[2];
33
	uchar	seq[2];
34
	uchar	data[1];
35
} Icmp;
36
 
37
enum {			/* Packet Types */
38
	EchoReply	= 0,
39
	Unreachable	= 3,
40
	SrcQuench	= 4,
41
	EchoRequest	= 8,
42
	TimeExceed	= 11,
43
	Timestamp	= 13,
44
	TimestampReply	= 14,
45
	InfoRequest	= 15,
46
	InfoReply	= 16,
47
 
48
	ICMP_IPSIZE	= 20,
49
	ICMP_HDRSIZE	= 8,
50
 
51
	Npings		= 8,
52
	Payload		= 32,
53
 
54
	Cachetime	= 60,
55
};
56
 
57
static Pingcache *Cache;
58
 
59
/*
60
 * We ignore the first result as that is probably bigger
61
 * than expected due to IP sorting out the routing to the host
62
 */
63
int
64
ping(char *host, int timeout)
65
{
66
	int rtt, fd, i, seq;
67
	long now;
68
	vlong then;
69
	uchar buf[128];
70
	Icmp *ip;
71
	Pingcache *c;
72
 
73
	now = time(nil);
74
	for(c = Cache; c; c = c->next)
75
		if(strcmp(c->host, host) == 0 && now < c->expire){
76
			if(Debug && strstr(Debug, "dfs") != nil)
77
				print("\t\tping host=%s timeout=%d - cache hit\n",
78
					host, timeout);
79
			return c->rtt;
80
		}
81
 
82
	rtt = -1;
83
	ip = (Icmp*)buf;
84
 
85
	if((fd = dial(netmkaddr(host, "icmp", "1"), 0, 0, 0)) == -1)
86
		goto fail;
87
 
88
	for(seq = 0; seq < Npings; seq++){
89
		then = nsec();
90
		for(i = Payload; i < sizeof buf; i++)
91
			buf[i] = i + seq;
92
		ip->type = EchoRequest;
93
		ip->code = 0;
94
		ip->seq[0] = seq;
95
		ip->seq[1] = seq;
96
		alarm(timeout);
97
		if(write(fd, ip, sizeof buf) != sizeof buf ||
98
		    read(fd, ip, sizeof buf) != sizeof buf)
99
			goto fail;
100
		alarm(0);
101
		if(ip->type != EchoReply || ip->code != 0 ||
102
		    ip->seq[0] != seq || ip->seq[1] != seq)
103
			goto fail;
104
		for(i = Payload; i < sizeof buf; i++)
105
			if((uchar)buf[i] != (uchar)(i + seq))
106
				goto fail;
107
		rtt = (rtt + nsec() - then) / 2;
108
	}
109
fail:
110
	if(fd != -1)
111
		close(fd);
112
 
113
	if(Debug && strstr(Debug, "dfs") != nil)
114
		print("\t\tping host=%s timeout=%d rtt=%d - failed\n",
115
			host, timeout, rtt);
116
 
117
	/*
118
	 * failures get cached too
119
	 */
120
	for(c = Cache; c; c = c->next)
121
		if(strcmp(c->host, host) == 0)
122
			break;
123
	if(c == nil){
124
		c = emalloc9p(sizeof(Pingcache));
125
		c->host = estrdup9p(host);
126
		c->next = Cache;
127
		Cache = c;
128
	}
129
	c->rtt = rtt;
130
	c->expire = now+Cachetime;
131
	return rtt;
132
}