NDIS_STATUS OvsSlowPathDecapVxlan(const PNET_BUFFER_LIST packet, OvsIPv4TunnelKey *tunnelKey) { NDIS_STATUS status = NDIS_STATUS_FAILURE; UDPHdr udpStorage; const UDPHdr *udp; VXLANHdr *VxlanHeader; VXLANHdr VxlanHeaderBuffer; struct IPHdr ip_storage; const struct IPHdr *nh; OVS_PACKET_HDR_INFO layers; layers.value = 0; do { nh = OvsGetIp(packet, layers.l3Offset, &ip_storage); if (nh) { layers.l4Offset = layers.l3Offset + nh->ihl * 4; } else { break; } /* make sure it's a VXLAN packet */ udp = OvsGetUdp(packet, layers.l4Offset, &udpStorage); if (udp) { layers.l7Offset = layers.l4Offset + sizeof *udp; } else { break; } /* XXX Should be tested against the dynamic port # in the VXLAN vport */ ASSERT(udp->dest == RtlUshortByteSwap(VXLAN_UDP_PORT)); VxlanHeader = (VXLANHdr *)OvsGetPacketBytes(packet, sizeof(*VxlanHeader), layers.l7Offset, &VxlanHeaderBuffer); if (VxlanHeader) { tunnelKey->src = nh->saddr; tunnelKey->dst = nh->daddr; tunnelKey->ttl = nh->ttl; tunnelKey->tos = nh->tos; if (VxlanHeader->instanceID) { tunnelKey->flags = OVS_TNL_F_KEY; tunnelKey->tunnelId = VXLAN_VNI_TO_TUNNELID(VxlanHeader->vxlanID); } else { tunnelKey->flags = 0; tunnelKey->tunnelId = 0; } } else { break; } status = NDIS_STATUS_SUCCESS; } while(FALSE); return status; }
/* * -------------------------------------------------------------------------- * GetSegmentHeaderInfo * * Extract header size and sequence number for the segment. * -------------------------------------------------------------------------- */ static NDIS_STATUS GetSegmentHeaderInfo(PNET_BUFFER_LIST nbl, const POVS_PACKET_HDR_INFO hdrInfo, UINT32 *hdrSize, UINT32 *seqNumber) { TCPHdr tcpStorage; const TCPHdr *tcp; /* Parse the orginal Eth/IP/TCP header */ tcp = OvsGetPacketBytes(nbl, sizeof *tcp, hdrInfo->l4Offset, &tcpStorage); if (tcp == NULL) { return NDIS_STATUS_FAILURE; } *seqNumber = ntohl(tcp->seq); *hdrSize = hdrInfo->l4Offset + TCP_HDR_LEN(tcp); return NDIS_STATUS_SUCCESS; }
/* *---------------------------------------------------------------------------- * OvsCtHandleFtp * Extract the FTP control data from the packet and created a related * entry if it's a valid connection. This method doesn't support extended * FTP yet. Supports PORT and PASV commands. * Eg: * 'PORT 192,168,137,103,192,22\r\n' -> '192.168.137.103' and 49174 * '227 Entering Passive Mode (192,168,137,104,194,14)\r\n' gets extracted * to '192.168.137.104' and 49678 *---------------------------------------------------------------------------- */ NDIS_STATUS OvsCtHandleFtp(PNET_BUFFER_LIST curNbl, OvsFlowKey *key, OVS_PACKET_HDR_INFO *layers, UINT64 currentTime, POVS_CT_ENTRY entry, BOOLEAN request) { NDIS_STATUS status; FTP_TYPE ftpType = 0; const char *buf; char temp[256] = { 0 }; char ftpMsg[256] = { 0 }; TCPHdr tcpStorage; const TCPHdr *tcp; tcp = OvsGetTcp(curNbl, layers->l4Offset, &tcpStorage); if (!tcp) { return NDIS_STATUS_INVALID_PACKET; } UINT32 len = OvsGetTcpPayloadLength(curNbl); if (len > sizeof(temp)) { /* We only care up to 256 */ len = sizeof(temp); } buf = OvsGetPacketBytes(curNbl, len, layers->l4Offset + TCP_HDR_LEN(tcp), temp); if (buf == NULL) { return NDIS_STATUS_INVALID_PACKET; } OvsStrlcpy((char *)ftpMsg, (char *)buf, min(len, sizeof(ftpMsg))); char *req = NULL; if (request) { if ((len >= 5) && (OvsStrncmp("PORT", ftpMsg, 4) == 0)) { ftpType = FTP_TYPE_ACTIVE; req = ftpMsg + 4; } } else { if ((len >= 4) && (OvsStrncmp(FTP_PASV_RSP_PREFIX, ftpMsg, 3) == 0)) { ftpType = FTP_TYPE_PASV; /* There are various formats for PASV command. We try to support * some of them. This has been addressed by RFC 2428 - EPSV. * Eg: * 227 Entering Passive Mode (h1,h2,h3,h4,p1,p2). * 227 Entering Passive Mode (h1,h2,h3,h4,p1,p2 * 227 Entering Passive Mode. h1,h2,h3,h4,p1,p2 * 227 =h1,h2,h3,h4,p1,p2 */ char *paren; paren = strchr(ftpMsg, '('); if (paren) { req = paren + 1; } else { /* PASV command without ( */ req = ftpMsg + 3; } } } if (req == NULL) { /* Not a PORT/PASV control packet */ return NDIS_STATUS_SUCCESS; } UINT32 arr[6] = {0}; status = OvsCtExtractNumbers(req, len, arr, 6, ','); if (status != NDIS_STATUS_SUCCESS) { return status; } UINT32 ip = ntohl((arr[0] << 24) | (arr[1] << 16) | (arr[2] << 8) | arr[3]); UINT16 port = ntohs(((arr[4] << 8) | arr[5])); switch (ftpType) { case FTP_TYPE_PASV: /* Ensure that the command states Server's IP address */ ASSERT(ip == key->ipKey.nwSrc); OvsCtRelatedEntryCreate(key->ipKey.nwProto, key->l2.dlType, /* Server's IP */ ip, /* Use intended client's IP */ key->ipKey.nwDst, /* Dynamic port opened on server */ port, /* We don't know the client port */ 0, currentTime, entry); break; case FTP_TYPE_ACTIVE: OvsCtRelatedEntryCreate(key->ipKey.nwProto, key->l2.dlType, /* Server's default IP address */ key->ipKey.nwDst, /* Client's IP address */ ip, /* FTP Data Port is 20 */ ntohs(IPPORT_FTP_DATA), /* Port opened up on Client */ port, currentTime, entry); break; default: OVS_LOG_ERROR("invalid ftp type:%d", ftpType); status = NDIS_STATUS_INVALID_PARAMETER; break; } return status; }