## Software from the book "Inferno Programming with Limbo"# published by John Wiley & Sons, January 2003.## p. Stanley-Marbell <pip@gemusehaken.org>#implement Xsniff; include "sys.m";include "draw.m";include "arg.m";include "xsniff.m"; Xsniff : module{ DUMPBYTES : con 32; init : fn(nil : ref Draw->Context, args : list of string);}; sys : Sys;arg : Arg;verbose := 0;etherdump := 0;dumpbytes := DUMPBYTES; init(nil : ref Draw->Context, args : list of string){ n : int; buf := array [Sys->ATOMICIO] of byte; sys = load Sys Sys->PATH; arg = load Arg Arg->PATH; dev := "/net/ether0"; arg->init(args); while((c := arg->opt()) != 0) { case c { 'v' => verbose = 1; 'e' => etherdump = 1; 'b' => dumpbytes = int arg->arg(); 'd' => dev = arg->arg(); * => usage(); } } args = arg->argv(); tmpfd := sys->open(dev+"/clone", sys->OREAD); if ((n = sys->read(tmpfd, buf, len buf)) < 1) { fatal("Could not read "+dev+"/clone : "+ sys->sprint("[%r]")); } (nil, dirstr) := sys->tokenize(string buf[:n], " \t"); channel := int (hd dirstr); infd := sys->open(dev+sys->sprint("/%d/data", channel), sys->ORDWR); if (infd == nil) { fatal(dev+sys->sprint("/%d/data : [%r]", channel)); } sys->print("Sniffing on %s/%d...\n", dev, channel); tmpfd = sys->open(dev+sys->sprint("/%d/ctl", channel), sys->ORDWR); if (tmpfd == nil) { fatal(dev+sys->sprint("/%d/ctl : [%r]", channel)); } # Get all packet types if (sys->fprint(tmpfd, "connect -1") < 0) { fatal("setting interface for all packet types : "+ sys->sprint("%r")); } if (sys->fprint(tmpfd, "promiscuous") < 0) { fatal("setting interface promiscuous failed : "+ sys->sprint("%r")); } spawn reader(infd, args);} reader(infd : ref Sys->FD, args : list of string){ n : int; ethptr : ref Ether; fmtmod : XFmt; ethptr = ref Ether(array [6] of byte, array [6] of byte, array [Sys->ATOMICIO] of byte, 0); while (1) { n = sys->read(infd, ethptr.data, len ethptr.data); if (n < 0) { fatal("error reading from fd : "+sys->sprint("%r")); } ethptr.pktlen = n - len ethptr.rcvifc; ethptr.rcvifc = ethptr.data[0:6]; ethptr.dstifc = ethptr.data[6:12]; # Construct a new module name based on payload type # This 'computed' module name will then be used to # load an appropriate formatting module: nextproto := "ether"+sys->sprint("%4.4X", (int ethptr.data[12] << 8) | (int ethptr.data[13])); # We only load new format module if it is not already # loaded. We use the module data item fmtmod->ID to # keep state within the loaded instance if ((fmtmod == nil) || (fmtmod->ID != nextproto)) { fmtmod = load XFmt XFmt->BASEPATH + nextproto + ".dis"; if (fmtmod == nil) { continue; } } # Call the loaded format module's formatter: (err, nil) := fmtmod->fmt(ethptr.data[14:], args); } return;} b2s(a : array of byte, n : int) : string{ tmp, s : string; # Convert an n-byte array to a 2n Hex character string for (i := 0; i < n; i++) { tmp = sys->sprint("%2.2X", int a[i]); # Grow by pushing the ceiling s[len s] = tmp[0]; s[len s] = tmp[1]; } return s;} usage(){ sys->print( "sniff [-e][-v][-d device][-b <# of Ethernet bytes to dump>]\n");} fatal(s : string){ sys->print("Sniff FATAL :: %s\n", s); kill(sys->pctl(0, nil));} kill(pid: int){ fd := sys->open("#p/"+string pid+"/ctl", sys->OWRITE); if (fd != nil) { sys->fprint(fd, "kill"); }}
#
# Software from the book "Inferno Programming with Limbo"
# published by John Wiley & Sons, January 2003.
#
# p. Stanley-Marbell <pip@gemusehaken.org>
#
implement Xsniff;
include "sys.m";
include "draw.m";
include "arg.m";
include "xsniff.m";
Xsniff : module
{
DUMPBYTES : con 32;
init : fn(nil : ref Draw->Context, args : list of string);
};
sys : Sys;
arg : Arg;
verbose := 0;
etherdump := 0;
dumpbytes := DUMPBYTES;
init(nil : ref Draw->Context, args : list of string)
{
n : int;
buf := array [Sys->ATOMICIO] of byte;
sys = load Sys Sys->PATH;
arg = load Arg Arg->PATH;
dev := "/net/ether0";
arg->init(args);
while((c := arg->opt()) != 0)
{
case c
{
'v' => verbose = 1;
'e' => etherdump = 1;
'b' => dumpbytes = int arg->arg();
'd' => dev = arg->arg();
* => usage();
}
}
args = arg->argv();
tmpfd := sys->open(dev+"/clone", sys->OREAD);
if ((n = sys->read(tmpfd, buf, len buf)) < 1)
{
fatal("Could not read "+dev+"/clone : "+
sys->sprint("[%r]"));
}
(nil, dirstr) := sys->tokenize(string buf[:n], " \t");
channel := int (hd dirstr);
infd := sys->open(dev+sys->sprint("/%d/data", channel),
sys->ORDWR);
if (infd == nil)
{
fatal(dev+sys->sprint("/%d/data : [%r]", channel));
}
sys->print("Sniffing on %s/%d...\n", dev, channel);
tmpfd = sys->open(dev+sys->sprint("/%d/ctl", channel),
sys->ORDWR);
if (tmpfd == nil)
{
fatal(dev+sys->sprint("/%d/ctl : [%r]", channel));
}
# Get all packet types
if (sys->fprint(tmpfd, "connect -1") < 0)
{
fatal("setting interface for all packet types : "+
sys->sprint("%r"));
}
if (sys->fprint(tmpfd, "promiscuous") < 0)
{
fatal("setting interface promiscuous failed : "+
sys->sprint("%r"));
}
spawn reader(infd, args);
}
reader(infd : ref Sys->FD, args : list of string)
{
n : int;
ethptr : ref Ether;
fmtmod : XFmt;
ethptr = ref Ether(array [6] of byte,
array [6] of byte,
array [Sys->ATOMICIO] of byte,
0);
while (1)
{
n = sys->read(infd, ethptr.data, len ethptr.data);
if (n < 0)
{
fatal("error reading from fd : "+sys->sprint("%r"));
}
ethptr.pktlen = n - len ethptr.rcvifc;
ethptr.rcvifc = ethptr.data[0:6];
ethptr.dstifc = ethptr.data[6:12];
# Construct a new module name based on payload type
# This 'computed' module name will then be used to
# load an appropriate formatting module:
nextproto := "ether"+sys->sprint("%4.4X",
(int ethptr.data[12] << 8) |
(int ethptr.data[13]));
# We only load new format module if it is not already
# loaded. We use the module data item fmtmod->ID to
# keep state within the loaded instance
if ((fmtmod == nil) || (fmtmod->ID != nextproto))
{
fmtmod = load XFmt XFmt->BASEPATH +
nextproto + ".dis";
if (fmtmod == nil)
{
continue;
}
}
# Call the loaded format module's formatter:
(err, nil) := fmtmod->fmt(ethptr.data[14:], args);
}
return;
}
b2s(a : array of byte, n : int) : string
{
tmp, s : string;
# Convert an n-byte array to a 2n Hex character string
for (i := 0; i < n; i++)
{
tmp = sys->sprint("%2.2X", int a[i]);
# Grow by pushing the ceiling
s[len s] = tmp[0];
s[len s] = tmp[1];
}
return s;
}
usage()
{
sys->print(
"sniff [-e][-v][-d device][-b <# of Ethernet bytes to dump>]\n");
}
fatal(s : string)
{
sys->print("Sniff FATAL :: %s\n", s);
kill(sys->pctl(0, nil));
}
kill(pid: int)
{
fd := sys->open("#p/"+string pid+"/ctl", sys->OWRITE);
if (fd != nil)
{
sys->fprint(fd, "kill");
}
}