xref: /openbsd-src/regress/sys/kern/sosplice/loop/bcast.pl (revision cba26e98faa2b48aa4705f205ed876af460243a2)
1#!/usr/bin/perl
2#	$OpenBSD: bcast.pl,v 1.1 2021/01/09 15:39:37 bluhm Exp $
3
4# Copyright (c) 2021 Alexander Bluhm <bluhm@openbsd.org>
5#
6# Permission to use, copy, modify, and distribute this software for any
7# purpose with or without fee is hereby granted, provided that the above
8# copyright notice and this permission notice appear in all copies.
9#
10# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
18use strict;
19use warnings;
20use BSD::Socket::Splice qw(setsplice geterror);
21use Errno;
22use Getopt::Std;
23use IO::Socket::IP;
24use Socket qw(getnameinfo AI_PASSIVE NI_NUMERICHOST NI_NUMERICSERV);
25
26# from /usr/include/sys/mbuf.h
27use constant M_MAXLOOP => 128;
28
29my %opts;
30getopts('b:v', \%opts) or do {
31    print STDERR <<"EOF";
32usage: $0 [-v] [-b bcast]
33    -b bcast	broadcast address, default 255.255.255.255
34    -v		verbose
35EOF
36    exit(2);
37};
38
39my $broadcast = $opts{b} || "255.255.255.255";
40my $verbose = $opts{v};
41
42my $timeout = 10;
43$SIG{ALRM} = sub { die "Timeout triggered after $timeout seconds" };
44alarm($timeout);
45
46my $ls = IO::Socket::IP->new(
47    Broadcast		=> $opts{b} ? 1 : undef,
48    GetAddrInfoFlags	=> AI_PASSIVE,
49    LocalHost		=> $broadcast,
50    Proto		=> "udp",
51    Type		=> SOCK_DGRAM,
52) or die "Listen socket failed: $@";
53my ($host, $service) = $ls->sockhost_service(1);
54print "listen on host '$host' service '$service'\n" if $verbose;
55
56my $cs = IO::Socket::IP->new(
57    PeerHost		=> $host,
58    PeerService		=> $service,
59    Proto		=> "udp",
60    Type		=> SOCK_DGRAM,
61) or die "Connect socket failed: $@";
62print "connect to host '$host' service '$service'\n" if $verbose;
63
64my $as = $ls;
65my $peer = $cs->sockname();
66$as->connect($peer)
67    or die "Connect passive socket failed: $!";
68if ($verbose) {
69    my ($err, $peerhost, $peerservice) = getnameinfo($peer,
70	NI_NUMERICHOST | NI_NUMERICSERV);
71    $err and die "Getnameinfo failed: $err";
72    print "accept from host '$peerhost' service '$peerservice'\n";
73}
74
75setsplice($as, $cs)
76    or die "Splice accept to connect socket failed: $!";
77setsplice($cs, $as)
78    or die "Splice connect to accept socket failed: $!";
79
80system("\${SUDO} fstat -n -p $$") if $verbose;
81my ($msg, $buf) = "foo";
82$cs->send($msg, 0)
83    or die "Send to connect socket failed: $!";
84defined $as->recv($buf, 100, 0)
85    or die "Recv from accept socket failed: $!";
86$msg eq $buf
87    or die "Value modified in splice chain";
88$! = geterror($as)
89    or die "No error at accept socket";
90$!{ELOOP}
91    or die "Errno at accept socket is not ELOOP: $!";
92
93# addresses are asymmetric, try it the other way around
94$msg = "bar";
95$as->send($msg, 0)
96    or die "Send to accept socket failed: $!";
97defined $cs->recv($buf, 100, 0)
98    or die "Recv from connect socket failed: $!";
99$msg eq $buf
100    or die "Value modified in splice chain";
101$! = geterror($cs)
102    or die "No error at connect socket";
103$!{ELOOP}
104    or die "Errno at connect socket is not ELOOP: $!";
105