icmp.c
上传用户:hepax88
上传日期:2007-01-03
资源大小:1101k
文件大小:7k
源码类别:

TCP/IP协议栈

开发平台:

Visual C++

  1. /* Internet Control Message Protocol (ICMP)
  2.  * Copyright 1991 Phil Karn, KA9Q
  3.  */
  4. #include <stdio.h>
  5. #include "global.h"
  6. #include "mbuf.h"
  7. #include "iface.h"
  8. #include "ip.h"
  9. #include "icmp.h"
  10. #include "ping.h"
  11. #include "netuser.h"
  12. struct mib_entry Icmp_mib[] = {
  13. "", 0,
  14. "icmpInMsgs", 0,
  15. "icmpInErrors", 0,
  16. "icmpInDestUnreachs", 0,
  17. "icmpInTimeExcds", 0,
  18. "icmpInParmProbs", 0,
  19. "icmpInSrcQuenchs", 0,
  20. "icmpInRedirects", 0,
  21. "icmpInEchos", 0,
  22. "icmpInEchoReps", 0,
  23. "icmpInTimestamps", 0,
  24. "icmpInTimestampReps", 0,
  25. "icmpInAddrMasks", 0,
  26. "icmpInAddrMaskReps", 0,
  27. "icmpOutMsgs", 0,
  28. "icmpOutErrors", 0,
  29. "icmpOutDestUnreachs", 0,
  30. "icmpOutTimeExcds", 0,
  31. "icmpOutParmProbs", 0,
  32. "icmpOutSrcQuenchs", 0,
  33. "icmpOutRedirects", 0,
  34. "icmpOutEchos", 0,
  35. "icmpOutEchoReps", 0,
  36. "icmpOutTimestamps", 0,
  37. "icmpOutTimestampReps", 0,
  38. "icmpOutAddrMasks", 0,
  39. "icmpOutAddrMaskReps", 0,
  40. };
  41. /* Process an incoming ICMP packet */
  42. void
  43. icmp_input(
  44. struct iface *iface, /* Incoming interface (ignored) */
  45. struct ip *ip, /* Pointer to decoded IP header structure */
  46. struct mbuf **bpp, /* Pointer to ICMP message */
  47. int rxbroadcast,
  48. int32 said
  49. ){
  50. struct icmplink *ipp;
  51. struct icmp icmp; /* ICMP header */
  52. struct ip oip; /* Offending datagram header */
  53. uint16 type; /* Type of ICMP message */
  54. uint16 length;
  55. icmpInMsgs++;
  56. if(rxbroadcast){
  57. /* Broadcast ICMP packets are to be IGNORED !! */
  58. icmpInErrors++;
  59. free_p(bpp);
  60. return;
  61. }
  62. length = ip->length - IPLEN - ip->optlen;
  63. if(cksum(NULL,*bpp,length) != 0){
  64. /* Bad ICMP checksum; discard */
  65. icmpInErrors++;
  66. free_p(bpp);
  67. return;
  68. }
  69. ntohicmp(&icmp,bpp);
  70. /* Process the message. Some messages are passed up to the protocol
  71.  * module for handling, others are handled here.
  72.  */
  73. type = icmp.type;
  74. switch(type){
  75. case ICMP_TIME_EXCEED: /* Time-to-live Exceeded */
  76. case ICMP_DEST_UNREACH: /* Destination Unreachable */
  77. case ICMP_QUENCH: /* Source Quench */
  78. case ICMP_IPSP: /* Bad security packet */
  79. switch(type){
  80. case ICMP_TIME_EXCEED: /* Time-to-live Exceeded */
  81. icmpInTimeExcds++;
  82. break;
  83. case ICMP_DEST_UNREACH: /* Destination Unreachable */
  84. icmpInDestUnreachs++;
  85. break;
  86. case ICMP_QUENCH: /* Source Quench */
  87. icmpInSrcQuenchs++;
  88. break;
  89. }
  90. ntohip(&oip,bpp); /* Extract offending IP header */
  91. if(Icmp_trace){
  92. printf("ICMP from %s:",inet_ntoa(ip->source));
  93. printf(" dest %s %s",inet_ntoa(oip.dest),
  94.  smsg(Icmptypes,ICMP_TYPES,type));
  95. switch(type){
  96. case ICMP_TIME_EXCEED:
  97. printf(" %sn",
  98.  smsg(Exceed,NEXCEED,icmp.code));
  99. break;
  100. case ICMP_DEST_UNREACH:
  101. printf(" %sn",
  102.  smsg(Unreach,NUNREACH,icmp.code));
  103. break;
  104. case ICMP_IPSP:
  105. printf(" %sn",smsg(Said_icmp,NIPSP,icmp.code));
  106. break;
  107. default:
  108. printf(" %un",icmp.code);
  109. break;
  110. }
  111. }
  112. for(ipp = Icmplink;ipp->funct != NULL;ipp++)
  113. if(ipp->proto == oip.protocol)
  114. break;
  115. if(ipp->funct != NULL){
  116. (*ipp->funct)(ip->source,oip.source,oip.dest,icmp.type,
  117.  icmp.code,bpp);
  118. }
  119. break;
  120. case ICMP_ECHO: /* Echo Request */
  121. /* Change type to ECHO_REPLY, recompute checksum,
  122.  * and return datagram.
  123.  */
  124. icmpInEchos++;
  125. icmp.type = ICMP_ECHO_REPLY;
  126. htonicmp(&icmp,bpp);
  127. icmpOutEchoReps++;
  128. ip_send(ip->dest,ip->source,ICMP_PTCL,ip->tos,0,bpp,length,0,0);
  129. return;
  130. case ICMP_REDIRECT: /* Redirect */
  131. icmpInRedirects++;
  132. ntohip(&oip,bpp); /* Extract offending IP header */
  133. if(Icmp_trace){
  134. printf("ICMP from %s:",inet_ntoa(ip->source));
  135. printf(" dest %s %s",inet_ntoa(oip.dest),
  136.  smsg(Icmptypes,ICMP_TYPES,type));
  137. printf(" new gateway %sn",inet_ntoa(icmp.args.address));
  138. }
  139. break;
  140. case ICMP_PARAM_PROB: /* Parameter Problem */
  141. icmpInParmProbs++;
  142. break;
  143. case ICMP_ECHO_REPLY: /* Echo Reply */
  144. icmpInEchoReps++;
  145. echo_proc(ip->source,ip->dest,&icmp,bpp);
  146. break;
  147. case ICMP_TIMESTAMP: /* Timestamp */
  148. icmpInTimestamps++;
  149. break;
  150. case ICMP_TIME_REPLY: /* Timestamp Reply */
  151. icmpInTimestampReps++;
  152. break;
  153. case ICMP_INFO_RQST: /* Information Request */
  154. break;
  155. case ICMP_INFO_REPLY: /* Information Reply */
  156. break;
  157. }
  158. free_p(bpp);
  159. }
  160. /* Return an ICMP response to the sender of a datagram.
  161.  * Unlike most routines, the callER frees the mbuf.
  162.  */
  163. int
  164. icmp_output(
  165. struct ip *ip, /* Header of offending datagram */
  166. struct mbuf *data, /* Data portion of datagram - FREED BY CALLER */
  167. uint8 type, /* Codes to send */
  168. uint8 code,
  169. union icmp_args *args
  170. ){
  171. struct mbuf *bp;
  172. struct icmp icmp; /* ICMP protocol header */
  173. uint16 dlen; /* Length of data portion of offending pkt */
  174. uint16 length; /* Total length of reply */
  175. if(ip == NULL)
  176. return -1;
  177. if(ip->protocol == ICMP_PTCL){
  178. /* Peek at type field of ICMP header to see if it's safe to
  179.  * return an ICMP message
  180.  */
  181. switch(data->data[0]){
  182. case ICMP_ECHO_REPLY:
  183. case ICMP_ECHO:
  184. case ICMP_TIMESTAMP:
  185. case ICMP_TIME_REPLY:
  186. case ICMP_INFO_RQST:
  187. case ICMP_INFO_REPLY:
  188. break; /* These are all safe */
  189. default:
  190. /* Never send an ICMP error message about another
  191.  * ICMP error message!
  192.  */
  193. return -1;
  194. }
  195. }
  196. /* Compute amount of original datagram to return.
  197.  * We return the original IP header, and up to 8 bytes past that.
  198.  */
  199. dlen = min(8,len_p(data));
  200. length = dlen + ICMPLEN + IPLEN + ip->optlen;
  201. /* Take excerpt from data portion */
  202. if(data != NULL && dup_p(&bp,data,0,dlen) == 0)
  203. return -1; /* The caller will free data */
  204. /* Recreate and tack on offending IP header */
  205. htonip(ip,&bp,IP_CS_NEW);
  206. icmp.type = type;
  207. icmp.code = code;
  208. icmp.args.unused = 0;
  209. switch(icmp.type){
  210. case ICMP_PARAM_PROB:
  211. icmpOutParmProbs++;
  212. icmp.args.pointer = args->pointer;
  213. break;
  214. case ICMP_REDIRECT:
  215. icmpOutRedirects++;
  216. icmp.args.address = args->address;
  217. break;
  218. case ICMP_ECHO:
  219. icmpOutEchos++;
  220. break;
  221. case ICMP_ECHO_REPLY:
  222. icmpOutEchoReps++;
  223. break;
  224. case ICMP_INFO_RQST:
  225. break;
  226. case ICMP_INFO_REPLY:
  227. break;
  228. case ICMP_TIMESTAMP:
  229. icmpOutTimestamps++;
  230. break;
  231. case ICMP_TIME_REPLY:
  232. icmpOutTimestampReps++;
  233. icmp.args.echo.id = args->echo.id;
  234. icmp.args.echo.seq = args->echo.seq;
  235. break;
  236. case ICMP_ADDR_MASK:
  237. icmpOutAddrMasks++;
  238. break;
  239. case ICMP_ADDR_MASK_REPLY:
  240. icmpOutAddrMaskReps++;
  241. break;
  242. case ICMP_DEST_UNREACH:
  243. if(icmp.code == ICMP_FRAG_NEEDED)
  244. icmp.args.mtu = args->mtu;
  245. icmpOutDestUnreachs++;
  246. break;
  247. case ICMP_TIME_EXCEED:
  248. icmpOutTimeExcds++;
  249. break;
  250. case ICMP_QUENCH:
  251. icmpOutSrcQuenchs++;
  252. break;
  253. }
  254. icmpOutMsgs++;
  255. /* Now stick on the ICMP header */
  256. htonicmp(&icmp,&bp);
  257. return ip_send(INADDR_ANY,ip->source,ICMP_PTCL,ip->tos,0,&bp,length,0,0);
  258. }