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 __APPLE__
30
31#define NETDISSECT_REWORKED
32#ifdef HAVE_CONFIG_H
33#include "config.h"
34#endif
35
36#include <tcpdump-stdinc.h>
37
38#define __APPLE_PCAP_NG_API
39#include <net/pktap.h>
40#include <pcap.h>
41
42#ifdef DLT_PCAPNG
43#include <pcap/pcap-ng.h>
44#include <pcap/pcap-util.h>
45#endif /* DLT_PCAPNG */
46
47#include <stdio.h>
48#include <string.h>
49#include <stdlib.h>
50#include <sys/queue.h>
51
52#include "netdissect.h"
53#include "interface.h"
54#include "pktmetadatafilter.h"
55
56extern node_t *pkt_meta_data_expression;
57
58extern netdissect_options *gndo;
59
60extern char *filter_src_buf;
61
62extern int pktap_if_count;
63
64extern u_int packets_mtdt_fltr_drop;
65
66extern char *svc2str(uint32_t);
67
68
69/*
70 * Returns zero if the packet doesn't match, non-zero if it matches
71 */
72int
73pktap_filter_packet(pcap_t *pcap, struct pcap_if_info *if_info,
74					const struct pcap_pkthdr *h, const u_char *sp)
75{
76	struct pktap_header *pktp_hdr;
77	const u_char *pkt_data;
78	int match = 0;
79
80	pktp_hdr = (struct pktap_header *)sp;
81
82	if (h->len < sizeof(struct pktap_header) ||
83		h->caplen < sizeof(struct pktap_header) ||
84		pktp_hdr->pth_length > h->caplen) {
85		error("%s: Packet too short", __func__);
86		return (0);
87	}
88
89	if (if_info == NULL) {
90		if_info = pcap_find_if_info_by_name(pcap, pktp_hdr->pth_ifname);
91		/*
92		 * New interface
93		 */
94		if (if_info == NULL) {
95			if_info = pcap_add_if_info(pcap, pktp_hdr->pth_ifname,
96											-1, pktp_hdr->pth_dlt, gndo->ndo_snaplen);
97			if (if_info == NULL) {
98				error("%s: pcap_add_if_info(%s, %u) failed: %s",
99					  __func__, pktp_hdr->pth_ifname, pktp_hdr->pth_dlt, pcap_geterr(pcap));
100				return (0);
101			}
102		}
103	}
104
105	if (if_info->if_filter_program.bf_insns == NULL)
106		match = 1;
107	else {
108		/*
109		 * The actual data packet is past the packet tap header
110		 */
111		struct pcap_pkthdr tmp_hdr;
112
113		bcopy(h, &tmp_hdr, sizeof(struct pcap_pkthdr));
114
115		tmp_hdr.caplen -= pktp_hdr->pth_length;
116		tmp_hdr.len -= pktp_hdr->pth_length;
117
118		pkt_data = sp + pktp_hdr->pth_length;
119
120		match = pcap_offline_filter(&if_info->if_filter_program, &tmp_hdr, pkt_data);
121	}
122	/*
123	 * Filter on packet metadata
124	 */
125	if (match && pkt_meta_data_expression != NULL) {
126		struct pkt_meta_data pmd;
127
128		pmd.itf = &pktp_hdr->pth_ifname[0];
129		pmd.proc = &pktp_hdr->pth_comm[0];
130		pmd.eproc = &pktp_hdr->pth_ecomm[0];
131		pmd.pid = pktp_hdr->pth_pid;
132		pmd.epid = pktp_hdr->pth_epid;
133		pmd.svc = svc2str(pktp_hdr->pth_svc);
134		pmd.dir = (pktp_hdr->pth_flags & PTH_FLAG_DIR_IN) ? "in" :
135			(pktp_hdr->pth_flags & PTH_FLAG_DIR_OUT) ? "out" : "";
136
137		match = evaluate_expression(pkt_meta_data_expression, &pmd);
138		if (match == 0)
139			packets_mtdt_fltr_drop++;
140	}
141
142	return (match);
143}
144
145#endif /* __APPLE__ */
146