#!@RUBY@
#
# dtcpc, Turmpet Dynamic Tunnel Configuration Protocol client
#
#
# Copyright (c) 2000-2006 Hajimu UMEMOTO <ume@mahoroba.org>
# All rights reserved.
#
# Copyright (C) 1999 WIDE Project.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# 3. Neither the name of the project nor the names of its contributors
# may be used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
# $Id: dtcpc.rb,v 1.3 2000/05/27 11:45:02 jinmei Exp $
# $Mahoroba: src/dtcp/dtcpc.rb,v 1.73 2006/01/08 18:24:01 ume Exp $
#
require 'getopts'
require "socket"
require "md5"
require 'syslog'
TIMEOUT = 60
DEBUG = false
PASSWDFILE = '@PREFIX@/etc/dtcpc.auth'
PIDFILE = '/var/run/dtcpc.pid'
UDP_TUNNEL_PORT = 4028
ROUTE_GATEWAY = 0
ROUTE_CHANGE = 1
ROUTE_INTERFACE = 2
ROUTE_IFP = 3
# NetBSD 1.6 or later
#TUNIF = "gif0"
#TUNIF_CLONING = true
#TUNNEL_CREATE = 'ifconfig %s tunnel %s %s'
#TUNNEL_DELETE = 'ifconfig %s deletetunnel'
#ROUTE_METHOD = ROUTE_IFP
#
# NetBSD 1.5.x or earlier
# and OpenBSD
#TUNIF = "gif0"
#TUNIF_CLONING = false
#TUNNEL_CREATE = 'ifconfig %s tunnel %s %s'
#TUNNEL_DELETE = 'ifconfig %s deletetunnel'
#ROUTE_METHOD = ROUTE_CHANGE
#
# FreeBSD 4.6-RELEASE or later
#TUNIF = "gif"
#TUNIF_CLONING = true
#TUNNEL_CREATE = 'ifconfig %s tunnel %s %s'
#TUNNEL_DELETE = 'ifconfig %s deletetunnel'
#ROUTE_METHOD = ROUTE_IFP
##ROUTE_METHOD = ROUTE_INTERFACE
#
# FreeBSD 4.4-RELEASE or 4.5-RELEASE
#TUNIF = "gif"
#TUNIF_CLONING = true
#TUNNEL_CREATE = 'ifconfig %s tunnel %s %s'
#TUNNEL_DELETE = 'ifconfig %s deletetunnel'
#ROUTE_METHOD = ROUTE_GATEWAY
#
# FreeBSD 4.3-RELASE or earlier
#TUNIF = "gif0"
#TUNIF_CLONING = false
#TUNNEL_CREATE = 'gifconfig %s %s %s'
#TUNNEL_DELETE = 'gifconfig %s delete'
#ROUTE_METHOD = ROUTE_GATEWAY
#
TUNIF = '@DTCPC_TUNIF@'
TUNIF_CLONING = true
TUNNEL_CREATE = 'ifconfig %s tunnel %s %s'
TUNNEL_DELETE = 'ifconfig %s deletetunnel'
ROUTE_METHOD = ROUTE_IFP
def usage()
$stderr.print "usage: #{File.basename($0)} [-cdDlnU] [-b udpport] [-i if] [-m mtu] [-p port] [-t tuntype] [-u username] [-A addr] [-R dest] [-P prefix-delegation] server\n"
end
class PDInfo
attr_accessor :iface
attr_accessor :slaid
attr_accessor :hostid
attr_accessor :prefixlen
private
def initialize(iface, slaid, hostid, prefixlen)
@iface = iface
@slaid = slaid
@hostid = (hostid == '') ? nil : hostid
@prefixlen = prefixlen ? prefixlen.to_i : 64
end
end
class PrefixDelegation
PrefixNew = 1
PrefixExist = 2
PrefixNoChange = 3
def update(prefixes)
if @pdinfo.size <= 0
return
end
prefixes.each { |prefix|
if @prefixes.has_key?(prefix)
@prefixes[prefix] = PrefixNoChange
else
@prefixes[prefix] = PrefixNew
end
}
@prefixes.each { |prefix, state|
case state
when PrefixNew
add_prefix(prefix)
@prefixes[prefix] = PrefixExist
when PrefixNoChange
@prefixes[prefix] = PrefixExist
else
delete_prefix(prefix)
@prefixes.delete(prefix)
end
}
if !@rtadvd_running
if !@forwarding_enabled
@old_forwarding = `sysctl -n net.inet6.ip6.forwarding`.chop
execute("sysctl -w net.inet6.ip6.forwarding=1")
@forwarding_enabled = true
end
if !@rtadvd_disable
@old_accept_rtadv = `sysctl -n net.inet6.ip6.accept_rtadv`.chop
execute("sysctl -w net.inet6.ip6.accept_rtadv=0")
execute("rtadvd #{@rtadvd_interfaces}")
@rtadvd_running = true
@rtadvd_invoked = true
end
end
end
def cleanup(*keep)
if @pdinfo.size <= 0
return
end
if !keep[0]
update([])
if @rtadvd_invoked
open("/var/run/rtadvd.pid", 'r') { |p|
Process.kill("SIGTERM", p.readline.to_i)
}
execute("sysctl -w net.inet6.ip6.accept_rtadv=#{@old_accept_rtadv}")
@rtadvd_running = false
@rtadvd_invoked = false
end
if @forwarding_enabled
execute("sysctl -w net.inet6.ip6.forwarding=#{@old_forwarding}")
@forwarding_enabled = false
end
end
end
private
def initialize(pdinfos, *rtadvd_disable)
@prefixes = {}
@pdinfo = []
pdinfos.each { |pdinfo|
iface, slaid, hostid, prefixlen = pdinfo.split('/')
@pdinfo.push(PDInfo.new(Interface.new(iface), slaid, hostid, prefixlen))
}
if @pdinfo.size <= 0
return
end
@forwarding_enabled = false
@rtadvd_invoked = false
@rtadvd_running = rtadvd_running?
@rtadvd_interfaces = rtadvd_interfaces
@rtadvd_disable = (rtadvd_disable[0] || @rtadvd_interfaces =~ /^\s*$/)
end
def rtadvd_running?
`ps ax`.each { |s|
if s.scan(/rtadvd/).size > 0
return true
end
}
return false
end
def rtadvd_interfaces
ifaces = []
@pdinfo.each { |pdinfo|
if pdinfo.prefixlen < 128
ifaces.push(pdinfo.iface.name)
end
}
return ifaces.uniq.join(' ')
end
def addr_to_nla(addr)
nla_ary = addr.split(':')[0..3]
(0..3).each { |i|
if !nla_ary[i] || nla_ary[i] == ''
nla_ary[i] = '0'
end
}
return nla_ary
end
def to_addr(nla_ary, slaid, hostid)
nla = [nla_ary[0..2], sprintf("%x", nla_ary[3].hex + slaid.hex)].join(':')
if hostid
addr = "#{nla}:#{hostid}"
else
addr = "#{nla}:: eui64"
end
return addr
end
def add_prefix(prefix)
addr, prefixlen = prefix.split('/')
execute("route add -inet6 #{addr} -prefixlen #{prefixlen} ::1 -reject")
nla_ary = addr_to_nla(addr)
@pdinfo.each { |pdinfo|
hostid = pdinfo.hostid ? pdinfo.hostid : pdinfo.iface.hostid
addr = to_addr(nla_ary, pdinfo.slaid, hostid)
pdinfo.iface.addaddr("#{addr} prefixlen #{pdinfo.prefixlen}")
}
end
def delete_prefix(prefix)
addr, prefixlen = prefix.split('/')
execute("route delete -inet6 #{addr} -prefixlen #{prefixlen} ::1 -reject")
nla_ary = addr_to_nla(addr)
@pdinfo.each { |pdinfo|
hostid = pdinfo.hostid ? pdinfo.hostid : pdinfo.iface.hostid
addr = to_addr(nla_ary, pdinfo.slaid, hostid)
pdinfo.iface.deladdr("#{addr} prefixlen #{pdinfo.prefixlen}")
}
end
end
def daemon(nochdir, noclose)
pid = fork
if pid == -1
return -1
elsif pid != nil
exit 0
end
Process.setsid()
Dir.chdir('/') if (nochdir == 0)
if noclose == 0
devnull = open("/dev/null", "r+")
$stdin.reopen(devnull)
$stdout.reopen(devnull)
$stderr.reopen(devnull)
end
return 0
end
def authenticate(user, seed, pass)
m = MD5.new(user)
m.update(seed)
m.update(pass)
return m.digest.unpack("H32")[0].tr('a-f', 'A-F')
end
def logmsg(msg)
if $syslog.opened?
$syslog.notice('%s', msg)
else
$stderr.print msg
end
end
def debugmsg(msg)
logmsg(msg) if ($debug)
end
def execute(cmd)
logmsg("#{cmd}\n")
system(cmd)
end
def getpassword_file(dst, user)
if not File.exist?(PASSWDFILE)
debugmsg("no authinfo file found\n")
return nil
end
if not File.readable?(PASSWDFILE)
debugmsg("no permission to read authinfo file\n")
return nil
end
open(PASSWDFILE, 'r') { |p|
p.each_line { |l|
d, u, passwd = l.chop.split(":")
if d == dst && u == user
debugmsg("ok, relevant authinfo item found\n")
return passwd
end
}
}
debugmsg("no relevant authinfo item found\n")
return nil
end
def getpassword(dst, username)
password = getpassword_file(dst, username)
if password == nil
open('/dev/tty', 'r') { |tty|
system("stty -echo")
$stderr.print "password for #{username}: "
password = tty.readline
}
system("stty sane")
$stderr.print "\n"
end
return password.chomp
end
class Route
def setup(dstif)
case @type
when "static"
@static_routes.split(/\s*,\s*/).each { |static_route|
execute("route delete -inet6 #{static_route} > /dev/null 2>&1")
cmd = route_add(static_route, dstif)
if !cmd
exit 1
end
execute(cmd)
}
when "solicit"
execute("rtsol #{dstif.name}")
end
end
def delete
if @type == "static"
@static_routes.split(/\s*,\s*/).each { |static_route|
execute("route delete -inet6 #{static_route}")
}
end
end
private
def initialize(type, static_routes)
@type = type
@static_routes = static_routes
end
def route_add(dest, tunif)
case ROUTE_METHOD
when ROUTE_CHANGE
cmd = "route add -inet6 #{dest} ::1; route change -inet6 #{dest} -ifp #{tunif.name}"
when ROUTE_INTERFACE
cmd = "route add -inet6 #{dest} -interface #{tunif.name}"
when ROUTE_IFP
cmd = "route add -inet6 #{dest} ::1 -ifp #{tunif.name}"
else
laddr = tunif.linklocal
if !laddr
logmsg("FATAL: cannot get link-local address of #{tunif.name}\n")
return nil
end
cmd = "route add -inet6 #{dest} #{laddr}"
end
return cmd
end
end
class Interface
attr :name
def up
execute("ifconfig #{@name} up")
end
def down
execute("ifconfig #{@name} down")
end
def addaddr(addr)
execute("ifconfig #{@name} inet6 #{addr} alias")
end
def deladdr(addr)
execute("ifconfig #{@name} inet6 #{addr} -alias")
end
def setmtu(mtu = 1500)
execute("ifconfig #{@name} mtu #{mtu}")
end
def linklocal
`ifconfig #{@name} inet6`.each { |s|
if s =~ /inet6 (fe80::[^ ]*)/
return $1
end
}
return nil
end
def hostid
laddr = linklocal
if !laddr
return nil
end
return laddr.sub(/^fe80::/, '').sub(/%.*$/, '')
end
private
def initialize(name)
@name = name
end
end
class ClonedInterface < Interface
def create
@name = @tunif
if @cloning
cmd = sprintf("ifconfig %s create", @name)
debugmsg("#{cmd}\n")
`#{cmd}`.each { |l|
if l =~ /^(#{@name}[0-9]+)/
@name = $1
break
end
}
end
@created = true
end
def created?
return @created
end
def delete
if @cloning && !@create_only
execute(sprintf("ifconfig %s destroy", @name))
end
@created = false
end
private
def initialize(tunif, cloning, create_only)
@tunif = tunif
@cloning = cloning
@create_only = create_only
@created = false
end
end
class GenericTunnel < ClonedInterface
def create(me, her)
super()
execute(sprintf(TUNNEL_CREATE, @name, me, her))
up
end
def delete
down
execute(sprintf(TUNNEL_DELETE, @name))
super
end
def addpeer(me, her)
execute("ifconfig #{@name} inet6 #{me} #{her} prefixlen 128 alias")
end
def delpeer(me, her)
execute("ifconfig #{@name} inet6 #{me} #{her} prefixlen 128 -alias")
end
def setmtu(mtu = 1280)
super(mtu)
end
end
class NetgraphInterface < Interface
def create
if !@tunif || @tunif == "ng"
@name = mkpeer
@created = true
return
end
if @tunif !~ /^ng([0-9]+)$/
raise "#{@tunif}: wrong name"
end
unitmax = $1.to_i
shutdown(@tunif)
bogus = Array.new
while TRUE
@name = mkpeer
if @name == @tunif
@created = true
break
end
bogus.push(@name)
if @name !~ /^ng([0-9]+)$/
raise "#{@name}: wrong name"
end
unit = $1.to_i
if unit > unitmax
raise "#{@name}: not expected"
end
end
bogus.each { |iface|
shutdown(iface)
}
end
def created?
return @created
end
def delete
shutdown(@name)
@created = false
end
private
def initialize(tunif = nil)
@tunif = tunif
@created = false
end
def mkpeer()
iface = nil
f = IO.popen("ngctl -f - 2> /dev/null", "w+")
f.write("mkpeer iface dummy inet6\n")
f.write("msg dummy nodeinfo\n")
f.write("quit\n")
f.flush
f.each_line { |line|
if line =~ / name="(ng[0-9]+)"/
iface = $1
break
end
}
f.close
if !iface
raise "ngctl failed"
end
return iface
end
def shutdown(iface = nil)
if !iface
iface = @name
end
execute("ngctl shutdown #{iface}: >/dev/null 2>&1")
end
end
class UDPTunnel < NetgraphInterface
def create(me, her)
me_addr, me_port = me.split(';')
her_addr, her_port = her.split(';')
super()
if !ksocket
raise "ngctl: mkpeer ksocket fail"
end
if !bind(me_addr, me_port)
raise "ngctl: bind fail addr=#{me_addr} port=#{me_port}"
end
if !connect(her_addr, her_port)
raise "ngctl: connect fail addr=#{her_addr} port=#{her_port}"
end
up
end
def delete
down
super
end
def addpeer(me, her)
execute("ifconfig #{@name} inet6 #{me} #{her} prefixlen 128 alias")
end
def delpeer(me, her)
execute("ifconfig #{@name} inet6 #{me} #{her} prefixlen 128 -alias")
end
private
def ksocket()
execute("ngctl mkpeer #{@name}: ksocket inet6 inet/dgram/udp")
end
def bind(addr, port)
execute("ngctl msg #{@name}:inet6 bind inet/#{addr}:#{port}")
end
def connect(addr, port)
execute("ngctl msg #{@name}:inet6 connect inet/#{addr}:#{port}")
end
end
class TunnelOnly
attr_accessor :me
attr_accessor :her
attr_accessor :mtu
def setup(intface)
@intface = intface
intface.create(@me, @her)
if @mtu > 0
intface.setmtu(@mtu)
end
end
def delete
if @mtu > 0
@intface.setmtu
end
@intface.delete
end
private
def initialize(me, her)
@me = me
@her = her
end
end
class TunnelHost < TunnelOnly
attr_accessor :me6
attr_accessor :her6
def setup(intface)
super
@intface.addpeer(@me6, @her6)
end
def delete
@intface.delpeer(@me6, @her6)
super
end
private
def initialize(me, her, me6, her6)
super(me, her)
@me6 = me6
@her6 = her6
end
end
class TunnelNetwork < TunnelOnly
attr_accessor :prefix
attr_accessor :me6
attr_accessor :her6
def setup(intface)
super
if @me6
@intface.addpeer(@me6, @her6)
end
end
def delete
if @me6
@intface.delpeer(@me6, @her6)
end
super
end
private
def initialize(me, her, prefix, me6 = nil, her6 = nil)
super(me, her)
@prefix = prefix
@me6 = me6
@her6 = her6
end
end
def sendmsg(sock, msg)
sock.print "#{msg}\r\n"
debugmsg(">>#{msg}\n")
end
class DTCPClient
def session
connect_to(@dst, @port) { |sock, server|
begin
me = sock.addr()[3]
logmsg("logging in to #{server[3]} port #{server[1]}\n")
# get greeting
begin
t = sock.readline
rescue
return
end
debugmsg(">>#{t}")
challenge = t.split(/ /)[1]
#logmsg("authenticate(#{@username} #{challenge} #{@password}): ")
response = authenticate(@username, challenge, @password)
#logmsg("#{response\n")
t = "tunnel #{@username} #{response} #{@tuntype}"
if @mtu > 0
t.concat(" #{@mtu}")
end
if @udp_tunnel
t.concat(" proto=udp")
if !@behind_nat
t.concat(" port=#{@udp_tunnel_port}")
end
end
sendmsg(sock, t)
begin
t = sock.readline
rescue
return
end
debugmsg(">>#{t}")
if (t !~ /^\+OK/)
t.gsub!(/[\r\n]*$/, '')
logmsg("failed, reason: #{t}")
if (t =~ /^\-ERR authentication/)
exit 1
end
return
end
t.gsub!(/[\r\n]/, '')
tun = t.split(/ /)
if @behind_nat
tun[1] = me
elsif me != tun[1]
logmsg("failed, you are behind a NAT box (#{me} != #{tun[1]})\n")
exit 1
end
if @udp_tunnel
tun[1].concat(";#{@udp_tunnel_port}")
end
case tun.length
when 3
@tunnel = TunnelOnly.new(tun[1], tun[2])
when 4
@tunnel = TunnelNetwork.new(tun[1], tun[2], tun[3])
when 5
@tunnel = TunnelHost.new(tun[1], tun[2], tun[3], tun[4])
when 6
@tunnel = TunnelNetwork.new(tun[1], tun[2], tun[5], tun[3], tun[4])
else
return
end
@tunnel.mtu = @mtu
# hook after session is established
begin
yield(@tunnel)
rescue
end
keep_alive(sock)
ensure
begin
sendmsg(sock, "quit")
rescue
end
end
}
end
def cleanup()
# hook for cleanup
begin
yield(@tunnel)
rescue
end
@tunnel = nil
end
private
def initialize(dst, port, username, password, tuntype, behind_nat, mtu = 0, udp_tunnel = false, udp_tunnel_port = 0)
@dst = dst
@port = port
@username = username
@password = password
@tuntype = tuntype
@mtu = mtu
@udp_tunnel = udp_tunnel
@udp_tunnel_port = udp_tunnel_port
@behind_nat = behind_nat
@tunnel = nil
end
def connect_to(dst, port)
res = []
begin
res = Socket.getaddrinfo(dst, port,
Socket::PF_INET, Socket::SOCK_STREAM, nil)
rescue
logmsg("FATAL: getaddrinfo failed (dst=#{dst} port=#{port})\n")
return
end
if (res.size <= 0)
logmsg("FATAL: getaddrinfo failed (dst=#{dst} port=#{port})\n")
return
end
sock = nil
begin
server = []
res.each do |i|
begin
sock = TCPsocket.open(i[3], i[1])
rescue
next
end
server = i
break
end
if server == []
logmsg("could not connect to #{dst} port #{port}\n")
return
end
yield(sock, server)
ensure
if sock
begin
sock.shutdown(1)
rescue
end
begin
sock.close
rescue
end
end
end
end
def keep_alive(sock)
begin
while TRUE
debugmsg("sleep(60)\n")
sleep 60
sendmsg(sock, "ping")
t = select([sock], [], [sock], TIMEOUT)
if t == nil
break
end
if sock.eof?
break
end
response = sock.readline
debugmsg(">>#{response}")
end
rescue
end
end
end
#------------------------------------------------------------
port = 20200
username = `whoami`.chomp
ousername = username
password = ''
tunif = TUNIF
cloning = TUNIF_CLONING
tuntype = 'tunnelonly'
route_type = 'static'
static_routes = 'default'
tunif_addrs = ''
prefix_delegation = ''
$debug = DEBUG
mtu = 0
udp_tunnel_port = UDP_TUNNEL_PORT
behind_nat = false
pidfile = PIDFILE
# # test pattern
# challenge = '0B1517C87D516A5FA65BED722D51A04F'
# response = authenticate('foo', challenge, 'bar')
# if response == 'DAC487C8DFBBF9EE5C7F8CDCC37B62A3'
# logmsg("good!\n")
# else
# logmsg("something bad in authenticate()\n")
# end
# exit 0
if !getopts('acdDlnoU', 'A:', 'b:', 'f:', 'i:', 'm:', 'p:', 'P:', 'r:', 'R:', 't:',
'u:')
usage()
exit 0
end
if ARGV.length != 1
usage()
exit 1
end
rtadvd_disable = $OPT_a
tunif_addrs = $OPT_A if $OPT_A
udp_tunnel_port = $OPT_b if $OPT_b
cloning = false if $OPT_c
$debug = $OPT_d
daemonize = $OPT_D
pidfile = $OPT_f if $OPT_f
tunif = $OPT_i if $OPT_i
loop = $OPT_l
mtu = $OPT_m.to_i if $OPT_m
behind_nat = $OPT_n
create_only = $OPT_o
port = $OPT_p if $OPT_p
prefix_delegation = $OPT_P if $OPT_P
route_type = $OPT_r if $OPT_r
static_routes = $OPT_R if $OPT_R
tuntype = $OPT_t if $OPT_t
username = $OPT_u if $OPT_u
udp_tunnel = $OPT_U
dst = ARGV[0]
if udp_tunnel && tunif !~ /^ng([0-9]+)?$/
tunif = "ng"
end
trap("SIGTERM", "EXIT")
trap("SIGINT", "EXIT")
trap("SIGHUP", "SIG_IGN")
$syslog = Syslog.instance
if daemonize
daemon(0, 0)
$syslog.open(File.basename($0), Syslog::LOG_PID, Syslog::LOG_DAEMON)
logmsg("start")
open(pidfile, 'w') { |p|
p.print "#{$$}\n"
}
end
begin
password = getpassword(dst, username)
pd = nil
begin
if udp_tunnel
intface = UDPTunnel.new(tunif)
else
intface = GenericTunnel.new(tunif, cloning, create_only)
end
route = Route.new(route_type, static_routes)
pd = PrefixDelegation.new(prefix_delegation.split(/\s*,\s*/),
rtadvd_disable)
dtcpc = DTCPClient.new(dst, port, username, password, tuntype, behind_nat,
mtu, udp_tunnel, udp_tunnel_port)
while TRUE
interrupt = nil
begin
trap("SIGHUP") {
raise(Interrupt, "SIGHUP")
}
dtcpc.session { |tunnel|
tunnel.setup(intface)
logmsg("tunnel to #{tunnel.her} established.\n")
route.setup(intface)
logmsg("default route was configured.\n")
tunif_addrs.split(/\s*,\s*/).each { |addr|
intface.addaddr(addr)
}
# prefix delegation
if tunnel.instance_of?(TunnelNetwork)
pd.update(tunnel.prefix.split(/\s*,\s*/))
end
}
rescue Interrupt => e
if e.to_str != "SIGHUP"
raise e
end
interrupt = e
ensure
trap("SIGHUP", "SIG_IGN")
dtcpc.cleanup { |tunnel|
if intface.created?
tunif_addrs.split(/\s*,\s*/).each { |addr|
intface.deladdr(addr)
}
route.delete
tunnel.delete
end
}
end
unless loop
break
end
if interrupt
logmsg("restart by SIGHUP.\n")
else
logmsg("connection was lost.\n")
sleep(10)
end
end
ensure
if pd
pd.cleanup
end
end
ensure
if daemonize
begin
pid = -1
open(pidfile, 'r') { |p|
pid = p.readline.to_i
}
if pid == $$
File.unlink(pidfile)
end
rescue
end
logmsg("exit\n")
end
end
exit 0
syntax highlighted by Code2HTML, v. 0.9.1