Changeset View
Changeset View
Standalone View
Standalone View
sbin/ping/ping.c
Show First 20 Lines • Show All 1,138 Lines • ▼ Show 20 Lines | |||||
static void | static void | ||||
pr_pack(char *buf, ssize_t cc, struct sockaddr_in *from, struct timespec *tv) | pr_pack(char *buf, ssize_t cc, struct sockaddr_in *from, struct timespec *tv) | ||||
{ | { | ||||
struct in_addr ina; | struct in_addr ina; | ||||
u_char *cp, *dp, l; | u_char *cp, *dp, l; | ||||
struct icmp icp; | struct icmp icp; | ||||
struct ip ip; | struct ip ip; | ||||
const u_char *icmp_data_raw; | const u_char *icmp_data_raw; | ||||
ssize_t icmp_data_raw_len; | |||||
double triptime; | double triptime; | ||||
int dupflag, hlen, i, j, recv_len; | int dupflag, i, j, recv_len; | ||||
uint8_t hlen; | |||||
uint16_t seq; | uint16_t seq; | ||||
static int old_rrlen; | static int old_rrlen; | ||||
static char old_rr[MAX_IPOPTLEN]; | static char old_rr[MAX_IPOPTLEN]; | ||||
struct ip oip; | struct ip oip; | ||||
u_char oip_header_len; | u_char oip_header_len; | ||||
struct icmp oicmp; | struct icmp oicmp; | ||||
const u_char *oicmp_raw; | const u_char *oicmp_raw; | ||||
/* | /* | ||||
* Get size of IP header of the received packet. The | * Get size of IP header of the received packet. | ||||
* information is contained in the lower four bits of the | * The header length is contained in the lower four bits of the first | ||||
* first byte. | * byte and represents the number of 4 byte ocets the header takes up. | ||||
* | |||||
* The IHL minimum value is 5 (20 bytes) and its maximum value is 15 | |||||
* (60 bytes). | |||||
*/ | */ | ||||
memcpy(&l, buf, sizeof(l)); | memcpy(&l, buf, sizeof(l)); | ||||
hlen = (l & 0x0f) << 2; | hlen = (l & 0x0f) << 2; | ||||
memcpy(&ip, buf, hlen); | |||||
/* Check the IP header */ | /* Reject IP packets with a short header */ | ||||
if (hlen < sizeof(struct ip)) { | |||||
if (options & F_VERBOSE) | |||||
warn("IHL too short (%d bytes) from %s", hlen, | |||||
inet_ntoa(from->sin_addr)); | |||||
return; | |||||
} | |||||
memcpy(&ip, buf, sizeof(struct ip)); | |||||
/* Check packet has enough data to carry a valid ICMP header */ | |||||
recv_len = cc; | recv_len = cc; | ||||
if (cc < hlen + ICMP_MINLEN) { | if (cc < hlen + ICMP_MINLEN) { | ||||
if (options & F_VERBOSE) | if (options & F_VERBOSE) | ||||
warn("packet too short (%zd bytes) from %s", cc, | warn("packet too short (%zd bytes) from %s", cc, | ||||
inet_ntoa(from->sin_addr)); | inet_ntoa(from->sin_addr)); | ||||
return; | return; | ||||
} | } | ||||
#ifndef icmp_data | #ifndef icmp_data | ||||
icmp_data_raw = buf + hlen + offsetof(struct icmp, icmp_ip); | icmp_data_raw = buf + hlen + offsetof(struct icmp, icmp_ip); | ||||
#else | #else | ||||
icmp_data_raw_len = cc - (hlen + offsetof(struct icmp, icmp_ip)); | |||||
icmp_data_raw = buf + hlen + offsetof(struct icmp, icmp_data); | icmp_data_raw = buf + hlen + offsetof(struct icmp, icmp_data); | ||||
#endif | #endif | ||||
/* Now the ICMP part */ | /* Now the ICMP part */ | ||||
cc -= hlen; | cc -= hlen; | ||||
memcpy(&icp, buf + hlen, MIN((ssize_t)sizeof(icp), cc)); | memcpy(&icp, buf + hlen, MIN((ssize_t)sizeof(icp), cc)); | ||||
if (icp.icmp_type == icmp_type_rsp) { | if (icp.icmp_type == icmp_type_rsp) { | ||||
if (icp.icmp_id != ident) | if (icp.icmp_id != ident) | ||||
▲ Show 20 Lines • Show All 115 Lines • ▼ Show 20 Lines | (void)printf("\nwrong data byte #%d should be 0x%x but was 0x%x", | ||||
* and ICMP type and ID. | * and ICMP type and ID. | ||||
* | * | ||||
* Only print all the error messages if we are running | * Only print all the error messages if we are running | ||||
* as root to avoid leaking information not normally | * as root to avoid leaking information not normally | ||||
* available to those not running as root. | * available to those not running as root. | ||||
*/ | */ | ||||
memcpy(&oip_header_len, icmp_data_raw, sizeof(oip_header_len)); | memcpy(&oip_header_len, icmp_data_raw, sizeof(oip_header_len)); | ||||
oip_header_len = (oip_header_len & 0x0f) << 2; | oip_header_len = (oip_header_len & 0x0f) << 2; | ||||
memcpy(&oip, icmp_data_raw, oip_header_len); | |||||
/* Reject IP packets with a short header */ | |||||
if (oip_header_len < sizeof(struct ip)) { | |||||
if (options & F_VERBOSE) | |||||
warn("inner IHL too short (%d bytes) from %s", | |||||
oip_header_len, inet_ntoa(from->sin_addr)); | |||||
return; | |||||
} | |||||
if (icmp_data_raw_len < | |||||
(ssize_t)(oip_header_len + sizeof(struct icmp))) { | |||||
if (options & F_VERBOSE) | |||||
warn("inner packet too short (%zd bytes) from %s", | |||||
icmp_data_raw_len, inet_ntoa(from->sin_addr)); | |||||
return; | |||||
} | |||||
memcpy(&oip, icmp_data_raw, sizeof(struct ip)); | |||||
oicmp_raw = icmp_data_raw + oip_header_len; | oicmp_raw = icmp_data_raw + oip_header_len; | ||||
memcpy(&oicmp, oicmp_raw, offsetof(struct icmp, icmp_id) + | memcpy(&oicmp, oicmp_raw, sizeof(struct icmp)); | ||||
sizeof(oicmp.icmp_id)); | |||||
if (((options & F_VERBOSE) && uid == 0) || | if (((options & F_VERBOSE) && uid == 0) || | ||||
(!(options & F_QUIET2) && | (!(options & F_QUIET2) && | ||||
(oip.ip_dst.s_addr == whereto.sin_addr.s_addr) && | (oip.ip_dst.s_addr == whereto.sin_addr.s_addr) && | ||||
(oip.ip_p == IPPROTO_ICMP) && | (oip.ip_p == IPPROTO_ICMP) && | ||||
(oicmp.icmp_type == ICMP_ECHO) && | (oicmp.icmp_type == ICMP_ECHO) && | ||||
(oicmp.icmp_id == ident))) { | (oicmp.icmp_id == ident))) { | ||||
(void)printf("%zd bytes from %s: ", cc, | (void)printf("%zd bytes from %s: ", cc, | ||||
▲ Show 20 Lines • Show All 458 Lines • Show Last 20 Lines |