*
*/
+#ifndef lint
+static const char rcsid[] _U_ =
+ "@(#) $Header: /tcpdump/master/tcpdump/print-isakmp.c,v 1.51 2005-04-07 00:28:17 mcr Exp $ (LBL)";
+#endif
#ifdef HAVE_CONFIG_H
#include "config.h"
#include "addrtoname.h"
#include "extract.h" /* must come after interface.h */
-#ifndef lint
-static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-isakmp.c,v 1.37 2003-11-15 00:39:28 guy Exp $ (LBL)";
-#endif
#include "ip.h"
#ifdef INET6
#include "ip6.h"
#endif
static const u_char *isakmp_sa_print(const struct isakmp_gen *,
- const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
+ u_int, const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
static const u_char *isakmp_p_print(const struct isakmp_gen *,
- const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
+ u_int, const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
static const u_char *isakmp_t_print(const struct isakmp_gen *,
- const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
+ u_int, const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
static const u_char *isakmp_ke_print(const struct isakmp_gen *,
- const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
+ u_int, const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
static const u_char *isakmp_id_print(const struct isakmp_gen *,
- const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
+ u_int, const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
static const u_char *isakmp_cert_print(const struct isakmp_gen *,
- const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
+ u_int, const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
static const u_char *isakmp_cr_print(const struct isakmp_gen *,
- const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
+ u_int, const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
static const u_char *isakmp_sig_print(const struct isakmp_gen *,
- const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
+ u_int, const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
static const u_char *isakmp_hash_print(const struct isakmp_gen *,
- const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
+ u_int, const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
static const u_char *isakmp_nonce_print(const struct isakmp_gen *,
- const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
+ u_int, const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
static const u_char *isakmp_n_print(const struct isakmp_gen *,
- const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
+ u_int, const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
static const u_char *isakmp_d_print(const struct isakmp_gen *,
- const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
+ u_int, const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
static const u_char *isakmp_vid_print(const struct isakmp_gen *,
- const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
+ u_int, const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
static const u_char *isakmp_sub0_print(u_char, const struct isakmp_gen *,
const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
static const u_char *isakmp_sub_print(u_char, const struct isakmp_gen *,
};
/* isakmp->np */
-static const u_char *(*npfunc[])(const struct isakmp_gen *, const u_char *,
- u_int32_t, u_int32_t, u_int32_t, int) = {
+static const u_char *(*npfunc[])(const struct isakmp_gen *, u_int,
+ const u_char *, u_int32_t, u_int32_t, u_int32_t, int) = {
NULL,
isakmp_sa_print,
isakmp_p_print,
return 0;
}
-static void
+static int
rawprint(caddr_t loc, size_t len)
{
static u_char *p;
size_t i;
+ TCHECK2(*loc, len);
+
p = (u_char *)loc;
for (i = 0; i < len; i++)
printf("%02x", p[i] & 0xff);
+ return 1;
+trunc:
+ return 0;
}
struct attrmap {
}
static const u_char *
-isakmp_sa_print(const struct isakmp_gen *ext, const u_char *ep, u_int32_t phase,
- u_int32_t doi0 _U_, u_int32_t proto0, int depth)
+isakmp_sa_print(const struct isakmp_gen *ext,
+ u_int item_len _U_,
+ const u_char *ep, u_int32_t phase, u_int32_t doi0 _U_,
+ u_int32_t proto0, int depth)
{
const struct isakmp_pl_sa *p;
struct isakmp_pl_sa sa;
printf("%s:", NPSTR(ISAKMP_NPTYPE_SA));
p = (struct isakmp_pl_sa *)ext;
+ TCHECK(*p);
safememcpy(&sa, ext, sizeof(sa));
doi = ntohl(sa.doi);
sit = ntohl(sa.sit);
np = (u_char *)ext + sizeof(sa);
if (sit != 0x01) {
+ TCHECK2(*(ext + 1), sizeof(ident));
safememcpy(&ident, ext + 1, sizeof(ident));
printf(" ident=%u", (u_int32_t)ntohl(ident));
np += sizeof(ident);
}
ext = (struct isakmp_gen *)np;
+ TCHECK(*ext);
cp = isakmp_sub_print(ISAKMP_NPTYPE_P, ext, ep, phase, doi, proto0,
depth);
return cp;
+trunc:
+ printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_SA));
+ return NULL;
}
static const u_char *
-isakmp_p_print(const struct isakmp_gen *ext, const u_char *ep, u_int32_t phase,
- u_int32_t doi0, u_int32_t proto0 _U_, int depth)
+isakmp_p_print(const struct isakmp_gen *ext, u_int item_len _U_,
+ const u_char *ep, u_int32_t phase, u_int32_t doi0,
+ u_int32_t proto0 _U_, int depth)
{
const struct isakmp_pl_p *p;
struct isakmp_pl_p prop;
printf("%s:", NPSTR(ISAKMP_NPTYPE_P));
p = (struct isakmp_pl_p *)ext;
+ TCHECK(*p);
safememcpy(&prop, ext, sizeof(prop));
printf(" #%d protoid=%s transform=%d",
prop.p_no, PROTOIDSTR(prop.prot_id), prop.num_t);
if (prop.spi_size) {
printf(" spi=");
- rawprint((caddr_t)(p + 1), prop.spi_size);
+ if (!rawprint((caddr_t)(p + 1), prop.spi_size))
+ goto trunc;
}
ext = (struct isakmp_gen *)((u_char *)(p + 1) + prop.spi_size);
+ TCHECK(*ext);
cp = isakmp_sub_print(ISAKMP_NPTYPE_T, ext, ep, phase, doi0,
prop.prot_id, depth);
return cp;
+trunc:
+ printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_P));
+ return NULL;
}
static const char *isakmp_p_map[] = {
};
static const u_char *
-isakmp_t_print(const struct isakmp_gen *ext, const u_char *ep,
- u_int32_t phase _U_, u_int32_t doi _U_, u_int32_t proto,
- int depth _U_)
+isakmp_t_print(const struct isakmp_gen *ext, u_int item_len,
+ const u_char *ep, u_int32_t phase _U_, u_int32_t doi _U_,
+ u_int32_t proto, int depth _U_)
{
const struct isakmp_pl_t *p;
struct isakmp_pl_t t;
printf("%s:", NPSTR(ISAKMP_NPTYPE_T));
p = (struct isakmp_pl_t *)ext;
+ TCHECK(*p);
safememcpy(&t, ext, sizeof(t));
switch (proto) {
else
printf(" #%d id=%d ", t.t_no, t.t_id);
cp = (u_char *)(p + 1);
- ep2 = (u_char *)p + ntohs(t.h.len);
+ ep2 = (u_char *)p + item_len;
while (cp < ep && cp < ep2) {
if (map && nmap) {
cp = isakmp_attrmap_print(cp, (ep < ep2) ? ep : ep2,
if (ep < ep2)
printf("...");
return cp;
+trunc:
+ printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_T));
+ return NULL;
}
static const u_char *
-isakmp_ke_print(const struct isakmp_gen *ext, const u_char *ep _U_,
- u_int32_t phase _U_, u_int32_t doi _U_, u_int32_t proto _U_,
- int depth _U_)
+isakmp_ke_print(const struct isakmp_gen *ext, u_int item_len _U_,
+ const u_char *ep _U_, u_int32_t phase _U_, u_int32_t doi _U_,
+ u_int32_t proto _U_, int depth _U_)
{
struct isakmp_gen e;
printf("%s:", NPSTR(ISAKMP_NPTYPE_KE));
+ TCHECK(*ext);
safememcpy(&e, ext, sizeof(e));
printf(" key len=%d", ntohs(e.len) - 4);
if (2 < vflag && 4 < ntohs(e.len)) {
printf(" ");
- rawprint((caddr_t)(ext + 1), ntohs(e.len) - 4);
+ if (!rawprint((caddr_t)(ext + 1), ntohs(e.len) - 4))
+ goto trunc;
}
return (u_char *)ext + ntohs(e.len);
+trunc:
+ printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_KE));
+ return NULL;
}
static const u_char *
-isakmp_id_print(const struct isakmp_gen *ext, const u_char *ep _U_,
- u_int32_t phase, u_int32_t doi _U_, u_int32_t proto _U_,
- int depth _U_)
+isakmp_id_print(const struct isakmp_gen *ext, u_int item_len _U_,
+ const u_char *ep _U_, u_int32_t phase, u_int32_t doi _U_,
+ u_int32_t proto _U_, int depth _U_)
{
#define USE_IPSECDOI_IN_PHASE1 1
const struct isakmp_pl_id *p;
printf("%s:", NPSTR(ISAKMP_NPTYPE_ID));
p = (struct isakmp_pl_id *)ext;
+ TCHECK(*p);
safememcpy(&id, ext, sizeof(id));
- if (sizeof(*p) < id.h.len)
+ if (sizeof(*p) < item_len) {
data = (u_char *)(p + 1);
- else
+ len = item_len - sizeof(*p);
+ } else {
data = NULL;
- len = ntohs(id.h.len) - sizeof(*p);
+ len = 0;
+ }
#if 0 /*debug*/
printf(" [phase=%d doi=%d proto=%d]", phase, doi, proto);
struct protoent *pe;
p = (struct ipsecdoi_id *)ext;
+ TCHECK(*p);
safememcpy(&id, ext, sizeof(id));
printf(" idtype=%s", STR_OR_ID(id.type, ipsecidtypestr));
if (id.proto_id) {
printf(" port=%d", ntohs(id.port));
if (!len)
break;
+ if (data == NULL)
+ goto trunc;
+ TCHECK2(*data, len);
switch (id.type) {
case IPSECDOI_ID_IPV4_ADDR:
- printf(" len=%d %s", len, ipaddr_string(data));
+ if (len < 4)
+ printf(" len=%d [bad: < 4]", len);
+ else
+ printf(" len=%d %s", len, ipaddr_string(data));
len = 0;
break;
case IPSECDOI_ID_FQDN:
case IPSECDOI_ID_IPV4_ADDR_SUBNET:
{
const u_char *mask;
- mask = data + sizeof(struct in_addr);
- printf(" len=%d %s/%u.%u.%u.%u", len,
- ipaddr_string(data),
- mask[0], mask[1], mask[2], mask[3]);
+ if (len < 8)
+ printf(" len=%d [bad: < 8]", len);
+ else {
+ mask = data + sizeof(struct in_addr);
+ printf(" len=%d %s/%u.%u.%u.%u", len,
+ ipaddr_string(data),
+ mask[0], mask[1], mask[2], mask[3]);
+ }
len = 0;
break;
}
#ifdef INET6
case IPSECDOI_ID_IPV6_ADDR:
- printf(" len=%d %s", len, ip6addr_string(data));
+ if (len < 16)
+ printf(" len=%d [bad: < 16]", len);
+ else
+ printf(" len=%d %s", len, ip6addr_string(data));
len = 0;
break;
case IPSECDOI_ID_IPV6_ADDR_SUBNET:
{
const u_int32_t *mask;
- mask = (u_int32_t *)(data + sizeof(struct in6_addr));
- /*XXX*/
- printf(" len=%d %s/0x%08x%08x%08x%08x", len,
- ip6addr_string(data),
- mask[0], mask[1], mask[2], mask[3]);
+ if (len < 20)
+ printf(" len=%d [bad: < 20]", len);
+ else {
+ mask = (u_int32_t *)(data + sizeof(struct in6_addr));
+ /*XXX*/
+ printf(" len=%d %s/0x%08x%08x%08x%08x", len,
+ ip6addr_string(data),
+ mask[0], mask[1], mask[2], mask[3]);
+ }
len = 0;
break;
}
#endif /*INET6*/
case IPSECDOI_ID_IPV4_ADDR_RANGE:
- printf(" len=%d %s-%s", len, ipaddr_string(data),
- ipaddr_string(data + sizeof(struct in_addr)));
+ if (len < 8)
+ printf(" len=%d [bad: < 8]", len);
+ else {
+ printf(" len=%d %s-%s", len,
+ ipaddr_string(data),
+ ipaddr_string(data + sizeof(struct in_addr)));
+ }
len = 0;
break;
#ifdef INET6
case IPSECDOI_ID_IPV6_ADDR_RANGE:
- printf(" len=%d %s-%s", len, ip6addr_string(data),
- ip6addr_string(data + sizeof(struct in6_addr)));
+ if (len < 32)
+ printf(" len=%d [bad: < 32]", len);
+ else {
+ printf(" len=%d %s-%s", len,
+ ip6addr_string(data),
+ ip6addr_string(data + sizeof(struct in6_addr)));
+ }
len = 0;
break;
#endif /*INET6*/
printf(" len=%d", len);
if (2 < vflag) {
printf(" ");
- rawprint((caddr_t)data, len);
+ if (!rawprint((caddr_t)data, len))
+ goto trunc;
}
}
- return (u_char *)ext + ntohs(id.h.len);
+ return (u_char *)ext + item_len;
+trunc:
+ printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_ID));
+ return NULL;
}
static const u_char *
-isakmp_cert_print(const struct isakmp_gen *ext, const u_char *ep _U_,
- u_int32_t phase _U_, u_int32_t doi0 _U_, u_int32_t proto0 _U_,
- int depth _U_)
+isakmp_cert_print(const struct isakmp_gen *ext, u_int item_len _U_,
+ const u_char *ep _U_, u_int32_t phase _U_,
+ u_int32_t doi0 _U_,
+ u_int32_t proto0 _U_, int depth _U_)
{
const struct isakmp_pl_cert *p;
struct isakmp_pl_cert cert;
printf("%s:", NPSTR(ISAKMP_NPTYPE_CERT));
p = (struct isakmp_pl_cert *)ext;
+ TCHECK(*p);
safememcpy(&cert, ext, sizeof(cert));
- printf(" len=%d", ntohs(cert.h.len) - 4);
+ printf(" len=%d", item_len - 4);
printf(" type=%s", STR_OR_ID((cert.encode), certstr));
- if (2 < vflag && 4 < ntohs(cert.h.len)) {
+ if (2 < vflag && 4 < item_len) {
printf(" ");
- rawprint((caddr_t)(ext + 1), ntohs(cert.h.len) - 4);
+ if (!rawprint((caddr_t)(ext + 1), item_len - 4))
+ goto trunc;
}
- return (u_char *)ext + ntohs(cert.h.len);
+ return (u_char *)ext + item_len;
+trunc:
+ printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_CERT));
+ return NULL;
}
static const u_char *
-isakmp_cr_print(const struct isakmp_gen *ext, const u_char *ep _U_,
- u_int32_t phase _U_, u_int32_t doi0 _U_, u_int32_t proto0 _U_,
- int depth _U_)
+isakmp_cr_print(const struct isakmp_gen *ext, u_int item_len _U_,
+ const u_char *ep _U_, u_int32_t phase _U_, u_int32_t doi0 _U_,
+ u_int32_t proto0 _U_, int depth _U_)
{
const struct isakmp_pl_cert *p;
struct isakmp_pl_cert cert;
printf("%s:", NPSTR(ISAKMP_NPTYPE_CR));
p = (struct isakmp_pl_cert *)ext;
+ TCHECK(*p);
safememcpy(&cert, ext, sizeof(cert));
- printf(" len=%d", ntohs(cert.h.len) - 4);
+ printf(" len=%d", item_len - 4);
printf(" type=%s", STR_OR_ID((cert.encode), certstr));
- if (2 < vflag && 4 < ntohs(cert.h.len)) {
+ if (2 < vflag && 4 < item_len) {
printf(" ");
- rawprint((caddr_t)(ext + 1), ntohs(cert.h.len) - 4);
+ if (!rawprint((caddr_t)(ext + 1), item_len - 4))
+ goto trunc;
}
- return (u_char *)ext + ntohs(cert.h.len);
+ return (u_char *)ext + item_len;
+trunc:
+ printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_CR));
+ return NULL;
}
static const u_char *
-isakmp_hash_print(const struct isakmp_gen *ext, const u_char *ep _U_,
- u_int32_t phase _U_, u_int32_t doi _U_, u_int32_t proto _U_,
- int depth _U_)
+isakmp_hash_print(const struct isakmp_gen *ext, u_int item_len _U_,
+ const u_char *ep _U_, u_int32_t phase _U_, u_int32_t doi _U_,
+ u_int32_t proto _U_, int depth _U_)
{
struct isakmp_gen e;
printf("%s:", NPSTR(ISAKMP_NPTYPE_HASH));
+ TCHECK(*ext);
safememcpy(&e, ext, sizeof(e));
printf(" len=%d", ntohs(e.len) - 4);
if (2 < vflag && 4 < ntohs(e.len)) {
printf(" ");
- rawprint((caddr_t)(ext + 1), ntohs(e.len) - 4);
+ if (!rawprint((caddr_t)(ext + 1), ntohs(e.len) - 4))
+ goto trunc;
}
return (u_char *)ext + ntohs(e.len);
+trunc:
+ printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_HASH));
+ return NULL;
}
static const u_char *
-isakmp_sig_print(const struct isakmp_gen *ext, const u_char *ep _U_,
- u_int32_t phase _U_, u_int32_t doi _U_, u_int32_t proto _U_,
- int depth _U_)
+isakmp_sig_print(const struct isakmp_gen *ext, u_int item_len _U_,
+ const u_char *ep _U_, u_int32_t phase _U_, u_int32_t doi _U_,
+ u_int32_t proto _U_, int depth _U_)
{
struct isakmp_gen e;
printf("%s:", NPSTR(ISAKMP_NPTYPE_SIG));
+ TCHECK(*ext);
safememcpy(&e, ext, sizeof(e));
printf(" len=%d", ntohs(e.len) - 4);
if (2 < vflag && 4 < ntohs(e.len)) {
printf(" ");
- rawprint((caddr_t)(ext + 1), ntohs(e.len) - 4);
+ if (!rawprint((caddr_t)(ext + 1), ntohs(e.len) - 4))
+ goto trunc;
}
return (u_char *)ext + ntohs(e.len);
+trunc:
+ printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_SIG));
+ return NULL;
}
static const u_char *
-isakmp_nonce_print(const struct isakmp_gen *ext, const u_char *ep _U_,
- u_int32_t phase _U_, u_int32_t doi _U_, u_int32_t proto _U_,
- int depth _U_)
+isakmp_nonce_print(const struct isakmp_gen *ext,
+ u_int item_len _U_,
+ const u_char *ep _U_,
+ u_int32_t phase _U_, u_int32_t doi _U_,
+ u_int32_t proto _U_, int depth _U_)
{
struct isakmp_gen e;
printf("%s:", NPSTR(ISAKMP_NPTYPE_NONCE));
+ TCHECK(*ext);
safememcpy(&e, ext, sizeof(e));
printf(" n len=%d", ntohs(e.len) - 4);
if (2 < vflag && 4 < ntohs(e.len)) {
printf(" ");
- rawprint((caddr_t)(ext + 1), ntohs(e.len) - 4);
+ if (!rawprint((caddr_t)(ext + 1), ntohs(e.len) - 4))
+ goto trunc;
}
return (u_char *)ext + ntohs(e.len);
+trunc:
+ printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_NONCE));
+ return NULL;
}
static const u_char *
-isakmp_n_print(const struct isakmp_gen *ext, const u_char *ep, u_int32_t phase,
- u_int32_t doi0 _U_, u_int32_t proto0 _U_, int depth)
+isakmp_n_print(const struct isakmp_gen *ext, u_int item_len,
+ const u_char *ep, u_int32_t phase, u_int32_t doi0 _U_,
+ u_int32_t proto0 _U_, int depth)
{
struct isakmp_pl_n *p, n;
const u_char *cp;
printf("%s:", NPSTR(ISAKMP_NPTYPE_N));
p = (struct isakmp_pl_n *)ext;
+ TCHECK(*p);
safememcpy(&n, ext, sizeof(n));
doi = ntohl(n.doi);
proto = n.prot_id;
printf(" type=%s", numstr(ntohs(n.type)));
if (n.spi_size) {
printf(" spi=");
- rawprint((caddr_t)(p + 1), n.spi_size);
+ if (!rawprint((caddr_t)(p + 1), n.spi_size))
+ goto trunc;
}
return (u_char *)(p + 1) + n.spi_size;
}
printf(" type=%s", numstr(ntohs(n.type)));
if (n.spi_size) {
printf(" spi=");
- rawprint((caddr_t)(p + 1), n.spi_size);
+ if (!rawprint((caddr_t)(p + 1), n.spi_size))
+ goto trunc;
}
cp = (u_char *)(p + 1) + n.spi_size;
- ep2 = (u_char *)p + ntohs(n.h.len);
+ ep2 = (u_char *)p + item_len;
if (cp < ep) {
printf(" orig=(");
break;
default:
/* NULL is dummy */
- isakmp_print(cp,
- ntohs(n.h.len) - sizeof(*p) - n.spi_size,
- NULL);
+ isakmp_print(gndo, cp,
+ item_len - sizeof(*p) - n.spi_size,
+ NULL);
}
printf(")");
}
- return (u_char *)ext + ntohs(n.h.len);
+ return (u_char *)ext + item_len;
+trunc:
+ printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_N));
+ return NULL;
}
static const u_char *
-isakmp_d_print(const struct isakmp_gen *ext, const u_char *ep _U_,
- u_int32_t phase _U_, u_int32_t doi0 _U_, u_int32_t proto0 _U_,
- int depth _U_)
+isakmp_d_print(const struct isakmp_gen *ext, u_int item_len _U_,
+ const u_char *ep _U_, u_int32_t phase _U_, u_int32_t doi0 _U_,
+ u_int32_t proto0 _U_, int depth _U_)
{
const struct isakmp_pl_d *p;
struct isakmp_pl_d d;
printf("%s:", NPSTR(ISAKMP_NPTYPE_D));
p = (struct isakmp_pl_d *)ext;
+ TCHECK(*p);
safememcpy(&d, ext, sizeof(d));
doi = ntohl(d.doi);
proto = d.prot_id;
for (i = 0; i < ntohs(d.num_spi); i++) {
if (i != 0)
printf(",");
- rawprint((caddr_t)q, d.spi_size);
+ if (!rawprint((caddr_t)q, d.spi_size))
+ goto trunc;
q += d.spi_size;
}
return q;
+trunc:
+ printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_D));
+ return NULL;
}
static const u_char *
-isakmp_vid_print(const struct isakmp_gen *ext, const u_char *ep _U_,
- u_int32_t phase _U_, u_int32_t doi _U_, u_int32_t proto _U_,
- int depth _U_)
+isakmp_vid_print(const struct isakmp_gen *ext,
+ u_int item_len _U_, const u_char *ep _U_,
+ u_int32_t phase _U_, u_int32_t doi _U_,
+ u_int32_t proto _U_, int depth _U_)
{
struct isakmp_gen e;
printf("%s:", NPSTR(ISAKMP_NPTYPE_VID));
+ TCHECK(*ext);
safememcpy(&e, ext, sizeof(e));
printf(" len=%d", ntohs(e.len) - 4);
if (2 < vflag && 4 < ntohs(e.len)) {
printf(" ");
- rawprint((caddr_t)(ext + 1), ntohs(e.len) - 4);
+ if (!rawprint((caddr_t)(ext + 1), ntohs(e.len) - 4))
+ goto trunc;
}
return (u_char *)ext + ntohs(e.len);
+trunc:
+ printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_VID));
+ return NULL;
}
static const u_char *
u_int item_len;
cp = (u_char *)ext;
+ TCHECK(*ext);
safememcpy(&e, ext, sizeof(e));
- if (NPFUNC(np))
- cp = (*NPFUNC(np))(ext, ep, phase, doi, proto, depth);
- else {
+ /*
+ * Since we can't have a payload length of less than 4 bytes,
+ * we need to bail out here if the generic header is nonsensical
+ * or truncated, otherwise we could loop forever processing
+ * zero-length items or otherwise misdissect the packet.
+ */
+ item_len = ntohs(e.len);
+ if (item_len <= 4)
+ return NULL;
+
+ if (NPFUNC(np)) {
+ /*
+ * XXX - what if item_len is too short, or too long,
+ * for this payload type?
+ */
+ cp = (*npfunc[np])(ext, item_len, ep, phase, doi, proto, depth);
+ } else {
printf("%s", NPSTR(np));
- item_len = ntohs(e.len);
- if (item_len == 0) {
- /*
- * We don't want to loop forever processing this
- * bogus (zero-length) item; return NULL so that
- * we stop dissecting.
- */
- cp = NULL;
- } else
- cp += item_len;
+ cp += item_len;
}
return cp;
+trunc:
+ printf(" [|isakmp]");
+ return NULL;
}
static const u_char *
cp = (const u_char *)ext;
while (np) {
+ TCHECK(*ext);
+
safememcpy(&e, ext, sizeof(e));
- if (ep < (u_char *)ext + ntohs(e.len)) {
- printf(" [|%s]", NPSTR(np));
- cp = ep + 1;
- break;
- }
+ TCHECK2(*ext, ntohs(e.len));
+
depth++;
printf("\n");
for (i = 0; i < depth; i++)
ext = (struct isakmp_gen *)cp;
}
return cp;
+trunc:
+ printf(" [|%s]", NPSTR(np));
+ return NULL;
}
static char *
}
void
-isakmp_print(const u_char *bp, u_int length, const u_char *bp2)
+isakmp_print(netdissect_options *ndo,
+ const u_char *bp, u_int length,
+ const u_char *bp2)
{
const struct isakmp *p;
struct isakmp base;
int major, minor;
p = (const struct isakmp *)bp;
- ep = snapend;
+ ep = ndo->ndo_snapend;
if ((struct isakmp *)ep < p + 1) {
printf("[|isakmp]");
printf("[%s%s]", base.flags & ISAKMP_FLAG_E ? "E" : "",
base.flags & ISAKMP_FLAG_C ? "C" : "");
}
- printf(":");
- {
- const struct isakmp_gen *ext;
- int nparen;
+ if (vflag) {
+ const struct isakmp_gen *ext;
+ int nparen;
#define CHECKLEN(p, np) \
- if (ep < (u_char *)(p)) { \
- printf(" [|%s]", NPSTR(np)); \
- goto done; \
- }
+ if (ep < (u_char *)(p)) { \
+ printf(" [|%s]", NPSTR(np)); \
+ goto done; \
+ }
- /* regardless of phase... */
- if (base.flags & ISAKMP_FLAG_E) {
- /*
- * encrypted, nothing we can do right now.
- * we hope to decrypt the packet in the future...
- */
- printf(" [encrypted %s]", NPSTR(base.np));
- goto done;
- }
+ printf(":");
- nparen = 0;
- CHECKLEN(p + 1, base.np)
+ /* regardless of phase... */
+ if (base.flags & ISAKMP_FLAG_E) {
+ /*
+ * encrypted, nothing we can do right now.
+ * we hope to decrypt the packet in the future...
+ */
+ printf(" [encrypted %s]", NPSTR(base.np));
+ goto done;
+ }
- np = base.np;
- ext = (struct isakmp_gen *)(p + 1);
- isakmp_sub_print(np, ext, ep, phase, 0, 0, 0);
- }
+ nparen = 0;
+ CHECKLEN(p + 1, base.np)
+
+ np = base.np;
+ ext = (struct isakmp_gen *)(p + 1);
+ isakmp_sub_print(np, ext, ep, phase, 0, 0, 0);
+ }
done:
if (vflag) {
if (ntohl(base.len) != length) {
- printf(" (len mismatch: isakmp %u/ip %d)",
+ printf(" (len mismatch: isakmp %u/ip %u)",
(u_int32_t)ntohl(base.len), length);
}
}
}
+
+void
+isakmp_rfc3948_print(netdissect_options *ndo,
+ const u_char *bp, u_int length,
+ const u_char *bp2)
+{
+ const u_char *ep;
+ ep = ndo->ndo_snapend;
+
+ if(length == 1 && bp[0]==0xff) {
+ ND_PRINT((ndo, "isakmp-nat-keep-alive"));
+ return;
+ }
+
+ if(length < 4) {
+ goto trunc;
+ }
+
+ /*
+ * see if this is an IKE packet
+ */
+ if(bp[0]==0 && bp[1]==0 && bp[2]==0 && bp[3]==0) {
+ ND_PRINT((ndo, "NONESP-encap: "));
+ isakmp_print(ndo, bp+4, length-4, bp2);
+ return;
+ }
+
+ /* must be an ESP packet */
+ {
+ int nh, enh, padlen;
+ int advance;
+
+ ND_PRINT((ndo, "UDP-encap: "));
+
+ advance = esp_print(ndo, bp, length, bp2, &enh, &padlen);
+ if(advance <= 0)
+ return;
+
+ bp += advance;
+ length -= advance + padlen;
+ nh = enh & 0xff;
+
+ ip_print_inner(ndo, bp, length, nh, bp2);
+ return;
+ }
+
+trunc:
+ printf("[|isakmp]");
+ return;
+}
+
+/*
+ * Local Variables:
+ * c-style: whitesmith
+ * c-basic-offset: 8
+ * End:
+ */
+
+
+
+