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, + * + * 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 + +#ifdef __KERNEL__ +/* for macrology */ +#include +#include +#include +#endif + +#include /* 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 + +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 #include +#ifdef CONFIG_MAGNET +#include +#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 #include +#ifdef CONFIG_MAGNET +#include +#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 #include +#if defined (CONFIG_MAGNET) +#include +#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 #include +#if defined (CONFIG_MAGNET) +#include +#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 +#ifdef CONFIG_MAGNET +#include +#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 +#include +#include + + +/* 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 \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 +#include +#include + +/* 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 \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 +#include + +#include +#include +#include +#include +#include +#include +#include + +/* 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 [-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, + * + * 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 + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include + +/* + 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 \"" + 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 +#include +#include + +#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 \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 #include +#ifdef CONFIG_MAGNET +#include +#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 /*