1 /*
2  *   This program is is free software; you can redistribute it and/or modify
3  *   it under the terms of the GNU General Public License, version 2 of the
4  *   License as published by the Free Software Foundation.
5  *
6  *   This program is distributed in the hope that it will be useful,
7  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
8  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
9  *   GNU General Public License for more details.
10  *
11  *   You should have received a copy of the GNU General Public License
12  *   along with this program; if not, write to the Free Software
13  *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
14  */
15 
16 /**
17  * $Id: 987a8ea3f049a843136905b1e2b4c82b26d163ee $
18  * @file pcap.c
19  * @brief Wrappers around libpcap functions
20  *
21  * @author Arran Cudbard-Bell <a.cudbardb@freeradius.org>
22  * @copyright 2013 Arran Cudbard-Bell <a.cudbardb@freeradius.org>
23  */
24 #ifdef HAVE_LIBPCAP
25 
26 #include <sys/ioctl.h>
27 #include <freeradius-devel/pcap.h>
28 
29 const FR_NAME_NUMBER pcap_types[] = {
30 	{ "interface",	PCAP_INTERFACE_IN },
31 	{ "file",	PCAP_FILE_IN },
32 	{ "stdio",	PCAP_STDIO_IN },
33 	{ "interface",	PCAP_INTERFACE_OUT },
34 	{ "file",	PCAP_FILE_OUT },
35 	{ "stdio",	PCAP_STDIO_OUT },
36 
37 	{ NULL, 0}
38 };
39 
40 /** Talloc destructor to free pcap resources associated with a handle.
41  *
42  * @param pcap to free.
43  * @return 0
44  */
_free_pcap(fr_pcap_t * pcap)45 static int _free_pcap(fr_pcap_t *pcap) {
46 	switch (pcap->type) {
47 	case PCAP_INTERFACE_IN:
48 	case PCAP_INTERFACE_OUT:
49 	case PCAP_FILE_IN:
50 	case PCAP_STDIO_IN:
51 		if (pcap->handle) {
52 			pcap_close(pcap->handle);
53 
54 			if (pcap->fd > 0) {
55 				close(pcap->fd);
56 			}
57 		}
58 
59 		break;
60 
61 	case PCAP_FILE_OUT:
62 	case PCAP_STDIO_OUT:
63 		if (pcap->dumper) {
64 			pcap_dump_flush(pcap->dumper);
65 			pcap_dump_close(pcap->dumper);
66 		}
67 
68 		break;
69 	case PCAP_INVALID:
70 		break;
71 	}
72 
73 	return 0;
74 }
75 
76 /** Get data link from pcap_if_t
77  *
78  * libpcap requires an open pcap handle to get data_link type
79  * unfortunately when we're trying to find useful interfaces
80  * this is too late.
81  *
82  * @param errbuff Error message.
83  * @param dev to get link layer for.
84  * @return datalink layer or -1 on failure.
85  */
fr_pcap_if_link_layer(char * errbuff,pcap_if_t * dev)86 int fr_pcap_if_link_layer(char *errbuff, pcap_if_t *dev)
87 {
88 	pcap_t *pcap;
89 	int data_link;
90 
91 	pcap = pcap_open_live(dev->name, 0, 0, 0, errbuff);
92 	if (!pcap) return -1;
93 
94 	data_link = pcap_datalink(pcap);
95 	pcap_close(pcap);
96 
97 	return data_link;
98 }
99 
100 /** Initialise a pcap handle abstraction
101  *
102  * @param ctx talloc TALLOC_CTX to allocate handle in.
103  * @param name of interface or file to open.
104  * @param type of handle to initialise.
105  * @return new handle or NULL on error.
106  */
fr_pcap_init(TALLOC_CTX * ctx,char const * name,fr_pcap_type_t type)107 fr_pcap_t *fr_pcap_init(TALLOC_CTX *ctx, char const *name, fr_pcap_type_t type)
108 {
109 	fr_pcap_t *this = talloc_zero(ctx, fr_pcap_t);
110 	if (!this) {
111 		return NULL;
112 	}
113 
114 	talloc_set_destructor(this, _free_pcap);
115 	this->name = talloc_typed_strdup(this, name);
116 	this->type = type;
117 	this->link_layer = -1;
118 
119 	return this;
120 }
121 
122 /** Open a PCAP handle abstraction
123  *
124  * This opens interfaces for capture or injection, or files/streams for reading/writing.
125  * @param pcap created with fr_pcap_init.
126  * @return 0 on success, -1 on error.
127  */
fr_pcap_open(fr_pcap_t * pcap)128 int fr_pcap_open(fr_pcap_t *pcap)
129 {
130 	switch (pcap->type) {
131 	case PCAP_INTERFACE_OUT:
132 	case PCAP_INTERFACE_IN:
133 	{
134 #if defined(HAVE_PCAP_CREATE) && defined(HAVE_PCAP_ACTIVATE)
135 		pcap->handle = pcap_create(pcap->name, pcap->errbuf);
136 		if (!pcap->handle) {
137 			fr_strerror_printf("%s", pcap->errbuf);
138 			return -1;
139 		}
140 		if (pcap_set_snaplen(pcap->handle, SNAPLEN) != 0) {
141 		create_error:
142 			fr_strerror_printf("%s", pcap_geterr(pcap->handle));
143 			pcap_close(pcap->handle);
144 			pcap->handle = NULL;
145 			return -1;
146 		}
147 		if (pcap_set_timeout(pcap->handle, PCAP_NONBLOCK_TIMEOUT) != 0) {
148 			goto create_error;
149 		}
150 		if (pcap_set_promisc(pcap->handle, pcap->promiscuous) != 0) {
151 			goto create_error;
152 		}
153 
154 		if (pcap_set_buffer_size(pcap->handle, SNAPLEN *
155 					 (pcap->buffer_pkts ? pcap->buffer_pkts : PCAP_BUFFER_DEFAULT)) != 0) {
156 			goto create_error;
157 		}
158 		if (pcap_activate(pcap->handle) != 0) {
159 			goto create_error;
160 		}
161 #else
162 		/*
163 		 *	Alternative functions for libpcap < 1.0
164 		 */
165 		pcap->handle = pcap_open_live(pcap->name, SNAPLEN, pcap->promiscuous, PCAP_NONBLOCK_TIMEOUT,
166 					      pcap->errbuf);
167 		if (!pcap->handle) {
168 			fr_strerror_printf("%s", pcap->errbuf);
169 			return -1;
170 		}
171 #endif
172 		/*
173 		 *	Despite accepting an errbuff, pcap_setnonblock doesn't seem to write
174 		 *	error message there in newer versions.
175 		 */
176 		if (pcap_setnonblock(pcap->handle, true, pcap->errbuf) != 0) {
177 			fr_strerror_printf("%s", *pcap->errbuf != '\0' ?
178 					   pcap->errbuf : pcap_geterr(pcap->handle));
179 			pcap_close(pcap->handle);
180 			pcap->handle = NULL;
181 			return -1;
182 		}
183 
184 		pcap->fd = pcap_get_selectable_fd(pcap->handle);
185 		pcap->link_layer = pcap_datalink(pcap->handle);
186 #ifndef __linux__
187 		{
188 			int value = 1;
189 			if (ioctl(pcap->fd, BIOCIMMEDIATE, &value) < 0) {
190 				fr_strerror_printf("Failed setting BIOCIMMEDIATE: %s", fr_syserror(errno));
191 			}
192 		}
193 #endif
194 	}
195 		break;
196 
197 	case PCAP_FILE_IN:
198 		pcap->handle = pcap_open_offline(pcap->name, pcap->errbuf);
199 		if (!pcap->handle) {
200 			fr_strerror_printf("%s", pcap->errbuf);
201 
202 			return -1;
203 		}
204 		pcap->fd = pcap_get_selectable_fd(pcap->handle);
205 		pcap->link_layer = pcap_datalink(pcap->handle);
206 		break;
207 
208 	case PCAP_FILE_OUT:
209 		if (pcap->link_layer < 0) {
210 			pcap->link_layer = DLT_EN10MB;
211 		}
212 		pcap->handle = pcap_open_dead(pcap->link_layer, SNAPLEN);
213 		if (!pcap->handle) {
214 			fr_strerror_printf("Unknown error occurred opening dead PCAP handle");
215 
216 			return -1;
217 		}
218 		pcap->dumper = pcap_dump_open(pcap->handle, pcap->name);
219 		if (!pcap->dumper) {
220 			fr_strerror_printf("%s", pcap_geterr(pcap->handle));
221 
222 			return -1;
223 		}
224 		break;
225 
226 #ifdef HAVE_PCAP_FOPEN_OFFLINE
227 	case PCAP_STDIO_IN:
228 		pcap->handle = pcap_fopen_offline(stdin, pcap->errbuf);
229 		if (!pcap->handle) {
230 			fr_strerror_printf("%s", pcap->errbuf);
231 
232 			return -1;
233 		}
234 		pcap->fd = pcap_get_selectable_fd(pcap->handle);
235 		pcap->link_layer = pcap_datalink(pcap->handle);
236 		break;
237 #else
238 	case PCAP_STDIO_IN:
239 		fr_strerror_printf("This version of libpcap does not support reading pcap data from streams");
240 
241 		return -1;
242 #endif
243 #ifdef HAVE_PCAP_DUMP_FOPEN
244 	case PCAP_STDIO_OUT:
245 		pcap->handle = pcap_open_dead(DLT_EN10MB, SNAPLEN);
246 		pcap->dumper = pcap_dump_fopen(pcap->handle, stdout);
247 		if (!pcap->dumper) {
248 			fr_strerror_printf("%s", pcap_geterr(pcap->handle));
249 
250 			return -1;
251 		}
252 		break;
253 #else
254 	case PCAP_STDIO_OUT:
255 		fr_strerror_printf("This version of libpcap does not support writing pcap data to streams");
256 
257 		return -1;
258 #endif
259 	case PCAP_INVALID:
260 	default:
261 		fr_assert(0);
262 		fr_strerror_printf("Bad handle type (%i)", pcap->type);
263 		return -1;
264 	}
265 
266 	return 0;
267 }
268 
269 /** Apply capture filter to an interface
270  *
271  * @param pcap handle to apply filter to.
272  * @param expression PCAP expression to use as a filter.
273  * @return 0 on success, 1 can't apply to interface, -1 on error.
274  */
fr_pcap_apply_filter(fr_pcap_t * pcap,char const * expression)275 int fr_pcap_apply_filter(fr_pcap_t *pcap, char const *expression)
276 {
277 	bpf_u_int32 mask = 0;				/* Our netmask */
278 	bpf_u_int32 net = 0;				/* Our IP */
279 	struct bpf_program fp;
280 
281 	/*
282 	 *	nflog devices are in the set of devices selected by default.
283 	 *	Unfortunately there's a bug in all released version of libpcap (as of 2/1/2014)
284 	 *	which triggers an abort if pcap_setfilter is called on an nflog interface.
285 	 *
286 	 *	See here:
287 	 * 	https://github.com/the-tcpdump-group/libpcap/commit/676cf8a61ed240d0a86d471ef419f45ba35dba80
288 	 */
289 #ifdef DLT_NFLOG
290 	if (pcap->link_layer == DLT_NFLOG) {
291 		fr_strerror_printf("NFLOG link-layer type filtering not implemented");
292 
293 		return 1;
294 	}
295 #endif
296 
297 	if (pcap->type == PCAP_INTERFACE_IN) {
298 		if (pcap_lookupnet(pcap->name, &net, &mask, pcap->errbuf) < 0) {
299 			fr_strerror_printf("Failed getting IP for interface \"%s\", using defaults: %s",
300 					   pcap->name, pcap->errbuf);
301 		}
302 	}
303 
304 	if (pcap_compile(pcap->handle, &fp, expression, 0, net) < 0) {
305 		fr_strerror_printf("%s", pcap_geterr(pcap->handle));
306 
307 		return -1;
308 	}
309 
310 	if (pcap_setfilter(pcap->handle, &fp) < 0) {
311 		fr_strerror_printf("%s", pcap_geterr(pcap->handle));
312 
313 		return -1;
314 	}
315 
316 	return 0;
317 }
318 
fr_pcap_device_names(TALLOC_CTX * ctx,fr_pcap_t * pcap,char c)319 char *fr_pcap_device_names(TALLOC_CTX *ctx, fr_pcap_t *pcap, char c)
320 {
321 	fr_pcap_t *pcap_p;
322 	char *buff, *p;
323 	size_t len = 0, left = 0, wrote;
324 
325 	if (!pcap) {
326 		goto null;
327 	}
328 
329 	for (pcap_p = pcap;
330 	     pcap_p;
331 	     pcap_p = pcap_p->next) {
332 		len += talloc_array_length(pcap_p->name);	// Talloc array length includes the \0
333 	}
334 
335 	if (!len) {
336 		null:
337 		return talloc_zero_array(ctx, char, 1);
338 	}
339 
340 	left = len + 1;
341 	buff = p = talloc_zero_array(ctx, char, left);
342 	for (pcap_p = pcap;
343 	     pcap_p;
344 	     pcap_p = pcap_p->next) {
345 		wrote = snprintf(p, left, "%s%c", pcap_p->name, c);
346 		left -= wrote;
347 		p += wrote;
348 	}
349 	buff[len - 1] = '\0';
350 
351 	return buff;
352 }
353 
354 /** Check whether fr_pcap_link_layer_offset can process a link_layer
355  *
356  * @param link_layer to check.
357  * @return true if supported, else false.
358  */
fr_pcap_link_layer_supported(int link_layer)359 bool fr_pcap_link_layer_supported(int link_layer)
360 {
361 	switch (link_layer) {
362 	case DLT_EN10MB:
363 	case DLT_RAW:
364 	case DLT_NULL:
365 	case DLT_LOOP:
366 #ifdef DLT_LINUX_SLL
367 	case DLT_LINUX_SLL:
368 #endif
369 	case DLT_PFLOG:
370 		return true;
371 
372 	default:
373 		return false;
374 	}
375 }
376 
377 /** Returns the length of the link layer header
378  *
379  * Libpcap does not include a decoding function to skip the L2 header, but it does
380  * at least inform us of the type.
381  *
382  * Unfortunately some headers are of variable length (like ethernet), so additional
383  * decoding logic is required.
384  *
385  * @note No header data is returned, this is only meant to be used to determine how
386  * data to consume before attempting to parse the IP header.
387  *
388  * @param data start of packet data.
389  * @param len caplen.
390  * @param link_layer value returned from pcap_linktype.
391  * @return the length of the header, or -1 on error.
392  */
fr_pcap_link_layer_offset(uint8_t const * data,size_t len,int link_layer)393 ssize_t fr_pcap_link_layer_offset(uint8_t const *data, size_t len, int link_layer)
394 {
395 	uint8_t const *p = data;
396 
397 	switch (link_layer) {
398 	case DLT_RAW:
399 		break;
400 
401 	case DLT_NULL:
402 	case DLT_LOOP:
403 		p += 4;
404 		if (((size_t)(p - data)) > len) {
405 		ood:
406 			fr_strerror_printf("Out of data, needed %zu bytes, have %zu bytes",
407 					   (size_t)(p - data), len);
408 			return -1;
409 		}
410 		break;
411 
412 	case DLT_EN10MB:
413 	{
414 		uint16_t ether_type;	/* Ethernet type */
415 		int i;
416 
417 		p += 12;		/* SRC/DST Mac-Addresses */
418 		if (((size_t)(p - data)) > len) {
419 			goto ood;
420 		}
421 
422 		for (i = 0; i < 3; i++) {
423 			ether_type = ntohs(*((uint16_t const *) p));
424 			switch (ether_type) {
425 			/*
426 			 *	There are a number of devices out there which
427 			 *	double tag with 0x8100 *sigh*
428 			 */
429 			case 0x8100:	/* CVLAN */
430 			case 0x9100:	/* SVLAN */
431 			case 0x9200:	/* SVLAN */
432 			case 0x9300:	/* SVLAN */
433 				p += 4;
434 				if (((size_t)(p - data)) > len) {
435 					goto ood;
436 				}
437 				break;
438 
439 			default:
440 				p += 2;
441 				if (((size_t)(p - data)) > len) {
442 					goto ood;
443 				}
444 				goto done;
445 			}
446 		}
447 		fr_strerror_printf("Exceeded maximum level of VLAN tag nesting (2)");
448 		return -1;
449 	}
450 
451 #ifdef DLT_LINUX_SLL
452 	case DLT_LINUX_SLL:
453 		p += 16;
454 		if (((size_t)(p - data)) > len) {
455 			goto ood;
456 		}
457 		break;
458 #endif
459 
460 	case DLT_PFLOG:
461 		p += 28;
462 		if (((size_t)(p - data)) > len) {
463 			goto ood;
464 		}
465 		break;
466 
467 	default:
468 		fr_strerror_printf("Unsupported link layer type %i", link_layer);
469 	}
470 
471 done:
472 	return p - data;
473 }
474 #endif	/* HAVE_LIBPCAP */
475