Commit 06b230d6 authored by Mac Newbold's avatar Mac Newbold

No longer needed. Moved to attic.

parent 510304a9
OBJS=divert.o divert_hash.o
POBJS=divert.po divert_hash.po
CFLAGS += -Wall -O2 # -DDEBUG=1
CC=gcc
# XXX - if we autoconf-ify this stuff, then fix this next line.
RANLIB=ranlib
all: libdivert.a divertest
divert.po: divert.c
${CC} -c -pg divert.c -o $@
divert_hash.po: divert_hash.c
${CC} -c -pg divert_hash.c -o $@
divertest: libdivert.a divertest.o
$(CC) $@.o -L. -ldivert -o $@
libdivert.a: ${OBJS}
${AR} cr $@ ${OBJS}
${RANLIB} $@
libdivert_p.a: ${POBJS}
${AR} cr $@ ${POBJS}
${RANLIB} $@
install: all
@echo "The install target is not yet functional."
@echo "Where should we stick these things?"
clean:
/bin/rm -rf $(OBJS) ${POBJS} divertest.o divertest libdivert.a libdivert_p.a
This diff is collapsed.
#ifndef _JANOS_DIVERT_H
#define _JANOS_DIVERT_H
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in_systm.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/udp.h>
#include <arpa/inet.h>
#include <netinet/ip_var.h>
#define MAXPACKET 2048
struct portmask {
int proto; /* currently IPPROTO_ICMP or IPPROTO_UDP */
union {
int port;
int icmptype;
} proto_data;
int ipfw_rule;
struct portmask *next;
};
struct msockinfo {
int sock;
int divert_port;
struct portmask *ports;
};
/*
* Returns the length of snooped packet or -1 if failure.
* Failure info is in errno. Fills in srcAddr, srcPort,
* destAddr, and destPort with header info from snooped packet.
*/
int receive_snoop(struct msockinfo *msock,
char *packetdata, int dataSize,
struct in_addr *srcAddr,
short *srcPort,
struct in_addr *destAddr,
short *destPort);
/* Ditto */
int send_snoop(struct msockinfo *msock,
char *packetdata,
int datalen,
struct in_addr srcAddr,
short srcPort,
struct in_addr destAddr,
short destPort);
/*
* Get a new divert socket object.
* Returns NULL if there was a problem.
*/
struct msockinfo *get_socket();
/*
* Free a divert socket object created by get_socket()
*/
void free_socket(struct msockinfo *s);
int add_mask_port(struct msockinfo *s, int port);
int rem_mask_port(struct msockinfo *s, int port);
/* We should clean up the interface to merge these..
* and add a rem_mask_icmp, or equivalent. */
int add_mask_icmp(struct msockinfo *s, int icmptype);
#endif /* _JANOS_DIVERT_H */
#include <stdlib.h>
#include "divert_hash.h"
#include <assert.h>
#include <errno.h>
static int addrtable_initted = 0;
static struct addrtable_entry *addrtable[ADDRTABLE_NUM_BUCKETS];
int hashaddr(unsigned long addr)
{
return addr % ADDRTABLE_NUM_BUCKETS; /* Lame */
}
void addrtable_init()
{
int i;
if (addrtable_initted) return;
addrtable_initted = 1;
for (i = 0; i < ADDRTABLE_NUM_BUCKETS; i++)
addrtable[i] = NULL;
}
/*
* -1 --> no entry
* 0 --> Not local
* 1 --> Local
*/
int bucket_contains(int bucket, unsigned long addr)
{
struct addrtable_entry *pte;
if (addrtable[bucket] == NULL)
return -1;
/* else walk the list in the bucket */
pte = addrtable[bucket];
while (pte) {
if (pte->addr == addr) return pte->islocal;
pte = pte->next;
}
return -1;
}
int addrtable_find(unsigned long addr)
{
int bucket;
int rc;
bucket = hashaddr(addr);
rc = bucket_contains(bucket, addr);
return rc;
}
int addrtable_insert(unsigned long addr, int islocal)
{
int bucket;
struct addrtable_entry *newent;
bucket = hashaddr(addr);
if (bucket_contains(bucket, addr) != -1) {
return EEXIST;
}
newent = malloc(sizeof(*newent));
if (newent == NULL) {
return ENOMEM;
}
newent->addr = addr;
newent->islocal = islocal;
newent->next = addrtable[bucket];
addrtable[bucket] = newent;
return 0;
}
int addrtable_remove(unsigned long addr)
{
int bucket;
struct addrtable_entry *pte;
struct addrtable_entry *prev;
bucket = hashaddr(addr);
if (addrtable[bucket] == NULL) {
return -1;
}
if (addrtable[bucket]->addr == addr) {
pte = addrtable[bucket];
addrtable[bucket] = addrtable[bucket]->next;
} else {
/* else walk the list in the bucket */
prev = addrtable[bucket];
pte = prev->next;
while (pte) {
if (pte->addr == addr)
break;
prev = pte;
pte = pte->next;
}
/* At this point, we have it, or it's null */
if (pte == NULL) {
return -1;
}
prev->next = pte->next;
}
free(pte);
return 0;
}
/*
* Manage the pid / process hash table map.
*/
#ifndef DIVERT_HASH_H
#define DIVERT_HASH_H
#define ADDRTABLE_NUM_BUCKETS 263
void addrtable_init();
int addrtable_insert(unsigned long addr, int islocal);
int addrtable_remove(unsigned long addr);
int addrtable_find(unsigned long addr);
struct addrtable_entry {
unsigned long addr;
int islocal;
struct addrtable_entry *next;
};
#endif /* DIVERT_HASH_H */
#include <stdio.h>
#include <stdlib.h>
#include <sys/signal.h>
#include "divert.h"
struct msockinfo *msock, *outsock;
#define DPRINTF(fmt, args...) /* Shut up */
void cleanup(int sig) {
DPRINTF("Sig %d caught\n", sig);
free_socket(msock);
exit(0);
}
int main(int argc, char **argv) {
int port = 69;
if (argc > 1) {
port = atoi(argv[1]);
}
signal(SIGINT, cleanup);
msock = get_socket();
outsock = get_socket();
add_mask_port(msock, port);
while (1) {
struct in_addr srcAddr, destAddr;
short srcPort, destPort;
int length, wlen;
char packetbuf[MAXPACKET];
length = receive_snoop(msock,
packetbuf,
MAXPACKET,
&srcAddr, &srcPort,
&destAddr, &destPort);
if (length < 0) {
DPRINTF("Breaking\n");
break;
}
DPRINTF("Received packet, dst 0x%lx port %d\n",
ntohl(destAddr.s_addr),
ntohs(destPort));
DPRINTF(" src 0x%lx port %d\n",
ntohl(srcAddr.s_addr),
ntohs(srcPort));
DPRINTF("Packet contents: %s\n",
packetbuf);
#if 1
add_mask_port(outsock, ntohs(srcPort));
#endif
wlen = send_snoop(msock,
packetbuf,
length,
srcAddr, srcPort,
destAddr, destPort);
DPRINTF("Sent %d bytes\n", wlen);
}
free_socket(msock);
DPRINTF("Exiting\n");
exit(0);
}
netpull and tools
----------------------------------------------------------------------
netpull.tcl
This script uses trace route to analyze a network and produce
output on the topology and RTT mean and variance. As argument it
takes the name of a file containing a list of IP addresses. These are
the nodes it runs trace routes to to look at the network. Traceroutes
are run in parallel (default 4 at a time) and each address is traced
to multiple times (default 4).
Output is to standard out and contains two types of lines:
NODE <ip> <state>
Indicates a node exists at <ip> and what the state of the node
is. Either UNKNOWN, UP, or UP? . UP? indicates that although it is
probably UP there were some problems in the trace.
LINK <src> <dst> <state> <rtt mean> <rtt variance> <rtt n> <finals>
Indicates a link from <src> to <dst>. <state> is OK?, DOWN,
BAD, DENIED, ERROR-#, or UP. OK? indicates that although everything
worked traceroute reported !'s in it's output. On
host/network/protocol errors the state is DOWN. Routing errors result
in a state of BAD and a DENIED indicates a administrative prohibition.
Finally, UNKNOWN results with impolite hosts (see below). ERROR-# is
ICMP unreachable codes. <rtt mean> and <rtt variance> are the mean
and variance of the RTT, measured over <rtt n> samples. <finals> is
the list of traceroutes (as destination IP addresses) that the link
showed up in.
In the case of a node that does not reply to expired packets
(impolite) (* * * in traceroute) netpull assigns a bogus ip address
of 0.0.0.#. Links to these nodes will have the state of UNKNOWN.
Options:
-n # - # is how many traceroutes to have running at once
-r # - This is how many times to trace to each IP
-v - If present progress information will be sent to stderr.
----------------------------------------------------------------------
npdiff.tcl
This is a script to compare two reports from npdiff. It takes
two files as arguments and produces the following output:
NodeAppear <ip> <ip> is in B but not A.
NodeVanish <ip> <ip> is in A but not B.
NodeChange <ip> <old> <new> <ip> changed from <old> to <new>
LinkAppear <src> <dst> In B but not A.
LinkVanish <src> <dst> In A but not B.
LinkChange <src> <dst> <old> <new>
Link changed state.
LinkRtt <src> <dst> <diff> RTT is <diff> off. This is only
displayed if the means are father apart then the variance times
some multiple (default 4, can be changed with '-v #'). I.e. if
diff > A.var * mult || diff > B.var * mult
----------------------------------------------------------------------
dnsconv.tcl
This is a quick script to change large numbers of hostnames to
IP addresses. Any hostname sent to stdin will result in the IP
address being sent to stdout.
Example:
tclsh ./dnsconv.tcl < test > test.ip
----------------------------------------------------------------------
test
A list of local machines for netpull demo purposes. Use
test.ip as the argument to netpull.
----------------------------------------------------------------------
test.ip
The 'test' file run through dnsconv.tcl.
######################################################################
# calfeldlib.tcl
#
# Provides some basic routines that show up all over the place.
#
# perror <msg> - Displays a message to stderr if errors are turned on.
# warn <msg> - Displays a message to stderr if warnings are turned on.
# debug <msg>
# verbose <msg> <type> - Displays a message to stdout if the verbose
# type is in the outputable types.
# setoutput <type> <state> - Sets the displaying of errors, warnings,
# and the verbose level.
#
# checkname <name> - Returns 1 if name ok, 0 otherwise
# listinsert <list> <index> <element> - Does a list insertion with replacement.
# delarray <arrayname> - Deletes the array named
# lremove <list> <element> - Removes an element from <list>
# lpop <list> - Pops from a list
# ldiff <a> <b> - returns <a not b> <a and b> <b not a>
######################################################################
namespace eval CalfeldLib {
# This is the date of last release (epoch+VERSION)
# 9/9/99
set VERSION 936900465
namespace export perror
namespace export warn
namespace export verbose
namespace export setoutput
namespace export checkname
namespace export debug
namespace export listinsert
namespace export delarray
namespace export lremove
namespace export lpop
namespace export ldiff
######################################################################
# Variables
######################################################################
##################################################
# Output
# Array indexed by error|warn|verbose that holds the levels of each.
##################################################
variable Output
set Output(error) 1
set Output(warn) 1
set Output(verbose) {ALL}
set Output(debug) {}
######################################################################
# Code
######################################################################
##################################################
# perror <msg>
# Displays <msg> to stderr if error level is > 0
##################################################
proc perror {msg} {
variable Output
if {$Output(error) > 0} {
puts stderr "ERROR: $msg"
}
}
##################################################
# warn <msg>
# Displays <msg> to stderr if warn level is > 0
##################################################
proc warn {msg} {
variable Output
if {$Output(warn) > 0} {
puts stderr "WARNING: $msg"
}
}
##################################################
# verbose <msg> <type>
# Displays <msg> to stdout if verbose level is in Output(verbose)
# XXX - use array to make this more efficient.
##################################################
proc verbose {msg type} {
variable Output
if {$Output(verbose) == "ALL" ||
[lsearch $Output(verbose) $type] != -1} {
puts "V: $msg"
}
}
##################################################
# debug <msg> <type>
# Displays <msg> to stdout if debug level is in Output(debug)
# XXX - use array to make this more efficient
##################################################
proc debug {msg type} {
variable Output
if {$Output(debug) == "ALL" ||
[lsearch $Output(debug) $type] != -1} {
puts "D: $msg"
}
}
##################################################
# setoutput <type> <value>
# Just a simple access routine to the Output varibale.
##################################################
proc setoutput {type value} {
variable Output
set Output($type) $value
}
##################################################
# checkname <name>
# Checks for a valid name, currently just avoids spaces.
##################################################
proc checkname {name} {
# XXX: add checking for [],{},",\t,\n, etc.
if {[regexp { } $name] == 1} {return 0} else {return 1}
}
##################################################
# listinsert <list> <index> <element>
# This inserts <element> into <list> at position <index>, filling
# with {}'s as necessary and returns the new list. Different from
# linsert in that it replaces elements rather than expanding the list.
##################################################
proc listinsert {list index element} {
set length1 [llength $list]
set length2 [expr $index + 1]
if {$length1 > $length2} {
set newlength $length1
} else {
set newlength $length2
}
set newlist {}
for {set i 0} {$i < $newlength} {incr i} {
if {$i == $index} {
lappend newlist $element
} else {
lappend newlist [lindex $list $i]
}
}
return $newlist
}
##################################################
# delarray <arrayname>
# Complete deletes the array named.
##################################################
proc delarray {arrayname} {
upvar $arrayname A
foreach ind [array names A] {
unset A($ind)
}
}
##################################################
# lremove <list> <element>
# Removes <element> from <list> (name of list)
##################################################
proc lremove {list element} {
upvar $list L
set i [lsearch $L $element]
if {$i == -1} {return}
set L [lreplace $L $i $i]
}
##################################################
# lpop <list>
##################################################
proc lpop {list} {
upvar $list L
set ret [lindex $L 0]
set L [lrange $L 1 end]
return $ret
}
##################################################
# ldiff <a> <b>
# Returns list of three lists: a-b, intersection, b-a
##################################################
proc ldiff {a b} {
set a [lsort $a]
set b [lsort $b]
set ab {}
set ba {}
set int {}
while {$a != {} && $b != {}} {
set ae [lindex $a 0]
set be [lindex $b 0]
if {$ae == $be} {
# in both lists
lappend int $ae
lpop a
lpop b
} else {
if {$ae < $be} {
# read from ae until >=
while {$a != {} && $ae < $be} {
lappend ab $ae
lpop a
set ae [lindex $a 0]
}
} else {
# read from be until >=
while {$b != {} && $be < $ae} {
lappend ba $be
lpop b
set be [lindex $b 0]
}
}
}
}
if {$a != {}} {
set ab [concat $ab $a]
} elseif {$b != {}} {
set ba [concat $ba $b]
}
return [list $ab $int $ba]
}
}
\ No newline at end of file
while {[gets stdin line] >= 0} {
if {$line == "" || [string index $line 0] == "#"} {continue}
set fp [open "|host $line" r]
set ip $line
while {[gets $fp hline] >= 0} {
if {[regexp {address ([0-9\.]+)} $hline match addr]} {
set ip $addr
}
}
puts $ip
close $fp
}
\ No newline at end of file
#!/usr/local/bin/tclsh
######################################################################
# netpull.tcl
#
# This program takes as an argument a file containing a list of IP
# addresses. It then uses traceroute to construct a picture of the
# network involving this IP address and output a machine parseable report
# on the state of the network including topology and mean and variance
# of RTT.
#
# OUTPUT:
# NODE <ip> <state>
# LINK <src> <dst> <state> <rtt mean> <rtt variance> <rtt n samples> <final destinations>
######################################################################
######################################################################
# Initialization
######################################################################
# load lpop
source calfeldlib.tcl
namespace import CalfeldLib::lpop
# Set some static settings
set traceroute /usr/sbin/traceroute
######################################################################
# Globals
######################################################################
# Bogus is a counter for assinging IP address to unknown hosts
variable Bogus 1
# The number of runs to make. Can be configured on command line.
variable NumRuns 4
# The number of trace routes to have running at once. Can be configured
# on command line.
variable NumSpawns 4
# The number of trace routes currently running
variable NumSpawned 0
# A flag that is waited on. Writing to this variable indicates that
# we are done.
variable Done 0
# This is an array of what links exist. It is used to gain a list
# of all links.
# LinksL
# This contains the last line processed
variable CurLine {}
# This indicates whether to display verbose output
variable Verbose 0
# This indicates whether to dump traceroute output
variable Dump 0
# A list of IP address to run on.
variable ToRun {}
# PREV is indexed by fp and is the previous node visited for a
# running traceroute on that run.
# State variables