]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/cifs/ping.c
kbdfs: simplfy
[plan9front.git] / sys / src / cmd / cifs / ping.c
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 }