解き放たれしソフトウェア

GNU/LinuxなどFLOSSについて書いてみるつもり

【Gentoo】ppp の ip-up / ip-down が異なる

問題

pppd によるPPP接続時に自動でスクリプトを実行させるフックとして、 /etc/ppp/ip-up /etc/ppp/ip-down があります。 しかし、Gentoo の /etc/ppp/ip-up /etc/ppp/ip-down は、net-dialup/ppp-scripts パッケージで提供されており、独自のスクリプト*1になっています。

だから例えばいくつかのウェブサイトに、 「pppd のオプションとして ipparam ipv6default と書いて、/etc/ppp/ipv6-up.d/ 内にシェルスクリプトファイルを作成して

#!/bin/sh
if [ -z "${CONNECT_TIME}" ]; then
    if [ "${PPP_IPPARAM}" = "ipv6default" ]; then
        ip -6 route add default dev ${PPP_IFACE}
    fi
fi

と書いて chmod +x しろ」 という説明が書いてありますが *2、これは Gentoo では動きません。

なお、ipparam というのは ip-up / ip-down のスクリプトに渡すパラメータを増設するための pppd のオプションです。

man 8 pppd

ipparam string
  ip-up と ip-down スクリプト用に余分のパラメータを指定します。 
  このオプションが与えられた場合、 string が 6 番目のパラメータとして、
  これらのスクリプトに与えられます。

解答

ともかく、 Gentoo の ip-up は、

#!/bin/sh

# This script is run by pppd after the link is established.
# It executes all the scripts available in /etc/ppp/ip-up.d directory,
# with the following parameters:
# $1 = interface name (e.g. ppp0)
# $2 = tty device
# $3 = speed
# $4 = local IP address
# $5 = remote IP address
# $6 = ipparam (user specified parameter, see man pppd)

cd /etc/ppp/ip-up.d || exit

for SCRIPT in *.sh ; do
        . ./"${SCRIPT}" "$@"
done

ですので、${PPP_IPPARAM} ではなく ${6} です。 ${PPP_IFACE} ではなく、 ${1} です。

さらに、Gentoo では、

  • /etc/ppp/ipv6-up.d と /etc/ppp/ipv6-down.d はそれぞれ ip-up.d と ip-down.d のシンボリックリンクなので、IPv4 用と IPv6 用にディレクトリが分かれてはいない
  • ip-up と ip-down は、該当ディレクトリの *.sh の中身を読み込むので、 chmod +x は要らない。もしも無効にしたいときはファイル名を変更すればよい

そのため例えば、/etc/ppp/ipv6-up.d/60-routing.sh というファイル名にでもして、

if [ "x${6}" = "xipv6default" ]
then /bin/ip -6 r a default dev "${1}"
fi

と書けばよいわけです。属性は r さえついていれば、x は要りません(あっても動きますが)。shebang も要らない(あっても動きますが)。

This script is run by pppd after the link is established

なので、[ -z "${CONNECT_TIME}" ] も要らないはず。

Gentoo Wiki の情報が全く足りない! たぶん「いまどき PPP なんかせずにルータだろ」or「こんなことしようとする猛者は、読めばわかるだろ、スクリプトなんだから」ということなのでしょう

補足

ちなみに、冒頭の例の [ "${PPP_IPPARAM}" = "ipv6default" ] は厳密には間違え。
参考:

それにまあ、if の入れ子構造でなくとも if [ -z "${CONNECT_TIME}" -a "x${PPP_IPPARAM}" = "xipv6default" ] 〜でいいはずですが、これ。

あ。そもそも iproute2 が無くて net-tools があったらどうなるだろ。ip 無いし(笑)。勿論 route ですが。

オチ

冒頭の例は、 Debian の ppp パッケージに入っている ip-up / ip-down で動かすためのスクリプトです。

#!/bin/sh
#
# This script is run by the pppd after the link is established.
# It uses run-parts to run scripts in /etc/ppp/ip-up.d, so to add routes,
# set IP address, run the mailq etc. you should create script(s) there.
#
# Be aware that other packages may include /etc/ppp/ip-up.d scripts (named
# after that package), so choose local script names with that in mind.
#
# This script is called with the following arguments:
#    Arg  Name                          Example
#    $1   Interface name                ppp0
#    $2   The tty                       ttyS1
#    $3   The link speed                38400
#    $4   Local IP number               12.34.56.78
#    $5   Peer  IP number               12.34.56.99
#    $6   Optional ``ipparam'' value    foo

# The  environment is cleared before executing this script
# so the path must be reset
PATH=/usr/local/sbin:/usr/sbin:/sbin:/usr/local/bin:/usr/bin:/bin
export PATH

# These variables are for the use of the scripts run by run-parts
PPP_IFACE="$1"
PPP_TTY="$2"
PPP_SPEED="$3"
PPP_LOCAL="$4"
PPP_REMOTE="$5"
PPP_IPPARAM="$6"
export PPP_IFACE PPP_TTY PPP_SPEED PPP_LOCAL PPP_REMOTE PPP_IPPARAM

Debian の /etc/ppp/ip-up の冒頭は上記のようになっていますです。 シェルスクリプトの読込みも

run-parts /etc/ppp/ip-up.d \
  --arg="$1" --arg="$2" --arg="$3" --arg="$4" --arg="$5" --arg="$6"

run-parts ですんで。

run-parts は、ディレクトリ directory にある、以下に述べる制約による名前を持つ実行ファイルを、すべて実行します。その他のファイルやディレクトリは、黙って無視します

Debian では ip-up / ip-down は run-parts で読み出すので、run-parts では実行ファイルでないと無視するから、 chmod +x が必要

/etc/ppp/ip-up /etc/ppp/ip-down のスクリプトディストリビューションごとに異なるため、気になりだしたら魔界に入れること請け合い。辛い。

Arch

https://git.archlinux.org/svntogit/packages.git/tree/trunk/ip-up?h=packages/ppp

CentOS

#!/bin/bash
# This file should not be modified -- make local changes to
# /etc/ppp/ip-up.local instead

PATH=/sbin:/usr/sbin:/bin:/usr/bin
export PATH

LOGDEVICE=$6
REALDEVICE=$1

[ -f /etc/sysconfig/network-scripts/ifcfg-${LOGDEVICE} ] && /etc/sysconfig/network-scripts/ifup-post --realdevice ${REALDEVICE} ifcfg-${LOGDEVICE}

/etc/ppp/ip-up.ipv6to4 ${LOGDEVICE}

[ -x /etc/ppp/ip-up.local ] && /etc/ppp/ip-up.local "$@"

exit 0