MFC r283784:
Remove trailing whitespaces. MFC r283785: Require the embedded packet to contain 8 bytes after the IP header instead of only 4. This is guaranteed by RFC 792 and the verification of GRE, ICMP and TCP packets use 8 bytes. MFC r283786: There is no payload anymore. So compute the minimum packet length correctly and use 40 as the default (if the minumum allows it), as specified in the man page. MFC r283806: When the packet verification fails in verbose mode, print the correct number of words in host byte order. Also remove a stray 'x'. MFC r283808: Don't send malformed SCTP probe packets. MFC r283813: Use an empty string for field descriptions of unknown protocols. MFC r283817: Don't send illegal packets when using UDP-Lite. MFC r283819: A TCP checksum of 0 is completely valid. Mapping 0 to 0xffff only applies to UDP and UDP-Lite. MFC r283820: The code starts with base + 1 as the first port. Fix to documentation to match that.
This commit is contained in:
parent
cec9850b29
commit
e9ec710324
@ -16,7 +16,7 @@
|
||||
.\" $Id: traceroute.8,v 1.19 2000/09/21 08:44:19 leres Exp $
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd June 19, 2012
|
||||
.Dd May 31, 2015
|
||||
.Dt TRACEROUTE 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -65,7 +65,7 @@ Turn on AS# lookups and use the given server instead of the
|
||||
default.
|
||||
.It Fl e
|
||||
Firewall evasion mode.
|
||||
Use fixed destination ports for UDP and TCP probes.
|
||||
Use fixed destination ports for UDP, UDP-Lite, TCP and SCTP probes.
|
||||
The destination port does NOT increment with each packet sent.
|
||||
.It Fl f Ar first_ttl
|
||||
Set the initial time-to-live used in the first outgoing probe packet.
|
||||
@ -110,21 +110,24 @@ Print hop addresses numerically rather than symbolically and numerically
|
||||
path).
|
||||
.It Fl P Ar proto
|
||||
Send packets of specified IP protocol. The currently supported protocols
|
||||
are: UDP, TCP, GRE and ICMP. Other protocols may also be specified (either by
|
||||
name or by number), though
|
||||
are: UDP, UDP-Lite, TCP, SCTP, GRE and ICMP. Other protocols may also be
|
||||
specified (either by name or by number), though
|
||||
.Nm
|
||||
does not implement any special knowledge of their packet formats. This
|
||||
option is useful for determining which router along a path may be
|
||||
blocking packets based on IP protocol number. But see BUGS below.
|
||||
.It Fl p Ar port
|
||||
Protocol specific. For UDP and TCP, sets
|
||||
Protocol specific. For UDP, UDP-Lite, TCP and SCTP, sets
|
||||
the base
|
||||
.Ar port
|
||||
number used in probes (default is 33434).
|
||||
Traceroute hopes that nothing is listening on UDP ports
|
||||
.Em base
|
||||
Traceroute hopes that nothing is listening on UDP ports (or UDP-Lite ports
|
||||
if used by
|
||||
.Nm
|
||||
and supported by the peer)
|
||||
.Em base + 1
|
||||
to
|
||||
.Em base + nhops * nprobes - 1
|
||||
.Em base + nhops * nprobes
|
||||
at the destination host (so an ICMP PORT_UNREACHABLE message will
|
||||
be returned to terminate the route tracing). If something is
|
||||
listening on a port in the default range, this option can be used
|
||||
|
@ -219,6 +219,7 @@ static const char rcsid[] =
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/ip_var.h>
|
||||
#include <netinet/ip_icmp.h>
|
||||
#include <netinet/sctp.h>
|
||||
#include <netinet/udp.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <netinet/tcpip.h>
|
||||
@ -367,9 +368,10 @@ void freehostinfo(struct hostinfo *);
|
||||
void getaddr(u_int32_t *, char *);
|
||||
struct hostinfo *gethostinfo(char *);
|
||||
u_short in_cksum(u_short *, int);
|
||||
u_int32_t sctp_crc32c(const void *, u_int32_t);
|
||||
char *inetname(struct in_addr);
|
||||
int main(int, char **);
|
||||
u_short p_cksum(struct ip *, u_short *, int);
|
||||
u_short p_cksum(struct ip *, u_short *, int, int);
|
||||
int packet_ok(u_char *, int, struct sockaddr_in *, int);
|
||||
char *pr_type(u_char);
|
||||
void print(u_char *, int, struct sockaddr_in *);
|
||||
@ -389,8 +391,12 @@ int usleep(u_int);
|
||||
|
||||
void udp_prep(struct outdata *);
|
||||
int udp_check(const u_char *, int);
|
||||
void udplite_prep(struct outdata *);
|
||||
int udplite_check(const u_char *, int);
|
||||
void tcp_prep(struct outdata *);
|
||||
int tcp_check(const u_char *, int);
|
||||
void sctp_prep(struct outdata *);
|
||||
int sctp_check(const u_char *, int);
|
||||
void gre_prep(struct outdata *);
|
||||
int gre_check(const u_char *, int);
|
||||
void gen_prep(struct outdata *);
|
||||
@ -423,6 +429,15 @@ struct outproto protos[] = {
|
||||
udp_prep,
|
||||
udp_check
|
||||
},
|
||||
{
|
||||
"udplite",
|
||||
"spt dpt cov sum",
|
||||
IPPROTO_UDPLITE,
|
||||
sizeof(struct udphdr),
|
||||
32768 + 666,
|
||||
udplite_prep,
|
||||
udplite_check
|
||||
},
|
||||
{
|
||||
"tcp",
|
||||
"spt dpt seq ack xxflwin sum urp",
|
||||
@ -432,6 +447,15 @@ struct outproto protos[] = {
|
||||
tcp_prep,
|
||||
tcp_check
|
||||
},
|
||||
{
|
||||
"sctp",
|
||||
"spt dpt vtag crc tyfllen tyfllen ",
|
||||
IPPROTO_SCTP,
|
||||
sizeof(struct sctphdr),
|
||||
32768 + 666,
|
||||
sctp_prep,
|
||||
sctp_check
|
||||
},
|
||||
{
|
||||
"gre",
|
||||
"flg pro len clid",
|
||||
@ -452,7 +476,7 @@ struct outproto protos[] = {
|
||||
},
|
||||
{
|
||||
NULL,
|
||||
NULL,
|
||||
"",
|
||||
0,
|
||||
2 * sizeof(u_short),
|
||||
0,
|
||||
@ -541,12 +565,12 @@ main(int argc, char **argv)
|
||||
case 'a':
|
||||
as_path = 1;
|
||||
break;
|
||||
|
||||
|
||||
case 'A':
|
||||
as_path = 1;
|
||||
as_server = optarg;
|
||||
break;
|
||||
|
||||
|
||||
case 'd':
|
||||
options |= SO_DEBUG;
|
||||
break;
|
||||
@ -669,8 +693,11 @@ main(int argc, char **argv)
|
||||
|
||||
if (lsrr > 0)
|
||||
optlen = (lsrr + 1) * sizeof(gwlist[0]);
|
||||
minpacket = sizeof(*outip) + proto->hdrlen + sizeof(struct outdata) + optlen;
|
||||
packlen = minpacket; /* minimum sized packet */
|
||||
minpacket = sizeof(*outip) + proto->hdrlen + optlen;
|
||||
if (minpacket > 40)
|
||||
packlen = minpacket;
|
||||
else
|
||||
packlen = 40;
|
||||
|
||||
/* Process destination and optional packet size */
|
||||
switch (argc - optind) {
|
||||
@ -704,6 +731,11 @@ main(int argc, char **argv)
|
||||
#endif
|
||||
|
||||
protlen = packlen - sizeof(*outip) - optlen;
|
||||
if ((proto->num == IPPROTO_SCTP) && (packlen & 3)) {
|
||||
Fprintf(stderr, "%s: packet length must be a multiple of 4\n",
|
||||
prog);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
outip = (struct ip *)malloc((unsigned)packlen);
|
||||
if (outip == NULL) {
|
||||
@ -931,7 +963,7 @@ main(int argc, char **argv)
|
||||
as_path = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC)
|
||||
if (setpolicy(sndsock, "in bypass") < 0)
|
||||
errx(1, "%s", ipsec_strerror());
|
||||
@ -1330,7 +1362,7 @@ packet_ok(register u_char *buf, int cc, register struct sockaddr_in *from,
|
||||
hiplen = ((u_char *)icp + cc) - (u_char *)hip;
|
||||
hlen = hip->ip_hl << 2;
|
||||
inner = (u_char *)((u_char *)hip + hlen);
|
||||
if (hlen + 12 <= cc
|
||||
if (hlen + 16 <= cc
|
||||
&& hip->ip_p == proto->num
|
||||
&& (*proto->check)(inner, (u_char)seq))
|
||||
return (type == ICMP_TIMXCEED ? -1 : code + 1);
|
||||
@ -1343,8 +1375,8 @@ packet_ok(register u_char *buf, int cc, register struct sockaddr_in *from,
|
||||
Printf("\n%d bytes from %s to ", cc, inet_ntoa(from->sin_addr));
|
||||
Printf("%s: icmp type %d (%s) code %d\n",
|
||||
inet_ntoa(ip->ip_dst), type, pr_type(type), icp->icmp_code);
|
||||
for (i = 4; i < cc ; i += sizeof(*lp))
|
||||
Printf("%2d: x%8.8x\n", i, *lp++);
|
||||
for (i = 4; i <= cc - ICMP_MINLEN; i += sizeof(*lp))
|
||||
Printf("%2d: %8.8x\n", i, ntohl(*lp++));
|
||||
}
|
||||
#endif
|
||||
return(0);
|
||||
@ -1383,7 +1415,7 @@ udp_prep(struct outdata *outdata)
|
||||
outudp->uh_ulen = htons((u_short)protlen);
|
||||
outudp->uh_sum = 0;
|
||||
if (doipcksum) {
|
||||
u_short sum = p_cksum(outip, (u_short*)outudp, protlen);
|
||||
u_short sum = p_cksum(outip, (u_short*)outudp, protlen, protlen);
|
||||
outudp->uh_sum = (sum) ? sum : 0xffff;
|
||||
}
|
||||
|
||||
@ -1399,6 +1431,32 @@ udp_check(const u_char *data, int seq)
|
||||
ntohs(udp->uh_dport) == port + (fixedPort ? 0 : seq));
|
||||
}
|
||||
|
||||
void
|
||||
udplite_prep(struct outdata *outdata)
|
||||
{
|
||||
struct udphdr *const outudp = (struct udphdr *) outp;
|
||||
|
||||
outudp->uh_sport = htons(ident + (fixedPort ? outdata->seq : 0));
|
||||
outudp->uh_dport = htons(port + (fixedPort ? 0 : outdata->seq));
|
||||
outudp->uh_ulen = htons(8);
|
||||
outudp->uh_sum = 0;
|
||||
if (doipcksum) {
|
||||
u_short sum = p_cksum(outip, (u_short*)outudp, protlen, 8);
|
||||
outudp->uh_sum = (sum) ? sum : 0xffff;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int
|
||||
udplite_check(const u_char *data, int seq)
|
||||
{
|
||||
struct udphdr *const udp = (struct udphdr *) data;
|
||||
|
||||
return (ntohs(udp->uh_sport) == ident + (fixedPort ? seq : 0) &&
|
||||
ntohs(udp->uh_dport) == port + (fixedPort ? 0 : seq));
|
||||
}
|
||||
|
||||
void
|
||||
tcp_prep(struct outdata *outdata)
|
||||
{
|
||||
@ -1412,10 +1470,8 @@ tcp_prep(struct outdata *outdata)
|
||||
tcp->th_flags = TH_SYN;
|
||||
tcp->th_sum = 0;
|
||||
|
||||
if (doipcksum) {
|
||||
u_short sum = p_cksum(outip, (u_short*)tcp, protlen);
|
||||
tcp->th_sum = (sum) ? sum : 0xffff;
|
||||
}
|
||||
if (doipcksum)
|
||||
tcp->th_sum = p_cksum(outip, (u_short*)tcp, protlen, protlen);
|
||||
}
|
||||
|
||||
int
|
||||
@ -1428,6 +1484,47 @@ tcp_check(const u_char *data, int seq)
|
||||
&& tcp->th_seq == (tcp_seq)((tcp->th_sport << 16) | tcp->th_dport));
|
||||
}
|
||||
|
||||
void
|
||||
sctp_prep(struct outdata *outdata)
|
||||
{
|
||||
struct sctphdr *const sctp = (struct sctphdr *) outp;
|
||||
struct sctp_chunkhdr *chk;
|
||||
|
||||
sctp->src_port = htons(ident);
|
||||
sctp->dest_port = htons(port + (fixedPort ? 0 : outdata->seq));
|
||||
sctp->v_tag = (sctp->src_port << 16) | sctp->dest_port;
|
||||
sctp->checksum = htonl(0);
|
||||
if (protlen >=
|
||||
(int)(sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr))) {
|
||||
chk = (struct sctp_chunkhdr *)(sctp + 1);
|
||||
chk->chunk_type = SCTP_SHUTDOWN_ACK;
|
||||
chk->chunk_flags = 0;
|
||||
chk->chunk_length = htons(4);
|
||||
}
|
||||
if (protlen >=
|
||||
(int)(sizeof(struct sctphdr) + 2 * sizeof(struct sctp_chunkhdr))) {
|
||||
chk = chk + 1;
|
||||
chk->chunk_type = SCTP_PAD_CHUNK;
|
||||
chk->chunk_flags = 0;
|
||||
chk->chunk_length = htons(protlen -
|
||||
(sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr)));
|
||||
}
|
||||
if (doipcksum) {
|
||||
sctp->checksum = sctp_crc32c(sctp, protlen);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
sctp_check(const u_char *data, int seq)
|
||||
{
|
||||
struct sctphdr *const sctp = (struct sctphdr *) data;
|
||||
|
||||
return (ntohs(sctp->src_port) == ident
|
||||
&& ntohs(sctp->dest_port) == port + (fixedPort ? 0 : seq)
|
||||
&& sctp->v_tag ==
|
||||
(u_int32_t)((sctp->src_port << 16) | sctp->dest_port));
|
||||
}
|
||||
|
||||
void
|
||||
gre_prep(struct outdata *outdata)
|
||||
{
|
||||
@ -1494,8 +1591,8 @@ print(register u_char *buf, register int cc, register struct sockaddr_in *from)
|
||||
/*
|
||||
* Checksum routine for UDP and TCP headers.
|
||||
*/
|
||||
u_short
|
||||
p_cksum(struct ip *ip, u_short *data, int len)
|
||||
u_short
|
||||
p_cksum(struct ip *ip, u_short *data, int len, int cov)
|
||||
{
|
||||
static struct ipovly ipo;
|
||||
u_short sum[2];
|
||||
@ -1506,7 +1603,7 @@ p_cksum(struct ip *ip, u_short *data, int len)
|
||||
ipo.ih_dst = ip->ip_dst;
|
||||
|
||||
sum[1] = in_cksum((u_short*)&ipo, sizeof(ipo)); /* pseudo ip hdr cksum */
|
||||
sum[0] = in_cksum(data, len); /* payload data cksum */
|
||||
sum[0] = in_cksum(data, cov); /* payload data cksum */
|
||||
|
||||
return ~in_cksum(sum, sizeof(sum));
|
||||
}
|
||||
@ -1546,6 +1643,98 @@ in_cksum(register u_short *addr, register int len)
|
||||
return (answer);
|
||||
}
|
||||
|
||||
/*
|
||||
* CRC32C routine for the Stream Control Transmission Protocol
|
||||
*/
|
||||
|
||||
#define CRC32C(c, d) (c = (c>>8) ^ crc_c[(c^(d))&0xFF])
|
||||
|
||||
static u_int32_t crc_c[256] = {
|
||||
0x00000000, 0xF26B8303, 0xE13B70F7, 0x1350F3F4,
|
||||
0xC79A971F, 0x35F1141C, 0x26A1E7E8, 0xD4CA64EB,
|
||||
0x8AD958CF, 0x78B2DBCC, 0x6BE22838, 0x9989AB3B,
|
||||
0x4D43CFD0, 0xBF284CD3, 0xAC78BF27, 0x5E133C24,
|
||||
0x105EC76F, 0xE235446C, 0xF165B798, 0x030E349B,
|
||||
0xD7C45070, 0x25AFD373, 0x36FF2087, 0xC494A384,
|
||||
0x9A879FA0, 0x68EC1CA3, 0x7BBCEF57, 0x89D76C54,
|
||||
0x5D1D08BF, 0xAF768BBC, 0xBC267848, 0x4E4DFB4B,
|
||||
0x20BD8EDE, 0xD2D60DDD, 0xC186FE29, 0x33ED7D2A,
|
||||
0xE72719C1, 0x154C9AC2, 0x061C6936, 0xF477EA35,
|
||||
0xAA64D611, 0x580F5512, 0x4B5FA6E6, 0xB93425E5,
|
||||
0x6DFE410E, 0x9F95C20D, 0x8CC531F9, 0x7EAEB2FA,
|
||||
0x30E349B1, 0xC288CAB2, 0xD1D83946, 0x23B3BA45,
|
||||
0xF779DEAE, 0x05125DAD, 0x1642AE59, 0xE4292D5A,
|
||||
0xBA3A117E, 0x4851927D, 0x5B016189, 0xA96AE28A,
|
||||
0x7DA08661, 0x8FCB0562, 0x9C9BF696, 0x6EF07595,
|
||||
0x417B1DBC, 0xB3109EBF, 0xA0406D4B, 0x522BEE48,
|
||||
0x86E18AA3, 0x748A09A0, 0x67DAFA54, 0x95B17957,
|
||||
0xCBA24573, 0x39C9C670, 0x2A993584, 0xD8F2B687,
|
||||
0x0C38D26C, 0xFE53516F, 0xED03A29B, 0x1F682198,
|
||||
0x5125DAD3, 0xA34E59D0, 0xB01EAA24, 0x42752927,
|
||||
0x96BF4DCC, 0x64D4CECF, 0x77843D3B, 0x85EFBE38,
|
||||
0xDBFC821C, 0x2997011F, 0x3AC7F2EB, 0xC8AC71E8,
|
||||
0x1C661503, 0xEE0D9600, 0xFD5D65F4, 0x0F36E6F7,
|
||||
0x61C69362, 0x93AD1061, 0x80FDE395, 0x72966096,
|
||||
0xA65C047D, 0x5437877E, 0x4767748A, 0xB50CF789,
|
||||
0xEB1FCBAD, 0x197448AE, 0x0A24BB5A, 0xF84F3859,
|
||||
0x2C855CB2, 0xDEEEDFB1, 0xCDBE2C45, 0x3FD5AF46,
|
||||
0x7198540D, 0x83F3D70E, 0x90A324FA, 0x62C8A7F9,
|
||||
0xB602C312, 0x44694011, 0x5739B3E5, 0xA55230E6,
|
||||
0xFB410CC2, 0x092A8FC1, 0x1A7A7C35, 0xE811FF36,
|
||||
0x3CDB9BDD, 0xCEB018DE, 0xDDE0EB2A, 0x2F8B6829,
|
||||
0x82F63B78, 0x709DB87B, 0x63CD4B8F, 0x91A6C88C,
|
||||
0x456CAC67, 0xB7072F64, 0xA457DC90, 0x563C5F93,
|
||||
0x082F63B7, 0xFA44E0B4, 0xE9141340, 0x1B7F9043,
|
||||
0xCFB5F4A8, 0x3DDE77AB, 0x2E8E845F, 0xDCE5075C,
|
||||
0x92A8FC17, 0x60C37F14, 0x73938CE0, 0x81F80FE3,
|
||||
0x55326B08, 0xA759E80B, 0xB4091BFF, 0x466298FC,
|
||||
0x1871A4D8, 0xEA1A27DB, 0xF94AD42F, 0x0B21572C,
|
||||
0xDFEB33C7, 0x2D80B0C4, 0x3ED04330, 0xCCBBC033,
|
||||
0xA24BB5A6, 0x502036A5, 0x4370C551, 0xB11B4652,
|
||||
0x65D122B9, 0x97BAA1BA, 0x84EA524E, 0x7681D14D,
|
||||
0x2892ED69, 0xDAF96E6A, 0xC9A99D9E, 0x3BC21E9D,
|
||||
0xEF087A76, 0x1D63F975, 0x0E330A81, 0xFC588982,
|
||||
0xB21572C9, 0x407EF1CA, 0x532E023E, 0xA145813D,
|
||||
0x758FE5D6, 0x87E466D5, 0x94B49521, 0x66DF1622,
|
||||
0x38CC2A06, 0xCAA7A905, 0xD9F75AF1, 0x2B9CD9F2,
|
||||
0xFF56BD19, 0x0D3D3E1A, 0x1E6DCDEE, 0xEC064EED,
|
||||
0xC38D26C4, 0x31E6A5C7, 0x22B65633, 0xD0DDD530,
|
||||
0x0417B1DB, 0xF67C32D8, 0xE52CC12C, 0x1747422F,
|
||||
0x49547E0B, 0xBB3FFD08, 0xA86F0EFC, 0x5A048DFF,
|
||||
0x8ECEE914, 0x7CA56A17, 0x6FF599E3, 0x9D9E1AE0,
|
||||
0xD3D3E1AB, 0x21B862A8, 0x32E8915C, 0xC083125F,
|
||||
0x144976B4, 0xE622F5B7, 0xF5720643, 0x07198540,
|
||||
0x590AB964, 0xAB613A67, 0xB831C993, 0x4A5A4A90,
|
||||
0x9E902E7B, 0x6CFBAD78, 0x7FAB5E8C, 0x8DC0DD8F,
|
||||
0xE330A81A, 0x115B2B19, 0x020BD8ED, 0xF0605BEE,
|
||||
0x24AA3F05, 0xD6C1BC06, 0xC5914FF2, 0x37FACCF1,
|
||||
0x69E9F0D5, 0x9B8273D6, 0x88D28022, 0x7AB90321,
|
||||
0xAE7367CA, 0x5C18E4C9, 0x4F48173D, 0xBD23943E,
|
||||
0xF36E6F75, 0x0105EC76, 0x12551F82, 0xE03E9C81,
|
||||
0x34F4F86A, 0xC69F7B69, 0xD5CF889D, 0x27A40B9E,
|
||||
0x79B737BA, 0x8BDCB4B9, 0x988C474D, 0x6AE7C44E,
|
||||
0xBE2DA0A5, 0x4C4623A6, 0x5F16D052, 0xAD7D5351
|
||||
};
|
||||
|
||||
u_int32_t
|
||||
sctp_crc32c(const void *packet, u_int32_t len)
|
||||
{
|
||||
u_int32_t i, crc32c;
|
||||
u_int8_t byte0, byte1, byte2, byte3;
|
||||
const u_int8_t *buf = (const u_int8_t *)packet;
|
||||
|
||||
crc32c = ~0;
|
||||
for (i = 0; i < len; i++)
|
||||
CRC32C(crc32c, buf[i]);
|
||||
crc32c = ~crc32c;
|
||||
byte0 = crc32c & 0xff;
|
||||
byte1 = (crc32c>>8) & 0xff;
|
||||
byte2 = (crc32c>>16) & 0xff;
|
||||
byte3 = (crc32c>>24) & 0xff;
|
||||
crc32c = ((byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3);
|
||||
return htonl(crc32c);
|
||||
}
|
||||
|
||||
/*
|
||||
* Subtract 2 timeval structs: out = out - in.
|
||||
* Out is assumed to be within about LONG_MAX seconds of in.
|
||||
|
Loading…
Reference in New Issue
Block a user