The FreeRADIUS server  $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
pcap.c
Go to the documentation of this file.
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 /** Wrappers around libpcap functions
17  *
18  * @file src/lib/util/pcap.c
19  *
20  * @author Arran Cudbard-Bell (a.cudbardb@freeradius.org)
21  * @copyright 2013 Arran Cudbard-Bell (a.cudbardb@freeradius.org)
22  */
23 #ifdef HAVE_LIBPCAP
24 
25 #include <freeradius-devel/util/debug.h>
26 #include <freeradius-devel/util/net.h>
27 #include <freeradius-devel/util/pair.h>
28 #include <freeradius-devel/util/pcap.h>
29 #include <freeradius-devel/util/syserror.h>
30 
31 #include <net/if.h>
32 #include <sys/ioctl.h>
33 #include <sys/uio.h>
34 
35 #ifndef SIOCGIFHWADDR
36 # include <ifaddrs.h>
37 # ifdef HAVE_NET_IF_DL_H
38 # include <net/if_dl.h>
39 # endif
40 #else
41 # include <net/if.h>
42 #endif
43 
44 
45 /** Talloc destructor to free pcap resources associated with a handle.
46  *
47  * @param pcap to free.
48  * @return 0
49  */
50 static int _free_pcap(fr_pcap_t *pcap)
51 {
52  switch (pcap->type) {
53  case PCAP_INTERFACE_IN:
54  case PCAP_INTERFACE_OUT:
55  case PCAP_INTERFACE_IN_OUT:
56  case PCAP_FILE_IN:
57  case PCAP_STDIO_IN:
58  if (pcap->handle) {
59  pcap_close(pcap->handle);
60 
61  if (pcap->fd > 0) {
62  close(pcap->fd);
63  }
64  }
65  break;
66 
67  case PCAP_FILE_OUT:
68  case PCAP_STDIO_OUT:
69  if (pcap->dumper) {
70  pcap_dump_flush(pcap->dumper);
71  pcap_dump_close(pcap->dumper);
72  }
73  break;
74 
75  case PCAP_INVALID:
76  break;
77  }
78 
79  return 0;
80 }
81 
82 /** Get data link from pcap_if_t
83  *
84  * libpcap requires an open pcap handle to get data_link type
85  * unfortunately when we're trying to find useful interfaces
86  * this is too late.
87  *
88  * @param dev to get link layer for.
89  * @return
90  * - Datalink layer.
91  * - -1 on failure.
92  */
93 int fr_pcap_if_link_layer(pcap_if_t *dev)
94 {
95  char errbuf[PCAP_ERRBUF_SIZE];
96  pcap_t *pcap;
97  int data_link;
98 
99  pcap = pcap_open_live(dev->name, 0, 0, 0, errbuf);
100  if (!pcap) {
101  fr_strerror_printf("%s", errbuf);
102  return -1;
103  }
104 
105  data_link = pcap_datalink(pcap);
106  pcap_close(pcap);
107 
108  return data_link;
109 }
110 
111 /** Initialise a pcap handle abstraction
112  *
113  * @param ctx talloc TALLOC_CTX to allocate handle in.
114  * @param name of interface or file to open.
115  * @param type of handle to initialise.
116  * @return new handle or NULL on error.
117  */
118 fr_pcap_t *fr_pcap_init(TALLOC_CTX *ctx, char const *name, fr_pcap_type_t type)
119 {
120  fr_pcap_t *this;
121 
122  if (!fr_cond_assert(type >= PCAP_INTERFACE_IN && type <= PCAP_INTERFACE_IN_OUT)) {
123  fr_strerror_printf("Invalid PCAP type: %d", type);
124  return NULL;
125  }
126 
127  this = talloc_zero(ctx, fr_pcap_t);
128  if (!this) return NULL;
129 
130  talloc_set_destructor(this, _free_pcap);
131  this->name = talloc_typed_strdup(this, name);
132  this->type = type;
133  this->link_layer = -1;
134 
135  return this;
136 }
137 
138 /** Get MAC address for given interface
139  *
140  * @param[out] macaddr to write MAC address to.
141  * @param[in] ifname to get MAC for.
142  * @return
143  * - 0 on success.
144  * - -1 on error.
145  */
146 int fr_pcap_mac_addr(uint8_t *macaddr, char *ifname)
147 {
148 #ifndef SIOCGIFHWADDR
149  struct ifaddrs *ifap, *ifaptr;
150  unsigned char *ptr;
151 
152  if (getifaddrs(&ifap) == 0) {
153  for (ifaptr = ifap; ifaptr != NULL; ifaptr = (ifaptr)->ifa_next) {
154  if (!strcmp((ifaptr)->ifa_name, ifname) && (((ifaptr)->ifa_addr)->sa_family == AF_LINK)) {
155  ptr = (uint8_t *)LLADDR((struct sockaddr_dl *)(ifaptr)->ifa_addr);
156  memcpy(macaddr, ptr, ETHER_ADDR_LEN);
157  break;
158  }
159  }
160  freeifaddrs(ifap);
161  return (ifaptr != NULL ? 0 : -1);
162  }
163  return -1;
164 #else
165  int fd, ret;
166  struct ifreq ifr;
167 
168  fd = socket(AF_INET, SOCK_DGRAM, 0);
169 
170  if (fd < 0) {
171  return -1;
172  }
173 
174  ifr.ifr_addr.sa_family = AF_INET;
175  strlcpy(ifr.ifr_name, ifname , IFNAMSIZ-1);
176 
177  ret = ioctl(fd, SIOCGIFHWADDR, &ifr);
178 
179  close(fd);
180 
181  if (ret == 0) {
182  memcpy(macaddr, (uint8_t *)ifr.ifr_hwaddr.sa_data, ETHER_ADDR_LEN);
183  return 0;
184  }
185  return -1;
186 #endif
187 }
188 
189 /** Open a PCAP handle abstraction
190  *
191  * This opens interfaces for capture or injection, or files/streams for reading/writing.
192  * @param pcap created with fr_pcap_init.
193  * @return
194  * - 0 on success.
195  * - -1 on failure.
196  */
197 int fr_pcap_open(fr_pcap_t *pcap)
198 {
199  switch (pcap->type) {
200  case PCAP_INTERFACE_OUT:
201  case PCAP_INTERFACE_IN:
202  case PCAP_INTERFACE_IN_OUT:
203  {
204  /*
205  * Also has the pleasant side effect of not allowing
206  * handles to be opened on "any".
207  *
208  * We do this first, as it's the most specific error.
209  */
210  pcap->ifindex = if_nametoindex(pcap->name);
211  if (!pcap->ifindex) {
212  fr_strerror_printf("Unknown interface \"%s\"", pcap->name);
213  return -1;
214  }
215 
216 #if defined(HAVE_PCAP_CREATE) && defined(HAVE_PCAP_ACTIVATE)
217  pcap->handle = pcap_create(pcap->name, pcap->errbuf);
218  if (!pcap->handle) {
219  fr_strerror_printf("%s", pcap->errbuf);
220  return -1;
221  }
222  if (pcap_set_snaplen(pcap->handle, SNAPLEN) != 0) {
223  create_error:
224  fr_strerror_printf("%s", pcap_geterr(pcap->handle));
225  pcap_close(pcap->handle);
226  pcap->handle = NULL;
227  return -1;
228  }
229  if (pcap_set_timeout(pcap->handle, PCAP_NONBLOCK_TIMEOUT) != 0) {
230  goto create_error;
231  }
232  if (pcap_set_promisc(pcap->handle, pcap->promiscuous) != 0) {
233  goto create_error;
234  }
235 
236  if (pcap_set_buffer_size(pcap->handle, SNAPLEN *
237  (pcap->buffer_pkts ? pcap->buffer_pkts : PCAP_BUFFER_DEFAULT)) != 0) {
238  goto create_error;
239  }
240  if (pcap_activate(pcap->handle) != 0) {
241  goto create_error;
242  }
243 #else
244  /*
245  * Alternative functions for libpcap < 1.0
246  */
247  pcap->handle = pcap_open_live(pcap->name, SNAPLEN, pcap->promiscuous, PCAP_NONBLOCK_TIMEOUT,
248  pcap->errbuf);
249  if (!pcap->handle) {
250  fr_strerror_printf("%s", pcap->errbuf);
251  return -1;
252  }
253 #endif
254 
255  /*
256  * Do this later so we get real errors from libpcap,
257  * when bad interfaces are passed in.
258  */
259  if (fr_pcap_mac_addr((uint8_t *)&pcap->ether_addr, pcap->name) != 0) {
260  fr_strerror_printf("Couldn't get MAC address for interface %s", pcap->name);
261  pcap_close(pcap->handle);
262  return -1;
263  }
264 
265  /*
266  * Despite accepting an errbuff, pcap_setnonblock doesn't seem to write
267  * error message there in newer versions.
268  */
269  if (pcap_setnonblock(pcap->handle, true, pcap->errbuf) != 0) {
270  fr_strerror_printf("%s", *pcap->errbuf != '\0' ?
271  pcap->errbuf : pcap_geterr(pcap->handle));
272  pcap_close(pcap->handle);
273  pcap->handle = NULL;
274  return -1;
275  }
276 
277  pcap->fd = pcap_get_selectable_fd(pcap->handle);
278  pcap->link_layer = pcap_datalink(pcap->handle);
279 #ifndef __linux__
280  {
281  int value = 1;
282  if (ioctl(pcap->fd, BIOCIMMEDIATE, &value) < 0) {
283  fr_strerror_printf("Failed setting BIOCIMMEDIATE: %s", fr_syserror(errno));
284  }
285  }
286 #endif
287  }
288  break;
289 
290  case PCAP_FILE_IN:
291  pcap->handle = pcap_open_offline(pcap->name, pcap->errbuf);
292  if (!pcap->handle) {
293  fr_strerror_printf("%s", pcap->errbuf);
294 
295  return -1;
296  }
297  pcap->fd = pcap_get_selectable_fd(pcap->handle);
298  pcap->link_layer = pcap_datalink(pcap->handle);
299  break;
300 
301  case PCAP_FILE_OUT:
302  if (pcap->link_layer < 0) {
303  pcap->link_layer = DLT_EN10MB;
304  }
305  pcap->handle = pcap_open_dead(pcap->link_layer, SNAPLEN);
306  if (!pcap->handle) {
307  fr_strerror_const("Unknown error occurred opening dead PCAP handle");
308 
309  return -1;
310  }
311  pcap->dumper = pcap_dump_open(pcap->handle, pcap->name);
312  if (!pcap->dumper) {
313  fr_strerror_printf("%s", pcap_geterr(pcap->handle));
314 
315  return -1;
316  }
317  break;
318 
319 #ifdef HAVE_PCAP_FOPEN_OFFLINE
320  case PCAP_STDIO_IN:
321  pcap->handle = pcap_fopen_offline(stdin, pcap->errbuf);
322  if (!pcap->handle) {
323  fr_strerror_printf("%s", pcap->errbuf);
324 
325  return -1;
326  }
327  pcap->fd = pcap_get_selectable_fd(pcap->handle);
328  pcap->link_layer = pcap_datalink(pcap->handle);
329  break;
330 #else
331  case PCAP_STDIO_IN:
332  fr_strerror_const("This version of libpcap does not support reading pcap data from streams");
333 
334  return -1;
335 #endif
336 #ifdef HAVE_PCAP_DUMP_FOPEN
337  case PCAP_STDIO_OUT:
338  pcap->handle = pcap_open_dead(DLT_EN10MB, SNAPLEN);
339  pcap->dumper = pcap_dump_fopen(pcap->handle, stdout);
340  if (!pcap->dumper) {
341  fr_strerror_printf("%s", pcap_geterr(pcap->handle));
342 
343  return -1;
344  }
345  break;
346 #else
347  case PCAP_STDIO_OUT:
348  fr_strerror_const("This version of libpcap does not support writing pcap data to streams");
349 
350  return -1;
351 #endif
352  case PCAP_INVALID:
353  default:
354  (void)fr_cond_assert(0);
355  fr_strerror_printf("Bad handle type (%i)", pcap->type);
356  return -1;
357  }
358 
359  return 0;
360 }
361 
362 /** Apply capture filter to an interface
363  *
364  * @param pcap handle to apply filter to.
365  * @param expression PCAP expression to use as a filter.
366  * @return
367  * - 0 on success.
368  * - 1 can't apply to interface.
369  * - -1 on failure.
370  */
371 int fr_pcap_apply_filter(fr_pcap_t *pcap, char const *expression)
372 {
373  bpf_u_int32 mask = 0; /* Our netmask */
374  bpf_u_int32 net = 0; /* Our IP */
375  struct bpf_program fp;
376 
377  /*
378  * nflog devices are in the set of devices selected by default.
379  * Unfortunately there's a bug in all released version of libpcap (as of 2/1/2014)
380  * which triggers an abort if pcap_setfilter is called on an nflog interface.
381  *
382  * See here:
383  * https://github.com/the-tcpdump-group/libpcap/commit/676cf8a61ed240d0a86d471ef419f45ba35dba80
384  */
385 #ifdef DLT_NFLOG
386  if (pcap->link_layer == DLT_NFLOG) {
387  fr_strerror_const("NFLOG link-layer type filtering not implemented");
388 
389  return 1;
390  }
391 #endif
392 
393  if (pcap->type == PCAP_INTERFACE_IN || pcap->type == PCAP_INTERFACE_IN_OUT) {
394  if (pcap_lookupnet(pcap->name, &net, &mask, pcap->errbuf) < 0) {
395  fr_strerror_printf("Failed getting IP for interface \"%s\", using defaults: %s",
396  pcap->name, pcap->errbuf);
397  }
398  }
399 
400  if (pcap_compile(pcap->handle, &fp, expression, 0, net) < 0) {
401  fr_strerror_printf("%s", pcap_geterr(pcap->handle));
402 
403  return -1;
404  }
405 
406  if (pcap_setfilter(pcap->handle, &fp) < 0) {
407  pcap_freecode(&fp);
408 
409  fr_strerror_printf("%s", pcap_geterr(pcap->handle));
410  return -1;
411  }
412 
413  pcap_freecode(&fp); /* Free the filter, it's not longer needed after its been applied */
414 
415  return 0;
416 }
417 
418 /** Retrieve list of interface names that will be used for capture.
419  * Only used for debugging.
420  *
421  * @param ctx talloc context for allicating string.
422  * @param pcap handle list.
423  * @param c separator to use for list.
424  * @return
425  * - string buffer.
426  */
427 char *fr_pcap_device_names(TALLOC_CTX *ctx, fr_pcap_t *pcap, char c)
428 {
429  fr_pcap_t *pcap_p;
430  char *buff, *p, *end;
431  size_t len = 0;
432 
433  if (!pcap) {
434  null:
435  return talloc_zero_array(ctx, char, 1);
436  }
437 
438  for (pcap_p = pcap;
439  pcap_p;
440  pcap_p = pcap_p->next) {
441  /*
442  * talloc_array_length includes \0 which accounts for c
443  */
444  len += talloc_array_length(pcap_p->name);
445  }
446 
447  if (!len) goto null;
448 
449  buff = p = talloc_zero_array(ctx, char, len);
450  end = p + len;
451 
452  for (pcap_p = pcap;
453  pcap_p;
454  pcap_p = pcap_p->next) {
455  size_t name_len = talloc_array_length(pcap_p->name) - 1;
456 
457  if (!fr_cond_assert(p < end)) {
458  talloc_free(buff);
459  return NULL;
460  }
461 
462  memcpy(p, pcap_p->name, name_len);
463  p += name_len;
464  *p++ = c;
465  }
466  *(end - 1) = '\0'; /* Strip trailing separation char */
467 
468  return buff;
469 }
470 
471 
472 /** Check whether fr_pcap_link_layer_offset can process a link_layer
473  *
474  * @param link_layer to check.
475  * @return
476  * - true if supported.
477  * - false if not supported.
478  */
479 bool fr_pcap_link_layer_supported(int link_layer)
480 {
481  switch (link_layer) {
482  case DLT_EN10MB:
483  case DLT_RAW:
484  case DLT_NULL:
485  case DLT_LOOP:
486 #ifdef DLT_LINUX_SLL
487  case DLT_LINUX_SLL:
488 #endif
489 #ifdef DLT_LINUX_SLL2
490  case DLT_LINUX_SLL2:
491 #endif
492  case DLT_PFLOG:
493  return true;
494 
495  default:
496  return false;
497  }
498 }
499 
500 /** Returns the length of the link layer header
501  *
502  * Libpcap does not include a decoding function to skip the L2 header, but it does
503  * at least inform us of the type.
504  *
505  * Unfortunately some headers are of variable length (like ethernet), so additional
506  * decoding logic is required.
507  *
508  * @note No header data is returned, this is only meant to be used to determine how
509  * data to consume before attempting to parse the IP header.
510  *
511  * @param data start of packet data.
512  * @param len caplen.
513  * @param link_layer value returned from pcap_linktype.
514  * @return
515  * - Length of the header.
516  * - -1 on failure.
517  */
518 ssize_t fr_pcap_link_layer_offset(uint8_t const *data, size_t len, int link_layer)
519 {
520  uint8_t const *p = data;
521 
522  switch (link_layer) {
523  case DLT_RAW:
524  break;
525 
526  case DLT_NULL:
527  case DLT_LOOP:
528  p += 4;
529  if (((size_t)(p - data)) > len) {
530  ood:
531  fr_strerror_printf("Out of data, needed %zu bytes, have %zu bytes",
532  (size_t)(p - data), len);
533  return -1;
534  }
535  break;
536 
537  case DLT_EN10MB:
538  {
539  uint16_t ether_type; /* Ethernet type */
540  int i;
541 
542  p += 12; /* SRC/DST Mac-Addresses */
543  if (((size_t)(p - data)) > len) {
544  goto ood;
545  }
546 
547  for (i = 0; i < 3; i++) {
548  ether_type = ntohs(*((uint16_t const *) p));
549  switch (ether_type) {
550  /*
551  * There are a number of devices out there which
552  * double tag with 0x8100 *sigh*
553  */
554  case 0x8100: /* CVLAN */
555  case 0x9100: /* SVLAN */
556  case 0x9200: /* SVLAN */
557  case 0x9300: /* SVLAN */
558  p += 4;
559  if (((size_t)(p - data)) > len) {
560  goto ood;
561  }
562  break;
563 
564  default:
565  p += 2;
566  if (((size_t)(p - data)) > len) {
567  goto ood;
568  }
569  goto done;
570  }
571  }
572  fr_strerror_const("Exceeded maximum level of VLAN tag nesting (2)");
573  return -1;
574  }
575 
576 #ifdef DLT_LINUX_SLL
577  case DLT_LINUX_SLL:
578  p += 16;
579  if (((size_t)(p - data)) > len) {
580  goto ood;
581  }
582  break;
583 #endif
584 
585 #ifdef DLT_LINUX_SLL2
586  case DLT_LINUX_SLL2:
587  p += 20;
588  if (((size_t)(p - data)) > len) {
589  goto ood;
590  }
591  break;
592 #endif
593 
594  case DLT_PFLOG:
595  p += 28;
596  if (((size_t)(p - data)) > len) {
597  goto ood;
598  }
599  break;
600 
601  default:
602  fr_strerror_printf("Unsupported link layer type %i", link_layer);
603  return -1;
604  }
605 
606 done:
607  return p - data;
608 }
609 #endif /* HAVE_LIBPCAP */
#define fr_cond_assert(_x)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
Definition: debug.h:139
Test enumeration values.
Definition: dict_test.h:92
#define AF_LINK
Definition: inet.c:1615
talloc_free(reap)
unsigned short uint16_t
Definition: merged_model.c:31
long int ssize_t
Definition: merged_model.c:24
unsigned char uint8_t
Definition: merged_model.c:30
#define ETHER_ADDR_LEN
Definition: net.h:64
@ DLT_LOOP
Definition: net.h:54
@ DLT_NULL
Definition: net.h:53
@ DLT_LINUX_SLL
Definition: net.h:56
@ DLT_PFLOG
Definition: net.h:57
@ DLT_EN10MB
Definition: net.h:55
@ DLT_RAW
Definition: net.h:52
static bool done
Definition: radclient.c:80
static uint32_t mask
Definition: rbmonkey.c:39
static char const * name
static char buff[sizeof("18446744073709551615")+3]
Definition: size_tests.c:41
fr_aka_sim_id_type_t type
size_t strlcpy(char *dst, char const *src, size_t siz)
Definition: strlcpy.c:34
char const * fr_syserror(int num)
Guaranteed to be thread-safe version of strerror.
Definition: syserror.c:243
char * talloc_typed_strdup(TALLOC_CTX *ctx, char const *p)
Call talloc_strdup, setting the type on the new chunk correctly.
Definition: talloc.c:445
close(uq->fd)
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.
Definition: strerror.h:64
#define fr_strerror_const(_msg)
Definition: strerror.h:223
static fr_slen_t data
Definition: value.h:1265