summaryrefslogtreecommitdiff
path: root/scripts/vyatta-vti-config.pl
blob: cbbde329e421aea9addb6a915bfde76300e3055a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
#!/usr/bin/perl -w
#
# Module: vyatta-vti-config.pl
#
# **** License ****
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# General Public License for more details.
#
# This code was originally developed by Vyatta, Inc.
# Portions created by Vyatta are Copyright (C) 2006, 2007, 2008, 2009 Vyatta, Inc.
# All Rights Reserved.
#
# Authors: Saurabh Mohan
# Date: 2012
# Description: setup the vti tunnel
#
# **** End License ****
#
#
# For each VTI tunnel (vpn ipsec site-to-site peer ip-address sti); find the vti tunnel, local address, mark.
#   Find the corresponding tunnel (interfaces vti vtiXXX), tunnel address, disable, mtu
#        if not configured: ip tunnel add vtiXXX mode esp local $local remote $remote i_key $mark
#                           if (mtu): configure mtu
#                           if (tunnel-addres): configur ip link vtiXXX address
#                           if (!disable): enable the interface.
#

use strict;
use lib "/opt/vyatta/share/perl5";

use Getopt::Long;


my $vti_cfg_err = "VPN VTI configuration error:";
my $gencmds = "";
my $result = 0;
my $updown="";
my $intfName="";
my $action="";
my $checkref="";

GetOptions(
    "updown" => \$updown,
    "intf=s"   => \$intfName,
    "action=s" => \$action,
    "checkref" => \$checkref,
);


#
# --updown intfName --action=[up|down]
#
if ($updown ne '') {
    if (!(defined $intfName) || $intfName eq '' ) {
        # invalid
        exit -1;
    }
    if (!(defined $action) || $action eq '' ) {
        # invalid
        exit -1;
    }
    vti_handle_updown($intfName, $action);
    exit 0;
}

#
# --checkref --intf=<intfName>
# Return 1 if the interface reference exits.
#
if ($checkref ne '' ) {
    if (!(defined $intfName) || $intfName eq '' ) {
        # invalid
        exit -1;
    }
    my $rval = vti_check_reference($intfName);
    exit $rval;
}

#
# Prepare Vyatta::Config object
#
use Vyatta::Config;
my $vcIntf = new Vyatta::Config();
my $vcVPN  = new Vyatta::Config();
$vcVPN->setLevel('vpn');
$vcIntf->setLevel('interfaces');

if (!$vcVPN->exists('ipsec') ) {
    exit $result;
}
if (!$vcVPN->exists('ipsec site-to-site') ) {
    exit $result;
}

my @peers = $vcVPN->listNodes('ipsec site-to-site peer');
if (@peers == 0) {
    exit $result;
}
    foreach my $peer (@peers) {
        if (! $vcVPN->exists("ipsec site-to-site peer $peer vti")) {
            next;
        }
        #
        # we have the vti configured.
        #
        my $lip = $vcVPN->returnValue("ipsec site-to-site peer $peer local-address");
        my $mark = $vcVPN->returnValue("ipsec site-to-site peer $peer vti mark");
        my $tunName = $vcVPN->returnValue("ipsec site-to-site peer $peer vti bind");

        # Check local address is valid.
        if (!defined($lip)) {
            print STDERR "$vti_cfg_err local-address not defined.\n";
            exit -1;
        }

        if ($lip eq "" || $lip eq "0.0.0.0") {
            print STDERR "$vti_cfg_err Invalid local-address \"$lip\".\n";
            exit -1;
        }
        # Check tunName is valid.
        if (!defined($tunName) || $tunName eq ""  || ! $vcIntf->exists("vti $tunName") ) {
            print STDERR "$vti_cfg_err Invalid tunnel name vti \"$tunName\".\n";
            exit -1;
        }
        # Check mark is valid.
        if (!defined($mark)) {
            print STDERR "$vti_cfg_err mark not defined.\n";
            exit -1;
        }
        if ($mark eq "" || $mark eq "0") {
            print STDERR "$vti_cfg_err Invalid mark \"$mark\".\n";
            exit -1;
        }
        #
        # Get the tunnel parameters.
        #
        # ip address's
        my @tunIPs = $vcIntf->returnValues("vti $tunName address");
        # mtu
        my $mtu = $vcIntf->returnValue("vti $tunName mtu");
        if (!defined($mtu) || $mtu eq "") {
            $mtu = 1500;
        }
        #my $exists = `ls -l /sys/class/net/$tunName &> /dev/null`;

        # description.
        my $description = $vcIntf->returnValue("vti $tunName description");

        #
        # Set the configuration into the output string.
        #
        # By default we delete the tunnel...
        $gencmds .= "sudo /sbin/ip link delete $tunName &> /dev/null\n";
        $gencmds .= "sudo /opt/vyatta/sbin/cfgvti add name $tunName key $mark remote $peer local $lip\n";
        foreach my $tunIP (@tunIPs) {
            $gencmds .= "sudo /sbin/ip addr add $tunIP dev $tunName\n";
        }
        $gencmds .= "sudo /sbin/ip link set $tunName mtu $mtu\n";

        if (defined($description)) {
            $gencmds .= "if [ -d /sys/class/net/$tunName ] ; then\n\tsudo echo \"$description\" > /sys/class/net/$tunName/ifalias\nfi\n";
        }
    }

if ($gencmds ne "") {
    open my $output_config, '>', '/tmp/vti_config' or die "Can't open /tmp/vti_config $!";
    print ${output_config} "#!/bin/sh\n";
    print ${output_config} $gencmds;
    close $output_config;
    `chmod 755 /tmp/vti_config`;
    system("/tmp/vti_config");
    $result = $? >> 8;
    #@SM TODO: remove /tmp/vti_config;
}
exit $result;


#
# Handle VTI tunnel state based on input from strongswan and configuration.
#
sub vti_handle_updown {
    my ($intfName, $action) = @_;
    use Vyatta::Config;
    my $vcIntf = new Vyatta::Config();
    $vcIntf->setLevel('interfaces');
    my $disabled = $vcIntf->existsOrig("vti $intfName disabled");
    if (!defined($disabled) || ! $disabled) {
        system("sudo /sbin/ip link set $intfName $action\n");
    }
}

sub vti_check_reference {
    my ($intfName) = @_;
    use Vyatta::Config;
    my $vcVPN = new Vyatta::Config();
    $vcVPN->setLevel('vpn ipsec site-to-site');
    my @peers = $vcVPN->listNodes('peer');
    if (@peers == 0) {
        return 0;
    }
    foreach my $peer (@peers) {
        if (! $vcVPN->exists("peer $peer vti")) {
            next;
        }
        if ( $vcVPN->exists("peer $peer vti bind $intfName")) {
            return 1;
        }
    }
    return 0;
}