Changeset View
Standalone View
sbin/ping/ping.c
Show First 20 Lines • Show All 85 Lines • ▼ Show 20 Lines | |||||
#endif /*IPSEC*/ | #endif /*IPSEC*/ | ||||
#include <capsicum_helpers.h> | #include <capsicum_helpers.h> | ||||
#include <ctype.h> | #include <ctype.h> | ||||
#include <err.h> | #include <err.h> | ||||
#include <errno.h> | #include <errno.h> | ||||
#include <math.h> | #include <math.h> | ||||
#include <netdb.h> | #include <netdb.h> | ||||
#include <stddef.h> | |||||
#include <signal.h> | #include <signal.h> | ||||
#include <stdio.h> | #include <stdio.h> | ||||
#include <stdlib.h> | #include <stdlib.h> | ||||
#include <string.h> | #include <string.h> | ||||
#include <sysexits.h> | #include <sysexits.h> | ||||
#include <time.h> | #include <time.h> | ||||
#include <unistd.h> | #include <unistd.h> | ||||
▲ Show 20 Lines • Show All 110 Lines • ▼ Show 20 Lines | |||||
static void fill(char *, char *); | static void fill(char *, char *); | ||||
static cap_channel_t *capdns_setup(void); | static cap_channel_t *capdns_setup(void); | ||||
static void check_status(void); | static void check_status(void); | ||||
static void finish(void) __dead2; | static void finish(void) __dead2; | ||||
static void pinger(void); | static void pinger(void); | ||||
static char *pr_addr(struct in_addr); | static char *pr_addr(struct in_addr); | ||||
static char *pr_ntime(n_time); | static char *pr_ntime(n_time); | ||||
static void pr_icmph(struct icmp *); | static void pr_icmph(struct icmp *, struct ip *, const u_char *const); | ||||
static void pr_iph(struct ip *); | static void pr_iph(struct ip *); | ||||
static void pr_pack(char *, int, struct sockaddr_in *, struct timespec *); | static void pr_pack(char *, ssize_t, struct sockaddr_in *, struct timespec *); | ||||
static void pr_retip(struct ip *); | static void pr_retip(struct ip *, const u_char *); | ||||
static void status(int); | static void status(int); | ||||
static void stopit(int); | static void stopit(int); | ||||
static void usage(void) __dead2; | static void usage(void) __dead2; | ||||
int | int | ||||
main(int argc, char *const *argv) | main(int argc, char *const *argv) | ||||
{ | { | ||||
struct sockaddr_in from, sock_in; | struct sockaddr_in from, sock_in; | ||||
struct in_addr ifaddr; | struct in_addr ifaddr; | ||||
struct timespec last, intvl; | struct timespec last, intvl; | ||||
struct iovec iov; | struct iovec iov; | ||||
struct ip *ip; | |||||
struct msghdr msg; | struct msghdr msg; | ||||
struct sigaction si_sa; | struct sigaction si_sa; | ||||
size_t sz; | size_t sz; | ||||
u_char *datap, packet[IP_MAXPACKET] __aligned(4); | u_char *datap, packet[IP_MAXPACKET] __aligned(4); | ||||
char *ep, *source, *target, *payload; | char *ep, *source, *target, *payload; | ||||
struct hostent *hp; | struct hostent *hp; | ||||
#ifdef IPSEC_POLICY_IPSEC | #ifdef IPSEC_POLICY_IPSEC | ||||
char *policy_in, *policy_out; | char *policy_in, *policy_out; | ||||
▲ Show 20 Lines • Show All 432 Lines • ▼ Show 20 Lines | if (policy_out != NULL) { | ||||
"ipsec policy cannot be configured"); | "ipsec policy cannot be configured"); | ||||
free(buf); | free(buf); | ||||
} | } | ||||
} | } | ||||
#endif /*IPSEC_POLICY_IPSEC*/ | #endif /*IPSEC_POLICY_IPSEC*/ | ||||
#endif /*IPSEC*/ | #endif /*IPSEC*/ | ||||
if (options & F_HDRINCL) { | if (options & F_HDRINCL) { | ||||
ip = (struct ip*)outpackhdr; | struct ip ip; | ||||
memcpy(&ip, outpackhdr, sizeof(ip)); | |||||
if (!(options & (F_TTL | F_MTTL))) { | if (!(options & (F_TTL | F_MTTL))) { | ||||
mib[0] = CTL_NET; | mib[0] = CTL_NET; | ||||
mib[1] = PF_INET; | mib[1] = PF_INET; | ||||
mib[2] = IPPROTO_IP; | mib[2] = IPPROTO_IP; | ||||
mib[3] = IPCTL_DEFTTL; | mib[3] = IPCTL_DEFTTL; | ||||
sz = sizeof(ttl); | sz = sizeof(ttl); | ||||
if (sysctl(mib, 4, &ttl, &sz, NULL, 0) == -1) | if (sysctl(mib, 4, &ttl, &sz, NULL, 0) == -1) | ||||
err(1, "sysctl(net.inet.ip.ttl)"); | err(1, "sysctl(net.inet.ip.ttl)"); | ||||
} | } | ||||
setsockopt(ssend, IPPROTO_IP, IP_HDRINCL, &hold, sizeof(hold)); | setsockopt(ssend, IPPROTO_IP, IP_HDRINCL, &hold, sizeof(hold)); | ||||
ip->ip_v = IPVERSION; | ip.ip_v = IPVERSION; | ||||
ip->ip_hl = sizeof(struct ip) >> 2; | ip.ip_hl = sizeof(struct ip) >> 2; | ||||
ip->ip_tos = tos; | ip.ip_tos = tos; | ||||
ip->ip_id = 0; | ip.ip_id = 0; | ||||
ip->ip_off = htons(df ? IP_DF : 0); | ip.ip_off = htons(df ? IP_DF : 0); | ||||
ip->ip_ttl = ttl; | ip.ip_ttl = ttl; | ||||
ip->ip_p = IPPROTO_ICMP; | ip.ip_p = IPPROTO_ICMP; | ||||
ip->ip_src.s_addr = source ? sock_in.sin_addr.s_addr : INADDR_ANY; | ip.ip_src.s_addr = source ? sock_in.sin_addr.s_addr : INADDR_ANY; | ||||
ip->ip_dst = to->sin_addr; | ip.ip_dst = to->sin_addr; | ||||
memcpy(outpackhdr, &ip, sizeof(ip)); | |||||
} | } | ||||
/* | /* | ||||
* Here we enter capability mode. Further down access to global | * Here we enter capability mode. Further down access to global | ||||
* namespaces (e.g filesystem) is restricted (see capsicum(4)). | * namespaces (e.g filesystem) is restricted (see capsicum(4)). | ||||
* We must connect(2) our socket before this point. | * We must connect(2) our socket before this point. | ||||
*/ | */ | ||||
caph_cache_catpages(); | caph_cache_catpages(); | ||||
▲ Show 20 Lines • Show All 175 Lines • ▼ Show 20 Lines | if (options & F_FLOOD) { | ||||
intvl.tv_sec = interval / 1000; | intvl.tv_sec = interval / 1000; | ||||
intvl.tv_nsec = interval % 1000 * 1000000; | intvl.tv_nsec = interval % 1000 * 1000000; | ||||
} | } | ||||
almost_done = 0; | almost_done = 0; | ||||
while (!finish_up) { | while (!finish_up) { | ||||
struct timespec now, timeout; | struct timespec now, timeout; | ||||
fd_set rfds; | fd_set rfds; | ||||
int cc, n; | int n; | ||||
ssize_t cc; | |||||
asomers: I don't think there's any reason to change the type of `n`, too. | |||||
Done Inline ActionsFixed. jansucan: Fixed. | |||||
check_status(); | check_status(); | ||||
if ((unsigned)srecv >= FD_SETSIZE) | if ((unsigned)srecv >= FD_SETSIZE) | ||||
errx(EX_OSERR, "descriptor too large"); | errx(EX_OSERR, "descriptor too large"); | ||||
FD_ZERO(&rfds); | FD_ZERO(&rfds); | ||||
FD_SET(srecv, &rfds); | FD_SET(srecv, &rfds); | ||||
(void)clock_gettime(CLOCK_MONOTONIC, &now); | (void)clock_gettime(CLOCK_MONOTONIC, &now); | ||||
timespecadd(&last, &intvl, &timeout); | timespecadd(&last, &intvl, &timeout); | ||||
▲ Show 20 Lines • Show All 101 Lines • ▼ Show 20 Lines | |||||
* bytes of the data portion are used to hold a UNIX "timespec" struct in | * bytes of the data portion are used to hold a UNIX "timespec" struct in | ||||
* host byte-order, to compute the round-trip time. | * host byte-order, to compute the round-trip time. | ||||
*/ | */ | ||||
static void | static void | ||||
pinger(void) | pinger(void) | ||||
{ | { | ||||
struct timespec now; | struct timespec now; | ||||
struct tv32 tv32; | struct tv32 tv32; | ||||
struct ip *ip; | struct icmp icp; | ||||
struct icmp *icp; | |||||
int cc, i; | int cc, i; | ||||
u_char *packet; | u_char *packet; | ||||
packet = outpack; | packet = outpack; | ||||
icp = (struct icmp *)outpack; | memcpy(&icp, outpack, ICMP_MINLEN + phdr_len); | ||||
icp->icmp_type = icmp_type; | icp.icmp_type = icmp_type; | ||||
icp->icmp_code = 0; | icp.icmp_code = 0; | ||||
icp->icmp_cksum = 0; | icp.icmp_cksum = 0; | ||||
icp->icmp_seq = htons(ntransmitted); | icp.icmp_seq = htons(ntransmitted); | ||||
icp->icmp_id = ident; /* ID */ | icp.icmp_id = ident; /* ID */ | ||||
CLR(ntransmitted % mx_dup_ck); | CLR(ntransmitted % mx_dup_ck); | ||||
if ((options & F_TIME) || timing) { | if ((options & F_TIME) || timing) { | ||||
(void)clock_gettime(CLOCK_MONOTONIC, &now); | (void)clock_gettime(CLOCK_MONOTONIC, &now); | ||||
/* | /* | ||||
* Truncate seconds down to 32 bits in order | * Truncate seconds down to 32 bits in order | ||||
* to fit the timestamp within 8 bytes of the | * to fit the timestamp within 8 bytes of the | ||||
* packet. We're only concerned with | * packet. We're only concerned with | ||||
* durations, not absolute times. | * durations, not absolute times. | ||||
*/ | */ | ||||
tv32.tv32_sec = (uint32_t)htonl(now.tv_sec); | tv32.tv32_sec = (uint32_t)htonl(now.tv_sec); | ||||
tv32.tv32_nsec = (uint32_t)htonl(now.tv_nsec); | tv32.tv32_nsec = (uint32_t)htonl(now.tv_nsec); | ||||
if (options & F_TIME) | if (options & F_TIME) | ||||
icp->icmp_otime = htonl((now.tv_sec % (24*60*60)) | icp.icmp_otime = htonl((now.tv_sec % (24*60*60)) | ||||
* 1000 + now.tv_nsec / 1000000); | * 1000 + now.tv_nsec / 1000000); | ||||
if (timing) | if (timing) | ||||
bcopy((void *)&tv32, | bcopy((void *)&tv32, | ||||
(void *)&outpack[ICMP_MINLEN + phdr_len], | (void *)&outpack[ICMP_MINLEN + phdr_len], | ||||
sizeof(tv32)); | sizeof(tv32)); | ||||
} | } | ||||
memcpy(outpack, &icp, ICMP_MINLEN + phdr_len); | |||||
cc = ICMP_MINLEN + phdr_len + datalen; | cc = ICMP_MINLEN + phdr_len + datalen; | ||||
/* compute ICMP checksum here */ | /* compute ICMP checksum here */ | ||||
icp->icmp_cksum = in_cksum((u_char *)icp, cc); | icp.icmp_cksum = in_cksum(outpack, cc); | ||||
/* Update icmp_cksum in the raw packet data buffer. */ | |||||
memcpy(outpack + offsetof(struct icmp, icmp_cksum), &icp.icmp_cksum, | |||||
sizeof(icp.icmp_cksum)); | |||||
if (options & F_HDRINCL) { | if (options & F_HDRINCL) { | ||||
struct ip ip; | |||||
cc += sizeof(struct ip); | cc += sizeof(struct ip); | ||||
ip = (struct ip *)outpackhdr; | ip.ip_len = htons(cc); | ||||
ip->ip_len = htons(cc); | /* Update ip_len in the raw packet data buffer. */ | ||||
ip->ip_sum = in_cksum(outpackhdr, cc); | memcpy(outpackhdr + offsetof(struct ip, ip_len), &ip.ip_len, | ||||
sizeof(ip.ip_len)); | |||||
ip.ip_sum = in_cksum(outpackhdr, cc); | |||||
/* Update ip_sum in the raw packet data buffer. */ | |||||
memcpy(outpackhdr + offsetof(struct ip, ip_sum), &ip.ip_sum, | |||||
sizeof(ip.ip_sum)); | |||||
packet = outpackhdr; | packet = outpackhdr; | ||||
} | } | ||||
i = send(ssend, (char *)packet, cc, 0); | i = send(ssend, (char *)packet, cc, 0); | ||||
if (i < 0 || i != cc) { | if (i < 0 || i != cc) { | ||||
if (i < 0) { | if (i < 0) { | ||||
if (options & F_FLOOD && errno == ENOBUFS) { | if (options & F_FLOOD && errno == ENOBUFS) { | ||||
usleep(FLOOD_BACKOFF); | usleep(FLOOD_BACKOFF); | ||||
return; | return; | ||||
Show All 13 Lines | |||||
/* | /* | ||||
* pr_pack -- | * pr_pack -- | ||||
* Print out the packet, if it came from us. This logic is necessary | * Print out the packet, if it came from us. This logic is necessary | ||||
* because ALL readers of the ICMP socket get a copy of ALL ICMP packets | * because ALL readers of the ICMP socket get a copy of ALL ICMP packets | ||||
* which arrive ('tis only fair). This permits multiple copies of this | * which arrive ('tis only fair). This permits multiple copies of this | ||||
* program to be run without having intermingled output (or statistics!). | * program to be run without having intermingled output (or statistics!). | ||||
*/ | */ | ||||
static void | static void | ||||
pr_pack(char *buf, int 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; | u_char *cp, *dp, l; | ||||
struct icmp *icp; | struct icmp icp; | ||||
struct ip *ip; | struct ip ip; | ||||
const void *tp; | const u_char *icmp_data_raw; | ||||
double triptime; | double triptime; | ||||
int dupflag, hlen, i, j, recv_len; | int dupflag, hlen, i, j, recv_len; | ||||
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; | |||||
u_char oip_header_len; | |||||
struct icmp oicmp; | |||||
const u_char *oicmp_raw; | |||||
/* | |||||
* Get size of IP header of the received packet. The | |||||
* information is contained in the lower four bits of the | |||||
* first byte. | |||||
*/ | |||||
memcpy(&l, buf, sizeof(l)); | |||||
hlen = (l & 0x0f) << 2; | |||||
memcpy(&ip, buf, hlen); | |||||
/* Check the IP header */ | /* Check the IP header */ | ||||
ip = (struct ip *)buf; | |||||
hlen = ip->ip_hl << 2; | |||||
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 (%d 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 | |||||
icmp_data_raw = buf + hlen + offsetof(struct icmp, icmp_ip); | |||||
#else | |||||
icmp_data_raw = buf + hlen + offsetof(struct icmp, icmp_data); | |||||
#endif | |||||
/* Now the ICMP part */ | /* Now the ICMP part */ | ||||
cc -= hlen; | cc -= hlen; | ||||
icp = (struct icmp *)(buf + hlen); | memcpy(&icp, buf + hlen, MIN((ssize_t)sizeof(icp), cc)); | ||||
if (icp->icmp_type == icmp_type_rsp) { | if (icp.icmp_type == icmp_type_rsp) { | ||||
Not Done Inline ActionsWould this be more clearly written MIN((int)sizeof(icp), cc)? asomers: Would this be more clearly written `MIN((int)sizeof(icp), cc)`?
And since `cc` is initialized… | |||||
Done Inline Actions
That's true. Current use of data types in the code is less appropriate than it should be. I will try to fix this in another diff. jansucan: > And since cc is initialized from the output of recvmsg, shouldn't it be of type ssize_t? | |||||
Done Inline ActionsAfter doing some experiments it seems that the least error prone way would be to type keep the type casting in (int)sizeof(icp). Changing data type of the variable for recvmsg's return value is OK. The problem is with cc argument to pr_pack. Changing it from int to ssize_t doesn't solve warning about comparing integers with different signs. Changing it from int to size_t (it's a size of a data buffer) starts avalanche of warnings about different signs. If one is corrected, another two appear. Better time for fixing this would be when the code is much more structured so it's much easier to see whether a variable really needs to hold negative values or not. jansucan: After doing some experiments it seems that the least error prone way would be to type keep the… | |||||
Not Done Inline ActionsTrue, a size cast would be needed if cc were ssize_t. But that's still better than the current situation which involves both a sign cast and a size cast (implicitly, when assigning from recvmsg). asomers: True, a size cast would be needed if `cc` were `ssize_t`. But that's still better than the… | |||||
Done Inline ActionsCan I change the data type in this diff, or should I create a separate one? jansucan: Can I change the data type in this diff, or should I create a separate one? | |||||
Not Done Inline ActionsIt should go into this diff. I don't see any reason to postpone. asomers: It should go into this diff. I don't see any reason to postpone. | |||||
if (icp->icmp_id != ident) | if (icp.icmp_id != ident) | ||||
return; /* 'Twas not our ECHO */ | return; /* 'Twas not our ECHO */ | ||||
++nreceived; | ++nreceived; | ||||
triptime = 0.0; | triptime = 0.0; | ||||
if (timing) { | if (timing) { | ||||
struct timespec tv1; | struct timespec tv1; | ||||
struct tv32 tv32; | struct tv32 tv32; | ||||
#ifndef icmp_data | const u_char *tp; | ||||
tp = &icp->icmp_ip; | |||||
#else | |||||
tp = icp->icmp_data; | |||||
#endif | |||||
tp = (const char *)tp + phdr_len; | |||||
tp = icmp_data_raw + phdr_len; | |||||
if ((size_t)(cc - ICMP_MINLEN - phdr_len) >= | if ((size_t)(cc - ICMP_MINLEN - phdr_len) >= | ||||
sizeof(tv1)) { | sizeof(tv1)) { | ||||
/* Copy to avoid alignment problems: */ | /* Copy to avoid alignment problems: */ | ||||
memcpy(&tv32, tp, sizeof(tv32)); | memcpy(&tv32, tp, sizeof(tv32)); | ||||
tv1.tv_sec = ntohl(tv32.tv32_sec); | tv1.tv_sec = ntohl(tv32.tv32_sec); | ||||
tv1.tv_nsec = ntohl(tv32.tv32_nsec); | tv1.tv_nsec = ntohl(tv32.tv32_nsec); | ||||
timespecsub(tv, &tv1, tv); | timespecsub(tv, &tv1, tv); | ||||
triptime = ((double)tv->tv_sec) * 1000.0 + | triptime = ((double)tv->tv_sec) * 1000.0 + | ||||
((double)tv->tv_nsec) / 1000000.0; | ((double)tv->tv_nsec) / 1000000.0; | ||||
tsum += triptime; | tsum += triptime; | ||||
tsumsq += triptime * triptime; | tsumsq += triptime * triptime; | ||||
if (triptime < tmin) | if (triptime < tmin) | ||||
tmin = triptime; | tmin = triptime; | ||||
if (triptime > tmax) | if (triptime > tmax) | ||||
tmax = triptime; | tmax = triptime; | ||||
} else | } else | ||||
timing = 0; | timing = 0; | ||||
} | } | ||||
seq = ntohs(icp->icmp_seq); | seq = ntohs(icp.icmp_seq); | ||||
if (TST(seq % mx_dup_ck)) { | if (TST(seq % mx_dup_ck)) { | ||||
++nrepeats; | ++nrepeats; | ||||
--nreceived; | --nreceived; | ||||
dupflag = 1; | dupflag = 1; | ||||
} else { | } else { | ||||
SET(seq % mx_dup_ck); | SET(seq % mx_dup_ck); | ||||
dupflag = 0; | dupflag = 0; | ||||
} | } | ||||
if (options & F_QUIET) | if (options & F_QUIET) | ||||
return; | return; | ||||
if (options & F_WAITTIME && triptime > waittime) { | if (options & F_WAITTIME && triptime > waittime) { | ||||
++nrcvtimeout; | ++nrcvtimeout; | ||||
return; | return; | ||||
} | } | ||||
if (options & F_FLOOD) | if (options & F_FLOOD) | ||||
(void)write(STDOUT_FILENO, &BSPACE, 1); | (void)write(STDOUT_FILENO, &BSPACE, 1); | ||||
else { | else { | ||||
(void)printf("%d bytes from %s: icmp_seq=%u", cc, | (void)printf("%zd bytes from %s: icmp_seq=%u", cc, | ||||
inet_ntoa(*(struct in_addr *)&from->sin_addr.s_addr), | inet_ntoa(*(struct in_addr *)&from->sin_addr.s_addr), | ||||
seq); | seq); | ||||
(void)printf(" ttl=%d", ip->ip_ttl); | (void)printf(" ttl=%d", ip.ip_ttl); | ||||
if (timing) | if (timing) | ||||
(void)printf(" time=%.3f ms", triptime); | (void)printf(" time=%.3f ms", triptime); | ||||
if (dupflag) | if (dupflag) | ||||
(void)printf(" (DUP!)"); | (void)printf(" (DUP!)"); | ||||
if (options & F_AUDIBLE) | if (options & F_AUDIBLE) | ||||
(void)write(STDOUT_FILENO, &BBELL, 1); | (void)write(STDOUT_FILENO, &BBELL, 1); | ||||
if (options & F_MASK) { | if (options & F_MASK) { | ||||
/* Just prentend this cast isn't ugly */ | /* Just prentend this cast isn't ugly */ | ||||
(void)printf(" mask=%s", | (void)printf(" mask=%s", | ||||
inet_ntoa(*(struct in_addr *)&(icp->icmp_mask))); | inet_ntoa(*(struct in_addr *)&(icp.icmp_mask))); | ||||
} | } | ||||
if (options & F_TIME) { | if (options & F_TIME) { | ||||
(void)printf(" tso=%s", pr_ntime(icp->icmp_otime)); | (void)printf(" tso=%s", pr_ntime(icp.icmp_otime)); | ||||
(void)printf(" tsr=%s", pr_ntime(icp->icmp_rtime)); | (void)printf(" tsr=%s", pr_ntime(icp.icmp_rtime)); | ||||
(void)printf(" tst=%s", pr_ntime(icp->icmp_ttime)); | (void)printf(" tst=%s", pr_ntime(icp.icmp_ttime)); | ||||
} | } | ||||
if (recv_len != send_len) { | if (recv_len != send_len) { | ||||
(void)printf( | (void)printf( | ||||
"\nwrong total length %d instead of %d", | "\nwrong total length %d instead of %d", | ||||
recv_len, send_len); | recv_len, send_len); | ||||
} | } | ||||
/* check the data */ | /* check the data */ | ||||
cp = (u_char*)&icp->icmp_data[phdr_len]; | cp = (u_char*)(buf + hlen + offsetof(struct icmp, | ||||
icmp_data) + phdr_len); | |||||
dp = &outpack[ICMP_MINLEN + phdr_len]; | dp = &outpack[ICMP_MINLEN + phdr_len]; | ||||
cc -= ICMP_MINLEN + phdr_len; | cc -= ICMP_MINLEN + phdr_len; | ||||
i = 0; | i = 0; | ||||
if (timing) { /* don't check variable timestamp */ | if (timing) { /* don't check variable timestamp */ | ||||
cp += TIMEVAL_LEN; | cp += TIMEVAL_LEN; | ||||
dp += TIMEVAL_LEN; | dp += TIMEVAL_LEN; | ||||
cc -= TIMEVAL_LEN; | cc -= TIMEVAL_LEN; | ||||
i += TIMEVAL_LEN; | i += TIMEVAL_LEN; | ||||
} | } | ||||
for (; i < datalen && cc > 0; ++i, ++cp, ++dp, --cc) { | for (; i < datalen && cc > 0; ++i, ++cp, ++dp, --cc) { | ||||
if (*cp != *dp) { | if (*cp != *dp) { | ||||
(void)printf("\nwrong data byte #%d should be 0x%x but was 0x%x", | (void)printf("\nwrong data byte #%d should be 0x%x but was 0x%x", | ||||
i, *dp, *cp); | i, *dp, *cp); | ||||
(void)printf("\ncp:"); | (void)printf("\ncp:"); | ||||
cp = (u_char*)&icp->icmp_data[0]; | cp = (u_char*)(buf + hlen + | ||||
offsetof(struct icmp, icmp_data)); | |||||
for (i = 0; i < datalen; ++i, ++cp) { | for (i = 0; i < datalen; ++i, ++cp) { | ||||
if ((i % 16) == 8) | if ((i % 16) == 8) | ||||
(void)printf("\n\t"); | (void)printf("\n\t"); | ||||
(void)printf("%2x ", *cp); | (void)printf("%2x ", *cp); | ||||
} | } | ||||
(void)printf("\ndp:"); | (void)printf("\ndp:"); | ||||
cp = &outpack[ICMP_MINLEN]; | cp = &outpack[ICMP_MINLEN]; | ||||
for (i = 0; i < datalen; ++i, ++cp) { | for (i = 0; i < datalen; ++i, ++cp) { | ||||
Show All 11 Lines | (void)printf("\nwrong data byte #%d should be 0x%x but was 0x%x", | ||||
* See if it's a reply to something that we sent. | * See if it's a reply to something that we sent. | ||||
* We can compare IP destination, protocol, | * We can compare IP destination, protocol, | ||||
* 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. | ||||
*/ | */ | ||||
#ifndef icmp_data | memcpy(&oip_header_len, icmp_data_raw, sizeof(oip_header_len)); | ||||
struct ip *oip = &icp->icmp_ip; | oip_header_len = (oip_header_len & 0x0f) << 2; | ||||
#else | memcpy(&oip, icmp_data_raw, oip_header_len); | ||||
struct ip *oip = (struct ip *)icp->icmp_data; | oicmp_raw = icmp_data_raw + oip_header_len; | ||||
#endif | memcpy(&oicmp, oicmp_raw, offsetof(struct icmp, icmp_id) + | ||||
struct icmp *oicmp = (struct icmp *)(oip + 1); | 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("%d bytes from %s: ", cc, | (void)printf("%zd bytes from %s: ", cc, | ||||
pr_addr(from->sin_addr)); | pr_addr(from->sin_addr)); | ||||
pr_icmph(icp); | pr_icmph(&icp, &oip, oicmp_raw); | ||||
} else | } else | ||||
return; | return; | ||||
} | } | ||||
/* Display any IP options */ | /* Display any IP options */ | ||||
cp = (u_char *)buf + sizeof(struct ip); | cp = (u_char *)buf + sizeof(struct ip); | ||||
for (; hlen > (int)sizeof(struct ip); --hlen, ++cp) | for (; hlen > (int)sizeof(struct ip); --hlen, ++cp) | ||||
▲ Show 20 Lines • Show All 169 Lines • ▼ Show 20 Lines | |||||
}; | }; | ||||
#endif | #endif | ||||
/* | /* | ||||
* pr_icmph -- | * pr_icmph -- | ||||
* Print a descriptive string about an ICMP header. | * Print a descriptive string about an ICMP header. | ||||
*/ | */ | ||||
static void | static void | ||||
pr_icmph(struct icmp *icp) | pr_icmph(struct icmp *icp, struct ip *oip, const u_char *const oicmp_raw) | ||||
{ | { | ||||
switch(icp->icmp_type) { | switch(icp->icmp_type) { | ||||
case ICMP_ECHOREPLY: | case ICMP_ECHOREPLY: | ||||
(void)printf("Echo Reply\n"); | (void)printf("Echo Reply\n"); | ||||
/* XXX ID + Seq + Data */ | /* XXX ID + Seq + Data */ | ||||
break; | break; | ||||
case ICMP_UNREACH: | case ICMP_UNREACH: | ||||
Show All 21 Lines | case ICMP_UNREACH_FILTER_PROHIB: | ||||
(void)printf("Communication prohibited by filter\n"); | (void)printf("Communication prohibited by filter\n"); | ||||
break; | break; | ||||
default: | default: | ||||
(void)printf("Dest Unreachable, Bad Code: %d\n", | (void)printf("Dest Unreachable, Bad Code: %d\n", | ||||
icp->icmp_code); | icp->icmp_code); | ||||
break; | break; | ||||
} | } | ||||
/* Print returned IP header information */ | /* Print returned IP header information */ | ||||
#ifndef icmp_data | pr_retip(oip, oicmp_raw); | ||||
pr_retip(&icp->icmp_ip); | |||||
#else | |||||
pr_retip((struct ip *)icp->icmp_data); | |||||
#endif | |||||
break; | break; | ||||
case ICMP_SOURCEQUENCH: | case ICMP_SOURCEQUENCH: | ||||
(void)printf("Source Quench\n"); | (void)printf("Source Quench\n"); | ||||
#ifndef icmp_data | pr_retip(oip, oicmp_raw); | ||||
pr_retip(&icp->icmp_ip); | |||||
#else | |||||
pr_retip((struct ip *)icp->icmp_data); | |||||
#endif | |||||
break; | break; | ||||
case ICMP_REDIRECT: | case ICMP_REDIRECT: | ||||
switch(icp->icmp_code) { | switch(icp->icmp_code) { | ||||
case ICMP_REDIRECT_NET: | case ICMP_REDIRECT_NET: | ||||
(void)printf("Redirect Network"); | (void)printf("Redirect Network"); | ||||
break; | break; | ||||
case ICMP_REDIRECT_HOST: | case ICMP_REDIRECT_HOST: | ||||
(void)printf("Redirect Host"); | (void)printf("Redirect Host"); | ||||
break; | break; | ||||
case ICMP_REDIRECT_TOSNET: | case ICMP_REDIRECT_TOSNET: | ||||
(void)printf("Redirect Type of Service and Network"); | (void)printf("Redirect Type of Service and Network"); | ||||
break; | break; | ||||
case ICMP_REDIRECT_TOSHOST: | case ICMP_REDIRECT_TOSHOST: | ||||
(void)printf("Redirect Type of Service and Host"); | (void)printf("Redirect Type of Service and Host"); | ||||
break; | break; | ||||
default: | default: | ||||
(void)printf("Redirect, Bad Code: %d", icp->icmp_code); | (void)printf("Redirect, Bad Code: %d", icp->icmp_code); | ||||
break; | break; | ||||
} | } | ||||
(void)printf("(New addr: %s)\n", inet_ntoa(icp->icmp_gwaddr)); | (void)printf("(New addr: %s)\n", inet_ntoa(icp->icmp_gwaddr)); | ||||
#ifndef icmp_data | pr_retip(oip, oicmp_raw); | ||||
pr_retip(&icp->icmp_ip); | |||||
#else | |||||
pr_retip((struct ip *)icp->icmp_data); | |||||
#endif | |||||
break; | break; | ||||
case ICMP_ECHO: | case ICMP_ECHO: | ||||
(void)printf("Echo Request\n"); | (void)printf("Echo Request\n"); | ||||
/* XXX ID + Seq + Data */ | /* XXX ID + Seq + Data */ | ||||
break; | break; | ||||
case ICMP_TIMXCEED: | case ICMP_TIMXCEED: | ||||
switch(icp->icmp_code) { | switch(icp->icmp_code) { | ||||
case ICMP_TIMXCEED_INTRANS: | case ICMP_TIMXCEED_INTRANS: | ||||
(void)printf("Time to live exceeded\n"); | (void)printf("Time to live exceeded\n"); | ||||
break; | break; | ||||
case ICMP_TIMXCEED_REASS: | case ICMP_TIMXCEED_REASS: | ||||
(void)printf("Frag reassembly time exceeded\n"); | (void)printf("Frag reassembly time exceeded\n"); | ||||
break; | break; | ||||
default: | default: | ||||
(void)printf("Time exceeded, Bad Code: %d\n", | (void)printf("Time exceeded, Bad Code: %d\n", | ||||
icp->icmp_code); | icp->icmp_code); | ||||
break; | break; | ||||
} | } | ||||
#ifndef icmp_data | pr_retip(oip, oicmp_raw); | ||||
pr_retip(&icp->icmp_ip); | |||||
#else | |||||
pr_retip((struct ip *)icp->icmp_data); | |||||
#endif | |||||
break; | break; | ||||
case ICMP_PARAMPROB: | case ICMP_PARAMPROB: | ||||
(void)printf("Parameter problem: pointer = 0x%02x\n", | (void)printf("Parameter problem: pointer = 0x%02x\n", | ||||
icp->icmp_hun.ih_pptr); | icp->icmp_hun.ih_pptr); | ||||
#ifndef icmp_data | pr_retip(oip, oicmp_raw); | ||||
pr_retip(&icp->icmp_ip); | |||||
#else | |||||
pr_retip((struct ip *)icp->icmp_data); | |||||
#endif | |||||
break; | break; | ||||
case ICMP_TSTAMP: | case ICMP_TSTAMP: | ||||
(void)printf("Timestamp\n"); | (void)printf("Timestamp\n"); | ||||
/* XXX ID + Seq + 3 timestamps */ | /* XXX ID + Seq + 3 timestamps */ | ||||
break; | break; | ||||
case ICMP_TSTAMPREPLY: | case ICMP_TSTAMPREPLY: | ||||
(void)printf("Timestamp Reply\n"); | (void)printf("Timestamp Reply\n"); | ||||
/* XXX ID + Seq + 3 timestamps */ | /* XXX ID + Seq + 3 timestamps */ | ||||
▲ Show 20 Lines • Show All 81 Lines • ▼ Show 20 Lines | pr_addr(struct in_addr ina) | ||||
return(buf); | return(buf); | ||||
} | } | ||||
/* | /* | ||||
* pr_retip -- | * pr_retip -- | ||||
* Dump some info on a returned (via ICMP) IP packet. | * Dump some info on a returned (via ICMP) IP packet. | ||||
*/ | */ | ||||
static void | static void | ||||
pr_retip(struct ip *ip) | pr_retip(struct ip *ip, const u_char *cp) | ||||
{ | { | ||||
u_char *cp; | |||||
int hlen; | |||||
pr_iph(ip); | pr_iph(ip); | ||||
hlen = ip->ip_hl << 2; | |||||
cp = (u_char *)ip + hlen; | |||||
if (ip->ip_p == 6) | if (ip->ip_p == 6) | ||||
(void)printf("TCP: from port %u, to port %u (decimal)\n", | (void)printf("TCP: from port %u, to port %u (decimal)\n", | ||||
(*cp * 256 + *(cp + 1)), (*(cp + 2) * 256 + *(cp + 3))); | (*cp * 256 + *(cp + 1)), (*(cp + 2) * 256 + *(cp + 3))); | ||||
else if (ip->ip_p == 17) | else if (ip->ip_p == 17) | ||||
(void)printf("UDP: from port %u, to port %u (decimal)\n", | (void)printf("UDP: from port %u, to port %u (decimal)\n", | ||||
(*cp * 256 + *(cp + 1)), (*(cp + 2) * 256 + *(cp + 3))); | (*cp * 256 + *(cp + 1)), (*(cp + 2) * 256 + *(cp + 3))); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 94 Lines • Show Last 20 Lines |
I don't think there's any reason to change the type of n, too.