public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [4/4] Network packet tracer module using kprobes interface.
@ 2004-08-11 16:22 Prasanna S Panchamukhi
  2004-08-12 12:35 ` Prasanna S Panchamukhi
  0 siblings, 1 reply; 4+ messages in thread
From: Prasanna S Panchamukhi @ 2004-08-11 16:22 UTC (permalink / raw)
  To: linux-kernel, torvalds, ak, akpm, suparna, shemminger; +Cc: prasanna

[-- Attachment #1: Type: text/plain, Size: 949 bytes --]

Hi,

Below is [4/4]kprobes-netptk-tracer-268-rc4.patch

This patch provides network packet tracing feature using kernel
space probes mechanism, which is efficient for dynamic tracing. Network
packet traceing allows you to see the network packets while moving up
and down the stack.
	Network packet tracing was suggested by Andi Kleen.
To trace the network packets based on source and target ports, insert the
module with source and target ports.
        Example insmod netpktlog.ko netpktlog=@62333,254
To trace the network packets based on only source port, insert module
with source port.
        Example insmod netpktlog.ko netpktlog=@62333,
To trace network packets based on target port, insert module with
target port.
        Example insmod netpktlog.ko netpktlog=@,254

Your comments are welcome!

Thanks
Prasanna
-- 

Prasanna S Panchamukhi
Linux Technology Center
India Software Labs, IBM Bangalore
Ph: 91-80-25044636
<prasanna@in.ibm.com>

[-- Attachment #2: kprobes-netptk-tracer-268-rc4.patch --]
[-- Type: text/plain, Size: 13898 bytes --]


	This patch provides network packet tracing feature using kernel
space probes mechanism, which is efficient for dynamic tracing. Network 
packet traceing allows you to see the network packets while moving up 
and down the stack.
To trace the network packets based on source and target ports, insert the
module with source and target ports.
	Example insmod netpktlog.ko netpktlog=@62333,254
To trace the network packets based on only source port, insert module
with source port.
	Example insmod netpktlog.ko netpktlog=@62333,
To trace network packets based on target port, insert module with
target port.
	Example insmod netpktlog.ko netpktlog=@,254

---

---

---

---

 linux-2.6.8-rc4-prasanna/drivers/net/Kconfig                    |   12 
 linux-2.6.8-rc4-prasanna/drivers/net/Makefile                   |    3 
 linux-2.6.8-rc4-prasanna/include/linux/netfilter_ipv4/ipt_LOG.h |    2 
 linux-2.6.8-rc4-prasanna/kernel/kallsyms.c                      |    1 
 linux-2.6.8-rc4-prasanna/net/ipv4/netfilter/ipt_LOG.c           |    3 



---

 linux-2.6.8-rc4-prasanna/drivers/net/Kconfig                    |   12 
 linux-2.6.8-rc4-prasanna/drivers/net/Makefile                   |    3 
 linux-2.6.8-rc4-prasanna/drivers/net/netpktlog.c                |  216 ++++++++++
 linux-2.6.8-rc4-prasanna/include/linux/netfilter_ipv4/ipt_LOG.h |    2 
 linux-2.6.8-rc4-prasanna/include/linux/netpktlog.h              |  114 +++++
 linux-2.6.8-rc4-prasanna/kernel/kallsyms.c                      |    1 
 linux-2.6.8-rc4-prasanna/net/ipv4/netfilter/ipt_LOG.c           |    3 
 7 files changed, 350 insertions(+), 1 deletion(-)

diff -puN drivers/net/Kconfig~kprobes-netptk-tracer-268-rc4 drivers/net/Kconfig
--- linux-2.6.8-rc4/drivers/net/Kconfig~kprobes-netptk-tracer-268-rc4	2004-08-11 21:02:39.000000000 +0530
+++ linux-2.6.8-rc4-prasanna/drivers/net/Kconfig	2004-08-11 21:02:39.000000000 +0530
@@ -2598,3 +2598,15 @@ config NETCONSOLE
 	If you want to log kernel messages over the network, enable this.
 	See Documentation/networking/netconsole.txt for details.
 
+config NETPKTLOG
+	tristate "Network packet Tracer using kernel probes(EXPERIMENTAL)"
+	depends on KPROBES && IP_NF_TARGET_LOG
+	---help---
+	Network packet tracering is achived using kernel probes allowing you
+	to see the network packets while moving up and down the stack. This
+	module uses kprobes mechanism which is highly efficient for dynamic
+	tracing.
+
+	See driver/net/netpktlog.c for details.
+	To compile this driver as a module, choose M.If unsure, say N.
+
diff -puN drivers/net/Makefile~kprobes-netptk-tracer-268-rc4 drivers/net/Makefile
--- linux-2.6.8-rc4/drivers/net/Makefile~kprobes-netptk-tracer-268-rc4	2004-08-11 21:02:39.000000000 +0530
+++ linux-2.6.8-rc4-prasanna/drivers/net/Makefile	2004-08-11 21:02:39.000000000 +0530
@@ -191,3 +191,6 @@ obj-$(CONFIG_HAMRADIO) += hamradio/
 obj-$(CONFIG_IRDA) += irda/
 
 obj-$(CONFIG_NETCONSOLE) += netconsole.o
+ifeq ($(CONFIG_NETPKTLOG),y)
+ obj-m += netpktlog.o
+endif
diff -puN /dev/null drivers/net/netpktlog.c
--- /dev/null	2003-01-30 15:54:37.000000000 +0530
+++ linux-2.6.8-rc4-prasanna/drivers/net/netpktlog.c	2004-08-11 21:03:13.000000000 +0530
@@ -0,0 +1,216 @@
+/*
+ *  Network Packet Tracer using Kernel Probes (KProbes)
+ *  net/driver/netpktlog.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Copyright (C) IBM Corporation, 2004
+ *
+ * 2004-Aug	Created by Prasanna S Panchamukhi <prasanna@in.ibm.com>
+ *		for network packet tracing using kernel probes interface.
+ * 		Suggested by Andi Kleen.
+ *
+ */
+#include <linux/module.h>
+#include <linux/kprobes.h>
+#include <linux/kallsyms.h>
+
+static char config[256];
+static unsigned short src_port, tgt_port;
+module_param_string(netpktlog, config, 256, 0);
+MODULE_PARM_DESC(netpktlog, " netpktlog=@<source-port>,<target-port>\n");
+
+#include <linux/netpktlog.h>
+
+/*
+ * Compile the kernel with options CONFIG_KPROBES, CONFIG_NETPKTLOG,
+ * CONFIG_NETFILTER, CONFIG_IP_NF_IPTABLES and CONFIG_IP_NF_TARGET_LOG enabled.
+ * You need to specify the parameters to the netpktlog module.
+ * To trace the network packets based on source and target ports, insert the
+ * module with source and target ports.
+ *	Example insmod netpktlog.ko netpktlog=@62333,254
+ * To trace the network packets based on only source port, insert module
+ * with source port. Example insmod netpktlog.ko netpktlog=@62333,
+ * To trace network packets based on target port, insert module with
+ * target port.	Example insmod netpktlog.ko netpktlog=@,254
+ */
+
+static void jnetif_rx(struct sk_buff *skb)
+{
+	netfilter_ip(skb);
+	jprobe_return();
+}
+
+static void j__kfree_skb(struct sk_buff *skb)
+{
+	netfilter_ip(skb);
+	jprobe_return();
+}
+
+static int jnetif_receive_skb(struct sk_buff *skb)
+{
+	netfilter_ip(skb);
+	jprobe_return();
+	return 0;
+}
+
+static int jip_rcv(struct sk_buff *skb, struct net_device *dev,
+		   struct packet_type *pt)
+{
+	netfilter_ip(skb);
+	jprobe_return();
+	return 0;
+}
+
+static int jip_local_deliver(struct sk_buff *skb)
+{
+	netfilter_ip(skb);
+	jprobe_return();
+	return 0;
+}
+
+static int jip_queue_xmit(struct sk_buff *skb, int ipfragok)
+{
+	netfilter_ip(skb);
+	jprobe_return();
+	return 0;
+}
+
+static int jip_output(struct sk_buff **pskb)
+{
+	netfilter_ip(*pskb);
+	jprobe_return();
+	return 0;
+}
+
+static int jtcp_v4_rcv(struct sk_buff *skb)
+{
+	netfilter_ip(skb);
+	jprobe_return();
+	return 0;
+}
+
+static int jtcp_v4_do_rcv(struct sock *sk, struct sk_buff *skb)
+{
+	netfilter_ip(skb);
+	jprobe_return();
+	return 0;
+}
+
+static int jtcp_rcv_established(struct sock *sk, struct sk_buff *skb,
+				struct tcphdr *th, unsigned len)
+{
+	netfilter_ip(skb);
+	jprobe_return();
+	return 0;
+}
+
+static int jskb_copy_datagram_iovec(struct sk_buff *from, int offset,
+				    struct iovec *to, int size)
+{
+	netfilter_ip(from);
+	jprobe_return();
+	return 0;
+}
+
+static void jtcp_send_dupack(struct sock *sk, struct sk_buff *skb)
+{
+	netfilter_ip(skb);
+	jprobe_return();
+}
+
+static int jip_forward(struct sk_buff *skb)
+{
+	netfilter_ip(skb);
+	jprobe_return();
+	return 0;
+}
+
+static char *nettrace_routines[] = {
+	"netif_rx",
+	"__kfree_skb",
+	"netif_receive_skb",
+	"ip_rcv",
+	"ip_local_deliver",
+	"ip_queue_xmit",
+	"ip_output",
+	"ip_forward",
+	"tcp_v4_rcv",
+	"tcp_v4_do_rcv",
+	"tcp_rcv_established",
+	"skb_copy_datagram_iovec",
+	"tcp_send_dupack"
+};
+static struct jprobe netpkt[] = {
+	{
+	 .entry = (kprobe_opcode_t *) jnetif_rx},
+	{
+	 .entry = (kprobe_opcode_t *) j__kfree_skb},
+	{
+	 .entry = (kprobe_opcode_t *) jnetif_receive_skb},
+	{
+	 .entry = (kprobe_opcode_t *) jip_rcv},
+	{
+	 .entry = (kprobe_opcode_t *) jip_local_deliver},
+	{
+	 .entry = (kprobe_opcode_t *) jip_queue_xmit},
+	{
+	 .entry = (kprobe_opcode_t *) jip_output},
+	{
+	 .entry = (kprobe_opcode_t *) jip_forward},
+	{
+	 .entry = (kprobe_opcode_t *) jtcp_v4_rcv},
+	{
+	 .entry = (kprobe_opcode_t *) jtcp_v4_do_rcv},
+	{
+	 .entry = (kprobe_opcode_t *) jtcp_rcv_established},
+	{
+	 .entry = (kprobe_opcode_t *) jskb_copy_datagram_iovec},
+	{
+	 .entry = (kprobe_opcode_t *) jtcp_send_dupack}
+};
+
+static int init_netpktlog(void)
+{
+	int i;
+	if (strlen(config))
+		option_setup(config);
+
+	/* first time invokation to initialize probe handler */
+	/* now we are all set to register the probe */
+	for (i = 0; i < MAX_NETPKT_ROUTINE; i++) {
+		netpkt[i].kp.addr =
+		    (kprobe_opcode_t *)
+		    kallsyms_lookup_name(nettrace_routines[i]);
+		printk("plant jprobe at %p, handler addr %p\n",
+		       netpkt[i].kp.addr, netpkt[i].entry);
+		register_jprobe(&netpkt[i]);
+	}
+
+	printk("Network packets tracing is enabled...\n");
+	return 0;
+}
+
+static void cleanup_netpktlog(void)
+{
+	int i;
+	for (i = 0; i < MAX_NETPKT_ROUTINE; i++)
+		unregister_jprobe(&netpkt[i]);
+	printk("Network packets tracing is disabled...\n");
+}
+
+module_init(init_netpktlog);
+module_exit(cleanup_netpktlog);
+MODULE_LICENSE("GPL");
diff -puN include/linux/netfilter_ipv4/ipt_LOG.h~kprobes-netptk-tracer-268-rc4 include/linux/netfilter_ipv4/ipt_LOG.h
--- linux-2.6.8-rc4/include/linux/netfilter_ipv4/ipt_LOG.h~kprobes-netptk-tracer-268-rc4	2004-08-11 21:02:39.000000000 +0530
+++ linux-2.6.8-rc4-prasanna/include/linux/netfilter_ipv4/ipt_LOG.h	2004-08-11 21:02:39.000000000 +0530
@@ -11,5 +11,7 @@ struct ipt_log_info {
 	unsigned char logflags;
 	char prefix[30];
 };
+void dump_packet(const struct ipt_log_info *info, const struct sk_buff *skb,
+			unsigned int iphoff);
 
 #endif /*_IPT_LOG_H*/
diff -puN /dev/null include/linux/netpktlog.h
--- /dev/null	2003-01-30 15:54:37.000000000 +0530
+++ linux-2.6.8-rc4-prasanna/include/linux/netpktlog.h	2004-08-11 21:02:39.000000000 +0530
@@ -0,0 +1,114 @@
+/*
+ *  Network Packet Tracer using Kernel Probes (KProbes)
+ *  include/linux/netpktlog.h
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Copyright (C) IBM Corporation, 2004
+ *
+ * 2004-Aug 	Created by Prasanna S Panchamukhi <prasanna@in.ibm.com>
+ *		for network packet tracing using kernel probes interface.
+ *		Suggested by Andi Kleen.
+ */
+#include <linux/inet.h>
+#include <linux/ip.h>
+#include <linux/netdevice.h>
+#include <linux/netfilter_ipv4/ipt_LOG.h>
+#include <net/ip.h>
+#include <net/tcp.h>
+#include <net/udp.h>
+
+void tcp_send_dupack(struct sock *sk, struct sk_buff *skb);
+#define MAX_NETPKT_ROUTINE (sizeof(netpkt)/sizeof(struct jprobe))
+
+static inline void option_setup(char *opt)
+{
+	char *cur = opt, *delim;
+
+	if (*cur != '@') {
+		printk("Wrong format\n");
+		return;
+	}
+	cur++;
+	if ((delim = strchr(cur, ',')) == NULL) {
+		printk("No ipaddress found\n");
+		return;
+	}
+	*delim = 0;
+	src_port = in_aton(cur);
+	delim++;
+	tgt_port = in_aton(delim);
+}
+
+/*
+ * netfilter_ip: This is a generic routine that can be used to dump the
+ * network packet for a given source and destination ip address.
+ * Network packet filtering is done based on source/target ip or both source and
+ * target ip.
+ */
+
+static inline void netfilter_ip(struct sk_buff *skb)
+{
+	struct ipt_log_info info;
+	struct iphdr *iph;
+	struct tcphdr *tcph;
+	struct udphdr *udph;
+	/* Log IP options */
+	info.logflags = IPT_LOG_IPOPT;
+
+	/*
+	 * Check if the protocol is IP before dumping the packet.
+	 */
+	if (skb->protocol == htons(ETH_P_IP)) {
+		iph = (struct iphdr *)skb->nh.iph;
+
+		if (iph == NULL)
+			return;
+		switch (iph->protocol) {
+		case IPPROTO_TCP:{
+				tcph = (struct tcphdr *)(unsigned long)iph
+				    + iph->ihl * 4;
+				if ((src_port == 0
+				     && ntohs(tcph->dest) == tgt_port)
+				    || (tgt_port == 0
+					&& ntohs(tcph->source) == src_port)
+				    || (ntohs(tcph->source) == src_port
+					&& ntohs(tcph->dest) == tgt_port)) {
+					dump_packet((struct ipt_log_info *)
+						    &info, skb, 0);
+					printk("\n");
+				}
+				break;
+			}
+		case IPPROTO_UDP:{
+				udph = (struct udphdr *)(unsigned long)iph
+				    + iph->ihl * 4;
+				if ((src_port == 0
+				     && ntohs(udph->dest) == tgt_port)
+				    || (tgt_port == 0
+					&& ntohs(udph->source) == src_port)
+				    || (ntohs(udph->source) == src_port
+					&& ntohs(udph->dest) == tgt_port)) {
+					dump_packet((struct ipt_log_info *)
+						    &info, skb, 0);
+					printk("\n");
+				}
+				break;
+			}
+		default:
+			break;
+		}
+	}
+}
diff -puN kernel/kallsyms.c~kprobes-netptk-tracer-268-rc4 kernel/kallsyms.c
--- linux-2.6.8-rc4/kernel/kallsyms.c~kprobes-netptk-tracer-268-rc4	2004-08-11 21:02:39.000000000 +0530
+++ linux-2.6.8-rc4-prasanna/kernel/kallsyms.c	2004-08-11 21:02:39.000000000 +0530
@@ -310,3 +310,4 @@ int __init kallsyms_init(void)
 __initcall(kallsyms_init);
 
 EXPORT_SYMBOL(__print_symbol);
+EXPORT_SYMBOL(kallsyms_lookup_name);
diff -puN net/ipv4/netfilter/ipt_LOG.c~kprobes-netptk-tracer-268-rc4 net/ipv4/netfilter/ipt_LOG.c
--- linux-2.6.8-rc4/net/ipv4/netfilter/ipt_LOG.c~kprobes-netptk-tracer-268-rc4	2004-08-11 21:02:39.000000000 +0530
+++ linux-2.6.8-rc4-prasanna/net/ipv4/netfilter/ipt_LOG.c	2004-08-11 21:02:39.000000000 +0530
@@ -41,7 +41,7 @@ MODULE_PARM_DESC(nflog, "register as int
 static spinlock_t log_lock = SPIN_LOCK_UNLOCKED;
 
 /* One level of recursion won't kill us */
-static void dump_packet(const struct ipt_log_info *info,
+void dump_packet(const struct ipt_log_info *info,
 			const struct sk_buff *skb,
 			unsigned int iphoff)
 {
@@ -461,5 +461,6 @@ static void __exit fini(void)
 	ipt_unregister_target(&ipt_log_reg);
 }
 
+EXPORT_SYMBOL_GPL(dump_packet);
 module_init(init);
 module_exit(fini);

_

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [4/4] Network packet tracer module using kprobes interface.
  2004-08-11 16:22 [4/4] Network packet tracer module using kprobes interface Prasanna S Panchamukhi
@ 2004-08-12 12:35 ` Prasanna S Panchamukhi
  2004-08-12 13:20   ` Andi Kleen
  0 siblings, 1 reply; 4+ messages in thread
From: Prasanna S Panchamukhi @ 2004-08-12 12:35 UTC (permalink / raw)
  To: ak; +Cc: linux-kernel, suparna

[-- Attachment #1: Type: text/plain, Size: 241 bytes --]

Hi Andi,

Please find the updated Network packet tracer patch below.

Your comments are welcome!

Thanks
Prasanna
-- 
Prasanna S Panchamukhi
Linux Technology Center
India Software Labs, IBM Bangalore
Ph: 91-80-25044636
<prasanna@in.ibm.com>

[-- Attachment #2: kprobes-netptk-tracer-268-rc4.patch --]
[-- Type: text/plain, Size: 13625 bytes --]


	This patch provides network packet tracing feature using kernel
space probes mechanism, which is efficient for dynamic tracing. Network 
packet traceing allows you to see the network packets while moving up 
and down the stack.
To trace the network packets based on source and target ports, insert the
module with source and target ports.
	Example insmod netpktlog.ko netpktlog=@62333,254
To trace the network packets based on only source port, insert module
with source port.
	Example insmod netpktlog.ko netpktlog=@62333,
To trace network packets based on target port, insert module with
target port.
	Example insmod netpktlog.ko netpktlog=@,254

---

---

---

---

 linux-2.6.8-rc4-prasanna/drivers/net/Kconfig                    |   12 
 linux-2.6.8-rc4-prasanna/drivers/net/Makefile                   |    3 
 linux-2.6.8-rc4-prasanna/include/linux/netfilter_ipv4/ipt_LOG.h |    2 
 linux-2.6.8-rc4-prasanna/kernel/kallsyms.c                      |    1 
 linux-2.6.8-rc4-prasanna/net/ipv4/netfilter/ipt_LOG.c           |    3 



---

 linux-2.6.8-rc4-prasanna/drivers/net/Kconfig                    |   12 
 linux-2.6.8-rc4-prasanna/drivers/net/Makefile                   |    3 
 linux-2.6.8-rc4-prasanna/drivers/net/netpktlog.c                |  204 ++++++++++
 linux-2.6.8-rc4-prasanna/include/linux/netfilter_ipv4/ipt_LOG.h |    2 
 linux-2.6.8-rc4-prasanna/include/linux/netpktlog.h              |  113 +++++
 linux-2.6.8-rc4-prasanna/kernel/kallsyms.c                      |    1 
 linux-2.6.8-rc4-prasanna/net/ipv4/netfilter/ipt_LOG.c           |    3 
 7 files changed, 337 insertions(+), 1 deletion(-)

diff -puN drivers/net/Kconfig~kprobes-netptk-tracer-268-rc4 drivers/net/Kconfig
--- linux-2.6.8-rc4/drivers/net/Kconfig~kprobes-netptk-tracer-268-rc4	2004-08-12 17:37:34.000000000 +0530
+++ linux-2.6.8-rc4-prasanna/drivers/net/Kconfig	2004-08-12 17:37:34.000000000 +0530
@@ -2598,3 +2598,15 @@ config NETCONSOLE
 	If you want to log kernel messages over the network, enable this.
 	See Documentation/networking/netconsole.txt for details.
 
+config NETPKTLOG
+	tristate "Network packet Tracer using kernel probes(EXPERIMENTAL)"
+	depends on KPROBES && IP_NF_TARGET_LOG
+	---help---
+	Network packet tracering is achived using kernel probes allowing you
+	to see the network packets while moving up and down the stack. This
+	module uses kprobes mechanism which is highly efficient for dynamic
+	tracing.
+
+	See driver/net/netpktlog.c for details.
+	To compile this driver as a module, choose M.If unsure, say N.
+
diff -puN drivers/net/Makefile~kprobes-netptk-tracer-268-rc4 drivers/net/Makefile
--- linux-2.6.8-rc4/drivers/net/Makefile~kprobes-netptk-tracer-268-rc4	2004-08-12 17:37:34.000000000 +0530
+++ linux-2.6.8-rc4-prasanna/drivers/net/Makefile	2004-08-12 17:37:34.000000000 +0530
@@ -191,3 +191,6 @@ obj-$(CONFIG_HAMRADIO) += hamradio/
 obj-$(CONFIG_IRDA) += irda/
 
 obj-$(CONFIG_NETCONSOLE) += netconsole.o
+ifeq ($(CONFIG_NETPKTLOG),y)
+ obj-m += netpktlog.o
+endif
diff -puN /dev/null drivers/net/netpktlog.c
--- /dev/null	2003-01-30 15:54:37.000000000 +0530
+++ linux-2.6.8-rc4-prasanna/drivers/net/netpktlog.c	2004-08-12 17:37:47.000000000 +0530
@@ -0,0 +1,204 @@
+/*
+ *  Network Packet Tracer using Kernel Probes (KProbes)
+ *  net/driver/netpktlog.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Copyright (C) IBM Corporation, 2004
+ *
+ * 2004-Aug	Created by Prasanna S Panchamukhi <prasanna@in.ibm.com>
+ *		for network packet tracing using kernel probes interface.
+ * 		Suggested by Andi Kleen.
+ *
+ */
+#include <linux/module.h>
+#include <linux/kprobes.h>
+#include <linux/kallsyms.h>
+
+static char config[256];
+static unsigned short src_port, tgt_port;
+module_param_string(netpktlog, config, 256, 0);
+MODULE_PARM_DESC(netpktlog, " netpktlog=@<source-port>,<target-port>\n");
+
+#include <linux/netpktlog.h>
+
+/*
+ * Compile the kernel with options CONFIG_KPROBES, CONFIG_NETPKTLOG,
+ * CONFIG_NETFILTER, CONFIG_IP_NF_IPTABLES and CONFIG_IP_NF_TARGET_LOG enabled.
+ * You need to specify the parameters to the netpktlog module.
+ * To trace the network packets based on source and target ports, insert the
+ * module with source and target ports.
+ *	Example insmod netpktlog.ko netpktlog=@62333,254
+ * To trace the network packets based on only source port, insert module
+ * with source port. Example insmod netpktlog.ko netpktlog=@62333,
+ * To trace network packets based on target port, insert module with
+ * target port.	Example insmod netpktlog.ko netpktlog=@,254
+ */
+
+static void jnetif_rx(struct sk_buff *skb)
+{
+	netfilter_ip(skb);
+	jprobe_return();
+}
+
+static void j__kfree_skb(struct sk_buff *skb)
+{
+	netfilter_ip(skb);
+	jprobe_return();
+}
+
+static int jnetif_receive_skb(struct sk_buff *skb)
+{
+	netfilter_ip(skb);
+	jprobe_return();
+	return 0;
+}
+
+static int jip_rcv(struct sk_buff *skb, struct net_device *dev,
+		   struct packet_type *pt)
+{
+	netfilter_ip(skb);
+	jprobe_return();
+	return 0;
+}
+
+static int jip_local_deliver(struct sk_buff *skb)
+{
+	netfilter_ip(skb);
+	jprobe_return();
+	return 0;
+}
+
+static int jip_queue_xmit(struct sk_buff *skb, int ipfragok)
+{
+	netfilter_ip(skb);
+	jprobe_return();
+	return 0;
+}
+
+static int jip_output(struct sk_buff **pskb)
+{
+	netfilter_ip(*pskb);
+	jprobe_return();
+	return 0;
+}
+
+static int jtcp_v4_rcv(struct sk_buff *skb)
+{
+	netfilter_ip(skb);
+	jprobe_return();
+	return 0;
+}
+
+static int jtcp_v4_do_rcv(struct sock *sk, struct sk_buff *skb)
+{
+	netfilter_ip(skb);
+	jprobe_return();
+	return 0;
+}
+
+static int jtcp_rcv_established(struct sock *sk, struct sk_buff *skb,
+				struct tcphdr *th, unsigned len)
+{
+	netfilter_ip(skb);
+	jprobe_return();
+	return 0;
+}
+
+static int jskb_copy_datagram_iovec(struct sk_buff *from, int offset,
+				    struct iovec *to, int size)
+{
+	netfilter_ip(from);
+	jprobe_return();
+	return 0;
+}
+
+static void jtcp_send_dupack(struct sock *sk, struct sk_buff *skb)
+{
+	netfilter_ip(skb);
+	jprobe_return();
+}
+
+static int jip_forward(struct sk_buff *skb)
+{
+	netfilter_ip(skb);
+	jprobe_return();
+	return 0;
+}
+
+struct nettrace_obj {
+	const char *funcname;
+	struct jprobe jp;
+};
+#define NTOBJ(func) \
+	{ .funcname = #func, .jp = { .entry = (kprobe_opcode_t*)j##func }}
+static struct nettrace_obj nettrace_objs[] = {
+	NTOBJ(netif_rx),
+	NTOBJ(__kfree_skb),
+	NTOBJ(netif_receive_skb),
+	NTOBJ(ip_rcv),
+	NTOBJ(ip_local_deliver),
+	NTOBJ(ip_queue_xmit),
+	NTOBJ(ip_output),
+	NTOBJ(ip_forward),
+	NTOBJ(tcp_v4_rcv),
+	NTOBJ(tcp_v4_do_rcv),
+	NTOBJ(tcp_rcv_established),
+	NTOBJ(skb_copy_datagram_iovec),
+	NTOBJ(tcp_send_dupack)
+};
+
+#define MAX_NETPKT_ROUTINE (sizeof(nettrace_objs)/sizeof(nettrace_objs[0]))
+
+static int init_netpktlog(void)
+{
+	int i;
+	struct nettrace_obj *nt;
+	if (strlen(config))
+		option_setup(config);
+
+	/* first time invokation to initialize probe handler */
+	/* now we are all set to register the probe */
+	for (i = 0, nt = nettrace_objs; i < MAX_NETPKT_ROUTINE; i++, nt++) {
+		nt->jp.kp.addr = (kprobe_opcode_t *)
+			kallsyms_lookup_name(nt->funcname);
+		if (nt->jp.kp.addr) {
+			printk("plant jprobe at %s (%p), handler addr %p\n",
+				nt->funcname, nt->jp.kp.addr, nt->jp.entry);
+			register_jprobe(&nt->jp);
+		} else {
+			printk("couldn't find %s to plant jprobe\n",
+				nt->funcname);
+		}
+	}
+
+	printk("Network packets tracing is enabled...\n");
+	return 0;
+}
+
+static void cleanup_netpktlog(void)
+{
+	int i;
+	for (i = 0; i < MAX_NETPKT_ROUTINE; i++) {
+		if (nettrace_objs[i].jp.kp.addr)
+			unregister_jprobe(&nettrace_objs[i].jp);
+	}
+	printk("Network packets tracing is disabled...\n");
+}
+
+
+module_init(init_netpktlog);
+module_exit(cleanup_netpktlog);
+MODULE_LICENSE("GPL");
diff -puN include/linux/netfilter_ipv4/ipt_LOG.h~kprobes-netptk-tracer-268-rc4 include/linux/netfilter_ipv4/ipt_LOG.h
--- linux-2.6.8-rc4/include/linux/netfilter_ipv4/ipt_LOG.h~kprobes-netptk-tracer-268-rc4	2004-08-12 17:37:34.000000000 +0530
+++ linux-2.6.8-rc4-prasanna/include/linux/netfilter_ipv4/ipt_LOG.h	2004-08-12 17:37:34.000000000 +0530
@@ -11,5 +11,7 @@ struct ipt_log_info {
 	unsigned char logflags;
 	char prefix[30];
 };
+void dump_packet(const struct ipt_log_info *info, const struct sk_buff *skb,
+			unsigned int iphoff);
 
 #endif /*_IPT_LOG_H*/
diff -puN /dev/null include/linux/netpktlog.h
--- /dev/null	2003-01-30 15:54:37.000000000 +0530
+++ linux-2.6.8-rc4-prasanna/include/linux/netpktlog.h	2004-08-12 17:37:34.000000000 +0530
@@ -0,0 +1,113 @@
+/*
+ *  Network Packet Tracer using Kernel Probes (KProbes)
+ *  include/linux/netpktlog.h
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Copyright (C) IBM Corporation, 2004
+ *
+ * 2004-Aug 	Created by Prasanna S Panchamukhi <prasanna@in.ibm.com>
+ *		for network packet tracing using kernel probes interface.
+ *		Suggested by Andi Kleen.
+ */
+#include <linux/inet.h>
+#include <linux/ip.h>
+#include <linux/netdevice.h>
+#include <linux/netfilter_ipv4/ipt_LOG.h>
+#include <net/ip.h>
+#include <net/tcp.h>
+#include <net/udp.h>
+
+void tcp_send_dupack(struct sock *sk, struct sk_buff *skb);
+
+static inline void option_setup(char *opt)
+{
+	char *cur = opt, *delim;
+
+	if (*cur != '@') {
+		printk("Wrong format\n");
+		return;
+	}
+	cur++;
+	if ((delim = strchr(cur, ',')) == NULL) {
+		printk("No ipaddress found\n");
+		return;
+	}
+	*delim = 0;
+	src_port = in_aton(cur);
+	delim++;
+	tgt_port = in_aton(delim);
+}
+
+/*
+ * netfilter_ip: This is a generic routine that can be used to dump the
+ * network packet for a given source and destination ip address.
+ * Network packet filtering is done based on source/target ip or both source and
+ * target ip.
+ */
+
+static inline void netfilter_ip(struct sk_buff *skb)
+{
+	struct ipt_log_info info;
+	struct iphdr *iph;
+	struct tcphdr *tcph;
+	struct udphdr *udph;
+	/* Log IP options */
+	info.logflags = IPT_LOG_IPOPT;
+
+	/*
+	 * Check if the protocol is IP before dumping the packet.
+	 */
+	if (skb->protocol == htons(ETH_P_IP)) {
+		iph = (struct iphdr *)skb->nh.iph;
+
+		if (iph == NULL)
+			return;
+		switch (iph->protocol) {
+		case IPPROTO_TCP:{
+				tcph = (struct tcphdr *)(unsigned long)iph
+				    + iph->ihl * 4;
+				if ((src_port == 0
+				     && ntohs(tcph->dest) == tgt_port)
+				    || (tgt_port == 0
+					&& ntohs(tcph->source) == src_port)
+				    || (ntohs(tcph->source) == src_port
+					&& ntohs(tcph->dest) == tgt_port)) {
+					dump_packet((struct ipt_log_info *)
+						    &info, skb, 0);
+					printk("\n");
+				}
+				break;
+			}
+		case IPPROTO_UDP:{
+				udph = (struct udphdr *)(unsigned long)iph
+				    + iph->ihl * 4;
+				if ((src_port == 0
+				     && ntohs(udph->dest) == tgt_port)
+				    || (tgt_port == 0
+					&& ntohs(udph->source) == src_port)
+				    || (ntohs(udph->source) == src_port
+					&& ntohs(udph->dest) == tgt_port)) {
+					dump_packet((struct ipt_log_info *)
+						    &info, skb, 0);
+					printk("\n");
+				}
+				break;
+			}
+		default:
+			break;
+		}
+	}
+}
diff -puN kernel/kallsyms.c~kprobes-netptk-tracer-268-rc4 kernel/kallsyms.c
--- linux-2.6.8-rc4/kernel/kallsyms.c~kprobes-netptk-tracer-268-rc4	2004-08-12 17:37:34.000000000 +0530
+++ linux-2.6.8-rc4-prasanna/kernel/kallsyms.c	2004-08-12 17:37:34.000000000 +0530
@@ -310,3 +310,4 @@ int __init kallsyms_init(void)
 __initcall(kallsyms_init);
 
 EXPORT_SYMBOL(__print_symbol);
+EXPORT_SYMBOL(kallsyms_lookup_name);
diff -puN net/ipv4/netfilter/ipt_LOG.c~kprobes-netptk-tracer-268-rc4 net/ipv4/netfilter/ipt_LOG.c
--- linux-2.6.8-rc4/net/ipv4/netfilter/ipt_LOG.c~kprobes-netptk-tracer-268-rc4	2004-08-12 17:37:34.000000000 +0530
+++ linux-2.6.8-rc4-prasanna/net/ipv4/netfilter/ipt_LOG.c	2004-08-12 17:37:34.000000000 +0530
@@ -41,7 +41,7 @@ MODULE_PARM_DESC(nflog, "register as int
 static spinlock_t log_lock = SPIN_LOCK_UNLOCKED;
 
 /* One level of recursion won't kill us */
-static void dump_packet(const struct ipt_log_info *info,
+void dump_packet(const struct ipt_log_info *info,
 			const struct sk_buff *skb,
 			unsigned int iphoff)
 {
@@ -461,5 +461,6 @@ static void __exit fini(void)
 	ipt_unregister_target(&ipt_log_reg);
 }
 
+EXPORT_SYMBOL_GPL(dump_packet);
 module_init(init);
 module_exit(fini);

_

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [4/4] Network packet tracer module using kprobes interface.
  2004-08-12 12:35 ` Prasanna S Panchamukhi
@ 2004-08-12 13:20   ` Andi Kleen
  2004-08-16 15:55     ` Prasanna S Panchamukhi
  0 siblings, 1 reply; 4+ messages in thread
From: Andi Kleen @ 2004-08-12 13:20 UTC (permalink / raw)
  To: Prasanna S Panchamukhi; +Cc: linux-kernel, suparna

> +static char config[256];
> +static unsigned short src_port, tgt_port;
> +module_param_string(netpktlog, config, 256, 0);
> +MODULE_PARM_DESC(netpktlog, " netpktlog=@<source-port>,<target-port>\n");

It would be better to use the new style module_parm here, then 
it could be even modified from sysfs at runtime when you set suitable 
permissions.

> + * with source port. Example insmod netpktlog.ko netpktlog=@62333,
> + * To trace network packets based on target port, insert module with
> + * target port.	Example insmod netpktlog.ko netpktlog=@,254
> + */
> +
> +static void jnetif_rx(struct sk_buff *skb)
> +{
> +	netfilter_ip(skb);

Are you sure this works?  I'm not sure skb->nh.iph is initialized
at this point. At this point you have to skip the ethernet header
yourself.

> +static void j__kfree_skb(struct sk_buff *skb)
> +{
> +	netfilter_ip(skb);

This may have the same problem depending on where it is called from.
Should be unlikely enough though that it could be ignored.

> +	jprobe_return();
> +}
> +
> +static int jnetif_receive_skb(struct sk_buff *skb)
> +{
> +	netfilter_ip(skb);

This function only sets skb->nh.iph
> +#include <net/udp.h>
> +
> +void tcp_send_dupack(struct sock *sk, struct sk_buff *skb);

This shouldn't be needed anymore, no? 

> +
> +static inline void option_setup(char *opt)

[...] Not sure why you made these two functions inline? 

-andi

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [4/4] Network packet tracer module using kprobes interface.
  2004-08-12 13:20   ` Andi Kleen
@ 2004-08-16 15:55     ` Prasanna S Panchamukhi
  0 siblings, 0 replies; 4+ messages in thread
From: Prasanna S Panchamukhi @ 2004-08-16 15:55 UTC (permalink / raw)
  To: Andi Kleen; +Cc: linux-kernel, suparna

[-- Attachment #1: Type: text/plain, Size: 990 bytes --]

Hi Andi,

Please find the updated patch below. The patch includes following updates as per 
your suggestions.

1. Module parameters can be modified at runtime using sysfs interface.
2. iph = (struct iphdr *)skb->data; is valid at few routines netif_rx, netif_receive_skb, ip_rcv, ip_local_deliver. Modified to dump packet header accordingly.
3. Other routines dump the network packet header from the skb->nh.iph, skb->h.th, skb->h.uh, skb->h.icmp.
4. IP/TCP header is not initialized at ip_queue_xmit() probe.

Please provide your comments.

Thanks
Prasanna
 

-- 
Prasanna S Panchamukhi
Linux Technology Center
India Software Labs, IBM Bangalore
Ph: 91-80-25044636
<prasanna@in.ibm.com>

This patch  demonistrates network packet tracing for specific source and 
target ports.
Network packet tracing is achived using kernel probes allowing you
to see the network packets while moving up and down the stack. This
module uses kprobes mechanism which is highly efficient for dynamic
tracing.


[-- Attachment #2: kprobes-netpkt-tracer-268-rc4.patch --]
[-- Type: text/plain, Size: 22362 bytes --]


---

 linux-2.6.8-rc4-prasanna/drivers/net/Kconfig                    |   12 
 linux-2.6.8-rc4-prasanna/drivers/net/Makefile                   |    3 
 linux-2.6.8-rc4-prasanna/include/linux/netfilter_ipv4/ipt_LOG.h |    2 
 linux-2.6.8-rc4-prasanna/kernel/kallsyms.c                      |    1 
 linux-2.6.8-rc4-prasanna/net/ipv4/netfilter/ipt_LOG.c           |    3 



---

 linux-2.6.8-rc4-prasanna/drivers/net/Kconfig                    |   12 
 linux-2.6.8-rc4-prasanna/drivers/net/Makefile                   |    3 
 linux-2.6.8-rc4-prasanna/drivers/net/netpktlog.c                |  672 ++++++++++
 linux-2.6.8-rc4-prasanna/include/linux/netfilter_ipv4/ipt_LOG.h |    2 
 linux-2.6.8-rc4-prasanna/kernel/kallsyms.c                      |    1 
 linux-2.6.8-rc4-prasanna/net/ipv4/netfilter/ipt_LOG.c           |    3 
 6 files changed, 692 insertions(+), 1 deletion(-)

diff -puN drivers/net/Kconfig~kprobes-netpkt-tracer-268-rc4 drivers/net/Kconfig
--- linux-2.6.8-rc4/drivers/net/Kconfig~kprobes-netpkt-tracer-268-rc4	2004-08-16 20:43:21.000000000 +0530
+++ linux-2.6.8-rc4-prasanna/drivers/net/Kconfig	2004-08-16 20:43:21.000000000 +0530
@@ -2598,3 +2598,15 @@ config NETCONSOLE
 	If you want to log kernel messages over the network, enable this.
 	See Documentation/networking/netconsole.txt for details.
 
+config NETPKTLOG
+	tristate "Network packet Tracer using kernel probes(EXPERIMENTAL)"
+	depends on KPROBES && IP_NF_TARGET_LOG
+	---help---
+	Network packet tracing is achived using kernel probes allowing you
+	to see the network packets while moving up and down the stack. This
+	module uses kprobes mechanism which is highly efficient for dynamic
+	tracing.
+
+	See driver/net/netpktlog.c for details.
+	To compile this driver as a module, choose M.If unsure, say N.
+
diff -puN drivers/net/Makefile~kprobes-netpkt-tracer-268-rc4 drivers/net/Makefile
--- linux-2.6.8-rc4/drivers/net/Makefile~kprobes-netpkt-tracer-268-rc4	2004-08-16 20:43:21.000000000 +0530
+++ linux-2.6.8-rc4-prasanna/drivers/net/Makefile	2004-08-16 20:43:21.000000000 +0530
@@ -191,3 +191,6 @@ obj-$(CONFIG_HAMRADIO) += hamradio/
 obj-$(CONFIG_IRDA) += irda/
 
 obj-$(CONFIG_NETCONSOLE) += netconsole.o
+ifeq ($(CONFIG_NETPKTLOG),y)
+ obj-m += netpktlog.o
+endif
diff -puN /dev/null drivers/net/netpktlog.c
--- /dev/null	2003-01-30 15:54:37.000000000 +0530
+++ linux-2.6.8-rc4-prasanna/drivers/net/netpktlog.c	2004-08-16 20:43:35.000000000 +0530
@@ -0,0 +1,672 @@
+/*
+ *  Network Packet Tracer using Kernel Probes (KProbes)
+ *  net/driver/netpktlog.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Copyright (C) IBM Corporation, 2004
+ *
+ * 2004-Aug	Created by Prasanna S Panchamukhi <prasanna@in.ibm.com>
+ *		for network packet tracing using kernel probes interface.
+ * 		Suggested by Andi Kleen.
+ *
+ */
+#include <linux/module.h>
+#include <linux/kprobes.h>
+#include <linux/kallsyms.h>
+#include <linux/inet.h>
+#include <linux/ip.h>
+#include <linux/netdevice.h>
+#include <linux/netfilter_ipv4/ipt_LOG.h>
+#include <net/ip.h>
+#include <net/tcp.h>
+#include <net/udp.h>
+#include <net/icmp.h>
+
+static unsigned short source_port, target_port;
+module_param(source_port, ushort, S_IRUSR | S_IWUSR);
+module_param(target_port, ushort, S_IRUSR | S_IWUSR);
+
+void dump_packet_hdr(const struct ipt_log_info *info, struct sk_buff *skb)
+{
+	struct iphdr iph;
+
+	if (memcpy(&iph, skb->nh.iph, sizeof(iph)) < 0) {
+		printk("TRUNCATED");
+		return;
+	}
+
+	/* Important fields:
+	 * TOS, len, DF/MF, fragment offset, TTL, src, dst, options. */
+	/* Max length: 40 "SRC=255.255.255.255 DST=255.255.255.255 " */
+	printk("SRC=%u.%u.%u.%u DST=%u.%u.%u.%u ",
+	       NIPQUAD(iph.saddr), NIPQUAD(iph.daddr));
+
+	/* Max length: 46 "LEN=65535 TOS=0xFF PREC=0xFF TTL=255 ID=65535 " */
+	printk("LEN=%u TOS=0x%02X PREC=0x%02X TTL=%u ID=%u ",
+	       ntohs(iph.tot_len), iph.tos & IPTOS_TOS_MASK,
+	       iph.tos & IPTOS_PREC_MASK, iph.ttl, ntohs(iph.id));
+
+	/* Max length: 6 "CE DF MF " */
+	if (ntohs(iph.frag_off) & IP_CE)
+		printk("CE ");
+	if (ntohs(iph.frag_off) & IP_DF)
+		printk("DF ");
+	if (ntohs(iph.frag_off) & IP_MF)
+		printk("MF ");
+
+	/* Max length: 11 "FRAG:65535 " */
+	if (ntohs(iph.frag_off) & IP_OFFSET)
+		printk("FRAG:%u ", ntohs(iph.frag_off) & IP_OFFSET);
+
+	if ((info->logflags & IPT_LOG_IPOPT)
+	    && iph.ihl * 4 > sizeof(struct iphdr)) {
+		unsigned char opt[4 * 15 - sizeof(struct iphdr)];
+		unsigned int i, optsize;
+
+		optsize = iph.ihl * 4 - sizeof(struct iphdr);
+		if (memcpy(opt, skb->nh.iph + sizeof(iph), optsize) < 0) {
+			printk("TRUNCATED");
+			return;
+		}
+
+		/* Max length: 127 "OPT (" 15*4*2chars ") " */
+		printk("OPT (");
+		for (i = 0; i < optsize; i++)
+			printk("%02X", opt[i]);
+		printk(") ");
+	}
+
+	switch (iph.protocol) {
+	case IPPROTO_TCP:{
+			struct tcphdr tcph;
+
+			/* Max length: 10 "PROTO=TCP " */
+			printk("PROTO=TCP ");
+
+			if (ntohs(iph.frag_off) & IP_OFFSET)
+				break;
+
+			/* Max length: 25 "INCOMPLETE [65535 bytes] " */
+			if (memcpy(&tcph, skb->h.th, sizeof(tcph))
+			    < 0) {
+				printk("INCOMPLETE [%u bytes] ", iph.ihl * 4);
+				break;
+			}
+
+			/* Max length: 20 "SPT=65535 DPT=65535 " */
+			printk("SPT=%u DPT=%u ",
+			       ntohs(tcph.source), ntohs(tcph.dest));
+			/* Max length: 30 "SEQ=4294967295 ACK=4294967295 " */
+			if (info->logflags & IPT_LOG_TCPSEQ)
+				printk("SEQ=%u ACK=%u ",
+				       ntohl(tcph.seq), ntohl(tcph.ack_seq));
+			/* Max length: 13 "WINDOW=65535 " */
+			printk("WINDOW=%u ", ntohs(tcph.window));
+			/* Max length: 9 "RES=0x3F " */
+			printk("RES=0x%02x ",
+			       (u8) (ntohl
+				     (tcp_flag_word(&tcph) & TCP_RESERVED_BITS)
+				     >> 22));
+			/* Max length: 32 "CWR ECE URG ACK PSH RST SYN FIN " */
+			if (tcph.cwr)
+				printk("CWR ");
+			if (tcph.ece)
+				printk("ECE ");
+			if (tcph.urg)
+				printk("URG ");
+			if (tcph.ack)
+				printk("ACK ");
+			if (tcph.psh)
+				printk("PSH ");
+			if (tcph.rst)
+				printk("RST ");
+			if (tcph.syn)
+				printk("SYN ");
+			if (tcph.fin)
+				printk("FIN ");
+			/* Max length: 11 "URGP=65535 " */
+			printk("URGP=%u ", ntohs(tcph.urg_ptr));
+
+			if ((info->logflags & IPT_LOG_TCPOPT)
+			    && tcph.doff * 4 > sizeof(struct tcphdr)) {
+				unsigned char opt[4 * 15 -
+						  sizeof(struct tcphdr)];
+				unsigned int i, optsize;
+
+				optsize = tcph.doff * 4 - sizeof(struct tcphdr);
+				if (memcpy(opt, skb->h.th + sizeof(tcph),
+					   optsize) < 0) {
+					printk("TRUNCATED");
+					return;
+				}
+
+				/* Max length: 127 "OPT (" 15*4*2chars ") " */
+				printk("OPT (");
+				for (i = 0; i < optsize; i++)
+					printk("%02X", opt[i]);
+				printk(") ");
+			}
+			break;
+		}
+	case IPPROTO_UDP:{
+			struct udphdr udph;
+
+			/* Max length: 10 "PROTO=UDP " */
+			printk("PROTO=UDP ");
+
+			if (ntohs(iph.frag_off) & IP_OFFSET)
+				break;
+
+			/* Max length: 25 "INCOMPLETE [65535 bytes] " */
+			if (memcpy(&udph, skb->h.uh, sizeof(udph))
+			    < 0) {
+				printk("INCOMPLETE [%u bytes] ", iph.ihl * 4);
+				break;
+			}
+
+			/* Max length: 20 "SPT=65535 DPT=65535 " */
+			printk("SPT=%u DPT=%u LEN=%u ",
+			       ntohs(udph.source), ntohs(udph.dest),
+			       ntohs(udph.len));
+			break;
+		}
+	case IPPROTO_ICMP:{
+			struct icmphdr icmph;
+			/* Max length: 11 "PROTO=ICMP " */
+			printk("PROTO=ICMP ");
+
+			if (ntohs(iph.frag_off) & IP_OFFSET)
+				break;
+
+			/* Max length: 25 "INCOMPLETE [65535 bytes] " */
+			if (memcpy(&icmph, skb->h.icmph, sizeof(icmph))
+			    < 0) {
+				printk("INCOMPLETE [bytes] ");
+				break;
+			}
+
+			/* Max length: 18 "TYPE=255 CODE=255 " */
+			printk("TYPE=%u CODE=%u ", icmph.type, icmph.code);
+
+			switch (icmph.type) {
+			case ICMP_ECHOREPLY:
+			case ICMP_ECHO:
+				/* Max length: 19 "ID=65535 SEQ=65535 " */
+				printk("ID=%u SEQ=%u ",
+				       ntohs(icmph.un.echo.id),
+				       ntohs(icmph.un.echo.sequence));
+				break;
+
+			case ICMP_PARAMETERPROB:
+				/* Max length: 14 "PARAMETER=255 " */
+				printk("PARAMETER=%u ",
+				       ntohl(icmph.un.gateway) >> 24);
+				break;
+			case ICMP_REDIRECT:
+				/* Max length: 24 "GATEWAY=255.255.255.255 " */
+				printk("GATEWAY=%u.%u.%u.%u ",
+				       NIPQUAD(icmph.un.gateway));
+				/* Fall through */
+			case ICMP_DEST_UNREACH:
+			case ICMP_SOURCE_QUENCH:
+			case ICMP_TIME_EXCEEDED:
+				/* Max length: 10 "MTU=65535 " */
+				if (icmph.type == ICMP_DEST_UNREACH
+				    && icmph.code == ICMP_FRAG_NEEDED)
+					printk("MTU=%u ",
+					       ntohs(icmph.un.frag.mtu));
+			}
+			break;
+		}
+		/* Max Length */
+	case IPPROTO_AH:{
+			struct ip_auth_hdr ah;
+
+			if (ntohs(iph.frag_off) & IP_OFFSET)
+				break;
+
+			/* Max length: 9 "PROTO=AH " */
+			printk("PROTO=AH ");
+
+			/* Max length: 25 "INCOMPLETE [65535 bytes] " */
+			if (memcpy
+			    (&ah, skb->h.icmph + sizeof(struct icmphdr),
+			     sizeof(ah)) < 0) {
+				printk("INCOMPLETE [bytes] ");
+				break;
+			}
+
+			/* Length: 15 "SPI=0xF1234567 " */
+			printk("SPI=0x%x ", ntohl(ah.spi));
+			break;
+		}
+	case IPPROTO_ESP:{
+			struct ip_esp_hdr esph;
+
+			/* Max length: 10 "PROTO=ESP " */
+			printk("PROTO=ESP ");
+
+			if (ntohs(iph.frag_off) & IP_OFFSET)
+				break;
+
+			/* Max length: 25 "INCOMPLETE [65535 bytes] " */
+			if (memcpy
+			    (&esph, skb->h.icmph + sizeof(struct icmphdr),
+			     sizeof(esph))
+			    < 0) {
+				printk("INCOMPLETE [bytes] ");
+				break;
+			}
+
+			/* Length: 15 "SPI=0xF1234567 " */
+			printk("SPI=0x%x ", ntohl(esph.spi));
+			break;
+		}
+		/* Max length: 10 "PROTO 255 " */
+	default:
+		printk("PROTO=%u ", iph.protocol);
+	}
+
+	/* Proto    Max log string length */
+	/* IP:      40+46+6+11+127 = 230 */
+	/* TCP:     10+max(25,20+30+13+9+32+11+127) = 252 */
+	/* UDP:     10+max(25,20) = 35 */
+	/* ICMP:    11+max(25, 18+25+max(19,14,24+3+n+10,3+n+10)) = 91+n */
+	/* ESP:     10+max(25)+15 = 50 */
+	/* AH:      9+max(25)+15 = 49 */
+	/* unknown: 10 */
+
+	/* (ICMP allows recursion one level deep) */
+	/* maxlen =  IP + ICMP +  IP + max(TCP,UDP,ICMP,unknown) */
+	/* maxlen = 230+   91  + 230 + 252 = 803 */
+}
+
+/*
+ * nettrace_port: This is a generic routine that can be used to dump the
+ * network packet for a given source and destination port numbers.
+ * Network packet filtering is done based on source/target port or
+ * both source and target ports.
+ */
+
+static inline int nettrace_port(unsigned short source, unsigned short dest)
+{
+	if (((!source_port) && (!target_port))
+	    || ((!source_port) && (dest == target_port))
+	    || ((!target_port) && (source == source_port))
+	    || ((source == source_port) && (dest == target_port)))
+		return 0;
+
+	return 1;
+}
+
+static void get_ports_skb(struct sk_buff *skb, unsigned short *source,
+			  unsigned short *dest)
+{
+	struct iphdr *iph;
+	struct tcphdr *tcph;
+	struct udphdr *udph;
+	iph = (struct iphdr *)skb->data;
+
+	switch (iph->protocol) {
+	case IPPROTO_TCP:
+		tcph = (struct tcphdr *)((unsigned long)iph + iph->ihl * 4);
+		*source = ntohs(tcph->source);
+		*dest = ntohs(tcph->dest);
+		break;
+	case IPPROTO_UDP:
+		udph = (struct udphdr *)((unsigned long)iph + iph->ihl * 4);
+		*source = ntohs(udph->source);
+		*dest = ntohs(udph->dest);
+		break;
+	}
+}
+
+static void get_ports_net(struct sk_buff *skb, unsigned short *source,
+			  unsigned short *dest)
+{
+	struct iphdr *iph;
+	struct tcphdr *tcph;
+	struct udphdr *udph;
+
+	iph = (struct iphdr *)skb->nh.iph;
+	switch (iph->protocol) {
+	case IPPROTO_TCP:
+		tcph = (struct tcphdr *)skb->h.th;
+		*source = ntohs(tcph->source);
+		*dest = ntohs(tcph->dest);
+		break;
+	case IPPROTO_UDP:
+		udph = (struct udphdr *)skb->h.uh;
+		*source = ntohs(udph->source);
+		*dest = ntohs(udph->dest);
+		break;
+	}
+}
+
+/*
+ * Compile the kernel with options CONFIG_KPROBES, CONFIG_NETPKTLOG,
+ * CONFIG_NETFILTER, CONFIG_IP_NF_IPTABLES and CONFIG_IP_NF_TARGET_LOG enabled.
+ * You need to specify the parameters to the netpktlog module.
+ * To trace the network packets based on source and target ports, insert the
+ * module with source and target ports.
+ *	Example insmod netpktlog.ko source_port=35707 target_port=22
+ * To trace the network packets based on only source port, insert module
+ * with source port. Example insmod netpktlog.ko source_port=35707
+ * To trace network packets based on target port, insert module with
+ * target port.	Example insmod netpktlog.ko target_port=22
+ */
+static void jnetif_rx(struct sk_buff *skb)
+{
+	struct iphdr *iph;
+	struct ipt_log_info info;
+	unsigned short source, dest;
+	info.logflags = IPT_LOG_IPOPT;
+
+	if ((skb->protocol == htons(ETH_P_IP))
+	    && (iph = (struct iphdr *)skb->data)) {
+		get_ports_skb(skb, &source, &dest);
+		if (!nettrace_port(source, dest)) {
+			printk("netif_rx: ");
+			dump_packet((struct ipt_log_info *)&info, skb, 0);
+			printk("\n");
+		}
+	}
+	jprobe_return();
+}
+
+static void j__kfree_skb(struct sk_buff *skb)
+{
+	struct iphdr *iph;
+	struct ipt_log_info info;
+	unsigned short source, dest;
+	info.logflags = IPT_LOG_IPOPT;
+
+	if ((skb->protocol == htons(ETH_P_IP))
+	    && (iph = (struct iphdr *)skb->nh.iph)) {
+		get_ports_net(skb, &source, &dest);
+		if (!nettrace_port(source, dest)) {
+			printk("__kfree_skb: ");
+			dump_packet_hdr((struct ipt_log_info *)&info, skb);
+			printk("\n");
+		}
+	}
+	jprobe_return();
+}
+
+static int jnetif_receive_skb(struct sk_buff *skb)
+{
+	struct iphdr *iph;
+	unsigned short source, dest;
+	struct ipt_log_info info;
+	info.logflags = IPT_LOG_IPOPT;
+
+	if ((skb->protocol == htons(ETH_P_IP))
+	    && (iph = (struct iphdr *)skb->data)) {
+		get_ports_skb(skb, &source, &dest);
+		if (!nettrace_port(source, dest)) {
+			printk("netif_receive_skb: ");
+			dump_packet((struct ipt_log_info *)&info, skb, 0);
+			printk("\n");
+		}
+	}
+	jprobe_return();
+	return 0;
+}
+
+static int jip_rcv(struct sk_buff *skb, struct net_device *dev,
+		   struct packet_type *pt)
+{
+	struct iphdr *iph;
+	struct ipt_log_info info;
+	unsigned short source, dest;
+	info.logflags = IPT_LOG_IPOPT;
+
+	if ((skb->protocol == htons(ETH_P_IP))
+	    && (iph = (struct iphdr *)skb->data)) {
+		get_ports_skb(skb, &source, &dest);
+		if (!nettrace_port(source, dest)) {
+			printk("ip_rcv: ");
+			dump_packet((struct ipt_log_info *)&info, skb, 0);
+			printk("\n");
+		}
+	}
+	jprobe_return();
+	return 0;
+}
+
+static int jip_local_deliver(struct sk_buff *skb)
+{
+	struct iphdr *iph;
+	struct ipt_log_info info;
+	unsigned short source, dest;
+	info.logflags = IPT_LOG_IPOPT;
+
+	if ((skb->protocol == htons(ETH_P_IP))
+	    && (iph = (struct iphdr *)skb->data)) {
+		get_ports_skb(skb, &source, &dest);
+		if (!nettrace_port(source, dest)) {
+			printk("ip_local_deliver: ");
+			dump_packet((struct ipt_log_info *)&info, skb, 0);
+			printk("\n");
+		}
+	}
+	jprobe_return();
+	return 0;
+}
+
+static int jip_output(struct sk_buff **pskb)
+{
+	struct iphdr *iph;
+	struct ipt_log_info info;
+	unsigned short source, dest;
+	info.logflags = IPT_LOG_IPOPT;
+
+	iph = (struct iphdr *)(*pskb)->nh.iph;
+	if (iph) {
+		get_ports_net(*pskb, &source, &dest);
+		if (!nettrace_port(source, dest)) {
+			printk("ip_output: ");
+			dump_packet_hdr((struct ipt_log_info *)&info, (*pskb));
+			printk("\n");
+		}
+	}
+	jprobe_return();
+	return 0;
+}
+
+static int jtcp_v4_rcv(struct sk_buff *skb)
+{
+	struct iphdr *iph;
+	struct ipt_log_info info;
+	unsigned short source, dest;
+	info.logflags = IPT_LOG_IPOPT;
+
+	if ((skb->protocol == htons(ETH_P_IP))
+	    && (iph = (struct iphdr *)skb->nh.iph)) {
+		get_ports_net(skb, &source, &dest);
+		if (!nettrace_port(source, dest)) {
+			printk("tcp_v4_rcv: ");
+			dump_packet_hdr((struct ipt_log_info *)&info, skb);
+			printk("\n");
+		}
+	}
+	jprobe_return();
+	return 0;
+}
+
+static int jtcp_v4_do_rcv(struct sock *sk, struct sk_buff *skb)
+{
+	struct iphdr *iph;
+	struct ipt_log_info info;
+	unsigned short source, dest;
+	info.logflags = IPT_LOG_IPOPT;
+
+	if ((skb->protocol == htons(ETH_P_IP))
+	    && (iph = (struct iphdr *)skb->nh.iph)) {
+		get_ports_net(skb, &source, &dest);
+		if (!nettrace_port(source, dest)) {
+			printk("tcp_v4_do_rcv: ");
+			dump_packet_hdr((struct ipt_log_info *)&info, skb);
+			printk("\n");
+		}
+	}
+	jprobe_return();
+	return 0;
+}
+
+static int jtcp_rcv_established(struct sock *sk, struct sk_buff *skb,
+				struct tcphdr *th, unsigned len)
+{
+	struct iphdr *iph;
+	struct ipt_log_info info;
+	unsigned short source, dest;
+	info.logflags = IPT_LOG_IPOPT;
+
+	if ((skb->protocol == htons(ETH_P_IP))
+	    && (iph = (struct iphdr *)skb->nh.iph)) {
+		get_ports_net(skb, &source, &dest);
+		if (!nettrace_port(source, dest)) {
+			printk("tcp_rcv_established: ");
+			dump_packet_hdr((struct ipt_log_info *)&info, skb);
+			printk("\n");
+		}
+	}
+	jprobe_return();
+	return 0;
+}
+
+static int jskb_copy_datagram_iovec(struct sk_buff *from, int offset,
+				    struct iovec *to, int size)
+{
+	struct iphdr *iph;
+	struct ipt_log_info info;
+	unsigned short source, dest;
+	info.logflags = IPT_LOG_IPOPT;
+
+	if ((from->protocol == htons(ETH_P_IP))
+	    && (iph = (struct iphdr *)from->nh.iph)) {
+		get_ports_net(from, &source, &dest);
+		if (!nettrace_port(source, dest)) {
+			printk("skb_copy_datagram_iovec: ");
+			dump_packet_hdr((struct ipt_log_info *)&info, from);
+			printk("\n");
+		}
+	}
+	jprobe_return();
+	return 0;
+}
+
+static void jtcp_send_dupack(struct sock *sk, struct sk_buff *skb)
+{
+	struct iphdr *iph;
+	struct ipt_log_info info;
+	unsigned short source, dest;
+	info.logflags = IPT_LOG_IPOPT;
+
+	iph = (struct iphdr *)skb->nh.iph;
+	if (iph) {
+		get_ports_net(skb, &source, &dest);
+		if (!nettrace_port(source, dest)) {
+			printk("tcp_send_dupack: ");
+			dump_packet_hdr((struct ipt_log_info *)&info, skb);
+			printk("\n");
+		}
+	}
+	jprobe_return();
+}
+
+static int jip_forward(struct sk_buff *skb)
+{
+	struct iphdr *iph;
+	struct ipt_log_info info;
+	unsigned short source, dest;
+	info.logflags = IPT_LOG_IPOPT;
+
+	iph = (struct iphdr *)skb->nh.iph;
+	if (iph) {
+		get_ports_net(skb, &source, &dest);
+		if (!nettrace_port(source, dest)) {
+			printk("ip_forward: ");
+			dump_packet_hdr((struct ipt_log_info *)&info, skb);
+			printk("\n");
+		}
+	}
+	jprobe_return();
+	return 0;
+}
+
+struct nettrace_obj {
+	const char *funcname;
+	struct jprobe jp;
+};
+
+#define NTOBJ(func) \
+	{ .funcname = #func, .jp = { .entry = (kprobe_opcode_t*)j##func }}
+static struct nettrace_obj nettrace_objs[] = {
+	NTOBJ(netif_rx),
+	NTOBJ(__kfree_skb),
+	NTOBJ(netif_receive_skb),
+	NTOBJ(ip_rcv),
+	NTOBJ(ip_local_deliver),
+	NTOBJ(ip_output),
+	NTOBJ(ip_forward),
+	NTOBJ(tcp_v4_rcv),
+	NTOBJ(tcp_v4_do_rcv),
+	NTOBJ(tcp_rcv_established),
+	NTOBJ(skb_copy_datagram_iovec),
+	NTOBJ(tcp_send_dupack)
+};
+
+#define MAX_NETTRACE_ROUTINE (sizeof(nettrace_objs)/sizeof(nettrace_objs[0]))
+
+static int init_netpktlog(void)
+{
+	int i;
+	struct nettrace_obj *nt;
+
+	/* first time invokation to initialize probe handler */
+	/* now we are all set to register the probe */
+	for (i = 0, nt = nettrace_objs; i < MAX_NETTRACE_ROUTINE; i++, nt++) {
+		nt = &nettrace_objs[i];
+		nt->jp.kp.addr = (kprobe_opcode_t *)
+		    kallsyms_lookup_name(nt->funcname);
+		if (nt->jp.kp.addr) {
+			printk("plant jprobe at %s (%p), handler addr %p\n",
+			       nt->funcname, nt->jp.kp.addr, nt->jp.entry);
+			register_jprobe(&nt->jp);
+		} else {
+			printk("couldn't find %s to plant jprobe\n",
+			       nt->funcname);
+		}
+	}
+
+	printk("Network packets tracing is enabled...\n");
+	return 0;
+}
+
+static void cleanup_netpktlog(void)
+{
+	int i;
+	for (i = 0; i < MAX_NETTRACE_ROUTINE; i++) {
+		if (nettrace_objs[i].jp.kp.addr)
+			unregister_jprobe(&nettrace_objs[i].jp);
+	}
+	printk("Network packets tracing is disabled...\n");
+}
+
+module_init(init_netpktlog);
+module_exit(cleanup_netpktlog);
+MODULE_LICENSE("GPL");
diff -puN include/linux/netfilter_ipv4/ipt_LOG.h~kprobes-netpkt-tracer-268-rc4 include/linux/netfilter_ipv4/ipt_LOG.h
--- linux-2.6.8-rc4/include/linux/netfilter_ipv4/ipt_LOG.h~kprobes-netpkt-tracer-268-rc4	2004-08-16 20:43:21.000000000 +0530
+++ linux-2.6.8-rc4-prasanna/include/linux/netfilter_ipv4/ipt_LOG.h	2004-08-16 20:43:21.000000000 +0530
@@ -11,5 +11,7 @@ struct ipt_log_info {
 	unsigned char logflags;
 	char prefix[30];
 };
+void dump_packet(const struct ipt_log_info *info, const struct sk_buff *skb,
+			unsigned int iphoff);
 
 #endif /*_IPT_LOG_H*/
diff -puN kernel/kallsyms.c~kprobes-netpkt-tracer-268-rc4 kernel/kallsyms.c
--- linux-2.6.8-rc4/kernel/kallsyms.c~kprobes-netpkt-tracer-268-rc4	2004-08-16 20:43:21.000000000 +0530
+++ linux-2.6.8-rc4-prasanna/kernel/kallsyms.c	2004-08-16 20:43:21.000000000 +0530
@@ -310,3 +310,4 @@ int __init kallsyms_init(void)
 __initcall(kallsyms_init);
 
 EXPORT_SYMBOL(__print_symbol);
+EXPORT_SYMBOL(kallsyms_lookup_name);
diff -puN net/ipv4/netfilter/ipt_LOG.c~kprobes-netpkt-tracer-268-rc4 net/ipv4/netfilter/ipt_LOG.c
--- linux-2.6.8-rc4/net/ipv4/netfilter/ipt_LOG.c~kprobes-netpkt-tracer-268-rc4	2004-08-16 20:43:21.000000000 +0530
+++ linux-2.6.8-rc4-prasanna/net/ipv4/netfilter/ipt_LOG.c	2004-08-16 20:43:21.000000000 +0530
@@ -41,7 +41,7 @@ MODULE_PARM_DESC(nflog, "register as int
 static spinlock_t log_lock = SPIN_LOCK_UNLOCKED;
 
 /* One level of recursion won't kill us */
-static void dump_packet(const struct ipt_log_info *info,
+void dump_packet(const struct ipt_log_info *info,
 			const struct sk_buff *skb,
 			unsigned int iphoff)
 {
@@ -461,5 +461,6 @@ static void __exit fini(void)
 	ipt_unregister_target(&ipt_log_reg);
 }
 
+EXPORT_SYMBOL_GPL(dump_packet);
 module_init(init);
 module_exit(fini);

_

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2004-08-16 16:01 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-08-11 16:22 [4/4] Network packet tracer module using kprobes interface Prasanna S Panchamukhi
2004-08-12 12:35 ` Prasanna S Panchamukhi
2004-08-12 13:20   ` Andi Kleen
2004-08-16 15:55     ` Prasanna S Panchamukhi

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox