xref: /openbsd/regress/usr.sbin/ospfd/Tap.pm (revision da1b64c4)
1*da1b64c4Sbluhm#	$OpenBSD: Tap.pm,v 1.1 2016/09/28 12:40:35 bluhm Exp $
2*da1b64c4Sbluhm
3*da1b64c4Sbluhm# Copyright (c) 2014 Alexander Bluhm <bluhm@openbsd.org>
4*da1b64c4Sbluhm#
5*da1b64c4Sbluhm# Permission to use, copy, modify, and distribute this software for any
6*da1b64c4Sbluhm# purpose with or without fee is hereby granted, provided that the above
7*da1b64c4Sbluhm# copyright notice and this permission notice appear in all copies.
8*da1b64c4Sbluhm#
9*da1b64c4Sbluhm# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10*da1b64c4Sbluhm# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11*da1b64c4Sbluhm# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12*da1b64c4Sbluhm# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13*da1b64c4Sbluhm# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14*da1b64c4Sbluhm# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15*da1b64c4Sbluhm# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16*da1b64c4Sbluhm
17*da1b64c4Sbluhm# Encapsulate tap interface handling into separate module.
18*da1b64c4Sbluhm
19*da1b64c4Sbluhmuse strict;
20*da1b64c4Sbluhmuse warnings;
21*da1b64c4Sbluhm
22*da1b64c4Sbluhmpackage Tap;
23*da1b64c4Sbluhmuse parent 'Exporter';
24*da1b64c4Sbluhmour @EXPORT_OK = qw(opentap);
25*da1b64c4Sbluhm
26*da1b64c4Sbluhmuse Carp;
27*da1b64c4Sbluhmuse Fcntl;
28*da1b64c4Sbluhmuse File::Basename;
29*da1b64c4Sbluhmuse POSIX qw(_exit);
30*da1b64c4Sbluhmuse PassFd 'recvfd';
31*da1b64c4Sbluhmuse Socket;
32*da1b64c4Sbluhm
33*da1b64c4Sbluhmsub opentap {
34*da1b64c4Sbluhm    my ($tap_number) = @_;
35*da1b64c4Sbluhm    my $tap_device = "/dev/tap$tap_number";
36*da1b64c4Sbluhm
37*da1b64c4Sbluhm    if ($> == 0) {
38*da1b64c4Sbluhm	sysopen(my $tap, $tap_device, O_RDWR)
39*da1b64c4Sbluhm	    or croak "Open $tap_device failed: $!";
40*da1b64c4Sbluhm	return $tap;
41*da1b64c4Sbluhm    }
42*da1b64c4Sbluhm
43*da1b64c4Sbluhm    if (!$ENV{SUDO}) {
44*da1b64c4Sbluhm	die "To open the device $tap_device you must run as root or\n".
45*da1b64c4Sbluhm	    "set the SUDO environment variable and allow closefrom_override.\n";
46*da1b64c4Sbluhm    }
47*da1b64c4Sbluhm
48*da1b64c4Sbluhm    my $opentap;
49*da1b64c4Sbluhm    my $curdir = dirname($0) || ".";
50*da1b64c4Sbluhm    if (-x "$curdir/opentap") {
51*da1b64c4Sbluhm	$opentap = "$curdir/opentap";
52*da1b64c4Sbluhm    } elsif (-x "./opentap") {
53*da1b64c4Sbluhm	$opentap = "./opentap";
54*da1b64c4Sbluhm    } else {
55*da1b64c4Sbluhm	die "To open the device $tap_device the tool opentap is needed.\n".
56*da1b64c4Sbluhm	    "Executable opentap not found in $curdir or current directory.\n";
57*da1b64c4Sbluhm    }
58*da1b64c4Sbluhm
59*da1b64c4Sbluhm    socketpair(my $parent, my $child, AF_UNIX, SOCK_STREAM, PF_UNSPEC)
60*da1b64c4Sbluhm	or croak "Socketpair failed: $!";
61*da1b64c4Sbluhm    $child->fcntl(F_SETFD, 0)
62*da1b64c4Sbluhm	or croak "Fcntl setfd failed: $!";
63*da1b64c4Sbluhm
64*da1b64c4Sbluhm    defined(my $pid = fork())
65*da1b64c4Sbluhm	or croak "Fork failed: $!";
66*da1b64c4Sbluhm
67*da1b64c4Sbluhm    unless ($pid) {
68*da1b64c4Sbluhm	# child process
69*da1b64c4Sbluhm	close($parent) or do {
70*da1b64c4Sbluhm	    warn "Close parent socket failed: $!";
71*da1b64c4Sbluhm	    _exit(3);
72*da1b64c4Sbluhm	};
73*da1b64c4Sbluhm	my @cmd = ($ENV{SUDO}, '-C', $child->fileno()+1, $opentap,
74*da1b64c4Sbluhm	    $child->fileno(), $tap_number);
75*da1b64c4Sbluhm	exec(@cmd);
76*da1b64c4Sbluhm	warn "Exec '@cmd' failed: $!";
77*da1b64c4Sbluhm	_exit(3);
78*da1b64c4Sbluhm    }
79*da1b64c4Sbluhm
80*da1b64c4Sbluhm    # parent process
81*da1b64c4Sbluhm    close($child)
82*da1b64c4Sbluhm	or croak "Close child socket failed: $!";
83*da1b64c4Sbluhm    my $tap = recvfd($parent)
84*da1b64c4Sbluhm	or croak "Recvfd failed: $!";
85*da1b64c4Sbluhm    wait()
86*da1b64c4Sbluhm	or croak "Wait failed: $!";
87*da1b64c4Sbluhm    $? == 0
88*da1b64c4Sbluhm	or croak "Child process failed: $?";
89*da1b64c4Sbluhm
90*da1b64c4Sbluhm    return $tap;
91*da1b64c4Sbluhm}
92*da1b64c4Sbluhm
93*da1b64c4Sbluhm1;
94