blob: 08882561819b1044279b3d71326ea3067c9d0ae3 [file] [log] [blame]
/*
*
* (C) 2005-12 - Luca Deri <deri@ntop.org>
* Alfredo Cardigliano <cardigliano@ntop.org>
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lessed General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
*
*/
#include "pfring.h"
#include "pfring_utils.h"
#include <linux/if.h>
#ifdef ENABLE_HW_TIMESTAMP
#include <linux/net_tstamp.h>
#endif
/* ******************************* */
int pfring_enable_hw_timestamp(pfring* ring, char *device_name, u_int8_t enable_rx, u_int8_t enable_tx) {
#ifdef ENABLE_HW_TIMESTAMP
struct hwtstamp_config hwconfig;
struct ifreq ifr;
int rc, sock_fd;
sock_fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
if(sock_fd <= 0) return(-1);
memset(&hwconfig, 0, sizeof(hwconfig));
hwconfig.rx_filter = (enable_rx ? HWTSTAMP_FILTER_ALL : HWTSTAMP_FILTER_NONE);
hwconfig.tx_type = (enable_tx ? HWTSTAMP_TX_ON : HWTSTAMP_TX_OFF);
memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_name, device_name, sizeof(ifr.ifr_name)-1);
ifr.ifr_data = (void *)&hwconfig;
rc = ioctl(sock_fd, SIOCSHWTSTAMP, &ifr);
if(rc < 0)
rc = errno;
else
rc = 0;
#ifdef RING_DEBUG
printf("pfring_enable_hw_timestamp(%s) returned %d\n", device_name, rc);
#endif
close(sock_fd);
return(rc);
#else
return(-1);
#endif
}
/* ******************************* */
static u_int32_t pfring_hash_pkt(struct pfring_pkthdr *hdr) {
if (hdr->extended_hdr.parsed_pkt.tunnel.tunnel_id == NO_TUNNEL_ID) {
return
hdr->extended_hdr.parsed_pkt.vlan_id +
hdr->extended_hdr.parsed_pkt.l3_proto +
hdr->extended_hdr.parsed_pkt.ip_src.v6.s6_addr32[0] +
hdr->extended_hdr.parsed_pkt.ip_src.v6.s6_addr32[1] +
hdr->extended_hdr.parsed_pkt.ip_src.v6.s6_addr32[2] +
hdr->extended_hdr.parsed_pkt.ip_src.v6.s6_addr32[3] +
hdr->extended_hdr.parsed_pkt.ip_dst.v6.s6_addr32[0] +
hdr->extended_hdr.parsed_pkt.ip_dst.v6.s6_addr32[1] +
hdr->extended_hdr.parsed_pkt.ip_dst.v6.s6_addr32[2] +
hdr->extended_hdr.parsed_pkt.ip_dst.v6.s6_addr32[3] +
hdr->extended_hdr.parsed_pkt.l4_src_port +
hdr->extended_hdr.parsed_pkt.l4_dst_port;
} else {
return
hdr->extended_hdr.parsed_pkt.vlan_id +
hdr->extended_hdr.parsed_pkt.tunnel.tunneled_proto +
hdr->extended_hdr.parsed_pkt.tunnel.tunneled_ip_src.v6.s6_addr32[1] +
hdr->extended_hdr.parsed_pkt.tunnel.tunneled_ip_src.v6.s6_addr32[2] +
hdr->extended_hdr.parsed_pkt.tunnel.tunneled_ip_src.v6.s6_addr32[3] +
hdr->extended_hdr.parsed_pkt.tunnel.tunneled_ip_dst.v6.s6_addr32[0] +
hdr->extended_hdr.parsed_pkt.tunnel.tunneled_ip_dst.v6.s6_addr32[1] +
hdr->extended_hdr.parsed_pkt.tunnel.tunneled_ip_dst.v6.s6_addr32[2] +
hdr->extended_hdr.parsed_pkt.tunnel.tunneled_ip_dst.v6.s6_addr32[3] +
hdr->extended_hdr.parsed_pkt.tunnel.tunneled_l4_src_port +
hdr->extended_hdr.parsed_pkt.tunnel.tunneled_l4_dst_port;
}
}
/* ******************************* */
static int __pfring_parse_tunneled_pkt(u_char *pkt, struct pfring_pkthdr *hdr, u_int16_t ip_version, u_int16_t tunnel_offset) {
u_int32_t ip_len = 0;
u_int16_t fragment_offset = 0;
if(ip_version == 4 /* IPv4 */ ) {
struct iphdr *tunneled_ip;
if(hdr->caplen < (tunnel_offset+sizeof(struct iphdr)))
return 0;
tunneled_ip = (struct iphdr *) (&pkt[tunnel_offset]);
hdr->extended_hdr.parsed_pkt.tunnel.tunneled_proto = tunneled_ip->protocol;
hdr->extended_hdr.parsed_pkt.tunnel.tunneled_ip_src.v4 = ntohl(tunneled_ip->saddr);
hdr->extended_hdr.parsed_pkt.tunnel.tunneled_ip_dst.v4 = ntohl(tunneled_ip->daddr);
fragment_offset = tunneled_ip->frag_off & htons(IP_OFFSET); /* fragment, but not the first */
ip_len = tunneled_ip->ihl*4;
tunnel_offset += ip_len;
} else if(ip_version == 6 /* IPv6 */ ) {
struct ipv6hdr *tunneled_ipv6;
if(hdr->caplen < (tunnel_offset+sizeof(struct ipv6hdr)))
return 0;
tunneled_ipv6 = (struct ipv6hdr *) (&pkt[tunnel_offset]);
hdr->extended_hdr.parsed_pkt.tunnel.tunneled_proto = tunneled_ipv6->nexthdr;
/* Values of IPv6 addresses are stored as network byte order */
memcpy(&hdr->extended_hdr.parsed_pkt.tunnel.tunneled_ip_src.v6, &tunneled_ipv6->saddr, sizeof(tunneled_ipv6->saddr));
memcpy(&hdr->extended_hdr.parsed_pkt.tunnel.tunneled_ip_dst.v6, &tunneled_ipv6->daddr, sizeof(tunneled_ipv6->daddr));
ip_len = sizeof(struct ipv6hdr);
while(hdr->extended_hdr.parsed_pkt.tunnel.tunneled_proto == NEXTHDR_HOP
|| hdr->extended_hdr.parsed_pkt.tunnel.tunneled_proto == NEXTHDR_DEST
|| hdr->extended_hdr.parsed_pkt.tunnel.tunneled_proto == NEXTHDR_ROUTING
|| hdr->extended_hdr.parsed_pkt.tunnel.tunneled_proto == NEXTHDR_AUTH
|| hdr->extended_hdr.parsed_pkt.tunnel.tunneled_proto == NEXTHDR_ESP
|| hdr->extended_hdr.parsed_pkt.tunnel.tunneled_proto == NEXTHDR_FRAGMENT) {
struct ipv6_opt_hdr *ipv6_opt;
if(hdr->caplen < (tunnel_offset+ip_len+sizeof(struct ipv6_opt_hdr))) return 1;
ipv6_opt = (struct ipv6_opt_hdr *)(&pkt[tunnel_offset+ip_len]);
ip_len += sizeof(struct ipv6_opt_hdr), fragment_offset = 0;
if(hdr->extended_hdr.parsed_pkt.tunnel.tunneled_proto == NEXTHDR_AUTH)
/*
RFC4302 2.2. Payload Length: This 8-bit field specifies the
length of AH in 32-bit words (4-byte units), minus "2".
*/
ip_len += ipv6_opt->hdrlen * 4;
else if(hdr->extended_hdr.parsed_pkt.tunnel.tunneled_proto != NEXTHDR_FRAGMENT)
ip_len += ipv6_opt->hdrlen;
hdr->extended_hdr.parsed_pkt.tunnel.tunneled_proto = ipv6_opt->nexthdr;
} /* while */
tunnel_offset += ip_len;
} else
return 0;
if (fragment_offset)
return 1;
if(hdr->extended_hdr.parsed_pkt.tunnel.tunneled_proto == IPPROTO_TCP) {
struct tcphdr *tcp;
if(hdr->caplen < tunnel_offset + sizeof(struct tcphdr))
return 1;
tcp = (struct tcphdr *)(&pkt[tunnel_offset]);
hdr->extended_hdr.parsed_pkt.tunnel.tunneled_l4_src_port = ntohs(tcp->source),
hdr->extended_hdr.parsed_pkt.tunnel.tunneled_l4_dst_port = ntohs(tcp->dest);
} else if(hdr->extended_hdr.parsed_pkt.tunnel.tunneled_proto == IPPROTO_UDP) {
struct udphdr *udp;
if(hdr->caplen < tunnel_offset + sizeof(struct udphdr))
return 1;
udp = (struct udphdr *)(&pkt[tunnel_offset]);
hdr->extended_hdr.parsed_pkt.tunnel.tunneled_l4_src_port = ntohs(udp->source),
hdr->extended_hdr.parsed_pkt.tunnel.tunneled_l4_dst_port = ntohs(udp->dest);
}
return 2;
}
/* ******************************* */
int pfring_parse_pkt(u_char *pkt, struct pfring_pkthdr *hdr, u_int8_t level /* L2..L4, 5 (tunnel) */,
u_int8_t add_timestamp /* 0,1 */, u_int8_t add_hash /* 0,1 */) {
struct ethhdr *eh = (struct ethhdr*) pkt;
u_int32_t displ = 0, ip_len;
u_int16_t analyzed = 0, fragment_offset = 0;
hdr->extended_hdr.parsed_pkt.tunnel.tunnel_id = NO_TUNNEL_ID;
/* Note: in order to optimize the computation, this function expects a zero-ed
* or partially parsed pkthdr */
//memset(&hdr->extended_hdr.parsed_pkt, 0, sizeof(struct pkt_parsing_info));
//hdr->extended_hdr.parsed_header_len = 0;
if (hdr->extended_hdr.parsed_pkt.offset.l3_offset != 0)
goto L3;
memcpy(&hdr->extended_hdr.parsed_pkt.dmac, eh->h_dest, sizeof(eh->h_dest));
memcpy(&hdr->extended_hdr.parsed_pkt.smac, eh->h_source, sizeof(eh->h_source));
hdr->extended_hdr.parsed_pkt.eth_type = ntohs(eh->h_proto);
hdr->extended_hdr.parsed_pkt.offset.eth_offset = 0;
hdr->extended_hdr.parsed_pkt.offset.vlan_offset = 0;
hdr->extended_hdr.parsed_pkt.vlan_id = 0; /* Any VLAN */
if (hdr->extended_hdr.parsed_pkt.eth_type == 0x8100 /* 802.1q (VLAN) */) {
struct eth_vlan_hdr *vh;
hdr->extended_hdr.parsed_pkt.offset.vlan_offset = sizeof(struct ethhdr) - sizeof(struct eth_vlan_hdr);
while (hdr->extended_hdr.parsed_pkt.eth_type == 0x8100 /* 802.1q (VLAN) */ ) {
hdr->extended_hdr.parsed_pkt.offset.vlan_offset += sizeof(struct eth_vlan_hdr);
vh = (struct eth_vlan_hdr *) &pkt[hdr->extended_hdr.parsed_pkt.offset.vlan_offset];
hdr->extended_hdr.parsed_pkt.vlan_id = ntohs(vh->h_vlan_id) & 0x0fff;
hdr->extended_hdr.parsed_pkt.eth_type = ntohs(vh->h_proto);
displ += sizeof(struct eth_vlan_hdr);
}
}
hdr->extended_hdr.parsed_pkt.offset.l3_offset = hdr->extended_hdr.parsed_pkt.offset.eth_offset + displ + sizeof(struct ethhdr);
L3:
analyzed = 2;
if (level < 3)
goto TIMESTAMP;
if (hdr->extended_hdr.parsed_pkt.offset.l4_offset != 0)
goto L4;
if (hdr->extended_hdr.parsed_pkt.eth_type == 0x0800 /* IPv4 */) {
struct iphdr *ip;
hdr->extended_hdr.parsed_pkt.ip_version = 4;
if (hdr->caplen < hdr->extended_hdr.parsed_pkt.offset.l3_offset + sizeof(struct iphdr))
goto TIMESTAMP;
ip = (struct iphdr *)(&pkt[hdr->extended_hdr.parsed_pkt.offset.l3_offset]);
hdr->extended_hdr.parsed_pkt.ipv4_src = ntohl(ip->saddr);
hdr->extended_hdr.parsed_pkt.ipv4_dst = ntohl(ip->daddr);
hdr->extended_hdr.parsed_pkt.l3_proto = ip->protocol;
hdr->extended_hdr.parsed_pkt.ipv4_tos = ip->tos;
fragment_offset = ip->frag_off & htons(IP_OFFSET); /* fragment, but not the first */
ip_len = ip->ihl*4;
} else if(hdr->extended_hdr.parsed_pkt.eth_type == 0x86DD /* IPv6 */) {
struct ipv6hdr *ipv6;
hdr->extended_hdr.parsed_pkt.ip_version = 6;
if(hdr->caplen < hdr->extended_hdr.parsed_pkt.offset.l3_offset + sizeof(struct ipv6hdr))
goto TIMESTAMP;
ipv6 = (struct ipv6hdr*)(&pkt[hdr->extended_hdr.parsed_pkt.offset.l3_offset]);
ip_len = sizeof(struct ipv6hdr);
/* Values of IPv6 addresses are stored as network byte order */
memcpy(&hdr->extended_hdr.parsed_pkt.ipv6_src, &ipv6->saddr, sizeof(ipv6->saddr));
memcpy(&hdr->extended_hdr.parsed_pkt.ipv6_dst, &ipv6->daddr, sizeof(ipv6->daddr));
hdr->extended_hdr.parsed_pkt.l3_proto = ipv6->nexthdr;
hdr->extended_hdr.parsed_pkt.ipv6_tos = ipv6->priority; /* IPv6 class of service */
while(hdr->extended_hdr.parsed_pkt.l3_proto == NEXTHDR_HOP ||
hdr->extended_hdr.parsed_pkt.l3_proto == NEXTHDR_DEST ||
hdr->extended_hdr.parsed_pkt.l3_proto == NEXTHDR_ROUTING ||
hdr->extended_hdr.parsed_pkt.l3_proto == NEXTHDR_AUTH ||
hdr->extended_hdr.parsed_pkt.l3_proto == NEXTHDR_ESP ||
hdr->extended_hdr.parsed_pkt.l3_proto == NEXTHDR_FRAGMENT) {
struct ipv6_opt_hdr *ipv6_opt;
if(hdr->caplen < hdr->extended_hdr.parsed_pkt.offset.l3_offset + ip_len + sizeof(struct ipv6_opt_hdr))
goto TIMESTAMP;
ipv6_opt = (struct ipv6_opt_hdr *)(&pkt[hdr->extended_hdr.parsed_pkt.offset.l3_offset + ip_len]);
ip_len += sizeof(struct ipv6_opt_hdr);
if(hdr->extended_hdr.parsed_pkt.l3_proto == NEXTHDR_AUTH)
/*
RFC4302 2.2. Payload Length: This 8-bit field specifies the
length of AH in 32-bit words (4-byte units), minus "2".
*/
ip_len += ipv6_opt->hdrlen * 4;
else if(hdr->extended_hdr.parsed_pkt.l3_proto != NEXTHDR_FRAGMENT)
ip_len += ipv6_opt->hdrlen;
hdr->extended_hdr.parsed_pkt.l3_proto = ipv6_opt->nexthdr;
}
} else {
hdr->extended_hdr.parsed_pkt.l3_proto = 0;
goto TIMESTAMP;
}
hdr->extended_hdr.parsed_pkt.offset.l4_offset = hdr->extended_hdr.parsed_pkt.offset.l3_offset + ip_len;
L4:
analyzed = 3;
if (level < 4 || fragment_offset)
goto TIMESTAMP;
if(hdr->extended_hdr.parsed_pkt.l3_proto == IPPROTO_TCP) {
struct tcphdr *tcp;
if(hdr->caplen < hdr->extended_hdr.parsed_pkt.offset.l4_offset + sizeof(struct tcphdr))
goto TIMESTAMP;
tcp = (struct tcphdr *)(&pkt[hdr->extended_hdr.parsed_pkt.offset.l4_offset]);
hdr->extended_hdr.parsed_pkt.l4_src_port = ntohs(tcp->source);
hdr->extended_hdr.parsed_pkt.l4_dst_port = ntohs(tcp->dest);
hdr->extended_hdr.parsed_pkt.offset.payload_offset = hdr->extended_hdr.parsed_pkt.offset.l4_offset + (tcp->doff * 4);
hdr->extended_hdr.parsed_pkt.tcp.seq_num = ntohl(tcp->seq);
hdr->extended_hdr.parsed_pkt.tcp.ack_num = ntohl(tcp->ack_seq);
hdr->extended_hdr.parsed_pkt.tcp.flags = (tcp->fin * TH_FIN_MULTIPLIER) + (tcp->syn * TH_SYN_MULTIPLIER) +
(tcp->rst * TH_RST_MULTIPLIER) + (tcp->psh * TH_PUSH_MULTIPLIER) +
(tcp->ack * TH_ACK_MULTIPLIER) + (tcp->urg * TH_URG_MULTIPLIER);
analyzed = 4;
} else if(hdr->extended_hdr.parsed_pkt.l3_proto == IPPROTO_UDP) {
struct udphdr *udp;
if(hdr->caplen < hdr->extended_hdr.parsed_pkt.offset.l4_offset + sizeof(struct udphdr))
goto TIMESTAMP;
udp = (struct udphdr *)(&pkt[hdr->extended_hdr.parsed_pkt.offset.l4_offset]);
hdr->extended_hdr.parsed_pkt.l4_src_port = ntohs(udp->source), hdr->extended_hdr.parsed_pkt.l4_dst_port = ntohs(udp->dest);
hdr->extended_hdr.parsed_pkt.offset.payload_offset = hdr->extended_hdr.parsed_pkt.offset.l4_offset + sizeof(struct udphdr);
analyzed = 4;
if (level < 5)
goto TIMESTAMP;
/* GTPv1 */
if((hdr->extended_hdr.parsed_pkt.l4_src_port == GTP_SIGNALING_PORT) ||
(hdr->extended_hdr.parsed_pkt.l4_dst_port == GTP_SIGNALING_PORT) ||
(hdr->extended_hdr.parsed_pkt.l4_src_port == GTP_U_DATA_PORT) ||
(hdr->extended_hdr.parsed_pkt.l4_dst_port == GTP_U_DATA_PORT)) {
struct gtp_v1_hdr *gtp;
u_int16_t gtp_len;
if(hdr->caplen < (hdr->extended_hdr.parsed_pkt.offset.payload_offset+sizeof(struct gtp_v1_hdr)))
goto TIMESTAMP;
gtp = (struct gtp_v1_hdr *) (&pkt[hdr->extended_hdr.parsed_pkt.offset.payload_offset]);
gtp_len = sizeof(struct gtp_v1_hdr);
if(((gtp->flags & GTP_FLAGS_VERSION) >> GTP_FLAGS_VERSION_SHIFT) == GTP_VERSION_1) {
struct iphdr *tunneled_ip;
hdr->extended_hdr.parsed_pkt.tunnel.tunnel_id = ntohl(gtp->teid);
if((hdr->extended_hdr.parsed_pkt.l4_src_port == GTP_U_DATA_PORT) ||
(hdr->extended_hdr.parsed_pkt.l4_dst_port == GTP_U_DATA_PORT)) {
if(gtp->flags & (GTP_FLAGS_EXTENSION | GTP_FLAGS_SEQ_NUM | GTP_FLAGS_NPDU_NUM)) {
struct gtp_v1_opt_hdr *gtpopt;
if(hdr->caplen < (hdr->extended_hdr.parsed_pkt.offset.payload_offset+gtp_len+sizeof(struct gtp_v1_opt_hdr)))
goto TIMESTAMP;
gtpopt = (struct gtp_v1_opt_hdr *) (&pkt[hdr->extended_hdr.parsed_pkt.offset.payload_offset + gtp_len]);
gtp_len += sizeof(struct gtp_v1_opt_hdr);
if((gtp->flags & GTP_FLAGS_EXTENSION) && gtpopt->next_ext_hdr) {
struct gtp_v1_ext_hdr *gtpext;
u_int8_t *next_ext_hdr;
do {
if(hdr->caplen < (hdr->extended_hdr.parsed_pkt.offset.payload_offset+gtp_len +1/* 8bit len field */)) goto TIMESTAMP;
gtpext = (struct gtp_v1_ext_hdr *) (&pkt[hdr->extended_hdr.parsed_pkt.offset.payload_offset + gtp_len]);
gtp_len += (gtpext->len * GTP_EXT_HDR_LEN_UNIT_BYTES);
if(gtpext->len == 0 || hdr->caplen < (hdr->extended_hdr.parsed_pkt.offset.payload_offset+gtp_len)) goto TIMESTAMP;
next_ext_hdr = (u_int8_t *) (&pkt[hdr->extended_hdr.parsed_pkt.offset.payload_offset + gtp_len - 1/* 8bit next_ext_hdr field*/]);
} while (*next_ext_hdr);
}
}
if(hdr->caplen < (hdr->extended_hdr.parsed_pkt.offset.payload_offset + gtp_len + sizeof(struct iphdr)))
goto TIMESTAMP;
tunneled_ip = (struct iphdr *) (&pkt[hdr->extended_hdr.parsed_pkt.offset.payload_offset + gtp_len]);
analyzed += __pfring_parse_tunneled_pkt(pkt, hdr, tunneled_ip->version, hdr->extended_hdr.parsed_pkt.offset.payload_offset + gtp_len);
}
}
}
} else if(hdr->extended_hdr.parsed_pkt.l3_proto == IPPROTO_GRE /* 0x47 */) {
struct gre_header *gre = (struct gre_header*)(&pkt[hdr->extended_hdr.parsed_pkt.offset.l4_offset]);
int gre_offset;
gre->flags_and_version = ntohs(gre->flags_and_version);
gre->proto = ntohs(gre->proto);
gre_offset = sizeof(struct gre_header);
if((gre->flags_and_version & GRE_HEADER_VERSION) == 0) {
if(gre->flags_and_version & (GRE_HEADER_CHECKSUM | GRE_HEADER_ROUTING)) gre_offset += 4;
if(gre->flags_and_version & GRE_HEADER_KEY) {
u_int32_t *tunnel_id = (u_int32_t*)(&pkt[hdr->extended_hdr.parsed_pkt.offset.l4_offset+gre_offset]);
gre_offset += 4;
hdr->extended_hdr.parsed_pkt.tunnel.tunnel_id = ntohl(*tunnel_id);
}
if(gre->flags_and_version & GRE_HEADER_SEQ_NUM) gre_offset += 4;
hdr->extended_hdr.parsed_pkt.offset.payload_offset = hdr->extended_hdr.parsed_pkt.offset.l4_offset + gre_offset;
analyzed = 4;
if (level < 5)
goto TIMESTAMP;
if (gre->proto == ETH_P_IP /* IPv4 */ || gre->proto == ETH_P_IPV6 /* IPv6 */)
analyzed += __pfring_parse_tunneled_pkt(pkt, hdr, gre->proto == ETH_P_IP ? 4 : 6, hdr->extended_hdr.parsed_pkt.offset.payload_offset);
} else { /* TODO handle other GRE versions */
hdr->extended_hdr.parsed_pkt.offset.payload_offset = hdr->extended_hdr.parsed_pkt.offset.l4_offset;
}
} else {
hdr->extended_hdr.parsed_pkt.offset.payload_offset = hdr->extended_hdr.parsed_pkt.offset.l4_offset;
hdr->extended_hdr.parsed_pkt.l4_src_port = hdr->extended_hdr.parsed_pkt.l4_dst_port = 0;
}
TIMESTAMP:
if(add_timestamp && hdr->ts.tv_sec == 0)
gettimeofday(&hdr->ts, NULL); /* TODO What about using clock_gettime(CLOCK_REALTIME, ts) ? */
if (add_hash && hdr->extended_hdr.pkt_hash == 0)
hdr->extended_hdr.pkt_hash = pfring_hash_pkt(hdr);
return analyzed;
}
/* ******************************* */
static int pfring_promisc(const char *device, int set_promisc) {
int sock_fd, ret = 0;
struct ifreq ifr;
if(device == NULL) return(-3);
sock_fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
if(sock_fd <= 0) return(-1);
memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
if(ioctl(sock_fd, SIOCGIFFLAGS, &ifr) == -1) {
close(sock_fd);
return(-2);
}
ret = ifr.ifr_flags & IFF_PROMISC;
if(set_promisc) {
if(ret == 0) ifr.ifr_flags |= IFF_PROMISC;
} else {
/* Remove promisc */
if(ret != 0) ifr.ifr_flags &= ~IFF_PROMISC;
}
if(ioctl(sock_fd, SIOCSIFFLAGS, &ifr) == -1)
return(-1);
close(sock_fd);
return(ret);
}
/* ******************************* */
int pfring_set_if_promisc(const char *device, int set_promisc) {
char name_copy[256], *elem;
int ret = 0;
snprintf(name_copy, sizeof(name_copy), "%s", device);
elem = strtok(name_copy, ";,");
while(elem != NULL) {
char *at = strchr(elem, '@');
if(at != NULL) at[0] = '\0';
ret = pfring_promisc(elem, set_promisc);
if(ret < 0) return(ret);
elem = strtok(NULL, ";,");
}
return(ret);
}
/* *************************************** */
char* pfring_format_numbers(double val, char *buf, u_int buf_len, u_int8_t add_decimals) {
u_int a1 = ((u_long)val / 1000000000) % 1000;
u_int a = ((u_long)val / 1000000) % 1000;
u_int b = ((u_long)val / 1000) % 1000;
u_int c = (u_long)val % 1000;
u_int d = (u_int)((val - (u_long)val)*100) % 100;
if(add_decimals) {
if(val >= 1000000000) {
snprintf(buf, buf_len, "%u'%03u'%03u'%03u.%02d", a1, a, b, c, d);
} else if(val >= 1000000) {
snprintf(buf, buf_len, "%u'%03u'%03u.%02d", a, b, c, d);
} else if(val >= 100000) {
snprintf(buf, buf_len, "%u'%03u.%02d", b, c, d);
} else if(val >= 1000) {
snprintf(buf, buf_len, "%u'%03u.%02d", b, c, d);
} else
snprintf(buf, buf_len, "%.2f", val);
} else {
if(val >= 1000000000) {
snprintf(buf, buf_len, "%u'%03u'%03u'%03u", a1, a, b, c);
} else if(val >= 1000000) {
snprintf(buf, buf_len, "%u'%03u'%03u", a, b, c);
} else if(val >= 100000) {
snprintf(buf, buf_len, "%u'%03u", b, c);
} else if(val >= 1000) {
snprintf(buf, buf_len, "%u'%03u", b, c);
} else
snprintf(buf, buf_len, "%u", (unsigned int)val);
}
return(buf);
}
/* *************************************** */
int pfring_get_mtu_size(pfring* ring) {
struct ifreq ifr;
memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_name, ring->device_name, sizeof(ifr.ifr_name));
if(ioctl(ring->fd, SIOCGIFMTU, &ifr) == -1) {
return(0); /* Unknown for this device */
}
return(ifr.ifr_mtu);
}