blob: 12f55ec553eb0c93649d4cc58a5db2f2bf8115d2 [file] [log] [blame]
/*
* Copyright (c) 2018 Intel Corporation.
*
* SPDX-License-Identifier: Apache-2.0
*/
#define LOG_MODULE_NAME net_promisc
#define SYS_LOG_DOMAIN "promisc"
#define NET_SYS_LOG_LEVEL SYS_LOG_LEVEL_DEBUG
#define NET_LOG_ENABLED 1
#include <zephyr.h>
#include <errno.h>
#include <net/net_core.h>
#include <net/promiscuous.h>
#include <net/tcp.h>
static void iface_cb(struct net_if *iface, void *user_data)
{
int ret;
ret = net_promisc_mode_on(iface);
if (ret < 0) {
NET_INFO("Cannot set promiscuous mode for interface %p (%d)",
iface, ret);
return;
}
NET_INFO("Promiscuous mode enabled for interface %p", iface);
}
static int get_ports(struct net_pkt *pkt, u16_t *src, u16_t *dst)
{
struct net_tcp_hdr hdr, *tcp_hdr;
tcp_hdr = net_tcp_get_hdr(pkt, &hdr);
if (!tcp_hdr) {
return -EINVAL;
}
*src = ntohs(tcp_hdr->src_port);
*dst = ntohs(tcp_hdr->dst_port);
return 0;
}
static void print_info(struct net_pkt *pkt)
{
char src_addr_buf[NET_IPV6_ADDR_LEN], *src_addr;
char dst_addr_buf[NET_IPV6_ADDR_LEN], *dst_addr;
sa_family_t family = AF_UNSPEC;
void *dst, *src;
u16_t dst_port, src_port;
u8_t next_hdr;
const char *proto;
size_t len;
int ret;
switch (NET_IPV6_HDR(pkt)->vtc & 0xf0) {
case 0x60:
family = AF_INET6;
net_pkt_set_family(pkt, AF_INET6);
dst = &NET_IPV6_HDR(pkt)->dst;
src = &NET_IPV6_HDR(pkt)->src;
next_hdr = NET_IPV6_HDR(pkt)->nexthdr;
net_pkt_set_ip_hdr_len(pkt, sizeof(struct net_ipv6_hdr));
break;
case 0x40:
family = AF_INET;
net_pkt_set_family(pkt, AF_INET);
dst = &NET_IPV4_HDR(pkt)->dst;
src = &NET_IPV4_HDR(pkt)->src;
next_hdr = NET_IPV4_HDR(pkt)->proto;
net_pkt_set_ip_hdr_len(pkt, sizeof(struct net_ipv4_hdr));
break;
}
if (family == AF_UNSPEC) {
NET_INFO("Recv %p len %d (unknown address family)",
pkt, net_pkt_get_len(pkt));
return;
}
ret = 0;
switch (next_hdr) {
case IPPROTO_TCP:
proto = "TCP";
ret = get_ports(pkt, &src_port, &dst_port);
break;
case IPPROTO_UDP:
proto = "UDP";
ret = get_ports(pkt, &src_port, &dst_port);
break;
case IPPROTO_ICMPV6:
case IPPROTO_ICMP:
proto = "ICMP";
break;
default:
proto = "<unknown>";
break;
}
if (ret < 0) {
NET_ERR("Cannot get port numbers for pkt %p", pkt);
return;
}
src_addr = net_addr_ntop(family, src,
src_addr_buf, sizeof(src_addr_buf));
dst_addr = net_addr_ntop(family, dst,
dst_addr_buf, sizeof(dst_addr_buf));
len = net_pkt_get_len(pkt);
if (family == AF_INET) {
if (next_hdr == IPPROTO_TCP || next_hdr == IPPROTO_UDP) {
NET_INFO("%s %s (%zd) %s:%u -> %s:%u",
"IPv4", proto, len, src_addr, src_port,
dst_addr, dst_port);
} else {
NET_INFO("%s %s (%zd) %s -> %s", "IPv4", proto,
len, src_addr, dst_addr);
}
} else {
if (next_hdr == IPPROTO_TCP || next_hdr == IPPROTO_UDP) {
NET_INFO("%s %s (%zd) [%s]:%u -> [%s]:%u",
"IPv6", proto, len, src_addr, src_port,
dst_addr, dst_port);
} else {
NET_INFO("%s %s (%zd) %s -> %s", "IPv6", proto,
len, src_addr, dst_addr);
}
}
}
void main(void)
{
struct net_pkt *pkt;
net_if_foreach(iface_cb, NULL);
while (1) {
pkt = net_promisc_mode_wait_data(K_FOREVER);
if (pkt) {
print_info(pkt);
}
net_pkt_unref(pkt);
}
}