icmp.c 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <ip.h>
  4. #include "dat.h"
  5. #include "protos.h"
  6. typedef struct Hdr Hdr;
  7. struct Hdr
  8. { uchar type;
  9. uchar code;
  10. uchar cksum[2]; /* Checksum */
  11. uchar data[1];
  12. };
  13. enum
  14. {
  15. ICMPLEN= 4,
  16. };
  17. enum
  18. {
  19. Ot, /* type */
  20. Op, /* next protocol */
  21. };
  22. static Field p_fields[] =
  23. {
  24. {"t", Fnum, Ot, "type", } ,
  25. {0}
  26. };
  27. enum
  28. {
  29. EchoRep= 0,
  30. Unreachable= 3,
  31. SrcQuench= 4,
  32. Redirect= 5,
  33. EchoReq= 8,
  34. TimeExceed= 11,
  35. ParamProb= 12,
  36. TSreq= 13,
  37. TSrep= 14,
  38. InfoReq= 15,
  39. InfoRep= 16,
  40. };
  41. static Mux p_mux[] =
  42. {
  43. {"ip", Unreachable, },
  44. {"ip", SrcQuench, },
  45. {"ip", Redirect, },
  46. {"ip", TimeExceed, },
  47. {"ip", ParamProb, },
  48. {0},
  49. };
  50. char *icmpmsg[236] =
  51. {
  52. [EchoRep] "EchoRep",
  53. [Unreachable] "Unreachable",
  54. [SrcQuench] "SrcQuench",
  55. [Redirect] "Redirect",
  56. [EchoReq] "EchoReq",
  57. [TimeExceed] "TimeExceed",
  58. [ParamProb] "ParamProb",
  59. [TSreq] "TSreq",
  60. [TSrep] "TSrep",
  61. [InfoReq] "InfoReq",
  62. [InfoRep] "InfoRep",
  63. };
  64. static void
  65. p_compile(Filter *f)
  66. {
  67. if(f->op == '='){
  68. compile_cmp(icmp.name, f, p_fields);
  69. return;
  70. }
  71. if(strcmp(f->s, "ip") == 0){
  72. f->pr = p_mux->pr;
  73. f->subop = Op;
  74. return;
  75. }
  76. sysfatal("unknown icmp field or protocol: %s", f->s);
  77. }
  78. static int
  79. p_filter(Filter *f, Msg *m)
  80. {
  81. Hdr *h;
  82. if(m->pe - m->ps < ICMPLEN)
  83. return 0;
  84. h = (Hdr*)m->ps;
  85. m->ps += ICMPLEN;
  86. switch(f->subop){
  87. case Ot:
  88. if(h->type == f->ulv)
  89. return 1;
  90. break;
  91. case Op:
  92. switch(h->type){
  93. case Unreachable:
  94. case TimeExceed:
  95. case SrcQuench:
  96. case Redirect:
  97. case ParamProb:
  98. m->ps += 4;
  99. return 1;
  100. }
  101. }
  102. return 0;
  103. }
  104. static int
  105. p_seprint(Msg *m)
  106. {
  107. Hdr *h;
  108. char *tn;
  109. char *p = m->p;
  110. char *e = m->e;
  111. ushort cksum2, cksum;
  112. h = (Hdr*)m->ps;
  113. m->ps += ICMPLEN;
  114. m->pr = &dump;
  115. if(m->pe - m->ps < ICMPLEN)
  116. return -1;
  117. tn = icmpmsg[h->type];
  118. if(tn == nil)
  119. p = seprint(p, e, "t=%ud c=%d ck=%4.4ux", h->type,
  120. h->code, (ushort)NetS(h->cksum));
  121. else
  122. p = seprint(p, e, "t=%s c=%d ck=%4.4ux", tn,
  123. h->code, (ushort)NetS(h->cksum));
  124. if(Cflag){
  125. cksum = NetS(h->cksum);
  126. h->cksum[0] = 0;
  127. h->cksum[1] = 0;
  128. cksum2 = ~ptclbsum((uchar*)h, m->pe - m->ps + ICMPLEN) & 0xffff;
  129. if(cksum != cksum2)
  130. p = seprint(p,e, " !ck=%4.4ux", cksum2);
  131. }
  132. switch(h->type){
  133. case EchoRep:
  134. case EchoReq:
  135. m->ps += 4;
  136. p = seprint(p, e, " id=%ux seq=%ux",
  137. NetS(h->data), NetS(h->data+2));
  138. break;
  139. case TSreq:
  140. case TSrep:
  141. m->ps += 12;
  142. p = seprint(p, e, " orig=%ud rcv=%ux xmt=%ux",
  143. NetL(h->data), NetL(h->data+4),
  144. NetL(h->data+8));
  145. m->pr = nil;
  146. break;
  147. case InfoReq:
  148. case InfoRep:
  149. break;
  150. case Unreachable:
  151. case TimeExceed:
  152. case SrcQuench:
  153. m->ps += 4;
  154. m->pr = &ip;
  155. break;
  156. case Redirect:
  157. m->ps += 4;
  158. m->pr = &ip;
  159. p = seprint(p, e, "gw=%V", h->data);
  160. break;
  161. case ParamProb:
  162. m->ps += 4;
  163. m->pr = &ip;
  164. p = seprint(p, e, "ptr=%2.2ux", h->data[0]);
  165. break;
  166. }
  167. m->p = p;
  168. return 0;
  169. }
  170. Proto icmp =
  171. {
  172. "icmp",
  173. p_compile,
  174. p_filter,
  175. p_seprint,
  176. p_mux,
  177. "%lud",
  178. p_fields,
  179. defaultframer,
  180. };