iputils-20121221-owl-pingsock.diff 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. http://openwall.info/wiki/people/segoon/ping
  2. --- iputils-s20101006/ping.c
  3. +++ iputils-s20101006/ping.c
  4. @@ -88,6 +88,7 @@ struct sockaddr_in whereto; /* who to pi
  5. int optlen = 0;
  6. int settos = 0; /* Set TOS, Precendence or other QOS options */
  7. int icmp_sock; /* socket file descriptor */
  8. +int using_ping_socket = 0;
  9. u_char outpack[0x10000];
  10. int maxpacket = sizeof(outpack);
  11. @@ -123,7 +124,11 @@ main(int argc, char **argv)
  12. char *target, hnamebuf[MAX_HOSTNAMELEN];
  13. char rspace[3 + 4 * NROUTES + 1]; /* record route space */
  14. - icmp_sock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
  15. + icmp_sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_ICMP);
  16. + if (icmp_sock != -1)
  17. + using_ping_socket = 1;
  18. + else
  19. + icmp_sock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
  20. socket_errno = errno;
  21. uid = getuid();
  22. @@ -377,13 +382,35 @@ main(int argc, char **argv)
  23. }
  24. }
  25. - if ((options&F_STRICTSOURCE) &&
  26. - bind(icmp_sock, (struct sockaddr*)&source, sizeof(source)) == -1) {
  27. - perror("bind");
  28. - exit(2);
  29. + if (!using_ping_socket) {
  30. + if ((options&F_STRICTSOURCE) &&
  31. + bind(icmp_sock, (struct sockaddr*)&source, sizeof(source)) == -1) {
  32. + perror("bind");
  33. + exit(2);
  34. + }
  35. + } else {
  36. + struct sockaddr_in sa;
  37. + socklen_t sl;
  38. +
  39. + sa.sin_family = AF_INET;
  40. + sa.sin_port = 0;
  41. + sa.sin_addr.s_addr = (options&F_STRICTSOURCE) ?
  42. + source.sin_addr.s_addr : 0;
  43. + sl = sizeof(sa);
  44. +
  45. + if (bind(icmp_sock, (struct sockaddr *) &sa, sl) == -1) {
  46. + perror("bind");
  47. + exit(2);
  48. + }
  49. +
  50. + if (getsockname(icmp_sock, (struct sockaddr *) &sa, &sl) == -1) {
  51. + perror("getsockname");
  52. + exit(2);
  53. + }
  54. + ident = sa.sin_port;
  55. }
  56. - if (1) {
  57. + if (!using_ping_socket) {
  58. struct icmp_filter filt;
  59. filt.data = ~((1<<ICMP_SOURCE_QUENCH)|
  60. (1<<ICMP_DEST_UNREACH)|
  61. @@ -398,6 +425,12 @@ main(int argc, char **argv)
  62. hold = 1;
  63. if (setsockopt(icmp_sock, SOL_IP, IP_RECVERR, (char *)&hold, sizeof(hold)))
  64. fprintf(stderr, "WARNING: your kernel is veeery old. No problems.\n");
  65. + if (using_ping_socket) {
  66. + if (setsockopt(icmp_sock, SOL_IP, IP_RECVTTL, (char *)&hold, sizeof(hold)))
  67. + perror("WARNING: setsockopt(IP_RECVTTL)");
  68. + if (setsockopt(icmp_sock, SOL_IP, IP_RETOPTS, (char *)&hold, sizeof(hold)))
  69. + perror("WARNING: setsockopt(IP_RETOPTS)");
  70. + }
  71. /* record route option */
  72. if (options & F_RROUTE) {
  73. @@ -566,6 +599,7 @@ int receive_error_msg()
  74. nerrors++;
  75. } else if (e->ee_origin == SO_EE_ORIGIN_ICMP) {
  76. struct sockaddr_in *sin = (struct sockaddr_in*)(e+1);
  77. + int error_pkt;
  78. if (res < sizeof(icmph) ||
  79. target.sin_addr.s_addr != whereto.sin_addr.s_addr ||
  80. @@ -576,9 +610,18 @@ int receive_error_msg()
  81. goto out;
  82. }
  83. - acknowledge(ntohs(icmph.un.echo.sequence));
  84. + error_pkt = (e->ee_type != ICMP_REDIRECT &&
  85. + e->ee_type != ICMP_SOURCE_QUENCH);
  86. + if (error_pkt) {
  87. + acknowledge(ntohs(icmph.un.echo.sequence));
  88. + net_errors++;
  89. + nerrors++;
  90. + }
  91. + else {
  92. + saved_errno = 0;
  93. + }
  94. - if (!working_recverr) {
  95. + if (!using_ping_socket && !working_recverr) {
  96. struct icmp_filter filt;
  97. working_recverr = 1;
  98. /* OK, it works. Add stronger filter. */
  99. @@ -589,15 +632,14 @@ int receive_error_msg()
  100. perror("\rWARNING: setsockopt(ICMP_FILTER)");
  101. }
  102. - net_errors++;
  103. - nerrors++;
  104. if (options & F_QUIET)
  105. goto out;
  106. if (options & F_FLOOD) {
  107. - write_stdout("\bE", 2);
  108. + if (error_pkt)
  109. + write_stdout("\bE", 2);
  110. } else {
  111. print_timestamp();
  112. - printf("From %s icmp_seq=%u ", pr_addr(sin->sin_addr.s_addr), ntohs(icmph.un.echo.sequence));
  113. + printf("From %s: icmp_seq=%u ", pr_addr(sin->sin_addr.s_addr), ntohs(icmph.un.echo.sequence));
  114. pr_icmph(e->ee_type, e->ee_code, e->ee_info, NULL);
  115. fflush(stdout);
  116. }
  117. @@ -695,15 +737,41 @@ parse_reply(struct msghdr *msg, int cc,
  118. struct iphdr *ip;
  119. int hlen;
  120. int csfailed;
  121. + struct cmsghdr *cmsg;
  122. + int ttl;
  123. + __u8 *opts;
  124. + int optlen;
  125. /* Check the IP header */
  126. ip = (struct iphdr *)buf;
  127. - hlen = ip->ihl*4;
  128. - if (cc < hlen + 8 || ip->ihl < 5) {
  129. - if (options & F_VERBOSE)
  130. - fprintf(stderr, "ping: packet too short (%d bytes) from %s\n", cc,
  131. - pr_addr(from->sin_addr.s_addr));
  132. - return 1;
  133. + if (!using_ping_socket) {
  134. + hlen = ip->ihl*4;
  135. + if (cc < hlen + 8 || ip->ihl < 5) {
  136. + if (options & F_VERBOSE)
  137. + fprintf(stderr, "ping: packet too short (%d bytes) from %s\n", cc,
  138. + pr_addr(from->sin_addr.s_addr));
  139. + return 1;
  140. + }
  141. + ttl = ip->ttl;
  142. + opts = buf + sizeof(struct iphdr);
  143. + optlen = hlen - sizeof(struct iphdr);
  144. + } else {
  145. + hlen = 0;
  146. + ttl = 0;
  147. + opts = buf;
  148. + optlen = 0;
  149. + for (cmsg = CMSG_FIRSTHDR(msg); cmsg; cmsg = CMSG_NXTHDR(msg, cmsg)) {
  150. + if (cmsg->cmsg_level != SOL_IP)
  151. + continue;
  152. + if (cmsg->cmsg_type == IP_TTL) {
  153. + if (cmsg->cmsg_len < sizeof(int))
  154. + continue;
  155. + ttl = *(int *) CMSG_DATA(cmsg);
  156. + } else if (cmsg->cmsg_type == IP_RETOPTS) {
  157. + opts = (__u8 *) CMSG_DATA(cmsg);
  158. + optlen = cmsg->cmsg_len;
  159. + }
  160. + }
  161. }
  162. /* Now the ICMP part */
  163. @@ -716,7 +784,7 @@ parse_reply(struct msghdr *msg, int cc,
  164. return 1; /* 'Twas not our ECHO */
  165. if (gather_statistics((__u8*)icp, sizeof(*icp), cc,
  166. ntohs(icp->un.echo.sequence),
  167. - ip->ttl, 0, tv, pr_addr(from->sin_addr.s_addr),
  168. + ttl, 0, tv, pr_addr(from->sin_addr.s_addr),
  169. pr_echo_reply))
  170. return 0;
  171. } else {
  172. @@ -807,7 +875,7 @@ parse_reply(struct msghdr *msg, int cc,
  173. }
  174. if (!(options & F_FLOOD)) {
  175. - pr_options(buf + sizeof(struct iphdr), hlen);
  176. + pr_options(opts, optlen + sizeof(struct iphdr));
  177. if (options & F_AUDIBLE)
  178. putchar('\a');
  179. @@ -916,8 +984,7 @@ void pr_icmph(__u8 type, __u8 code, __u3
  180. printf("Redirect, Bad Code: %d", code);
  181. break;
  182. }
  183. - if (icp)
  184. - printf("(New nexthop: %s)\n", pr_addr(icp->un.gateway));
  185. + printf("(New nexthop: %s)\n", pr_addr(icp ? icp->un.gateway : info));
  186. if (icp && (options & F_VERBOSE))
  187. pr_iph((struct iphdr*)(icp + 1));
  188. break;
  189. @@ -1217,7 +1284,7 @@ void install_filter(void)
  190. insns
  191. };
  192. - if (once)
  193. + if (once || using_ping_socket)
  194. return;
  195. once = 1;
  196. --- iputils-s20101006/ping_common.c
  197. +++ iputils-s20101006/ping_common.c
  198. @@ -515,7 +515,8 @@ void setup(int icmp_sock)
  199. *p++ = i;
  200. }
  201. - ident = htons(getpid() & 0xFFFF);
  202. + if (!ident)
  203. + ident = htons(getpid() & 0xFFFF);
  204. set_signal(SIGINT, sigexit);
  205. set_signal(SIGALRM, sigexit);