summaryrefslogtreecommitdiff
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/Makefile1
-rw-r--r--net/eth-uclass.c5
-rw-r--r--net/eth_legacy.c10
-rw-r--r--net/mdio-uclass.c13
-rw-r--r--net/net.c14
-rw-r--r--net/nfs.c19
-rw-r--r--net/nfs.h2
-rw-r--r--net/pcap.c156
8 files changed, 214 insertions, 6 deletions
diff --git a/net/Makefile b/net/Makefile
index 826544f05f..2a700c8401 100644
--- a/net/Makefile
+++ b/net/Makefile
@@ -22,6 +22,7 @@ obj-$(CONFIG_CMD_LINK_LOCAL) += link_local.o
obj-$(CONFIG_NET) += net.o
obj-$(CONFIG_CMD_NFS) += nfs.o
obj-$(CONFIG_CMD_PING) += ping.o
+obj-$(CONFIG_CMD_PCAP) += pcap.o
obj-$(CONFIG_CMD_RARP) += rarp.o
obj-$(CONFIG_CMD_SNTP) += sntp.o
obj-$(CONFIG_CMD_TFTPBOOT) += tftp.o
diff --git a/net/eth-uclass.c b/net/eth-uclass.c
index 1d5d2f03b7..3bd98b01ad 100644
--- a/net/eth-uclass.c
+++ b/net/eth-uclass.c
@@ -11,6 +11,7 @@
#include <net.h>
#include <dm/device-internal.h>
#include <dm/uclass-internal.h>
+#include <net/pcap.h>
#include "eth_internal.h"
DECLARE_GLOBAL_DATA_PTR;
@@ -344,6 +345,10 @@ int eth_send(void *packet, int length)
/* We cannot completely return the error at present */
debug("%s: send() returned error %d\n", __func__, ret);
}
+#if defined(CONFIG_CMD_PCAP)
+ if (ret >= 0)
+ pcap_post(packet, length, true);
+#endif
return ret;
}
diff --git a/net/eth_legacy.c b/net/eth_legacy.c
index 850f362d87..41f5263526 100644
--- a/net/eth_legacy.c
+++ b/net/eth_legacy.c
@@ -11,6 +11,7 @@
#include <net.h>
#include <phy.h>
#include <linux/errno.h>
+#include <net/pcap.h>
#include "eth_internal.h"
DECLARE_GLOBAL_DATA_PTR;
@@ -352,10 +353,17 @@ int eth_is_active(struct eth_device *dev)
int eth_send(void *packet, int length)
{
+ int ret;
+
if (!eth_current)
return -ENODEV;
- return eth_current->send(eth_current, packet, length);
+ ret = eth_current->send(eth_current, packet, length);
+#if defined(CONFIG_CMD_PCAP)
+ if (ret >= 0)
+ pcap_post(packet, lengeth, true);
+#endif
+ return ret;
}
int eth_rx(void)
diff --git a/net/mdio-uclass.c b/net/mdio-uclass.c
index 36a404ff44..6f922e80b6 100644
--- a/net/mdio-uclass.c
+++ b/net/mdio-uclass.c
@@ -23,6 +23,17 @@ void dm_mdio_probe_devices(void)
static int dm_mdio_post_bind(struct udevice *dev)
{
+ const char *dt_name;
+
+ /* set a custom name for the MDIO device, if present in DT */
+ if (ofnode_valid(dev->node)) {
+ dt_name = ofnode_read_string(dev->node, "device-name");
+ if (dt_name) {
+ debug("renaming dev %s to %s\n", dev->name, dt_name);
+ device_set_name(dev, dt_name);
+ }
+ }
+
/*
* MDIO command doesn't like spaces in names, don't allow them to keep
* it happy
@@ -75,7 +86,7 @@ static int dm_mdio_post_probe(struct udevice *dev)
pdata->mii_bus->write = mdio_write;
pdata->mii_bus->reset = mdio_reset;
pdata->mii_bus->priv = dev;
- strncpy(pdata->mii_bus->name, dev->name, MDIO_NAME_LEN);
+ strncpy(pdata->mii_bus->name, dev->name, MDIO_NAME_LEN - 1);
return mdio_register(pdata->mii_bus);
}
diff --git a/net/net.c b/net/net.c
index 40511db645..ded86e7456 100644
--- a/net/net.c
+++ b/net/net.c
@@ -96,6 +96,9 @@
#include <net.h>
#include <net/fastboot.h>
#include <net/tftp.h>
+#if defined(CONFIG_CMD_PCAP)
+#include <net/pcap.h>
+#endif
#if defined(CONFIG_LED_STATUS)
#include <miiphy.h>
#include <status_led.h>
@@ -672,6 +675,11 @@ done:
net_set_icmp_handler(NULL);
#endif
net_set_state(prev_net_state);
+
+#if defined(CONFIG_CMD_PCAP)
+ if (pcap_active())
+ pcap_print_status();
+#endif
return ret;
}
@@ -1084,6 +1092,9 @@ void net_process_received_packet(uchar *in_packet, int len)
debug_cond(DEBUG_NET_PKT, "packet received\n");
+#if defined(CONFIG_CMD_PCAP)
+ pcap_post(in_packet, len, false);
+#endif
net_rx_packet = in_packet;
net_rx_packet_len = len;
et = (struct ethernet_hdr *)in_packet;
@@ -1253,6 +1264,9 @@ void net_process_received_packet(uchar *in_packet, int len)
return;
}
+ if (ntohs(ip->udp_len) < UDP_HDR_SIZE || ntohs(ip->udp_len) > ntohs(ip->ip_len))
+ return;
+
debug_cond(DEBUG_DEV_PKT,
"received UDP (to=%pI4, from=%pI4, len=%d)\n",
&dst_ip, &src_ip, len);
diff --git a/net/nfs.c b/net/nfs.c
index d6a7f8e827..aca0ca55f3 100644
--- a/net/nfs.c
+++ b/net/nfs.c
@@ -196,10 +196,10 @@ static void rpc_req(int rpc_prog, int rpc_proc, uint32_t *data, int datalen)
rpc_pkt.u.call.vers = htonl(2); /* portmapper is version 2 */
}
rpc_pkt.u.call.proc = htonl(rpc_proc);
- p = (uint32_t *)&(rpc_pkt.u.call.data);
+ p = rpc_pkt.u.call.data;
if (datalen)
- memcpy((char *)p, (char *)data, datalen*sizeof(uint32_t));
+ memcpy(p, data, datalen * sizeof(uint32_t));
pktlen = (char *)p + datalen * sizeof(uint32_t) - (char *)&rpc_pkt;
@@ -566,11 +566,15 @@ static int nfs_lookup_reply(uchar *pkt, unsigned len)
}
if (supported_nfs_versions & NFSV2_FLAG) {
+ if (((uchar *)&(rpc_pkt.u.reply.data[0]) - (uchar *)(&rpc_pkt) + NFS_FHSIZE) > len)
+ return -NFS_RPC_DROP;
memcpy(filefh, rpc_pkt.u.reply.data + 1, NFS_FHSIZE);
} else { /* NFSV3_FLAG */
filefh3_length = ntohl(rpc_pkt.u.reply.data[1]);
if (filefh3_length > NFS3_FHSIZE)
filefh3_length = NFS3_FHSIZE;
+ if (((uchar *)&(rpc_pkt.u.reply.data[0]) - (uchar *)(&rpc_pkt) + filefh3_length) > len)
+ return -NFS_RPC_DROP;
memcpy(filefh, rpc_pkt.u.reply.data + 2, filefh3_length);
}
@@ -579,7 +583,7 @@ static int nfs_lookup_reply(uchar *pkt, unsigned len)
static int nfs3_get_attributes_offset(uint32_t *data)
{
- if (ntohl(data[1]) != 0) {
+ if (data[1]) {
/* 'attributes_follow' flag is TRUE,
* so we have attributes on 21 dwords */
/* Skip unused values :
@@ -634,6 +638,9 @@ static int nfs_readlink_reply(uchar *pkt, unsigned len)
/* new path length */
rlen = ntohl(rpc_pkt.u.reply.data[1 + nfsv3_data_offset]);
+ if (((uchar *)&(rpc_pkt.u.reply.data[0]) - (uchar *)(&rpc_pkt) + rlen) > len)
+ return -NFS_RPC_DROP;
+
if (*((char *)&(rpc_pkt.u.reply.data[2 + nfsv3_data_offset])) != '/') {
int pathlen;
@@ -701,6 +708,9 @@ static int nfs_read_reply(uchar *pkt, unsigned len)
&(rpc_pkt.u.reply.data[4 + nfsv3_data_offset]);
}
+ if (((uchar *)&(rpc_pkt.u.reply.data[0]) - (uchar *)(&rpc_pkt) + rlen) > len)
+ return -9999;
+
if (store_block(data_ptr, nfs_offset, rlen))
return -9999;
@@ -732,6 +742,9 @@ static void nfs_handler(uchar *pkt, unsigned dest, struct in_addr sip,
debug("%s\n", __func__);
+ if (len > sizeof(struct rpc_t))
+ return;
+
if (dest != nfs_our_port)
return;
diff --git a/net/nfs.h b/net/nfs.h
index a377c90088..68ada0efeb 100644
--- a/net/nfs.h
+++ b/net/nfs.h
@@ -78,7 +78,7 @@ struct rpc_t {
NFS_MAX_ATTRS];
} reply;
} u;
-} __attribute__((packed));
+};
void nfs_start(void); /* Begin NFS */
diff --git a/net/pcap.c b/net/pcap.c
new file mode 100644
index 0000000000..4036d8a3fa
--- /dev/null
+++ b/net/pcap.c
@@ -0,0 +1,156 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2019 Ramon Fried <rfried.dev@gmail.com>
+ */
+
+#include <common.h>
+#include <net.h>
+#include <net/pcap.h>
+#include <time.h>
+#include <asm/io.h>
+
+#define LINKTYPE_ETHERNET 1
+
+static bool initialized;
+static bool running;
+static bool buffer_full;
+static void *buf;
+static unsigned int max_size;
+static unsigned int pos;
+
+static unsigned long incoming_count;
+static unsigned long outgoing_count;
+
+struct pcap_header {
+ u32 magic;
+ u16 version_major;
+ u16 version_minor;
+ s32 thiszone;
+ u32 sigfigs;
+ u32 snaplen;
+ u32 network;
+};
+
+struct pcap_packet_header {
+ u32 ts_sec;
+ u32 ts_usec;
+ u32 incl_len;
+ u32 orig_len;
+};
+
+static struct pcap_header file_header = {
+ .magic = 0xa1b2c3d4,
+ .version_major = 2,
+ .version_minor = 4,
+ .snaplen = 65535,
+ .network = LINKTYPE_ETHERNET,
+};
+
+int pcap_init(phys_addr_t paddr, unsigned long size)
+{
+ buf = map_physmem(paddr, size, 0);
+ if (!buf) {
+ printf("Failed mapping PCAP memory\n");
+ return -ENOMEM;
+ }
+
+ printf("PCAP capture initialized: addr: 0x%lx max length: %lu\n",
+ (unsigned long)buf, size);
+
+ memcpy(buf, &file_header, sizeof(file_header));
+ pos = sizeof(file_header);
+ max_size = size;
+ initialized = true;
+ running = false;
+ buffer_full = false;
+ incoming_count = 0;
+ outgoing_count = 0;
+ return 0;
+}
+
+int pcap_start_stop(bool start)
+{
+ if (!initialized) {
+ printf("error: pcap was not initialized\n");
+ return -ENODEV;
+ }
+
+ running = start;
+
+ return 0;
+}
+
+int pcap_clear(void)
+{
+ if (!initialized) {
+ printf("error: pcap was not initialized\n");
+ return -ENODEV;
+ }
+
+ pos = sizeof(file_header);
+ incoming_count = 0;
+ outgoing_count = 0;
+ buffer_full = false;
+
+ printf("pcap capture cleared\n");
+ return 0;
+}
+
+int pcap_post(const void *packet, size_t len, bool outgoing)
+{
+ struct pcap_packet_header header;
+ u64 cur_time = timer_get_us();
+
+ if (!initialized || !running || !buf)
+ return -ENODEV;
+
+ if (buffer_full)
+ return -ENOMEM;
+
+ if ((pos + len + sizeof(header)) >= max_size) {
+ buffer_full = true;
+ printf("\n!!! Buffer is full, consider increasing buffer size !!!\n");
+ return -ENOMEM;
+ }
+
+ header.ts_sec = cur_time / 1000000;
+ header.ts_usec = cur_time % 1000000;
+ header.incl_len = len;
+ header.orig_len = len;
+
+ memcpy(buf + pos, &header, sizeof(header));
+ pos += sizeof(header);
+ memcpy(buf + pos, packet, len);
+ pos += len;
+
+ if (outgoing)
+ outgoing_count++;
+ else
+ incoming_count++;
+
+ env_set_hex("pcapsize", pos);
+
+ return 0;
+}
+
+int pcap_print_status(void)
+{
+ if (!initialized) {
+ printf("pcap was not initialized\n");
+ return -ENODEV;
+ }
+ printf("PCAP status:\n");
+ printf("\tInitialized addr: 0x%lx\tmax length: %u\n",
+ (unsigned long)buf, max_size);
+ printf("\tStatus: %s.\t file size: %u\n", running ? "Active" : "Idle",
+ pos);
+ printf("\tIncoming packets: %lu Outgoing packets: %lu\n",
+ incoming_count, outgoing_count);
+
+ return 0;
+}
+
+bool pcap_active(void)
+{
+ return running;
+}