Initial commit
This commit is contained in:
892
fuzzing-ping/afl_ping.c
Normal file
892
fuzzing-ping/afl_ping.c
Normal file
@ -0,0 +1,892 @@
|
||||
/*
|
||||
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the project nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 1989, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Mike Muuss.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Using the InterNet Control Message Protocol (ICMP) "ECHO" facility,
|
||||
* measure round-trip-delays and packet loss across network paths.
|
||||
*
|
||||
* Author -
|
||||
* Mike Muuss
|
||||
* U. S. Army Ballistic Research Laboratory
|
||||
* December, 1983
|
||||
*
|
||||
* Status -
|
||||
* Public Domain. Distribution Unlimited.
|
||||
* Bugs -
|
||||
* More statistics could always be gathered.
|
||||
* This program has to run SUID to ROOT to access the ICMP socket.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/uio.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/ip_icmp.h>
|
||||
#include <netinet/ip_var.h>
|
||||
#include <netinet/ip6.h>
|
||||
#include <netinet/icmp6.h>
|
||||
#include <netinet/ip_ah.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
#include <math.h>
|
||||
#include <poll.h>
|
||||
#include <pwd.h>
|
||||
#include <signal.h>
|
||||
#include <siphash.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define F_FLOOD 0x0001
|
||||
#define F_INTERVAL 0x0002
|
||||
#define F_HOSTNAME 0x0004
|
||||
#define F_PINGFILLED 0x0008
|
||||
#define F_QUIET 0x0010
|
||||
#define F_RROUTE 0x0020
|
||||
#define F_SO_DEBUG 0x0040
|
||||
#define F_SHOWCHAR 0x0080
|
||||
#define F_VERBOSE 0x0100
|
||||
/* 0x0200 */
|
||||
#define F_HDRINCL 0x0400
|
||||
#define F_TTL 0x0800
|
||||
#define F_TOS 0x1000
|
||||
#define F_AUD_RECV 0x2000
|
||||
#define F_AUD_MISS 0x4000
|
||||
|
||||
|
||||
#define ECHOLEN 8 /* icmp echo header len excluding time */
|
||||
#define ECHOTMLEN sizeof(struct payload)
|
||||
#define DEFDATALEN (64 - ECHOLEN) /* default data length */
|
||||
#define MAXIPLEN 60
|
||||
#define MAXICMPLEN 76
|
||||
#define MAXPAYLOAD (IP_MAXPACKET - MAXIPLEN - ECHOLEN)
|
||||
#define IP6LEN 40
|
||||
#define EXTRA 256 /* for AH and various other headers. weird. */
|
||||
#define MAXPAYLOAD6 IPV6_MAXPACKET - IP6LEN - ECHOLEN
|
||||
#define MAXWAIT_DEFAULT 10 /* secs to wait for response */
|
||||
#define NROUTES 9 /* number of record route slots */
|
||||
|
||||
struct tv64 {
|
||||
u_int64_t tv64_sec;
|
||||
u_int64_t tv64_nsec;
|
||||
};
|
||||
|
||||
struct payload {
|
||||
struct tv64 tv64;
|
||||
u_int8_t mac[SIPHASH_DIGEST_LENGTH];
|
||||
};
|
||||
|
||||
const char *pr_addr(struct sockaddr *, socklen_t);
|
||||
void pr_pack(u_char *, int, struct msghdr *);
|
||||
/* IPv4 specific functions */
|
||||
void pr_ipopt(int, u_char *);
|
||||
int in_cksum(u_short *, int);
|
||||
void pr_icmph(struct icmp *);
|
||||
void pr_retip(struct ip *);
|
||||
void pr_iph(struct ip *);
|
||||
int map_tos(char *, int *);
|
||||
|
||||
int v6flag = 0;
|
||||
int options = F_VERBOSE;
|
||||
|
||||
char BSPACE = '\b'; /* characters written for flood */
|
||||
char DOT = '.';
|
||||
int datalen = DEFDATALEN;
|
||||
|
||||
int64_t npackets; /* max packets to transmit */
|
||||
int64_t nreceived; /* # of packets we got back */
|
||||
int64_t nrepeats; /* number of duplicates */
|
||||
int64_t ntransmitted; /* sequence # for outbound packets = #sent */
|
||||
int64_t nmissedmax = 1; /* max value of ntransmitted - nreceived - 1 */
|
||||
struct timeval interval = {1, 0}; /* interval between packets */
|
||||
|
||||
/* timing */
|
||||
int timing; /* flag to do timing */
|
||||
int timinginfo;
|
||||
unsigned int maxwait = MAXWAIT_DEFAULT; /* max seconds to wait for response */
|
||||
double tmin = 999999999.0; /* minimum round trip time */
|
||||
double tmax; /* maximum round trip time */
|
||||
double tsum; /* sum of all times, for doing average */
|
||||
double tsumsq; /* sum of all times squared, for std. dev. */
|
||||
|
||||
struct tv64 tv64_offset;
|
||||
|
||||
/*
|
||||
* MAX_DUP_CHK is the number of bits in received table, i.e. the maximum
|
||||
* number of received sequence numbers we can keep track of. Change 128
|
||||
* to 8192 for complete accuracy...
|
||||
*/
|
||||
#define MAX_DUP_CHK (8 * 8192)
|
||||
int mx_dup_ck = MAX_DUP_CHK;
|
||||
char rcvd_tbl[MAX_DUP_CHK / 8];
|
||||
|
||||
#define A(bit) rcvd_tbl[(bit)>>3] /* identify byte in array */
|
||||
#define B(bit) (1 << ((bit) & 0x07)) /* identify bit in byte */
|
||||
#define SET(bit) (A(bit) |= B(bit))
|
||||
#define CLR(bit) (A(bit) &= (~B(bit)))
|
||||
#define TST(bit) (A(bit) & B(bit))
|
||||
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
FILE *f;
|
||||
size_t fsize;
|
||||
uint8_t *buf;
|
||||
|
||||
f = fopen(argv[1], "rb");
|
||||
fseek(f, 0, SEEK_END);
|
||||
fsize = ftell(f);
|
||||
rewind(f);
|
||||
|
||||
buf = malloc(fsize + 1);
|
||||
if (buf == NULL)
|
||||
err(1, NULL);
|
||||
fread(buf, fsize, 1, f);
|
||||
fclose(f);
|
||||
|
||||
pr_pack(buf, fsize, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
pr_pack(u_char *buf, int cc, struct msghdr *mhdr)
|
||||
{
|
||||
struct ip *ip = NULL;
|
||||
struct icmp *icp = NULL;
|
||||
struct icmp6_hdr *icp6 = NULL;
|
||||
struct timespec ts, tp;
|
||||
struct payload payload;
|
||||
struct sockaddr *from;
|
||||
socklen_t fromlen;
|
||||
double triptime = 0;
|
||||
int i, dupflag;
|
||||
int hlen = -1, hoplim = -1, echo_reply = 0;
|
||||
u_int16_t seq;
|
||||
u_char *cp, *dp;
|
||||
char* pkttime;
|
||||
|
||||
if (clock_gettime(CLOCK_MONOTONIC, &ts) == -1)
|
||||
err(1, "clock_gettime(CLOCK_MONOTONIC)");
|
||||
|
||||
if (v6flag) {
|
||||
#if 0
|
||||
if (!mhdr || !mhdr->msg_name ||
|
||||
mhdr->msg_namelen != sizeof(struct sockaddr_in6) ||
|
||||
((struct sockaddr *)mhdr->msg_name)->sa_family !=
|
||||
AF_INET6) {
|
||||
if (options & F_VERBOSE)
|
||||
warnx("invalid peername");
|
||||
return;
|
||||
}
|
||||
from = (struct sockaddr *)mhdr->msg_name;
|
||||
fromlen = mhdr->msg_namelen;
|
||||
|
||||
if (cc < sizeof(struct icmp6_hdr)) {
|
||||
if (options & F_VERBOSE)
|
||||
warnx("packet too short (%d bytes) from %s", cc,
|
||||
pr_addr(from, fromlen));
|
||||
return;
|
||||
}
|
||||
icp6 = (struct icmp6_hdr *)buf;
|
||||
|
||||
if ((hoplim = get_hoplim(mhdr)) == -1) {
|
||||
warnx("failed to get receiving hop limit");
|
||||
return;
|
||||
}
|
||||
|
||||
if (icp6->icmp6_type == ICMP6_ECHO_REPLY) {
|
||||
if (icp6->icmp6_id != ident)
|
||||
return; /* 'Twas not our ECHO */
|
||||
seq = icp6->icmp6_seq;
|
||||
echo_reply = 1;
|
||||
pkttime = (char *)(icp6 + 1);
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
#if 0
|
||||
if (!mhdr || !mhdr->msg_name ||
|
||||
mhdr->msg_namelen != sizeof(struct sockaddr_in) ||
|
||||
((struct sockaddr *)mhdr->msg_name)->sa_family != AF_INET) {
|
||||
if (options & F_VERBOSE)
|
||||
warnx("invalid peername");
|
||||
return;
|
||||
}
|
||||
from = (struct sockaddr *)mhdr->msg_name;
|
||||
fromlen = mhdr->msg_namelen;
|
||||
#endif
|
||||
/* Check the IP header */
|
||||
ip = (struct ip *)buf;
|
||||
hlen = ip->ip_hl << 2;
|
||||
if (cc < hlen + ICMP_MINLEN) {
|
||||
if (options & F_VERBOSE)
|
||||
warnx("packet too short (%d bytes) from %s", cc,
|
||||
pr_addr(from, fromlen));
|
||||
return;
|
||||
}
|
||||
|
||||
/* Now the ICMP part */
|
||||
cc -= hlen;
|
||||
icp = (struct icmp *)(buf + hlen);
|
||||
if (icp->icmp_type == ICMP_ECHOREPLY) {
|
||||
#if 0
|
||||
if (icp->icmp_id != ident)
|
||||
return; /* 'Twas not our ECHO */
|
||||
#endif
|
||||
seq = icp->icmp_seq;
|
||||
echo_reply = 1;
|
||||
pkttime = (char *)icp->icmp_data;
|
||||
}
|
||||
}
|
||||
|
||||
if (echo_reply) {
|
||||
++nreceived;
|
||||
if (cc >= ECHOLEN + ECHOTMLEN) {
|
||||
SIPHASH_CTX ctx;
|
||||
struct tv64 *tv64;
|
||||
u_int8_t mac[SIPHASH_DIGEST_LENGTH];
|
||||
|
||||
memcpy(&payload, pkttime, sizeof(payload));
|
||||
tv64 = &payload.tv64;
|
||||
|
||||
#if 0
|
||||
SipHash24_Init(&ctx, &mac_key);
|
||||
SipHash24_Update(&ctx, tv64, sizeof(*tv64));
|
||||
SipHash24_Update(&ctx, &ident, sizeof(ident));
|
||||
SipHash24_Update(&ctx, &seq, sizeof(seq));
|
||||
SipHash24_Final(mac, &ctx);
|
||||
|
||||
if (timingsafe_memcmp(mac, &payload.mac,
|
||||
sizeof(mac)) != 0) {
|
||||
printf("signature mismatch from %s: "
|
||||
"icmp_seq=%u\n", pr_addr(from, fromlen),
|
||||
ntohs(seq));
|
||||
--nreceived;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
timinginfo=1;
|
||||
|
||||
tp.tv_sec = betoh64(tv64->tv64_sec) -
|
||||
tv64_offset.tv64_sec;
|
||||
tp.tv_nsec = betoh64(tv64->tv64_nsec) -
|
||||
tv64_offset.tv64_nsec;
|
||||
|
||||
timespecsub(&ts, &tp, &ts);
|
||||
triptime = ((double)ts.tv_sec) * 1000.0 +
|
||||
((double)ts.tv_nsec) / 1000000.0;
|
||||
tsum += triptime;
|
||||
tsumsq += triptime * triptime;
|
||||
if (triptime < tmin)
|
||||
tmin = triptime;
|
||||
if (triptime > tmax)
|
||||
tmax = triptime;
|
||||
}
|
||||
|
||||
if (TST(ntohs(seq) % mx_dup_ck)) {
|
||||
++nrepeats;
|
||||
--nreceived;
|
||||
dupflag = 1;
|
||||
} else {
|
||||
SET(ntohs(seq) % mx_dup_ck);
|
||||
dupflag = 0;
|
||||
}
|
||||
|
||||
if (options & F_QUIET)
|
||||
return;
|
||||
|
||||
if (options & F_FLOOD)
|
||||
write(STDOUT_FILENO, &BSPACE, 1);
|
||||
|
||||
else if (options & F_SHOWCHAR) {
|
||||
if (dupflag)
|
||||
putchar('D');
|
||||
else if (cc - ECHOLEN < datalen)
|
||||
putchar('T');
|
||||
else
|
||||
putchar('!');
|
||||
} else {
|
||||
printf("%d bytes from %s: icmp_seq=%u", cc,
|
||||
pr_addr(from, fromlen), ntohs(seq));
|
||||
if (v6flag)
|
||||
printf(" hlim=%d", hoplim);
|
||||
else
|
||||
printf(" ttl=%d", ip->ip_ttl);
|
||||
if (cc >= ECHOLEN + ECHOTMLEN)
|
||||
printf(" time=%.3f ms", triptime);
|
||||
if (dupflag)
|
||||
printf(" (DUP!)");
|
||||
/* check the data */
|
||||
if (cc - ECHOLEN < datalen)
|
||||
printf(" (TRUNC!)");
|
||||
if (v6flag)
|
||||
cp = buf + ECHOLEN + ECHOTMLEN;
|
||||
else
|
||||
cp = (u_char *)&icp->icmp_data[ECHOTMLEN];
|
||||
#if 0
|
||||
dp = &outpack[ECHOLEN + ECHOTMLEN];
|
||||
for (i = ECHOLEN + ECHOTMLEN;
|
||||
i < cc && i < datalen;
|
||||
++i, ++cp, ++dp) {
|
||||
if (*cp != *dp) {
|
||||
printf("\nwrong data byte #%d "
|
||||
"should be 0x%x but was 0x%x",
|
||||
i - ECHOLEN, *dp, *cp);
|
||||
if (v6flag)
|
||||
cp = buf + ECHOLEN;
|
||||
else
|
||||
cp = (u_char *)
|
||||
&icp->icmp_data[0];
|
||||
for (i = ECHOLEN; i < cc && i < datalen;
|
||||
++i, ++cp) {
|
||||
if ((i % 32) == 8)
|
||||
printf("\n\t");
|
||||
printf("%x ", *cp);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
} else {
|
||||
/* We've got something other than an ECHOREPLY */
|
||||
if (!(options & F_VERBOSE))
|
||||
return;
|
||||
printf("%d bytes from %s: ", cc, pr_addr(from, fromlen));
|
||||
#if 0
|
||||
if (v6flag)
|
||||
pr_icmph6(icp6, buf + cc);
|
||||
else
|
||||
#endif
|
||||
pr_icmph(icp);
|
||||
}
|
||||
|
||||
/* Display any IP options */
|
||||
if (!v6flag && hlen > sizeof(struct ip))
|
||||
pr_ipopt(hlen, buf);
|
||||
|
||||
if (!(options & F_FLOOD)) {
|
||||
if (!(options & F_SHOWCHAR)) {
|
||||
putchar('\n');
|
||||
#if 0
|
||||
if (v6flag && (options & F_VERBOSE))
|
||||
pr_exthdrs(mhdr);
|
||||
#endif
|
||||
}
|
||||
fflush(stdout);
|
||||
if (options & F_AUD_RECV)
|
||||
fputc('\a', stderr);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
pr_ipopt(int hlen, u_char *buf)
|
||||
{
|
||||
static int old_rrlen;
|
||||
static char old_rr[MAX_IPOPTLEN];
|
||||
struct sockaddr_in s_in;
|
||||
in_addr_t l;
|
||||
u_int i, j;
|
||||
u_char *cp;
|
||||
|
||||
cp = buf + sizeof(struct ip);
|
||||
|
||||
s_in.sin_len = sizeof(s_in);
|
||||
s_in.sin_family = AF_INET;
|
||||
|
||||
for (; hlen > (int)sizeof(struct ip); --hlen, ++cp) {
|
||||
switch (*cp) {
|
||||
case IPOPT_EOL:
|
||||
hlen = 0;
|
||||
break;
|
||||
case IPOPT_LSRR:
|
||||
printf("\nLSRR: ");
|
||||
hlen -= 2;
|
||||
j = *++cp;
|
||||
++cp;
|
||||
i = 0;
|
||||
if (j > IPOPT_MINOFF) {
|
||||
for (;;) {
|
||||
l = *++cp;
|
||||
l = (l<<8) + *++cp;
|
||||
l = (l<<8) + *++cp;
|
||||
l = (l<<8) + *++cp;
|
||||
if (l == 0)
|
||||
printf("\t0.0.0.0");
|
||||
else {
|
||||
s_in.sin_addr.s_addr = ntohl(l);
|
||||
printf("\t%s",
|
||||
pr_addr((struct sockaddr*)
|
||||
&s_in, sizeof(s_in)));
|
||||
}
|
||||
hlen -= 4;
|
||||
j -= 4;
|
||||
i += 4;
|
||||
if (j <= IPOPT_MINOFF)
|
||||
break;
|
||||
if (i >= MAX_IPOPTLEN) {
|
||||
printf("\t(truncated route)");
|
||||
break;
|
||||
}
|
||||
putchar('\n');
|
||||
}
|
||||
}
|
||||
break;
|
||||
case IPOPT_RR:
|
||||
j = *++cp; /* get length */
|
||||
i = *++cp; /* and pointer */
|
||||
hlen -= 2;
|
||||
if (i > j)
|
||||
i = j;
|
||||
i -= IPOPT_MINOFF;
|
||||
if (i <= 0)
|
||||
continue;
|
||||
if (i == old_rrlen &&
|
||||
cp == buf + sizeof(struct ip) + 2 &&
|
||||
!memcmp(cp, old_rr, i) &&
|
||||
!(options & F_FLOOD)) {
|
||||
printf("\t(same route)");
|
||||
i = (i + 3) & ~0x3;
|
||||
hlen -= i;
|
||||
cp += i;
|
||||
break;
|
||||
}
|
||||
if (i < MAX_IPOPTLEN) {
|
||||
old_rrlen = i;
|
||||
memcpy(old_rr, cp, i);
|
||||
} else
|
||||
old_rrlen = 0;
|
||||
|
||||
printf("\nRR: ");
|
||||
j = 0;
|
||||
for (;;) {
|
||||
l = *++cp;
|
||||
l = (l<<8) + *++cp;
|
||||
l = (l<<8) + *++cp;
|
||||
l = (l<<8) + *++cp;
|
||||
if (l == 0)
|
||||
printf("\t0.0.0.0");
|
||||
else {
|
||||
s_in.sin_addr.s_addr = ntohl(l);
|
||||
printf("\t%s",
|
||||
pr_addr((struct sockaddr*)&s_in,
|
||||
sizeof(s_in)));
|
||||
}
|
||||
hlen -= 4;
|
||||
i -= 4;
|
||||
j += 4;
|
||||
if (i <= 0)
|
||||
break;
|
||||
if (j >= MAX_IPOPTLEN) {
|
||||
printf("\t(truncated route)");
|
||||
break;
|
||||
}
|
||||
putchar('\n');
|
||||
}
|
||||
break;
|
||||
case IPOPT_NOP:
|
||||
printf("\nNOP");
|
||||
break;
|
||||
default:
|
||||
printf("\nunknown option %x", *cp);
|
||||
if (cp[IPOPT_OLEN] > 0 && (cp[IPOPT_OLEN] - 1) <= hlen) {
|
||||
hlen = hlen - (cp[IPOPT_OLEN] - 1);
|
||||
cp = cp + (cp[IPOPT_OLEN] - 1);
|
||||
} else
|
||||
hlen = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* pr_addr --
|
||||
* Return address in numeric form or a host name
|
||||
*/
|
||||
const char *
|
||||
pr_addr(struct sockaddr *addr, socklen_t addrlen)
|
||||
{
|
||||
static char buf[NI_MAXHOST];
|
||||
int flag = 0;
|
||||
|
||||
return "not implemented";
|
||||
|
||||
if (!(options & F_HOSTNAME))
|
||||
flag |= NI_NUMERICHOST;
|
||||
|
||||
if (getnameinfo(addr, addrlen, buf, sizeof(buf), NULL, 0, flag) == 0)
|
||||
return (buf);
|
||||
else
|
||||
return "?";
|
||||
}
|
||||
|
||||
/*
|
||||
* pr_icmph --
|
||||
* Print a descriptive string about an ICMP header.
|
||||
*/
|
||||
void
|
||||
pr_icmph(struct icmp *icp)
|
||||
{
|
||||
switch(icp->icmp_type) {
|
||||
case ICMP_ECHOREPLY:
|
||||
printf("Echo Reply\n");
|
||||
/* XXX ID + Seq + Data */
|
||||
break;
|
||||
case ICMP_UNREACH:
|
||||
switch(icp->icmp_code) {
|
||||
case ICMP_UNREACH_NET:
|
||||
printf("Destination Net Unreachable\n");
|
||||
break;
|
||||
case ICMP_UNREACH_HOST:
|
||||
printf("Destination Host Unreachable\n");
|
||||
break;
|
||||
case ICMP_UNREACH_PROTOCOL:
|
||||
printf("Destination Protocol Unreachable\n");
|
||||
break;
|
||||
case ICMP_UNREACH_PORT:
|
||||
printf("Destination Port Unreachable\n");
|
||||
break;
|
||||
case ICMP_UNREACH_NEEDFRAG:
|
||||
if (icp->icmp_nextmtu != 0)
|
||||
printf("frag needed and DF set (MTU %d)\n",
|
||||
ntohs(icp->icmp_nextmtu));
|
||||
else
|
||||
printf("frag needed and DF set\n");
|
||||
break;
|
||||
case ICMP_UNREACH_SRCFAIL:
|
||||
printf("Source Route Failed\n");
|
||||
break;
|
||||
case ICMP_UNREACH_NET_UNKNOWN:
|
||||
printf("Network Unknown\n");
|
||||
break;
|
||||
case ICMP_UNREACH_HOST_UNKNOWN:
|
||||
printf("Host Unknown\n");
|
||||
break;
|
||||
case ICMP_UNREACH_ISOLATED:
|
||||
printf("Source Isolated\n");
|
||||
break;
|
||||
case ICMP_UNREACH_NET_PROHIB:
|
||||
printf("Dest. Net Administratively Prohibited\n");
|
||||
break;
|
||||
case ICMP_UNREACH_HOST_PROHIB:
|
||||
printf("Dest. Host Administratively Prohibited\n");
|
||||
break;
|
||||
case ICMP_UNREACH_TOSNET:
|
||||
printf("Destination Net Unreachable for TOS\n");
|
||||
break;
|
||||
case ICMP_UNREACH_TOSHOST:
|
||||
printf("Destination Host Unreachable for TOS\n");
|
||||
break;
|
||||
case ICMP_UNREACH_FILTER_PROHIB:
|
||||
printf("Route administratively prohibited\n");
|
||||
break;
|
||||
case ICMP_UNREACH_HOST_PRECEDENCE:
|
||||
printf("Host Precedence Violation\n");
|
||||
break;
|
||||
case ICMP_UNREACH_PRECEDENCE_CUTOFF:
|
||||
printf("Precedence Cutoff\n");
|
||||
break;
|
||||
default:
|
||||
printf("Dest Unreachable, Unknown Code: %d\n",
|
||||
icp->icmp_code);
|
||||
break;
|
||||
}
|
||||
/* Print returned IP header information */
|
||||
pr_retip((struct ip *)icp->icmp_data);
|
||||
break;
|
||||
case ICMP_SOURCEQUENCH:
|
||||
printf("Source Quench\n");
|
||||
pr_retip((struct ip *)icp->icmp_data);
|
||||
break;
|
||||
case ICMP_REDIRECT:
|
||||
switch(icp->icmp_code) {
|
||||
case ICMP_REDIRECT_NET:
|
||||
printf("Redirect Network");
|
||||
break;
|
||||
case ICMP_REDIRECT_HOST:
|
||||
printf("Redirect Host");
|
||||
break;
|
||||
case ICMP_REDIRECT_TOSNET:
|
||||
printf("Redirect Type of Service and Network");
|
||||
break;
|
||||
case ICMP_REDIRECT_TOSHOST:
|
||||
printf("Redirect Type of Service and Host");
|
||||
break;
|
||||
default:
|
||||
printf("Redirect, Unknown Code: %d", icp->icmp_code);
|
||||
break;
|
||||
}
|
||||
printf("(New addr: %s)\n",
|
||||
inet_ntoa(icp->icmp_gwaddr));
|
||||
pr_retip((struct ip *)icp->icmp_data);
|
||||
break;
|
||||
case ICMP_ECHO:
|
||||
printf("Echo Request\n");
|
||||
/* XXX ID + Seq + Data */
|
||||
break;
|
||||
case ICMP_ROUTERADVERT:
|
||||
/* RFC1256 */
|
||||
printf("Router Discovery Advertisement\n");
|
||||
printf("(%d entries, lifetime %d seconds)\n",
|
||||
icp->icmp_num_addrs, ntohs(icp->icmp_lifetime));
|
||||
break;
|
||||
case ICMP_ROUTERSOLICIT:
|
||||
/* RFC1256 */
|
||||
printf("Router Discovery Solicitation\n");
|
||||
break;
|
||||
case ICMP_TIMXCEED:
|
||||
switch(icp->icmp_code) {
|
||||
case ICMP_TIMXCEED_INTRANS:
|
||||
printf("Time to live exceeded\n");
|
||||
break;
|
||||
case ICMP_TIMXCEED_REASS:
|
||||
printf("Frag reassembly time exceeded\n");
|
||||
break;
|
||||
default:
|
||||
printf("Time exceeded, Unknown Code: %d\n",
|
||||
icp->icmp_code);
|
||||
break;
|
||||
}
|
||||
pr_retip((struct ip *)icp->icmp_data);
|
||||
break;
|
||||
case ICMP_PARAMPROB:
|
||||
switch(icp->icmp_code) {
|
||||
case ICMP_PARAMPROB_OPTABSENT:
|
||||
printf("Parameter problem, required option "
|
||||
"absent: pointer = 0x%02x\n",
|
||||
ntohs(icp->icmp_hun.ih_pptr));
|
||||
break;
|
||||
default:
|
||||
printf("Parameter problem: pointer = 0x%02x\n",
|
||||
ntohs(icp->icmp_hun.ih_pptr));
|
||||
break;
|
||||
}
|
||||
pr_retip((struct ip *)icp->icmp_data);
|
||||
break;
|
||||
case ICMP_TSTAMP:
|
||||
printf("Timestamp\n");
|
||||
/* XXX ID + Seq + 3 timestamps */
|
||||
break;
|
||||
case ICMP_TSTAMPREPLY:
|
||||
printf("Timestamp Reply\n");
|
||||
/* XXX ID + Seq + 3 timestamps */
|
||||
break;
|
||||
case ICMP_IREQ:
|
||||
printf("Information Request\n");
|
||||
/* XXX ID + Seq */
|
||||
break;
|
||||
case ICMP_IREQREPLY:
|
||||
printf("Information Reply\n");
|
||||
/* XXX ID + Seq */
|
||||
break;
|
||||
case ICMP_MASKREQ:
|
||||
printf("Address Mask Request\n");
|
||||
break;
|
||||
case ICMP_MASKREPLY:
|
||||
printf("Address Mask Reply (Mask 0x%08x)\n",
|
||||
ntohl(icp->icmp_mask));
|
||||
break;
|
||||
default:
|
||||
printf("Unknown ICMP type: %d\n", icp->icmp_type);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* pr_iph --
|
||||
* Print an IP header with options.
|
||||
*/
|
||||
void
|
||||
pr_iph(struct ip *ip)
|
||||
{
|
||||
int hlen;
|
||||
u_char *cp;
|
||||
|
||||
hlen = ip->ip_hl << 2;
|
||||
cp = (u_char *)ip + 20; /* point to options */
|
||||
|
||||
printf("Vr HL TOS Len ID Flg off TTL Pro cks Src Dst Data\n");
|
||||
printf(" %1x %1x %02x %04x %04x",
|
||||
ip->ip_v, ip->ip_hl, ip->ip_tos, ip->ip_len, ip->ip_id);
|
||||
printf(" %1x %04x", ((ip->ip_off) & 0xe000) >> 13,
|
||||
(ip->ip_off) & 0x1fff);
|
||||
printf(" %02x %02x %04x", ip->ip_ttl, ip->ip_p, ip->ip_sum);
|
||||
printf(" %s ", inet_ntoa(*(struct in_addr *)&ip->ip_src.s_addr));
|
||||
printf(" %s ", inet_ntoa(*(struct in_addr *)&ip->ip_dst.s_addr));
|
||||
/* dump and option bytes */
|
||||
while (hlen-- > 20) {
|
||||
printf("%02x", *cp++);
|
||||
}
|
||||
putchar('\n');
|
||||
}
|
||||
|
||||
/*
|
||||
* pr_retip --
|
||||
* Dump some info on a returned (via ICMP) IP packet.
|
||||
*/
|
||||
void
|
||||
pr_retip(struct ip *ip)
|
||||
{
|
||||
int hlen;
|
||||
u_char *cp;
|
||||
|
||||
pr_iph(ip);
|
||||
hlen = ip->ip_hl << 2;
|
||||
cp = (u_char *)ip + hlen;
|
||||
|
||||
if (ip->ip_p == 6)
|
||||
printf("TCP: from port %u, to port %u (decimal)\n",
|
||||
(*cp * 256 + *(cp + 1)), (*(cp + 2) * 256 + *(cp + 3)));
|
||||
else if (ip->ip_p == 17)
|
||||
printf("UDP: from port %u, to port %u (decimal)\n",
|
||||
(*cp * 256 + *(cp + 1)), (*(cp + 2) * 256 + *(cp + 3)));
|
||||
}
|
||||
|
||||
#ifndef SMALL
|
||||
int
|
||||
map_tos(char *key, int *val)
|
||||
{
|
||||
/* DiffServ Codepoints and other TOS mappings */
|
||||
const struct toskeywords {
|
||||
const char *keyword;
|
||||
int val;
|
||||
} *t, toskeywords[] = {
|
||||
{ "af11", IPTOS_DSCP_AF11 },
|
||||
{ "af12", IPTOS_DSCP_AF12 },
|
||||
{ "af13", IPTOS_DSCP_AF13 },
|
||||
{ "af21", IPTOS_DSCP_AF21 },
|
||||
{ "af22", IPTOS_DSCP_AF22 },
|
||||
{ "af23", IPTOS_DSCP_AF23 },
|
||||
{ "af31", IPTOS_DSCP_AF31 },
|
||||
{ "af32", IPTOS_DSCP_AF32 },
|
||||
{ "af33", IPTOS_DSCP_AF33 },
|
||||
{ "af41", IPTOS_DSCP_AF41 },
|
||||
{ "af42", IPTOS_DSCP_AF42 },
|
||||
{ "af43", IPTOS_DSCP_AF43 },
|
||||
{ "critical", IPTOS_PREC_CRITIC_ECP },
|
||||
{ "cs0", IPTOS_DSCP_CS0 },
|
||||
{ "cs1", IPTOS_DSCP_CS1 },
|
||||
{ "cs2", IPTOS_DSCP_CS2 },
|
||||
{ "cs3", IPTOS_DSCP_CS3 },
|
||||
{ "cs4", IPTOS_DSCP_CS4 },
|
||||
{ "cs5", IPTOS_DSCP_CS5 },
|
||||
{ "cs6", IPTOS_DSCP_CS6 },
|
||||
{ "cs7", IPTOS_DSCP_CS7 },
|
||||
{ "ef", IPTOS_DSCP_EF },
|
||||
{ "inetcontrol", IPTOS_PREC_INTERNETCONTROL },
|
||||
{ "lowdelay", IPTOS_LOWDELAY },
|
||||
{ "netcontrol", IPTOS_PREC_NETCONTROL },
|
||||
{ "reliability", IPTOS_RELIABILITY },
|
||||
{ "throughput", IPTOS_THROUGHPUT },
|
||||
{ NULL, -1 },
|
||||
};
|
||||
|
||||
for (t = toskeywords; t->keyword != NULL; t++) {
|
||||
if (strcmp(key, t->keyword) == 0) {
|
||||
*val = t->val;
|
||||
return (1);
|
||||
}
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
#endif /* SMALL */
|
||||
|
||||
#if 0
|
||||
void
|
||||
pr_exthdrs(struct msghdr *mhdr)
|
||||
{
|
||||
struct cmsghdr *cm;
|
||||
|
||||
for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(mhdr); cm;
|
||||
cm = (struct cmsghdr *)CMSG_NXTHDR(mhdr, cm)) {
|
||||
if (cm->cmsg_level != IPPROTO_IPV6)
|
||||
continue;
|
||||
|
||||
switch (cm->cmsg_type) {
|
||||
case IPV6_HOPOPTS:
|
||||
printf(" HbH Options: ");
|
||||
pr_ip6opt(CMSG_DATA(cm));
|
||||
break;
|
||||
case IPV6_DSTOPTS:
|
||||
case IPV6_RTHDRDSTOPTS:
|
||||
printf(" Dst Options: ");
|
||||
pr_ip6opt(CMSG_DATA(cm));
|
||||
break;
|
||||
case IPV6_RTHDR:
|
||||
printf(" Routing: ");
|
||||
pr_rthdr(CMSG_DATA(cm));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
Reference in New Issue
Block a user