You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
225 lines
6.2 KiB
225 lines
6.2 KiB
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);
|