-# $OpenBSD: Makefile,v 1.25 2021/10/02 07:06:13 anton Exp $
+# $OpenBSD: Makefile,v 1.26 2021/11/11 10:03:54 claudio Exp $
SUBDIR += acme-client
SUBDIR += arp
SUBDIR += relayd
SUBDIR += rpki-client
SUBDIR += snmpd
-SUBDIR += switchd
SUBDIR += syslogd
.if ${MACHINE} == "amd64" || ${MACHINE} == "i386"
+++ /dev/null
-# $OpenBSD: Makefile,v 1.11 2021/10/11 05:46:42 anton Exp $
-
-# The following ports must be installed for the regression tests:
-# p5-Net-Pcap Perl interface for libpcap
-# p5-NetPacket Perl interface for packet encoding/decoding
-# p5-BSD-arc4random Perl interface to the arc4 random number generator
-#
-# Check wether all required perl packages are installed. If some
-# are missing print a warning and skip the tests, but do not fail.
-
-PERL_REQUIRE != perl -Mstrict -Mwarnings -e ' \
- eval { require NetPacket::Ethernet } or print $@; \
- eval { require Net::Pcap } or print $@; \
- eval { require BSD::arc4random } or print $@; \
-'
-.if ! empty (PERL_REQUIRE)
-regress:
- @echo "${PERL_REQUIRE}"
- @echo install these perl packages for additional tests
- @echo SKIPPED
-.endif
-
-# Automatically generate regress targets from test cases in directory.
-
-ARGS != cd ${.CURDIR} && ls args-*.pm
-CLEANFILES += stamp-* *.h *.ph *.conf *.log ktrace.out
-
-SRC_PATH = ${.CURDIR}/../../../usr.sbin/switchd
-SYS_PATH = ${.CURDIR}/../../../sys/net
-OFP_HEADERS = ofp.h ofp10.h
-OFP_PERLHEADERS = ${OFP_HEADERS:S/.h/.ph/}
-
-# Set variables so that make runs with and without obj directory.
-# Only do that if necessary to keep visible output short.
-
-.if ${.CURDIR} == ${.OBJDIR}
-PERLINC = -I.
-PERLPATH =
-.else
-PERLINC = -I${.CURDIR} -I${.OBJDIR}
-PERLPATH = ${.CURDIR}/
-.endif
-
-# The arg tests take a perl hash with arguments controlling the
-# test parameters. Generally they consist of switch, switchd.
-
-.for a in ${ARGS}
-REGRESS_TARGETS += run-$a
-run-$a: $a
- time SUDO="${SUDO}" KTRACE=${KTRACE} SWITCHD=${SWITCHD} \
- perl ${PERLINC} ${PERLPATH}run.pl ${PERLPATH}$a
-.endfor
-
-${OFP_HEADERS}:
-.for p in ${SRC_PATH} ${SYS_PATH}
- ! test -s $p/$@ || grep -v '^#include' $p/$@ >$@
-.endfor
-
-.SUFFIXES: .h .ph
-.h.ph:
- @h2ph -d ${.OBJDIR} $<
-
-REGRESS_SETUP = ${OFP_PERLHEADERS}
-
-# make perl syntax check for all args files
-
-.PHONY: syntax
-
-syntax: stamp-syntax
-
-stamp-syntax: ${ARGS}
-.for a in ${ARGS}
- @perl -c ${PERLPATH}$a
-.endfor
- @date >$@
-
-.include <bsd.regress.mk>
+++ /dev/null
-#
-# NetPacket::OFP - Decode and encode OpenFlow packets.
-#
-
-package NetPacket::OFP;
-
-#
-# Copyright (c) 2016 Reyk Floeter <reyk@openbsd.org>.
-#
-# This package is free software and is provided "as is" without express
-# or implied warranty. It may be used, redistributed and/or modified
-# under the terms of the Perl Artistic License (see
-# http://www.perl.com/perl/misc/Artistic.html)
-#
-
-use strict;
-use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
-use NetPacket;
-
-my $myclass;
-BEGIN {
- $myclass = __PACKAGE__;
- $VERSION = "0.01";
-}
-sub Version () { "$myclass v$VERSION" }
-
-BEGIN {
- @ISA = qw(Exporter NetPacket);
-
- @EXPORT = qw();
-
- @EXPORT_OK = qw(ofp_strip);
-
- %EXPORT_TAGS = (
- ALL => [@EXPORT, @EXPORT_OK],
- strip => [qw(ofp_strip)],
- );
-}
-
-#
-# Get aligned packet size
-#
-
-sub ofp_align {
- my $matchlen = shift;
-
- return (($matchlen + (8 - 1)) & (~(8 - 1)));
-}
-
-#
-# Decode the packet
-#
-
-sub decode {
- my $class = shift;
- my($pkt, $parent, @rest) = @_;
- my $self = {};
-
- # Class fields
- $self->{_parent} = $parent;
- $self->{_frame} = $pkt;
-
- $self->{version} = 1;
- $self->{type} = 0;
- $self->{length} = 0;
- $self->{xid} = 0;
- $self->{data} = '';
-
- # Decode OpenFlow packet
- if (defined($pkt)) {
- ($self->{version}, $self->{type}, $self->{length},
- $self->{xid}, $self->{data}) = unpack("CCnNa*", $pkt);
- }
-
- # Return a blessed object
- bless($self, $class);
-
- return ($self);
-}
-
-#
-# Strip header from packet and return the data contained in it
-#
-
-undef &udp_strip;
-*ofp_strip = \&strip;
-
-sub strip {
- my ($pkt, @rest) = @_;
- my $ofp_obj = decode($pkt);
- return ($ofp_obj->data);
-}
-
-#
-# Encode a packet
-#
-
-sub encode {
- my $class = shift;
- my $self = shift;
- my $pkt = '';
- my $datalen = length($self->{data});
-
- if ($self->{length} == 0) {
- $self->{length} = 8 + $datalen;
- }
-
- if ($datalen == 0) {
- $pkt = pack('CCnN', $self->{version}, $self->{type},
- $self->{length}, $self->{xid});
- } else {
- $pkt = pack('CCnNa*', $self->{version}, $self->{type},
- $self->{length}, $self->{xid}, $self->{data});
- }
-
- return ($pkt);
-}
-
-#
-# Table property Multipart reply
-#
-
-sub ofp_table_property {
- my $tp_type = shift;
- my $tp_payload = shift;
- my $tp_header;
- my ($datalen, $pad);
-
- # len = header + payload
- $datalen = 4 + length($tp_payload);
-
- $tp_header = pack('nna*',
- $tp_type, # type
- $datalen, # length
- $tp_payload # payload
- );
-
- $pad = ofp_align($datalen) - $datalen;
- if ($pad > 0) {
- $tp_header .= pack("x[$pad]");
- }
-
- return ($tp_header);
-}
-
-sub ofp_table_features_reply {
- my $class = shift;
- my $self = shift;
- my $pkt = NetPacket::OFP->decode() or fatal($class, "new packet");
- my ($tf_header, $tf_payload);
- my ($tp_header, $tp_payload);
- my $mp_header;
-
- $tf_payload = '';
-
- #
- # instructions
- #
- $tp_payload = '';
- for (my $inst = main::OFP_INSTRUCTION_T_GOTO_TABLE();
- $inst <= main::OFP_INSTRUCTION_T_METER(); $inst++) {
- $tp_payload .= pack('nn',
- $inst, # type
- 4 # length
- );
- }
-
- $tf_payload .=
- ofp_table_property(main::OFP_TABLE_FEATPROP_INSTRUCTION(),
- $tp_payload);
- $tf_payload .=
- ofp_table_property(main::OFP_TABLE_FEATPROP_INSTRUCTION_MISS(),
- $tp_payload);
-
- #
- # Next tables
- #
- $tp_payload = '';
-
- $tf_payload .=
- ofp_table_property(main::OFP_TABLE_FEATPROP_NEXT_TABLES(),
- $tp_payload);
- $tf_payload .=
- ofp_table_property(main::OFP_TABLE_FEATPROP_NEXT_TABLES_MISS(),
- $tp_payload);
-
- #
- # Write / Apply actions
- #
- $tp_payload = pack('nn',
- main::OFP_ACTION_OUTPUT(), # type
- 4, # length
- );
- $tp_payload .= pack('nn',
- main::OFP_ACTION_PUSH_VLAN(), # type
- 4, # length
- );
- $tp_payload .= pack('nn',
- main::OFP_ACTION_POP_VLAN(), # type
- 4, # length
- );
-
- $tf_payload .=
- ofp_table_property(main::OFP_TABLE_FEATPROP_WRITE_ACTIONS(),
- $tp_payload);
- $tf_payload .=
- ofp_table_property(main::OFP_TABLE_FEATPROP_WRITE_ACTIONS_MISS(),
- $tp_payload);
- $tf_payload .=
- ofp_table_property(main::OFP_TABLE_FEATPROP_APPLY_ACTIONS(),
- $tp_payload);
- $tf_payload .=
- ofp_table_property(main::OFP_TABLE_FEATPROP_APPLY_ACTIONS_MISS(),
- $tp_payload);
-
- #
- # Match/Wildcards/Write set-field/Apply set-field
- #
- $tp_payload = pack('nCC',
- main::OFP_OXM_C_OPENFLOW_BASIC(), # class
- main::OFP_XM_T_IN_PORT() << 1, # type
- 4, # length
- );
- $tp_payload .= pack('nCC',
- main::OFP_OXM_C_OPENFLOW_BASIC(), # class
- main::OFP_XM_T_ETH_TYPE() << 1, # type
- 4, # length
- );
- $tp_payload .= pack('nCC',
- main::OFP_OXM_C_OPENFLOW_BASIC(), # class
- main::OFP_XM_T_ETH_SRC() << 1, # type
- 4, # length
- );
- $tp_payload .= pack('nCC',
- main::OFP_OXM_C_OPENFLOW_BASIC(), # class
- main::OFP_XM_T_ETH_DST() << 1, # type
- 4, # length
- );
- $tf_payload .=
- ofp_table_property(main::OFP_TABLE_FEATPROP_MATCH(),
- $tp_payload);
- $tf_payload .=
- ofp_table_property(main::OFP_TABLE_FEATPROP_WILDCARDS(),
- $tp_payload);
- $tf_payload .=
- ofp_table_property(main::OFP_TABLE_FEATPROP_WRITE_SETFIELD(),
- $tp_payload);
- $tf_payload .=
- ofp_table_property(main::OFP_TABLE_FEATPROP_WRITE_SETFIELD_MISS(),
- $tp_payload);
- $tf_payload .=
- ofp_table_property(main::OFP_TABLE_FEATPROP_APPLY_SETFIELD(),
- $tp_payload);
- $tf_payload .=
- ofp_table_property(main::OFP_TABLE_FEATPROP_APPLY_SETFIELD_MISS(),
- $tp_payload);
-
- #
- # Finish
- #
- $tf_header = pack('nCx[5]a[32]NNNNNN',
- 64 + length($tf_payload), # length
- 0, # tableid
- 'start', # name
- 0x00000000, 0x00000000, # metadata_match
- 0x00000000, 0x00000000, # metadata_write
- 0x00000000, # config
- 10000 # max_entries
- );
- $tf_header .= $tf_payload;
- # XXX everything fits a single multipart reply, for now.
-
- $mp_header = pack('nnx[4]',
- main::OFP_MP_T_TABLE_FEATURES(), # multipart type
- 0 # multipart flags
- );
-
- $mp_header .= $tf_header;
-
- $pkt->{version} = $self->{version};
- $pkt->{type} = main::OFP_T_MULTIPART_REPLY();
- $pkt->{xid} = $self->{xid}++;
- $pkt->{data} = $mp_header;
- $pkt = NetPacket::OFP->encode($pkt);
-
- main::ofp_output($self, $pkt);
-
- # Wait for new flow-mod
- main::ofp_input($self);
-}
-
-#
-# Module initialisation
-#
-
-1;
-
-# autoloaded methods go after the END token (&& pod) below
-
-__END__
-
-=head1 NAME
-
-C<NetPacket::OFP> - Assemble and disassemble OpenFlow packets.
-
-=head1 SYNOPSIS
-
- use NetPacket::OFP;
-
- $ofp_obj = NetPacket::OFP->decode($raw_pkt);
- $ofp_pkt = NetPacket::OFP->encode($ofp_obj);
- $ofp_data = NetPacket::OFP::strip($raw_pkt);
-
-=head1 DESCRIPTION
-
-C<NetPacket::OFP> provides a set of routines for assembling and
-disassembling packets using OpenFlow.
-
-=head2 Methods
-
-=over
-
-=item C<NetPacket::OFP-E<gt>decode([RAW PACKET])>
-
-Decode the raw packet data given and return an object containing
-instance data. This method will quite happily decode garbage input.
-It is the responsibility of the programmer to ensure valid packet data
-is passed to this method.
-
-=item C<NetPacket::OFP-E<gt>encode($ofp_obj)>
-
-Return a OFP packet encoded with the instance data specified.
-
-=back
-
-=head2 Functions
-
-=over
-
-=item C<NetPacket::OFP::strip([RAW PACKET])>
-
-Return the encapsulated data (or payload) contained in the OpenFlow
-packet. This data is suitable to be used as input for other
-C<NetPacket::*> modules.
-
-This function is equivalent to creating an object using the
-C<decode()> constructor and returning the C<data> field of that
-object.
-
-=back
-
-=head2 Instance data
-
-The instance data for the C<NetPacket::OFP> object consists of
-the following fields.
-
-=over
-
-=item version
-
-The OpenFlow version.
-
-=item type
-
-The message type.
-
-=item length
-
-The total message length.
-
-=item xid
-
-The transaction Id.
-
-=item data
-
-The encapsulated data (payload) for this packet.
-
-=back
-
-=head2 Exports
-
-=over
-
-=item default
-
-none
-
-=item exportable
-
-ofp_strip
-
-=item tags
-
-The following tags group together related exportable items.
-
-=over
-
-=item C<:strip>
-
-Import the strip function C<ofp_strip>.
-
-=item C<:ALL>
-
-All the above exportable items.
-
-=back
-
-=back
-
-=head1 COPYRIGHT
-
- Copyright (c) 2016 Reyk Floeter <reyk@openbsd.org>
-
- This package is free software and is provided "as is" without express
- or implied warranty. It may be used, redistributed and/or modified
- under the terms of the Perl Artistic License (see
- http://www.perl.com/perl/misc/Artistic.html)
-
-=head1 AUTHOR
-
-Reyk Floeter E<lt>reyk@openbsd.orgE<gt>
-
-=cut
-
-# any real autoloaded methods go after this line
+++ /dev/null
-# $OpenBSD: Proc.pm,v 1.2 2021/10/11 05:46:42 anton Exp $
-
-# Copyright (c) 2010-2017 Alexander Bluhm <bluhm@openbsd.org>
-#
-# Permission to use, copy, modify, and distribute this software for any
-# purpose with or without fee is hereby granted, provided that the above
-# copyright notice and this permission notice appear in all copies.
-#
-# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-use strict;
-use warnings;
-
-package Proc;
-use Carp;
-use Errno;
-use IO::File;
-use POSIX;
-use Time::HiRes qw(time alarm sleep);
-
-my %CHILDREN;
-
-sub kill_children {
- my @pids = @_ ? @_ : keys %CHILDREN
- or return;
- my @perms;
- foreach my $pid (@pids) {
- if (kill(TERM => $pid) != 1 and $!{EPERM}) {
- push @perms, $pid;
- }
- }
- if (my @sudo = split(' ', $ENV{SUDO}) and @perms) {
- local $?; # do not modify during END block
- my @cmd = (@sudo, '/bin/kill', '-TERM', @perms);
- system(@cmd);
- }
- delete @CHILDREN{@pids};
-}
-
-BEGIN {
- $SIG{TERM} = $SIG{INT} = sub {
- my $sig = shift;
- kill_children();
- $SIG{TERM} = $SIG{INT} = 'DEFAULT';
- POSIX::raise($sig);
- };
-}
-
-END {
- kill_children();
- $SIG{TERM} = $SIG{INT} = 'DEFAULT';
-}
-
-sub new {
- my $class = shift;
- my $self = { @_ };
- $self->{down} ||= "Shutdown";
- $self->{func} && ref($self->{func}) eq 'CODE'
- or croak "$class func not given";
- $self->{logfile}
- or croak "$class log file not given";
- open(my $fh, '>', $self->{logfile})
- or die "$class log file $self->{logfile} create failed: $!";
- $fh->autoflush;
- $self->{log} = $fh;
- $self->{ppid} = $$;
- return bless $self, $class;
-}
-
-sub run {
- my $self = shift;
-
- pipe(my $reader, my $writer)
- or die ref($self), " pipe to child failed: $!";
- defined(my $pid = fork())
- or die ref($self), " fork child failed: $!";
- if ($pid) {
- $CHILDREN{$pid} = 1;
- $self->{pid} = $pid;
- close($reader);
- $self->{pipe} = $writer;
- return $self;
- }
- %CHILDREN = ();
- $SIG{TERM} = $SIG{INT} = 'DEFAULT';
- $SIG{__DIE__} = sub {
- die @_ if $^S;
- warn @_;
- IO::Handle::flush(\*STDERR);
- POSIX::_exit(255);
- };
- open(STDERR, '>&', $self->{log})
- or die ref($self), " dup STDERR failed: $!";
- close($writer);
- open(STDIN, '<&', $reader)
- or die ref($self), " dup STDIN failed: $!";
- close($reader);
-
- do {
- $self->child();
- print STDERR $self->{up}, "\n";
- $self->{func}->($self);
- } while ($self->{redo});
- print STDERR "Shutdown", "\n";
-
- IO::Handle::flush(\*STDOUT);
- IO::Handle::flush(\*STDERR);
- POSIX::_exit(0);
-}
-
-sub wait {
- my $self = shift;
- my $flags = shift;
-
- # if we a not the parent process, assume the child is still running
- return 0 unless $self->{ppid} == $$;
-
- my $pid = $self->{pid}
- or croak ref($self), " no child pid";
- my $kid = waitpid($pid, $flags);
- if ($kid > 0) {
- my $status = $?;
- my $code;
- $code = "exit: ". WEXITSTATUS($?) if WIFEXITED($?);
- $code = "signal: ". WTERMSIG($?) if WIFSIGNALED($?);
- $code = "stop: ". WSTOPSIG($?) if WIFSTOPPED($?);
- delete $CHILDREN{$pid} if WIFEXITED($?) || WIFSIGNALED($?);
- return wantarray ? ($kid, $status, $code) : $kid;
- }
- return $kid;
-}
-
-sub loggrep {
- my $self = shift;
- my($regex, $timeout) = @_;
-
- my $end;
- $end = time() + $timeout if $timeout;
-
- do {
- my($kid, $status, $code) = $self->wait(WNOHANG);
- if ($kid > 0 && $status != 0 && !$self->{dryrun}) {
- # child terminated with failure
- die ref($self), " child status: $status $code";
- }
- open(my $fh, '<', $self->{logfile})
- or die ref($self), " log file open failed: $!";
- my @match = grep { /$regex/ } <$fh>;
- return wantarray ? @match : $match[0] if @match;
- close($fh);
- # pattern not found
- if ($kid == 0) {
- # child still running, wait for log data
- sleep .1;
- } else {
- # child terminated, no new log data possible
- return;
- }
- } while ($timeout and time() < $end);
-
- return;
-}
-
-sub up {
- my $self = shift;
- my $timeout = shift || 10;
- $self->loggrep(qr/$self->{up}/, $timeout)
- or croak ref($self), " no '$self->{up}' in $self->{logfile} ".
- "after $timeout seconds";
- return $self;
-}
-
-sub down {
- my $self = shift;
- my $timeout = shift || 30;
- $self->loggrep(qr/$self->{down}/, $timeout)
- or croak ref($self), " no '$self->{down}' in $self->{logfile} ".
- "after $timeout seconds";
- return $self;
-}
-
-sub kill_child {
- my $self = shift;
- kill_children($self->{pid});
- return $self;
-}
-
-1;
+++ /dev/null
-# $OpenBSD: Switchd.pm,v 1.2 2021/10/11 05:46:42 anton Exp $
-
-# Copyright (c) 2010-2017 Alexander Bluhm <bluhm@openbsd.org>
-#
-# Permission to use, copy, modify, and distribute this software for any
-# purpose with or without fee is hereby granted, provided that the above
-# copyright notice and this permission notice appear in all copies.
-#
-# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-use strict;
-use warnings;
-
-package Switchd;
-use parent 'Proc';
-use Carp;
-use Cwd;
-use Sys::Hostname;
-use File::Basename;
-
-sub new {
- my $class = shift;
- my %args = @_;
- $args{logfile} ||= "switchd.log";
- $args{up} ||= $args{dryrun} || "listen on ";
- $args{down} ||= $args{dryrun} ? "switchd.conf:" : "parent terminating";
- $args{func} = sub { Carp::confess "$class func may not be called" };
- $args{conffile} ||= "switchd.conf";
- my $self = Proc::new($class, %args);
- $self->{listenaddr}
- or croak "$class listen addr not given";
- $self->{listenport}
- or croak "$class listen port not given";
-
- # substitute variables in config file
- my $curdir = dirname($0) || ".";
- my $objdir = getcwd();
- my $hostname = hostname();
- (my $host = $hostname) =~ s/\..*//;
- my $listenaddr = $self->{listenaddr};
- my $listenport = $self->{listenport};
-
- my $test = basename($self->{testfile} || "");
- open(my $fh, '>', $self->{conffile})
- or die ref($self), " conf file $self->{conffile} create failed: $!";
-
- my $config = "# regress $test\n";
- $config .= "listen on $self->{listenaddr} port $self->{listenport}\n"
- unless $self->{conf} && $self->{conf} =~ /^listen /;
- $config .= $self->{conf} if $self->{conf};
- $config =~ s/(\$[a-z]+)/$1/eeg;
- print $fh $config;
- close $fh;
-
- return $self;
-}
-
-sub child {
- my $self = shift;
- my @sudo = $ENV{SUDO} ? split(' ', $ENV{SUDO}) : ();
- my @ktrace = $ENV{KTRACE} ? ($ENV{KTRACE}, "-i") : ();
- my $switchd = $ENV{SWITCHD} ? $ENV{SWITCHD} : "switchd";
- my @cmd = (@sudo, @ktrace, $switchd, "-dvv", "-f", $self->{conffile});
- print STDERR "execute: @cmd\n";
- exec @cmd;
- die ref($self), " exec '@cmd' failed: $!";
-}
-
-1;
+++ /dev/null
-# $OpenBSD: args-http.pm,v 1.1 2016/07/19 17:19:58 reyk Exp $
-
-# Copyright (c) 2016 Reyk Floeter <reyk@openbsd.org>
-#
-# Permission to use, copy, modify, and distribute this software for any
-# purpose with or without fee is hereby granted, provided that the above
-# copyright notice and this permission notice appear in all copies.
-#
-# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-package args_http;
-
-use strict;
-use warnings;
-use base qw(Exporter);
-our @EXPORT = qw(init next);
-
-my $topology = {
- hosts => {
- "6c8814709208" => {
- "port" => 8
- },
- "3431c4778157" => {
- "port" => 24
- }
- }
-};
-
-sub init {
- my $class = shift;
- my $sock = shift;
- my $self = { "count" => 0, "pcap" => "args-http.pcap",
- "sock" => $sock, "version" => main::OFP_V_1_0() };
-
- bless($self, $class);
-
- main::ofp_hello($self);
-
- return ($self);
-}
-
-sub next {
- my $class = shift;
- my $self = shift;
- my $src;
-
- $self->{count}++;
-
- $src = $topology->{hosts}->{$self->{eh}->{src_mac}};
- if ($src) {
- $self->{port} = $src->{port};
- }
-
- main::ofp_packet_in($self, $self->{data});
-}
-
-1;
+++ /dev/null
-# $OpenBSD: args-icmp.pm,v 1.1 2016/07/19 17:19:58 reyk Exp $
-
-# Copyright (c) 2016 Reyk Floeter <reyk@openbsd.org>
-#
-# Permission to use, copy, modify, and distribute this software for any
-# purpose with or without fee is hereby granted, provided that the above
-# copyright notice and this permission notice appear in all copies.
-#
-# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-package args_icmp;
-
-use strict;
-use warnings;
-use base qw(Exporter);
-our @EXPORT = qw(init next);
-
-sub init {
- my $class = shift;
- my $sock = shift;
- my $self = { "count" => 0, "pcap" => "args-icmp.pcap",
- "sock" => $sock, "version" => main::OFP_V_1_0() };
-
- bless($self, $class);
-
- main::ofp_hello($self);
-
- return ($self);
-}
-
-sub next {
- my $class = shift;
- my $self = shift;
-
- $self->{count}++;
- $self->{port} = $self->{count} % 2;
-
- main::ofp_packet_in($self, $self->{data});
-}
-
-1;
+++ /dev/null
-# $OpenBSD: args-packet-jumbo.pm,v 1.4 2016/11/17 14:37:55 rzalamena Exp $
-
-# Copyright (c) 2016 Reyk Floeter <reyk@openbsd.org>
-#
-# Permission to use, copy, modify, and distribute this software for any
-# purpose with or without fee is hereby granted, provided that the above
-# copyright notice and this permission notice appear in all copies.
-#
-# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-package args_packet_jumbo;
-
-use strict;
-use warnings;
-use base qw(Exporter);
-our @EXPORT = qw(init next);
-
-my $topology = {
- buffers => {},
- hosts => {
- "a00000000001" => {
- "port" => 1
- },
- "a00000000002" => {
- "port" => 2
- },
- "a00000000003" => {
- "port" => 3
- }
- },
- packets => [
- {
- "src_mac" => "a00000000001",
- "dest_mac" => "a00000000002",
- "src_ip" => "10.0.0.1",
- "src_port" => 12345,
- "dest_ip" => "10.0.0.2",
- "dest_port" => 80,
- "length" => 2048,
- "count" => 3,
- "ofp_response" => main::OFP_T_PACKET_OUT()
- },
- {
- "src_mac" => "a00000000002",
- "dest_mac" => "a00000000001",
- "src_ip" => "10.0.0.2",
- "src_port" => 80,
- "dest_ip" => "10.0.0.1",
- "dest_port" => 12345,
- "length" => 17000,
- "count" => 3,
- "ofp_response" => main::OFP_T_FLOW_MOD()
-
- },
- {
- "src_mac" => "a00000000001",
- "dest_mac" => "ffffffffffff",
- "src_ip" => "10.0.0.1",
- "dest_ip" => "10.255.255.255",
- "length" => 65451,
- "count" => 3,
- "ofp_response" => main::OFP_T_PACKET_OUT()
- }
- ]
-};
-
-sub init {
- my $class = shift;
- my $sock = shift;
- my $self = { "count" => 0,
- "sock" => $sock, "version" => main::OFP_V_1_3() };
-
- bless($self, $class);
- main::ofp_hello($self);
-
- for (my $i = 0; $i < @{$topology->{packets}}; $i++) {
- my $packet = $topology->{packets}[$i];
- my $src = $topology->{hosts}->{$packet->{src_mac}};
-
- $self->{port} = $src->{port} if ($src);
-
- for (my $j = 0; $j < $packet->{count}; $j++) {
- my $ofp;
- $self->{count}++;
- $ofp = main::packet_send($self, $packet);
-
- if (not defined($packet->{ofp_response})) {
- continue;
- }
-
- if ($ofp->{type} != $packet->{ofp_response}) {
- main::fatal($class,
- "invalid ofp response type " .
- $ofp->{type});
- }
-
- # Flow-mod also expects an packet-out.
- if ($packet->{ofp_response} == main::OFP_T_FLOW_MOD()) {
- $ofp = main::ofp_input($self);
- if ($ofp->{type} != main::OFP_T_PACKET_OUT()) {
- main::fatal($class,
- "invalid ofp response type " .
- $ofp->{type});
- }
- }
- }
- }
-
- return ($self);
-}
-
-sub next {
- # Not used
-}
-
-1;
+++ /dev/null
-#!/usr/bin/perl
-# $OpenBSD: run.pl,v 1.12 2018/12/03 22:41:00 bluhm Exp $
-
-# Copyright (c) 2017 Alexander Bluhm <bluhm@openbsd.org>
-# Copyright (c) 2016 Reyk Floeter <reyk@openbsd.org>
-#
-# Permission to use, copy, modify, and distribute this software for any
-# purpose with or without fee is hereby granted, provided that the above
-# copyright notice and this permission notice appear in all copies.
-#
-# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-use strict;
-use warnings;
-use File::Basename;
-use IO::Socket::INET;
-use Net::Pcap;
-use NetPacket::Ethernet;
-use NetPacket::IP;
-use NetPacket::UDP;
-use BSD::arc4random qw(arc4random arc4random_uniform arc4random_bytes);
-
-use Switchd;
-
-BEGIN {
- require OFP;
- require 'ofp.ph';
- require 'ofp10.ph';
-}
-
-sub fatal {
- my $class = shift;
- my $err = shift;
- print STDERR "*** ".$class.": ".$err."\n";
- die($err);
-}
-
-sub ofp_debug {
- my $dir = shift;
- my $ofp = shift;
-
- fatal("OFP", "empty response") if (!$ofp->{version});
-
- printf("OFP ".$dir." version %d type %d length %d xid %d\n",
- $ofp->{version},
- $ofp->{type},
- $ofp->{length},
- $ofp->{xid});
-
-}
-
-sub ofp_input {
- my $self = shift;
- my $pkt;
- my $pktext;
- my $ofp;
- my $ofplen;
-
- # Read the OFP payload head
- $self->{sock}->recv($pkt, 8);
- $ofp = NetPacket::OFP->decode($pkt) or
- fatal('ofp_input', 'Failed to decode OFP header');
-
- # Read the body and decode it.
- $ofplen = $ofp->{length};
- if (defined($ofplen) && $ofplen > 8) {
- $ofplen -= 8;
-
- # Perl recv() only reads 16k at a time, so loop here.
- while ($ofplen > 0) {
- $self->{sock}->recv($pktext, $ofplen);
- if (length($pktext) == 0) {
- fatal('ofp_input', 'Socket closed');
- }
- $ofplen -= length($pktext);
- $pkt .= $pktext;
- }
-
- $ofp = NetPacket::OFP->decode($pkt) or
- fatal('ofp_input', 'Failed to decode OFP');
- }
- ofp_debug('<', $ofp);
-
- return ($ofp);
-}
-
-sub ofp_output {
- my $self = shift;
- my $pkt = shift;
- my $ofp = NetPacket::OFP->decode($pkt);
-
- ofp_debug('>', $ofp);
- $self->{sock}->send($pkt);
-}
-
-sub ofp_match_align {
- my $matchlen = shift;
-
- return (($matchlen + (8 - 1)) & (~(8 - 1)));
-}
-
-sub ofp_hello {
- my $class;
- my $self = shift;
- my $hello = NetPacket::OFP->decode() or fatal($class, "new packet");
- my $features;
- my $pkt;
-
- $hello->{version} = $self->{version};
- $hello->{type} = OFP_T_HELLO();
- $hello->{xid} = $self->{xid}++;
- $pkt = NetPacket::OFP->encode($hello);
-
- # XXX timeout
- ofp_output($self, $pkt);
- $hello = ofp_input($self);
-
- # OpenFlow >= 1.3 wants features, set-config and table features.
- if ($self->{version} == OFP_V_1_3()) {
- $features = ofp_input($self);
- if ($features->{type} != OFP_T_FEATURES_REQUEST()) {
- fatal($class, 'Unexpected packet type ' .
- $features->{type});
- }
-
- $pkt = NetPacket::OFP->decode() or
- fatal($class, 'new packet');
- $pkt->{version} = $self->{version};
- $pkt->{type} = OFP_T_FEATURES_REPLY();
- $pkt->{xid} = $features->{xid};
- $pkt->{data} = pack('NNNCCxxNN',
- 0x00FFAABB, 0xCCDDEEFF, # datapath_id
- 0, # nbuffers
- 1, # ntables
- 0, # aux_id
- 0x00000001, # capabilities
- 0x00000001 # actions
- );
- ofp_output($self, NetPacket::OFP->encode($pkt));
-
- # Just read set-config and table features request
- ofp_input($self);
- ofp_input($self);
-
- # Answer the table features so switchd(8) install table-miss
- NetPacket::OFP->ofp_table_features_reply($self);
- }
-
- return ($hello);
-}
-
-sub ofp_packet_in {
- my $class;
- my $self = shift;
- my $data = shift;
- my $pktin = NetPacket::OFP->decode() or fatal($class, "new packet");
- my $pkt;
-
- if ($self->{version} == OFP_V_1_0()) {
- $pkt = pack('NnnCxa*',
- OFP_PKTOUT_NO_BUFFER(), # buffer_id
- length($data), # total_len
- $self->{port} || OFP_PORT_NORMAL(), # port
- OFP_PKTIN_REASON_NO_MATCH(), # reason
- $data # data
- );
- } else {
- my $match = pack('nCCN',
- OFP_OXM_C_OPENFLOW_BASIC(), # class
- OFP_XM_T_IN_PORT(), # field + mask
- 4, # length
- $self->{port} || OFP_PORT_NORMAL() # in_port
- );
- # matchlen is OXMs + ofp_match header.
- my $matchlen = 4 + length($match);
- my $padding = ofp_match_align($matchlen) - $matchlen;
- if ($padding > 0) {
- $match .= pack("x[$padding]");
- }
-
- $pkt = pack('NnCCNNnna*xxa*',
- OFP_PKTOUT_NO_BUFFER(), # buffer_id
- length($data), # total_len
- OFP_PKTIN_REASON_NO_MATCH(), # reason
- 0, # table_id
- 0x00000000, 0x00000000, # cookie
- OFP_MATCH_OXM(), # match_type
- $matchlen, # match_len
- $match, # OXM matches
- $data # data
- );
- }
-
- $pktin->{version} = $self->{version};
- $pktin->{type} = OFP_T_PACKET_IN();
- $pktin->{xid} = $self->{xid}++;
- $pktin->{data} = $pkt;
- $pkt = NetPacket::OFP->encode($pktin);
-
- # XXX timeout
- ofp_output($self, $pkt);
- return (ofp_input($self));
-}
-
-sub packet_send {
- my $class;
- my $self = shift;
- my $packet = shift;
- my $eth;
- my $ip;
- my $udp;
- my $data;
- my $pkt;
- my $src;
-
- # Payload
- $data = arc4random_bytes($packet->{length});
-
- # IP header
- $ip = NetPacket::IP->decode();
- $ip->{src_ip} = $packet->{src_ip} || "127.0.0.1";
- $ip->{dest_ip} = $packet->{dest_ip} || "127.0.0.1";
- $ip->{ver} = NetPacket::IP::IP_VERSION_IPv4;
- $ip->{hlen} = 5;
- $ip->{tos} = 0;
- $ip->{id} = arc4random_uniform(2**16);
- $ip->{ttl} = 0x5a;
- $ip->{flags} = 0; #XXX NetPacket::IP::IP_FLAG_DONTFRAG;
- $ip->{foffset} = 0;
- $ip->{proto} = NetPacket::IP::IP_PROTO_UDP;
- $ip->{options} = '';
-
- # UDP header
- $udp = NetPacket::UDP->decode();
- $udp->{src_port} = $packet->{src_port} || 9000;
- $udp->{dest_port} = $packet->{dest_port} || 9000;
- $udp->{data} = $data;
-
- $ip->{data} = $udp->encode($ip);
- $pkt = $ip->encode() or fatal($class, "ip");
-
- # Create Ethernet header
- $self->{data} = pack('H12H12na*' ,
- $packet->{dest_mac},
- $packet->{src_mac},
- NetPacket::Ethernet::ETH_TYPE_IP,
- $pkt);
-
- return (main::ofp_packet_in($self, $self->{data}));
-}
-
-sub packet_decode {
- my $pkt = shift;
- my $hdr = shift;
- my $eh = NetPacket::Ethernet->decode($pkt);
-
- printf("%s %s %04x %d",
- join(':', unpack '(A2)*', $eh->{src_mac}),
- join(':', unpack '(A2)*', $eh->{dest_mac}),
- $eh->{type}, length($pkt));
- if (length($pkt) < $hdr->{len}) {
- printf("/%d", $hdr->{len})
- }
- printf("\n");
-
- return ($eh);
-}
-
-sub process {
- my $sock = shift;
- my $path = shift;
- my $pcap_t;
- my $err;
- my $pkt;
- my %hdr;
- my ($filename, $dirs, $suffix) = fileparse($path, ".pm");
- (my $func = $filename) =~ s/-/_/g;
- my $state;
- local $@;
-
- print "- $filename\n";
-
- require $path or fatal("main", $path);
-
- eval {
- $state = $func->init($sock);
- };
- die if($@);
-
- return if not $state->{pcap};
-
- $pcap_t = Net::Pcap::open_offline($dirs."".$state->{pcap}, \$err)
- or fatal("main", $err);
-
- while ($pkt = Net::Pcap::next($pcap_t, \%hdr)) {
-
- $state->{data} = $pkt;
- $state->{eh} = packet_decode($pkt, \%hdr);
-
- eval {
- $func->next($state);
- };
- die if($@);
- }
-
- Net::Pcap::close($pcap_t);
-}
-
-if (@ARGV < 1) {
- print "\nUsage: run.pl test.pl\n";
- exit;
-}
-
-# Flush after every write
-$| = 1;
-
-my $test = $ARGV[0];
-my @test_files = ();
-for (@ARGV) {
- push(@test_files, glob($_));
-}
-
-my $sd = Switchd->new(
- listenaddr => "127.0.0.1",
- listenport => 6633,
- testfile => $test,
-);
-$sd->run->up;
-
-# Open connection to the controller
-my $sock = IO::Socket::INET->new(
- PeerHost => "127.0.0.1",
- PeerPort => 6633,
- Proto => 'tcp',
-) or fatal("main", "ERROR in Socket Creation : $!\n");
-
-# Run all requested tests
-for my $test_file (@test_files) {
- process($sock, $test_file);
-}
-
-$sock->close();
-
-$sd->kill_child->down;
-
-1;