measure.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. #include <u.h>
  10. #include <libc.h>
  11. #include <bio.h>
  12. #include <ip.h>
  13. /*
  14. * ether packet
  15. */
  16. typedef struct Etherpkt Etherpkt;
  17. struct Etherpkt {
  18. uint8_t d[6];
  19. uint8_t s[6];
  20. uint8_t type[2];
  21. char data[1500];
  22. };
  23. #define ETHERMINTU 60 /* minimum transmit size */
  24. #define ETHERMAXTU 1514 /* maximum transmit size */
  25. #define ETHERHDRSIZE 14 /* size of an ethernet header */
  26. /*
  27. * ip packets
  28. */
  29. typedef struct Ippkt Ippkt;
  30. struct Ippkt
  31. {
  32. uint8_t vihl; /* Version and header length */
  33. uint8_t tos; /* Type of service */
  34. uint8_t length[2]; /* packet length */
  35. uint8_t id[2]; /* Identification */
  36. uint8_t frag[2]; /* Fragment information */
  37. uint8_t ttl; /* Time to live */
  38. uint8_t proto; /* Protocol */
  39. uint8_t cksum[2]; /* Header checksum */
  40. uint8_t src[4]; /* Ip source */
  41. uint8_t dst[4]; /* Ip destination */
  42. char data[1];
  43. };
  44. #define IP_HDRSIZE 20
  45. #define IP_UDPPROTO 17
  46. #define IP_MBONEPROTO 4
  47. #define IP_TCPPROTO 6
  48. #define IP_ILPROTO 40
  49. #define IP_ICMPPROTO 1
  50. #define IP_DF 0x4000
  51. #define IP_MF 0x2000
  52. #define NetS(x) (((x)[0]<<8) | (x)[1])
  53. #define NetL(x) (((x)[0]<<24) | ((x)[1]<<16) | ((x)[2]<<8) | (x)[3])
  54. /*
  55. * run flags
  56. */
  57. int debug;
  58. int mbone;
  59. uint32_t protoin[256];
  60. uint32_t protoout[256];
  61. uint32_t protopin[256];
  62. uint32_t protopout[256];
  63. void
  64. error(char *s)
  65. {
  66. char buf[ERRMAX];
  67. errstr(buf, sizeof buf);
  68. fprint(2, "snoopy: %s %s\n", buf, s);
  69. exits("death");
  70. }
  71. void
  72. warning(char *s)
  73. {
  74. char buf[ERRMAX];
  75. errstr(buf, sizeof buf);
  76. fprint(2, "snoopy: %s %s\n", buf, s);
  77. }
  78. void
  79. printproto(int p)
  80. {
  81. print("\t%d(%ld %ld %ld %ld)", p, protoin[p], protopin[p], protoout[p], protopout[p]);
  82. }
  83. void
  84. main(int argc, char *argv[])
  85. {
  86. Etherpkt e;
  87. Ippkt *ip;
  88. long n;
  89. int fd, cfd;
  90. int ts, len, t;
  91. long start;
  92. int delta;
  93. uint8_t target[6];
  94. char buf[256];
  95. uintptr samples;
  96. samples = -1;
  97. ARGBEGIN{
  98. case 'd':
  99. debug++;
  100. break;
  101. case 's':
  102. samples = atoi(ARGF());
  103. break;
  104. }ARGEND;
  105. if(argc < 2){
  106. fprint(2, "usage: %s device ip-addr [minutes-per-sample]\n", argv0);
  107. exits("usage");
  108. }
  109. if(argc > 2)
  110. delta = atoi(argv[2])*60*1000;
  111. else
  112. delta = 5*60*1000;
  113. parseether(target, argv[1]);
  114. fmtinstall('E', eipfmt);
  115. fmtinstall('I', eipfmt);
  116. snprint(buf, sizeof(buf), "%s!-2", argv[0]);
  117. fd = dial(buf, 0, 0, &cfd);
  118. if(fd < 0)
  119. error("opening ether data");
  120. if(write(cfd, "promiscuous", sizeof("promiscuous")-1) <= 0)
  121. error("connecting");
  122. start = 0;
  123. fd = -1;
  124. for(;;){
  125. if(fd < 0){
  126. fd = dial(buf, 0, 0, &cfd);
  127. if(fd < 0)
  128. error("opening ether data");
  129. if(write(cfd, "promiscuous", sizeof("promiscuous")-1) <= 0)
  130. error("connecting");
  131. close(cfd);
  132. }
  133. n = read(fd, &e, sizeof(e));
  134. if(n <= 0)
  135. break;
  136. ts = NetL(&e.d[60]);
  137. n = NetS(&e.d[58]) - ETHERHDRSIZE;
  138. if(n < 0)
  139. continue;
  140. if(start == 0)
  141. start = ts;
  142. t = NetS(e.type);
  143. if(t == 0x0800 || (t&0xFF00) == 0x1000){
  144. ip = (Ippkt*)e.data;
  145. len = NetS(ip->length);
  146. if(len > n)
  147. len = n;
  148. if(debug)
  149. fprint(2, "%I -> %I %d\n", ip->src, ip->dst, len);
  150. if(memcmp(e.s, target, 6) == 0){
  151. protopin[0]++;
  152. protoin[0] += len;
  153. if(ip->proto){
  154. protopin[ip->proto]++;
  155. protoin[ip->proto] += len;
  156. }
  157. }
  158. if(memcmp(e.d, target, 6) == 0){
  159. protopout[0]++;
  160. protoout[0] += len;
  161. if(ip->proto){
  162. protopout[ip->proto]++;
  163. protoout[ip->proto] += len;
  164. }
  165. }
  166. }
  167. if(ts - start >= delta){
  168. print("%8.8ld %ld", time(0), ts - start);
  169. printproto(0);
  170. printproto(IP_MBONEPROTO);
  171. printproto(IP_UDPPROTO);
  172. printproto(IP_TCPPROTO);
  173. print("\n");
  174. start = 0;
  175. memset(protoin, 0, sizeof(protoin));
  176. memset(protoout, 0, sizeof(protoout));
  177. memset(protopin, 0, sizeof(protopin));
  178. memset(protopout, 0, sizeof(protopout));
  179. close(fd);
  180. fd = -1;
  181. if(--samples == 0)
  182. break;
  183. }
  184. }
  185. exits(0);
  186. }