--- nono/host/netdriver_bpf.cpp 2026/04/29 17:04:54 1.1.1.5 +++ nono/host/netdriver_bpf.cpp 2026/04/29 17:05:11 1.1.1.6 @@ -4,8 +4,13 @@ // Licensed under nono-license.txt // +// +// ホストネットワークの BPF ドライバ +// + #include "netdriver_bpf.h" #include "autofd.h" +#include "hostnet.h" #include #include #include @@ -16,9 +21,8 @@ #include // コンストラクタ -NetDriverBPF::NetDriverBPF(EthernetDevice *parent_, int loglevel_, - const std::string& ifname_) - : inherited("BPF", parent_, loglevel_) +NetDriverBPF::NetDriverBPF(HostDevice *hostdev_, const std::string& ifname_) + : inherited(hostdev_, "BPF") { ifname = ifname_; if (ifname.empty()) { @@ -32,13 +36,14 @@ NetDriverBPF::~NetDriverBPF() Close(); } -// ドライバ初期化 & オープン +// ドライバ初期化 bool NetDriverBPF::InitDriver() { struct ifreq ifr; struct bpf_program prog; u_int val; + u_int bpfbuflen; struct bpf_insn insn[] = { // すべてのパケットを全長受信 BPF_STMT(BPF_RET + BPF_K, (u_int)-1), @@ -89,7 +94,7 @@ NetDriverBPF::InitDriver() memset(&ifr, 0, sizeof(ifr)); strlcpy(ifr.ifr_name, ifname.c_str(), sizeof(ifr.ifr_name)); if (ioctl(fd, BIOCSETIF, &ifr) == -1) { - errmsg = string_format("%s(%s): BIOCSETIF: %s", + errmsg = string_format("%s(%s): BIOCSETIF: %s", devpath.c_str(), ifname.c_str(), strerror(errno)); goto abort; } @@ -130,18 +135,18 @@ NetDriverBPF::InitDriver() } // 受信用バッファを確保 - try { - bpfbuf.reset(new uint8 [bpfbuflen]); - } catch (...) { - errmsg = "memory allocation failed"; - goto abort; - } + bpfbuf.resize(bpfbuflen); putmsg(1, "opened %s for %s", devpath.c_str(), ifname.c_str()); putmsg(1, "warning: communicating with the localhost is not possible"); // bpf では ifup スクリプトは実行しない + if (hostdev->AddOuter(fd) < 0) { + putmsg(0, "AddOuter(fd=%d): %s", (int)fd, strerror(errno)); + return false; + } + return true; abort: @@ -155,9 +160,9 @@ NetDriverBPF::InitDriver() void NetDriverBPF::Close() { - if (IsOpen()) { - close(fd); - fd = -1; + if (fd.Valid()) { + hostdev->DelOuter(fd); + fd.Close(); } } @@ -170,28 +175,57 @@ NetDriverBPF::MonitorUpdateMD(TextScreen } // パケットを送信する -bool -NetDriverBPF::SendPacket(const std::vector& data) +void +NetDriverBPF::Write(const void *buf, int buflen) { - int n; + ssize_t n; - assert(IsOpen()); + n = write(fd, buf, buflen); + if (n < 0) { + putmsg(0, "write: %s", strerror(errno)); + return; + } + if (n < buflen) { + putmsg(0, "write: short"); + return; + } +} - putlog(2, "SendPacket %zu bytes", data.size()); - tx_pkts++; - tx_bytes += data.size(); +// パケットを受信する +int +NetDriverBPF::Read(NetPacket *p) +{ + uint8 *buf = bpfbuf.data(); - n = write(fd, data.data(), data.size()); - if (n == -1) { - putmsg(0, "%s: write failed: fd=%d datalen=%zu: %s", - __func__, fd, data.size(), strerror(errno)); - return false; + if (bpfptr == NULL) { + bpflen = read(fd, bpfbuf.data(), bpfbuf.size()); + if (bpflen < 0) { + putmsg(0, "read: %s", strerror(errno)); + return NODATA; + } + + bpfptr = buf; } - if (n < (int)data.size()) { - return false; + // BPF ヘッダを除いた部分が 1 パケット + struct bpf_hdr *bh = (struct bpf_hdr *)bpfptr; + + NetPacket& packet = *p; + memcpy(packet.data(), bpfptr + bh->bh_hdrlen, bh->bh_caplen); + packet.length = bh->bh_caplen; + + // 次のフレームの先頭を指す + int framelen = BPF_WORDALIGN(bh->bh_hdrlen + bh->bh_caplen); + bpfptr += framelen; + + if (bpfptr < buf + bpflen) { + // 次がある + return 1; + } else { + // 次はない + bpfptr = NULL; + return 0; } - return true; } // 最初に見付かった使えそうなインタフェース名を返す。 @@ -220,28 +254,3 @@ NetDriverBPF::FindInterface() const return std::string(name); } - -// パケットを受信する -ssize_t -NetDriverBPF::RecvPacket() -{ - uint8 *buf = bpfbuf.get(); - uint8 *bpfptr = buf; - ssize_t n; - - n = read(fd, buf, bpfbuflen); - if (n <= 0) { - return n; - } - - while (bpfptr < buf + n) { - // BPF ヘッダを除いた部分が 1 パケット - struct bpf_hdr *bh = (struct bpf_hdr *)bpfptr; - RecvEnqueue(bpfptr + bh->bh_hdrlen, bh->bh_caplen); - - // 次のフレームの先頭を指す - int framelen = BPF_WORDALIGN(bh->bh_hdrlen + bh->bh_caplen); - bpfptr += framelen; - } - return n; -}