/* Ido Barnea Cisco Systems, Inc. */ /* Copyright (c) 2016-2016 Cisco Systems, Inc. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include #include #include #include #include #include #include #include #include "rx_check_header.h" #include "test_pkt_gen.h" // For use in tests char *CTestPktGen::create_test_pkt(uint16_t l3_type, uint16_t l4_proto, uint8_t ttl, uint32_t ip_id, uint16_t flags , uint16_t max_payload, int &pkt_size) { // ASA 2 uint8_t dst_mac[6] = {0x74, 0xa2, 0xe6, 0xd5, 0x39, 0x25}; uint8_t src_mac[6] = {0xa0, 0x36, 0x9f, 0x38, 0xa4, 0x02}; uint8_t vlan_header[4] = {0x0a, 0xbc, 0x00, 0x00}; // we set the type below according to if pkt is ipv4 or 6 uint8_t vlan_header2[4] = {0x0a, 0xbc, 0x88, 0xa8}; uint16_t l2_proto; uint16_t payload_len; // ASA 1 // uint8_t dst_mac[6] = {0xd4, 0x8c, 0xb5, 0xc9, 0x54, 0x2b}; // uint8_t src_mac[6] = {0xa0, 0x36, 0x9f, 0x38, 0xa4, 0x0}; if (flags & DPF_VLAN) { l2_proto = 0x0081; } else { l2_proto = htons(l3_type); } uint8_t ip_header[] = { 0x45,0x02,0x00,0x30, 0x00,0x00,0x40,0x00, 0xff,0x01,0xbd,0x04, 0x10,0x0,0x0,0x1, //SIP 0x30,0x0,0x0,0x1, //DIP // 0x82, 0x0b, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // IP option. change 45 to 48 (header len) if using it. }; uint8_t ipv6_header[] = { 0x60,0x00,0xff,0x30, // traffic class + flow label 0x00,0x00,0x40,0x00, // payload len + next header + hop limit 0x10,0x0,0x0,0x1,0x10,0x0,0x0,0x1,0x10,0x0,0x0,0x1,0x10,0x0,0x0,0x1, //SIP 0x30,0x0,0x0,0x1,0x10,0x0,0x0,0x1,0x30,0x0,0x0,0x1,0x10,0x0,0x0,0x1, //DIP }; uint8_t udp_header[] = {0x11, 0x11, 0x11,0x11, 0x00, 0x6d, 0x00, 0x00}; uint8_t udp_data[] = {0x64,0x31,0x3a,0x61, 0x64,0x32,0x3a,0x69,0x64, 0x32,0x30,0x3a,0xd0,0x0e, 0xa1,0x4b,0x7b,0xbd,0xbd, 0x16,0xc6,0xdb,0xc4,0xbb,0x43, 0xf9,0x4b,0x51,0x68,0x33,0x72, 0x20,0x39,0x3a,0x69,0x6e,0x66,0x6f, 0x5f,0x68,0x61,0x73,0x68,0x32,0x30,0x3a,0xee,0xc6,0xa3, 0xd3,0x13,0xa8,0x43,0x06,0x03,0xd8,0x9e,0x3f,0x67,0x6f, 0xe7,0x0a,0xfd,0x18,0x13,0x8d,0x65,0x31,0x3a,0x71,0x39, 0x3a,0x67,0x65,0x74,0x5f,0x70,0x65,0x65,0x72,0x73,0x31, 0x3a,0x74,0x38,0x3a,0x3d,0xeb,0x0c,0xbf,0x0d,0x6a,0x0d, 0xa5,0x31,0x3a,0x79,0x31,0x3a,0x71,0x65,0x87,0xa6,0x7d, 0xe7 }; uint8_t tcp_header[] = {0xab, 0xcd, 0x00, 0x80, // src, dst ports 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, // seq num, ack num 0x50, 0x00, 0xff, 0xff, // Header size, flags, window size 0x00, 0x00, 0x00, 0x00, // checksum ,urgent pointer }; uint8_t tcp_data[] = {0x8, 0xa, 0x1, 0x2, 0x3, 0x4, 0x3, 0x4, 0x6, 0x5, 0x8, 0xa, 0x1, 0x2, 0x3, 0x4, 0x3, 0x4, 0x6, 0x5}; uint8_t icmp_header[] = { 0x08, 0x00, 0xb8, 0x21, //checksum 0xaa, 0xbb, // id 0x00, 0x01, // Sequence number }; uint8_t icmp_data[] = { 0xd6, 0x6e, 0x64, 0x34, // magic 0x6a, 0xad, 0x0f, 0x00, //64 bit counter 0x00, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12, 0x00, 0x00 // seq }; pkt_size = 14; if (flags & DPF_VLAN) { pkt_size += 4; if (flags & DPF_QINQ) { pkt_size += 4; } } switch(l3_type) { case EthernetHeader::Protocol::IP: pkt_size += sizeof(ip_header); break; case EthernetHeader::Protocol::IPv6: pkt_size += sizeof(ipv6_header); if (flags & DPF_RXCHECK) { pkt_size += sizeof(struct CRx_check_header); } break; } switch (l4_proto) { case IPPROTO_ICMP: pkt_size += sizeof(icmp_header); payload_len = (max_payload < sizeof(icmp_data)) ? max_payload:sizeof(icmp_data); pkt_size += payload_len; break; case IPPROTO_UDP: pkt_size += sizeof(udp_header); payload_len = (max_payload < sizeof(udp_data)) ? max_payload:sizeof(udp_data); pkt_size += payload_len; break; case IPPROTO_TCP: pkt_size += sizeof(tcp_header); payload_len = (max_payload < sizeof(tcp_data)) ? max_payload:sizeof(tcp_data); pkt_size += payload_len; break; default: payload_len = (max_payload < sizeof(udp_data)) ? max_payload:sizeof(udp_data); pkt_size += payload_len; break; } char *p_start = (char *)malloc(pkt_size); assert(p_start); char *p = p_start; /* set pkt data */ memcpy(p, dst_mac, sizeof(dst_mac)); p += sizeof(dst_mac); memcpy(p, src_mac, sizeof(src_mac)); p += sizeof(src_mac); memcpy(p, &l2_proto, sizeof(l2_proto)); p += sizeof(l2_proto); if (flags & DPF_VLAN) { if (flags & DPF_QINQ) { memcpy(p, &vlan_header2, sizeof(vlan_header2)); p += sizeof(vlan_header2); } uint16_t l3_type_htons = htons(l3_type); memcpy(&vlan_header[2], &l3_type_htons, sizeof(l3_type)); memcpy(p, &vlan_header, sizeof(vlan_header)); p += sizeof(vlan_header); } struct IPHeader *ip = (IPHeader *)p; struct IPv6Header *ipv6 = (IPv6Header *)p; switch(l3_type) { case EthernetHeader::Protocol::IP: memcpy(p, ip_header, sizeof(ip_header)); p += sizeof(ip_header); ip->setProtocol(l4_proto); ip->setTotalLength(pkt_size - 14); ip->setId(ip_id); break; case EthernetHeader::Protocol::IPv6: memcpy(p, ipv6_header, sizeof(ipv6_header)); p += sizeof(ipv6_header); if (flags & DPF_RXCHECK) { // rx check header ipv6->setNextHdr(RX_CHECK_V6_OPT_TYPE); if (flags & DPF_RXCHECK) { struct CRx_check_header *rxch = (struct CRx_check_header *)p; p += sizeof(CRx_check_header); rxch->m_option_type = l4_proto; rxch->m_option_len = RX_CHECK_V6_OPT_LEN; } } else { ipv6->setNextHdr(l4_proto); } ipv6->setPayloadLen(pkt_size - 14 - sizeof(ipv6_header)); ipv6->setFlowLabel(ip_id); break; } struct TCPHeader *tcp = (TCPHeader *)p; struct ICMPHeader *icmp= (ICMPHeader *)p; switch (l4_proto) { case IPPROTO_ICMP: memcpy(p, icmp_header, sizeof(icmp_header)); p += sizeof(icmp_header); memcpy(p, icmp_data, payload_len); p += payload_len; icmp->updateCheckSum(sizeof(icmp_header) + sizeof(icmp_data)); break; case IPPROTO_UDP: memcpy(p, udp_header, sizeof(udp_header)); p += sizeof(udp_header); memcpy(p, udp_data, payload_len); p += payload_len; break; case IPPROTO_TCP: memcpy(p, tcp_header, sizeof(tcp_header)); p += sizeof(tcp_header); memcpy(p, tcp_data, payload_len); p += payload_len; tcp->setSynFlag(false); // printf("Sending TCP header:"); //tcp->dump(stdout); break; default: memcpy(p, udp_data, payload_len); p += payload_len; break; } switch(l3_type) { case EthernetHeader::Protocol::IP: ip->setTimeToLive(ttl); ip->updateCheckSum(); break; case EthernetHeader::Protocol::IPv6: ipv6->setHopLimit(ttl); break; } return p_start; }