// Verify the ACK message bool DlipReceiveAck(int fd) { union DL_primitives *dlp; struct strbuf ctl; int flags = 0; char *buf; // Validate arguments if (fd == -1) { return false; } buf = MallocFast(SOLARIS_MAXDLBUF); Zero(&ctl, sizeof(ctl)); ctl.maxlen = SOLARIS_MAXDLBUF; ctl.len = 0; ctl.buf = buf; if (getmsg(fd, &ctl, NULL, &flags) < 0) { return false; } dlp = (union DL_primitives *)ctl.buf; if (dlp->dl_primitive != (UINT)DL_OK_ACK && dlp->dl_primitive != (UINT)DL_BIND_ACK) { Free(buf); return false; } Free(buf); return true; }
// Read the next sent packet from the driver bool VLanGetNextPacket(VLAN *v, void **buf, UINT *size) { // Validate arguments if (v == NULL || buf == NULL || size == NULL) { return false; } if (v->Halt) { return false; } PROBE_STR("VLanGetNextPacket"); while (true) { if (v->CurrentPacketCount < NEO_NUM_PACKET(v->GetBuffer)) { // There are still packets that have been read already *size = NEO_SIZE_OF_PACKET(v->GetBuffer, v->CurrentPacketCount); *buf = MallocFast(*size); Copy(*buf, NEO_ADDR_OF_PACKET(v->GetBuffer, v->CurrentPacketCount), *size); // Increment the packet number v->CurrentPacketCount++; return true; } else { // Read the next packet from the driver if (VLanGetPacketsFromDriver(v) == false) { return false; } if (NEO_NUM_PACKET(v->GetBuffer) == 0) { // Packet is not received currently *buf = NULL; *size = 0; return true; } v->CurrentPacketCount = 0; } } }
UINT EthGetPacketSolaris(ETH *e, void **data) { UCHAR tmp[UNIX_ETH_TMP_BUFFER_SIZE]; struct strbuf buf; int s; int flags = 0; int ret; // Validate arguments if (e == NULL || data == NULL) { return INFINITE; } s = e->Socket; if (s == INVALID_SOCKET) { return INFINITE; } Zero(&buf, sizeof(buf)); buf.buf = tmp; buf.maxlen = sizeof(tmp); ret = getmsg(s, NULL, &buf, &flags); if (ret < 0 || ret > sizeof(tmp)) { if (errno == EAGAIN) { // No packet *data = NULL; return 0; } // Error *data = NULL; return INFINITE; } ret = buf.len; *data = MallocFast(ret); Copy(*data, tmp, ret); return ret; }
UINT EthGetPacketLinux(ETH *e, void **data) { int s, ret; UCHAR tmp[UNIX_ETH_TMP_BUFFER_SIZE]; // Validate arguments if (e == NULL || data == NULL) { return INFINITE; } if (e->Tap != NULL) { #ifndef NO_VLAN // tap mode void *buf; UINT size; if (VLanGetNextPacket(e->Tap, &buf, &size) == false) { return INFINITE; } *data = buf; return size; #else // NO_VLAN return INFINITE; #endif } s = e->Socket; if (s == INVALID_SOCKET) { return INFINITE; } // Read ret = read(s, tmp, sizeof(tmp)); if (ret == 0 || (ret == -1 && errno == EAGAIN)) { // No packet *data = NULL; return 0; } else if (ret == -1 || ret > sizeof(tmp)) { // Error *data = NULL; e->Socket = INVALID_SOCKET; return INFINITE; } else { // Success to read a packet *data = MallocFast(ret); Copy(*data, tmp, ret); return ret; } return 0; }
// Read next packet UINT EthGetPacket(ETH *e, void **data) { BLOCK *b; bool flag = false; // Validate arguments if (e == NULL || data == NULL) { return INFINITE; } if (e->HasFatalError) { return INFINITE; } if (e->SuAdapter != NULL) { // Read packet with SeLow UINT size; if (SuGetNextPacket(e->SuAdapter, data, &size) == false) { // Error occurred e->HasFatalError = true; return INFINITE; } return size; } RETRY: // Check the presence of the packet in queue b = GetNext(e->PacketQueue); if (b != NULL) { UINT size; size = b->Size; *data = b->Buf; Free(b); if (e->PacketQueue->num_item == 0) { e->Empty = true; } return size; } if (e->Empty) { e->Empty = false; return 0; } if (flag == false) { // Try to get next packet PROBE_STR("EthGetPacket: PacketInitPacket"); wp->PacketInitPacket(e->Packet, e->Buffer, e->BufferSize); PROBE_STR("EthGetPacket: PacketReceivePacket"); if (wp->PacketReceivePacket(e->Adapter, e->Packet, false) == false) { // Failed return INFINITE; } else { UCHAR *buf; UINT total; UINT offset; buf = (UCHAR *)e->Packet->Buffer; total = e->Packet->ulBytesReceived; offset = 0; while (offset < total) { struct bpf_hdr *header; UINT packet_size; UCHAR *packet_data; header = (struct bpf_hdr *)(buf + offset); packet_size = header->bh_caplen; offset += header->bh_hdrlen; packet_data = buf + offset; offset = Packet_WORDALIGN(offset + packet_size); if (packet_size >= 14) { UCHAR *tmp; BLOCK *b; PROBE_DATA2("EthGetPacket: NewBlock", packet_data, packet_size); tmp = MallocFast(packet_size); Copy(tmp, packet_data, packet_size); b = NewBlock(tmp, packet_size, 0); InsertQueue(e->PacketQueue, b); } } flag = true; goto RETRY; } } // No more packet return 0; }
// Send multiple packets void EthPutPackets(ETH *e, UINT num, void **datas, UINT *sizes) { UINT i, total_size; UCHAR *buf; UINT write_pointer; UINT err = 0; // Validate arguments if (e == NULL || num == 0 || datas == NULL || sizes == NULL) { return; } if (e->HasFatalError) { return; } if (e->SuAdapter != NULL) { bool ok = true; // Send packets with SeLow for (i = 0;i < num;i++) { UCHAR *data = datas[i]; UINT size = sizes[i]; if (ok) { // Actually, only enqueuing ok = SuPutPacket(e->SuAdapter, data, size); } if (ok == false) { // Free memory on write error Free(data); } } if (ok) { // Send all data in queue at once ok = SuPutPacket(e->SuAdapter, NULL, 0); } if (ok == false) { // Error occurred e->HasFatalError = true; } return; } if (IsWin32BridgeWithSee() == false) { if (e->LastSetSingleCpu == 0 || (e->LastSetSingleCpu + 10000) <= Tick64()) { e->LastSetSingleCpu = Tick64(); MsSetThreadSingleCpu(); } } // Calculate buffer size total_size = 0; for (i = 0;i < num;i++) { void *data = datas[i]; UINT size = sizes[i]; if (data != NULL && size >= 14 && size <= MAX_PACKET_SIZE) { total_size += size + sizeof(struct dump_bpf_hdr); } } buf = MallocFast(total_size * 100 / 75 + 1600); write_pointer = 0; // Enqueue for (i = 0;i < num;i++) { void *data = datas[i]; UINT size = sizes[i]; if (data != NULL && size >= 14 && size <= MAX_PACKET_SIZE) { struct dump_bpf_hdr *h; h = (struct dump_bpf_hdr *)(buf + write_pointer); Zero(h, sizeof(struct dump_bpf_hdr)); h->caplen = h->len = size; write_pointer += sizeof(struct dump_bpf_hdr); Copy(buf + write_pointer, data, size); write_pointer += size; PROBE_DATA2("EthPutPackets", data, size); } // Free original buffer Free(data); } // Send if (total_size != 0) { err = wp->PacketSendPackets(e->Adapter, buf, total_size, true); } Free(buf); if (err == 0x7FFFFFFF) { // Critical error (infinite loop) occurred on sending e->HasFatalError = true; } }
UINT EthGetPacketLinux(ETH *e, void **data) { int s, ret; UCHAR tmp[UNIX_ETH_TMP_BUFFER_SIZE]; // 引数チェック if (e == NULL || data == NULL) { return INFINITE; } if (e->Tap != NULL) { #ifndef NO_VLAN // tap モード void *buf; UINT size; if (VLanGetNextPacket(e->Tap, &buf, &size) == false) { return INFINITE; } *data = buf; return size; #else // NO_VLAN return INFINITE; #endif } s = e->Socket; if (s == INVALID_SOCKET) { return INFINITE; } // 読み込み ret = read(s, tmp, sizeof(tmp)); if (ret == 0 || (ret == -1 && errno == EAGAIN)) { // パケット無し *data = NULL; return 0; } else if (ret == -1 || ret > sizeof(tmp)) { // エラー *data = NULL; e->Socket = INVALID_SOCKET; return INFINITE; } else { // パケット読み込み成功 *data = MallocFast(ret); Copy(*data, tmp, ret); return ret; } return 0; }
UINT EthGetPacketLinux(ETH *e, void **data) { int s, ret; UCHAR tmp[UNIX_ETH_TMP_BUFFER_SIZE]; struct iovec msg_iov; struct msghdr msg_header; struct cmsghdr *cmsg; union { struct cmsghdr cmsg; char buf[CMSG_SPACE(sizeof(struct my_tpacket_auxdata))]; } cmsg_buf; // Validate arguments if (e == NULL || data == NULL) { return INFINITE; } if (e->Tap != NULL) { #ifndef NO_VLAN // tap mode void *buf; UINT size; if (VLanGetNextPacket(e->Tap, &buf, &size) == false) { return INFINITE; } *data = buf; return size; #else // NO_VLAN return INFINITE; #endif } s = e->Socket; if (s == INVALID_SOCKET) { return INFINITE; } // Read msg_iov.iov_base = tmp; msg_iov.iov_len = sizeof(tmp); msg_header.msg_name = NULL; msg_header.msg_namelen = 0; msg_header.msg_iov = &msg_iov; msg_header.msg_iovlen = 1; if (e->Linux_IsAuxDataSupported) { memset(&cmsg_buf, 0, sizeof(cmsg_buf)); msg_header.msg_control = &cmsg_buf; msg_header.msg_controllen = sizeof(cmsg_buf); } else { msg_header.msg_control = NULL; msg_header.msg_controllen = 0; } msg_header.msg_flags = 0; ret = recvmsg(s, &msg_header, 0); if (ret == 0 || (ret == -1 && errno == EAGAIN)) { // No packet *data = NULL; return 0; } else if (ret == -1 || ret > sizeof(tmp)) { // Error *data = NULL; e->Socket = INVALID_SOCKET; return INFINITE; } else { bool flag = false; USHORT api_vlan_id = 0; USHORT api_vlan_tpid = 0; if (e->Linux_IsAuxDataSupported) { for (cmsg = CMSG_FIRSTHDR(&msg_header); cmsg; cmsg = CMSG_NXTHDR(&msg_header, cmsg)) { struct my_tpacket_auxdata *aux; UINT len; USHORT vlan_tpid = 0x8100; USHORT vlan_id = 0; if (cmsg->cmsg_len < CMSG_LEN(sizeof(struct my_tpacket_auxdata)) || cmsg->cmsg_level != SOL_PACKET || cmsg->cmsg_type != MY_PACKET_AUXDATA) { continue; } aux = (struct my_tpacket_auxdata *)CMSG_DATA(cmsg); if (aux != NULL) { if (aux->tp_vlan_tci != 0) { vlan_id = aux->tp_vlan_tci; } } if (vlan_id != 0) { api_vlan_id = vlan_id; api_vlan_tpid = vlan_tpid; break; } } if (api_vlan_id != 0 && api_vlan_tpid != 0) { // VLAN ID has been received with PACKET_AUXDATA. // Insert the tag. USHORT vlan_id_ne = Endian16(api_vlan_id); USHORT vlan_tpid_ne = Endian16(api_vlan_tpid); if (ret >= 14) { if (*((USHORT *)(tmp + 12)) != vlan_tpid_ne) { *data = MallocFast(ret + 4); Copy(*data, tmp, 12); Copy(((UCHAR *)*data) + 12, &vlan_tpid_ne, 2); Copy(((UCHAR *)*data) + 14, &vlan_id_ne, 2); Copy(((UCHAR *)*data) + 16, tmp + 12, ret - 12); flag = true; ret += 4; } } } } // Success to read a packet (No VLAN) if (flag == false) { *data = MallocFast(ret); Copy(*data, tmp, ret); } return ret; } return 0; }
// パケットヘッダをコピーする PKT *ClonePacket(PKT *p, bool copy_data) { PKT *ret; // 引数チェック if (p == NULL) { return NULL; } ret = ZeroMallocFast(sizeof(PKT)); ret->PacketSize = p->PacketSize; // MAC ヘッダのコピー ret->MacHeader = MallocFast(sizeof(MAC_HEADER)); Copy(ret->MacHeader, p->MacHeader, sizeof(MAC_HEADER)); // MAC フラグのコピー ret->BroadcastPacket = p->BroadcastPacket; ret->InvalidSourcePacket = p->InvalidSourcePacket; // IPv6 関係構造体のコピー Copy(&ret->IPv6HeaderPacketInfo, &p->IPv6HeaderPacketInfo, sizeof(IPV6_HEADER_PACKET_INFO)); Copy(&ret->ICMPv6HeaderPacketInfo, &p->ICMPv6HeaderPacketInfo, sizeof(ICMPV6_HEADER_INFO)); // Layer 3 ret->TypeL3 = p->TypeL3; switch (ret->TypeL3) { case L3_ARPV4: // ARP パケット ret->L3.ARPv4Header = MallocFast(sizeof(ARPV4_HEADER)); Copy(ret->L3.ARPv4Header, p->L3.ARPv4Header, sizeof(ARPV4_HEADER)); break; case L3_IPV4: // IPv4 パケット ret->L3.IPv4Header = MallocFast(sizeof(IPV4_HEADER)); Copy(ret->L3.IPv4Header, p->L3.IPv4Header, sizeof(IPV4_HEADER)); break; case L3_IPV6: // IPv6 パケット ret->L3.IPv6Header = MallocFast(sizeof(IPV6_HEADER)); Copy(ret->L3.IPv6Header, p->L3.IPv6Header, sizeof(IPV6_HEADER)); ret->IPv6HeaderPacketInfo.IPv6Header = Clone(p->IPv6HeaderPacketInfo.IPv6Header, sizeof(IPV6_HEADER)); ret->IPv6HeaderPacketInfo.HopHeader = Clone(p->IPv6HeaderPacketInfo.HopHeader, sizeof(IPV6_OPTION_HEADER)); ret->IPv6HeaderPacketInfo.EndPointHeader = Clone(p->IPv6HeaderPacketInfo.EndPointHeader, sizeof(IPV6_OPTION_HEADER)); ret->IPv6HeaderPacketInfo.RoutingHeader = Clone(p->IPv6HeaderPacketInfo.RoutingHeader, sizeof(IPV6_OPTION_HEADER)); ret->IPv6HeaderPacketInfo.FragmentHeader = Clone(p->IPv6HeaderPacketInfo.FragmentHeader, sizeof(IPV6_FRAGMENT_HEADER)); ret->IPv6HeaderPacketInfo.Payload = Clone(p->IPv6HeaderPacketInfo.Payload, p->IPv6HeaderPacketInfo.PayloadSize); break; } // Layer 4 ret->TypeL4 = p->TypeL4; switch (ret->TypeL4) { case L4_ICMPV4: // ICMPv4 パケット ret->L4.ICMPHeader = MallocFast(sizeof(ICMP_HEADER)); Copy(ret->L4.ICMPHeader, p->L4.ICMPHeader, sizeof(ICMP_HEADER)); break; case L4_ICMPV6: // ICMPv6 パケット ret->L4.ICMPHeader = MallocFast(sizeof(ICMP_HEADER)); Copy(ret->L4.ICMPHeader, p->L4.ICMPHeader, sizeof(ICMP_HEADER)); ret->ICMPv6HeaderPacketInfo.Data = Clone(p->ICMPv6HeaderPacketInfo.Data, p->ICMPv6HeaderPacketInfo.DataSize); ret->ICMPv6HeaderPacketInfo.EchoData = Clone(p->ICMPv6HeaderPacketInfo.EchoData, p->ICMPv6HeaderPacketInfo.EchoDataSize); switch (ret->ICMPv6HeaderPacketInfo.Type) { case ICMPV6_TYPE_ECHO_REQUEST: case ICMPV6_TYPE_ECHO_RESPONSE: break; case ICMPV6_TYPE_ROUTER_SOLICIATION: ret->ICMPv6HeaderPacketInfo.Headers.RouterSoliciationHeader = Clone(p->ICMPv6HeaderPacketInfo.Headers.RouterSoliciationHeader, sizeof(ICMPV6_ROUTER_SOLICIATION_HEADER)); break; case ICMPV6_TYPE_ROUTER_ADVERTISEMENT: ret->ICMPv6HeaderPacketInfo.Headers.RouterAdvertisementHeader = Clone(p->ICMPv6HeaderPacketInfo.Headers.RouterAdvertisementHeader, sizeof(ICMPV6_ROUTER_ADVERTISEMENT_HEADER)); break; case ICMPV6_TYPE_NEIGHBOR_SOLICIATION: ret->ICMPv6HeaderPacketInfo.Headers.NeighborSoliciationHeader = Clone(p->ICMPv6HeaderPacketInfo.Headers.NeighborSoliciationHeader, sizeof(ICMPV6_NEIGHBOR_SOLICIATION_HEADER)); break; case ICMPV6_TYPE_NEIGHBOR_ADVERTISEMENT: ret->ICMPv6HeaderPacketInfo.Headers.NeighborAdvertisementHeader = Clone(p->ICMPv6HeaderPacketInfo.Headers.NeighborAdvertisementHeader, sizeof(ICMPV6_NEIGHBOR_ADVERTISEMENT_HEADER)); break; } CloneICMPv6Options(&ret->ICMPv6HeaderPacketInfo.OptionList, &p->ICMPv6HeaderPacketInfo.OptionList); break; case L4_TCP: // TCP パケット ret->L4.TCPHeader = MallocFast(sizeof(TCP_HEADER)); Copy(ret->L4.TCPHeader, p->L4.TCPHeader, sizeof(TCP_HEADER)); break; case L4_UDP: // UDP パケット ret->L4.UDPHeader = MallocFast(sizeof(UDP_HEADER)); Copy(ret->L4.UDPHeader, p->L4.UDPHeader, sizeof(UDP_HEADER)); break; } // Layer 7 ret->TypeL7 = p->TypeL7; switch (ret->TypeL7) { case L7_DHCPV4: // DHCP パケット ret->L7.DHCPv4Header = MallocFast(sizeof(DHCPV4_HEADER)); Copy(ret->L7.DHCPv4Header, p->L7.DHCPv4Header, sizeof(DHCPV4_HEADER)); break; } // アドレスデータ ret->MacAddressSrc = ret->MacHeader->SrcAddress; ret->MacAddressDest = ret->MacHeader->DestAddress; if (copy_data) { // パケット本体もコピー ret->PacketData = MallocFast(p->PacketSize); Copy(ret->PacketData, p->PacketData, p->PacketSize); } return ret; }