123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225 |
- http://openwall.info/wiki/people/segoon/ping
- --- iputils-s20101006/ping.c
- +++ iputils-s20101006/ping.c
- @@ -88,6 +88,7 @@ struct sockaddr_in whereto; /* who to pi
- int optlen = 0;
- int settos = 0; /* Set TOS, Precendence or other QOS options */
- int icmp_sock; /* socket file descriptor */
- +int using_ping_socket = 0;
- u_char outpack[0x10000];
- int maxpacket = sizeof(outpack);
-
- @@ -123,7 +124,11 @@ main(int argc, char **argv)
- char *target, hnamebuf[MAX_HOSTNAMELEN];
- char rspace[3 + 4 * NROUTES + 1]; /* record route space */
-
- - icmp_sock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
- + icmp_sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_ICMP);
- + if (icmp_sock != -1)
- + using_ping_socket = 1;
- + else
- + icmp_sock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
- socket_errno = errno;
-
- uid = getuid();
- @@ -377,13 +382,35 @@ main(int argc, char **argv)
- }
- }
-
- - if ((options&F_STRICTSOURCE) &&
- - bind(icmp_sock, (struct sockaddr*)&source, sizeof(source)) == -1) {
- - perror("bind");
- - exit(2);
- + if (!using_ping_socket) {
- + if ((options&F_STRICTSOURCE) &&
- + bind(icmp_sock, (struct sockaddr*)&source, sizeof(source)) == -1) {
- + perror("bind");
- + exit(2);
- + }
- + } else {
- + struct sockaddr_in sa;
- + socklen_t sl;
- +
- + sa.sin_family = AF_INET;
- + sa.sin_port = 0;
- + sa.sin_addr.s_addr = (options&F_STRICTSOURCE) ?
- + source.sin_addr.s_addr : 0;
- + sl = sizeof(sa);
- +
- + if (bind(icmp_sock, (struct sockaddr *) &sa, sl) == -1) {
- + perror("bind");
- + exit(2);
- + }
- +
- + if (getsockname(icmp_sock, (struct sockaddr *) &sa, &sl) == -1) {
- + perror("getsockname");
- + exit(2);
- + }
- + ident = sa.sin_port;
- }
-
- - if (1) {
- + if (!using_ping_socket) {
- struct icmp_filter filt;
- filt.data = ~((1<<ICMP_SOURCE_QUENCH)|
- (1<<ICMP_DEST_UNREACH)|
- @@ -398,6 +425,12 @@ main(int argc, char **argv)
- hold = 1;
- if (setsockopt(icmp_sock, SOL_IP, IP_RECVERR, (char *)&hold, sizeof(hold)))
- fprintf(stderr, "WARNING: your kernel is veeery old. No problems.\n");
- + if (using_ping_socket) {
- + if (setsockopt(icmp_sock, SOL_IP, IP_RECVTTL, (char *)&hold, sizeof(hold)))
- + perror("WARNING: setsockopt(IP_RECVTTL)");
- + if (setsockopt(icmp_sock, SOL_IP, IP_RETOPTS, (char *)&hold, sizeof(hold)))
- + perror("WARNING: setsockopt(IP_RETOPTS)");
- + }
-
- /* record route option */
- if (options & F_RROUTE) {
- @@ -566,6 +599,7 @@ int receive_error_msg()
- nerrors++;
- } else if (e->ee_origin == SO_EE_ORIGIN_ICMP) {
- struct sockaddr_in *sin = (struct sockaddr_in*)(e+1);
- + int error_pkt;
-
- if (res < sizeof(icmph) ||
- target.sin_addr.s_addr != whereto.sin_addr.s_addr ||
- @@ -576,9 +610,18 @@ int receive_error_msg()
- goto out;
- }
-
- - acknowledge(ntohs(icmph.un.echo.sequence));
- + error_pkt = (e->ee_type != ICMP_REDIRECT &&
- + e->ee_type != ICMP_SOURCE_QUENCH);
- + if (error_pkt) {
- + acknowledge(ntohs(icmph.un.echo.sequence));
- + net_errors++;
- + nerrors++;
- + }
- + else {
- + saved_errno = 0;
- + }
-
- - if (!working_recverr) {
- + if (!using_ping_socket && !working_recverr) {
- struct icmp_filter filt;
- working_recverr = 1;
- /* OK, it works. Add stronger filter. */
- @@ -589,15 +632,14 @@ int receive_error_msg()
- perror("\rWARNING: setsockopt(ICMP_FILTER)");
- }
-
- - net_errors++;
- - nerrors++;
- if (options & F_QUIET)
- goto out;
- if (options & F_FLOOD) {
- - write_stdout("\bE", 2);
- + if (error_pkt)
- + write_stdout("\bE", 2);
- } else {
- print_timestamp();
- - printf("From %s icmp_seq=%u ", pr_addr(sin->sin_addr.s_addr), ntohs(icmph.un.echo.sequence));
- + printf("From %s: icmp_seq=%u ", pr_addr(sin->sin_addr.s_addr), ntohs(icmph.un.echo.sequence));
- pr_icmph(e->ee_type, e->ee_code, e->ee_info, NULL);
- fflush(stdout);
- }
- @@ -695,15 +737,41 @@ parse_reply(struct msghdr *msg, int cc,
- struct iphdr *ip;
- int hlen;
- int csfailed;
- + struct cmsghdr *cmsg;
- + int ttl;
- + __u8 *opts;
- + int optlen;
-
- /* Check the IP header */
- ip = (struct iphdr *)buf;
- - hlen = ip->ihl*4;
- - if (cc < hlen + 8 || ip->ihl < 5) {
- - if (options & F_VERBOSE)
- - fprintf(stderr, "ping: packet too short (%d bytes) from %s\n", cc,
- - pr_addr(from->sin_addr.s_addr));
- - return 1;
- + if (!using_ping_socket) {
- + hlen = ip->ihl*4;
- + if (cc < hlen + 8 || ip->ihl < 5) {
- + if (options & F_VERBOSE)
- + fprintf(stderr, "ping: packet too short (%d bytes) from %s\n", cc,
- + pr_addr(from->sin_addr.s_addr));
- + return 1;
- + }
- + ttl = ip->ttl;
- + opts = buf + sizeof(struct iphdr);
- + optlen = hlen - sizeof(struct iphdr);
- + } else {
- + hlen = 0;
- + ttl = 0;
- + opts = buf;
- + optlen = 0;
- + for (cmsg = CMSG_FIRSTHDR(msg); cmsg; cmsg = CMSG_NXTHDR(msg, cmsg)) {
- + if (cmsg->cmsg_level != SOL_IP)
- + continue;
- + if (cmsg->cmsg_type == IP_TTL) {
- + if (cmsg->cmsg_len < sizeof(int))
- + continue;
- + ttl = *(int *) CMSG_DATA(cmsg);
- + } else if (cmsg->cmsg_type == IP_RETOPTS) {
- + opts = (__u8 *) CMSG_DATA(cmsg);
- + optlen = cmsg->cmsg_len;
- + }
- + }
- }
-
- /* Now the ICMP part */
- @@ -716,7 +784,7 @@ parse_reply(struct msghdr *msg, int cc,
- return 1; /* 'Twas not our ECHO */
- if (gather_statistics((__u8*)icp, sizeof(*icp), cc,
- ntohs(icp->un.echo.sequence),
- - ip->ttl, 0, tv, pr_addr(from->sin_addr.s_addr),
- + ttl, 0, tv, pr_addr(from->sin_addr.s_addr),
- pr_echo_reply))
- return 0;
- } else {
- @@ -807,7 +875,7 @@ parse_reply(struct msghdr *msg, int cc,
- }
-
- if (!(options & F_FLOOD)) {
- - pr_options(buf + sizeof(struct iphdr), hlen);
- + pr_options(opts, optlen + sizeof(struct iphdr));
-
- if (options & F_AUDIBLE)
- putchar('\a');
- @@ -916,8 +984,7 @@ void pr_icmph(__u8 type, __u8 code, __u3
- printf("Redirect, Bad Code: %d", code);
- break;
- }
- - if (icp)
- - printf("(New nexthop: %s)\n", pr_addr(icp->un.gateway));
- + printf("(New nexthop: %s)\n", pr_addr(icp ? icp->un.gateway : info));
- if (icp && (options & F_VERBOSE))
- pr_iph((struct iphdr*)(icp + 1));
- break;
- @@ -1217,7 +1284,7 @@ void install_filter(void)
- insns
- };
-
- - if (once)
- + if (once || using_ping_socket)
- return;
- once = 1;
-
- --- iputils-s20101006/ping_common.c
- +++ iputils-s20101006/ping_common.c
- @@ -515,7 +515,8 @@ void setup(int icmp_sock)
- *p++ = i;
- }
-
- - ident = htons(getpid() & 0xFFFF);
- + if (!ident)
- + ident = htons(getpid() & 0xFFFF);
-
- set_signal(SIGINT, sigexit);
- set_signal(SIGALRM, sigexit);
|