netlog.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. #include "u.h"
  2. #include "../port/lib.h"
  3. #include "mem.h"
  4. #include "dat.h"
  5. #include "fns.h"
  6. #include "../port/error.h"
  7. #include "../ip/ip.h"
  8. enum {
  9. Nlog = 16*1024,
  10. };
  11. /*
  12. * action log
  13. */
  14. struct Netlog {
  15. Lock;
  16. int opens;
  17. char* buf;
  18. char *end;
  19. char *rptr;
  20. int len;
  21. int logmask; /* mask of things to debug */
  22. uchar iponly[IPaddrlen]; /* ip address to print debugging for */
  23. int iponlyset;
  24. QLock;
  25. Rendez;
  26. };
  27. typedef struct Netlogflag {
  28. char* name;
  29. int mask;
  30. } Netlogflag;
  31. static Netlogflag flags[] =
  32. {
  33. { "ppp", Logppp, },
  34. { "ip", Logip, },
  35. { "fs", Logfs, },
  36. { "tcp", Logtcp, },
  37. { "icmp", Logicmp, },
  38. { "udp", Logudp, },
  39. { "compress", Logcompress, },
  40. { "gre", Loggre, },
  41. { "tcpwin", Logtcp|Logtcpwin, },
  42. { "tcprxmt", Logtcp|Logtcprxmt, },
  43. { "udpmsg", Logudp|Logudpmsg, },
  44. { "ipmsg", Logip|Logipmsg, },
  45. { "esp", Logesp, },
  46. { nil, 0, },
  47. };
  48. char Ebadnetctl[] = "too few arguments for netlog control message";
  49. enum
  50. {
  51. CMset,
  52. CMclear,
  53. CMonly,
  54. };
  55. static
  56. Cmdtab routecmd[] = {
  57. CMset, "set", 0,
  58. CMclear, "clear", 0,
  59. CMonly, "only", 0,
  60. };
  61. void
  62. netloginit(Fs *f)
  63. {
  64. f->alog = smalloc(sizeof(Netlog));
  65. }
  66. void
  67. netlogopen(Fs *f)
  68. {
  69. lock(f->alog);
  70. if(waserror()){
  71. unlock(f->alog);
  72. nexterror();
  73. }
  74. if(f->alog->opens == 0){
  75. if(f->alog->buf == nil)
  76. f->alog->buf = malloc(Nlog);
  77. f->alog->rptr = f->alog->buf;
  78. f->alog->end = f->alog->buf + Nlog;
  79. }
  80. f->alog->opens++;
  81. unlock(f->alog);
  82. poperror();
  83. }
  84. void
  85. netlogclose(Fs *f)
  86. {
  87. lock(f->alog);
  88. if(waserror()){
  89. unlock(f->alog);
  90. nexterror();
  91. }
  92. f->alog->opens--;
  93. if(f->alog->opens == 0){
  94. free(f->alog->buf);
  95. f->alog->buf = nil;
  96. }
  97. unlock(f->alog);
  98. poperror();
  99. }
  100. static int
  101. netlogready(void *a)
  102. {
  103. Fs *f = a;
  104. return f->alog->len;
  105. }
  106. long
  107. netlogread(Fs *f, void *a, ulong, long n)
  108. {
  109. int i, d;
  110. char *p, *rptr;
  111. qlock(f->alog);
  112. if(waserror()){
  113. qunlock(f->alog);
  114. nexterror();
  115. }
  116. for(;;){
  117. lock(f->alog);
  118. if(f->alog->len){
  119. if(n > f->alog->len)
  120. n = f->alog->len;
  121. d = 0;
  122. rptr = f->alog->rptr;
  123. f->alog->rptr += n;
  124. if(f->alog->rptr >= f->alog->end){
  125. d = f->alog->rptr - f->alog->end;
  126. f->alog->rptr = f->alog->buf + d;
  127. }
  128. f->alog->len -= n;
  129. unlock(f->alog);
  130. i = n-d;
  131. p = a;
  132. memmove(p, rptr, i);
  133. memmove(p+i, f->alog->buf, d);
  134. break;
  135. }
  136. else
  137. unlock(f->alog);
  138. sleep(f->alog, netlogready, f);
  139. }
  140. qunlock(f->alog);
  141. poperror();
  142. return n;
  143. }
  144. void
  145. netlogctl(Fs *f, char* s, int n)
  146. {
  147. int i, set;
  148. Netlogflag *fp;
  149. Cmdbuf *cb;
  150. Cmdtab *ct;
  151. cb = parsecmd(s, n);
  152. if(waserror()){
  153. free(cb);
  154. nexterror();
  155. }
  156. if(cb->nf < 2)
  157. error(Ebadnetctl);
  158. ct = lookupcmd(cb, routecmd, nelem(routecmd));
  159. SET(set);
  160. switch(ct->index){
  161. case CMset:
  162. set = 1;
  163. break;
  164. case CMclear:
  165. set = 0;
  166. break;
  167. case CMonly:
  168. parseip(f->alog->iponly, cb->f[1]);
  169. if(ipcmp(f->alog->iponly, IPnoaddr) == 0)
  170. f->alog->iponlyset = 0;
  171. else
  172. f->alog->iponlyset = 1;
  173. free(cb);
  174. return;
  175. default:
  176. cmderror(cb, "unknown ip control message");
  177. }
  178. for(i = 1; i < cb->nf; i++){
  179. for(fp = flags; fp->name; fp++)
  180. if(strcmp(fp->name, cb->f[i]) == 0)
  181. break;
  182. if(fp->name == nil)
  183. continue;
  184. if(set)
  185. f->alog->logmask |= fp->mask;
  186. else
  187. f->alog->logmask &= ~fp->mask;
  188. }
  189. free(cb);
  190. poperror();
  191. }
  192. void
  193. netlog(Fs *f, int mask, char *fmt, ...)
  194. {
  195. char buf[128], *t, *fp;
  196. int i, n;
  197. va_list arg;
  198. if(!(f->alog->logmask & mask))
  199. return;
  200. if(f->alog->opens == 0)
  201. return;
  202. va_start(arg, fmt);
  203. n = vseprint(buf, buf+sizeof(buf), fmt, arg) - buf;
  204. va_end(arg);
  205. lock(f->alog);
  206. i = f->alog->len + n - Nlog;
  207. if(i > 0){
  208. f->alog->len -= i;
  209. f->alog->rptr += i;
  210. if(f->alog->rptr >= f->alog->end)
  211. f->alog->rptr = f->alog->buf + (f->alog->rptr - f->alog->end);
  212. }
  213. t = f->alog->rptr + f->alog->len;
  214. fp = buf;
  215. f->alog->len += n;
  216. while(n-- > 0){
  217. if(t >= f->alog->end)
  218. t = f->alog->buf + (t - f->alog->end);
  219. *t++ = *fp++;
  220. }
  221. unlock(f->alog);
  222. wakeup(f->alog);
  223. }