Category Archives: Computer

Reverse engineering a alpha ticker led scoller

Cobra from the Icecrew got his hands on some Led scrollers.

But they only had a windows program to controll these, so we started some reverseengineering.

First we had to make a serial cable.
(Now we could easily use a logic analyser with protocol decoding)

Next i made a sniffer .. because we only had a windows program to control the display.
So we used a windows machine to control the display by serial, and using a read line to a linux machine to stiff the serial traffic

After some tinkering .. we got this

So we wrote some software to control it using Linux

Some code

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
#!/usr/bin/perl
# Get the attention of the sign
print "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
# Tell the sign to print the message
$message = "��������������������� ";
print "\001" . "Z" . "01" . "\002" . "AA" . "\x1B" . " b" . $message . "\004";
#print "\001" . "Z" . "01" . "\002" . "AA" . "\x1B" . " a" . $message .
#"\004";
::::::::::::::
PERLTESTLED
::::::::::::::
#!/usr/bin/perl
print "\0\0\0\0\0\001" . "Z" . "00" . "\002" . "AA" . "\x1B" . " b" . "Test Message" . "\004";
::::::::::::::
PERLTESTLED2
::::::::::::::
#!/usr/bin/perl
# Get the attention of the sign
print "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
# Tell the sign to print the message
$message = "<<<<<<<<<<<<<<<<";
#print "\001" . "Z" . "01" . "\002" . "AA" . "\x1B" . " b" . $message . "\004";
print "\001" . "Z" . "01" . "\002" . "AA" . "\x1B" . " a" . $message . "\004";
#!/usr/bin/perl # Get the attention of the sign print "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; # Tell the sign to print the message $message = "��������������������� "; print "\001" . "Z" . "01" . "\002" . "AA" . "\x1B" . " b" . $message . "\004"; #print "\001" . "Z" . "01" . "\002" . "AA" . "\x1B" . " a" . $message . #"\004"; :::::::::::::: PERLTESTLED :::::::::::::: #!/usr/bin/perl print "\0\0\0\0\0\001" . "Z" . "00" . "\002" . "AA" . "\x1B" . " b" . "Test Message" . "\004"; :::::::::::::: PERLTESTLED2 :::::::::::::: #!/usr/bin/perl # Get the attention of the sign print "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; # Tell the sign to print the message $message = "<<<<<<<<<<<<<<<<"; #print "\001" . "Z" . "01" . "\002" . "AA" . "\x1B" . " b" . $message . "\004"; print "\001" . "Z" . "01" . "\002" . "AA" . "\x1B" . " a" . $message . "\004";
#!/usr/bin/perl
# Get the attention of the sign
print "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
# Tell the sign to print the message
$message = "���������������������    ";
print "\001" . "Z" . "01" . "\002" . "AA" . "\x1B" . " b" . $message . "\004";
#print "\001" . "Z" . "01" . "\002" . "AA" . "\x1B" . " a" . $message . 
#"\004";

::::::::::::::
PERLTESTLED
::::::::::::::
#!/usr/bin/perl
print "\0\0\0\0\0\001" . "Z" . "00" . "\002" . "AA" . "\x1B" . " b" . "Test Message" . "\004";

::::::::::::::
PERLTESTLED2
::::::::::::::
#!/usr/bin/perl
# Get the attention of the sign
print "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
# Tell the sign to print the message
$message = "<<<<<<<<<<<<<<<<";
#print "\001" . "Z" . "01" . "\002" . "AA" . "\x1B" . " b" . $message . "\004";
print "\001" . "Z" . "01" . "\002" . "AA" . "\x1B" . " a" . $message . "\004";

A few days later i wrote a controller using glade. (Could not find more code)

Some time later we found some datasheets which could have helped!

Dartabase

Somewhere start 2002, i made a tool for playing darts.
Well … keeping score and history

I was multiuser, multigame with statistics and undo.
You could click on the little dartboard what your have thrown on a real board. It just kept score and told you best finish options.

Screenshot below was a digitized picture, no way accurate. Versions later the board was realtime drawn with GDlib and pixelperfect.
It even showed you previous throws.

At the end of the game it should give you the hotspots you have thrown.

Later version

Sound Firewall

See also 2nd Firewall 2013 and Led Firewall
https://www.henriaanstoot.nl/2013/08/03/ohm-2013-hackerevent/

While partying @ HAL2001, a hackers event, Venom and I made a Soundfirewall.

We had a little DMZ, with our servers.
This was protected by a iptables firewall.

Our idea was to get a sound notification on every (interesting) network packet the firewall dropped.

So we made this: (At the bottom are the sound definitions.)
Example of the sound we heared whole day.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
#use strict;
# @(#) First Edit: Bas
# @(#) Last Edit: Fash
use POSIX ":sys_wait_h";
use vars qw(%Msg_Rec);
$SIG{'TERM'} = $SIG{'HUP'} = 'goodbye';
$SIG{'CHLD'} = 'IGNORE';
## Constants
my $BELL = "";
my $MAILER = "/usr/sbin/sendmail";
my $WRITE = "/usr/bin/write";
$/ = "
";
autoflush STDOUT;
sub goodbye {
$| = 0;
close_pipe_if_open();
exit(0);
}
#
# in_range($range, $number)
# returns 1 if $number is inside $range, 0 if not
#
sub in_range {
my $range = shift;
my $num = shift;
foreach my $f (split(/,/, $range)) {
if ($f =~ /-/) {
my ($low,$high) = split(/-/, $f);
return 1 if ($low <= $num and $num <= $high);
} elsif ($f == $num) {
return 1;
}
}
return 0;
}
#
# inside_time_window($days,$hours)
# returns 1 if inside window, 0 if outside window
#
sub inside_time_window {
my $range = shift;
my($days, $hours) = split(/:/, $range);
my ($hr, $wday) = (localtime(time))[2,6];
if (($days eq '*' or in_range($days, $wday))
and ($hours eq '*' or in_range($hours, $hr))) {
return 1;
} else {
return 0;
}
}
print "\n*** swatch-3.0.1 (pid:6826) started at " . `/bin/date` . "\n";
use Date::Calc qw(:all);
sub parse_dot {
my $message = shift;
my $dot_loc = shift;
my @dot = ();
my @ranges = split(/:/, $dot_loc);
foreach my $range (0..$#ranges) {
if ($ranges[$range] != -1) {
my ($begin, $end) = split(/-/, $ranges[$range]);
$dot[$range] = substr($message, $begin, ($end - $begin + 1));
}
}
return @dot;
}
my ($date_loc, $time_loc) = ("-1:0-2:4-5", "7-8:10-11:13-14");
my %months = (
Jan => 1,
Feb => 2,
Mar => 3,
Apr => 4,
May => 5,
Jun => 6,
Jul => 7,
Aug => 8,
Sep => 9,
Oct => 10,
Nov => 11,
Dec => 12
);
# Returns an array of year, month, day, hours, minutes, and seconds.
#
sub YMDHMS {
my $string = shift;
my $year_today = (Today())[0];
my ($y, $m, $d) = parse_dot($string, $date_loc);
my ($hrs, $mins, $secs) = parse_dot($string, $time_loc);
if (length($y) eq 0) { $y = (Today())[0] };
return ($y, $months{$m}, $d, $hrs, $mins, $secs);
}
sub new_msg {
my $use = shift;
my $msg = shift;
my $count = shift;
my @delta = @_;
my $delta;
if ($delta[0] == 0) {
$delta = sprintf("%d:%.2d:%.2d", $delta[1], $delta[2], $delta[3]);
} else {
$delta = sprintf("$delta[0] day%s %d:%.2d:%.2d", $delta[0] > 1 ? 's' : '',
$delta[1], $delta[2], $delta[3]);
}
if ($use eq 'regex') {
return "$count $msg regular expressions in $delta";
} else {
return "$count in $delta: $msg";
}
}
#
# Stores message information in
# $Msg_Rec = (
# {<truncated message>|<pattern>} => {
# dhms => [ array ], # days,hours,minutes,seconds
# count => integer,
sub throttle {
my %opts = (
KEY => $_,
CUT_MARKS => [ "0:16" ], # not used yet
USE => 'message',
@_
);
my $msg = $opts{'KEY'};
my $use = $opts{'USE'};
my @ymdhms = YMDHMS($msg);
my $key;
my @min_dhms_delta = split(/(\s+|:)/, $opts{'MIN_DELTA'});
foreach my $i (0..$#min_dhms_delta) {
# strip out unwanted element
splice (@min_dhms_delta, $i, 1) if ($min_dhms_delta[$i] eq ":");
}
if ($use eq 'regex') {
$key = $opts{'REGEX'};
} else {
$key = substr($msg, 16);
$key =~ s/\[\d+\]/[PID]/;
}
while ($#min_dhms_delta < 3) {
unshift(@min_dhms_delta, 0); # make sure that the dhms array is full
}
if (exists $Msg_Rec{$key} and defined $Msg_Rec{$key}->{ymdhms}) {
my $passed = 1;
$Msg_Rec{$key}->{count}++;
if ($ymdhms[1] > $Msg_Rec{$key}->{ymdhms}[1]) { $ymdhms[0]--; }
my @delta_dhms = Delta_DHMS(@{$Msg_Rec{$key}->{ymdhms}}, @ymdhms);
foreach my $i (0..$#min_dhms_delta) {
$passed = 0 if ($delta_dhms[$i] < $min_dhms_delta[$i]);
last unless ($delta_dhms[$i] == $min_dhms_delta[$i]);
}
if ($passed) {
my $new = '';
$new = new_msg($use, $key, $Msg_Rec{$key}->{count}, @delta_dhms);
$Msg_Rec{$key}->{ymdhms} = [ @ymdhms ];
$Msg_Rec{$key}->{count} = 1;
return $new;
} else {
return '';
}
} else {
my $rec;
$rec->{ymdhms} = [ @ymdhms ];
$Msg_Rec{$key} = $rec;
return $msg;
}
}
##
## ACTION SUBROUTINES
##
my %text_modes = (
"black" => "\033[30;1m",
"red" => "\033[31;1m",
"green" => "\033[32;1m",
"yellow" => "\033[33;1m",
"blue" => "\033[34;1m",
"magenta" => "\033[35;1m",
"cyan" => "\033[36;1m",
"white" => "\033[37;1m",
"black_h" => "\033[40;1m",
"red_h" => "\033[41;1m",
"green_h" => "\033[42;1m",
"yellow_h" => "\033[43;1m",
"blue_h" => "\033[44;1m",
"magenta_h" => "\033[45;1m",
"cyan_h" => "\033[46;1m",
"white_h" => "\033[47;1m",
"bold" => "\033[1m",
"blink" => "\033[5m",
"inverse" => "\033[7m",
"normal" => "\033[0m",
"underscore" => "\033[4m",
);
sub echo {
my %args = (
'MODES' => [ 'normal' ],
@_
);
return if (exists($args{'WHEN'}) and not inside_time_window($args{'WHEN'}));
if ($args{'MODES'}[0] eq 'random') {
my @mode_names = keys %text_modes;
print $text_modes{$mode_names[rand $#mode_names]};
} else {
foreach my $mode (@{$args{'MODES'}}) {
print $text_modes{$mode};
}
}
print $args{'MESSAGE'};
print $text_modes{'normal'};
print "\n";
}
#
# ring_bell(args) -- send x number of control-G characters to the output.
#
sub ring_bell {
my %args = (
'RINGS' => 1,
@_
);
my $sun_terminal = (`uname -s` eq 'SunOS\n');
return if exists($args{'WHEN'}) and not inside_time_window($args{'WHEN'});
my $bells = $args{'RINGS'};
for ( ; $bells > 0 ; $bells-- ) {
print $BELL;
sleep 1 if $sun_terminal; # SunOS needed this. Not sure about Solaris though
}
}
#
# exec_command(args) -- fork and execute a command
#
sub exec_command {
my %args = (@_);
my $exec_pid;
my $command;
if (exists $args{'COMMAND'}) {
$command = $args{'COMMAND'};
} else {
warn "$0: No command was specified in exec action.\n";
return;
}
return if exists($args{'WHEN'}) and not inside_time_window($args{'WHEN'});
EXECFORK: {
if ($exec_pid = fork) {
waitpid(-1, WNOHANG);
return;
} elsif (defined $exec_pid) {
exec($command);
} elsif ($! =~ /No more processes/) {
# EAGAIN, supposedly recoverable fork error
sleep 5;
redo EXECFORK;
} else {
warn "$0: Can't fork to exec $command: $!\n";
}
}
return;
}
{
my $pipe_is_open;
my $current_command_name;
#
# send_message_to_pipe -- send text to a pipe.
#
# usage: &send_message_to_pipe($program_to_pipe_to_including_the_vertical_bar_symbol,
# $message_to_send_to_the_pipe);
#
sub send_message_to_pipe {
my %args = (@_);
my $command;
if (exists $args{'COMMAND'}) {
$command = $args{'COMMAND'};
} else {
warn "$0: No command was specified in pipe action.\n";
return;
}
return if exists($args{'WHEN'}) and not inside_time_window($args{'WHEN'});
# open a new pipe if necessary
if ( !$pipe_is_open or $current_command_name ne $command ) {
# first close an open pipe
close(PIPE) if $pipe_is_open;
$pipe_is_open = 0;
open(PIPE, "| $command")
or warn "$0: cannot open pipe to $command: $!\n" && return;
PIPE->autoflush(1);
$pipe_is_open = 1;
$current_command_name = $command;
}
# send the text
print PIPE "$args{'MESSAGE'}";
if (not exists $args{'KEEP_OPEN'}) {
close(PIPE) if $pipe_is_open;
$pipe_is_open = 0;
}
}
#
# close_pipe_if_open -- used at the end of a script to close a pipe
# opened by &pipe_it().
#
# usage: &close_pipe_if_open();
#
sub close_pipe_if_open {
if ($pipe_is_open) {
close(PIPE);
}
}
}
#
# send_email -- send some mail using $MAILER.
#
# usage: &send_email($addresses_to_mail_to);
#
sub send_email {
my $login = (getpwuid($<))[0];
my %args = (
'ADDRESSES' => $login,
'SUBJECT' => 'Message from Swatch',
@_
);
return if exists($args{'WHEN'}) and not inside_time_window($args{'WHEN'});
my $addresses = $args{'ADDRESSES'};
$addresses =~ s/:/,/g;
if ($MAILER eq '') {
warn "ERROR: $0 cannot find a mail delivery program\n";
return;
}
open(MAIL, "| $MAILER $addresses")
or warn "$0: cannot open pipe to $MAILER: $!\n" && return;
print MAIL "To: $addresses\n";
print MAIL "Subject: $args{SUBJECT}\n\n";
print MAIL "$args{'MESSAGE'}\n";
close(MAIL);
}
#
# write_message -- use $WRITE to send a message logged on users.
#
sub write_message {
my %args = (@_);
return if exists($args{'WHEN'}) and not inside_time_window($args{'WHEN'});
if ($WRITE eq '') {
warn "ERROR: $0 cannot find the write(1) program\n";
return;
}
if (exists($args{'USERS'})) {
foreach my $user (split(/:/, $args{'USERS'})) {
send_message_to_pipe(COMMAND => "$WRITE $user 2>/dev/null",
MESSAGE => "$args{'MESSAGE'}\n");
}
}
}
use File::Tail;
my $Filename = '/var/log/ulog/syslogemu.log';
my $File = File::Tail->new(name=>$Filename, maxinterval => 1, interval => 1);
if (not defined $File) {
die "/usr/local/bin/swatch: cannot read input \"$Filename\": $!\n";
}
LOOP: while (defined($_=$File->read)) {
chomp;
my $sanitized_ = $_;
@_ = split;
# quote all special shell chars
$sanitized_ =~ s/([;&\(\)\|\^><\$`'\\])/\\$1/g;
my @sanitized_ = split(/\s+/, $sanitized_);
if (/INVALID|REPEATED|INCOMPLETE:LOGIN/) {
echo('MODES' => [ "bold", ], 'MESSAGE' => "$_", );
ring_bell('RINGS' => "3", );
next;
}
if (/(panic|halt)/) {
echo('MESSAGE' => "$_", );
ring_bell();
next;
}
if (/Regents/) {
echo('MODES' => [ "bold", ], 'MESSAGE' => "$_", );
ring_bell();
next;
}
if (/ipfw:.*Deny ICMP:8.0/) {
echo('MODES' => [ "bold", ], 'MESSAGE' => "$_", );
exec_command('COMMAND' => "mpg123 -q /root/wavs/drip.wav &", );
next;
}
if (/ipfw:.*Deny TCP .*:6000/) {
echo('MODES' => [ "bold", ], 'MESSAGE' => "$_", );
exec_command('COMMAND' => "mpg123 -q /root/wavs/camera.wav &", );
next;
}
if (/ipfw:.*Deny UDP .*:513/) {
echo('MODES' => [ "bold", ], 'MESSAGE' => "$_", );
exec_command('COMMAND' => "mpg123 -q /root/wavs/flush.wav &", );
next;
}
if (/ipfw:.*Deny TCP .*:21/) {
echo('MODES' => [ "bold", ], 'MESSAGE' => "$_", );
exec_command('COMMAND' => "mpg123 -q /root/wavs/vault.wav &", );
next;
}
if (/PROTO=TCP .*DPT=80/) {
echo('MODES' => [ "bold", ], 'MESSAGE' => "$_", );
exec_command('COMMAND' => "mpg123 /root/wavs/tcp80.mp3 &", );
next;
}
if (/PROTO=TCP .*DPT=23/) {
echo('MODES' => [ "bold", ], 'MESSAGE' => "$_", );
exec_command('COMMAND' => "mpg123 /root/wavs/tcp23.mp3 &", );
next;
}
if (/UDP .*=1300007/) {
echo('MODES' => [ "bold", ], 'MESSAGE' => "$_", );
exec_command('COMMAND' => "mpg123 /root/wavs/udp137.mp3 &", );
next;
}
if (/PROTO=ICMP/) {
echo('MODES' => [ "bold", ], 'MESSAGE' => "$_", );
exec_command('COMMAND' => "mpg123 /root/wavs/ping.mp3 &", );
next;
}
if (/.*/) {
echo('MESSAGE' => "$_", );
next;
}
}
#use strict; # @(#) First Edit: Bas # @(#) Last Edit: Fash use POSIX ":sys_wait_h"; use vars qw(%Msg_Rec); $SIG{'TERM'} = $SIG{'HUP'} = 'goodbye'; $SIG{'CHLD'} = 'IGNORE'; ## Constants my $BELL = ""; my $MAILER = "/usr/sbin/sendmail"; my $WRITE = "/usr/bin/write"; $/ = " "; autoflush STDOUT; sub goodbye { $| = 0; close_pipe_if_open(); exit(0); } # # in_range($range, $number) # returns 1 if $number is inside $range, 0 if not # sub in_range { my $range = shift; my $num = shift; foreach my $f (split(/,/, $range)) { if ($f =~ /-/) { my ($low,$high) = split(/-/, $f); return 1 if ($low <= $num and $num <= $high); } elsif ($f == $num) { return 1; } } return 0; } # # inside_time_window($days,$hours) # returns 1 if inside window, 0 if outside window # sub inside_time_window { my $range = shift; my($days, $hours) = split(/:/, $range); my ($hr, $wday) = (localtime(time))[2,6]; if (($days eq '*' or in_range($days, $wday)) and ($hours eq '*' or in_range($hours, $hr))) { return 1; } else { return 0; } } print "\n*** swatch-3.0.1 (pid:6826) started at " . `/bin/date` . "\n"; use Date::Calc qw(:all); sub parse_dot { my $message = shift; my $dot_loc = shift; my @dot = (); my @ranges = split(/:/, $dot_loc); foreach my $range (0..$#ranges) { if ($ranges[$range] != -1) { my ($begin, $end) = split(/-/, $ranges[$range]); $dot[$range] = substr($message, $begin, ($end - $begin + 1)); } } return @dot; } my ($date_loc, $time_loc) = ("-1:0-2:4-5", "7-8:10-11:13-14"); my %months = ( Jan => 1, Feb => 2, Mar => 3, Apr => 4, May => 5, Jun => 6, Jul => 7, Aug => 8, Sep => 9, Oct => 10, Nov => 11, Dec => 12 ); # Returns an array of year, month, day, hours, minutes, and seconds. # sub YMDHMS { my $string = shift; my $year_today = (Today())[0]; my ($y, $m, $d) = parse_dot($string, $date_loc); my ($hrs, $mins, $secs) = parse_dot($string, $time_loc); if (length($y) eq 0) { $y = (Today())[0] }; return ($y, $months{$m}, $d, $hrs, $mins, $secs); } sub new_msg { my $use = shift; my $msg = shift; my $count = shift; my @delta = @_; my $delta; if ($delta[0] == 0) { $delta = sprintf("%d:%.2d:%.2d", $delta[1], $delta[2], $delta[3]); } else { $delta = sprintf("$delta[0] day%s %d:%.2d:%.2d", $delta[0] > 1 ? 's' : '', $delta[1], $delta[2], $delta[3]); } if ($use eq 'regex') { return "$count $msg regular expressions in $delta"; } else { return "$count in $delta: $msg"; } } # # Stores message information in # $Msg_Rec = ( # {<truncated message>|<pattern>} => { # dhms => [ array ], # days,hours,minutes,seconds # count => integer, sub throttle { my %opts = ( KEY => $_, CUT_MARKS => [ "0:16" ], # not used yet USE => 'message', @_ ); my $msg = $opts{'KEY'}; my $use = $opts{'USE'}; my @ymdhms = YMDHMS($msg); my $key; my @min_dhms_delta = split(/(\s+|:)/, $opts{'MIN_DELTA'}); foreach my $i (0..$#min_dhms_delta) { # strip out unwanted element splice (@min_dhms_delta, $i, 1) if ($min_dhms_delta[$i] eq ":"); } if ($use eq 'regex') { $key = $opts{'REGEX'}; } else { $key = substr($msg, 16); $key =~ s/\[\d+\]/[PID]/; } while ($#min_dhms_delta < 3) { unshift(@min_dhms_delta, 0); # make sure that the dhms array is full } if (exists $Msg_Rec{$key} and defined $Msg_Rec{$key}->{ymdhms}) { my $passed = 1; $Msg_Rec{$key}->{count}++; if ($ymdhms[1] > $Msg_Rec{$key}->{ymdhms}[1]) { $ymdhms[0]--; } my @delta_dhms = Delta_DHMS(@{$Msg_Rec{$key}->{ymdhms}}, @ymdhms); foreach my $i (0..$#min_dhms_delta) { $passed = 0 if ($delta_dhms[$i] < $min_dhms_delta[$i]); last unless ($delta_dhms[$i] == $min_dhms_delta[$i]); } if ($passed) { my $new = ''; $new = new_msg($use, $key, $Msg_Rec{$key}->{count}, @delta_dhms); $Msg_Rec{$key}->{ymdhms} = [ @ymdhms ]; $Msg_Rec{$key}->{count} = 1; return $new; } else { return ''; } } else { my $rec; $rec->{ymdhms} = [ @ymdhms ]; $Msg_Rec{$key} = $rec; return $msg; } } ## ## ACTION SUBROUTINES ## my %text_modes = ( "black" => "\033[30;1m", "red" => "\033[31;1m", "green" => "\033[32;1m", "yellow" => "\033[33;1m", "blue" => "\033[34;1m", "magenta" => "\033[35;1m", "cyan" => "\033[36;1m", "white" => "\033[37;1m", "black_h" => "\033[40;1m", "red_h" => "\033[41;1m", "green_h" => "\033[42;1m", "yellow_h" => "\033[43;1m", "blue_h" => "\033[44;1m", "magenta_h" => "\033[45;1m", "cyan_h" => "\033[46;1m", "white_h" => "\033[47;1m", "bold" => "\033[1m", "blink" => "\033[5m", "inverse" => "\033[7m", "normal" => "\033[0m", "underscore" => "\033[4m", ); sub echo { my %args = ( 'MODES' => [ 'normal' ], @_ ); return if (exists($args{'WHEN'}) and not inside_time_window($args{'WHEN'})); if ($args{'MODES'}[0] eq 'random') { my @mode_names = keys %text_modes; print $text_modes{$mode_names[rand $#mode_names]}; } else { foreach my $mode (@{$args{'MODES'}}) { print $text_modes{$mode}; } } print $args{'MESSAGE'}; print $text_modes{'normal'}; print "\n"; } # # ring_bell(args) -- send x number of control-G characters to the output. # sub ring_bell { my %args = ( 'RINGS' => 1, @_ ); my $sun_terminal = (`uname -s` eq 'SunOS\n'); return if exists($args{'WHEN'}) and not inside_time_window($args{'WHEN'}); my $bells = $args{'RINGS'}; for ( ; $bells > 0 ; $bells-- ) { print $BELL; sleep 1 if $sun_terminal; # SunOS needed this. Not sure about Solaris though } } # # exec_command(args) -- fork and execute a command # sub exec_command { my %args = (@_); my $exec_pid; my $command; if (exists $args{'COMMAND'}) { $command = $args{'COMMAND'}; } else { warn "$0: No command was specified in exec action.\n"; return; } return if exists($args{'WHEN'}) and not inside_time_window($args{'WHEN'}); EXECFORK: { if ($exec_pid = fork) { waitpid(-1, WNOHANG); return; } elsif (defined $exec_pid) { exec($command); } elsif ($! =~ /No more processes/) { # EAGAIN, supposedly recoverable fork error sleep 5; redo EXECFORK; } else { warn "$0: Can't fork to exec $command: $!\n"; } } return; } { my $pipe_is_open; my $current_command_name; # # send_message_to_pipe -- send text to a pipe. # # usage: &send_message_to_pipe($program_to_pipe_to_including_the_vertical_bar_symbol, # $message_to_send_to_the_pipe); # sub send_message_to_pipe { my %args = (@_); my $command; if (exists $args{'COMMAND'}) { $command = $args{'COMMAND'}; } else { warn "$0: No command was specified in pipe action.\n"; return; } return if exists($args{'WHEN'}) and not inside_time_window($args{'WHEN'}); # open a new pipe if necessary if ( !$pipe_is_open or $current_command_name ne $command ) { # first close an open pipe close(PIPE) if $pipe_is_open; $pipe_is_open = 0; open(PIPE, "| $command") or warn "$0: cannot open pipe to $command: $!\n" && return; PIPE->autoflush(1); $pipe_is_open = 1; $current_command_name = $command; } # send the text print PIPE "$args{'MESSAGE'}"; if (not exists $args{'KEEP_OPEN'}) { close(PIPE) if $pipe_is_open; $pipe_is_open = 0; } } # # close_pipe_if_open -- used at the end of a script to close a pipe # opened by &pipe_it(). # # usage: &close_pipe_if_open(); # sub close_pipe_if_open { if ($pipe_is_open) { close(PIPE); } } } # # send_email -- send some mail using $MAILER. # # usage: &send_email($addresses_to_mail_to); # sub send_email { my $login = (getpwuid($<))[0]; my %args = ( 'ADDRESSES' => $login, 'SUBJECT' => 'Message from Swatch', @_ ); return if exists($args{'WHEN'}) and not inside_time_window($args{'WHEN'}); my $addresses = $args{'ADDRESSES'}; $addresses =~ s/:/,/g; if ($MAILER eq '') { warn "ERROR: $0 cannot find a mail delivery program\n"; return; } open(MAIL, "| $MAILER $addresses") or warn "$0: cannot open pipe to $MAILER: $!\n" && return; print MAIL "To: $addresses\n"; print MAIL "Subject: $args{SUBJECT}\n\n"; print MAIL "$args{'MESSAGE'}\n"; close(MAIL); } # # write_message -- use $WRITE to send a message logged on users. # sub write_message { my %args = (@_); return if exists($args{'WHEN'}) and not inside_time_window($args{'WHEN'}); if ($WRITE eq '') { warn "ERROR: $0 cannot find the write(1) program\n"; return; } if (exists($args{'USERS'})) { foreach my $user (split(/:/, $args{'USERS'})) { send_message_to_pipe(COMMAND => "$WRITE $user 2>/dev/null", MESSAGE => "$args{'MESSAGE'}\n"); } } } use File::Tail; my $Filename = '/var/log/ulog/syslogemu.log'; my $File = File::Tail->new(name=>$Filename, maxinterval => 1, interval => 1); if (not defined $File) { die "/usr/local/bin/swatch: cannot read input \"$Filename\": $!\n"; } LOOP: while (defined($_=$File->read)) { chomp; my $sanitized_ = $_; @_ = split; # quote all special shell chars $sanitized_ =~ s/([;&\(\)\|\^><\$`'\\])/\\$1/g; my @sanitized_ = split(/\s+/, $sanitized_); if (/INVALID|REPEATED|INCOMPLETE:LOGIN/) { echo('MODES' => [ "bold", ], 'MESSAGE' => "$_", ); ring_bell('RINGS' => "3", ); next; } if (/(panic|halt)/) { echo('MESSAGE' => "$_", ); ring_bell(); next; } if (/Regents/) { echo('MODES' => [ "bold", ], 'MESSAGE' => "$_", ); ring_bell(); next; } if (/ipfw:.*Deny ICMP:8.0/) { echo('MODES' => [ "bold", ], 'MESSAGE' => "$_", ); exec_command('COMMAND' => "mpg123 -q /root/wavs/drip.wav &", ); next; } if (/ipfw:.*Deny TCP .*:6000/) { echo('MODES' => [ "bold", ], 'MESSAGE' => "$_", ); exec_command('COMMAND' => "mpg123 -q /root/wavs/camera.wav &", ); next; } if (/ipfw:.*Deny UDP .*:513/) { echo('MODES' => [ "bold", ], 'MESSAGE' => "$_", ); exec_command('COMMAND' => "mpg123 -q /root/wavs/flush.wav &", ); next; } if (/ipfw:.*Deny TCP .*:21/) { echo('MODES' => [ "bold", ], 'MESSAGE' => "$_", ); exec_command('COMMAND' => "mpg123 -q /root/wavs/vault.wav &", ); next; } if (/PROTO=TCP .*DPT=80/) { echo('MODES' => [ "bold", ], 'MESSAGE' => "$_", ); exec_command('COMMAND' => "mpg123 /root/wavs/tcp80.mp3 &", ); next; } if (/PROTO=TCP .*DPT=23/) { echo('MODES' => [ "bold", ], 'MESSAGE' => "$_", ); exec_command('COMMAND' => "mpg123 /root/wavs/tcp23.mp3 &", ); next; } if (/UDP .*=1300007/) { echo('MODES' => [ "bold", ], 'MESSAGE' => "$_", ); exec_command('COMMAND' => "mpg123 /root/wavs/udp137.mp3 &", ); next; } if (/PROTO=ICMP/) { echo('MODES' => [ "bold", ], 'MESSAGE' => "$_", ); exec_command('COMMAND' => "mpg123 /root/wavs/ping.mp3 &", ); next; } if (/.*/) { echo('MESSAGE' => "$_", ); next; } }
#use strict;
#       @(#)    First Edit: Bas
#       @(#)    Last Edit: Fash

use POSIX ":sys_wait_h";
use vars qw(%Msg_Rec);

$SIG{'TERM'} = $SIG{'HUP'} = 'goodbye';
$SIG{'CHLD'} = 'IGNORE';

## Constants
my $BELL   = "";
my $MAILER = "/usr/sbin/sendmail";
my $WRITE  = "/usr/bin/write";
$/ = "
";

autoflush STDOUT;

sub goodbye {
  $| = 0;

  close_pipe_if_open();
  exit(0);
}

#
# in_range($range, $number) 
# returns 1 if $number is inside $range, 0 if not
#
sub in_range {
  my $range = shift;
  my $num = shift;

  foreach my $f (split(/,/, $range)) {
    if ($f =~ /-/) {
      my ($low,$high) = split(/-/, $f);
      return 1 if ($low <= $num and $num <= $high);
    } elsif ($f == $num) {
      return 1;
    }
  }
  return 0;
}

# 
# inside_time_window($days,$hours)
# returns 1 if inside window, 0 if outside window
#
sub inside_time_window {
  my $range = shift;
  my($days, $hours) = split(/:/, $range);

  my ($hr, $wday) = (localtime(time))[2,6];

  if (($days eq '*' or in_range($days, $wday))
      and ($hours eq '*' or in_range($hours, $hr))) {
    return 1;
  } else {
    return 0;
  }
}

  
print "\n*** swatch-3.0.1 (pid:6826) started at " . `/bin/date` . "\n";

  
use Date::Calc qw(:all);

sub parse_dot {
  my $message = shift;
  my $dot_loc = shift;
  my @dot = ();
  my @ranges = split(/:/, $dot_loc);

  foreach my $range (0..$#ranges) {
    if ($ranges[$range] != -1) {
      my ($begin, $end) = split(/-/, $ranges[$range]);
      $dot[$range] = substr($message, $begin, ($end - $begin + 1));
    }
  }

  return @dot;
}

my ($date_loc, $time_loc) = ("-1:0-2:4-5", "7-8:10-11:13-14");
my %months = (
              Jan => 1,
              Feb => 2,
              Mar => 3,
              Apr => 4,
              May => 5,
              Jun => 6,
              Jul => 7,
              Aug => 8,
              Sep => 9,
              Oct => 10,
              Nov => 11,
              Dec => 12
             );

# Returns an array of year, month, day, hours, minutes, and seconds.
#
sub YMDHMS {
  my $string = shift;
  my $year_today = (Today())[0];

  my ($y, $m, $d) = parse_dot($string, $date_loc);
  my ($hrs, $mins, $secs) = parse_dot($string, $time_loc);
  if (length($y) eq 0) { $y = (Today())[0] };

  return ($y, $months{$m}, $d, $hrs, $mins, $secs);
}

sub new_msg {
  my $use = shift;
  my $msg = shift;
  my $count = shift;
  my @delta = @_;
  my $delta;
  if ($delta[0] == 0) {
    $delta = sprintf("%d:%.2d:%.2d", $delta[1], $delta[2], $delta[3]);
  } else {
    $delta = sprintf("$delta[0] day%s %d:%.2d:%.2d", $delta[0] > 1 ? 's' : '',
                    $delta[1], $delta[2], $delta[3]);
  }
  if ($use eq 'regex') {
    return "$count $msg regular expressions in $delta";
  } else {
    return "$count in $delta: $msg";
  }
}

#
# Stores message information in 
#    $Msg_Rec = (
#      {<truncated message>|<pattern>} => {
#        dhms => [ array ], # days,hours,minutes,seconds
#        count => integer,

sub throttle {
  my %opts = (
              KEY       => $_,
              CUT_MARKS => [ "0:16" ], # not used yet
              USE       => 'message',
              @_
             );

  my $msg = $opts{'KEY'};
  my $use = $opts{'USE'};
  my @ymdhms = YMDHMS($msg);
  my $key;
  my @min_dhms_delta = split(/(\s+|:)/, $opts{'MIN_DELTA'});

  foreach my $i (0..$#min_dhms_delta) {
    # strip out unwanted element
    splice (@min_dhms_delta, $i, 1) if ($min_dhms_delta[$i] eq ":");
  }

  if ($use eq 'regex') {
    $key = $opts{'REGEX'};
  } else {
    $key = substr($msg, 16);
    $key =~ s/\[\d+\]/[PID]/;
  }

  while ($#min_dhms_delta < 3) {
    unshift(@min_dhms_delta, 0); # make sure that the dhms array is full
  }

  if (exists $Msg_Rec{$key} and defined $Msg_Rec{$key}->{ymdhms}) {
    my $passed = 1;
    $Msg_Rec{$key}->{count}++;
    if ($ymdhms[1] > $Msg_Rec{$key}->{ymdhms}[1]) { $ymdhms[0]--; }

    my @delta_dhms = Delta_DHMS(@{$Msg_Rec{$key}->{ymdhms}}, @ymdhms);
    foreach my $i (0..$#min_dhms_delta) {
      $passed = 0 if ($delta_dhms[$i] < $min_dhms_delta[$i]);
      last unless ($delta_dhms[$i] == $min_dhms_delta[$i]);
    }    
    if ($passed) {
      my $new = '';
      $new = new_msg($use, $key, $Msg_Rec{$key}->{count}, @delta_dhms);
      $Msg_Rec{$key}->{ymdhms} = [ @ymdhms ];
      $Msg_Rec{$key}->{count} = 1;
      return $new;
    } else {
      return '';
    }
  } else {
    my $rec;
    $rec->{ymdhms} = [ @ymdhms ];
    $Msg_Rec{$key} = $rec;
    return $msg;
  }
}


##
## ACTION SUBROUTINES
##

my %text_modes = (
  "black"       => "\033[30;1m",
  "red"         => "\033[31;1m",
  "green"       => "\033[32;1m",
  "yellow"      => "\033[33;1m",
  "blue"        => "\033[34;1m",
  "magenta"     => "\033[35;1m",
  "cyan"        => "\033[36;1m",
  "white"       => "\033[37;1m",
  "black_h"     => "\033[40;1m",
  "red_h"       => "\033[41;1m",
  "green_h"     => "\033[42;1m",
  "yellow_h"    => "\033[43;1m",
  "blue_h"      => "\033[44;1m",
  "magenta_h"   => "\033[45;1m",
  "cyan_h"      => "\033[46;1m",
  "white_h"     => "\033[47;1m",
  "bold"        => "\033[1m",
  "blink"       => "\033[5m",
  "inverse"     => "\033[7m",
  "normal"      => "\033[0m",
  "underscore"  => "\033[4m",
);
  
sub echo {
  my %args = (
              'MODES' => [ 'normal' ],
              @_
             );

  return if (exists($args{'WHEN'}) and not inside_time_window($args{'WHEN'}));
  
  if ($args{'MODES'}[0] eq 'random') {
    my @mode_names = keys %text_modes;
    print $text_modes{$mode_names[rand $#mode_names]};
  } else {
    foreach my $mode (@{$args{'MODES'}}) {
      print $text_modes{$mode};
    }
  }
  print $args{'MESSAGE'};
  print $text_modes{'normal'};
  print "\n";
}

#
# ring_bell(args) -- send x number of control-G characters to the output.
#
sub ring_bell {
  my %args = (
              'RINGS' => 1,
              @_
             );
  my $sun_terminal = (`uname -s` eq 'SunOS\n');
  
  return if exists($args{'WHEN'}) and not inside_time_window($args{'WHEN'});
  
  my $bells = $args{'RINGS'};
  for ( ; $bells > 0 ; $bells-- ) {
    print $BELL;
    sleep 1 if $sun_terminal; # SunOS needed this. Not sure about Solaris though
  }
}

#
# exec_command(args) -- fork and execute a command
#
sub exec_command {
  my %args = (@_);
  my $exec_pid;
  my $command;

  if (exists $args{'COMMAND'}) {
    $command = $args{'COMMAND'};
  } else {
    warn "$0: No command was specified in exec action.\n";
    return;
  }

  return if exists($args{'WHEN'}) and not inside_time_window($args{'WHEN'});

 EXECFORK: {
    if ($exec_pid = fork) {
      waitpid(-1, WNOHANG);
      return;
    } elsif (defined $exec_pid) {
      exec($command);
      } elsif ($! =~ /No more processes/) {
        # EAGAIN, supposedly recoverable fork error
        sleep 5;
        redo EXECFORK;
      } else {
        warn "$0: Can't fork to exec $command: $!\n";
      }
  }
  return;
}


{
  my $pipe_is_open;
  my $current_command_name;
  #
  # send_message_to_pipe -- send text to a pipe.
  #
  # usage: &send_message_to_pipe($program_to_pipe_to_including_the_vertical_bar_symbol,
  #               $message_to_send_to_the_pipe);
  # 
  
  sub send_message_to_pipe {
    my %args = (@_);
    my $command;

    if (exists $args{'COMMAND'}) {
      $command = $args{'COMMAND'};
    } else {
      warn "$0: No command was specified in pipe action.\n";
      return;
    }

    return if exists($args{'WHEN'}) and not inside_time_window($args{'WHEN'});

    # open a new pipe if necessary
    if ( !$pipe_is_open or $current_command_name ne $command ) {
      # first close an open pipe
      close(PIPE) if $pipe_is_open;
      $pipe_is_open = 0;
      open(PIPE, "| $command") 
        or warn "$0: cannot open pipe to $command: $!\n" && return;
      PIPE->autoflush(1);
      $pipe_is_open = 1;
      $current_command_name = $command;
    }
    # send the text
    print PIPE "$args{'MESSAGE'}";

    if (not exists $args{'KEEP_OPEN'}) {
      close(PIPE) if $pipe_is_open;
      $pipe_is_open = 0;
    }
  }

  #
  # close_pipe_if_open -- used at the end of a script to close a pipe
  #     opened by &pipe_it().
  #
  # usage: &close_pipe_if_open();
  #
  sub close_pipe_if_open {
    if ($pipe_is_open) {
      close(PIPE);
    }
  }
}


#
# send_email -- send some mail using $MAILER.
#
# usage: &send_email($addresses_to_mail_to);
#
sub send_email {
  my $login = (getpwuid($<))[0];
  my %args = (
              'ADDRESSES' => $login,
              'SUBJECT' => 'Message from Swatch',
              @_
             );

  return if exists($args{'WHEN'}) and not inside_time_window($args{'WHEN'});

  my $addresses = $args{'ADDRESSES'};
  $addresses =~ s/:/,/g;

  if ($MAILER eq '') {
    warn "ERROR: $0 cannot find a mail delivery program\n";
    return;
  }

  open(MAIL, "| $MAILER $addresses")
    or warn "$0: cannot open pipe to $MAILER: $!\n" && return;

  print MAIL "To: $addresses\n";
  print MAIL "Subject: $args{SUBJECT}\n\n";
  print MAIL "$args{'MESSAGE'}\n";
  close(MAIL);
}


#
# write_message -- use $WRITE to send a message logged on users.
#
sub write_message {
  my %args = (@_);

  return if exists($args{'WHEN'}) and not inside_time_window($args{'WHEN'});

  if ($WRITE eq '') {
    warn "ERROR: $0 cannot find the write(1) program\n";
    return;
  }

  if (exists($args{'USERS'})) {
    foreach my $user (split(/:/, $args{'USERS'})) {
      send_message_to_pipe(COMMAND => "$WRITE $user 2>/dev/null", 
                           MESSAGE => "$args{'MESSAGE'}\n");
    }
  }
}

use File::Tail;
my $Filename = '/var/log/ulog/syslogemu.log';
my $File = File::Tail->new(name=>$Filename, maxinterval => 1, interval => 1);
if (not defined $File) {
    die "/usr/local/bin/swatch: cannot read input \"$Filename\": $!\n";
}

LOOP: while (defined($_=$File->read)) {

    chomp;
    my $sanitized_ = $_;
    @_ = split;
    
    # quote all special shell chars
    $sanitized_ =~ s/([;&\(\)\|\^><\$`'\\])/\\$1/g;
    my @sanitized_ = split(/\s+/, $sanitized_);
    if (/INVALID|REPEATED|INCOMPLETE:LOGIN/) {
        echo('MODES' => [ "bold", ], 'MESSAGE' => "$_", );
        ring_bell('RINGS' => "3", );
        next;
    }

    if (/(panic|halt)/) {
        echo('MESSAGE' => "$_", );
        ring_bell();
        next;
    }

    if (/Regents/) {
        echo('MODES' => [ "bold", ], 'MESSAGE' => "$_", );
        ring_bell();
        next;
    }

    if (/ipfw:.*Deny ICMP:8.0/) {
        echo('MODES' => [ "bold", ], 'MESSAGE' => "$_", );
        exec_command('COMMAND' => "mpg123 -q /root/wavs/drip.wav &", );
        next;
    }

    if (/ipfw:.*Deny TCP .*:6000/) {
        echo('MODES' => [ "bold", ], 'MESSAGE' => "$_", );
        exec_command('COMMAND' => "mpg123 -q /root/wavs/camera.wav &", );
        next;
    }

    if (/ipfw:.*Deny UDP .*:513/) {
        echo('MODES' => [ "bold", ], 'MESSAGE' => "$_", );
        exec_command('COMMAND' => "mpg123 -q /root/wavs/flush.wav &", );
        next;
    }

    if (/ipfw:.*Deny TCP .*:21/) {
        echo('MODES' => [ "bold", ], 'MESSAGE' => "$_", );
        exec_command('COMMAND' => "mpg123 -q /root/wavs/vault.wav &", );
        next;
    }

    if (/PROTO=TCP .*DPT=80/) {
        echo('MODES' => [ "bold", ], 'MESSAGE' => "$_", );
        exec_command('COMMAND' => "mpg123 /root/wavs/tcp80.mp3 &", );
        next;
    }
    if (/PROTO=TCP .*DPT=23/) {
        echo('MODES' => [ "bold", ], 'MESSAGE' => "$_", );
        exec_command('COMMAND' => "mpg123 /root/wavs/tcp23.mp3 &", );
        next;
    }

    if (/UDP .*=1300007/) {
        echo('MODES' => [ "bold", ], 'MESSAGE' => "$_", );
        exec_command('COMMAND' => "mpg123 /root/wavs/udp137.mp3 &", );
        next;
    }

    if (/PROTO=ICMP/) {
        echo('MODES' => [ "bold", ], 'MESSAGE' => "$_", );
        exec_command('COMMAND' => "mpg123 /root/wavs/ping.mp3 &", );
        next;
    }

    if (/.*/) {
        echo('MESSAGE' => "$_", );
        next;
    }

}

Led Firewall (netled)

FW led box without labels

Above is a picture of a Box with leds which lightup when certain network packets are seen on the network.

It is connected to the parallel port of a PC (using port 0x3bc)

Makefile:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
CC=gcc
CCOPT=-O2 -I/usr/include/pcap
LIBS=-lpcap
all: netled
netled: netled.c
$(CC) $(CCOPT) -o netled netled.c $(LIBS)
CC=gcc CCOPT=-O2 -I/usr/include/pcap LIBS=-lpcap all: netled netled: netled.c $(CC) $(CCOPT) -o netled netled.c $(LIBS)
CC=gcc
CCOPT=-O2 -I/usr/include/pcap
LIBS=-lpcap

all:	netled

netled:	netled.c
	$(CC) $(CCOPT) -o netled netled.c $(LIBS)

netled.c code ( older version, i will upload a newer if found)

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
#include <stdio.h>
#include <pcap.h>
#include <netinet/in.h>
#include <sys/io.h>
#include <sys/time.h>
#include <signal.h>
#include "ether.h"
#include "ethertype.h"
#include "ip.h"
#include "tcp.h"
#define LP_PORT 0x3bc
#define CAPLEN 64
#define DELAY 30000
char *program_name;
static pcap_t *pd;
const u_char *snapend;
u_char leds = 0;
int mode = 0;
long packets;
void do_leds() {
mode ^= 1;
if(!leds && mode) return;
if(mode) {
outb(leds, LP_PORT);
leds = 0;
}
else {
outb(0, LP_PORT);
}
}
int do_tcp(register const u_char *bp) {
register const struct tcphdr *tp;
u_int16_t sport, dport;
tp = (struct tcphdr *)bp;
sport = ntohs(tp->th_sport);
dport = ntohs(tp->th_dport);
if (sport == 22 || dport == 22) {
leds |= 8;
}
return;
}
int do_ip(register const u_char *bp, register u_int length) {
register const struct ip *ip;
register u_int hlen, len, len0, off;
register const u_char *cp;
ip = (const struct ip *)bp;
if ((u_char *)(ip + 1) > snapend ||
length < sizeof (struct ip)) {
return;
}
hlen = IP_HL(ip) * 4;
if (hlen < sizeof (struct ip)) {
fprintf(stderr, "bad-hlen %d\n", hlen);
return;
}
len = ntohs(ip->ip_len);
if (length < len)
(void)printf("truncated-ip - %d bytes missing!",
len - length);
len -= hlen;
len0 = len;
off = ntohs(ip->ip_off);
if ((off & 0x1fff) == 0) {
cp = (const u_char *)ip + hlen;
switch(ip->ip_p) {
case IPPROTO_TCP:
// fprintf(stderr, "TCP!\n");
leds |= 128;
do_tcp(cp);
break;
case IPPROTO_UDP:
// fprintf(stderr, "UDP!\n");
leds |= 64;
break;
case IPPROTO_ICMP:
// fprintf(stderr, "ICMP!\n");
leds |= 32;
break;
default:
fprintf(stderr, "HUH? [ip_proto: %i]\n", ip->ip_p);
break;
}
}
}
void handler(u_char *user, const struct pcap_pkthdr *h, const u_char *p) {
u_int caplen = h->caplen;
u_int length = h->len;
u_short ether_type;
register const struct ether_header *ep;
u_short extracted_ethertype;
if (caplen < ETHER_HDRLEN) {
printf("c: [%d] e: [%d]\n", caplen, ETHER_HDRLEN);
return;
}
ep = (struct ether_header *)p;
ether_type = ntohs(ep->ether_type);
snapend = p + caplen;
p += ETHER_HDRLEN;
length -= ETHER_HDRLEN;
if (ether_type > ETHERMTU) {
switch (ether_type) {
case ETHERTYPE_ARP:
case ETHERTYPE_REVARP:
// leds |= 8;
// fprintf(stderr, "(R)ARP\n");
break;
case ETHERTYPE_IP:
// fprintf(stderr, "IP!\n");
do_ip(p, length);
break;
default:
fprintf(stderr, "HUH? [et: %i]\n", ether_type);
}
}
}
int main(int argc, char *argv[]) {
char *device;
char ebuf[PCAP_ERRBUF_SIZE];
register char *cp;
u_char *pcap_userdata;
void *sig_old;
struct itimerval timer_old, timer_new;
if ((cp = (char *)strrchr(argv[0], '/')) != NULL)
program_name = cp + 1;
else
program_name = argv[0];
if(ioperm(LP_PORT,3,1))
error("IOPEEEEERM!\n");
sig_old = signal(SIGALRM, do_leds);
if (sig_old == SIG_ERR)
error("SIGNAAAAAAAAAAAAAL!\n");
timer_new.it_value.tv_usec = DELAY;
timer_new.it_value.tv_sec = 0;
timer_new.it_interval.tv_usec = DELAY;
timer_new.it_interval.tv_sec = 0;
if(setitimer(ITIMER_REAL, &timer_new, &timer_old))
error("SETITIMEEEEEER!\n");
device = pcap_lookupdev(ebuf);
if (device == NULL)
error("%s", ebuf);
pd = pcap_open_live(device, CAPLEN, 1, 1000, ebuf);
if (pd == NULL)
error("%s", ebuf);
if (pcap_loop(pd, -1, handler, pcap_userdata) < 0) {
(void)fprintf(stderr, "%s: pcap_loop: %s\n",
program_name, pcap_geterr(pd));
exit(1);
}
return 0;
}
#include <stdio.h> #include <pcap.h> #include <netinet/in.h> #include <sys/io.h> #include <sys/time.h> #include <signal.h> #include "ether.h" #include "ethertype.h" #include "ip.h" #include "tcp.h" #define LP_PORT 0x3bc #define CAPLEN 64 #define DELAY 30000 char *program_name; static pcap_t *pd; const u_char *snapend; u_char leds = 0; int mode = 0; long packets; void do_leds() { mode ^= 1; if(!leds && mode) return; if(mode) { outb(leds, LP_PORT); leds = 0; } else { outb(0, LP_PORT); } } int do_tcp(register const u_char *bp) { register const struct tcphdr *tp; u_int16_t sport, dport; tp = (struct tcphdr *)bp; sport = ntohs(tp->th_sport); dport = ntohs(tp->th_dport); if (sport == 22 || dport == 22) { leds |= 8; } return; } int do_ip(register const u_char *bp, register u_int length) { register const struct ip *ip; register u_int hlen, len, len0, off; register const u_char *cp; ip = (const struct ip *)bp; if ((u_char *)(ip + 1) > snapend || length < sizeof (struct ip)) { return; } hlen = IP_HL(ip) * 4; if (hlen < sizeof (struct ip)) { fprintf(stderr, "bad-hlen %d\n", hlen); return; } len = ntohs(ip->ip_len); if (length < len) (void)printf("truncated-ip - %d bytes missing!", len - length); len -= hlen; len0 = len; off = ntohs(ip->ip_off); if ((off & 0x1fff) == 0) { cp = (const u_char *)ip + hlen; switch(ip->ip_p) { case IPPROTO_TCP: // fprintf(stderr, "TCP!\n"); leds |= 128; do_tcp(cp); break; case IPPROTO_UDP: // fprintf(stderr, "UDP!\n"); leds |= 64; break; case IPPROTO_ICMP: // fprintf(stderr, "ICMP!\n"); leds |= 32; break; default: fprintf(stderr, "HUH? [ip_proto: %i]\n", ip->ip_p); break; } } } void handler(u_char *user, const struct pcap_pkthdr *h, const u_char *p) { u_int caplen = h->caplen; u_int length = h->len; u_short ether_type; register const struct ether_header *ep; u_short extracted_ethertype; if (caplen < ETHER_HDRLEN) { printf("c: [%d] e: [%d]\n", caplen, ETHER_HDRLEN); return; } ep = (struct ether_header *)p; ether_type = ntohs(ep->ether_type); snapend = p + caplen; p += ETHER_HDRLEN; length -= ETHER_HDRLEN; if (ether_type > ETHERMTU) { switch (ether_type) { case ETHERTYPE_ARP: case ETHERTYPE_REVARP: // leds |= 8; // fprintf(stderr, "(R)ARP\n"); break; case ETHERTYPE_IP: // fprintf(stderr, "IP!\n"); do_ip(p, length); break; default: fprintf(stderr, "HUH? [et: %i]\n", ether_type); } } } int main(int argc, char *argv[]) { char *device; char ebuf[PCAP_ERRBUF_SIZE]; register char *cp; u_char *pcap_userdata; void *sig_old; struct itimerval timer_old, timer_new; if ((cp = (char *)strrchr(argv[0], '/')) != NULL) program_name = cp + 1; else program_name = argv[0]; if(ioperm(LP_PORT,3,1)) error("IOPEEEEERM!\n"); sig_old = signal(SIGALRM, do_leds); if (sig_old == SIG_ERR) error("SIGNAAAAAAAAAAAAAL!\n"); timer_new.it_value.tv_usec = DELAY; timer_new.it_value.tv_sec = 0; timer_new.it_interval.tv_usec = DELAY; timer_new.it_interval.tv_sec = 0; if(setitimer(ITIMER_REAL, &timer_new, &timer_old)) error("SETITIMEEEEEER!\n"); device = pcap_lookupdev(ebuf); if (device == NULL) error("%s", ebuf); pd = pcap_open_live(device, CAPLEN, 1, 1000, ebuf); if (pd == NULL) error("%s", ebuf); if (pcap_loop(pd, -1, handler, pcap_userdata) < 0) { (void)fprintf(stderr, "%s: pcap_loop: %s\n", program_name, pcap_geterr(pd)); exit(1); } return 0; }
#include <stdio.h>
#include <pcap.h>
#include <netinet/in.h>
#include <sys/io.h>
#include <sys/time.h>
#include <signal.h>
#include "ether.h"
#include "ethertype.h"
#include "ip.h"
#include "tcp.h"

#define LP_PORT 0x3bc
#define CAPLEN 64
#define DELAY 30000

char *program_name;
static pcap_t *pd;
const u_char *snapend;
u_char leds = 0;
int mode = 0;
long packets;

void do_leds() {
    mode ^= 1;

    if(!leds && mode) return;

    if(mode) {
	outb(leds, LP_PORT);
	leds = 0;
    }
    else {
	outb(0, LP_PORT);
    }
}

int do_tcp(register const u_char *bp) {
    register const struct tcphdr *tp;
    u_int16_t sport, dport;

    tp = (struct tcphdr *)bp;
    sport = ntohs(tp->th_sport);
    dport = ntohs(tp->th_dport);

    if (sport == 22 || dport == 22) {
	leds |= 8;
    }

    return;
}

int do_ip(register const u_char *bp, register u_int length) {
    register const struct ip *ip;
    register u_int hlen, len, len0, off;
    register const u_char *cp;

    ip = (const struct ip *)bp;

    if ((u_char *)(ip + 1) > snapend ||
	length < sizeof (struct ip)) {
	return;
    }

    hlen = IP_HL(ip) * 4;
    if (hlen < sizeof (struct ip)) {
	fprintf(stderr, "bad-hlen %d\n", hlen);
	return;
    }

    len = ntohs(ip->ip_len);
    if (length < len)
	(void)printf("truncated-ip - %d bytes missing!",
	    len - length);
    len -= hlen;
    len0 = len;


    off = ntohs(ip->ip_off);
    if ((off & 0x1fff) == 0) {
	cp = (const u_char *)ip + hlen;

	switch(ip->ip_p) {

	    case IPPROTO_TCP:
		// fprintf(stderr, "TCP!\n");
		leds |= 128;
		do_tcp(cp);
		break;

	    case IPPROTO_UDP:
		// fprintf(stderr, "UDP!\n");
		leds |= 64;
		break;

	    case IPPROTO_ICMP:
		// fprintf(stderr, "ICMP!\n");
		leds |= 32;
		break;

	    default:
		fprintf(stderr, "HUH? [ip_proto: %i]\n", ip->ip_p);
		break;
	}
    }
}

void handler(u_char *user, const struct pcap_pkthdr *h, const u_char *p) {
    u_int caplen = h->caplen;
    u_int length = h->len;
    u_short ether_type;
    register const struct ether_header *ep;
    u_short extracted_ethertype;

    if (caplen < ETHER_HDRLEN) {
	printf("c: [%d] e: [%d]\n", caplen, ETHER_HDRLEN);
	return;
    }

    ep = (struct ether_header *)p;
    ether_type = ntohs(ep->ether_type);

    snapend = p + caplen;
    p += ETHER_HDRLEN;
    length -= ETHER_HDRLEN;
    if (ether_type > ETHERMTU) {


	switch (ether_type) {

	    case ETHERTYPE_ARP:
	    case ETHERTYPE_REVARP:
		// leds |= 8;
                // fprintf(stderr, "(R)ARP\n");
		break;

	    case ETHERTYPE_IP:
		// fprintf(stderr, "IP!\n");
		do_ip(p, length);
		break;

	    default:
		fprintf(stderr, "HUH? [et: %i]\n", ether_type);

	}
    }
}

int main(int argc, char *argv[]) {
    char *device;
    char ebuf[PCAP_ERRBUF_SIZE];
    register char *cp;
    u_char *pcap_userdata;
    void *sig_old;
    struct itimerval timer_old, timer_new;

    if ((cp = (char *)strrchr(argv[0], '/')) != NULL)
	program_name = cp + 1;
    else
	program_name = argv[0];

    if(ioperm(LP_PORT,3,1))
	error("IOPEEEEERM!\n");

    sig_old = signal(SIGALRM, do_leds);
    if (sig_old == SIG_ERR)
	error("SIGNAAAAAAAAAAAAAL!\n");
    timer_new.it_value.tv_usec = DELAY;
    timer_new.it_value.tv_sec = 0;
    timer_new.it_interval.tv_usec = DELAY;
    timer_new.it_interval.tv_sec = 0;
    if(setitimer(ITIMER_REAL, &timer_new, &timer_old))
	error("SETITIMEEEEEER!\n");

    device = pcap_lookupdev(ebuf);
    if (device == NULL)
	error("%s", ebuf);

    pd = pcap_open_live(device, CAPLEN, 1, 1000, ebuf);
    if (pd == NULL)
	error("%s", ebuf);

    if (pcap_loop(pd, -1, handler, pcap_userdata) < 0) {
	(void)fprintf(stderr, "%s: pcap_loop: %s\n",
	    program_name, pcap_geterr(pd));
	exit(1);
    }

    return 0;
}

Tracking ip/access websites

I wanted to know when a certain webpage was being accessed.
Also when an archive website was being accessed.

So I used below scripts

This one checks the apache log file, using a bash script which was being run every night at 0:00

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
#!/bin/bash
: > /tmp/mail
today=$(date +%d/%b/%Y --date="yesterday")
grep -i $today /var/log/httpd/xxxxxxxx.henriaanstoot.nl-access.log | cut -f1,7 -d" " | grep /$ | grep -v feed > /tmp/today
nslookup friendofmine.nl | grep Address | tail -1 | cut -f2 -d" " > /tmp/ipcheck
nslookup myworkgateway | grep Address | tail -1 | cut -f2 -d" " >> /tmp/ipcheck
nslookup xxxx.dyndns.org | grep Address | tail -1 | cut -f2 -d" " >> /tmp/ipcheck
echo "192.168.1.99" >> /tmp/ipcheck
cat /tmp/ipcheck | while read; do
grep "$REPLY " /tmp/today >> /tmp/mail
done
cat /tmp/mail | mutt -s "ipgrabber" fash@mailserver
#!/bin/bash : > /tmp/mail today=$(date +%d/%b/%Y --date="yesterday") grep -i $today /var/log/httpd/xxxxxxxx.henriaanstoot.nl-access.log | cut -f1,7 -d" " | grep /$ | grep -v feed > /tmp/today nslookup friendofmine.nl | grep Address | tail -1 | cut -f2 -d" " > /tmp/ipcheck nslookup myworkgateway | grep Address | tail -1 | cut -f2 -d" " >> /tmp/ipcheck nslookup xxxx.dyndns.org | grep Address | tail -1 | cut -f2 -d" " >> /tmp/ipcheck echo "192.168.1.99" >> /tmp/ipcheck cat /tmp/ipcheck | while read; do grep "$REPLY " /tmp/today >> /tmp/mail done cat /tmp/mail | mutt -s "ipgrabber" fash@mailserver
#!/bin/bash
: > /tmp/mail
today=$(date +%d/%b/%Y --date="yesterday")
grep -i $today /var/log/httpd/xxxxxxxx.henriaanstoot.nl-access.log | cut -f1,7 -d" " | grep /$ | grep -v feed > /tmp/today

nslookup friendofmine.nl | grep Address | tail -1 | cut -f2 -d" " > /tmp/ipcheck
nslookup myworkgateway | grep Address | tail -1 | cut -f2 -d" " >> /tmp/ipcheck
nslookup xxxx.dyndns.org | grep Address | tail -1 | cut -f2 -d" " >> /tmp/ipcheck
echo "192.168.1.99" >> /tmp/ipcheck

cat /tmp/ipcheck | while read; do
grep "$REPLY " /tmp/today >> /tmp/mail
done
cat /tmp/mail | mutt -s "ipgrabber" fash@mailserver

The script which tracked a certain webpage realtime was using something like a pixel tracker. But it was a complete logo.

I created a cgi-bin bash script which, when called, just printed a jpg with the correct headers, and because the server was in my room, it played a soundfile over the speakers also.

Just place the following part somewhere in your webpage

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
#!/bin/sh
echo Content-type: image/jpeg
echo
cat /var/lib/httpd/htdocs/banners/logo.jpg
bwavplay /data/test.wav > /dev/null
echo ACCESS | mail 0612345678@gin.nl -s "Archive Site Accessed"
#!/bin/sh echo Content-type: image/jpeg echo cat /var/lib/httpd/htdocs/banners/logo.jpg bwavplay /data/test.wav > /dev/null echo ACCESS | mail 0612345678@gin.nl -s "Archive Site Accessed"
#!/bin/sh
echo Content-type: image/jpeg
echo
cat /var/lib/httpd/htdocs/banners/logo.jpg
bwavplay /data/test.wav > /dev/null
echo ACCESS | mail 0612345678@gin.nl -s "Archive Site Accessed"

Old hardware projects unsorted – till 2000

Will add to this page … when dates are unsure

1997-2000 somewhere – Hardware webcounter

Build a hardware webcounter (it was a thing back then) , i used below schematic. Wanted to use huge 7 segment displays but never got around it to buy the large ones.. It was easily converted to multiple segments. I think i used 4 and pulses where send via a parallel port.

Old webcounter schematic

The three (my case four) buttons are to get the counter in sync with my real counter which was a CGI script. It generated html code with took numeric images and displayed these on a page, the state was stored in a file. No numbers where send to the counter, only a pulse. So no synchronisation! Not the way to do this nowadays!

Joystick recorder

I designed a joystick movement recorder for a school project.

You could record movement, and press a button to start recording. (and starting the game) It was not really usable. Because, it needed a higher recording rate, a game which always reacted to the player in the same manner. Only made a half proof of concept.

Drawing images using lasers

For another school project i wanted to be able to draw figures using a laser. One of my teachers fixed a meetup for me with a guy attending university in Enschede. He was using lasers to scan miniscule objects using a laser in groves something resembling a longplayer record.

I wanted to use two DACs to control the movement of two mirrors.
But i’d had to take into account the speed of the movement and the weight of the mirrors, else images where distorted.

He gave me a schematic which used:
2 controllabe video disc mirrors, light split glasses and amplifier part.

Previous project with Oscilloscope drawings helped, with understanding those problems.
https://www.henriaanstoot.nl/1992/01/01/oscilloscope-graphics-using-a-amiga-bonus-vectrex/

I’ve still got the components, except for the high grade laser i lend from a friend.
But a simple laser pen should suffice

Made a webinterface for my DIY webcam

Using a steppermotor controller with two motors. A video capturing device (videoblaster) and a mini B/W camera.

  • Up/down/left/right and diagonal
    • Red double speed green single speed
  • Reset view
  • 2 Presets with save and recall
Setup with parallel cable

Written software in html and some CGI scripts.
Perl and C.

#include <asm/io.h>

# C Code for moving left

int main(int agrc,char agrv[])
{
  int i,wachten;
  int richting1[8]={0x27,0x2d,0x1c,0x0d,0x03,0x09,0x38,0x29};
  int richting2[8]={0x29,0x38,0x09,0x03,0x0d,0x1c,0x2d,0x27};
  ioperm(0x378,3,1);
  ioperm(0x37a,3,1);
  wachten=100;


for (i=0; i<=7; i=i+1)
        {
        outb(richting2[i], 0x378);
        outb(1, 0x37a);
        usleep(wachten);
        outb(0, 0x37a);
        usleep(wachten);
        outb(1, 0x37a);
        usleep(wachten);
        }

 return(0);
}
#!/usr/bin/perl
# Perl CGI script 

# Uses 204 no content trick to stay on same page
use LWP::Simple;
my $img = get ('http://10.1.0.1/cgi-bin/left.cgi');
print "Status: 204 No content\n\n";

Streaming video was done using progressive JPG push.
Later i used the capturing command in the loop below.

#!/bin/sh

# push jpg, and update after 1sec
# output mime header

echo Content-type: multipart/x-mixed-replace;boundary=--WebcamRules\n
echo
echo --WebcamRules

# create stream

while true; do
   echo Content-type: image/jpeg
   echo
   cat /var/lib/httpd/htdocs/webcam.jpg
   echo
   echo --WebcamRules

   sleep 1
done

Steppermotor card was using a parallel port.

Aluminum machined part by Joost

Old skool Home Automation & GPC

The date of this post is when we worked on GMC’s GPC, but i’ll post some other own made hardware related to domotica.

GPC Original Page: https://gpc.metro.cx/gpc/README

This DIY home automation was written by GMC in C.
Later we made little microcontroller prints, which could control/switch lights and more.

PIC16x84

We uses GPASM as assembler

One of my schematics
What is this?
=============

 This is the Global Premises Control package. It is intended to be a
complete solution to the DIY home automation. It provides you with a
daemon which will centralize all control functions, and some custom
programs for sound, remote control and things like that.
 The first steps to realizing the goal was made by Koen Martens. He wrote
the first daemon and made the first support programs. Other people got
interested and ported the GPC package to their homes. Since then it seemed
wise to coordinate development to prevent from having three different
versions of the package. It is currently under development and is far from
complete.

History
=======

 15-03-98 - The first initiative
	    With the help of Henri Aanstoot and Marco Geels the first
	    cables were mounted in the ceiling at Waalstraat 136. This
            involved re-dedicating some high voltage lines for the low 
	    voltage used by GPC equipment.
	    The next few days Koen Martens spend his time writing software
	    to switch on the lights (which was not possible without
	    software anymore :). This software was very rudimentry and 
	    did not feauture the daemon yet.
 28-03-98   Version 1.0 was born.
	    The need for a global way to control the premises arose, and
	    Koen Martens decided to write a daemon which would control the
	    input and output lines, with support programs for the logic.
	    This resulted in global, the gpc daemon. 
	    Running on different servers there were programs to control
	    lights and lightswitches (light_control), sound (sound) and
	    the alarm clock (wakeup). 
 10-06-98   Version 2.0 (r0.2.0) was born. 
	    The support programs containing any logic had vanished,
	    instead the daemon had all the logic encoded in it.    
 03-07-98   Version 2.0 still.
	    - Added remote control receiver code.
 29-11-98   GPC r0.3.0
	    - Started coordinated development
 11-12-98   GPC r0.3.1
	    - Security support included, providing a (basic) interface
	      for protecting variables with passwords on a security level 
	      clearance basis.
	    - Global notify protocol added, clients can now register one
	      or more variables. This makes the old (0.3.0) polling method
	      obsolete thus reducing the network load dramatically.
	    - Logging library added.

Development
===========

 The development is done on the following beta sites:

 - Subnet
	Location	: Waalstraat 136, Enschede, Netherlands
	Site coordinator: Koen Martens AKA gmc (gmc@freemail.nl)
	Site description: Single floor appartment
			  3 occupants (1 human, 2 rats)
			  P60 32MB RAM running linux
			  486 8MB RAM running FreeBSD
			  486 8MB RAM running linux
			  DEC Writer
			  WYSE terminal
			  The 486 linux machine has the daemon, and is 
			  hooked up to the premises.
			  The P60 has a sound card and a RC receiver.
 - Lip-on-ice
	Location	: Lipperkerkstraat 321, Enschede, Netherlands
	Site coordinator: Willem-Jan Faber AKA aloha AKA xtz ( And Henri Aanstoot AKA Fash)
			  (w-jfaber@freemail.nl)
	Site description: Three floor house
			  Four occupants (3 male, 1 female)
			  Connected to three other premises.
			  Computer list not yet in!
			  
 - Venom
	Location	: P. Mondriaanstraat ??, Almelo, Netherlands
	Site coordinator: Sebastiaan Smit AKA venom (wssmit@freemail.nl)
	Site description: Three floor house
			  Three occupants
			  4 computers

 If you would like to join the development, mail me at gmc@freemail.nl.


In progress
===========

 The following projects are in progress right now:
	- A script language to describe the control logic for the daemon
		Koen Martens
	- An cgi interface for the http connectivity
	- Support for sharing variables on multiple daemons

Usage
=====

 Use is for your own risk. We can not be held responsible for any damage
resulted from running any of this software.
 Keeping that in mind, usage is very simple but work needs to be done on
the documentation :)

DIY door sensor using a bend CDROM and a sensor i got

I’d would send a signal to our computers and playing a sound sample on our sound system. Also a IRCbot named (lampje) would mention “Backdoor open” in our own channel. (We where running our own IRC servers, interconnected .. because we can. A average of 3 Clients per server sound the way to go .. LOL )
Lampje the IRCbot also controlled the livingroom light and more.

ICH Meeting

Internet Club Hengelo ..

Later we started Intranet Club Enschede, which was the birth of Icecrew.

Some explained website building, browsing the net, and tools to use.

Bigred and me build the network, and services which where used for demonstrations.
We also helped with solving network related problems.

Interview Radio Oost

Above was done with my little DIY streaming webcam.
(progressive push jpg cgi script, see other post)

I found some text/log about this day
(found a scanned item first, then i used namazu .. i love namazu, it found the original ascii text file.
(Dutch only)

Zaterdag 20 September 1997
--------------------------

's ochtens om 8 uur wakker gemaakt door Marco.
Ik was nog een beetje ziek, maar toch maar de 2 pc's ingepakt.
(die van Miko en die van mij)
Ook Marco z'n pc met cd-brander stond al in de auto.
Omdat het een kleine opel kadett was moesten we behoorlijk proppen.
Ondertussen had ik al overgegeven maar ik kon moeilijk thuisblijven want ik moest het netwerk voor die dag nog aan de praat zien te krijgen.
Na een 'bumpy ride' in de Kadett waren we eindelijk op de plaats van bestemming.

Hier aangekomen bleek dat waar we de pc's neer moesten zetten, toch verder van de ISDN-aansluiting was als verwacht.
Moest ik nu mijn pc (welke als proxy-server/firewall moest werken) nu in dit kantoortje staan en dan een coax naar de rest van de pc's of moesten we voor een lang ISDN kabel zorgen?
Omdat de Webcam aan mijn pc zat moesten we eigenlijk een langere ISDN kabel hebben.
(Het was ook nog een probleem met de ISDN aansluitingen omdat de beide aansluitingen die de PTT had aangelegd al bezet waren i.v.m. de telefoonaansluitingen)
Nadat we 1 van de aansluitingen eruit hadden getrokken bleek dat he helft van de telefoons in het gebouw niet meer werken.

Na bij de PTT kabel's te hebben gekocht (1x 10 meter en 1x 25 meter plus en tussenstukje 62 gulden nogwat)
Kon ik eindelijk beginnen met het opzetten van de proxy server.

(Ondertussen nog even iemand van een netwerk-kaart voorzien en andere problemen opgelost)
Ook de netwerk instellingen moesten marco en ik bij iedereen behalve Miko en mijzelf veranderen.
(Komt er ook nog 1 zeuren over Office enzo)

Na wat aanpassingen werkte de proxy-server en de webcam.
Ook de http-server op Miko's pc werkte tegelijkertijd.

We werden ook nog geinterviewed door radio-oost ofzo. Dit wilden we tegelijkertijd via de webcam op internet laten zien, maar dat kon niet want die radio-meneer moest
zijn microfoon via de telefoon laten werken om rechtstreeks in de uitzending te komen.
Dus de proxy-server maar even uitgezet en het interview als avi opgenomen.

Later nog een website gemaakt met wat foto's van die dag erop.

Voor de volgende keer moet ik wel zorgen dat ik ook Irc en Mail via de proxy kan laten werken.

Op de terugweg nog een paar keer problemen gehad met de auto, deze viel zomaar uit.
Na met een startkabel tegen de stuurkolom de auto weer aan 't starten te hebben gekregen.
Liet marco de startkabel maar tussen de deur van de auto, zo kon hij nog een paar keer de auto simpel starten door de startkabel (welke van onder de moterkap kwam) tegen de stuurkolom te houden.
Website with pictures, avi part probably contained the streaming webcam part