traceroute_aux.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
/*
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* Copyright (c) 1988, 1989, 1991, 1994, 1995, 1996, 1997
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that: (1) source code distributions
* retain the above copyright notice and this paragraph in its entirety, (2)
* distributions including binary code include the above copyright notice and
* this paragraph in its entirety in the documentation or other materials
* provided with the distribution, and (3) all advertising materials mentioning
* features or use of this software display the following acknowledgement:
* ``This product includes software developed by the University of California,
* Lawrence Berkeley Laboratory and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
*
* @(#)$Header: traceroute.c,v 1.49 97/06/13 02:30:23 leres Exp $ (LBL)
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <strings.h>
#include <libintl.h>
#include <errno.h>
#include <netinet/in_systm.h>
#include <netdb.h>
#include <ifaddrlist.h>
#include "traceroute.h"
/*
* IPv4 source routing option.
* In order to avoid padding for the alignment of IPv4 addresses, ipsr_addrs
* is defined as a 2-D array of uint8_t, instead of 1-D array of struct in_addr.
*/
struct ip_sourceroute {
/* up to 9 IPv4 addresses */
};
extern char *inet_name(union any_in_addr *, int);
struct timeval *, int);
struct ip *set_buffers(int);
/*
* prepares the buffer to be sent as an IP datagram
*/
struct ip *
set_buffers(int plen)
{
int optlen = 0;
}
if (gw_count > 0) {
/* 8 = 5 (NO OPs) + 3 (code, len, ptr) */
}
if (settos)
/*
* LBNL bug fixed: missing '- optlen' before, causing optlen
* added twice
*
* BSD bug: BSD touches the header fields 'len' and 'ip_off'
* even when HDRINCL is set. It applies htons() on these
* fields. It should send the header untouched when HDRINCL
* is set.
*/
/* setup ICMP or UDP */
if (useicmp) {
/* LINTED E_BAD_PTR_CAST_ALIGN */
} else {
/* LINTED E_BAD_PTR_CAST_ALIGN */
}
return (outip);
}
/*
* Setup the source routing for IPv4.
*/
void
union any_in_addr *gwIPlist)
{
struct ip_sourceroute *srp;
int i;
}
/* final hop */
/*
* the option length passed to setsockopt() needs to be a multiple of
* 32 bits. Therefore we need to use a 1-byte padding (source routing
* information takes 4x+3 bytes).
*/
/* 3 = 1 (code) + 1 (len) + 1 (ptr) */
for (i = 0; i <= gw_count; i++) {
sizeof (struct in_addr));
}
}
}
/*
* send a probe packet to the destination
*/
void
{
int cc;
int optlen = 0;
int send_size;
/* initialize buffer pointers */
/* LINTED E_BAD_PTR_CAST_ALIGN */
/* LINTED E_BAD_PTR_CAST_ALIGN */
/* LINTED E_BAD_PTR_CAST_ALIGN */
if (gw_count > 0) {
/* 8 = 5 (NO OPs) + 3 (code, len, ptr) */
}
if (raw_req) {
} else if (useicmp) {
} else {
sizeof (struct udphdr);
}
/*
* If a raw IPv4 packet is going to be sent, the Time to Live
* field in the packet was initialized above. Otherwise, it is
* initialized here using the IPPROTO_IP level socket option.
*/
if (!raw_req) {
sizeof (ttl)) < 0) {
}
}
/*
* In most cases, the kernel will recalculate the ip checksum.
* But we must do it anyway so that the udp checksum comes out
* right.
*/
if (docksum) {
}
/* Payload */
if (useicmp) {
} else {
}
if (!raw_req)
/* LINTED E_BAD_PTR_CAST_ALIGN */
/* (We can only do the checksum if we know our ip address) */
if (docksum) {
if (useicmp) {
outicmp->icmp_cksum = 0;
if (outicmp->icmp_cksum == 0)
} else {
/* Checksum (must save and restore ip header) */
}
}
if (raw_req) {
sizeof (struct sockaddr_in));
} else if (useicmp) {
sizeof (struct sockaddr_in));
} else {
sizeof (struct sockaddr_in));
}
if (cc < 0) {
}
Printf("%s: wrote %s %d chars, ret=%d\n",
}
}
/*
* Check out the reply packet to see if it's what we were expecting.
* Returns REPLY_GOT_TARGET if the reply comes from the target
* REPLY_GOT_GATEWAY if an intermediate gateway sends TIME_EXCEEDED
* REPLY_GOT_OTHER for other kinds of unreachables indicating none of
* the above two cases
*
* It also sets the icmp type and icmp code values
*/
int
{
int hlen;
/* LINTED E_BAD_PTR_CAST_ALIGN */
if (verbose) {
Printf("packet too short (%d bytes) from %s\n",
}
return (REPLY_SHORT_PKT);
}
/* LINTED E_BAD_PTR_CAST_ALIGN */
/*
* traceroute interpretes only ICMP_TIMXCEED_INTRANS, ICMP_UNREACH and
* ICMP_ECHOREPLY, ignores others
*/
cc -= ICMP_MINLEN;
if (useicmp) {
if (*type == ICMP_ECHOREPLY &&
return (REPLY_GOT_TARGET);
/* LINTED E_BAD_PTR_CAST_ALIGN */
if (ICMP_MINLEN <= cc &&
return ((*type == ICMP_TIMXCEED) ?
}
} else {
/* LINTED E_BAD_PTR_CAST_ALIGN */
/*
* at least 4 bytes of UDP header is required for this
* check
*/
if (4 <= cc &&
(MAX_PORT + 1))) {
if (*type == ICMP_UNREACH &&
*code == ICMP_UNREACH_PORT) {
return (REPLY_GOT_TARGET);
} else if (*type == ICMP_TIMXCEED) {
return (REPLY_GOT_GATEWAY);
} else {
return (REPLY_GOT_OTHER);
}
}
}
}
if (verbose) {
int i, j;
Printf("%s: icmp type %d (%s) code %d\n",
for (i = 0; i < cc; i += 4) {
Printf("%2d: x", i);
for (j = 0; ((j < 4) && ((i + j) < cc)); j++)
(void) putchar('\n');
}
}
return (REPLY_SHORT_PKT);
}
/*
* convert an ICMP "type" field to a printable string.
*/
static char *
{
static struct icmptype_table ttab[] = {
{ICMP_ECHOREPLY, "Echo Reply"},
{1, "ICMP 1"},
{2, "ICMP 2"},
{ICMP_UNREACH, "Dest Unreachable"},
{ICMP_SOURCEQUENCH, "Source Quench"},
{ICMP_REDIRECT, "Redirect"},
{6, "ICMP 6"},
{7, "ICMP 7"},
{ICMP_ECHO, "Echo"},
{ICMP_ROUTERADVERT, "Router Advertisement"},
{ICMP_ROUTERSOLICIT, "Router Solicitation"},
{ICMP_TIMXCEED, "Time Exceeded"},
{ICMP_PARAMPROB, "Param Problem"},
{ICMP_TSTAMP, "Timestamp"},
{ICMP_TSTAMPREPLY, "Timestamp Reply"},
{ICMP_IREQ, "Info Request"},
{ICMP_IREQREPLY, "Info Reply"},
{ICMP_MASKREQ, "Netmask Request"},
{ICMP_MASKREPLY, "Netmask Reply"}
};
int i = 0;
}
return ("OUT-OF-RANGE");
}
/*
* print the IPv4 src address of the reply packet
*/
void
{
/* LINTED E_BAD_PTR_CAST_ALIGN */
union any_in_addr ip_addr;
/* LINTED E_BAD_PTR_CAST_ALIGN */
if (nflag) {
} else {
}
if (verbose)
}
/*
* ICMP messages which doesn't mean we got the target, or we got a gateway, are
* processed here. It returns _B_TRUE if it's some sort of 'unreachable'.
*/
{
/*
* this function only prints '!*' for ICMP unreachable messages,
* ignores others.
*/
if (type != ICMP_UNREACH) {
return (_B_FALSE);
}
switch (code) {
case ICMP_UNREACH_PORT:
break;
case ICMP_UNREACH_NET_UNKNOWN:
case ICMP_UNREACH_NET:
Printf(" !N");
break;
case ICMP_UNREACH_HOST:
Printf(" !H");
break;
case ICMP_UNREACH_PROTOCOL:
Printf(" !P");
break;
case ICMP_UNREACH_NEEDFRAG:
Printf(" !F");
break;
case ICMP_UNREACH_SRCFAIL:
Printf(" !S");
break;
case ICMP_UNREACH_NET_PROHIB:
case ICMP_UNREACH_HOST_PROHIB:
Printf(" !X");
break;
case ICMP_UNREACH_TOSNET:
case ICMP_UNREACH_TOSHOST:
Printf(" !T");
break;
case ICMP_UNREACH_ISOLATED:
Printf(" !U");
break;
default:
break;
}
return (unreach);
}