IPv6のユニークローカルアドレス(ULA)セグメントの生成

# IPv6のユニークローカルアドレス(ULA)セグメントの生成
諸般の事情により、IPv6でローカルネットワークを構築することになりました。

で、IPのセグメントを割り当てる必要があるのですが、
IPv4であれば、192.168.1.0/24などを、好きに切りだして使ってよかったところが、
IPv6では、ローカルでもなるべく他人とかぶらないセグメントを作成して使ってね、
という方針に変わったようです。

詳しくは、以下のページが参考になるかと思います。
[IPv4の常識 vs IPv6の常識＠家庭内LAN](https://qiita.com/tetsuy/items/22f0a1707f0adfe10d06)
[インターネット10分講座：IPv6アドレス～技術解説～](https://www.nic.ad.jp/ja/newsletter/No32/090.html)
[RFC 4193 - Unique Local IPv6 Unicast Addresses](https://datatracker.ietf.org/doc/html/rfc4193)

で、その「他人とかぶらない」セグメントの作成方法が、RFC 4193で提案されており、
今回、なるべくこの仕様に沿ってセグメントを切り出すPowerShellを作成してみました。

詳しい説明はそのうち書くかもですが、たぶん書く暇ないような気がするので、
興味のある方は、RFC 4193とコードを見比べながら追ってください。
(大したことはやっていないです)

何かご指摘等あれば、コメントいただけると助かります。

```Powershell:GenerateIPv6UlaSegment.ps1
#### GenerateIPv6UlaSegment.ps1
# IPv6のユニークローカルアドレス(ULA) (IPv4のプライベートアドレスに相当)の
# ネットワークセグメントをRFC 4193 で提案されている方法で
# 生成する(つもり)のスクリプトです


###### 定数など
# NTPサーバを指定
$NTPServer = "ntp.nict.jp"
$NTPPort = 123

# サブネットIDを指定
$SubnetID = "01"


###### NTPサーバから日付を取得(Transmit Timstamp(64bits)をそのまま使用)
$Socket = New-Object -typename Net.Sockets.Socket -argumentlist ( 'InterNetwork', 'Dgram', 'Udp' )
$Socket.SendTimeOut    = 2000  # ms
$Socket.ReceiveTimeOut = 2000  # ms
$Socket.Connect( $NTPServer, $NTPPort )
$NTPData = New-Object -TypeName byte[] -ArgumentList 48
$NTPData[0] = 27 # Request header: 00 = No Leap Warning; 011 = Version 3; 011 = Client Mode; 00011011 = 27
$Socket.Send($NTPData) | Out-Null
$Socket.Receive($NTPData) | Out-Null
$TimeData = $NTPData[40..47] # Transmit Timestamp

Write-Host("時刻から算出したシード値:" + $TimeData)


###### MACアドレスからEUI-64 IDを作成
# このシェルを実行している端末のMACをひとつ取得
$DeviceInfo = (getmac | Select-String "Device" | Select-Object -First 1)
$MacAddress = $deviceInfo.ToString().Substring(0,17)
Write-Host("MACアドレス:" + $MacAddress)

# EUI-64 ID の作成
$MacSplit = $MacAddress.Split("-")
$SeventhBit = [Convert]::ToInt32($MacSplit[0], 16) -band 2 # 1byte目の7bit目の抽出

$MacData = New-Object -TypeName byte[] -ArgumentList 8
$MacData[0] = [Convert]::ToInt32($MacSplit[0], 16) + 2 - 2*$SeventhBit # 7bit目を反転
$MacData[1] = [Convert]::ToInt32($MacSplit[1], 16)
$MacData[2] = [Convert]::ToInt32($MacSplit[2], 16)
$MacData[3] = [Convert]::ToInt32("FF", 16)
$MacData[4] = [Convert]::ToInt32("FE", 16)
$MacData[5] = [Convert]::ToInt32($MacSplit[3], 16)
$MacData[6] = [Convert]::ToInt32($MacSplit[4], 16)
$MacData[7] = [Convert]::ToInt32($MacSplit[5], 16)

Write-Host("MACアドレスから算出したEUI-64 ID値:" + $MacData)


###### 日付データとMACデータを結合し、SHA1値を取得。末尾40bitをGlobal IDとして取得
$Buffer = $TimeData + $MacData
$Sha1 = [System.Security.Cryptography.SHA1]::Create()
$Hash = $Sha1.ComputeHash($Buffer)
$GlobalID = $Hash[15..19]

Write-Host("Global ID値:" + $GlobalID)


###### ユニークローカルアドレスのセグメント生成
$UlaSegment = New-Object -TypeName byte[] -ArgumentList 8
$UlaSegmentPre = [Convert]::ToInt32("FD", 16),[Convert]::ToInt32("00", 16) # 先頭は固定
$UlaSegmentPost = ,[Convert]::ToInt32($SubnetID , 16) # 末尾はサブネットID

$UlaSegment = $UlaSegmentPre + $GlobalID + $UlaSegmentPost

$UlaSegmentStr = [System.BitConverter]::ToString($UlaSegment)
$UlaSegmentStr = $UlaSegmentStr -replace "-",""
$UlaSegmentStr = $UlaSegmentStr.Substring(0,4) + ":" + $UlaSegmentStr.Substring(4,4) + ":"  + $UlaSegmentStr.Substring(8,4)+ ":" + $UlaSegmentStr.Substring(12,4)
$UlaSegmentStr = $UlaSegmentStr + "::/64"

Write-Host("ULAセグメント:" + $UlaSegmentStr)
```