网卡设备ID格式为:
\Device\NPF_{网卡名称},网卡名称可以通过 WINAPI “GetAdaptersInfo” 函数来获取,当然人们仍旧可以使用 Packet32 提供的 “PacketGetAdapterNames” 函数来获取,每个网卡之间使用 “/x0” 来做分隔符,结束标志位为某端两个“\x0”,用法简单就不再本文过多描述了。
PacketOpenAdapter 打开网卡设备
inline static LPADAPTER ethernet_open_device(const std::string& id) {
if (id.empty()) {
return NULL;
}
LPADAPTER p = PacketOpenAdapter(id.data());
if (!p) {
PacketCloseAdapter(p);
return NULL;
}
if (!PacketSetHwFilter(p, NDIS_PACKET_TYPE_PROMISCUOUS)) {
PacketCloseAdapter(p);
return NULL;
}
if (!PacketSetBuff(p, 16 * 1024 * 1024)) {
PacketCloseAdapter(p);
return NULL;
}
if (!PacketSetReadTimeout(p, INFINITE)) {
PacketCloseAdapter(p);
return NULL;
}
return p;
}
PacketReceivePacket 读入网卡数据(一次读入多个以太网帧)
inline static bool ethernet_loopback(const std::string& device, const std::string& id) {
ETHERNET_NIC = ethernet_open_device(id);
if (!ETHERNET_NIC) {
return false;
}
else {
ethernet_init();
}
LPPACKET PACKET = PacketAllocatePacket();
while (!ETHERNET_FIN) {
LPADAPTER NIC = ETHERNET_NIC;
if (!NIC) {
break;
}
static CHAR BUFF[65536];
PacketInitPacket(PACKET, BUFF, sizeof(BUFF));
if (!PacketReceivePacket(NIC, PACKET, TRUE)) {
break;
}
CHAR* PKG = BUFF;
while (PACKET->ulBytesReceived > 0) {
struct bpf_hdr* HDR = (struct bpf_hdr*)PKG;
int LEN = HDR->bh_datalen;
do {
struct eth_hdr* ETH = (struct eth_hdr*)(PKG + HDR->bh_hdrlen);
int PROTO = ntohs(ETH->proto);
if (PROTO == ETHTYPE_IP) {
if (MAC2I64(ETH->dst) != MAC2I64(ETHERNET_MAC)) {
break;
}
}
std::shared_ptr<char> FRM = std::shared_ptr<char>((char*)malloc(LEN), free);
memcpy(FRM.get(), ETH, LEN);
ETHERNET_CONTEXT_.post(std::bind(ethernet_input, ETH, PROTO, FRM, LEN));
} while (0);
LEN = Packet_WORDALIGN(HDR->bh_hdrlen + HDR->bh_datalen);
PKG += LEN;
PACKET->ulBytesReceived -= LEN;
}
}
PacketFreePacket(PACKET);
ethernet_release();
return true;
}
PacketSendPacket 写入网卡数据,MAX: 1514 BYTE
int ethernet_output(struct eth_hdr* eth, int len) {
static const INT32 MTU = 1514;
if (!eth || len < sizeof(*eth)) {
return -1;
}
LPADAPTER NIC = ETHERNET_NIC;
if (!NIC) {
return -1;
}
int ERR = -1;
LPPACKET PACKET = PacketAllocatePacket();
if (PACKET) {
CHAR* DATA = (CHAR*)eth;
INT32 SIZE = (INT32)len;
while (SIZE > 0) {
INT32 BT = min(SIZE, MTU);
PacketInitPacket(PACKET, DATA, BT);
if (!PacketSendPacket(NIC, PACKET, TRUE)) {
break;
}
SIZE -= BT;
DATA += BT;
}
ERR = 0;
}
PacketFreePacket(PACKET);
return ERR;
}