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 <sys/types.h> 34#include <sys/queue.h> 35#include <stdio.h> 36#include <string.h> 37#include <stdlib.h> 38#include <stdint.h> 39 40#include "pcap-int.h" 41#include "pcap-util.h" 42 43 44void 45pcap_clear_if_infos(pcap_t * pcap) 46{ 47 int i; 48 49 if (pcap->if_infos != NULL) { 50 for (i = 0; i < pcap->if_info_count; i++) 51 pcap_free_if_info(pcap, pcap->if_infos[i]); 52 53 free(pcap->if_infos); 54 pcap->if_infos = NULL; 55 } 56 pcap->if_info_count = 0; 57 58 return; 59} 60 61struct pcap_if_info * 62pcap_find_if_info_by_name(pcap_t * pcap, const char *name) 63{ 64 int i; 65 66 for (i = 0; i < pcap->if_info_count; i++) { 67 if (strcmp(name, pcap->if_infos[i]->if_name) == 0) 68 return (pcap->if_infos[i]); 69 } 70 return (NULL); 71} 72 73struct pcap_if_info * 74pcap_find_if_info_by_id(pcap_t * pcap, int if_id) 75{ 76 int i; 77 78 for (i = 0; i < pcap->if_info_count; i++) { 79 if (if_id == pcap->if_infos[i]->if_id) 80 return (pcap->if_infos[i]); 81 } 82 return (NULL); 83} 84 85void 86pcap_free_if_info(pcap_t * pcap, struct pcap_if_info *if_info) 87{ 88 if (if_info != NULL) { 89 int i; 90 91 for (i = 0; i < pcap->if_info_count; i++) { 92 if (pcap->if_infos[i] == if_info) { 93 pcap->if_infos[i] = NULL; 94 break; 95 } 96 } 97 98 pcap_freecode(&if_info->if_filter_program); 99 free(if_info); 100 } 101} 102 103struct pcap_if_info * 104pcap_add_if_info(pcap_t * pcap, const char *name, 105 int if_id, int linktype, int snaplen) 106{ 107 struct pcap_if_info *if_info = NULL; 108 size_t ifname_len = strlen(name); 109 struct pcap_if_info **newarray; 110 111 pcap->cleanup_extra_op = pcap_ng_init_section_info; 112 113 /* 114 * Stash the interface name after the structure 115 */ 116 if_info = calloc(1, sizeof(struct pcap_if_info) + ifname_len + 1); 117 if (if_info == NULL) { 118 snprintf(pcap->errbuf, PCAP_ERRBUF_SIZE, 119 "%s: calloc() failed", __func__); 120 return (NULL); 121 } 122 if_info->if_name = (char *)(if_info + 1); 123 if (ifname_len > 0) 124 bcopy(name, if_info->if_name, ifname_len); 125 if_info->if_name[ifname_len] = 0; 126 if (if_id == -1) 127 if_info->if_id = pcap->if_info_count; 128 else 129 if_info->if_id = if_id; 130 if_info->if_linktype = linktype; 131 if_info->if_snaplen = snaplen; 132 133 /* 134 * The compilation of a BPF filter expression depends on 135 * the DLT so we store the program in the if_info 136 */ 137 if (pcap->filter_str != NULL && *pcap->filter_str != 0) { 138 if (pcap_compile_nopcap(if_info->if_snaplen, 139 if_info->if_linktype, 140 &if_info->if_filter_program, 141 pcap->filter_str, 0, PCAP_NETMASK_UNKNOWN) == -1) { 142 snprintf(pcap->errbuf, PCAP_ERRBUF_SIZE, 143 "%s: pcap_compile_nopcap() failed", __func__); 144 free(if_info); 145 return (NULL); 146 } 147 } 148 149 /* 150 * Resize pointer array 151 */ 152 newarray = realloc(pcap->if_infos, 153 (pcap->if_info_count + 1) * sizeof(struct pcap_if_info *)); 154 if (newarray == NULL) { 155 snprintf(pcap->errbuf, PCAP_ERRBUF_SIZE, 156 "%s: realloc() failed", __func__); 157 pcap_free_if_info(pcap, if_info); 158 return (NULL); 159 } 160 pcap->if_infos = newarray; 161 pcap->if_infos[pcap->if_info_count] = if_info; 162 pcap->if_info_count += 1; 163 164 return (if_info); 165} 166 167void 168pcap_clear_proc_infos(pcap_t * pcap) 169{ 170 int i; 171 172 if (pcap->proc_infos != NULL) { 173 for (i = 0; i < pcap->proc_info_count; i++) 174 pcap_free_proc_info(pcap, pcap->proc_infos[i]); 175 176 free(pcap->proc_infos); 177 pcap->proc_infos = NULL; 178 } 179 pcap->proc_info_count = 0; 180 181 return; 182} 183 184struct pcap_proc_info * 185pcap_find_proc_info(pcap_t * pcap, uint32_t pid, const char *name) 186{ 187 int i; 188 189 for (i = 0; i < pcap->proc_info_count; i++) { 190 struct pcap_proc_info *proc_info = pcap->proc_infos[i]; 191 192 if (pid == proc_info->proc_pid && 193 strcmp(name, proc_info->proc_name) == 0) 194 return (proc_info); 195 } 196 return (NULL); 197} 198 199struct pcap_proc_info * 200pcap_find_proc_info_by_index(pcap_t * pcap, uint32_t index) 201{ 202 int i; 203 204 for (i = 0; i < pcap->proc_info_count; i++) { 205 struct pcap_proc_info *proc_info = pcap->proc_infos[i]; 206 207 if (index == proc_info->proc_index) 208 return (proc_info); 209 } 210 return (NULL); 211} 212 213void 214pcap_free_proc_info(pcap_t * pcap, struct pcap_proc_info *proc_info) 215{ 216 217 if (proc_info != NULL) { 218 int i; 219 220 for (i = 0; i < pcap->proc_info_count; i++) { 221 if (pcap->proc_infos[i] == proc_info) { 222 pcap->proc_infos[i] = NULL; 223 break; 224 } 225 } 226 free(proc_info); 227 } 228} 229 230struct pcap_proc_info * 231pcap_add_proc_info(pcap_t * pcap, uint32_t pid, const char *name) 232{ 233 struct pcap_proc_info *proc_info = NULL; 234 size_t name_len = strlen(name); 235 struct pcap_proc_info **newarray; 236 237 pcap->cleanup_extra_op = pcap_ng_init_section_info; 238 239 /* 240 * Stash the process name after the structure 241 */ 242 proc_info = calloc(1, sizeof(struct pcap_proc_info) + name_len + 1); 243 if (proc_info == NULL) { 244 snprintf(pcap->errbuf, PCAP_ERRBUF_SIZE, 245 "%s: calloc() failed", __func__); 246 return (NULL); 247 } 248 proc_info->proc_name = (char *)(proc_info + 1); 249 if (name_len > 0) 250 bcopy(name, proc_info->proc_name, name_len); 251 proc_info->proc_name[name_len] = 0; 252 proc_info->proc_pid = pid; 253 proc_info->proc_index = pcap->proc_info_count; 254 255 /* 256 * Resize pointer array 257 */ 258 newarray = realloc(pcap->proc_infos, 259 (pcap->proc_info_count + 1) * sizeof(struct pcap_proc_info *)); 260 if (newarray == NULL) { 261 snprintf(pcap->errbuf, PCAP_ERRBUF_SIZE, 262 "%s: malloc() failed", __func__); 263 pcap_free_proc_info(pcap, proc_info); 264 return (NULL); 265 } 266 pcap->proc_infos = newarray; 267 pcap->proc_infos[pcap->proc_info_count] = proc_info; 268 pcap->proc_info_count += 1; 269 270 return (proc_info); 271} 272 273int 274pcap_set_filter_info(pcap_t *pcap, const char *str, int optimize, bpf_u_int32 netmask) 275{ 276 if (pcap->filter_str != NULL) 277 free(pcap->filter_str); 278 if (str == NULL) 279 pcap->filter_str = NULL; 280 else { 281 pcap->filter_str = strdup(str); 282 if (pcap->filter_str == NULL) 283 return (PCAP_ERROR); 284 } 285 286 return (0); 287} 288 289void 290pcap_ng_init_section_info(pcap_t *p) 291{ 292 p->shb_added = 0; 293 pcap_clear_if_infos(p); 294 pcap_clear_proc_infos(p); 295 296} 297 298