タイトルが示すように、TCP / IPスタックを作成してTCPがどのように機能するかを学びたいと思います。以下のようにプログラムでRustでTAPデバイスを作成しています。
pub struct Tap {
fd: i32,
}
#[repr(C)]
struct IFreq {
name: [c_char; IFNAMSIZ],
flags: c_short,
}
impl Tap {
pub fn new(name: &CStr) -> Result<Tap, TapError> {
let fd = unsafe {
let fd = libc::open(b"/dev/net/tun\0".as_ptr() as *const _, libc::O_RDWR);
if fd < 0 {
Err(TapError::OpenFD(std::io::Error::last_os_error()))
} else {
Ok(fd)
}
}?;
let mut ifr = IFreq {
name: [0; IFNAMSIZ],
flags: (libc::IFF_TAP | libc::IFF_NO_PI) as c_short,
};
for (dst, src) in ifr.name[0..IFNAMSIZ - 1]
.iter_mut()
.zip(name.to_bytes().iter())
{
*dst = *src as i8;
}
unsafe {
let err = libc::ioctl(fd, TUNSETIFF, &mut ifr as *mut _);
if err == -1 {
return Err(TapError::IOCTL(std::io::Error::last_os_error()));
}
}
Ok(Tap { fd })
}
}
ただし、これを使用しip link set dev <tap name> up
てイーサネットフレームを読み始めると、IPv6フレーム(イーサネットタイプ0x86DD)のみが得られるようです。これは普通ですか?これが起こらないようにするにはどうすればよいですか?私は現在IPv4の実装に専念しており、IPv6トラフィックは処理したくありません。
ベストアンサー1
ただし、ip link set dev upを使用して起動してイーサネットフレームを読み始めると、IPv6フレーム(イーサネットタイプ0x86DD)しか取得されないようです。これは普通ですか?これが起こらないようにするにはどうすればよいですか?私は現在IPv4の実装に専念しており、IPv6トラフィックは処理したくありません。
IPv6をサポートするシステムでは、各インターフェイスは自動的にローカルリンクプレフィックスのIPv6アドレスfe80::/64
。これは主にインフラストラクチャの目的に使用されます。たとえば、DHCPv4クライアントなどのrawソケットを使用する代わりに、SLAACおよびDHCPv6パケット(それぞれICMPv6およびUDP)を一般的な方法で送信できます。
初期パケットは、OSがリンクローカルアドレスを割り当てることによって発生する「冗長アドレス検出」パケット、またはSLAAC自動設定を開始する「ルータ要求」である可能性があると疑われます。
お客様の場合、特にネットワークスタックが処理する必要がある通常の状況なので、この機能を無効にしないことをお勧めします。〜でもIPv6をサポートしていません。物理イーサネットネットワークに接続されている物理デバイスにTCP / IPを実装している場合、他のデバイスが送信するものを選択することはできません。会議IPv6だけでなく、あらゆる種類の奇妙で不要なフレームを受信します(例:実際の例では、イーサネット用のLLDP、STP、RoMON、CTP)。
つまり、OSがTapインターフェイスでIPv6と通信するのを防いでいても可能、これは運動が実用的ではなく、しばしば誤ったアプローチになります。
代わりに、ネットワークスタックは静かにする必要があります。無視するIPv6、DECnet、IPXなど、認識できないイーサネットタイプのすべてのイーサネットフレーム。 (つまり、ここでは特別なケースである0x86DDは必要ありません。0x0800 / 0x0806以外は安全に削除できます。)