/*
* Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 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.
*/
/*
* print the recorded route in an IP RR, LSRR or SSRR option.
*/
static int
ip_printroute(netdissect_options *ndo,
const u_char *cp, u_int length)
{
u_int ptr;
u_int len;
for (len = 3; len < length; len += 4) {
ND_TCHECK_4(cp + len); /* Needed to print the IP addresses */
ND_PRINT(" %s", GET_IPADDR_STRING(cp + len));
if (ptr > len)
ND_PRINT(",");
}
return (0);
trunc:
return (-1);
}
/*
* If source-routing is present and valid, return the final destination.
* Otherwise, return IP destination.
*
* This is used for UDP and TCP pseudo-header in the checksum
* calculation.
*/
static uint32_t
ip_finddst(netdissect_options *ndo,
const struct ip *ip)
{
u_int length;
u_int len;
const u_char *cp;
len = GET_BE_U_2(ip->ip_len);
if (len > length) {
ND_PRINT("[total length %u > length %u]", len, length);
nd_print_invalid(ndo);
ND_PRINT(" ");
}
if (len == 0) {
/* we guess that it is a TSO send */
len = length;
presumed_tso = 1;
} else
ND_ICHECKMSG_U("total length", len, <, hlen);
ND_TCHECK_SIZE(ip);
/*
* Cut off the snapshot length to the end of the IP payload.
*/
if (!nd_push_snaplen(ndo, bp, len)) {
(*ndo->ndo_error)(ndo, S_ERR_ND_MEM_ALLOC,
"%s: can't push snaplen on buffer stack", __func__);
}
/*
* for the firewall guys, print id, offset.
* On all but the last stick a "+" in the flags portion.
* For unfragmented datagrams, note the don't fragment flag.
*/
ND_PRINT(", id %u, offset %u, flags [%s], proto %s (%u)",
GET_BE_U_2(ip->ip_id),
(off & IP_OFFMASK) * 8,
bittok2str(ip_frag_values, "none", off & (IP_RES|IP_DF|IP_MF)),
tok2str(ipproto_values, "unknown", ip_proto),
ip_proto);
/*
* If this is fragment zero, hand it to the next higher
* level protocol. Let them know whether there are more
* fragments.
*/
if ((off & IP_OFFMASK) == 0) {
uint8_t nh = GET_U_1(ip->ip_p);
if (nh != IPPROTO_TCP && nh != IPPROTO_UDP &&
nh != IPPROTO_SCTP && nh != IPPROTO_DCCP) {
ND_PRINT("%s > %s: ",
GET_IPADDR_STRING(ip->ip_src),
GET_IPADDR_STRING(ip->ip_dst));
}
/*
* Do a bounds check before calling ip_demux_print().
* At least the header data is required.
*/
if (!ND_TTEST_LEN((const u_char *)ip, hlen)) {
ND_PRINT(" [remaining caplen(%u) < header length(%u)]",
ND_BYTES_AVAILABLE_AFTER((const u_char *)ip),
hlen);
nd_trunc_longjmp(ndo);
}
ip_demux_print(ndo, (const u_char *)ip + hlen, len, 4,
off & IP_MF, GET_U_1(ip->ip_ttl), nh, bp);
} else {
/*
* Ultra quiet now means that all this stuff should be
* suppressed.
*/
if (ndo->ndo_qflag > 1) {
nd_pop_packet_info(ndo);
return;
}
/*
* This isn't the first frag, so we're missing the
* next level protocol header. print the ip addr
* and the protocol.
*/
ND_PRINT("%s > %s:", GET_IPADDR_STRING(ip->ip_src),
GET_IPADDR_STRING(ip->ip_dst));
if (!ndo->ndo_nflag && (p_name = netdb_protoname(ip_proto)) != NULL)
ND_PRINT(" %s", p_name);
else
ND_PRINT(" ip-proto-%u", ip_proto);
}
nd_pop_packet_info(ndo);
return;