diff options
author | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
---|---|---|
committer | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
commit | e5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch) | |
tree | d8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/cmd/cifs/ping.c |
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/cmd/cifs/ping.c')
-rwxr-xr-x | sys/src/cmd/cifs/ping.c | 132 |
1 files changed, 132 insertions, 0 deletions
diff --git a/sys/src/cmd/cifs/ping.c b/sys/src/cmd/cifs/ping.c new file mode 100755 index 000000000..0aaaaa7e8 --- /dev/null +++ b/sys/src/cmd/cifs/ping.c @@ -0,0 +1,132 @@ +#include <u.h> +#include <libc.h> +#include <fcall.h> +#include <thread.h> +#include <libsec.h> +#include <9p.h> + +extern char *Debug; + +typedef struct Pingcache Pingcache; +struct Pingcache { + Pingcache*next; + long rtt; + char *host; + long expire; +}; + +typedef struct { + 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]; +} Icmp; + +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, + + Npings = 8, + Payload = 32, + + Cachetime = 60, +}; + +static Pingcache *Cache; + +/* + * We ignore the first result as that is probably bigger + * than expected due to IP sorting out the routing to the host + */ +int +ping(char *host, int timeout) +{ + int rtt, fd, i, seq; + long now; + vlong then; + uchar buf[128]; + Icmp *ip; + Pingcache *c; + + now = time(nil); + for(c = Cache; c; c = c->next) + if(strcmp(c->host, host) == 0 && now < c->expire){ + if(Debug && strstr(Debug, "dfs") != nil) + print("\t\tping host=%s timeout=%d - cache hit\n", + host, timeout); + return c->rtt; + } + + rtt = -1; + ip = (Icmp*)buf; + + if((fd = dial(netmkaddr(host, "icmp", "1"), 0, 0, 0)) == -1) + goto fail; + + for(seq = 0; seq < Npings; seq++){ + then = nsec(); + for(i = Payload; i < sizeof buf; i++) + buf[i] = i + seq; + ip->type = EchoRequest; + ip->code = 0; + ip->seq[0] = seq; + ip->seq[1] = seq; + alarm(timeout); + if(write(fd, ip, sizeof buf) != sizeof buf || + read(fd, ip, sizeof buf) != sizeof buf) + goto fail; + alarm(0); + if(ip->type != EchoReply || ip->code != 0 || + ip->seq[0] != seq || ip->seq[1] != seq) + goto fail; + for(i = Payload; i < sizeof buf; i++) + if((uchar)buf[i] != (uchar)(i + seq)) + goto fail; + rtt = (rtt + nsec() - then) / 2; + } +fail: + if(fd != -1) + close(fd); + + if(Debug && strstr(Debug, "dfs") != nil) + print("\t\tping host=%s timeout=%d rtt=%d - failed\n", + host, timeout, rtt); + + /* + * failures get cached too + */ + for(c = Cache; c; c = c->next) + if(strcmp(c->host, host) == 0) + break; + if(c == nil){ + c = emalloc9p(sizeof(Pingcache)); + c->host = estrdup9p(host); + c->next = Cache; + Cache = c; + } + c->rtt = rtt; + c->expire = now+Cachetime; + return rtt; +} |