/* \summary: IP printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
-#include <string.h>
-
#include "netdissect.h"
#include "addrtoname.h"
#include "extract.h"
}
if ((length + 1) & 3)
ND_PRINT(" [bad length %u]", length);
- ND_TCHECK_1(cp + 2);
ptr = GET_U_1(cp + 2) - 1;
if (ptr < 3 || ((ptr + 1) & 3) || ptr > length + 1)
ND_PRINT(" [bad ptr %u]", GET_U_1(cp + 2));
for (len = 3; len < length; len += 4) {
- ND_TCHECK_4(cp + len);
- ND_PRINT(" %s", ipaddr_string(ndo, cp + len));
+ ND_TCHECK_4(cp + len); /* Needed to print the IP addresses */
+ ND_PRINT(" %s", GET_IPADDR_STRING(cp + len));
if (ptr > len)
ND_PRINT(",");
}
for (; length != 0; cp += len, length -= len) {
int tt;
- ND_TCHECK_1(cp);
tt = GET_U_1(cp);
if (tt == IPOPT_EOL)
break;
else if (tt == IPOPT_NOP)
len = 1;
else {
- ND_TCHECK_1(cp + 1);
len = GET_U_1(cp + 1);
if (len < 2)
break;
return (0);
}
ND_PRINT(" TS{");
- ND_TCHECK_1(cp + 3);
hoplen = ((GET_U_1(cp + 3) & 0xF) != IPOPT_TS_TSONLY) ? 8 : 4;
if ((length - 4) & (hoplen-1))
ND_PRINT("[bad length %u]", length);
- ND_TCHECK_1(cp + 2);
ptr = GET_U_1(cp + 2) - 1;
len = 0;
if (ptr < 4 || ((ptr - 4) & (hoplen-1)) || ptr > length + 1)
ND_PRINT("[bad ptr %u]", GET_U_1(cp + 2));
- ND_TCHECK_1(cp + 3);
switch (GET_U_1(cp + 3)&0xF) {
case IPOPT_TS_TSONLY:
ND_PRINT("TSONLY");
case IPOPT_TS_TSANDADDR:
ND_PRINT("TS+ADDR");
break;
- /*
- * prespecified should really be 3, but some ones might send 2
- * instead, and the IPOPT_TS_PRESPEC constant can apparently
- * have both values, so we have to hard-code it here.
- */
-
- case 2:
- ND_PRINT("PRESPEC2.0");
- break;
- case 3: /* IPOPT_TS_PRESPEC */
+ case IPOPT_TS_PRESPEC:
ND_PRINT("PRESPEC");
break;
default:
type = " ^ ";
ND_TCHECK_LEN(cp + len, hoplen);
ND_PRINT("%s%u@%s", type, GET_BE_U_4(cp + len + hoplen - 4),
- hoplen!=8 ? "" : ipaddr_string(ndo, cp + len));
+ hoplen!=8 ? "" : GET_IPADDR_STRING(cp + len));
type = " ";
}
ND_PRINT("%s", sep);
sep = ",";
- ND_TCHECK_1(cp);
option_code = GET_U_1(cp);
ND_PRINT("%s",
option_len = 1;
else {
- ND_TCHECK_1(cp + 1);
option_len = GET_U_1(cp + 1);
if (option_len < 2) {
ND_PRINT(" [bad length %u]", option_len);
void
ip_print(netdissect_options *ndo,
const u_char *bp,
- u_int length)
+ const u_int length)
{
const struct ip *ip;
- const u_char *ipend;
u_int off;
u_int hlen;
u_int len;
uint16_t sum, ip_sum;
const char *p_name;
int truncated = 0;
+ int presumed_tso = 0;
ndo->ndo_protocol = "ip";
ip = (const struct ip *)bp;
- if (IP_V(ip) != 4) { /* print version and fail if != 4 */
- if (IP_V(ip) == 6)
- ND_PRINT("IP6, wrong link-layer encapsulation");
- else
- ND_PRINT("IP%u", IP_V(ip));
- nd_print_invalid(ndo);
- return;
- }
- if (!ndo->ndo_eflag)
- ND_PRINT("IP ");
- ND_TCHECK_SIZE(ip);
- if (length < sizeof (struct ip)) {
- ND_PRINT("truncated-ip %u", length);
- return;
+ if (!ndo->ndo_eflag) {
+ nd_print_protocol_caps(ndo);
+ ND_PRINT(" ");
}
+
+ ND_ICHECK_ZU(length, <, sizeof (struct ip));
+ ND_ICHECKMSG_U("version", IP_V(ip), !=, 4);
+
hlen = IP_HL(ip) * 4;
- if (hlen < sizeof (struct ip)) {
- ND_PRINT("bad-hlen %u", hlen);
- return;
- }
+ ND_ICHECKMSG_ZU("header length", hlen, <, sizeof (struct ip));
len = GET_BE_U_2(ip->ip_len);
- if (length < len)
- ND_PRINT("truncated-ip - %u bytes missing! ",
- len - length);
- if (len < hlen) {
-#ifdef GUESS_TSO
- if (len) {
- ND_PRINT("bad-len %u", len);
- return;
- }
- else {
- /* we guess that it is a TSO send */
- len = length;
- }
-#else
- ND_PRINT("bad-len %u", len);
- return;
-#endif /* GUESS_TSO */
+ 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.
+ * Cut off the snapshot length to the end of the IP payload
+ * or the end of the data in which it's contained, whichever
+ * comes first.
*/
- ipend = bp + len;
- if (ipend < ndo->ndo_snapend)
- ndo->ndo_snapend = ipend;
+ if (!nd_push_snaplen(ndo, bp, ND_MIN(length, len))) {
+ (*ndo->ndo_error)(ndo, S_ERR_ND_MEM_ALLOC,
+ "%s: can't push snaplen on buffer stack", __func__);
+ }
len -= hlen;
tok2str(ipproto_values, "unknown", ip_proto),
ip_proto);
- ND_PRINT(", length %u", GET_BE_U_2(ip->ip_len));
+ if (presumed_tso)
+ ND_PRINT(", length %u [was 0, presumed TSO]", length);
+ else
+ ND_PRINT(", length %u", GET_BE_U_2(ip->ip_len));
- if ((hlen - sizeof(struct ip)) > 0) {
+ if ((hlen > sizeof(struct ip))) {
ND_PRINT(", options (");
if (ip_optprint(ndo, (const u_char *)(ip + 1),
hlen - sizeof(struct ip)) == -1) {
ND_PRINT(")");
}
- if (!ndo->ndo_Kflag && (const u_char *)ip + hlen <= ndo->ndo_snapend) {
+ if (!ndo->ndo_Kflag && ND_TTEST_LEN((const u_char *)ip, hlen)) {
vec[0].ptr = (const uint8_t *)(const void *)ip;
vec[0].len = hlen;
sum = in_cksum(vec, 1);
ND_PRINT(")\n ");
if (truncated) {
ND_PRINT("%s > %s: ",
- ipaddr_string(ndo, ip->ip_src),
- ipaddr_string(ndo, ip->ip_dst));
- goto trunc;
+ GET_IPADDR_STRING(ip->ip_src),
+ GET_IPADDR_STRING(ip->ip_dst));
+ nd_print_trunc(ndo);
+ nd_pop_packet_info(ndo);
+ return;
}
}
if (nh != IPPROTO_TCP && nh != IPPROTO_UDP &&
nh != IPPROTO_SCTP && nh != IPPROTO_DCCP) {
ND_PRINT("%s > %s: ",
- ipaddr_string(ndo, ip->ip_src),
- ipaddr_string(ndo, ip->ip_dst));
+ 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_print_demux(ndo, (const u_char *)ip + hlen, len, 4,
- off & IP_MF, GET_U_1(ip->ip_ttl), nh, bp);
+ 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)
+ 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:", ipaddr_string(ndo, ip->ip_src),
- ipaddr_string(ndo, ip->ip_dst));
+ 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;
trunc:
nd_print_trunc(ndo);
return;
+
+invalid:
+ nd_print_invalid(ndo);
}
void
ipN_print(netdissect_options *ndo, const u_char *bp, u_int length)
{
- ndo->ndo_protocol = "ipN";
+ ndo->ndo_protocol = "ipn";
if (length < 1) {
ND_PRINT("truncated-ip %u", length);
return;
}
- ND_TCHECK_1(bp);
switch (GET_U_1(bp) & 0xF0) {
case 0x40:
ip_print(ndo, bp, length);
ND_PRINT("unknown ip %u", (GET_U_1(bp) & 0xF0) >> 4);
break;
}
- return;
-
-trunc:
- nd_print_trunc(ndo);
- return;
}