Alixで作成したブロードバンドルータを再起動した時に、自動でfeel6へ接続しIPv6通信ができるようにしました。 単純にいくつかのスクリプトを作成して、組み合せただけですけどね。
- 修正 & 作成したスクリプトについて
- /usr/local/sbin/yadtcpc.pl
- /usr/local/sbin/ipv6_up.sh
- /usr/local/sbin/ipv6_down.sh
- /etc/network/interfacesファイルの修正
修正 & 作成したスクリプトについて
今回作成したスクリプトは次の通りです。
- /usr/local/sbin/yadtcpc.pl
- /usr/local/sbin/ipv6_up.sh
- /usr/local/sbin/ipv6_down.sh
起動時に呼ばれるスクリプトは"ipv6_up.sh"で、"ipv6_down.sh"は停止時、及び、メンテナンス用のスクリプト。 yadtcpc.plは"ipv6_up.sh"が内部的に呼び出すため、明示的に実行する必要はありません。
/usr/local/sbin/yadtcpc.pl
前回の投稿で紹介したNet::POP3モジュールを使ったDTCPクライアントです。少し変更して、DTCP接続時に渡された情報を標準出力ではなくファイルに出力するようにしました。 接続時には、このファイルから必要な情報を読み取るようにしています。
local=219.xxx.xxx.xxx,remote=43.244.xxx.xx,prefix=2001:03xx:xxxx::,mask=48
また内部では適当なwaitを入れてループしていますが、"/var/run/yadtcpc.control"ファイルから停止の指示があるとquit()により接続を切って全体の処理を中断します。 停止したい場合には$ echo exit | sudo tee /var/run/yadtcpc.controlのようなコマンドを実行します。
前回作成したpackage YADtcpc;はそのまま使い、後ろにあるmain処理全体を次のようなコードで置き換えています。
...
################
## main class ##
################
package Main;
sub new {
my ($class) = @_;
my $self = {
dtcpc => undef,
local => undef,
remote => undef,
prefix => undef,
mask => undef,
feel6_remote => "dtcp.feel6.jp",
feel6_port => 20200,
feel6_id => undef,
feel6_password => undef,
};
bless $self, $class;
return $self;
}
sub connect {
my ($self) = @_;
if($self->{dtcpc}) {
$self->{dtcpc}->quit();
$self->{dtcpc} = undef;
}
$self->{dtcpc} = YADtcpc->new($self->{feel6_remote}, Port=>$self->{feel6_port});
($self->{local}, $self->{remote}, $self->{prefix},$self->{mask}) = $self->{dtcpc}->dtcp($self->{feel6_id}, $self->{feel6_password});
$self;
}
sub write_log {
my ($self, $log_file) = @_;
if(open(LOG, ">$log_file")) {
printf LOG "local=%s,remote=%s,prefix=%s,mask=%s\n", $self->{local}, $self->{remote}, $self->{prefix},$self->{mask};
close(LOG);
}
$self;
}
## for debug purpose only
sub print_log {
my ($self) = @_;
printf "local=%s,remote=%s,prefix=%s,mask=%s\n", $self->{local}, $self->{remote}, $self->{prefix},$self->{mask};
$self;
}
sub ping_pong {
my ($self, $check_file) = @_;
while ($self->{dtcpc}->ping() =~ /pong/i) {
if(open(CHECK, $check_file)) {
my $check = <CHECK>;
if($check =~ /exit/i) {
$self->{dtcpc}->quit();
exit;
}
close(CHECK);
}
sleep 210; ## essential to send 'ping' within five minutes intervales.
}
$self;
}
##########
## main ##
##########
my $main = Main->new();
$main->{feel6_remote} = "dtcp.feel6.jp";
$main->{feel6_port} = 20200;
$main->{feel6_id} = "xxxxxxxx";
$main->{feel6_password} = "xxxxxxxx";
my $info_file = "/var/run/yadtcpc.info";
my $control_file = "/var/run/yadtcpc.control";
do {
$main->connect();
$main->write_log($info_file);
$main->ping_pong($control_file);
sleep 1;
} while(1);
__END__
あとはPIDを"/var/run/yadtcpc.pid"辺りに書き出して、コマンドの起動時に重複起動のチェックをしようかなと思っています。
/usr/local/sbin/ipv6_up.sh
内部では次のような処理を行なっています。
- DTCPクライアント(yadtcpc.pl)の起動
- /var/run/yadtcpc.infoファイルの読み込み
- デフォルトルートの設定
- eth1, eth2へのユニキャストアドレスの設定、及びルーティング
- RAサーバ(radvd)の起動
#!/bin/bash
umask 022
PATH=/sbin:/usr/sbin:/bin:/usr/bin
LANG=C
export PATH LANG
function ipv4to6addr {
## main process
ipv4_1="$(echo $1 | cut -d'.' -f1)"
ipv4_2="$(echo $1 | cut -d'.' -f2)"
ipv4_3="$(echo $1 | cut -d'.' -f3)"
ipv4_4="$(echo $1 | cut -d'.' -f4)"
printf "%02x%02x:%02x%02x\n" "${ipv4_1}" "${ipv4_2}" "${ipv4_3}" "${ipv4_4}"
}
## start the my DTCP client
## - first remove the control file
YADTCPC_FILE=/var/run/yadtcpc.control
test -f ${YADTCPC_FILE} && rm ${YADTCPC_FILE}
## - start the client
/usr/local/sbin/yadtcpc.pl &
## - waiting to finish the DTCP configuration
sleep 5
YADTCPC_FILE=/var/run/yadtcpc.info
if test -f ${YADTCPC_FILE}; then
IPV6_LOCAL="$(cat ${YADTCPC_FILE}|cut -d, -f1|cut -d= -f2)"
IPV6_REMOTE="$(cat ${YADTCPC_FILE}|cut -d, -f2|cut -d= -f2)"
IPV6_PREFIX="$(cat ${YADTCPC_FILE}|cut -d, -f3|cut -d= -f2)"
IPV6_MASK="$(cat ${YADTCPC_FILE}|cut -d, -f4|cut -d= -f2)"
else
exit 1
fi
## setup sit device
ifconfig sit0 up tunnel ::${IPV6_REMOTE} mtu 1454
route -A inet6 del ::/0 dev eth0
DEV_NAME="$(ifconfig | grep ^sit | grep -v sit0 | head -1 | cut -d' ' -f1)"
test "${DEV_NAME}" && route -A inet6 add ::/0 dev "${DEV_NAME}"
## setup network address
DEV1_IP="$(ip -f inet addr show eth1 | tail -1 | awk '{print $2}' | cut -d/ -f1)"
DEV1_NET="$(echo ${IPV6_PREFIX}|sed -e 's/::/:/')1"
ip -f inet6 addr add ${DEV1_NET}::$(ipv4to6addr ${DEV1_IP})/64 dev eth1
ip -f inet6 route add ${DEV1_NET}::/64 dev eth1
DEV2_IP="$(ip -f inet addr show eth2 | tail -1 | awk '{print $2}' | cut -d/ -f1)"
DEV2_NET="$(echo ${IPV6_PREFIX}|sed -e 's/::/:/')10"
ip -f inet6 addr add ${DEV2_NET}::$(ipv4to6addr ${DEV2_IP})/64 dev eth2
ip -f inet6 route add ${DEV2_NET}::/64 dev eth2
## start radvd
INIT_RADVD=/etc/init.d/radvd
if test -f ${INIT_RADVD}; then
${INIT_RADVD} start
fi
/usr/local/sbin/ipv6_down.sh
内部の処理は、ほぼ起動時の処理の逆ですが、既にLAN内部でIPv6を使った接続済みのセッションを切断しないようにデバイスのIPv6アドレス、及び、ルーティング情報は削除していません。
#!/bin/bash
umask 022
LANG=C
PATH=/sbin:/bin:/usr/bin/:/usr/sbin
export LANG PATH
if test -f /var/run/yadtcpc.info; then
IPV6_LOCAL="$(cat /var/run/yadtcpc.info|cut -d, -f1|cut -d= -f2)"
IPV6_REMOTE="$(cat /var/run/yadtcpc.info|cut -d, -f2|cut -d= -f2)"
IPV6_PREFIX="$(cat /var/run/yadtcpc.info|cut -d, -f3|cut -d= -f2)"
IPV6_MASK="$(cat /var/run/yadtcpc.info|cut -d, -f4|cut -d= -f2)"
fi
## stop the my DTCP client
echo exit > /var/run/yadtcpc.control
## list up sit+ devices other than sit0
DEV_LIST="$(ifconfig | grep ^sit | grep -v sit0 | cut -d' ' -f1)"
## stop radvd
INIT_RADVD=/etc/init.d/radvd
if test -f ${INIT_RADVD}; then
${INIT_RADVD} stop
fi
## down devices
for sit_dev in ${DEV_LIST}
do
route -A inet6 del ::/0 dev ${sit_dev}
ip link set ${sit_dev} down
ip tunnel del ${sit_dev}
done
/etc/network/interfacesファイルの修正
ファイルを配置してから、interfacesファイルを編集します。 再起動の後で$ ping6 www.kame.netが成功する事を確認しています。
auto dsl-provider
iface dsl-provider inet ppp
pre-up /sbin/ifconfig eth0 up # line maintained by pppoeconf
provider dsl-provider
post-up /usr/local/sbin/config_iptables.sh
post-up /usr/local/sbin/config_ip6tables.sh
post-up /usr/local/sbin/ipv6_up.sh
pre-down /usr/local/sbin/ipv6_down.sh
0 件のコメント:
コメントを投稿