前に書いたdhclientでNGNの情報を取得するテストを、OpenWrt標準のudhcpでやり直し。
ちょっと経緯とか
dhclientが含まれるISC DHCPのメンテナンスは終わっていて、keaへの移行が推奨となっています。
DHCP取得するだけなのでdhclientを使い続けても問題無いと思いますが、今後パッケージなくなったり等もありえるので、標準機能での取得できないかをやってみました。
とりあえず設定してみる
OpenWrtではudhcpが通常使われています。IPv4の設定オプションを見ると、reqoptsとsendoptsがあるので、dhclientの設定を参考に設定してみましたが、うまくいきません。というかどこに取得値保存されているのかがわからず。
調べてみると、OpenWrtのudhcpcは、受信したDHCPオプションをすべて環境変数として、ユーザー定義のスクリプト (/etc/udhcpc.user.d/) に渡してくれるとのことです。
ただコンソールでenvしても値が無いので、ユーザースクリプトで取得した物を全部吐き出させてみましたが、やはりデータが取得できていません。
なので、一度dhclientでの動作を確認します。
最初やってみた残骸
# wanに書いてみた設定
# 欲しいOptionの指定
option reqopts '120 121 125 210'
# 送信するOption (send vendor-class.ntt =~の部分)
option sendopts '210:06aabbccddeeff'
cat << 'EOF' > /etc/udhcpc.user.d/99-env-dump.sh
#!/bin/sh
env > /tmp/ngn_info.txt
EOF
動作を調べる
tcpdumpでONUへNGN情報取得するDHCPパケットを確認
長いから畳んだ…
tcpdump -i wan -vvn port 67 and port 68
tcpdump: listening on wan, link-type EN10MB (Ethernet), snapshot length 262144 bytes
01:59:40.774573 IP (tos 0x10, ttl 128, id 0, offset 0, flags [none], proto UDP (17), length 328)
0.0.0.0.68 > 255.255.255.255.67: [udp sum ok] BOOTP/DHCP, Request from 58:27:8c:xx:xx:xx, length 300, xid 0xe8b9df7a, Flags [none] (0x0000)
Client-Ethernet-Address 58:27:8c:xx:xx:xx
Vendor-rfc1048 Extensions
Magic Cookie 0x63825363
DHCP-Message (53), length 1: Request
Requested-IP (50), length 4: ***.***.***.***
Parameter-Request (55), length 5:
Subnet-Mask (1), Default-Gateway (3), Unknown (120), Classless-Static-Route (121)
Unknown (125)
Client-ID (61), length 7: ether xx:xx:xx:xx:xx:xx
Unknown (124), length 12: 210,xxxxxxxxx,xxxxxxxxxx
01:59:40.793326 IP (tos 0xb8, ttl 255, id 32100, offset 0, flags [none], proto UDP (17), length 402)
xxx.xxx.xxx.xxx.67 > ***.***.***.***.68: [udp sum ok] BOOTP/DHCP, Reply, length 374, xid 0xe8b9df7a, Flags [none] (0x0000)
Your-IP ***.***.***.***
Server-IP xxx.xxx.xxx.xxx
Gateway-IP xxx.xxx.xxx.xxx
Client-Ethernet-Address xx:xx:xx:xx:xx:xx
Vendor-rfc1048 Extensions
Magic Cookie 0x63825363
DHCP-Message (53), length 1: ACK
Subnet-Mask (1), length 4: 255.255.255.252
Default-Gateway (3), length 4: xxx.xxx.xxx.xxx
Unknown (120), length 5: 1.118.xxx.xxx.xxx
Classless-Static-Route (121), length 7: (118.xxx.xxx.xxx/16:xxx.xxx.xxx.xxx)
Unknown (125), length 76: 210,xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Lease-Time (51), length 4: 14400
Server-ID (54), length 4: xxx.xxx.xxx.xxx
RN (58), length 4: 7200
RB (59), length 4: 10800
tcpdumpでRequest確認したところ、120、121、125が追加されている部分のようで、
Unknown (124)となっている部分のデータに210があります。
というわけで、DHCPで送るオプションを完全に勘違いしていたようです。
調べなおしてみると124がVender-class-dataらしく、送ると125を返してくるようです。
で、210って何だったのかというとnttのIDらしい。探してみるとRFC3925?
VIVCO (Vendor-Identifying Vendor Class – Option 124)
VIVSO (Vendor-Identifying Vendor-Specific Information – Option 125)
結論としては、Option124をID210,07,06+MACアドレスというデータで送ると、他のオプションも返してくれるようになるみたいです。
Enterprise Number 210=東 211=西
OpenWrtでNGN情報を取得する設定
というわけで、色々確認して出来上がった設定がこちら
#/etc/config/networkにngn取得用のDHCPインターフェース生やす
config interface 'ngn'
option proto 'dhcp'
option defaultroute '0'
option peerdns '0'
option multipath 'off'
option delegate '0'
option device 'wan'
option reqopts '120 121 125' # SIP, StaticRoute, VenderDataを要求
option sendopts '124:000000d20706************' ←*にMACアドレスを入れる
これで取得ができるのですが、取得した内容はそのままどこにも保存されないので、テキストに吐き出すようにします。
option125で取得したデータ列も、そのままでは使いづらいのでデコード処理します。
Geminiがシェルスクリプト頑張ってくれた。
#sshでそのまま貼り付け用
cat << 'EOF' > /etc/udhcpc.user.d/99-ngn-env-dump.sh
#!/bin/sh
DUMP_FILE="/tmp/ngn-info.txt"
env | grep -iE "^(opt|sip|ip|subnet|router|staticroutes|dns)" > "$DUMP_FILE"
if [ -n "$opt125" ]; then
echo "$opt125" | awk -v file="$DUMP_FILE" '
function h2d(h, res, k, p) {
h = tolower(h)
res = 0
for(k=1; k<=length(h); k++) {
p = index("0123456789abcdef", substr(h, k, 1)) - 1
res = res * 16 + p
}
return res
}
function hex2ascii(h, ascii, i) {
ascii = ""
for(i=1; i<=length(h); i+=2) {
ascii = ascii sprintf("%c", h2d(substr(h, i, 2)))
}
return ascii
}
function parse_dns(h, dns, p_pos, lbl_len, lbl_txt) {
dns = ""
p_pos = 1
while(p_pos <= length(h)) {
lbl_len = h2d(substr(h, p_pos, 2))
if(lbl_len == 0) break
p_pos += 2
lbl_txt = hex2ascii(substr(h, p_pos, lbl_len*2))
dns = dns (dns=="" ? "" : ".") lbl_txt
p_pos += lbl_len*2
}
return dns
}
{
hex = $0
pos = 11
while (pos < length(hex)) {
type = substr(hex, pos, 2)
len = h2d(substr(hex, pos+2, 2))
val = substr(hex, pos+4, len*2)
if (type == "c9") {
mac = ""
for(i=1; i<=length(val); i+=2) mac = mac (mac==""?"":":") substr(val, i, 2)
print "opt201=" mac >> file
}
else if (type == "ca") {
print "opt202=" hex2ascii(val) >> file
}
else if (type == "cc") {
print "opt204=" parse_dns(val) >> file
}
else if (type == "d2") {
print "opt210=" parse_dns(val) >> file
}
pos += 4 + len*2
}
}'
fi
EOF
これで /tmp/ngn-info.txt に全部吐き出すことができました。
うまくいくとこんな感じです。
cat /tmp/ngn-info.txt
subnet=255.255.255.252
router=118.***.***.***
opt58=00001c20
opt59=00002a30
staticroutes=118.****.0.0/16 xxx.xxx.xxx.xxx
opt125=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
sipsrv=118.***.***.***
ip=xxx.xxx.xxx.xxx.
opt53=05
opt201=xx:xx:xx:xx:xx:xx
opt202=でんわばんごう
opt204=ntt-east.ne.jp
opt210=www.verinfo.hgw.flets-east.jp
これでSIPやドメイン取得できましたね。
やっと動作を完全に理解した。
他環境でも行けそうですね。
その他参考など
あとから見つかった何か。 https://www.voip-info.jp/index.php/PR-S300SE




コメント