The following patch mainly adds a set of test case to verify that
several spoofing attacks are prevented by the nwfilter subsystem.
In order to have a well defined test machine, the patch also includes
test scripts to network install a virtual disk from scratch, to boot the
virtual test machine prior to running the actual test scripts and to
shut it down afterwards.
While I have tried to remove as much dependency on my local setup as
possible there is still some left, so I am currently more interested in
feedback about the general approach, not necessarily actual inclusion
into the libvirt-TCK git.
For example, I am currently trying to find a suitable location for the
kickstart file, and also a suitable place for the common_functions.pl.
Comments are appreciated ... thanks,
Gerhard
Index: libvirt-tck/scripts/network/README
===================================================================
--- /dev/null
+++ libvirt-tck/scripts/network/README
@@ -0,0 +1,14 @@
+
+Test cases:
+
+000-install-image.t creates and install a 2GB fedora virtual disk via
kickstart file from the network
+001-boot-image.t defines and boots a VM which uses the fedora virtual
disk
+100-ping-still-working.t verifies the VM is pingable
+210-no-mac-spoofing.t verifies mac spoofing is prevented
+220-no-ip-spoofing.t verifies ip spoofing is prevented
+230-no-mac-broadcast.t verifies mac broadcasting is prevented
+240-no-arp-spoofing.t verifies arp spoofing is prevented
+999-shutdown-image.t shuts the VM down
+
+
+
Index: libvirt-tck/scripts/network/000-install-image.t
===================================================================
--- /dev/null
+++ libvirt-tck/scripts/network/000-install-image.t
@@ -0,0 +1,181 @@
+# -*- perl -*-
+#
+# Copyright (C) 2010 IBM Corp.
+#
+# This program is free software; You can redistribute it and/or modify
+# it under the GNU General Public License as published by the Free
+# Software Foundation; either version 2, or (at your option) any
+# later version
+#
+# The file "LICENSE" distributed along with this file provides full
+# details of the terms and conditions
+#
+
+=pod
+
+=head1 NAME
+
+network/000-install-image.t - install network test image
+
+=head1 DESCRIPTION
+
+The test case creates and install a 2GB fedora virtual
+disk via kickstart file from the network.
+
+=cut
+
+use strict;
+use warnings;
+
+use Test::More tests => 1;
+
+use Sys::Virt::TCK;
+
+my $tck = Sys::Virt::TCK->new();
+my $conn = eval { $tck->setup(); };
+BAIL_OUT "failed to setup test harness: $@" if $@;
+END { $tck->cleanup if $tck; }
+
+# variables which may need to be adapted
+my $domain_name ="f12nwtest";
+my $disk_name = "/var/lib/libvirt/images/${domain_name}.img";
+my $disk_size = "2147483648";
+
+my $kickstart_file ="http://192.168.122.1/ks.cfg";
+my $cmdline = "ip=dhcp gateway=192.168.122.1 ks=${kickstart_file}";
+
+# see if the domain already exits
+my $already_defined = 0;
+diag "searching if ${domain_name} is already defined";
+my $nnames = $conn->num_of_defined_domains();
+my @names = $conn->list_defined_domain_names($nnames);
+foreach (@names){
+ if (/${domain_name}/) {
+ print "$_ already exists, no need to redefine\n";
+ $already_defined = 1;
+ }
+}
+diag $already_defined;
+
+# check for installation disk and build it if not exists
+my $already_installed = 0;
+my $pool = $conn->get_storage_pool_by_name("default");
+my $nnames = $pool->num_of_storage_volumes();
+my @volNames = $pool->list_storage_vol_names($nnames);
+foreach (@volNames){
+ if (/${domain_name}/) {
+ print "$_ already exists, no need to install\n";
+ $already_installed = 1;
+ }
+}
+
+my $volumexml = "<volume>".
+" <name>${domain_name}.img</name>".
+" <key>${disk_name}</key>".
+" <source>".
+" </source>".
+" <capacity>${disk_size}</capacity>".
+" <allocation>4096</allocation>".
+" <target>".
+" <path>${disk_name}</path>".
+" <format type='raw'/>".
+" <permissions>".
+" <mode>0644</mode>".
+" <owner>0</owner>".
+" <group>0</group>".
+" </permissions>".
+" </target>".
+"</volume>";
+
+
+# prepare image
+if ($already_installed == 0) {
+ diag "Creating ${disk_name}";
+ diag $volumexml;
+ my $vol = $pool->create_volume($volumexml)
+# system("qemu-img create ${disk_name} ${disk_size}");
+}
+
+my $topxml = " <name>${domain_name}</name>".
+" <memory>524288</memory>".
+" <currentMemory>524288</currentMemory>".
+" <vcpu>1</vcpu>";
+
+my $osxml = " <os>".
+" <type arch='x86_64'
machine='fedora-13'>hvm</type>".
+" <kernel>/var/cache/libvirt-tck/os-i686-hvm/vmlinuz</kernel>".
+" <initrd>/var/cache/libvirt-tck/os-i686-hvm/initrd</initrd>".
+" <cmdline>${cmdline}</cmdline>".
+" <boot dev='hd'/>".
+" </os>";
+
+my $bottomxml = " <features>".
+" <acpi/>".
+" <apic/>".
+" </features>".
+" <clock offset='utc'/>".
+" <on_poweroff>destroy</on_poweroff>".
+" <on_reboot>restart</on_reboot>".
+" <on_crash>restart</on_crash>".
+" <devices>".
+" <emulator>/usr/bin/qemu-kvm</emulator>".
+" <disk type='file' device='disk'>".
+" <driver name='qemu' type='raw'/>".
+" <source file='${disk_name}'/>".
+" <target dev='hda' bus='ide'/>".
+" </disk>".
+" <controller type='ide' index='0'>".
+" </controller>".
+" <interface type='network'>".
+" <source network='default'/>".
+" <target dev='vnet0'/>".
+" <model type='virtio'/>".
+" </interface>".
+" <serial type='pty'>".
+" <target port='0'/>".
+" </serial>".
+" <console type='pty'>".
+" <target port='0'/>".
+" </console>".
+" <graphics type='vnc' port='-1' autoport='yes'
listen='127.0.0.1'
keymap='de'/>".
+" <video>".
+" <model type='cirrus' vram='9216'
heads='1'/>".
+" </video>".
+" </devices>";
+
+my $xml = "<domain type='kvm'>" .
+$topxml.
+$osxml.
+$bottomxml.
+"</domain>";
+
+diag $xml;
+diag "Defining an inactive domain config";
+my $dom;
+
+# no need to start if already installed
+if (($already_installed == 0) && ($already_defined == 0)) {
+ ok_domain(sub { $dom = $conn->define_domain($xml) }, "defined
persistent domain config");
+ $xml = $dom->get_xml_description;
+ diag $xml;
+ diag "Starting inactive domain config";
+ $dom->create;
+
+ # wait for completion of installation
+ diag "wait for installation to finish .. ";
+ while($dom->is_active()) {
+ sleep(10);
+ diag ".. to view progress connect to virtual machine ${domain_name} ..
";
+ }
+ sleep(10);
+ diag " .. done";
+ # cleanup
+ $dom->undefine;
+} else {
+ ok_domain { $dom = $conn->get_domain_by_name($domain_name) } "the
existing domain object";
+}
+
+
+
+
+
Index: libvirt-tck/scripts/network/001-boot-image.t
===================================================================
--- /dev/null
+++ libvirt-tck/scripts/network/001-boot-image.t
@@ -0,0 +1,133 @@
+# -*- perl -*-
+#
+# Copyright (C) 2010 IBM Corp.
+#
+# This program is free software; You can redistribute it and/or modify
+# it under the GNU General Public License as published by the Free
+# Software Foundation; either version 2, or (at your option) any
+# later version
+#
+# The file "LICENSE" distributed along with this file provides full
+# details of the terms and conditions
+#
+
+=pod
+
+=head1 NAME
+
+network/001-boot-image.t - boot installed test image
+
+=head1 DESCRIPTION
+
+The test case defines and boots a VM which uses the
+fedora virtual disk create ny 000-install-image
+
+=cut
+
+use strict;
+use warnings;
+
+use Test::More tests => 2;
+
+use Sys::Virt::TCK;
+use XML::LibXML;
+
+require 'scripts/network/common_functions.pl';
+
+my $tck = Sys::Virt::TCK->new();
+my $conn = eval { $tck->setup(); };
+BAIL_OUT "failed to setup test harness: $@" if $@;
+END { $tck->cleanup if $tck; }
+
+my $already_defined = 0;
+my $domain_name ="f12nwtest";
+
+# see if the domain already exits
+diag "searching if ${domain_name} is already defined";
+my $nnames = $conn->num_of_defined_domains();
+my @names = $conn->list_defined_domain_names($nnames);
+foreach (@names){
+ if (/${domain_name}/) {
+ print "$_ already exists, no need to redefine\n";
+ $already_defined = 1;
+ }
+}
+diag $already_defined;
+
+my $dom;
+my $xml;
+
+if ($already_defined == 1) {
+ ok_domain { $dom = $conn->get_domain_by_name($domain_name) } "the
existing domain object";
+} else {
+ my $topxml = " <name>${domain_name}</name>".
+ " <memory>524288</memory>".
+ " <currentMemory>524288</currentMemory>".
+ " <vcpu>1</vcpu>";
+
+ my $osxml = " <os>".
+ " <type arch='x86_64'
machine='fedora-13'>hvm</type>".
+ " <boot dev='hd'/>".
+ " </os>";
+
+ my $bottomxml = " <features>".
+ " <acpi/>".
+ " <apic/>".
+ " </features>".
+ " <clock offset='utc'/>".
+ " <on_poweroff>destroy</on_poweroff>".
+ " <on_reboot>restart</on_reboot>".
+ " <on_crash>restart</on_crash>".
+ " <devices>".
+ " <emulator>/usr/bin/qemu-kvm</emulator>".
+ " <disk type='file' device='disk'>".
+ " <driver name='qemu' type='raw'/>".
+ " <source
file='/var/lib/libvirt/images/${domain_name}.img'/>".
+ " <target dev='hda' bus='ide'/>".
+ " </disk>".
+ " <controller type='ide' index='0'>".
+ " </controller>".
+ " <interface type='network'>".
+ " <source network='default'/>".
+ " <filterref filter='no-spoofing'/>".
+ " <target dev='vnet0'/>".
+ " <model type='virtio'/>".
+ " </interface>".
+ " <serial type='pty'>".
+ " <target port='0'/>".
+ " </serial>".
+ " <console type='pty'>".
+ " <target port='0'/>".
+ " </console>".
+ " <graphics type='vnc' port='-1' autoport='yes'
listen='127.0.0.1'
keymap='de'/>".
+ " <video>".
+ " <model type='cirrus' vram='9216'
heads='1'/>".
+ " </video>".
+ " </devices>";
+
+ $xml = "<domain type='kvm'>" .
+ $topxml.
+ $osxml.
+ $bottomxml.
+ "</domain>";
+
+ diag $xml;
+ diag "Defining an inactive domain config";
+ ok_domain(sub { $dom = $conn->define_domain($xml) }, "defined
persistent domain config");
+}
+
+# already existing or newly defined, start it up
+$dom->create;
+my $uuid = $dom->get_uuid_string();
+diag $uuid;
+$xml = $dom->get_xml_description();
+diag $xml;
+ok($dom->get_id() > 0, "running domain has an ID > 0");
+
+my $mac = get_macaddress($xml);
+diag $mac;
+# wait for guest to boot and request dhcp
+sleep(20);
+my $ip = get_ip_from_leases($mac);
+diag "ip is $ip";
+
Index: libvirt-tck/scripts/network/100-ping-still-working.t
===================================================================
--- /dev/null
+++ libvirt-tck/scripts/network/100-ping-still-working.t
@@ -0,0 +1,71 @@
+# -*- perl -*-
+#
+# Copyright (C) 2010 IBM Corp.
+#
+# This program is free software; You can redistribute it and/or modify
+# it under the GNU General Public License as published by the Free
+# Software Foundation; either version 2, or (at your option) any
+# later version
+#
+# The file "LICENSE" distributed along with this file provides full
+# details of the terms and conditions
+#
+
+=pod
+
+=head1 NAME
+
+network/100-ping-still-working.t - verify machines can be pinged from
host
+
+=head1 DESCRIPTION
+
+The test case validates that it is possible to ping a guest machine
from
+the host.
+
+=cut
+
+use strict;
+use warnings;
+
+use Test::More tests => 4;
+
+use Sys::Virt::TCK;
+use Test::Exception;
+use Net::SSH::Perl;
+use XML::LibXML;
+
+require 'scripts/network/common_functions.pl';
+
+my $tck = Sys::Virt::TCK->new();
+my $conn = eval { $tck->setup(); };
+BAIL_OUT "failed to setup test harness: $@" if $@;
+END {
+ $tck->cleanup if $tck;
+}
+
+# create first domain and start it
+diag "Trying domain lookup by name";
+my $dom1;
+my $domain_name ="f12nwtest";
+
+ok_domain { $dom1 = $conn->get_domain_by_name($domain_name) } "the
running domain object";
+my $xml = $dom1->get_xml_description;
+diag $xml;
+ok($dom1->get_id() > 0, "running domain has an ID > 0");
+my $mac1 = get_macaddress($xml);
+diag $mac1;
+my $guestip1 = get_ip_from_leases($mac1);
+diag "ip is $guestip1";
+
+# check ebtables entry
+my $ebtable1 = `/sbin/ebtables -L;/sbin/ebtables -t nat -L`;
+diag $ebtable1;
+# fixme to include mac adress
+ok($ebtable1 =~ "vnet0", "check ebtables entry");
+
+# ping guest1
+my $ping1 = `ping -c 10 $guestip1`;
+diag $ping1;
+ok($ping1 =~ "10 received", "ping $guestip1 test");
+
+exit 0;
Index: libvirt-tck/scripts/network/210-no-mac-spoofing.t
===================================================================
--- /dev/null
+++ libvirt-tck/scripts/network/210-no-mac-spoofing.t
@@ -0,0 +1,113 @@
+# -*- perl -*-
+#
+# Copyright (C) 2010 IBM Corp.
+#
+# This program is free software; You can redistribute it and/or modify
+# it under the GNU General Public License as published by the Free
+# Software Foundation; either version 2, or (at your option) any
+# later version
+#
+# The file "LICENSE" distributed along with this file provides full
+# details of the terms and conditions
+#
+
+=pod
+
+=head1 NAME
+
+network/210-no-mac-spoofing.t - verify MAC spoofing is prevented
+
+=head1 DESCRIPTION
+
+The test case validates that MAC spoofing is prevented
+
+=cut
+
+use strict;
+use warnings;
+
+use Test::More tests => 5;
+
+use Sys::Virt::TCK;
+use Test::Exception;
+use Net::SSH::Perl;
+use XML::LibXML;
+
+require 'scripts/network/common_functions.pl';
+
+my $tck = Sys::Virt::TCK->new();
+my $conn = eval { $tck->setup(); };
+BAIL_OUT "failed to setup test harness: $@" if $@;
+END {
+ $tck->cleanup if $tck;
+}
+
+# create first domain and start it
+diag "Trying domain lookup by name";
+my $domain_name ="f12nwtest";
+my $dom1;
+ok_domain { $dom1 = $conn->get_domain_by_name($domain_name) } "the
running domain object";
+ok($dom1->get_id() > 0, "running domain has an ID > 0");
+my $xml = $dom1->get_xml_description;
+diag $xml;
+
+# check ebtables entry
+my $ebtable1 = `/sbin/ebtables -L;/sbin/ebtables -t nat -L`;
+diag $ebtable1;
+# fixme to include mac adress
+ok($ebtable1 =~ "vnet0", "check ebtables entry");
+
+# wait for guest to boot
+diag "waiting for guests to boot";
+#system("sleep 20");
+diag "done";
+
+# ping guest1 first nic
+my $mac1 = get_macaddress($xml);
+diag "$mac1";
+my $guestip1 = get_ip_from_leases($mac1);
+diag "ip is $guestip1";
+my $gateway = "192.168.122.1";
+my $macfalse = "52:54:00:f9:21:22";
+my $ping1 = `ping -c 10 $guestip1`;
+diag $ping1;
+ok($ping1 =~ "10 received", "ping $guestip1 test");
+
+# log into guest
+my $ssh = Net::SSH::Perl->new($guestip1);
+$ssh->login("root", "foobar");
+
+# now bring eth0 down, change MAC and bring it up again
+diag "fiddling with mac";
+my $cmdfile = "echo '" .
+ "/sbin/ifconfig eth0\n".
+ "/sbin/ifconfig eth0 down\n".
+ "/sbin/ifconfig eth0 hw ether ${macfalse}\n".
+ "/sbin/ifconfig eth0 up\n".
+ "/sbin/ifconfig eth0\n".
+ "ping -c 10 ${gateway}\n".
+ "/sbin/ifconfig eth0 down\n".
+ "/sbin/ifconfig eth0 hw ether ${mac1}\n".
+ "/sbin/ifconfig eth0 up\n".
+ "/sbin/ifconfig eth0\n".
+ "' > /test.sh";
+diag $cmdfile;
+my ($stdout, $stderr, $exit) = $ssh->cmd($cmdfile);
+diag $stdout;
+diag $stderr;
+diag $exit;
+($stdout, $stderr, $exit) = $ssh->cmd("chmod +x /test.sh");
+diag $stdout;
+diag $stderr;
+diag $exit;
+($stdout, $stderr, $exit) = $ssh->cmd("/test.sh > /test.log");
+diag $stdout;
+diag $stderr;
+diag $exit;
+($stdout, $stderr, $exit) = $ssh->cmd("cat /test.log");
+diag $stdout;
+diag $stderr;
+diag $exit;
+ok($stdout =~ "100% packet loss", "packet loss expected");
+
+exit 0;
Index: libvirt-tck/scripts/network/230-no-mac-broadcast.t
===================================================================
--- /dev/null
+++ libvirt-tck/scripts/network/230-no-mac-broadcast.t
@@ -0,0 +1,102 @@
+# -*- perl -*-
+#
+# Copyright (C) 2010 IBM Corp.
+#
+# This program is free software; You can redistribute it and/or modify
+# it under the GNU General Public License as published by the Free
+# Software Foundation; either version 2, or (at your option) any
+# later version
+#
+# The file "LICENSE" distributed along with this file provides full
+# details of the terms and conditions
+#
+
+=pod
+
+=head1 NAME
+
+network/230-no-mac-broadcast.t - verify MAC broadcasts are prevented
+
+=head1 DESCRIPTION
+
+The test case validates that MAC broadcasts are prevented
+
+=cut
+
+use strict;
+use warnings;
+
+use Test::More tests => 4;
+
+use Sys::Virt::TCK;
+use Test::Exception;
+use Net::SSH::Perl;
+use XML::LibXML;
+
+require 'scripts/network/common_functions.pl';
+
+my $tck = Sys::Virt::TCK->new();
+my $conn = eval { $tck->setup(); };
+BAIL_OUT "failed to setup test harness: $@" if $@;
+END {
+ $tck->cleanup if $tck;
+}
+
+# create first domain and start it
+diag "Trying domain lookup by name";
+my $dom1;
+ok_domain { $dom1 = $conn->get_domain_by_name("f12nwtest") } "the
running domain object";
+
+ok($dom1->get_id() > 0, "running domain has an ID > 0");
+my $xml = $dom1->get_xml_description;
+diag $xml;
+my $mac1 = get_macaddress($xml);
+diag "$mac1";
+my $guestip1 = get_ip_from_leases($mac1);
+diag "ip is $guestip1";
+
+# check ebtables entry
+my $ebtable1 = `/sbin/ebtables -L;/sbin/ebtables -t nat -L`;
+diag $ebtable1;
+# fixme to include mac adress
+ok($ebtable1 =~ "vnet0", "check ebtables entry");
+
+# prepare tcpdump
+diag "prepare tcpdump";
+system("/usr/sbin/tcpdump -v -i virbr0 -n host 255.255.255.255
2> /tmp/tcpdump.log &");
+
+# log into guest
+my $ssh = Net::SSH::Perl->new($guestip1);
+$ssh->login("root", "foobar");
+
+# now generate a mac broadcast paket
+diag "generate mac broadcast";
+my $cmdfile = "echo '" .
+ "/bin/ping -c 1 192.168.122.255 -b\n".
+ "' > /test.sh";
+diag $cmdfile;
+my ($stdout, $stderr, $exit) = $ssh->cmd($cmdfile);
+diag $stdout;
+diag $stderr;
+diag $exit;
+($stdout, $stderr, $exit) = $ssh->cmd("chmod +x /test.sh");
+diag $stdout;
+diag $stderr;
+diag $exit;
+($stdout, $stderr, $exit) = $ssh->cmd("/test.sh > /test.log");
+diag $stdout;
+diag $stderr;
+diag $exit;
+($stdout, $stderr, $exit) = $ssh->cmd("cat /test.log");
+diag $stdout;
+diag $stderr;
+diag $exit;
+
+# now stop tcpdump and verify result
+diag "stopping tcpdump";
+system("kill -15 `/sbin/pidof tcpdump`");
+my $tcpdumplog = `cat /tmp/tcpdump.log`;
+diag($tcpdumplog);
+ok($tcpdumplog =~ "0 packets captured", "tcpdump expected to capture no
packets");
+
+exit 0;
Index: libvirt-tck/scripts/network/240-no-arp-spoofing.t
===================================================================
--- /dev/null
+++ libvirt-tck/scripts/network/240-no-arp-spoofing.t
@@ -0,0 +1,111 @@
+# -*- perl -*-
+#
+# Copyright (C) 2010 IBM Corp.
+#
+# This program is free software; You can redistribute it and/or modify
+# it under the GNU General Public License as published by the Free
+# Software Foundation; either version 2, or (at your option) any
+# later version
+#
+# The file "LICENSE" distributed along with this file provides full
+# details of the terms and conditions
+#
+
+=pod
+
+=head1 NAME
+
+network/240-no-arp-spoofing.t - verify ARP spoofing is prevented
+
+=head1 DESCRIPTION
+
+The test case validates that ARP spoofing is prevented
+
+=cut
+
+use strict;
+use warnings;
+
+use Test::More tests => 4;
+
+use Sys::Virt::TCK;
+use Test::Exception;
+use Net::SSH::Perl;
+use XML::LibXML;
+
+require 'scripts/network/common_functions.pl';
+
+my $spoofid = "192.168.122.183";
+
+my $tck = Sys::Virt::TCK->new();
+my $conn = eval { $tck->setup(); };
+BAIL_OUT "failed to setup test harness: $@" if $@;
+END {
+ $tck->cleanup if $tck;
+}
+
+# looking up domain
+diag "Trying domain lookup by name";
+my $dom1;
+my $domain_name ="f12nwtest";
+ok_domain { $dom1 = $conn->get_domain_by_name($domain_name) } "the
running domain object";
+ok($dom1->get_id() > 0, "running domain has an ID > 0");
+my $xml = $dom1->get_xml_description;
+diag $xml;
+my $mac1 = get_macaddress($xml);
+diag "$mac1";
+my $guestip1 = get_ip_from_leases($mac1);
+diag "ip is $guestip1";
+
+# check ebtables entry
+my $ebtable1 = `/sbin/ebtables -L;/sbin/ebtables -t nat -L`;
+diag $ebtable1;
+# check if mac address is listed
+ok($ebtable1 =~ "$guestip1", "check ebtables entry");
+
+# prepare tcpdump
+diag "prepare tcpdump";
+system("/usr/sbin/tcpdump -v -i virbr0 not ip > /tmp/tcpdump.log &");
+
+# log into guest
+my $ssh = Net::SSH::Perl->new($guestip1);
+$ssh->login("root", "foobar");
+
+# now generate a arp spoofing packets
+diag "generate arpspoof";
+my $cmdfile = "echo '" .
+ "/usr/bin/yum -y install dsniff\n".
+ "/usr/sbin/arpspoof ${spoofid} &\n".
+ "/bin/sleep 10\n".
+ "kill -15 `/sbin/pidof arpspoof`\n".
+ "' > /test.sh";
+diag "content of cmdfile:";
+diag $cmdfile;
+diag "creating cmdfile";
+my ($stdout, $stderr, $exit) = $ssh->cmd($cmdfile);
+diag $stdout;
+diag $stderr;
+diag $exit;
+($stdout, $stderr, $exit) = $ssh->cmd("chmod +x /test.sh");
+diag $stdout;
+diag $stderr;
+diag $exit;
+diag "excuting cmdfile";
+($stdout, $stderr, $exit) = $ssh->cmd("/test.sh > /test.log");
+diag $stdout;
+diag $stderr;
+diag $exit;
+($stdout, $stderr, $exit) = $ssh->cmd("echo test.log\ncat /test.log");
+diag $stdout;
+diag $stderr;
+diag $exit;
+
+# now stop tcpdump and verify result
+diag "stopping tcpdump";
+system("kill -15 `/sbin/pidof tcpdump`");
+diag "tcpdump.log:";
+my $tcpdumplog = `cat /tmp/tcpdump.log`;
+diag($tcpdumplog);
+ok($tcpdumplog !~ "${spoofid} is-at", "tcpdump expected to capture no
arp reply packets");
+
+exit 0;
Index: libvirt-tck/scripts/network/220-no-ip-spoofing.t
===================================================================
--- /dev/null
+++ libvirt-tck/scripts/network/220-no-ip-spoofing.t
@@ -0,0 +1,101 @@
+# -*- perl -*-
+#
+# Copyright (C) 2010 IBM Corp.
+#
+# This program is free software; You can redistribute it and/or modify
+# it under the GNU General Public License as published by the Free
+# Software Foundation; either version 2, or (at your option) any
+# later version
+#
+# The file "LICENSE" distributed along with this file provides full
+# details of the terms and conditions
+#
+
+=pod
+
+=head1 NAME
+
+network/220-no-ip-spoofing.t - verify IP spoofing is prevented
+
+=head1 DESCRIPTION
+
+The test case validates that IP spoofing is prevented
+
+=cut
+
+use strict;
+use warnings;
+
+use Test::More tests => 4;
+
+use Sys::Virt::TCK;
+use Test::Exception;
+use Net::SSH::Perl;
+use XML::LibXML;
+
+require 'scripts/network/common_functions.pl';
+
+my $tck = Sys::Virt::TCK->new();
+my $conn = eval { $tck->setup(); };
+BAIL_OUT "failed to setup test harness: $@" if $@;
+END {
+ $tck->cleanup if $tck;
+}
+
+# looking up domain
+diag "Trying domain lookup by name";
+my $dom1;
+my $domain_name ="f12nwtest";
+
+ok_domain { $dom1 = $conn->get_domain_by_name($domain_name) } "the
running domain object";
+ok($dom1->get_id() > 0, "running domain has an ID > 0");
+my $xml = $dom1->get_xml_description;
+diag $xml;
+my $mac1 = get_macaddress($xml);
+diag "$mac1";
+my $guestip1 = get_ip_from_leases($mac1);
+diag "ip is $guestip1";
+
+# check ebtables entry
+my $ebtable1 = `/sbin/ebtables -L;/sbin/ebtables -t nat -L`;
+diag $ebtable1;
+# check if IP address is listed
+ok($ebtable1 =~ "$guestip1", "check ebtables entry");
+
+# log into guest
+my $ssh = Net::SSH::Perl->new($guestip1);
+$ssh->login("root", "foobar");
+
+# now bring eth0 down, change IP and bring it up again
+diag "preparing ip spoof";
+my $cmdfile = "echo '" .
+ "/bin/sleep 1\n".
+ "/sbin/ifconfig eth0\n".
+ "/sbin/ifconfig eth0 down\n".
+ "/sbin/ifconfig eth0 192.168.122.183 netmask 255.255.255.0 up\n".
+ "/sbin/ifconfig eth0\n".
+ "/bin/sleep 1\n".
+ "/bin/ping -c 1 192.168.122.1\n".
+ "/sbin/ifconfig eth0 down\n".
+ "/sbin/ifconfig eth0 ${guestip1} netmask 255.255.255.0 up\n".
+ "/sbin/ifconfig eth0 \n".
+ "/bin/sleep 1\n".
+ "' > /test.sh";
+diag $cmdfile;
+my ($stdout, $stderr, $exit) = $ssh->cmd($cmdfile);
+diag $stdout;
+diag $stderr;
+diag $exit;
+($stdout, $stderr, $exit) = $ssh->cmd("chmod +x /test.sh");
+diag $stdout;
+diag $stderr;
+diag $exit;
+diag "running ip spoof";
+($stdout, $stderr, $exit) = $ssh->cmd("/test.sh");
+diag $stdout;
+diag $stderr;
+diag $exit;
+diag "checking result";
+ok($stdout =~ "100% packet loss", "packet loss expected");
+
+exit 0;
Index: libvirt-tck/scripts/network/999-shutdown-image.t
===================================================================
--- /dev/null
+++ libvirt-tck/scripts/network/999-shutdown-image.t
@@ -0,0 +1,59 @@
+# -*- perl -*-
+#
+# Copyright (C) 2010 IBM Corp.
+#
+# This program is free software; You can redistribute it and/or modify
+# it under the GNU General Public License as published by the Free
+# Software Foundation; either version 2, or (at your option) any
+# later version
+#
+# The file "LICENSE" distributed along with this file provides full
+# details of the terms and conditions
+#
+
+=pod
+
+=head1 NAME
+
+network/240-no-arp-spoofing.t - verify ARP spoofing is prevented
+
+=head1 DESCRIPTION
+
+The test case validates that ARP spoofing is prevented
+
+=cut
+
+use strict;
+use warnings;
+
+use Test::More tests => 2;
+
+use Sys::Virt::TCK;
+use Test::Exception;
+use Net::SSH::Perl;
+
+
+my $tck = Sys::Virt::TCK->new();
+my $conn = eval { $tck->setup(); };
+BAIL_OUT "failed to setup test harness: $@" if $@;
+END {
+ $tck->cleanup if $tck;
+}
+
+# find domain
+my $domain_name = "f12nwtest";
+diag "Trying domain lookup by name";
+my $dom;
+ok_domain { $dom = $conn->get_domain_by_name($domain_name) } "the
running domain object";
+ok($dom->get_id() > 0, "running domain has an ID > 0");
+
+# cleanup guest
+diag "cleaning up";
+$dom->shutdown();
+ while($dom->is_active()) {
+ sleep(1);
+ diag ".. waiting for virtual machine ${domain_name} to shutdown.. ";
+ }
+#$dom->undefine();
+
+exit 0;
Index: libvirt-tck/scripts/network/common_functions.pl
===================================================================
--- /dev/null
+++ libvirt-tck/scripts/network/common_functions.pl
@@ -0,0 +1,35 @@
+use utf8;
+#no utf8;
+
+sub get_macaddress {
+ my $xmldesc = shift;
+
+ my $mac;
+ my $parser = XML::LibXML->new();
+
+ my $doc = $parser->parse_string($xmldesc);
+
+ my $rootel = $doc -> getDocumentElement();
+
+ my @devices = $rootel->getChildrenByTagName("devices");
+ foreach my $device(@devices) {
+ my @interfaces = $device->getChildrenByTagName("interface");
+ foreach my $interface(@interfaces) {
+ my @targets = $interface->getChildrenByTagName("mac");
+ foreach my $target(@targets) {
+ $mac = $target->getAttribute("address");
+ }
+ }
+ }
+ utf8::decode($mac);
+ return $mac;
+}
+
+sub get_ip_from_leases{
+ my $mac = shift;
+ my $tmp = `grep $mac /var/lib/dnsmasq/dnsmasq.leases`;
+ my @fields = split(/ /, $tmp);
+ my $ip = $fields[2];
+ return $ip;
+}
+1;
--
Best regards,
Gerhard Stenzel,
-----------------------------------------------------------------------------------------------------------------------------------
IBM Deutschland Research & Development GmbH
Vorsitzender des Aufsichtsrats: Martin Jetter
Geschäftsführung: Dirk Wittkopp
Sitz der Gesellschaft: Böblingen
Registergericht: Amtsgericht Stuttgart, HRB 243294