Category

C++26でネットワークプログラミング

C++26のstd::span、std::expectedなどのエルゴノミクスを使い、L2から上位のネットワークスタックを軽微に実装します。

10件の記事

簡易TCPのシーケンス番号・再送・フロー制御と、自作TCPクライアントが踏む「自分のカーネルのRST」問題

TCPヘッダのparse/buildの上に、stop-and-wait方式によるシーケンス番号管理・タイムアウト再送・簡易フロー制御を実装します。合わせて、OSの標準ソケットAPIを経由せず生ソケットで自前のTCPコネクションを実装したときに必ず踏む、「送信元マシン自身のカーネルが身に覚えのないセグメントへRSTを送り返してしまう」という設計上の制約と、その回避方法についても扱います。

続きを読む

TCPヘッダのパース/構築と、3-wayハンドシェイクの実装

TCPヘッダはICMP/UDPと違い、フラグ・シーケンス番号・可変長のオプションを持ちます。3-wayハンドシェイクに必要な範囲でヘッダの型を設計し、UDPと同じ疑似ヘッダ方式のチェックサムを再利用しつつ、UDPには存在する「0はチェックサム未使用」という読み替えがTCPには不要である理由にも触れます。最後に、実際にLAN上のホストとSYN/SYN-ACK/ACKを交わすところまで確認します。

続きを読む

UDPデータグラムのパース/構築と、疑似ヘッダによるチェックサム

UDPヘッダの`parse`/`build`を`std::expected`で設計します。ICMPと違い、UDPのチェックサムはヘッダ+ペイロードだけでなくIPv4ヘッダの一部を仮想的に含めた「疑似ヘッダ」を対象に計算する必要があります。あわせて、この1の補数和チェックサムが持つ検出限界(16bitワードの入れ替えを検出できない)にも触れます。

続きを読む

ICMP Echo Request/Replyのパースとバイト変換ヘルパーの共通化

ping応答/送信に必要なICMP Echo Request/Replyのパース・構築を`std::expected`と`std::vector<std::byte>`で実装し、IPv4ヘッダとの違い(チェックサムが可変長のデータ部まで含む点)と、複数ファイルで重複していた16bit読み書きヘルパーを内部ヘッダに切り出した設計を整理します。

続きを読む

IPv4ヘッダをパースしてチェックサムを検証する

IPv4ヘッダを`std::expected`でパースし、インターネットチェックサムを検証する`parse_ipv4_packet`の設計です。1の補数和による検証トリックと、RFCの「Type of Service」オクテットが現在はDSCP/ECNとして再定義されているポイントを扱います。

続きを読む

ARP requestを実際に送ってIPアドレスをMACアドレスに解決する

指定したIPアドレスに対してARP requestを送信し、返ってきたreplyからMACアドレスを解決する`arp_resolve`を実装しました。Ethernetヘッダを手で組み立てる方法、ioctlでローカルのMAC/IPを取得する方法、そして「本当に待っていたreplyか」を見極める必要がある理由を扱います。

続きを読む

IP→MAC対応をキャッシュするArpCacheとTTL設計

ARPで解決したIP→MAC対応をキャッシュする`ArpCache`を実装しました。std::unordered_mapに独自のハッシュ関数を渡す方法、TTLの期限切れをsleepなしでテストする方法、そして実機のARPトラフィックでTTL失効を確認するところまでをまとめます。

続きを読む

AF_PACKET raw socketによるL2フレームキャプチャの実装

AF_PACKET raw socketでNICからEthernetフレームを直接送受信する`RawSocket`を実装しました。OSリソースの所有権をクラスとして表現する設計判断と、実機で実際のARPトラフィックを観測した結果までをまとめます。

続きを読む

ARPパケットの解析とバイト列の組み立て

ARPパケットのヘッダ構造をパースし、Request/Replyそれぞれのバイト列を組み立てる実装を行いました。エラー型をどう分割するか、パースと組み立てをラウンドトリップでテストする設計判断を整理します。

続きを読む

std::span/std::expectedで設計するEthernet IIフレーム解析

C++26対応のGCC 15と、std::span・std::expectedを使ってEthernet IIフレームのヘッダ解析を実装しました。生バイト列をコピーせずに扱う設計や、コンパイル時にサイズを保証するstd::spanの使い方、失敗をどこでどう表現するかという判断を整理します。

続きを読む