1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177
|
/*
* Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000
* 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.
*/
/* \summary: Apple's DLT_PKTAP printer */
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "netdissect-stdinc.h"
#define ND_LONGJMP_FROM_TCHECK
#include "netdissect.h"
#include "extract.h"
#ifdef DLT_PKTAP
/*
* XXX - these are little-endian in the captures I've seen, but Apple
* no longer make any big-endian machines (Macs use x86, iOS machines
* use ARM and run it little-endian), so that might be by definition
* or they might be host-endian.
*
* If a big-endian PKTAP file ever shows up, and it comes from a
* big-endian machine, presumably these are host-endian, and we need
* to just fetch the fields directly in tcpdump but byte-swap them
* to host byte order in libpcap.
*/
typedef struct pktap_header {
nd_uint32_t pkt_len; /* length of pktap header */
nd_uint32_t pkt_rectype; /* type of record */
nd_uint32_t pkt_dlt; /* DLT type of this packet */
char pkt_ifname[24]; /* interface name */
nd_uint32_t pkt_flags;
nd_uint32_t pkt_pfamily; /* "protocol family" */
nd_uint32_t pkt_llhdrlen; /* link-layer header length? */
nd_uint32_t pkt_lltrlrlen; /* link-layer trailer length? */
nd_uint32_t pkt_pid; /* process ID */
char pkt_cmdname[20]; /* command name */
nd_uint32_t pkt_svc_class; /* "service class" */
nd_uint16_t pkt_iftype; /* "interface type" */
nd_uint16_t pkt_ifunit; /* unit number of interface? */
nd_uint32_t pkt_epid; /* "effective process ID" */
char pkt_ecmdname[20]; /* "effective command name" */
} pktap_header_t;
/*
* Record types.
*/
#define PKT_REC_NONE 0 /* nothing follows the header */
#define PKT_REC_PACKET 1 /* a packet follows the header */
static void
pktap_header_print(netdissect_options *ndo, const u_char *bp, u_int length)
{
const pktap_header_t *hdr;
uint32_t dlt, hdrlen;
const char *dltname;
hdr = (const pktap_header_t *)bp;
dlt = GET_LE_U_4(hdr->pkt_dlt);
hdrlen = GET_LE_U_4(hdr->pkt_len);
dltname = pcap_datalink_val_to_name(dlt);
if (!ndo->ndo_qflag) {
ND_PRINT("DLT %s (%u) len %u",
(dltname != NULL ? dltname : "UNKNOWN"), dlt, hdrlen);
} else {
ND_PRINT("%s", (dltname != NULL ? dltname : "UNKNOWN"));
}
ND_PRINT(", length %u: ", length);
}
/*
* This is the top level routine of the printer. 'p' points
* to the ether header of the packet, 'h->ts' is the timestamp,
* 'h->len' is the length of the packet off the wire, and 'h->caplen'
* is the number of bytes actually captured.
*/
void
pktap_if_print(netdissect_options *ndo,
const struct pcap_pkthdr *h, const u_char *p)
{
uint32_t dlt, hdrlen, rectype;
u_int caplen = h->caplen;
u_int length = h->len;
if_printer printer;
const pktap_header_t *hdr;
struct pcap_pkthdr nhdr;
ndo->ndo_protocol = "pktap";
if (length < sizeof(pktap_header_t)) {
ND_PRINT(" (packet too short, %u < %zu)",
length, sizeof(pktap_header_t));
goto invalid;
}
hdr = (const pktap_header_t *)p;
dlt = GET_LE_U_4(hdr->pkt_dlt);
hdrlen = GET_LE_U_4(hdr->pkt_len);
if (hdrlen < sizeof(pktap_header_t)) {
/*
* Claimed header length < structure length.
* XXX - does this just mean some fields aren't
* being supplied, or is it truly an error (i.e.,
* is the length supplied so that the header can
* be expanded in the future)?
*/
ND_PRINT(" (pkt_len too small, %u < %zu)",
hdrlen, sizeof(pktap_header_t));
goto invalid;
}
if (hdrlen > length) {
ND_PRINT(" (pkt_len too big, %u > %u)",
hdrlen, length);
goto invalid;
}
ND_TCHECK_LEN(p, hdrlen);
if (ndo->ndo_eflag)
pktap_header_print(ndo, p, length);
length -= hdrlen;
caplen -= hdrlen;
p += hdrlen;
rectype = GET_LE_U_4(hdr->pkt_rectype);
switch (rectype) {
case PKT_REC_NONE:
ND_PRINT("no data");
break;
case PKT_REC_PACKET:
printer = lookup_printer(dlt);
if (printer != NULL) {
nhdr = *h;
nhdr.caplen = caplen;
nhdr.len = length;
printer(ndo, &nhdr, p);
hdrlen += ndo->ndo_ll_hdr_len;
} else {
if (!ndo->ndo_eflag)
pktap_header_print(ndo, (const u_char *)hdr,
length + hdrlen);
if (!ndo->ndo_suppress_default_print)
ND_DEFAULTPRINT(p, caplen);
}
break;
}
ndo->ndo_ll_hdr_len += hdrlen;
return;
invalid:
nd_print_invalid(ndo);
}
#endif /* DLT_PKTAP */
|