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>
32 #include <sys/ioctl.h>
37 # ifdef HAVE_NET_IF_DL_H
38 # include <net/if_dl.h>
50 static int _free_pcap(fr_pcap_t *pcap)
53 case PCAP_INTERFACE_IN:
54 case PCAP_INTERFACE_OUT:
55 case PCAP_INTERFACE_IN_OUT:
59 pcap_close(pcap->handle);
70 pcap_dump_flush(pcap->dumper);
71 pcap_dump_close(pcap->dumper);
93 int fr_pcap_if_link_layer(pcap_if_t *dev)
95 char errbuf[PCAP_ERRBUF_SIZE];
99 pcap = pcap_open_live(dev->name, 0, 0, 0, errbuf);
105 data_link = pcap_datalink(pcap);
118 fr_pcap_t *fr_pcap_init(TALLOC_CTX *ctx,
char const *
name, fr_pcap_type_t
type)
127 this = talloc_zero(ctx, fr_pcap_t);
128 if (!
this)
return NULL;
130 talloc_set_destructor(
this, _free_pcap);
133 this->link_layer = -1;
146 int fr_pcap_mac_addr(
uint8_t *macaddr,
char *ifname)
148 #ifndef SIOCGIFHWADDR
149 struct ifaddrs *ifap, *ifaptr;
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);
161 return (ifaptr != NULL ? 0 : -1);
168 fd = socket(AF_INET, SOCK_DGRAM, 0);
174 ifr.ifr_addr.sa_family = AF_INET;
175 strlcpy(ifr.ifr_name, ifname , IFNAMSIZ-1);
177 ret = ioctl(fd, SIOCGIFHWADDR, &ifr);
197 int fr_pcap_open(fr_pcap_t *pcap)
199 switch (pcap->type) {
200 case PCAP_INTERFACE_OUT:
201 case PCAP_INTERFACE_IN:
202 case PCAP_INTERFACE_IN_OUT:
210 pcap->ifindex = if_nametoindex(pcap->name);
211 if (!pcap->ifindex) {
216 #if defined(HAVE_PCAP_CREATE) && defined(HAVE_PCAP_ACTIVATE)
217 pcap->handle = pcap_create(pcap->name, pcap->errbuf);
222 if (pcap_set_snaplen(pcap->handle, SNAPLEN) != 0) {
225 pcap_close(pcap->handle);
229 if (pcap_set_timeout(pcap->handle, PCAP_NONBLOCK_TIMEOUT) != 0) {
232 if (pcap_set_promisc(pcap->handle, pcap->promiscuous) != 0) {
236 if (pcap_set_buffer_size(pcap->handle, SNAPLEN *
237 (pcap->buffer_pkts ? pcap->buffer_pkts : PCAP_BUFFER_DEFAULT)) != 0) {
240 if (pcap_activate(pcap->handle) != 0) {
247 pcap->handle = pcap_open_live(pcap->name, SNAPLEN, pcap->promiscuous, PCAP_NONBLOCK_TIMEOUT,
259 if (fr_pcap_mac_addr((
uint8_t *)&pcap->ether_addr, pcap->name) != 0) {
261 pcap_close(pcap->handle);
269 if (pcap_setnonblock(pcap->handle,
true, pcap->errbuf) != 0) {
271 pcap->errbuf : pcap_geterr(pcap->handle));
272 pcap_close(pcap->handle);
277 pcap->fd = pcap_get_selectable_fd(pcap->handle);
278 pcap->link_layer = pcap_datalink(pcap->handle);
282 if (ioctl(pcap->fd, BIOCIMMEDIATE, &
value) < 0) {
291 pcap->handle = pcap_open_offline(pcap->name, pcap->errbuf);
297 pcap->fd = pcap_get_selectable_fd(pcap->handle);
298 pcap->link_layer = pcap_datalink(pcap->handle);
302 if (pcap->link_layer < 0) {
305 pcap->handle = pcap_open_dead(pcap->link_layer, SNAPLEN);
311 pcap->dumper = pcap_dump_open(pcap->handle, pcap->name);
319 #ifdef HAVE_PCAP_FOPEN_OFFLINE
321 pcap->handle = pcap_fopen_offline(stdin, pcap->errbuf);
327 pcap->fd = pcap_get_selectable_fd(pcap->handle);
328 pcap->link_layer = pcap_datalink(pcap->handle);
332 fr_strerror_const(
"This version of libpcap does not support reading pcap data from streams");
336 #ifdef HAVE_PCAP_DUMP_FOPEN
338 pcap->handle = pcap_open_dead(
DLT_EN10MB, SNAPLEN);
339 pcap->dumper = pcap_dump_fopen(pcap->handle, stdout);
348 fr_strerror_const(
"This version of libpcap does not support writing pcap data to streams");
371 int fr_pcap_apply_filter(fr_pcap_t *pcap,
char const *expression)
373 bpf_u_int32
mask = 0;
375 struct bpf_program fp;
386 if (pcap->link_layer == DLT_NFLOG) {
393 if (pcap->type == PCAP_INTERFACE_IN || pcap->type == PCAP_INTERFACE_IN_OUT) {
394 if (pcap_lookupnet(pcap->name, &net, &
mask, pcap->errbuf) < 0) {
396 pcap->name, pcap->errbuf);
400 if (pcap_compile(pcap->handle, &fp, expression, 0, net) < 0) {
406 if (pcap_setfilter(pcap->handle, &fp) < 0) {
427 char *fr_pcap_device_names(TALLOC_CTX *ctx, fr_pcap_t *pcap,
char c)
430 char *
buff, *p, *end;
435 return talloc_zero_array(ctx,
char, 1);
440 pcap_p = pcap_p->next) {
444 len += talloc_array_length(pcap_p->name);
449 buff = p = talloc_zero_array(ctx,
char, len);
454 pcap_p = pcap_p->next) {
455 size_t name_len = talloc_array_length(pcap_p->name) - 1;
462 memcpy(p, pcap_p->name, name_len);
479 bool fr_pcap_link_layer_supported(
int link_layer)
481 switch (link_layer) {
489 #ifdef DLT_LINUX_SLL2
522 switch (link_layer) {
529 if (((
size_t)(p -
data)) > len) {
532 (
size_t)(p -
data), len);
543 if (((
size_t)(p -
data)) > len) {
547 for (i = 0; i < 3; i++) {
548 ether_type = ntohs(*((
uint16_t const *) p));
549 switch (ether_type) {
559 if (((
size_t)(p -
data)) > len) {
566 if (((
size_t)(p -
data)) > len) {
579 if (((
size_t)(p -
data)) > len) {
585 #ifdef DLT_LINUX_SLL2
588 if (((
size_t)(p -
data)) > len) {
596 if (((
size_t)(p -
data)) > len) {
#define fr_cond_assert(_x)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
static char buff[sizeof("18446744073709551615")+3]
fr_aka_sim_id_type_t type
size_t strlcpy(char *dst, char const *src, size_t siz)
char const * fr_syserror(int num)
Guaranteed to be thread-safe version of strerror.
char * talloc_typed_strdup(TALLOC_CTX *ctx, char const *p)
Call talloc_strdup, setting the type on the new chunk correctly.
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.
#define fr_strerror_const(_msg)