freebsd-dev/contrib/tcpdump/print-dccp.c

699 lines
18 KiB
C
Raw Normal View History

2006-09-04 20:04:42 +00:00
/*
* Copyright (C) Arnaldo Carvalho de Melo 2004
* Copyright (C) Ian McDonald 2005
* Copyright (C) Yoshifumi Nishida 2005
*
* This software may be distributed either under the terms of the
* BSD-style license that accompanies tcpdump or the GNU GPL version 2
*/
2017-01-31 19:17:06 +00:00
/* \summary: Datagram Congestion Control Protocol (DCCP) printer */
2006-09-04 20:04:42 +00:00
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
2017-01-31 19:17:06 +00:00
#include <netdissect-stdinc.h>
2006-09-04 20:04:42 +00:00
#include <stdio.h>
#include <string.h>
2017-01-31 19:17:06 +00:00
#include "netdissect.h"
2006-09-04 20:04:42 +00:00
#include "addrtoname.h"
2017-01-31 19:17:06 +00:00
#include "extract.h"
2006-09-04 20:04:42 +00:00
#include "ip.h"
#include "ip6.h"
#include "ipproto.h"
/* RFC4340: Datagram Congestion Control Protocol (DCCP) */
2015-01-06 19:03:11 +00:00
/**
* struct dccp_hdr - generic part of DCCP packet header, with a 24-bit
* sequence number
*
* @dccph_sport - Relevant port on the endpoint that sent this packet
* @dccph_dport - Relevant port on the other endpoint
* @dccph_doff - Data Offset from the start of the DCCP header, in 32-bit words
* @dccph_ccval - Used by the HC-Sender CCID
* @dccph_cscov - Parts of the packet that are covered by the Checksum field
* @dccph_checksum - Internet checksum, depends on dccph_cscov
* @dccph_x - 0 = 24 bit sequence number, 1 = 48
* @dccph_type - packet type, see DCCP_PKT_ prefixed macros
* @dccph_seq - 24-bit sequence number
*/
struct dccp_hdr {
uint16_t dccph_sport,
dccph_dport;
uint8_t dccph_doff;
uint8_t dccph_ccval_cscov;
uint16_t dccph_checksum;
uint8_t dccph_xtr;
uint8_t dccph_seq[3];
} UNALIGNED;
/**
* struct dccp_hdr_ext - generic part of DCCP packet header, with a 48-bit
* sequence number
*
* @dccph_sport - Relevant port on the endpoint that sent this packet
* @dccph_dport - Relevant port on the other endpoint
* @dccph_doff - Data Offset from the start of the DCCP header, in 32-bit words
* @dccph_ccval - Used by the HC-Sender CCID
* @dccph_cscov - Parts of the packet that are covered by the Checksum field
* @dccph_checksum - Internet checksum, depends on dccph_cscov
* @dccph_x - 0 = 24 bit sequence number, 1 = 48
* @dccph_type - packet type, see DCCP_PKT_ prefixed macros
* @dccph_seq - 48-bit sequence number
*/
struct dccp_hdr_ext {
uint16_t dccph_sport,
dccph_dport;
uint8_t dccph_doff;
uint8_t dccph_ccval_cscov;
uint16_t dccph_checksum;
uint8_t dccph_xtr;
uint8_t reserved;
uint8_t dccph_seq[6];
} UNALIGNED;
#define DCCPH_CCVAL(dh) (((dh)->dccph_ccval_cscov >> 4) & 0xF)
#define DCCPH_CSCOV(dh) (((dh)->dccph_ccval_cscov) & 0xF)
#define DCCPH_X(dh) ((dh)->dccph_xtr & 1)
#define DCCPH_TYPE(dh) (((dh)->dccph_xtr >> 1) & 0xF)
/**
* struct dccp_hdr_request - Conection initiation request header
*
* @dccph_req_service - Service to which the client app wants to connect
*/
struct dccp_hdr_request {
uint32_t dccph_req_service;
} UNALIGNED;
/**
* struct dccp_hdr_response - Conection initiation response header
*
* @dccph_resp_ack - 48 bit ack number, contains GSR
* @dccph_resp_service - Echoes the Service Code on a received DCCP-Request
*/
struct dccp_hdr_response {
uint8_t dccph_resp_ack[8]; /* always 8 bytes */
uint32_t dccph_resp_service;
} UNALIGNED;
/**
* struct dccp_hdr_reset - Unconditionally shut down a connection
*
* @dccph_resp_ack - 48 bit ack number
* @dccph_reset_service - Echoes the Service Code on a received DCCP-Request
*/
struct dccp_hdr_reset {
uint8_t dccph_reset_ack[8]; /* always 8 bytes */
uint8_t dccph_reset_code,
dccph_reset_data[3];
} UNALIGNED;
enum dccp_pkt_type {
DCCP_PKT_REQUEST = 0,
DCCP_PKT_RESPONSE,
DCCP_PKT_DATA,
DCCP_PKT_ACK,
DCCP_PKT_DATAACK,
DCCP_PKT_CLOSEREQ,
DCCP_PKT_CLOSE,
DCCP_PKT_RESET,
DCCP_PKT_SYNC,
DCCP_PKT_SYNCACK
};
static const struct tok dccp_pkt_type_str[] = {
{ DCCP_PKT_REQUEST, "DCCP-Request" },
{ DCCP_PKT_RESPONSE, "DCCP-Response" },
{ DCCP_PKT_DATA, "DCCP-Data" },
{ DCCP_PKT_ACK, "DCCP-Ack" },
{ DCCP_PKT_DATAACK, "DCCP-DataAck" },
{ DCCP_PKT_CLOSEREQ, "DCCP-CloseReq" },
{ DCCP_PKT_CLOSE, "DCCP-Close" },
{ DCCP_PKT_RESET, "DCCP-Reset" },
{ DCCP_PKT_SYNC, "DCCP-Sync" },
{ DCCP_PKT_SYNCACK, "DCCP-SyncAck" },
{ 0, NULL}
2015-01-06 19:03:11 +00:00
};
enum dccp_reset_codes {
DCCP_RESET_CODE_UNSPECIFIED = 0,
DCCP_RESET_CODE_CLOSED,
DCCP_RESET_CODE_ABORTED,
DCCP_RESET_CODE_NO_CONNECTION,
DCCP_RESET_CODE_PACKET_ERROR,
DCCP_RESET_CODE_OPTION_ERROR,
DCCP_RESET_CODE_MANDATORY_ERROR,
DCCP_RESET_CODE_CONNECTION_REFUSED,
DCCP_RESET_CODE_BAD_SERVICE_CODE,
DCCP_RESET_CODE_TOO_BUSY,
DCCP_RESET_CODE_BAD_INIT_COOKIE,
DCCP_RESET_CODE_AGGRESSION_PENALTY,
__DCCP_RESET_CODE_LAST
};
static const char tstr[] = "[|dccp]";
2006-09-04 20:04:42 +00:00
static const char *dccp_reset_codes[] = {
"unspecified",
"closed",
"aborted",
"no_connection",
"packet_error",
"option_error",
"mandatory_error",
"connection_refused",
"bad_service_code",
"too_busy",
"bad_init_cookie",
"aggression_penalty",
};
static const char *dccp_feature_nums[] = {
2015-01-06 19:03:11 +00:00
"reserved",
2006-09-04 20:04:42 +00:00
"ccid",
"allow_short_seqno",
"sequence_window",
2015-01-06 19:03:11 +00:00
"ecn_incapable",
"ack_ratio",
2006-09-04 20:04:42 +00:00
"send_ack_vector",
2015-01-06 19:03:11 +00:00
"send_ndp_count",
"minimum checksum coverage",
2006-09-04 20:04:42 +00:00
"check data checksum",
};
2012-05-14 08:01:48 +00:00
static inline u_int dccp_csum_coverage(const struct dccp_hdr* dh, u_int len)
2009-03-21 16:23:46 +00:00
{
u_int cov;
2015-01-06 19:03:11 +00:00
2009-03-21 16:23:46 +00:00
if (DCCPH_CSCOV(dh) == 0)
return len;
2015-01-06 19:03:11 +00:00
cov = (dh->dccph_doff + DCCPH_CSCOV(dh) - 1) * sizeof(uint32_t);
2009-03-21 16:23:46 +00:00
return (cov > len)? len : cov;
}
2015-01-06 19:03:11 +00:00
static int dccp_cksum(netdissect_options *ndo, const struct ip *ip,
2006-09-04 20:04:42 +00:00
const struct dccp_hdr *dh, u_int len)
{
2017-01-31 19:17:06 +00:00
return nextproto4_cksum(ndo, ip, (const uint8_t *)(const void *)dh, len,
2015-01-06 19:03:11 +00:00
dccp_csum_coverage(dh, len), IPPROTO_DCCP);
2006-09-04 20:04:42 +00:00
}
2017-01-31 19:17:06 +00:00
static int dccp6_cksum(netdissect_options *ndo, const struct ip6_hdr *ip6,
const struct dccp_hdr *dh, u_int len)
2006-09-04 20:04:42 +00:00
{
2017-01-31 19:17:06 +00:00
return nextproto6_cksum(ndo, ip6, (const uint8_t *)(const void *)dh, len,
2015-01-06 19:03:11 +00:00
dccp_csum_coverage(dh, len), IPPROTO_DCCP);
2006-09-04 20:04:42 +00:00
}
2015-01-06 19:03:11 +00:00
static const char *dccp_reset_code(uint8_t code)
2006-09-04 20:04:42 +00:00
{
if (code >= __DCCP_RESET_CODE_LAST)
return "invalid";
return dccp_reset_codes[code];
}
2015-01-06 19:03:11 +00:00
static uint64_t dccp_seqno(const u_char *bp)
2006-09-04 20:04:42 +00:00
{
2015-01-06 19:03:11 +00:00
const struct dccp_hdr *dh = (const struct dccp_hdr *)bp;
uint64_t seqno;
2006-09-04 20:04:42 +00:00
if (DCCPH_X(dh) != 0) {
2015-01-06 19:03:11 +00:00
const struct dccp_hdr_ext *dhx = (const struct dccp_hdr_ext *)bp;
seqno = EXTRACT_48BITS(dhx->dccph_seq);
} else {
seqno = EXTRACT_24BITS(dh->dccph_seq);
2006-09-04 20:04:42 +00:00
}
return seqno;
}
2007-10-16 02:20:42 +00:00
static inline unsigned int dccp_basic_hdr_len(const struct dccp_hdr *dh)
2006-09-04 20:04:42 +00:00
{
2015-01-06 19:03:11 +00:00
return DCCPH_X(dh) ? sizeof(struct dccp_hdr_ext) : sizeof(struct dccp_hdr);
2007-10-16 02:20:42 +00:00
}
2015-01-06 19:03:11 +00:00
static void dccp_print_ack_no(netdissect_options *ndo, const u_char *bp)
2007-10-16 02:20:42 +00:00
{
const struct dccp_hdr *dh = (const struct dccp_hdr *)bp;
2015-01-06 19:03:11 +00:00
const u_char *ackp = bp + dccp_basic_hdr_len(dh);
uint64_t ackno;
2006-09-04 20:04:42 +00:00
if (DCCPH_X(dh) != 0) {
2015-01-06 19:03:11 +00:00
ND_TCHECK2(*ackp, 8);
ackno = EXTRACT_48BITS(ackp + 2);
} else {
ND_TCHECK2(*ackp, 4);
ackno = EXTRACT_24BITS(ackp + 1);
2006-09-04 20:04:42 +00:00
}
2015-01-06 19:03:11 +00:00
ND_PRINT((ndo, "(ack=%" PRIu64 ") ", ackno));
2007-10-16 02:20:42 +00:00
trunc:
return;
2006-09-04 20:04:42 +00:00
}
2015-01-06 19:03:11 +00:00
static int dccp_print_option(netdissect_options *, const u_char *, u_int);
2006-09-04 20:04:42 +00:00
/**
* dccp_print - show dccp packet
* @bp - beginning of dccp packet
2015-01-06 19:03:11 +00:00
* @data2 - beginning of enclosing
2006-09-04 20:04:42 +00:00
* @len - lenght of ip packet
*/
2015-01-06 19:03:11 +00:00
void dccp_print(netdissect_options *ndo, const u_char *bp, const u_char *data2,
u_int len)
2006-09-04 20:04:42 +00:00
{
const struct dccp_hdr *dh;
const struct ip *ip;
const struct ip6_hdr *ip6;
const u_char *cp;
u_short sport, dport;
u_int hlen;
2015-01-06 19:03:11 +00:00
u_int fixed_hdrlen;
uint8_t dccph_type;
2006-09-04 20:04:42 +00:00
dh = (const struct dccp_hdr *)bp;
2017-01-31 19:17:06 +00:00
ip = (const struct ip *)data2;
2006-09-04 20:04:42 +00:00
if (IP_V(ip) == 6)
ip6 = (const struct ip6_hdr *)data2;
else
ip6 = NULL;
2015-01-06 19:03:11 +00:00
/* make sure we have enough data to look at the X bit */
2006-09-04 20:04:42 +00:00
cp = (const u_char *)(dh + 1);
2015-01-06 19:03:11 +00:00
if (cp > ndo->ndo_snapend) {
ND_PRINT((ndo, "[Invalid packet|dccp]"));
2006-09-04 20:04:42 +00:00
return;
}
if (len < sizeof(struct dccp_hdr)) {
2015-01-06 19:03:11 +00:00
ND_PRINT((ndo, "truncated-dccp - %u bytes missing!",
len - (u_int)sizeof(struct dccp_hdr)));
2006-09-04 20:04:42 +00:00
return;
}
2015-01-06 19:03:11 +00:00
/* get the length of the generic header */
fixed_hdrlen = dccp_basic_hdr_len(dh);
if (len < fixed_hdrlen) {
ND_PRINT((ndo, "truncated-dccp - %u bytes missing!",
len - fixed_hdrlen));
2015-01-06 19:03:11 +00:00
return;
}
ND_TCHECK2(*dh, fixed_hdrlen);
2006-09-04 20:04:42 +00:00
sport = EXTRACT_16BITS(&dh->dccph_sport);
dport = EXTRACT_16BITS(&dh->dccph_dport);
hlen = dh->dccph_doff * 4;
if (ip6) {
2015-01-06 19:03:11 +00:00
ND_PRINT((ndo, "%s.%d > %s.%d: ",
ip6addr_string(ndo, &ip6->ip6_src), sport,
ip6addr_string(ndo, &ip6->ip6_dst), dport));
2017-01-31 19:17:06 +00:00
} else {
2015-01-06 19:03:11 +00:00
ND_PRINT((ndo, "%s.%d > %s.%d: ",
ipaddr_string(ndo, &ip->ip_src), sport,
ipaddr_string(ndo, &ip->ip_dst), dport));
2006-09-04 20:04:42 +00:00
}
ND_PRINT((ndo, "DCCP"));
2015-01-06 19:03:11 +00:00
if (ndo->ndo_qflag) {
ND_PRINT((ndo, " %d", len - hlen));
2006-09-04 20:04:42 +00:00
if (hlen > len) {
ND_PRINT((ndo, " [bad hdr length %u - too long, > %u]",
hlen, len));
2006-09-04 20:04:42 +00:00
}
return;
}
/* other variables in generic header */
2015-01-06 19:03:11 +00:00
if (ndo->ndo_vflag) {
ND_PRINT((ndo, " (CCVal %d, CsCov %d, ", DCCPH_CCVAL(dh), DCCPH_CSCOV(dh)));
2006-09-04 20:04:42 +00:00
}
/* checksum calculation */
2015-01-06 19:03:11 +00:00
if (ndo->ndo_vflag && ND_TTEST2(bp[0], len)) {
uint16_t sum = 0, dccp_sum;
2006-09-04 20:04:42 +00:00
2009-03-21 16:23:46 +00:00
dccp_sum = EXTRACT_16BITS(&dh->dccph_checksum);
2015-01-06 19:03:11 +00:00
ND_PRINT((ndo, "cksum 0x%04x ", dccp_sum));
2009-03-21 16:23:46 +00:00
if (IP_V(ip) == 4)
2015-01-06 19:03:11 +00:00
sum = dccp_cksum(ndo, ip, dh, len);
2009-03-21 16:23:46 +00:00
else if (IP_V(ip) == 6)
2017-01-31 19:17:06 +00:00
sum = dccp6_cksum(ndo, ip6, dh, len);
2009-03-21 16:23:46 +00:00
if (sum != 0)
ND_PRINT((ndo, "(incorrect -> 0x%04x)",in_cksum_shouldbe(dccp_sum, sum)));
2009-03-21 16:23:46 +00:00
else
ND_PRINT((ndo, "(correct)"));
2006-09-04 20:04:42 +00:00
}
if (ndo->ndo_vflag)
ND_PRINT((ndo, ")"));
ND_PRINT((ndo, " "));
dccph_type = DCCPH_TYPE(dh);
switch (dccph_type) {
2006-09-04 20:04:42 +00:00
case DCCP_PKT_REQUEST: {
2017-01-31 19:17:06 +00:00
const struct dccp_hdr_request *dhr =
(const struct dccp_hdr_request *)(bp + fixed_hdrlen);
2015-01-06 19:03:11 +00:00
fixed_hdrlen += 4;
if (len < fixed_hdrlen) {
ND_PRINT((ndo, "truncated-%s - %u bytes missing!",
tok2str(dccp_pkt_type_str, "", dccph_type),
len - fixed_hdrlen));
2015-01-06 19:03:11 +00:00
return;
}
ND_TCHECK(*dhr);
ND_PRINT((ndo, "%s (service=%d) ",
tok2str(dccp_pkt_type_str, "", dccph_type),
EXTRACT_32BITS(&dhr->dccph_req_service)));
2006-09-04 20:04:42 +00:00
break;
}
case DCCP_PKT_RESPONSE: {
2017-01-31 19:17:06 +00:00
const struct dccp_hdr_response *dhr =
(const struct dccp_hdr_response *)(bp + fixed_hdrlen);
2015-01-06 19:03:11 +00:00
fixed_hdrlen += 12;
if (len < fixed_hdrlen) {
ND_PRINT((ndo, "truncated-%s - %u bytes missing!",
tok2str(dccp_pkt_type_str, "", dccph_type),
len - fixed_hdrlen));
2015-01-06 19:03:11 +00:00
return;
}
ND_TCHECK(*dhr);
ND_PRINT((ndo, "%s (service=%d) ",
tok2str(dccp_pkt_type_str, "", dccph_type),
EXTRACT_32BITS(&dhr->dccph_resp_service)));
2006-09-04 20:04:42 +00:00
break;
}
case DCCP_PKT_DATA:
ND_PRINT((ndo, "%s ", tok2str(dccp_pkt_type_str, "", dccph_type)));
2006-09-04 20:04:42 +00:00
break;
case DCCP_PKT_ACK: {
2015-01-06 19:03:11 +00:00
fixed_hdrlen += 8;
if (len < fixed_hdrlen) {
ND_PRINT((ndo, "truncated-%s - %u bytes missing!",
tok2str(dccp_pkt_type_str, "", dccph_type),
len - fixed_hdrlen));
2015-01-06 19:03:11 +00:00
return;
}
ND_PRINT((ndo, "%s ", tok2str(dccp_pkt_type_str, "", dccph_type)));
2006-09-04 20:04:42 +00:00
break;
}
case DCCP_PKT_DATAACK: {
2015-01-06 19:03:11 +00:00
fixed_hdrlen += 8;
if (len < fixed_hdrlen) {
ND_PRINT((ndo, "truncated-%s - %u bytes missing!",
tok2str(dccp_pkt_type_str, "", dccph_type),
len - fixed_hdrlen));
2015-01-06 19:03:11 +00:00
return;
}
ND_PRINT((ndo, "%s ", tok2str(dccp_pkt_type_str, "", dccph_type)));
2006-09-04 20:04:42 +00:00
break;
}
case DCCP_PKT_CLOSEREQ:
2015-01-06 19:03:11 +00:00
fixed_hdrlen += 8;
if (len < fixed_hdrlen) {
ND_PRINT((ndo, "truncated-%s - %u bytes missing!",
tok2str(dccp_pkt_type_str, "", dccph_type),
len - fixed_hdrlen));
2015-01-06 19:03:11 +00:00
return;
}
ND_PRINT((ndo, "%s ", tok2str(dccp_pkt_type_str, "", dccph_type)));
2006-09-04 20:04:42 +00:00
break;
case DCCP_PKT_CLOSE:
2015-01-06 19:03:11 +00:00
fixed_hdrlen += 8;
if (len < fixed_hdrlen) {
ND_PRINT((ndo, "truncated-%s - %u bytes missing!",
tok2str(dccp_pkt_type_str, "", dccph_type),
len - fixed_hdrlen));
2015-01-06 19:03:11 +00:00
return;
}
ND_PRINT((ndo, "%s ", tok2str(dccp_pkt_type_str, "", dccph_type)));
2006-09-04 20:04:42 +00:00
break;
case DCCP_PKT_RESET: {
2017-01-31 19:17:06 +00:00
const struct dccp_hdr_reset *dhr =
(const struct dccp_hdr_reset *)(bp + fixed_hdrlen);
2015-01-06 19:03:11 +00:00
fixed_hdrlen += 12;
if (len < fixed_hdrlen) {
ND_PRINT((ndo, "truncated-%s - %u bytes missing!",
tok2str(dccp_pkt_type_str, "", dccph_type),
len - fixed_hdrlen));
2015-01-06 19:03:11 +00:00
return;
}
ND_TCHECK(*dhr);
ND_PRINT((ndo, "%s (code=%s) ",
tok2str(dccp_pkt_type_str, "", dccph_type),
dccp_reset_code(dhr->dccph_reset_code)));
2006-09-04 20:04:42 +00:00
break;
}
case DCCP_PKT_SYNC:
2015-01-06 19:03:11 +00:00
fixed_hdrlen += 8;
if (len < fixed_hdrlen) {
ND_PRINT((ndo, "truncated-%s - %u bytes missing!",
tok2str(dccp_pkt_type_str, "", dccph_type),
len - fixed_hdrlen));
2015-01-06 19:03:11 +00:00
return;
}
ND_PRINT((ndo, "%s ", tok2str(dccp_pkt_type_str, "", dccph_type)));
2006-09-04 20:04:42 +00:00
break;
case DCCP_PKT_SYNCACK:
2015-01-06 19:03:11 +00:00
fixed_hdrlen += 8;
if (len < fixed_hdrlen) {
ND_PRINT((ndo, "truncated-%s - %u bytes missing!",
tok2str(dccp_pkt_type_str, "", dccph_type),
len - fixed_hdrlen));
2015-01-06 19:03:11 +00:00
return;
}
ND_PRINT((ndo, "%s ", tok2str(dccp_pkt_type_str, "", dccph_type)));
2006-09-04 20:04:42 +00:00
break;
default:
ND_PRINT((ndo, "%s ", tok2str(dccp_pkt_type_str, "unknown-type-%u", dccph_type)));
2006-09-04 20:04:42 +00:00
break;
}
2015-01-06 19:03:11 +00:00
if ((DCCPH_TYPE(dh) != DCCP_PKT_DATA) &&
2007-10-16 02:20:42 +00:00
(DCCPH_TYPE(dh) != DCCP_PKT_REQUEST))
2015-01-06 19:03:11 +00:00
dccp_print_ack_no(ndo, bp);
2007-10-16 02:20:42 +00:00
2015-01-06 19:03:11 +00:00
if (ndo->ndo_vflag < 2)
2006-09-04 20:04:42 +00:00
return;
2015-01-06 19:03:11 +00:00
ND_PRINT((ndo, "seq %" PRIu64, dccp_seqno(bp)));
2006-09-04 20:04:42 +00:00
/* process options */
2015-01-06 19:03:11 +00:00
if (hlen > fixed_hdrlen){
2006-09-04 20:04:42 +00:00
u_int optlen;
2015-01-06 19:03:11 +00:00
cp = bp + fixed_hdrlen;
ND_PRINT((ndo, " <"));
2006-09-04 20:04:42 +00:00
2015-01-06 19:03:11 +00:00
hlen -= fixed_hdrlen;
2006-09-04 20:04:42 +00:00
while(1){
2015-01-06 19:03:11 +00:00
optlen = dccp_print_option(ndo, cp, hlen);
if (!optlen)
break;
if (hlen <= optlen)
break;
2006-09-04 20:04:42 +00:00
hlen -= optlen;
cp += optlen;
2015-01-06 19:03:11 +00:00
ND_PRINT((ndo, ", "));
2006-09-04 20:04:42 +00:00
}
2015-01-06 19:03:11 +00:00
ND_PRINT((ndo, ">"));
2006-09-04 20:04:42 +00:00
}
return;
trunc:
2015-01-06 19:03:11 +00:00
ND_PRINT((ndo, "%s", tstr));
2006-09-04 20:04:42 +00:00
return;
}
2015-01-06 19:03:11 +00:00
static const struct tok dccp_option_values[] = {
{ 0, "nop" },
{ 1, "mandatory" },
{ 2, "slowreceiver" },
{ 32, "change_l" },
{ 33, "confirm_l" },
{ 34, "change_r" },
{ 35, "confirm_r" },
{ 36, "initcookie" },
{ 37, "ndp_count" },
{ 38, "ack_vector0" },
{ 39, "ack_vector1" },
{ 40, "data_dropped" },
{ 41, "timestamp" },
{ 42, "timestamp_echo" },
{ 43, "elapsed_time" },
{ 44, "data_checksum" },
{ 0, NULL }
2015-01-06 19:03:11 +00:00
};
2019-10-06 04:36:53 +00:00
static int
dccp_print_option(netdissect_options *ndo, const u_char *option, u_int hlen)
2015-01-06 19:03:11 +00:00
{
uint8_t optlen, i;
2006-09-04 20:04:42 +00:00
2015-01-06 19:03:11 +00:00
ND_TCHECK(*option);
2006-09-04 20:04:42 +00:00
if (*option >= 32) {
2015-01-06 19:03:11 +00:00
ND_TCHECK(*(option+1));
2006-09-04 20:04:42 +00:00
optlen = *(option +1);
if (optlen < 2) {
2015-01-06 19:03:11 +00:00
if (*option >= 128)
ND_PRINT((ndo, "CCID option %u optlen too short", *option));
else
ND_PRINT((ndo, "%s optlen too short",
tok2str(dccp_option_values, "Option %u", *option)));
2015-01-06 19:03:11 +00:00
return 0;
2006-09-04 20:04:42 +00:00
}
2015-01-06 19:03:11 +00:00
} else
optlen = 1;
if (hlen < optlen) {
if (*option >= 128)
ND_PRINT((ndo, "CCID option %u optlen goes past header length",
*option));
Update tcpdump to 4.1.1. Changes: Thu. April 1, 2010. guy@alum.mit.edu. Summary for 4.1.1 tcpdump release Fix build on systems with PF, such as FreeBSD and OpenBSD. Don't blow up if a zero-length link-layer address is passed to linkaddr_string(). Thu. March 11, 2010. ken@netfunctional.ca/guy@alum.mit.edu. Summary for 4.1.0 tcpdump release Fix printing of MAC addresses for VLAN frames with a length field Add some additional bounds checks and use the EXTRACT_ macros more Add a -b flag to print the AS number in BGP packets in ASDOT notation rather than ASPLAIN notation Add ICMPv6 RFC 5006 support Decode the access flags in NFS access requests Handle the new DLT_ for memory-mapped USB captures on Linux Make the default snapshot (-s) the maximum Print name of device (when -L is used) Support for OpenSolaris (and SXCE build 125 and later) Print new TCP flags Add support for RPL DIO Add support for TCP User Timeout (UTO) Add support for non-standard Ethertypes used by 3com PPPoE gear Add support for 802.11n and 802.11s Add support for Transparent Ethernet Bridge ethertype in GRE Add 4 byte AS support for BGP printer Add support for the MDT SAFI 66 BG printer Add basic IPv6 support to print-olsr Add USB printer Add printer for ForCES Handle frames with an FCS Handle 802.11n Control Wrapper, Block Acq Req and Block Ack frames Fix TCP sequence number printing Report 802.2 packets as 802.2 instead of 802.3 Don't include -L/usr/lib in LDFLAGS On x86_64 Linux, look in lib64 directory too Lots of code clean ups Autoconf clean ups Update testcases to make output changes Fix compiling with/out smi (--with{,out}-smi) Fix compiling without IPv6 support (--disable-ipv6)
2010-10-28 16:23:25 +00:00
else
2015-01-06 19:03:11 +00:00
ND_PRINT((ndo, "%s optlen goes past header length",
tok2str(dccp_option_values, "Option %u", *option)));
2015-01-06 19:03:11 +00:00
return 0;
}
ND_TCHECK2(*option, optlen);
if (*option >= 128) {
ND_PRINT((ndo, "CCID option %d", *option));
switch (optlen) {
case 4:
ND_PRINT((ndo, " %u", EXTRACT_16BITS(option + 2)));
break;
case 6:
ND_PRINT((ndo, " %u", EXTRACT_32BITS(option + 2)));
break;
default:
break;
}
} else {
ND_PRINT((ndo, "%s", tok2str(dccp_option_values, "Option %u", *option)));
switch (*option) {
case 32:
case 33:
case 34:
case 35:
if (optlen < 3) {
ND_PRINT((ndo, " optlen too short"));
return optlen;
}
if (*(option + 2) < 10){
ND_PRINT((ndo, " %s", dccp_feature_nums[*(option + 2)]));
for (i = 0; i < optlen - 3; i++)
ND_PRINT((ndo, " %d", *(option + 3 + i)));
}
break;
case 36:
if (optlen > 2) {
ND_PRINT((ndo, " 0x"));
for (i = 0; i < optlen - 2; i++)
ND_PRINT((ndo, "%02x", *(option + 2 + i)));
}
break;
case 37:
for (i = 0; i < optlen - 2; i++)
ND_PRINT((ndo, " %d", *(option + 2 + i)));
break;
case 38:
if (optlen > 2) {
ND_PRINT((ndo, " 0x"));
for (i = 0; i < optlen - 2; i++)
ND_PRINT((ndo, "%02x", *(option + 2 + i)));
}
break;
case 39:
if (optlen > 2) {
ND_PRINT((ndo, " 0x"));
for (i = 0; i < optlen - 2; i++)
ND_PRINT((ndo, "%02x", *(option + 2 + i)));
}
break;
case 40:
if (optlen > 2) {
ND_PRINT((ndo, " 0x"));
for (i = 0; i < optlen - 2; i++)
ND_PRINT((ndo, "%02x", *(option + 2 + i)));
}
break;
case 41:
2019-10-06 04:36:53 +00:00
/*
* 13.1. Timestamp Option
*
* +--------+--------+--------+--------+--------+--------+
* |00101001|00000110| Timestamp Value |
* +--------+--------+--------+--------+--------+--------+
* Type=41 Length=6
*/
if (optlen == 6)
2015-01-06 19:03:11 +00:00
ND_PRINT((ndo, " %u", EXTRACT_32BITS(option + 2)));
else
2019-10-06 04:36:53 +00:00
ND_PRINT((ndo, " [optlen != 6]"));
2015-01-06 19:03:11 +00:00
break;
case 42:
2019-10-06 04:36:53 +00:00
/*
* 13.3. Timestamp Echo Option
*
* +--------+--------+--------+--------+--------+--------+
* |00101010|00000110| Timestamp Echo |
* +--------+--------+--------+--------+--------+--------+
* Type=42 Len=6
*
* +--------+--------+------- ... -------+--------+--------+
* |00101010|00001000| Timestamp Echo | Elapsed Time |
* +--------+--------+------- ... -------+--------+--------+
* Type=42 Len=8 (4 bytes)
*
* +--------+--------+------- ... -------+------- ... -------+
* |00101010|00001010| Timestamp Echo | Elapsed Time |
* +--------+--------+------- ... -------+------- ... -------+
* Type=42 Len=10 (4 bytes) (4 bytes)
*/
switch (optlen) {
case 6:
2015-01-06 19:03:11 +00:00
ND_PRINT((ndo, " %u", EXTRACT_32BITS(option + 2)));
2019-10-06 04:36:53 +00:00
break;
case 8:
ND_PRINT((ndo, " %u", EXTRACT_32BITS(option + 2)));
ND_PRINT((ndo, " (elapsed time %u)", EXTRACT_16BITS(option + 6)));
break;
case 10:
ND_PRINT((ndo, " %u", EXTRACT_32BITS(option + 2)));
ND_PRINT((ndo, " (elapsed time %u)", EXTRACT_32BITS(option + 6)));
break;
default:
ND_PRINT((ndo, " [optlen != 6 or 8 or 10]"));
break;
}
2015-01-06 19:03:11 +00:00
break;
case 43:
if (optlen == 6)
ND_PRINT((ndo, " %u", EXTRACT_32BITS(option + 2)));
else if (optlen == 4)
ND_PRINT((ndo, " %u", EXTRACT_16BITS(option + 2)));
else
2019-10-06 04:36:53 +00:00
ND_PRINT((ndo, " [optlen != 4 or 6]"));
2015-01-06 19:03:11 +00:00
break;
case 44:
if (optlen > 2) {
ND_PRINT((ndo, " "));
for (i = 0; i < optlen - 2; i++)
ND_PRINT((ndo, "%02x", *(option + 2 + i)));
2006-09-04 20:04:42 +00:00
}
break;
}
}
return optlen;
trunc:
2015-01-06 19:03:11 +00:00
ND_PRINT((ndo, "%s", tstr));
2006-09-04 20:04:42 +00:00
return 0;
}