1/*
2 * Copyright (c) 2012-2013 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28
29#ifdef HAVE_CONFIG_H
30#include "config.h"
31#endif
32
33#include <tcpdump-stdinc.h>
34
35#include <pcap.h>
36
37#include "interface.h"
38
39#ifdef DLT_PKTAP
40
41#include <net/pktap.h>
42#include <strings.h>
43
44extern char *svc2str(uint32_t);
45
46#define DEBUG 1
47#ifdef DEBUG
48void
49print_pktap_header(struct pktap_header *pktp_hdr)
50{
51	printf("pth_length %u (sizeof(struct pktap_header)  %lu)\n",
52		   pktp_hdr->pth_length, sizeof(struct pktap_header));
53	printf("pth_type_next %u\n", pktp_hdr->pth_type_next);
54	printf("pth_dlt %u\n", pktp_hdr->pth_dlt);
55	printf("pth_ifname %s\n", pktp_hdr->pth_ifname);
56	printf("pth_flags 0x%x\n", pktp_hdr->pth_flags);
57	printf("pth_protocol_family %u\n", pktp_hdr->pth_protocol_family);
58	printf("pth_frame_pre_length %u\n", pktp_hdr->pth_frame_pre_length);
59	printf("pth_frame_post_length %u\n", pktp_hdr->pth_frame_post_length);
60	printf("pth_pid %d\n", pktp_hdr->pth_pid);
61	printf("pth_comm %s\n", pktp_hdr->pth_comm);
62	printf("pth_svc %u\n", pktp_hdr->pth_svc);
63	printf("pth_epid %d\n", pktp_hdr->pth_epid);
64	printf("pth_ecomm %s\n", pktp_hdr->pth_ecomm);
65}
66#endif /* DEBUG */
67
68u_int
69pktap_if_print(struct netdissect_options *ndo, const struct pcap_pkthdr *h,
70			   const u_char *p)
71{
72	struct pktap_header *pktp_hdr;
73	uint32_t dlt;
74	if_ndo_printer ndo_printer;
75	if_printer printer;
76	struct pcap_pkthdr tmp_hdr;
77
78	pktp_hdr = (struct pktap_header *)p;
79
80	if (h->len < sizeof(struct pktap_header) ||
81		h->caplen < sizeof(struct pktap_header) ||
82		pktp_hdr->pth_length > h->caplen) {
83		ND_PRINT((ndo, "[|pktap]"));
84		return sizeof(struct pktap_header);
85	}
86
87#ifdef DEBUG
88	if (eflag > 1)
89		print_pktap_header(pktp_hdr);
90#endif
91
92	if (kflag != PRMD_NONE) {
93		const char *prsep = "";
94
95		ND_PRINT((ndo, "("));
96
97		if (kflag & PRMD_IF) {
98			ND_PRINT((ndo, "%s", pktp_hdr->pth_ifname));
99			prsep = ", ";
100		}
101		if (pktp_hdr->pth_pid != -1) {
102			switch ((kflag & (PRMD_PNAME |PRMD_PID))) {
103				case (PRMD_PNAME |PRMD_PID):
104					ND_PRINT((ndo, "%sproc %s:%u",
105							  prsep,
106							  pktp_hdr->pth_comm, pktp_hdr->pth_pid));
107					prsep = ", ";
108                    if ((pktp_hdr->pth_flags & PTH_FLAG_PROC_DELEGATED)) {
109                        ND_PRINT((ndo, "%seproc %s:%u",
110                                  prsep,
111                                  pktp_hdr->pth_ecomm, pktp_hdr->pth_epid));
112                        prsep = ", ";
113                    }
114					break;
115				case PRMD_PNAME:
116					ND_PRINT((ndo, "%sproc %s",
117							  prsep,
118							  pktp_hdr->pth_comm));
119					prsep = ", ";
120                    if ((pktp_hdr->pth_flags & PTH_FLAG_PROC_DELEGATED)) {
121                        ND_PRINT((ndo, "%seproc %s",
122                                  prsep,
123                                  pktp_hdr->pth_ecomm));
124                        prsep = ", ";
125                    }
126					break;
127
128				case PRMD_PID:
129					ND_PRINT((ndo, "%sproc %u",
130							  prsep,
131							  pktp_hdr->pth_pid));
132					prsep = ", ";
133                    if ((pktp_hdr->pth_flags & PTH_FLAG_PROC_DELEGATED)) {
134                        ND_PRINT((ndo, "%seproc %u",
135                                  prsep,
136                                  pktp_hdr->pth_epid));
137                        prsep = ", ";
138                    }
139					break;
140
141				default:
142					break;
143			}
144		}
145		if ((kflag & PRMD_SVC) && pktp_hdr->pth_svc != -1) {
146			ND_PRINT((ndo, "%ssvc %s",
147					  prsep,
148					  svc2str(pktp_hdr->pth_svc)));
149			prsep = ", ";
150		}
151		if (kflag & PRMD_DIR) {
152			if ((pktp_hdr->pth_flags & PTH_FLAG_DIR_IN)) {
153				ND_PRINT((ndo, "%sin",
154						  prsep));
155				prsep = ", ";
156			} else if ((pktp_hdr->pth_flags & PTH_FLAG_DIR_OUT)) {
157				ND_PRINT((ndo, "%sout",
158						  prsep));
159				prsep = ", ";
160			}
161		}
162		ND_PRINT((ndo, ") "));
163	}
164
165    /*
166	 * Compensate for the pktap header
167	 */
168	bcopy(h, &tmp_hdr, sizeof(struct pcap_pkthdr));
169	tmp_hdr.caplen -= pktp_hdr->pth_length;
170	tmp_hdr.len -= pktp_hdr->pth_length;
171	p += pktp_hdr->pth_length;
172
173	dlt = pktp_hdr->pth_dlt;
174
175	if ((printer = lookup_printer(dlt)) != NULL) {
176		printer(&tmp_hdr, p);
177	} else if ((ndo_printer = lookup_ndo_printer(dlt)) != NULL) {
178		ndo_printer(ndo, &tmp_hdr, p);
179	} else {
180		if (!ndo->ndo_suppress_default_print)
181			ndo->ndo_default_print(ndo, p,tmp_hdr.caplen);
182	}
183
184	return sizeof(struct pktap_header);
185}
186
187#endif /* DLT_PKTAP */
188