/* \summary: Linux cooked sockets capture printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
-#ifdef HAVE_NET_IF_H
+#ifdef __linux__
#include <net/if.h>
#endif
#include "netdissect-stdinc.h"
+#define ND_LONGJMP_FROM_TCHECK
#include "netdissect.h"
#include "addrtoname.h"
#include "ethertype.h"
u_short ether_type;
ndo->ndo_protocol = "sll";
- ND_PRINT("%3s ",tok2str(sll_pkttype_values,"?",EXTRACT_BE_U_2(sllp->sll_pkttype)));
+ ND_PRINT("%3s ",
+ tok2str(sll_pkttype_values,"?",GET_BE_U_2(sllp->sll_pkttype)));
/*
* XXX - check the link-layer address type value?
* For now, we just assume 6 means Ethernet.
* XXX - print others as strings of hex?
*/
- if (EXTRACT_BE_U_2(sllp->sll_halen) == 6)
- ND_PRINT("%s ", etheraddr_string(ndo, sllp->sll_addr));
+ if (GET_BE_U_2(sllp->sll_halen) == MAC48_LEN)
+ ND_PRINT("%s ", GET_MAC48_STRING(sllp->sll_addr));
if (!ndo->ndo_qflag) {
- ether_type = EXTRACT_BE_U_2(sllp->sll_protocol);
+ ether_type = GET_BE_U_2(sllp->sll_protocol);
if (ether_type <= MAX_ETHERNET_LENGTH_VAL) {
/*
* 'h->len' is the length of the packet off the wire, and 'h->caplen'
* is the number of bytes actually captured.
*/
-u_int
+void
sll_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, const u_char *p)
{
u_int caplen = h->caplen;
u_int length = h->len;
const struct sll_header *sllp;
+ u_short hatype;
u_short ether_type;
int llc_hdrlen;
u_int hdrlen;
- ndo->ndo_protocol = "sll_if";
- if (caplen < SLL_HDR_LEN) {
- /*
- * XXX - this "can't happen" because "pcap-linux.c" always
- * adds this many bytes of header to every packet in a
- * cooked socket capture.
- */
- nd_print_trunc(ndo);
- return (caplen);
- }
+ ndo->ndo_protocol = "sll";
+ ND_TCHECK_LEN(p, SLL_HDR_LEN);
sllp = (const struct sll_header *)p;
p += SLL_HDR_LEN;
hdrlen = SLL_HDR_LEN;
- ether_type = EXTRACT_BE_U_2(sllp->sll_protocol);
+ hatype = GET_BE_U_2(sllp->sll_hatype);
+ switch (hatype) {
+
+ case 803:
+ /*
+ * This is an packet with a radiotap header;
+ * just dissect the payload as such.
+ */
+ ndo->ndo_ll_hdr_len += SLL_HDR_LEN;
+ ndo->ndo_ll_hdr_len += ieee802_11_radio_print(ndo, p, length, caplen);
+ return;
+ }
+ ether_type = GET_BE_U_2(sllp->sll_protocol);
recurse:
/*
* the enclosed type field.
*/
if (caplen < 4) {
- ND_PRINT("[|vlan]");
- return (hdrlen + caplen);
- }
- if (length < 4) {
- ND_PRINT("[|vlan]");
- return (hdrlen + length);
+ ndo->ndo_protocol = "vlan";
+ nd_print_trunc(ndo);
+ ndo->ndo_ll_hdr_len += hdrlen + caplen;
+ return;
}
if (ndo->ndo_eflag) {
- uint16_t tag = EXTRACT_BE_U_2(p);
+ uint16_t tag = GET_BE_U_2(p);
ND_PRINT("%s, ", ieee8021q_tci_string(tag));
}
- ether_type = EXTRACT_BE_U_2(p + 2);
+ ether_type = GET_BE_U_2(p + 2);
if (ether_type <= MAX_ETHERNET_LENGTH_VAL)
ether_type = LINUX_SLL_P_802_2;
if (!ndo->ndo_qflag) {
}
}
- return (hdrlen);
+ ndo->ndo_ll_hdr_len += hdrlen;
}
static void
u_short ether_type;
ndo->ndo_protocol = "sll2";
- ND_PRINT("%3s ",tok2str(sll_pkttype_values,"?",EXTRACT_U_1(sllp->sll2_pkttype)));
+ ND_PRINT("ifindex %u ", GET_BE_U_4(sllp->sll2_if_index));
/*
* XXX - check the link-layer address type value?
* For now, we just assume 6 means Ethernet.
* XXX - print others as strings of hex?
*/
- if (EXTRACT_U_1(sllp->sll2_halen) == 6)
- ND_PRINT("%s ", etheraddr_string(ndo, sllp->sll2_addr));
+ if (GET_U_1(sllp->sll2_halen) == MAC48_LEN)
+ ND_PRINT("%s ", GET_MAC48_STRING(sllp->sll2_addr));
if (!ndo->ndo_qflag) {
- ether_type = EXTRACT_BE_U_2(sllp->sll2_protocol);
+ ether_type = GET_BE_U_2(sllp->sll2_protocol);
if (ether_type <= MAX_ETHERNET_LENGTH_VAL) {
/*
* Linux "cooked capture" 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.
+ *
+ * On Linux, we attempt to look up the interface index and print the
+ * name of the interface on which the packet arrived or was sent.
+ *
+ * This look up is only likely to work well if done on the same machine
+ * as the one on which the capture was done, as the interface with a
+ * given index on the latter machine is unlikely to have the same
+ * name as the interface with that index on the former machine.
+ *
+ * As DLT_LINUX_SLL2 live captures are supported only on Linux, this
+ * means that if the machine on which we're reading the file isn't
+ * running Linux, it's probably not the machine that captured the file,
+ * so we don't bother trying to do the lookup on non-Linux machines.
*/
-u_int
+void
sll2_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, const u_char *p)
{
u_int caplen = h->caplen;
u_int length = h->len;
const struct sll2_header *sllp;
+ u_short hatype;
u_short ether_type;
int llc_hdrlen;
u_int hdrlen;
-#ifdef HAVE_NET_IF_H
+#ifdef __linux__
uint32_t if_index;
char ifname[IF_NAMESIZE];
#endif
- ndo->ndo_protocol = "sll2_if";
- if (caplen < SLL2_HDR_LEN) {
- /*
- * XXX - this "can't happen" because "pcap-linux.c" always
- * adds this many bytes of header to every packet in a
- * cooked socket capture.
- */
- nd_print_trunc(ndo);
- return (caplen);
- }
+ ndo->ndo_protocol = "sll2";
+ ND_TCHECK_LEN(p, SLL2_HDR_LEN);
sllp = (const struct sll2_header *)p;
-#ifdef HAVE_NET_IF_H
- if_index = EXTRACT_BE_U_4(sllp->sll2_if_index);
- if (if_indextoname(if_index, ifname))
- ND_PRINT("ifindex %u (%s) ", if_index, ifname);
- else
- ND_PRINT("ifindex %u ", if_index);
+#ifdef __linux__
+ if_index = GET_BE_U_4(sllp->sll2_if_index);
+ if (!if_indextoname(if_index, ifname))
+ strncpy(ifname, "?", 2);
+ ND_PRINT("%-5s ", ifname);
#endif
+ ND_PRINT("%-3s ",
+ tok2str(sll_pkttype_values, "?", GET_U_1(sllp->sll2_pkttype)));
+
if (ndo->ndo_eflag)
sll2_print(ndo, sllp, length);
p += SLL2_HDR_LEN;
hdrlen = SLL2_HDR_LEN;
- ether_type = EXTRACT_BE_U_2(sllp->sll2_protocol);
+ hatype = GET_BE_U_2(sllp->sll2_hatype);
+ switch (hatype) {
+
+ case 803:
+ /*
+ * This is an packet with a radiotap header;
+ * just dissect the payload as such.
+ */
+ ndo->ndo_ll_hdr_len += SLL2_HDR_LEN;
+ ndo->ndo_ll_hdr_len += ieee802_11_radio_print(ndo, p, length, caplen);
+ return;
+ }
+ ether_type = GET_BE_U_2(sllp->sll2_protocol);
recurse:
/*
* the enclosed type field.
*/
if (caplen < 4) {
- ND_PRINT("[|vlan]");
- return (hdrlen + caplen);
- }
- if (length < 4) {
- ND_PRINT("[|vlan]");
- return (hdrlen + length);
+ ndo->ndo_protocol = "vlan";
+ nd_print_trunc(ndo);
+ ndo->ndo_ll_hdr_len += hdrlen + caplen;
+ return;
}
if (ndo->ndo_eflag) {
- uint16_t tag = EXTRACT_BE_U_2(p);
+ uint16_t tag = GET_BE_U_2(p);
ND_PRINT("%s, ", ieee8021q_tci_string(tag));
}
- ether_type = EXTRACT_BE_U_2(p + 2);
+ ether_type = GET_BE_U_2(p + 2);
if (ether_type <= MAX_ETHERNET_LENGTH_VAL)
ether_type = LINUX_SLL_P_802_2;
if (!ndo->ndo_qflag) {
if (ethertype_print(ndo, ether_type, p, length, caplen, NULL, NULL) == 0) {
/* ether_type not known, print raw packet */
if (!ndo->ndo_eflag)
- sll2_print(ndo, sllp, length + SLL_HDR_LEN);
+ sll2_print(ndo, sllp, length + SLL2_HDR_LEN);
if (!ndo->ndo_suppress_default_print)
ND_DEFAULTPRINT(p, caplen);
}
}
- return (hdrlen);
+ ndo->ndo_ll_hdr_len += hdrlen;
}