icmp.c
上传用户:liugui
上传日期:2007-01-04
资源大小:822k
文件大小:6k
源码类别:

代理服务器

开发平台:

Unix_Linux

  1. /*
  2.  * $Id: icmp.c,v 1.69 1998/12/05 00:54:29 wessels Exp $
  3.  *
  4.  * DEBUG: section 37    ICMP Routines
  5.  * AUTHOR: Duane Wessels
  6.  *
  7.  * SQUID Internet Object Cache  http://squid.nlanr.net/Squid/
  8.  * ----------------------------------------------------------
  9.  *
  10.  *  Squid is the result of efforts by numerous individuals from the
  11.  *  Internet community.  Development is led by Duane Wessels of the
  12.  *  National Laboratory for Applied Network Research and funded by the
  13.  *  National Science Foundation.  Squid is Copyrighted (C) 1998 by
  14.  *  Duane Wessels and the University of California San Diego.  Please
  15.  *  see the COPYRIGHT file for full details.  Squid incorporates
  16.  *  software developed and/or copyrighted by other sources.  Please see
  17.  *  the CREDITS file for full details.
  18.  *
  19.  *  This program is free software; you can redistribute it and/or modify
  20.  *  it under the terms of the GNU General Public License as published by
  21.  *  the Free Software Foundation; either version 2 of the License, or
  22.  *  (at your option) any later version.
  23.  *  
  24.  *  This program is distributed in the hope that it will be useful,
  25.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  26.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  27.  *  GNU General Public License for more details.
  28.  *  
  29.  *  You should have received a copy of the GNU General Public License
  30.  *  along with this program; if not, write to the Free Software
  31.  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
  32.  *
  33.  */
  34. #include "squid.h"
  35. #if USE_ICMP
  36. #define S_ICMP_ECHO 1
  37. #if ALLOW_SOURCE_PING
  38. #define S_ICMP_ICP 2
  39. #endif
  40. #define S_ICMP_DOM 3
  41. static PF icmpRecv;
  42. static void icmpSend(pingerEchoData * pkt, int len);
  43. #if ALLOW_SOURCE_PING
  44. static void icmpHandleSourcePing(const struct sockaddr_in *from, const char *buf);
  45. #endif
  46. static void
  47. icmpSendEcho(struct in_addr to, int opcode, const char *payload, int len)
  48. {
  49.     static pingerEchoData pecho;
  50.     if (payload && len == 0)
  51. len = strlen(payload);
  52.     pecho.to = to;
  53.     pecho.opcode = (unsigned char) opcode;
  54.     pecho.psize = len;
  55.     xmemcpy(pecho.payload, payload, len);
  56.     icmpSend(&pecho, sizeof(pingerEchoData) - PINGER_PAYLOAD_SZ + len);
  57. }
  58. static void
  59. icmpRecv(int unused1, void *unused2)
  60. {
  61.     int n;
  62.     static int fail_count = 0;
  63.     pingerReplyData preply;
  64.     static struct sockaddr_in F;
  65.     commSetSelect(icmp_sock, COMM_SELECT_READ, icmpRecv, NULL, 0);
  66.     memset(&preply, '', sizeof(pingerReplyData));
  67.     Counter.syscalls.sock.recvfroms++;
  68.     n = recv(icmp_sock,
  69. (char *) &preply,
  70. sizeof(pingerReplyData),
  71. 0);
  72.     if (n < 0) {
  73. debug(50, 1) ("icmpRecv: recv: %sn", xstrerror());
  74. if (++fail_count == 10 || errno == ECONNREFUSED)
  75.     icmpClose();
  76. return;
  77.     }
  78.     fail_count = 0;
  79.     if (n == 0) /* test probe from pinger */
  80. return;
  81.     F.sin_family = AF_INET;
  82.     F.sin_addr = preply.from;
  83.     F.sin_port = 0;
  84.     switch (preply.opcode) {
  85.     case S_ICMP_ECHO:
  86. break;
  87. #if ALLOW_SOURCE_PING
  88.     case S_ICMP_ICP:
  89. icmpHandleSourcePing(&F, preply.payload);
  90. break;
  91. #endif
  92.     case S_ICMP_DOM:
  93. netdbHandlePingReply(&F, preply.hops, preply.rtt);
  94. break;
  95.     default:
  96. debug(37, 1) ("icmpRecv: Bad opcode: %dn", (int) preply.opcode);
  97. break;
  98.     }
  99. }
  100. static void
  101. icmpSend(pingerEchoData * pkt, int len)
  102. {
  103.     int x;
  104.     if (icmp_sock < 0)
  105. return;
  106.     x = send(icmp_sock, (char *) pkt, len, 0);
  107.     if (x < 0) {
  108. debug(50, 1) ("icmpSend: send: %sn", xstrerror());
  109. if (errno == ECONNREFUSED) {
  110.     icmpClose();
  111.     return;
  112. }
  113.     } else if (x != len) {
  114. debug(37, 1) ("icmpSend: Wrote %d of %d bytesn", x, len);
  115.     }
  116. }
  117. #if ALLOW_SOURCE_PING
  118. static void
  119. icmpHandleSourcePing(const struct sockaddr_in *from, const char *buf)
  120. {
  121.     const cache_key *key;
  122.     icp_common_t header;
  123.     const char *url;
  124.     xmemcpy(&header, buf, sizeof(icp_common_t));
  125.     url = buf + sizeof(icp_common_t);
  126.     key = icpGetCacheKey(url, (int) header.reqnum);
  127.     debug(37, 3) ("icmpHandleSourcePing: from %s, key '%s'n",
  128. inet_ntoa(from->sin_addr), storeKeyText(key));
  129.     /* call neighborsUdpAck even if ping_status != PING_WAITING */
  130.     neighborsUdpAck(key, &header, from);
  131. }
  132. #endif
  133. #endif /* USE_ICMP */
  134. void
  135. icmpPing(struct in_addr to)
  136. {
  137. #if USE_ICMP
  138.     icmpSendEcho(to, S_ICMP_ECHO, NULL, 0);
  139. #endif
  140. }
  141. #if ALLOW_SOURCE_PING
  142. void
  143. icmpSourcePing(struct in_addr to, const icp_common_t * header, const char *url)
  144. {
  145. #if USE_ICMP
  146.     char *payload;
  147.     int len;
  148.     int ulen;
  149.     debug(37, 3) ("icmpSourcePing: '%s'n", url);
  150.     if ((ulen = strlen(url)) > MAX_URL)
  151. return;
  152.     payload = memAllocate(MEM_8K_BUF);
  153.     len = sizeof(icp_common_t);
  154.     xmemcpy(payload, header, len);
  155.     strcpy(payload + len, url);
  156.     len += ulen + 1;
  157.     icmpSendEcho(to, S_ICMP_ICP, payload, len);
  158.     memFree(payload, MEM_8K_BUF);
  159. #endif
  160. }
  161. #endif
  162. void
  163. icmpDomainPing(struct in_addr to, const char *domain)
  164. {
  165. #if USE_ICMP
  166.     debug(37, 3) ("icmpDomainPing: '%s'n", domain);
  167.     icmpSendEcho(to, S_ICMP_DOM, domain, 0);
  168. #endif
  169. }
  170. void
  171. icmpOpen(void)
  172. {
  173. #if USE_ICMP
  174.     char *args[2];
  175.     int x;
  176.     int rfd;
  177.     int wfd;
  178.     args[0] = "(pinger)";
  179.     args[1] = NULL;
  180.     x = ipcCreate(IPC_UDP_SOCKET,
  181. Config.Program.pinger,
  182. args,
  183. "Pinger Socket",
  184. &rfd,
  185. &wfd);
  186.     if (x < 0)
  187. return;
  188.     assert(rfd == wfd);
  189.     icmp_sock = rfd;
  190.     commSetSelect(icmp_sock, COMM_SELECT_READ, icmpRecv, NULL, 0);
  191.     commSetTimeout(icmp_sock, -1, NULL, NULL);
  192.     debug(29, 1) ("Pinger socket opened on FD %dn", icmp_sock);
  193. #endif
  194. }
  195. void
  196. icmpClose(void)
  197. {
  198. #if USE_ICMP
  199.     if (icmp_sock < 0)
  200. return;
  201.     debug(29, 1) ("Closing Pinger socket on FD %dn", icmp_sock);
  202.     comm_close(icmp_sock);
  203.     icmp_sock = -1;
  204. #endif
  205. }