diff -PBbruw linux/Documentation/Configure.help magnet/Documentation/Configure.help
--- linux/Documentation/Configure.help	Sun Mar 25 19:24:31 2001
+++ magnet/Documentation/Configure.help	Tue Apr 10 10:08:12 2001
@@ -1785,6 +1785,33 @@
   You can say Y here if you want to get additional messages useful in
   debugging the netfilter code. 
 
+MAGNeT Network Instrumentation (EXPERIMENTAL)
+CONFIG_MAGNET
+  MAGNeT: the Monitor for Application Generated Network Traffic.
+  
+  This is kernel-side code which instruments the Linux network
+  subsystem.  It records incoming and outgoing packets at various
+  levels in the network stack(s), and records some pertinent details
+  of the packets (timestamps, etc).  It is of use only to protocol
+  designers, researchers, and implementors, and should be disabled
+  by all normal people.  Say N here.
+
+  See Documentation/magnet.txt for information on how to use MAGNeT.
+
+MAGNeT Extended Instrumentation
+CONFIG_MAGNET_EXTENDED
+  This enables MAGNeT to store extended information (ie, the entire
+  TCP state snapshot) with each data point.  This significantly adds
+  to the overhead of the instrumentation, and thus should not normally
+  be used.  Its here if you really need it.
+
+MAGNeT: Socket Calls Only
+CONFIG_MAGNET_SOCK_ONLY
+  For the absolute minimum of instrumentation overhead.  This tells
+  MAGNeT to only record application socket send() and recv() calls.
+  Thus, individual protocols (TCP, IP, etc) will NOT be monitored if
+  you say Y here.
+
 IP: connection tracking (required for masq/NAT)
 CONFIG_IP_NF_CONNTRACK
   Connection tracking keeps a record of what packets have passed
@@ -17339,6 +17366,7 @@
 #
 # This is used by Emacs' spell checker ispell.el:
 #
+# LocalWords:  MAGNeT recv
 # LocalWords:  CONFIG coprocessor DX Pentium SX lilo loadlin HOWTO ftp metalab
 # LocalWords:  unc edu docs emu README kB BLK DEV FD Thinkpad fd MFM RLL IDE gz
 # LocalWords:  cdrom diskless netboot nfs xzvf ATAPI MB ide pavia rubini pl pd
diff -PBbruw linux/Documentation/magnet.txt magnet/Documentation/magnet.txt
--- linux/Documentation/magnet.txt	Wed Dec 31 17:00:00 1969
+++ magnet/Documentation/magnet.txt	Tue Apr 10 10:36:38 2001
@@ -0,0 +1,90 @@
+MAGNet - Monitor for Application Generated Network Traffic
+----------------------------------------------------------
+
+MAGNeT is a research tool created by Los Alamos National Laboratory's RADIANT
+(Research and Development in Advanced Networking Technology) team.  The purpose
+of MAGNeT is to obtain an understanding of the actual network traffic patterns
+as that traffic traverses the networking stack in the kernel.  While
+traditional traffic monitoring solutions (ie, network sniffers) are capable of
+reporting traffic on the wire, this may or may not reflect the actual traffic
+patterns that applications generate -- for example, several small packets might
+be queued up by TCP before being sent across the network.  MAGNeT is the first
+tool designed to show application-level rather then wire-level traffic.
+
+This is accomplished by a small bit of code in the Linux kernel.  At strategic
+points in the processing of network traffic (for example, when the TCP code
+hands a packet of data to the IP layer, or when the kernel socket code hands
+data from the TCP layer to the running application), a quick routine is run
+to add a timestamp to a permanent, non-swappable kernel circular buffer.  Since
+this buffer space is guaranteed to be in memory, the marking has minimal impact
+on networking performance.  To read the recorded data, an user-level
+application simply mmaps() the kernel circular buffer and reads out of it as it
+is updated.
+
+This architecture allows MAGNeT to be used for any type of BSD Socket-based
+communication.  Currently, general socket calls (read(), write(), etc) and the
+TCP and IP layers are instrumented.  Additionally, the TCP and IP run-time 
+state snapshots can be optionally recorded at each timestamp. (This, of course,
+results in much more data being moved around, and thus a bigger performance
+impact)  In this mode, MAGNeT can be used by protocol designers and 
+implementors to debug the workings of their protocol under known conditions.
+
+MAGNeT currently consists of the following:
+
+include/linux/magnet.h -
+		    Header file to describe MAGNeT data types, for both kernel
+		    and user-level programs.  Also defines kernel function
+		    prototypes.
+
+net/magnet/magnet.c -
+		    The code to maintain the kernel circular buffer and 
+		    perform MAGNeT initialization and tear-down.
+
+net/magnet/magnet-read.c -
+		    Sample user-level program to read MAGNeT data from the
+		    kernel buffer.  This sample program works by mmapping a
+		    pre-existing file and transferring filesize bytes of data
+		    from the kernel to the file.  Rather simple, but usable.
+
+net/magnet/magnet-parse.c -
+		    Program to read binary data collected from the kernel
+		    buffer (ie, by magnet-read.c) and display the data in a
+		    human-readable form.  The timestamps reported are the CPU
+		    cycle counter (which ticks once per CPU clock/instruction).
+
+net/magnet/mkmagnet.c -
+		    Simple program to create the files which magnet-read.c 
+		    reads kernel data into.
+
+net/magnet/magnet.cron & net/magnet/magnet.copy -
+                    Simple shell scripts to automate running the above user
+                    space program to collect and archive data.  magnet.cron
+                    also takes care of creating the magnet device file (see
+                    below)
+
+The following kernel compilation options are available:
+
+CONFIG_MAGNET
+	Compile in the base MAGNeT code
+
+CONFIG_MAGNET_EXTENDED
+	Compile extended MAGNeT data (protocol state snapshots, etc)
+
+CONFIG_MAGNET_SOCK_ONLY
+	Normally, MAGNeT records data for all protocols for which MAGNeT is
+	implemented (currently, sockets, TCP, and IP).  This option limits
+	MAGNeT reporting to only socket-layer activities.
+
+A Linux system running with MAGNeT installed has two special files:
+
+/proc/net/magnet -
+		 Displaying this file displays various information about the
+		 currently running MAGNeT version, including size of data 
+		 packets, size of the kernel buffer, and other pertinent
+		 details.
+
+/dev/magnet -
+	    A special device file must be created to perform the mmap()ing from
+	    the kernel to user-level space.  /proc/net/magnet contains the
+	    name and major/minor mode numbers this special file requires.
+
diff -PBbruw linux/include/linux/magnet.h magnet/include/linux/magnet.h
--- linux/include/linux/magnet.h	Wed Dec 31 17:00:00 1969
+++ magnet/include/linux/magnet.h	Tue May  1 15:35:00 2001
@@ -0,0 +1,271 @@
+/*
+ * MAGNET	Monitor for Application Generated Network Traffic
+ *              - Define basic data structures for socket instrumentation
+ *
+ * Version:	@(#)magnet.h	1.0.0	2001/03/06
+ *
+ * Author:	Jeff Hay, <jrhay@lanl.gov>
+ *
+ * Fixes:
+ *
+ *		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.
+ *
+ */
+#ifndef _MAGNET_H
+#define _MAGNET_H
+
+#include <asm/timex.h>
+
+#ifdef __KERNEL__
+/* for macrology */
+#include <net/sock.h>
+#include <linux/tcp.h>
+#include <linux/ip.h>
+#endif
+
+#include <asm/page.h>  /* Need PAGE_SIZE definition (for user-mode apps) */
+#define MAGNET_DATA_SIZE 64*PAGE_SIZE /* System-wide magnet data buffer */
+
+/* Per-protocol/event storage area buffers */
+
+enum {  /* Defined magnet event types */
+  MAGNET_LOST = 0,     /* Lost data.  "size" = # records lost */
+
+  MAGNET_SOCK = 0xF,          /* Default - socket operations */
+  MAGNET_SOCK_SEND = 0x1,     /* Message sent to lower level protocol */
+  MAGNET_SOCK_RECV = 0x2,     /* Message received from lower level protocol */
+  MAGNET_SOCK_SENDCALL = 0x3, /* Application called send() */
+  MAGNET_SOCK_RECVCALL = 0x4, /* Application called recv() */
+  
+  MAGNET_TCP = 0xF0,          /* TCP Protocol event */
+  MAGNET_TCP_SSOCK = 0x10,    /* Received message from socket */
+  MAGNET_TCP_RSOCK = 0x20,    /* Sent message to socket */
+  MAGNET_TCP_SIP   = 0x30,    /* Received message from IP layer */
+  MAGNET_TCP_RIP   = 0x40,    /* Sent message to IP layer */
+
+  MAGNET_IP = 0xF00,          /* IP Protocol event */
+  MAGNET_IP_SEND = 0x100,     /* Sent message to network device */
+  MAGNET_IP_RECV = 0x200,     /* Received message from network device */
+
+  MAGNET_UNKNOWN = 0x1000,     /* Unknown Protocol - max value */
+  MAGNET_EMPTY   = 0x0FEFEFEFE,/* Empty Space created by mkmagnet */
+  MAGNET_SYSINFO = 0x0FFFFFFFF /* System Info packet */
+};
+#define MAX_MAGNET_EVENT MAGNET_UNKNOWN
+
+/* MAGNeT Version number:  0x 00     00    0000
+                              Major Minor  Revision */
+#define MAGNET_VERSION 0x01000000
+/* History: 0x00000000 -> Pre versioning info
+            0x01000000 -> MAGNeT 1.0.0 
+                           - CPU Cycle counter in MAGNET_SYSINFO is now in
+                             kHZ, not Hz.
+*/
+
+#ifdef CONFIG_MAGNET_EXTENDED
+
+/* Data and routines for extended instrumentation.  This significantly adds
+   to the space magnet packets take up in memory, but provides very detailed
+   reporting about the current running state.  Use as needed. 
+   Ideally, this would be a run-time-selectable thing, rather then a build-time
+   select.  
+
+  (data storage sizes in here need to be made platform-generic for both
+   kernel and user space routines.....) */
+
+
+/***
+// Extended SOCK-type information 
+***/
+struct magnet_sock {
+	pid_t   pid;
+	char    name[11];
+}; /* struct magnet_sock */
+
+#ifdef __KERNEL__
+extern __inline__ struct magnet_sock magnet_no_data(void) 
+{
+	struct magnet_sock sock;
+
+	memset((void *)&sock, '\0', sizeof(struct magnet_sock));
+	if (current == NULL)
+	  {
+	    sock.pid = 0;
+	    return sock;
+	  }
+	sock.pid = current->pid;
+
+// This doesn't work.  Things just freeze.  Not fun.  Don't do it.
+//	if (current->mm != NULL)
+//		access_process_vm(current, current->mm->arg_start, sock.name, 1, 0);
+// (It is supposed to get the PID's command line as an identifier... ah well..)
+	return sock;
+}
+
+/***
+// Dummy extended type for "No extended information"
+***/
+#define MAGNET_NO_DATA (union magnet_ext_data) magnet_no_data()
+#endif
+
+/***
+// Extended TCP-type information 
+***/
+struct magnet_tcp { /* data from "struct tcp_opt" in include/net/sock.h */
+
+	unsigned short  source;         /* TCP source port number            */
+	unsigned short  dest;           /* TCP destination port number       */
+
+	unsigned long	snd_wnd;	/* The window we expect to receive   */
+
+	unsigned long	srtt;		/* smothed round trip time << 3	     */
+  	unsigned long	rto;		/* retransmit timeout		     */
+
+  	unsigned long	packets_out;	/* Packets which are "in flight"     */
+  	unsigned long	retrans_out;	/* Retransmitted packets out	     */
+
+  	unsigned long	snd_ssthresh;	/* Slow start size threshold	     */
+  	unsigned long	snd_cwnd;	/* Sending congestion window	     */
+
+  	unsigned long	rcv_wnd;	/* Current receiver window	     */
+  	unsigned long	write_seq;	/* Tail+1 of data in tcp send buffer */
+  	unsigned long	copied_seq;	/* Head of yet unread data	     */
+
+	unsigned short  fin:1,syn:1,rst:1,psh:1,ack:1,urg:1,ece:1,cwr:1; /* TCP flags*/
+}; /* struct magnet_tcp */
+
+#ifdef __KERNEL__
+ extern __inline__ struct magnet_tcp magnet_tcp_data(
+	struct tcp_opt *tp, struct sk_buff *skb)
+{
+	struct magnet_tcp tcp;
+	struct tcphdr *head;
+
+	memset((void *)&tcp, '\0', sizeof(struct magnet_tcp));
+	if (tp != NULL) {
+	  tcp.snd_wnd = tp->snd_wnd; tcp.srtt = tp->srtt; tcp.rto = tp->rto;
+	  tcp.packets_out = tp->packets_out; tcp.retrans_out = tp->retrans_out;
+	  tcp.snd_ssthresh = tp->snd_ssthresh; tcp.snd_cwnd = tp->snd_cwnd;
+	  tcp.write_seq = tp->write_seq; tcp.copied_seq = tp->copied_seq;
+	}
+
+#if 0
+	/* Weird bug here -- even after the NULL checks, dereferencing head->
+	   will consistaintly fail the first time data comes in; works fine
+	   after that.... dunno why... */
+	if (skb != NULL) {
+	  head = skb->h.th;
+	  if (head != NULL) {
+	    tcp.source = head->source;
+	    tcp.dest = head->dest;
+	    tcp.fin = head->fin; tcp.syn = head->syn; tcp.psh = head->psh;
+	    tcp.ack = head->ack; tcp.urg = head->urg; tcp.ece = head->ece;
+	    tcp.cwr = head->cwr;
+	  }
+	}
+#endif
+
+	return tcp;
+}
+#define MAGNET_TCP_DATA (union magnet_ext_data) magnet_tcp_data(tp, skb)
+#endif
+
+/***
+// Extended IP-type information 
+***/
+
+struct magnet_ip {
+	unsigned char	version;
+	unsigned char	tos;
+	unsigned short	id;
+	unsigned short	frag_off;
+	unsigned char	ttl;
+	unsigned char	protocol;
+}; /* struct magnet_ip */
+
+#ifdef __KERNEL__
+extern __inline__ struct magnet_ip magnet_ip_data(struct iphdr *iph)
+{
+	struct magnet_ip ip;
+
+	memset((void *)&ip, '\0', sizeof(struct magnet_ip));
+	if (iph != NULL) {
+	  ip.version = iph->version; ip.tos = iph->tos; 
+	  ip.id = iph->id; ip.frag_off = iph->frag_off;
+	  ip.ttl = iph->ttl; ip.protocol = iph->protocol;
+	}
+	return ip;
+
+}
+#define MAGNET_IP_DATA (union magnet_ext_data) magnet_ip_data(iph)
+#endif
+
+/***
+// Declaration of magnet extended data type
+***/
+
+union magnet_ext_data { /* Stores data for different events */
+	struct magnet_sock sock;
+	struct magnet_tcp tcp;
+	struct magnet_ip ip;
+};                        
+
+#else // not defined CONFIG_MAGNET_EXTENDED
+
+union magnet_ext_data { int dummy; } magnet_false_data;
+#define MAGNET_IP_DATA magnet_false_data
+#define MAGNET_TCP_DATA magnet_false_data
+#define MAGNET_NO_DATA magnet_false_data
+
+#endif // defined CONFIG_MAGNET_EXTENDED
+
+struct magnet_data {
+	void *sockid;
+	unsigned long long timestamp;   /* Time of event (cycle counter) */
+	unsigned int event;             /* Kind of event */
+	unsigned int size;              /* Size (in bytes) of event */
+	union magnet_ext_data data;   /* Event-specific data */
+}; /* struct magnet_data */
+
+
+#ifdef __KERNEL__
+
+/*
+  Data structures and routines to do shared memory with user-space progs 
+*/
+
+#include <linux/proc_fs.h>
+
+extern int magnet_open(struct inode *inode, struct file *file);
+extern int magnet_close(struct inode *inode, struct file *file);
+extern int magnet_mmap(struct file *file, struct vm_area_struct *vma);
+extern struct page * magnet_nopage(struct vm_area_struct *vma,
+				     unsigned long address,
+				     int no_share);
+
+/* 
+   Routines to access magnet_buffers 
+*/
+
+/* Copy data to the system-wide socket buffer */
+extern  __inline__ void magnet_copy(void *data, int len);
+ 
+/* Add an event to a per-socket queue */
+extern __inline__ void magnet_add(struct sock *sk,
+				    unsigned int magnet_event,
+				    unsigned int magnet_size,
+				    union magnet_ext_data data);
+
+/* Initialize this socket's instrumentation interface */
+extern __inline__ int magnet_setup(void);
+extern __inline__ void magnet_init(void);
+
+/* Teardown this socket's instrumentation ineterface */
+extern __inline__ void magnet_destroy(void);
+
+#endif /* __KERNEL__ */
+
+#endif	/* _MAGNET_H */
diff -PBbruw linux/net/Config.in magnet/net/Config.in
--- linux/net/Config.in	Tue Mar  6 23:44:15 2001
+++ magnet/net/Config.in	Tue Apr 10 10:03:53 2001
@@ -17,6 +17,12 @@
    bool '  Network packet filtering debugging' CONFIG_NETFILTER_DEBUG
 fi
 bool 'Socket Filtering'  CONFIG_FILTER
+if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+   bool 'MAGNeT: Socket Instrumentation interface' CONFIG_MAGNET
+fi
+if [ "$CONFIG_MAGNET" = "y" ]; then
+   source net/magnet/Config.in
+fi
 tristate 'Unix domain sockets' CONFIG_UNIX
 bool 'TCP/IP networking' CONFIG_INET
 if [ "$CONFIG_INET" = "y" ]; then
diff -PBbruw linux/net/Makefile magnet/net/Makefile
--- linux/net/Makefile	Fri Dec 29 15:07:24 2000
+++ magnet/net/Makefile	Tue Apr 10 10:03:53 2001
@@ -45,6 +45,8 @@
 subdir-$(CONFIG_DECNET)		+= decnet
 subdir-$(CONFIG_ECONET)		+= econet
 
+subdir-$(CONFIG_MAGNET)		+= magnet
+
 
 obj-y	:= socket.o $(join $(subdir-y), $(patsubst %,/%.o,$(notdir $(subdir-y))))
 ifeq ($(CONFIG_NET),y)
diff -PBbruw linux/net/README magnet/net/README
--- linux/net/README	Thu Nov  9 16:57:53 2000
+++ magnet/net/README	Tue Apr 10 10:03:53 2001
@@ -21,5 +21,6 @@
 wanrouter		gene@compuserve.com, jaspreet@sangoma and dm@sangoma.com
 unix			alan@lxorguk.ukuu.org.uk
 x25			g4klx@g4klx.demon.co.uk
+magnet			jrhay@lanl.gov
 
 
diff -PBbruw linux/net/core/sock.c magnet/net/core/sock.c
--- linux/net/core/sock.c	Sat Feb  3 12:26:44 2001
+++ magnet/net/core/sock.c	Tue Apr 10 10:03:53 2001
@@ -586,6 +586,9 @@
 		sock_lock_init(sk);
 	}
 
+	/* MAGNET: This is where we'd call the per-socket magnet_setup()
+	   function, if we had one... */
+
 	return sk;
 }
 
@@ -594,6 +597,9 @@
 #ifdef CONFIG_FILTER
 	struct sk_filter *filter;
 #endif
+
+	/* MAGNET: This is where we'd call the per-socket magnet_destroy()
+	   function, if we had one... */
 
 	if (sk->destruct)
 		sk->destruct(sk);
diff -PBbruw linux/net/ipv4/ip_input.c magnet/net/ipv4/ip_input.c
--- linux/net/ipv4/ip_input.c	Mon Dec 11 13:37:04 2000
+++ magnet/net/ipv4/ip_input.c	Tue Apr 10 10:03:53 2001
@@ -144,6 +144,10 @@
 #include <linux/mroute.h>
 #include <linux/netlink.h>
 
+#ifdef CONFIG_MAGNET
+#include <linux/magnet.h>
+#endif
+
 /*
  *	SNMP management statistics
  */
@@ -234,6 +238,12 @@
 		struct sock *raw_sk = raw_v4_htable[hash];
 		struct inet_protocol *ipprot;
 		int flag;
+
+#ifdef CONFIG_MAGNET
+		/* Mark IP hand-off to the upper layer protocol */
+		magnet_add(raw_sk, MAGNET_IP_RECV, skb->len,
+			     MAGNET_IP_DATA);
+#endif
 
 		/* If there maybe a raw socket we must check - if not we
 		 * don't care less
diff -PBbruw linux/net/ipv4/ip_output.c magnet/net/ipv4/ip_output.c
--- linux/net/ipv4/ip_output.c	Fri Oct 27 12:03:14 2000
+++ magnet/net/ipv4/ip_output.c	Tue Apr 10 10:03:53 2001
@@ -77,6 +77,10 @@
 #include <linux/mroute.h>
 #include <linux/netlink.h>
 
+#ifdef CONFIG_MAGNET
+#include <linux/magnet.h>
+#endif
+
 /*
  *      Shall we try to damage output packets if routing dev changes?
  */
@@ -149,6 +153,11 @@
 		ip_options_build(skb, opt, daddr, rt, 0);
 	}
 	ip_send_check(iph);
+
+#ifdef CONFIG_MAGNET
+	/* Mark IP hand-off to the physical layer */
+	magnet_add(sk, MAGNET_IP_SEND, skb->len, MAGNET_IP_DATA);
+#endif
 
 	/* Send it out. */
 	return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
diff -PBbruw linux/net/ipv4/tcp.c magnet/net/ipv4/tcp.c
--- linux/net/ipv4/tcp.c	Fri Feb  9 12:34:13 2001
+++ magnet/net/ipv4/tcp.c	Tue Apr 10 10:03:53 2001
@@ -258,6 +258,10 @@
 #include <asm/uaccess.h>
 #include <asm/ioctls.h>
 
+#if defined (CONFIG_MAGNET)
+#include <linux/magnet.h>
+#endif
+
 int sysctl_tcp_fin_timeout = TCP_FIN_TIMEOUT;
 
 struct tcp_mib	tcp_statistics[NR_CPUS*2];
@@ -1366,6 +1370,11 @@
 
 		err = 0;
 		if (!(flags&MSG_TRUNC)) {
+#ifdef CONFIG_MAGNET
+			/* Mark the TCP hand-off to Socket */
+			magnet_add(sk,MAGNET_TCP_RSOCK,used,MAGNET_TCP_DATA);
+#endif
+
 			err = memcpy_toiovec(msg->msg_iov, ((unsigned char *)skb->h.th) + skb->h.th->doff*4 + offset, used);
 			if (err) {
 				/* Exception. Bailout! */
diff -PBbruw linux/net/ipv4/tcp_ipv4.c magnet/net/ipv4/tcp_ipv4.c
--- linux/net/ipv4/tcp_ipv4.c	Mon Jan  1 12:01:58 2001
+++ magnet/net/ipv4/tcp_ipv4.c	Tue Apr 10 10:03:53 2001
@@ -63,6 +63,10 @@
 #include <linux/stddef.h>
 #include <linux/ipsec.h>
 
+#if defined (CONFIG_MAGNET)
+#include <linux/magnet.h>
+#endif
+
 extern int sysctl_ip_dynaddr;
 
 /* Check TCP sequence numbers in ICMP packets. */
@@ -1606,6 +1610,9 @@
 	struct tcphdr *th;
 	struct sock *sk;
 	int ret;
+#ifdef CONFIG_MAGNET
+	struct tcp_opt *tp = NULL;
+#endif
 
 	if (skb->pkt_type!=PACKET_HOST)
 		goto discard_it;
@@ -1641,6 +1648,13 @@
 
 	if (!sk)
 		goto no_tcp_socket;
+
+
+#ifdef CONFIG_MAGNET
+	/* Mark TCP receive from IP layer */
+	tp = &(sk->tp_pinfo.af_tcp);
+	magnet_add(sk, MAGNET_TCP_SIP, len, MAGNET_TCP_DATA);
+#endif
 
 process:
 	if(!ipsec_sk_policy(sk,skb))
diff -PBbruw linux/net/ipv4/tcp_output.c magnet/net/ipv4/tcp_output.c
--- linux/net/ipv4/tcp_output.c	Tue Nov 28 22:53:45 2000
+++ magnet/net/ipv4/tcp_output.c	Tue Apr 10 10:03:53 2001
@@ -40,6 +40,10 @@
 
 #include <linux/smp_lock.h>
 
+#ifdef CONFIG_MAGNET
+#include <linux/magnet.h>
+#endif
+
 /* People can turn this off for buggy TCP's found in printers etc. */
 int sysctl_tcp_retrans_collapse = 1;
 
@@ -285,6 +289,10 @@
 
 		TCP_INC_STATS(TcpOutSegs);
 
+#ifdef CONFIG_MAGNET
+		/* Mark TCP hand-off to the IP layer */
+		magnet_add(sk, MAGNET_TCP_RIP, skb->len, MAGNET_TCP_DATA);
+#endif
 		err = tp->af_specific->queue_xmit(skb);
 		if (err <= 0)
 			return err;
@@ -315,6 +323,11 @@
 void tcp_send_skb(struct sock *sk, struct sk_buff *skb, int force_queue, unsigned cur_mss)
 {
 	struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+
+#ifdef CONFIG_MAGNET
+	/* Mark the socket hand-off to TCP */
+	magnet_add(sk,MAGNET_TCP_SSOCK,skb->len,MAGNET_TCP_DATA);
+#endif
 
 	/* Advance write_seq and place onto the write_queue. */
 	tp->write_seq = TCP_SKB_CB(skb)->end_seq;
diff -PBbruw linux/net/magnet/Config.in magnet/net/magnet/Config.in
--- linux/net/magnet/Config.in	Wed Dec 31 17:00:00 1969
+++ magnet/net/magnet/Config.in	Tue Apr 10 10:03:53 2001
@@ -0,0 +1,5 @@
+#
+# MAGNeT configuration
+# 
+bool '    MAGNeT: Enable Extended Instrumentation' CONFIG_MAGNET_EXTENDED
+bool '    MAGNeT: Instrument only socket calls (no protocol stack)' CONFIG_MAGNET_SOCK_ONLY
diff -PBbruw linux/net/magnet/Makefile magnet/net/magnet/Makefile
--- linux/net/magnet/Makefile	Wed Dec 31 17:00:00 1969
+++ magnet/net/magnet/Makefile	Tue Apr 10 10:03:53 2001
@@ -0,0 +1,15 @@
+#
+# Makefile for the socket instrumentation interface.
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+# Note 2! The CFLAGS definition is now in the main makefile...
+
+O_TARGET :=
+
+obj-y = magnet.o
+
+include $(TOPDIR)/Rules.make
+
diff -PBbruw linux/net/magnet/magnet-extract.c magnet/net/magnet/magnet-extract.c
--- linux/net/magnet/magnet-extract.c	Wed Dec 31 17:00:00 1969
+++ magnet/net/magnet/magnet-extract.c	Tue Apr 24 11:02:36 2001
@@ -0,0 +1,200 @@
+/*
+  MAGNeT - Monitor for Application-Generated Network Traffic
+         - MAGNeT data extractor
+	 - Written by Jeff Hay, jrhay@lanl.gov
+*/
+
+/* This is an application, distributed with the kernel source.  Therefore, its
+   likely to be built with the default kernel Makefiles, which define the 
+   __KERNEL__ flag.  Undo this nonsense for this program... */
+#ifdef __KERNEL__
+#undef __KERNEL__
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <linux/magnet.h>
+
+
+/* Report what we know  */
+int magnet_extract(void *magnet_data, int *datalen, char *buf, int len)
+{
+	struct magnet_data *sicurrent;
+	char *name;
+	int count, outlen, offset;
+	int error = 0;
+	
+	len = len - 1;
+	outlen = offset = 0;
+	while (((*datalen - offset) >= sizeof(struct magnet_data)) && 
+	       (outlen < len))  {
+		sicurrent = (struct magnet_data *)(magnet_data+offset);
+		count = snprintf(buf+outlen, len-outlen, 
+				 "%llu\t%p\t%6u\t%s\t%s\n", 
+				 sicurrent->timestamp,
+				 sicurrent->sockid,
+				 sicurrent->size, 
+				 (name = magnet_event_name(sicurrent->event)),
+				 magnet_extended_data(sicurrent->event, 
+						      sicurrent->data)
+			);
+		if (!strcmp(name, "Unknown")) {
+			fprintf(stderr, 
+		     "Error: Unknown MAGNeT Event Type Found in Data File!\n");
+			return -1 * offset;
+		}
+		
+		if ((outlen+count) <= len)
+		{ /* Make sure we only output complete lines */
+			outlen += count;
+			offset += sizeof(struct magnet_data);
+		}
+		else
+			*datalen = offset;
+	}
+	
+	if (outlen > 0)
+		buf[outlen] = '\0';
+	*datalen = offset;
+	
+	if (error > 0)
+		outlen = -1 * outlen;
+	
+	return outlen;
+} /* magnet_parse() */
+
+void hexprint(void *buffer, int buflen, int From, int To, int Mark) 
+/* Prints a "hex dump" of a specified region of memory.  Each line of the dump
+   contains 16 bytes of data, with an offset, hex values, and text translation,
+   and looks something like:
+   "864: D9 CA 28 DA AB 87 48 D9 10 0C 93 C3 80 36 EE C3  || ..(...H......6.."
+
+   The dump proceeds from byte "From" to byte "To" of buffer.  If Mark
+   is non-zero, then the byte at abs(Mark) is specially indicated.  If
+   From is less then 0, or greater then buflen, From is forced to zero.
+   If To is less then or equal to zero, less then or equal to From, or
+   greater then buflen, it too is forced to zero.  If the value of Mark
+   is outside the range formed by From and To, Mark is forced to zero.
+   Byte counting starts at zero.
+*/
+
+{
+	int count, out;
+	char letter;
+	char hex[45], text[17];
+
+	/* Error Checking - make sure we're all within our boundries */
+	if ((From < 0) || (From > buflen))
+		From = 0;
+	if ((To <= 0) || (To > buflen) || (To <= From))
+		To = buflen;
+	Mark = abs(Mark);
+	if ((Mark < From) || (Mark > To))
+		Mark = 0;
+	
+	hex[0] = '\0';
+	text[0] = '\0';
+	out = 0;
+	for(count=From; count <= To; count++) {
+		/* Print hex value of the next byte, 
+		   and store that value in 'letter' */
+		sprintf(hex, "%s%2.2X ", hex, 
+			(((char *)buffer)[count] & 0x0FF));
+		letter = ((char *)buffer)[count];
+		
+		/* If 'letter' is within printable ASCII character range,
+		   print it; otherwise, print a '.' */
+		if ((letter >= ' ') && (letter <= '~'))
+			sprintf(text, "%s%c", text, letter);
+		else
+			sprintf(text, "%s.", text);
+		
+		/* If we've processed an output-line worth, print the line, 
+		   Marking the Mark byte, if requested */
+		out++;
+		if ((out % 16) == 0) {
+			if ((Mark > 0) && (Mark < (count+1))) {
+				printf("%d: %s *| %s (%d)\n", 
+				       (count-15), hex, text, 
+				       16 - (count - Mark));
+				Mark = 0;
+			}
+			else
+				printf("%d: %s || %s\n", 
+				       (count-15), hex, text);
+			hex[0] = '\0';
+			text[0] = '\0';
+		}
+	}
+	/* Print remaining information (processed, but not a full line) */
+	printf("%d: %-48s || %-16s\n", (count-(count%16)), hex, text);
+	
+	return;
+} /* hexprint() */
+
+
+int main(int argc, char *argv[]) {
+  FILE *infile;
+  struct magnet_data* magnet_data; /* Shared memory region */
+  unsigned long long bytes;
+  unsigned long long outcount;
+  char outbuf[4096];
+  int count, error, offset;
+
+
+  printf("%s: MAGNeT Data File Reader\n\n", argv[0]);
+  
+  if (argc < 2) {
+    fprintf(stderr," syntax: %s <MAGNeT data file> \n\n", argv[0]);
+    return -1;
+  }
+  
+  if ((infile = fopen(argv[1], "r")) == NULL) {
+    fprintf(stderr,"%s: Unable to read input file \"%s\"\n",argv[0],argv[1]);
+    return -2;
+  }
+
+  if ((magnet_data=malloc(MAGNET_DATA_SIZE)) == NULL) {
+    fprintf(stderr, "%s: Can not allocate read buffer\n", argv[0]);
+    return -3;
+  }
+
+  bytes=0;
+  outcount=0;
+  count = 0;
+  while ((count = fread(((void*)magnet_data)+count, 
+			1, MAGNET_DATA_SIZE-count, infile)) > 0) {
+    bytes += count;
+    if ((error=magnet_parse(magnet_data, &count, outbuf, sizeof(outbuf))) > 0)
+      {
+	outcount++;
+	printf("%s\n", outbuf);
+	if (count < MAGNET_DATA_SIZE)
+	  memcpy(magnet_data, ((void *)magnet_data)+count, MAGNET_DATA_SIZE-count);
+	count = MAGNET_DATA_SIZE-count;
+      }
+    else
+      {
+	printf("ERROR - <%llu>: %s -- ERROR\n", outcount, outbuf);
+	printf("Error at position %llu\n", (bytes + abs(error)));
+	offset = (-1 * error);
+	
+	printf("Union Size: %d\n", sizeof(union magnet_ext_data));
+	hexprint((void *)magnet_data, MAGNET_DATA_SIZE, 
+		 offset - sizeof(struct magnet_data), offset-1, 0);
+	printf("\n");
+	hexprint((void *)magnet_data, MAGNET_DATA_SIZE, 
+		 offset, offset+sizeof(struct magnet_data)-1,error);
+	printf("\n");
+	hexprint((void *)magnet_data, MAGNET_DATA_SIZE, 
+		 offset + sizeof(struct magnet_data),
+		 offset + 2*sizeof(struct magnet_data)-1, 0);
+	printf("\n");
+	return -4;
+      }
+  }
+  
+  free(magnet_data);
+  fclose(infile);
+  return 0;
+} /* main() */
diff -PBbruw linux/net/magnet/magnet-parse.c magnet/net/magnet/magnet-parse.c
--- linux/net/magnet/magnet-parse.c	Wed Dec 31 17:00:00 1969
+++ magnet/net/magnet/magnet-parse.c	Tue May  1 15:44:14 2001
@@ -0,0 +1,314 @@
+/*
+  MAGNeT - Monitor for Application-Generated Network Traffic
+         - MAGNeT data file to ASCII text convertor
+	 - Written by Jeff Hay, jrhay@lanl.gov
+*/
+
+/* This is an application, distributed with the kernel source.  Therefore, its
+   likely to be built with the default kernel Makefiles, which define the 
+   __KERNEL__ flag.  Undo this nonsense for this program... */
+#ifdef __KERNEL__
+#undef __KERNEL__
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <linux/magnet.h>
+
+/* Translate a  event code to a human-readable name */
+char *magnet_event_name(int event)
+{
+	char *name;
+	
+	switch (event) {
+	case MAGNET_LOST: name = "Lost";
+		break;
+		
+	case MAGNET_SOCK: name = "Socket";
+		break;
+	case MAGNET_SOCK_SEND: name = "Send";
+		break;
+	case MAGNET_SOCK_RECV: name = "Receive";
+		break;
+	case MAGNET_SOCK_SENDCALL: name = "SndCall";
+		break;
+	case MAGNET_SOCK_RECVCALL: name = "RcvCall";
+		break;
+		
+	case MAGNET_TCP: name = "TCP";
+		break;
+	case MAGNET_TCP_SSOCK: name = "Ap->TCP";
+		break;
+ 	case MAGNET_TCP_RSOCK: name = "TCP->Ap";
+		break;
+	case MAGNET_TCP_SIP: name = "IP->TCP";
+		break;
+	case MAGNET_TCP_RIP: name = "TCP->IP";
+		break;
+		
+	case MAGNET_IP: name = "IP";
+		break;
+	case MAGNET_IP_SEND: name = "IP->net";
+		break;
+	case MAGNET_IP_RECV: name = "net->IP";
+		break;
+
+	case MAGNET_EMPTY: name = "Empty";
+		break;
+		
+	case MAGNET_SYSINFO: name = "SysInfo";
+		break;
+
+	default: 	  
+		name = "Unknown";
+	}
+	
+	return name;
+} /* magnet_event_name() */
+
+/* Print extended event data in human-readable form */
+char *magnet_extended_data(int event, union magnet_ext_data data)
+{
+	
+#ifdef CONFIG_MAGNET_EXTENDED
+	static char databuf[1024];
+	int count;
+	
+	count = 0;
+	if (event & MAGNET_SOCK) {
+		count += sprintf(databuf, "pid=%d,name=%s", 
+				 data.sock.pid, data.sock.name);
+		/* Socket Events */
+	} else if (event & MAGNET_TCP) {
+		/* TCP Events */
+		count += sprintf(databuf,
+#if 0
+				 "source=%u,dest=%u,"
+				 "fin=%u,rst=%u,psh=%u,ack=%u,urg=%u,ece=%u,"
+				 "cwr=%u"
+#endif
+				 "snd_wnd=%lu,srtt=%lu,rto=%lu,packets_out=%lu"
+				 "retrans_out=%lu,snd_ssthresh=%lu,"
+				 "snd_cwnd=%lu,rcv_wnd=%lu,write_seq=%lu,"
+				 "copied_seq=%lu",
+#if 0
+				 data.tcp.source,data.tcp.dest,
+				 data.tcp.fin,data.tcp.rst,data.tcp.psh,
+				 data.tcp.ack,data.tcp.urg,data.tcp.ece,
+				 data.tcp.cwr,
+#endif
+				 data.tcp.snd_wnd,data.tcp.srtt,data.tcp.rto,
+				 data.tcp.packets_out,data.tcp.retrans_out,
+				 data.tcp.snd_ssthresh,data.tcp.snd_cwnd,
+				 data.tcp.rcv_wnd,data.tcp.write_seq, 
+				 data.tcp.copied_seq);
+	} else if (event & MAGNET_IP) {
+		/* IP Events */
+		count += sprintf(databuf,
+				 "version=%u,tos=%u,id=%u,frag_off=%u,"
+				 "ttl=%u,protocol=%u",
+				 data.ip.version,data.ip.tos, data.ip.id,
+				 data.ip.frag_off,data.ip.ttl, 
+				 data.ip.protocol);
+	}
+	
+	databuf[count] = '\0';
+	
+	return databuf;
+#else
+	char *databuf = "";
+	return databuf;
+#endif // defined CONFIG_MAGNET_EXTENDED
+	
+} /* magnet_extended_data() */
+
+/* Report what we know  */
+int magnet_parse(void *magnet_data, int *datalen, char *buf, int len)
+{
+	struct magnet_data *sicurrent;
+	char *name;
+	int count, outlen, offset;
+	int error = 0;
+	
+	len = len - 1;
+	outlen = offset = 0;
+	while (((*datalen - offset) >= sizeof(struct magnet_data)) && 
+	       (outlen < len))  {
+		sicurrent = (struct magnet_data *)(magnet_data+offset);
+		count = snprintf(buf+outlen, len-outlen, 
+				 "%llu\t%p\t%6u\t%s\t%s\n", 
+				 sicurrent->timestamp,
+				 sicurrent->sockid,
+				 sicurrent->size, 
+				 (name = magnet_event_name(sicurrent->event)),
+				 magnet_extended_data(sicurrent->event, 
+						      sicurrent->data)
+			);
+		if (!strcmp(name, "Unknown")) {
+			fprintf(stderr, 
+		     "Error: Unknown MAGNeT Event Type Found in Data File!\n");
+			return -1 * offset;
+		}
+		
+		if ((outlen+count) <= len)
+		{ /* Make sure we only output complete lines */
+			outlen += count;
+			offset += sizeof(struct magnet_data);
+		}
+		else
+			*datalen = offset;
+	}
+	
+	if (outlen > 0)
+		buf[outlen] = '\0';
+	*datalen = offset;
+	
+	if (error > 0)
+		outlen = -1 * outlen;
+	
+	return outlen;
+} /* magnet_parse() */
+
+void hexprint(void *buffer, int buflen, int From, int To, int Mark) 
+/* Prints a "hex dump" of a specified region of memory.  Each line of the dump
+   contains 16 bytes of data, with an offset, hex values, and text translation,
+   and looks something like:
+   "864: D9 CA 28 DA AB 87 48 D9 10 0C 93 C3 80 36 EE C3  || ..(...H......6.."
+
+   The dump proceeds from byte "From" to byte "To" of buffer.  If Mark
+   is non-zero, then the byte at abs(Mark) is specially indicated.  If
+   From is less then 0, or greater then buflen, From is forced to zero.
+   If To is less then or equal to zero, less then or equal to From, or
+   greater then buflen, it too is forced to zero.  If the value of Mark
+   is outside the range formed by From and To, Mark is forced to zero.
+   Byte counting starts at zero.
+*/
+
+{
+	int count, out;
+	char letter;
+	char hex[45], text[17];
+
+	/* Error Checking - make sure we're all within our boundries */
+	if ((From < 0) || (From > buflen))
+		From = 0;
+	if ((To <= 0) || (To > buflen) || (To <= From))
+		To = buflen;
+	Mark = abs(Mark);
+	if ((Mark < From) || (Mark > To))
+		Mark = 0;
+	
+	hex[0] = '\0';
+	text[0] = '\0';
+	out = 0;
+	for(count=From; count <= To; count++) {
+		/* Print hex value of the next byte, 
+		   and store that value in 'letter' */
+		sprintf(hex, "%s%2.2X ", hex, 
+			(((char *)buffer)[count] & 0x0FF));
+		letter = ((char *)buffer)[count];
+		
+		/* If 'letter' is within printable ASCII character range,
+		   print it; otherwise, print a '.' */
+		if ((letter >= ' ') && (letter <= '~'))
+			sprintf(text, "%s%c", text, letter);
+		else
+			sprintf(text, "%s.", text);
+		
+		/* If we've processed an output-line worth, print the line, 
+		   Marking the Mark byte, if requested */
+		out++;
+		if ((out % 16) == 0) {
+			if ((Mark > 0) && (Mark < (count+1))) {
+				printf("%d: %s *| %s (%d)\n", 
+				       (count-15), hex, text, 
+				       16 - (count - Mark));
+				Mark = 0;
+			}
+			else
+				printf("%d: %s || %s\n", 
+				       (count-15), hex, text);
+			hex[0] = '\0';
+			text[0] = '\0';
+		}
+	}
+	/* Print remaining information (processed, but not a full line) */
+	printf("%d: %-48s || %-16s\n", (count-(count%16)), hex, text);
+	
+	return;
+} /* hexprint() */
+
+
+int main(int argc, char *argv[]) {
+  FILE *infile;
+  struct magnet_data* magnet_data; /* Shared memory region */
+  unsigned long long bytes;
+  unsigned long long outcount;
+  char outbuf[4096];
+  int count, error, offset;
+
+
+  printf("%s: MAGNeT Data File Reader\n\n", argv[0]);
+  
+  if (argc < 2) {
+    fprintf(stderr," syntax: %s <MAGNeT data file> \n\n", argv[0]);
+    return -1;
+  }
+  
+  if (!strcmp(argv[1], "-")) {
+	  if ((infile = fdopen(0, "r")) == NULL) {
+		  fprintf(stderr, "%s: Unable to read stdin\n", argv[0]);
+		  return -2;
+	  }
+  } else {
+	  if ((infile = fopen(argv[1], "r")) == NULL) {
+		  fprintf(stderr, "%s: Unable to read input file \"%s\"\n",
+			  argv[0], argv[1]);
+		  return -2;
+	  }
+  }
+
+  if ((magnet_data=malloc(MAGNET_DATA_SIZE)) == NULL) {
+    fprintf(stderr, "%s: Can not allocate read buffer\n", argv[0]);
+    return -3;
+  }
+
+  bytes=0;
+  outcount=0;
+  count = 0;
+  while ((count = fread(((void*)magnet_data)+count, 
+			1, MAGNET_DATA_SIZE-count, infile)) > 0) {
+    bytes += count;
+    if ((error=magnet_parse(magnet_data, &count, outbuf, sizeof(outbuf))) > 0)
+      {
+	outcount++;
+	printf("%s\n", outbuf);
+	if (count < MAGNET_DATA_SIZE)
+	  memcpy(magnet_data, ((void *)magnet_data)+count, MAGNET_DATA_SIZE-count);
+	count = MAGNET_DATA_SIZE-count;
+      }
+    else
+      {
+	printf("ERROR - <%llu>: %s -- ERROR\n", outcount, outbuf);
+	printf("Error at position %llu\n", (bytes + abs(error)));
+	offset = (-1 * error);
+	
+	printf("Union Size: %d\n", sizeof(union magnet_ext_data));
+	hexprint((void *)magnet_data, MAGNET_DATA_SIZE, 
+		 offset - sizeof(struct magnet_data), offset-1, 0);
+	printf("\n");
+	hexprint((void *)magnet_data, MAGNET_DATA_SIZE, 
+		 offset, offset+sizeof(struct magnet_data)-1,error);
+	printf("\n");
+	hexprint((void *)magnet_data, MAGNET_DATA_SIZE, 
+		 offset + sizeof(struct magnet_data),
+		 offset + 2*sizeof(struct magnet_data)-1, 0);
+	printf("\n");
+	return -4;
+      }
+  }
+  
+  free(magnet_data);
+  fclose(infile);
+  return 0;
+} /* main() */
diff -PBbruw linux/net/magnet/magnet-read.c magnet/net/magnet/magnet-read.c
--- linux/net/magnet/magnet-read.c	Wed Dec 31 17:00:00 1969
+++ magnet/net/magnet/magnet-read.c	Thu Apr 12 14:54:44 2001
@@ -0,0 +1,223 @@
+/*
+  MAGNeT - Monitor for Application-Generated Network Traffic
+         - User-mode monitor information reader
+	 - Written Nov 2000, Jeff Hay, jrhay@lanl.gov
+*/
+
+/* This is an application, distributed with the kernel source.  Therefore, its
+   likely to be built with the default kernel Makefiles, which define the 
+   __KERNEL__ flag.  Undo this nonsense for this program... */
+#ifdef __KERNEL__
+#undef __KERNEL__
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <linux/magnet.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <signal.h>
+
+/* Global (ie, syrnconization, etc) variables */
+char *fname;
+int fileout;
+int magnet, sleepwatch;
+unsigned int written;
+struct magnet_data *kernel_data;
+struct magnet_data *save_data;
+struct stat outstat;
+
+struct sigaction act, oact_term, oact_int;
+
+/* Code to handle TERM signal correctly */
+
+
+/* Main program code */
+
+/* Computes a default time to sleep (in ms) between reading instrumentation
+   data from the kernel, along with high- and low-water marks (used for dynamic
+   adjustment of sleep time, if requested) */
+unsigned int get_sleeptime(unsigned int *high_water,
+			   unsigned int *low_water) 
+{
+	unsigned int num_events, packet_size, net_speed, pkts_second;
+	unsigned int data_rate, drain_rate, sleep_time;
+	
+	
+	/* Initial Sleep time calculation */
+	num_events = ((int)(MAGNET_DATA_SIZE)) / sizeof(struct magnet_data);
+	packet_size = 1;  /* Assume worst case => 1 byte packets */
+	net_speed = 1000;
+	pkts_second = (net_speed * 10000000) / (packet_size * 8);
+	data_rate = (pkts_second / 8);  /* 4 events per network packet */
+	drain_rate = data_rate / num_events;
+
+	printf("   Kernel Buffer: %d events\n", num_events);
+	printf("Max network rate: %d events/second.\n", data_rate);
+	printf("Kernel buffer will be drained %d times per second\n", 
+	       drain_rate);
+	sleep_time = 1000000 / drain_rate;
+	printf("\n");
+	
+	if ((high_water != NULL) && (low_water != NULL)) {
+		/* high and low water marks */
+		*low_water = num_events / 4;
+		*high_water = 3 * *low_water;
+		printf("High-water mark: %d events\n", *high_water);
+		printf("Low-Water mark: %d events\n", *low_water);
+	}
+	
+	return sleep_time;
+} /* get_sleeptime() */
+
+void read_kernel_data(unsigned int maxwrite) {
+	unsigned int num_packets, sleep_time, high_water, low_water;
+	struct magnet_data *out_data;
+	void *current;
+	int count, sleepcount;
+	struct timeval timeout;
+	int readcount = 0;
+	
+	printf("Memory area successfully mapped\n");
+	sleep_time = get_sleeptime(&high_water, &low_water);
+	printf("Recording started; Reading maximum of %d bytes\n", maxwrite);
+  
+	num_packets = ((int)(MAGNET_DATA_SIZE)) / sizeof(struct magnet_data);
+	
+	count = 0;
+	current = kernel_data;
+	written = 0;
+	out_data = save_data;
+	while ((maxwrite <= 0) || (written < maxwrite)) {
+		timeout.tv_sec = 0;
+		timeout.tv_usec = sleep_time;
+		select(0, NULL, NULL, NULL, &timeout);
+	  
+		sleepcount = 0;
+
+		while (((struct magnet_data *)current)->timestamp != 0) {
+		        memcpy(out_data++, current, 
+			       sizeof(struct magnet_data));
+			written += sizeof(struct magnet_data);
+
+			readcount = 0;
+			((struct magnet_data *)current)->timestamp = 0;
+			current += sizeof(struct magnet_data);
+			if (++count >= num_packets) {
+				current = kernel_data;
+				count = 0;
+			}
+			sleepcount++;
+		}
+	  
+		if ((sleepwatch) && (sleepcount > 0)) {
+			if (sleepcount >= high_water)
+				sleep_time /= 2;
+			else if (sleepcount <= low_water)
+				sleep_time *= 2;
+		}
+  }
+
+  return;
+} /* read_kernel_data() */
+
+void terminate(int signal)
+{
+  printf("Closing shared memory\n");
+
+  munmap(kernel_data, MAGNET_DATA_SIZE);
+  close(magnet);  
+
+  printf("syncing mmap file\n");
+  msync(save_data, written, MS_SYNC);
+  munmap(save_data, outstat.st_size);
+  munlock(save_data, outstat.st_size);
+  close(fileout);
+
+  printf("Saved %u bytes of instrumentation\n", written);  
+
+  if (written < outstat.st_size)
+    truncate(fname, written);
+
+  if (sigaction(SIGTERM, &oact_term, NULL) < 0)
+    fprintf(stderr, "error: Failed to restore SIGTERM signal handler\n");
+  if (sigaction(SIGINT, &oact_int, NULL) < 0)
+    fprintf(stderr, "error: Failed to restore SIGINT signal handler\n");
+
+  return;
+}
+
+int main(int argc, char *argv[]) {
+
+  printf("%s: Monitor for Application Generated Network Traffic\n\n", argv[0]);
+
+  if (argc < 3) {
+    fprintf(stderr, " syntax: %s <magnet file> <output file> [-d]\n\n", 
+	    argv[0]);
+    fprintf(stderr, " \"-d\" = Dynamic Sleep Time Adjustment enabled\n");
+    return -1;
+  }
+
+  sleepwatch = 0;
+  if ((argc > 3) && (!strcmp(argv[3], "-d"))) {
+    sleepwatch = 1;
+  }
+
+  fname = argv[2];
+  if ((fileout = open(argv[2], O_RDWR|O_NDELAY)) <= 0) {
+	  fprintf(stderr, "%s: Can not open output file \"%s\"\n", 
+		  argv[0], argv[2]);
+	  fprintf(stderr, "%s: Is the file created?  If not, try mkmagnet\n",
+		  argv[0]);
+	  return -2;
+  }
+  if (fstat(fileout, &outstat) != 0) {
+	  fprintf(stderr, "%s: Can not stat output file \"%s\"\n", 
+		  argv[0], argv[2]);
+	  return -2;
+  }
+  if (outstat.st_size <= 0) {
+	  fprintf(stderr, "%s: Output file must be non-zero length\n", 
+		  argv[0]);
+	  return -3;
+  }
+
+  if ((magnet = open(argv[1], O_RDONLY)) == -1) {
+    fprintf(stderr, "%s: \"%s\": ", argv[0], argv[1]);
+    perror("Invalid MAGNeT device");
+    return -1;
+  }
+  printf("\tRecording %d bytes of data\n", (int)outstat.st_size);
+
+  /* Set up SIGTERM handler */
+  act.sa_handler = &terminate;
+  sigemptyset(&act.sa_mask);
+  act.sa_flags = 0;
+  if (sigaction(SIGTERM, &act, &oact_term) < 0)
+    fprintf(stderr, "%s: Failed to install SIGTERM signal handler\n", argv[0]);
+  if (sigaction(SIGINT, &act, &oact_int) < 0)
+    fprintf(stderr, "%s: Failed to install SIGINT signal handler\n", argv[0]);
+
+  /* Map the shared memory region into our own space */
+  if ((int)(kernel_data = (struct magnet_data *)
+       mmap(NULL,MAGNET_DATA_SIZE,PROT_READ,MAP_PRIVATE,magnet,0)) == -1) {
+	  perror("Can not map kernel instrumentation data");
+	  return -1;
+  }
+
+  if ((int)(save_data = (struct magnet_data *)
+       mmap(NULL,outstat.st_size,PROT_WRITE,MAP_SHARED,fileout,0)) == -1) { 
+	  perror("Can not mmap output file");
+	  return -1;
+  }
+  mlock(save_data, outstat.st_size);
+
+  read_kernel_data(outstat.st_size);
+
+  terminate(SIGTERM);
+  exit(0);
+} /* main() */
diff -PBbruw linux/net/magnet/magnet.c magnet/net/magnet/magnet.c
--- linux/net/magnet/magnet.c	Wed Dec 31 17:00:00 1969
+++ magnet/net/magnet/magnet.c	Tue Apr 10 10:14:10 2001
@@ -0,0 +1,259 @@
+/*
+ * MAGNET	 Monitor for Application Generated Network Traffic
+ *
+ * Version:	@(#)magnet.c	1.0.0	2001/03/06
+ *
+ * Author:	Jeff Hay, <jrhay@lanl.gov>
+ *
+ * Fixes:
+ *
+ *		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.
+ */
+
+#include <linux/config.h>
+
+#include <linux/kernel.h>
+#include <linux/stddef.h>
+#include <linux/mm.h>
+
+#include <asm/page.h>
+#include <net/sock.h>
+
+#include <linux/mm.h>
+#include <linux/pagemap.h>
+#include <linux/fs.h>
+#include <asm/io.h>
+#include <linux/miscdevice.h>
+#include <linux/wrapper.h>
+
+#include <linux/magnet.h>
+
+#include <linux/smp_lock.h>
+
+/*
+  mmap() structures to facilitate user/kernel shared memory
+*/
+
+static struct file_operations magnet_fops = {
+  mmap:    magnet_mmap,
+  open:    magnet_open,
+  release: magnet_close
+};
+
+// This corresponds with a /dev/magnet device with 
+// major number 10, minor MISC_DYNAMIC_MINOR (normally 63)
+static struct miscdevice magnet_device = {
+  minor:  MISC_DYNAMIC_MINOR,
+  name:   "magnet",
+  fops:   &magnet_fops
+};
+
+/* For reporting system info; this is i386-specific */
+extern unsigned long cpu_khz;
+
+/*
+  Globbal Magnet Variables 
+*/
+
+/* Global socket instrumentation variables */
+char *magnet_data;              /* kernel-space magnet buffer */
+char *magnet_data_offs;         /* where kernelspace is in buffer */
+unsigned int magnet_lost_pkts;  /* Info overwritten before user-level read */
+
+/* 
+   Routines to access magnet data
+*/
+extern int magnet_procread(char *buf, char **extbuf, off_t offset, int len) 
+{
+	len = 0;
+        len = sprintf(buf+len, "MAGNeT: Monitor for Application Generated Network Traffic\n");
+	len += sprintf(buf+len, "Research tool created by Los Alamos National Laboratory's RADIANT Team\n");
+	len += sprintf(buf+len, "(http://www.lanl.gov/radiant)\n\n");
+	len += sprintf(buf+len, "      MAGNeT Device Name: /dev/%s\n", magnet_device.name);
+	len += sprintf(buf+len, "    MAGNeT Device Number: 10, %d\n", magnet_device.minor);
+	len += sprintf(buf+len, "  Kernel Memory Reserved: %ld Kb (%ld pages)\n", 
+		       (MAGNET_DATA_SIZE / 1024), (MAGNET_DATA_SIZE / PAGE_SIZE));
+	len += sprintf(buf+len, "        Data packet size: %d bytes\n",sizeof(struct magnet_data));
+	len += sprintf(buf+len, "Extended Instrumentation: ");
+#ifdef CONFIG_MAGNET_EXTENDED
+	len += sprintf(buf+len, "on\n");
+#else
+	len += sprintf(buf+len, "off\n");
+#endif
+	len += sprintf(buf+len, "   Instrument All Events: ");
+#ifdef CONFIG_MAGNET_SOCK_ONLY
+	len += sprintf(buf+len, "off\n");
+#else
+	len += sprintf(buf+len, "on\n");
+#endif
+	len += sprintf(buf+len, "\n");
+        return len;
+} 
+
+__inline__ void magnet_add(struct sock *sk,
+			     unsigned int magnet_event,
+			     unsigned int magnet_size,
+			     union magnet_ext_data data)
+{
+	unsigned int datasize = sizeof(struct magnet_data);
+	struct magnet_data *sicurrent;
+	unsigned long long currenttime;
+
+	currenttime = get_cycles();
+
+	if ((magnet_data == NULL) || (magnet_size < 1))
+		return;
+
+#ifdef CONFIG_MAGNET_SOCK_ONLY
+	if ((magnet_event & MAGNET_SOCK) == 0) /*mask out all non-sock calls*/
+		return;
+#endif
+	sicurrent = (struct magnet_data *)magnet_data_offs;
+	if (sicurrent->timestamp == 0) {
+		if (magnet_lost_pkts > 0) {
+			sicurrent->sockid = NULL;
+			sicurrent->event  = MAGNET_LOST;
+			sicurrent->size   = magnet_lost_pkts+1;
+			magnet_lost_pkts      = 0;
+		} else {
+			sicurrent->sockid = sk;
+			sicurrent->event  = magnet_event;
+			sicurrent->size   = magnet_size;
+#ifdef CONFIG_MAGNET_EXTENDED
+			sicurrent->data   = data;
+#endif
+		}
+		/* Write timestamp last as a signal to user-space program */
+		sicurrent->timestamp = currenttime;
+
+	       magnet_data_offs += datasize;
+	       if (magnet_data_offs >= 
+		   (magnet_data + MAGNET_DATA_SIZE - datasize - 1)) {
+		       magnet_data_offs = magnet_data;
+	       }
+	} else {
+		magnet_lost_pkts++;
+	}
+	
+	return;
+}
+
+
+/* Initialize socket instrumentation interface */
+int magnet_setup()
+{
+	struct page *page;
+	int error;
+
+	/* Initialize kernel-space pointer into buffer */
+	magnet_data_offs = magnet_data;
+
+	/* Create /proc/net/magnet file for reporting misc. status */
+	proc_net_create("magnet", S_IFREG | S_IRUGO, magnet_procread);
+
+	/* Pin down our buffer's pages, so it can't be swapped out */
+	for (page = virt_to_page(magnet_data);
+	     page < virt_to_page(magnet_data + MAGNET_DATA_SIZE);
+	     page++)
+		mem_map_reserve(page);
+
+	/* Register as a misc char device for doing mmap's */	
+	error = misc_register(&magnet_device);
+
+	return error;
+}
+
+/* Called at boot-time when socket code is being initialized */
+void magnet_init()
+{
+	printk(KERN_INFO "NET4: MAGNeT: Socket Instrumentation Interface for NET4.0\n");
+	if ((magnet_data = (char *)__get_free_pages(
+		GFP_ATOMIC, get_order(MAGNET_DATA_SIZE))) == NULL)
+		printk(KERN_ERR "NET4: MAGNeT: No memory for instrumentation buffer\n");
+	else
+		magnet_setup();
+	return;
+}
+
+/* Teardown socket instrumentation interface 
+   (this is never called in the current implementation.  Code listed here
+    to make converting this to a module "easy"....)
+*/
+void magnet_destroy()
+{
+	struct page *page;
+
+	/* disable mmap()ing of buffer space */
+	misc_deregister(&magnet_device);
+
+	/* un-pin buffer space */
+	for (page = virt_to_page(magnet_data);
+	     page < virt_to_page(magnet_data + MAGNET_DATA_SIZE);
+	     page++)
+		mem_map_unreserve(page);
+
+	/* remove /proc information hook */
+	proc_net_remove("magnet");
+	return;
+}
+
+/*
+  mmap() shared-memory routines 
+*/
+
+int magnet_open(struct inode *inode, struct file *file)
+{
+	/* Do nothing; this is just a dummy procedure to make the
+	   VFS happy... */
+//	printk(KERN_INFO "magnet: opening mmap file\n");   
+	return 0;
+}
+
+int magnet_close(struct inode *inode, struct file *file)
+{
+	/* Do nothing; this is just a dummy procedure to make the
+	   VFS happy... */
+//	printk(KERN_INFO "magnet: closing mmap file\n");
+	return 0;
+}
+
+int magnet_mmap(struct file *file, struct vm_area_struct *vma)
+{
+	/* Set up the shared memory to user-level process */
+	unsigned long size = (unsigned long)(vma->vm_end - vma->vm_start);
+	
+	/* First, make sure we're within bounds */
+	if (size > MAGNET_DATA_SIZE)
+		return -EINVAL;
+
+	lock_kernel();
+	/* Step through our buffer a page at a time, and remap each page
+	   into the user-mode address space */
+	if (remap_page_range(vma->vm_start, 
+			     virt_to_phys(magnet_data),
+			     size, PAGE_SHARED)) {
+		printk(KERN_ERR "MAGNeT: remapping failed\n");
+		return -EAGAIN;
+	}
+
+        /* Don't swap this VMA out! */
+	vma->vm_flags |= VM_SHM | VM_LOCKED | VM_IO;
+
+	/* Clear the memory so user doesn't read old information */
+	memset(magnet_data, 0, size);
+	magnet_data_offs = magnet_data;
+	magnet_lost_pkts = 0;
+
+	unlock_kernel();
+
+	/* Add a system information field to the beginning of the dump */
+	magnet_add((void *)(MAGNET_VERSION), MAGNET_SYSINFO, 
+		   (unsigned int)(cpu_khz), MAGNET_NO_DATA);
+
+
+	/* Success! */
+	return 0;
+}
diff -PBbruw linux/net/magnet/magnet.copy magnet/net/magnet/magnet.copy
--- linux/net/magnet/magnet.copy	Wed Dec 31 17:00:00 1969
+++ magnet/net/magnet/magnet.copy	Tue Apr 10 10:03:53 2001
@@ -0,0 +1,39 @@
+#!/bin/sh
+#
+# magnet.copy
+#   Sample MAGNeT archiving script.  Copies any gzipped files in the
+#   directory given as the first parameter to a directory on a remote
+#   machine, using scp (or any other rcp-like command).
+###
+# Configurable parameters:
+
+# Host to archive to
+ARCH_HOST=radiant-server
+
+# Directory to archive to
+ARCH_DIR=/array0/data/magnet/wishsong
+
+# RCP-like program
+RCP=/usr/local/bin/scp
+RCP_OPTS="-qp"
+
+# Archive log file
+ARCH_FILE=/var/log/magnet
+
+####################################################################
+
+if [ "$1" = "" -o ! -d "$1" ]; then
+  echo "$0: Invalid directory to archive: syntax \"$0 <arch_dir>\""
+  exit 1
+fi
+
+for FILE in `ls $1/*.gz`
+do
+  echo -n `date`": " >> $ARCH_FILE
+  echo "Archiving $FILE to $ARCH_HOST" >> $ARCH_FILE
+  $RCP $RCP_OPTS $FILE $ARCH_HOST:$ARCH_DIR/ >> $ARCH_FILE 2>&1
+  if [ $? -eq 0 ]; then
+    rm -f $FILE
+  fi
+done
+
diff -PBbruw linux/net/magnet/magnet.cron magnet/net/magnet/magnet.cron
--- linux/net/magnet/magnet.cron	Wed Dec 31 17:00:00 1969
+++ magnet/net/magnet/magnet.cron	Tue Apr 10 10:03:53 2001
@@ -0,0 +1,123 @@
+#!/bin/sh
+#
+# magnet.cron
+#    This is a wrapper script for the MAGNeT tools.  It is
+# primairly intended to be run from cron, or upon bootup.  The
+# script:
+#       o Ensures that the kernel is running MAGNeT code
+#         + Aborts gracefully if non-MAGNeTized
+#       o Ensures that the proper MAGNeT device file exists
+#         + Creates the file if it does not exist
+#         + Modifies device numbers if necessary
+#       o Compresses any un-compressed MAGNeT data
+#       o Calls the Archive script to archive the data
+#       o Generates a new MAGNeT data storage file
+#       o Runs magnet-read with proper parameters 
+#         (as a background process)
+#
+# Configurable parameters for the script follow.  Script must
+# be run suid root. The following programs must be in the 
+# current path when the script is run:
+#
+# ls echo date dc cut rm mknod kill awk ps hostname gzip
+#
+# If the first parameter to this script is "-n", the script will
+# echo the commands it would normally execute to stdout, and will
+# NOT execute them.
+#################################################################
+# Set up the following constants to conform to your system
+#   - Path names should NOT end with a "/"
+
+# Complete path to magnet binary files
+MAGNET_BIN="/opt/home/jrhay/src/sockinst"
+
+# Complete path to magnet data storage area
+MAGNET_DATA="/opt/magnet"
+
+# Size of MAGNeT data storage files, in Megabytes
+MAGNET_SAVESIZE=100
+
+# Parameters to pass to "magnet-read"
+MAGNET_OPTS=""
+
+# MAGNeT archiving script name
+# This script is called to move all gzipped files in $MAGNET_DATA
+# to an archival location.  $MAGNET_DATA is passed as first param.
+# The script is guarented to be called when MAGNeT is NOT running.
+# This var may be set to empty
+MAGNET_ARCHIVE="$MAGNET_BIN/magnet.copy"
+
+# End of configurable options
+##################################################################
+
+##################################################################
+# Set up some constants for this incarnation of MAGNeT
+
+# Name of MAGNeT /proc file (shouldn't ever change)
+MAGNAME="/proc/net/magnet"
+
+# Pattern to match in /proc file for MAGNeT Device Name
+MAGDEVNAME="Device Name"
+
+# Pattern to match in /proc file for MAGNeT Device Numbers
+MAGDEVNUM="Device Number"
+
+# Names of MAGNeT executable files
+MKMAGNET="mkmagnet"
+MAGNETREAD="magnet-read"
+
+# End of constant setup
+##################################################################
+
+# Set up "-n" functionality
+if [ "$1" == "-n" ]; then
+  CMD="echo"
+fi
+
+# First, determine if we are running a MAGNeTized kernel
+ls $MAGNAME > /dev/null 2>&1
+if [ $? -ne 0 ]; then
+  echo "$0: Not running MAGNeTized kernel; aborting."
+  exit 1
+fi
+
+# Make sure we have proper MAGNeT device file (device name/number match)
+#
+DEVICE=`grep "$MAGDEVNAME" $MAGNAME | cut -f2 -d:`
+DNUM=`grep "$MAGDEVNUM" $MAGNAME | cut -f2 -d:`
+EXIST=`ls -l $DEVICE` > /dev/null 2>&1
+NEWDEV=$?
+DEVNUM=`echo $EXIST | cut -f5-6 -d" "`
+if [ $NEWDEV -ne 0 -o " $DEVNUM" != "$DNUM" ]; then
+  $CMD rm -f $DEVICE
+  $CMD mknod $DEVICE c $DMAJOR `echo $DNUM | awk 'BEGIN {FS=","}{print $1 $2}'`
+fi
+
+# Generate a unique file name for the storage file
+HOST=`hostname`
+UNIQUE=`date +"%d%b%Y-%H%M%S"`
+FNAME="$MAGNET_DATA/$HOST.$UNIQUE"
+
+# Make the new storage file
+$CMD $MAGNET_BIN/$MKMAGNET $FNAME `echo "1024 1024 $MAGNET_SAVESIZE * * p" | dc`
+
+# There's a chance (ie, we're running from cron) that magnet-read is
+# currently running.  If so, send the TERM signal to it (this
+# works for multiple running instances)
+MPID=`ps -e | awk '{ if ($4 == "'$MAGNETREAD'") {print $1} }'`
+if [ "$MPID" != "" ]; then
+  $CMD kill $MPID
+fi
+
+# Compress and Archive latest MAGNeT storage file(s)
+for STORE in `ls $MAGNET_DATA | grep -v ".gz" | grep -v $HOST.$UNIQUE`
+do
+  $CMD gzip $MAGNET_DATA/$STORE
+done
+# Call Archive script to off-load the old storage files
+if [ "$MAGNET_ARCHIVE" != "" ]; then
+  $CMD $MAGNET_ARCHIVE $MAGNET_DATA
+fi
+
+# All's ready; re-run MAGNeT
+$CMD $MAGNET_BIN/$MAGNETREAD $MAGNET_OPTS $DEVICE $FNAME &
\ No newline at end of file
diff -PBbruw linux/net/magnet/mkmagnet.c magnet/net/magnet/mkmagnet.c
--- linux/net/magnet/mkmagnet.c	Wed Dec 31 17:00:00 1969
+++ magnet/net/magnet/mkmagnet.c	Tue Apr 10 10:03:53 2001
@@ -0,0 +1,68 @@
+/*
+  MAGNeT - Monitor for Application-Generated Network Traffic
+         - MAGNeT storage file creator
+	 - Written by Jeff Hay, jrhay@lanl.gov
+*/
+
+/* This is an application, distributed with the kernel source.  Therefore, its
+   likely to be built with the default kernel Makefiles, which define the 
+   __KERNEL__ flag.  Undo this nonsense for this program... */
+#ifdef __KERNEL__
+#undef __KERNEL__
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#define BufferSize 1024*1024
+
+int main(int argc, char *argv[])
+{
+  FILE *OutFile;
+  int FinalSize = 0, Steps = 0;
+  void *DataSpace;
+
+  printf("%s: MAGNeT Data Storage File Maker\n\n", argv[0]);
+
+  if (argc < 3) {
+    fprintf(stderr," syntax: %s <new data file name>  <file bytes>\n", 
+	    argv[0]);
+    return -1;
+  }
+
+  if ((FinalSize = atoi(argv[2])) <= 0) {
+    fprintf(stderr, "%s: \"%s\" is not a valid file byte count; aborting.\n", 
+	    argv[0], argv[1]);
+    return -2;
+  }
+
+  if (!(OutFile = fopen(argv[1], "wb"))) {
+    fprintf(stderr, "%s: Can not open \"%s\" for writing/creating\n", 
+	    argv[0], argv[1]);
+    return -1;
+  }
+
+  if ((DataSpace = malloc(BufferSize)) == NULL) {
+    fprintf(stderr, "%s: Out of Memory; Can not create data store!\n", 
+	    argv[0]);
+    return -3;
+  }
+  printf("\tGenerating space for %d bytes of data\n", FinalSize);
+ 
+  memset(DataSpace, 0x0FE, BufferSize);
+  Steps = 0;
+  while (FinalSize > (BufferSize)) {
+    Steps++;
+    FinalSize -= BufferSize;
+  }
+
+  while (Steps-- > 0) {
+    fwrite(DataSpace, BufferSize, 1, OutFile);
+  }
+  fwrite(DataSpace, FinalSize, 1, OutFile);
+
+  fclose(OutFile);  
+  free(DataSpace);
+  return 0;
+} /* main() */
diff -PBbruw linux/net/socket.c magnet/net/socket.c
--- linux/net/socket.c	Fri Nov 17 12:36:27 2000
+++ magnet/net/socket.c	Tue May  1 15:28:53 2001
@@ -86,6 +86,10 @@
 #include <net/scm.h>
 #include <linux/netfilter.h>
 
+#ifdef CONFIG_MAGNET
+#include <linux/magnet.h>
+#endif
+
 static int sock_no_open(struct inode *irrelevant, struct file *dontcare);
 static loff_t sock_lseek(struct file *file, loff_t offset, int whence);
 static ssize_t sock_read(struct file *file, char *buf,
@@ -505,7 +509,15 @@
 
 	err = scm_send(sock, msg, &scm);
 	if (err >= 0) {
+#ifdef CONFIG_MAGNET
+		magnet_add(sock->sk, MAGNET_SOCK_SENDCALL, size, 
+			     MAGNET_NO_DATA);
+#endif
 		err = sock->ops->sendmsg(sock, msg, size, &scm);
+#ifdef CONFIG_MAGNET
+		magnet_add(sock->sk, MAGNET_SOCK_SEND, size, 
+			     MAGNET_NO_DATA);
+#endif
 		scm_destroy(&scm);
 	}
 	return err;
@@ -514,10 +526,15 @@
 int sock_recvmsg(struct socket *sock, struct msghdr *msg, int size, int flags)
 {
 	struct scm_cookie scm;
-
 	memset(&scm, 0, sizeof(scm));
 
+#ifdef CONFIG_MAGNET
+	magnet_add(sock->sk, MAGNET_SOCK_RECVCALL, size, MAGNET_NO_DATA);
+#endif
 	size = sock->ops->recvmsg(sock, msg, size, flags, &scm);
+#ifdef CONFIG_MAGNET
+	magnet_add(sock->sk, MAGNET_SOCK_RECV, size, MAGNET_NO_DATA);
+#endif
 	if (size >= 0)
 		scm_recv(sock, msg, &scm, flags);
 
@@ -1676,6 +1693,14 @@
 
 #ifdef CONFIG_WAN_ROUTER	 
 	wanrouter_init();
+#endif
+
+	/*
+	 *     Socket Instrumentation Interface.
+	 */
+
+#ifdef CONFIG_MAGNET
+	magnet_init();
 #endif
 
 	/*