init
This commit is contained in:
commit
d55ff5a0fb
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
.idea
|
||||
cmake-*
|
6
CMakeLists.txt
Normal file
6
CMakeLists.txt
Normal file
@ -0,0 +1,6 @@
|
||||
cmake_minimum_required(VERSION 3.24)
|
||||
project(icmpv6_echo C)
|
||||
|
||||
set(CMAKE_C_STANDARD 23)
|
||||
|
||||
add_executable(icmpv6_echo main.c)
|
27
README.md
Normal file
27
README.md
Normal file
@ -0,0 +1,27 @@
|
||||
# Build IPv6 ICMP ECHO packet with Ethernet headers
|
||||
|
||||
* https://en.wikipedia.org/wiki/Ethernet_frame
|
||||
* https://en.wikipedia.org/wiki/IPv6_packet
|
||||
* https://en.wikipedia.org/wiki/Internet_Control_Message_Protocol_for_IPv6
|
||||
* https://www.pdbuchan.com/rawsock/icmp6_cooked.c
|
||||
* https://stackoverflow.com/a/14937171
|
||||
* https://github.com/secdev/scapy/blob/a1f999fb1721a64415af75d575cabde19625a6f5/scapy/utils.py#L493-L501
|
||||
* https://github.com/secdev/scapy/blob/master/scapy/layers/inet6.py#L608-L624
|
||||
|
||||
## Scapy code samples
|
||||
Writen in `scapy` shell
|
||||
|
||||
```python
|
||||
# import hex as packet
|
||||
e = Ether(bytes.fromhex('fc de ad be ef 05 fc de ad be ef 56 86 dd 60 00 00 00 00 08 3a 02 fe 80 00 00 00 00 00 00 00 00 00 00 00 00 00 01 fe 80 00 00 00 00 00 00 50 5d 18 fb 5e 52 ec c0 81 00 4e cd 00 00 00 00 ef be ad de'))
|
||||
e.show()
|
||||
|
||||
# Write packet as pcap to open in Wireshark
|
||||
wrpcap("test.pcap", e)
|
||||
|
||||
# Calculate icmpv6 checksum
|
||||
i = e[IPv6][ICMPv6EchoReply]
|
||||
i.cksum = 0
|
||||
r = raw(i)
|
||||
print(hex(in6_chksum(socket.IPPROTO_ICMPV6, e[IPv6], r)))
|
||||
```
|
140
main.c
Normal file
140
main.c
Normal file
@ -0,0 +1,140 @@
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
struct ethernet_header {
|
||||
uint8_t dest[6];
|
||||
uint8_t src[6];
|
||||
uint16_t ethertype;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct ipv6_header {
|
||||
uint32_t vtf;
|
||||
/*uint32_t version :4;
|
||||
uint32_t traffic_class :8;
|
||||
uint32_t flow_label :20;*/
|
||||
uint16_t len;
|
||||
uint8_t next_header;
|
||||
uint8_t hop_limit;
|
||||
|
||||
uint8_t src[16];
|
||||
uint8_t dest[16];
|
||||
} __attribute__((packed));
|
||||
|
||||
struct icmpv6_header {
|
||||
uint8_t type;
|
||||
uint8_t code;
|
||||
uint16_t checksum;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct ipv6_pseudo {
|
||||
uint8_t src[16];
|
||||
uint8_t dest[16];
|
||||
uint32_t len;
|
||||
uint32_t zeros :24;
|
||||
uint32_t next_header :8;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct icmpv6_echo {
|
||||
uint16_t identifier;
|
||||
uint16_t sequence;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct packet {
|
||||
struct ethernet_header eth;
|
||||
struct ipv6_header ip6;
|
||||
struct icmpv6_header icmp;
|
||||
struct icmpv6_echo echo;
|
||||
uint32_t ethernet_frame_check;
|
||||
} __attribute__((packed));
|
||||
|
||||
uint16_t checksum (uint16_t *addr, size_t bytes) {
|
||||
unsigned int i;
|
||||
uint16_t *p = addr;
|
||||
uint32_t sum = 0;
|
||||
|
||||
/* Sum */
|
||||
for (i=bytes; i > 1; i -= 2)
|
||||
sum += *p++;
|
||||
|
||||
/* If uneven length */
|
||||
if (i > 0)
|
||||
sum += (uint16_t) *((unsigned char *) (p));
|
||||
|
||||
/* Carry */
|
||||
while ((sum & 0xFFFF0000) != 0)
|
||||
sum = (sum >> 16) + (sum & 0xFFFF);
|
||||
|
||||
return ~((uint16_t) sum);
|
||||
}
|
||||
|
||||
uint16_t calc_icmpv6_checksum(struct ipv6_header *ip6_header, void *data, size_t len) {
|
||||
uint8_t buf[1500] = {};
|
||||
struct ipv6_pseudo pseudo = {};
|
||||
|
||||
memcpy(pseudo.src, ip6_header->src, sizeof(ip6_header->src));
|
||||
memcpy(pseudo.dest, ip6_header->dest, sizeof(ip6_header->dest));
|
||||
pseudo.next_header = ip6_header->next_header;
|
||||
pseudo.len = htonl(len);
|
||||
|
||||
memcpy(buf, &pseudo, sizeof(pseudo));
|
||||
memcpy(buf + sizeof(pseudo), data, len);
|
||||
|
||||
return checksum(&buf, sizeof(pseudo) + len);
|
||||
}
|
||||
|
||||
int main() {
|
||||
struct packet pkt;
|
||||
|
||||
uint8_t eth_dest[] = {0xfc, 0xde, 0xad, 0xbe, 0xef, 0x05};
|
||||
uint8_t eth_src[] = {0xfc, 0xde, 0xad, 0xbe, 0xef, 0x56};
|
||||
memcpy(pkt.eth.dest, eth_dest, sizeof(pkt.eth.dest));
|
||||
memcpy(pkt.eth.src, eth_src, sizeof(pkt.eth.src));
|
||||
|
||||
pkt.eth.ethertype = 0xdd86; // ipv6
|
||||
|
||||
pkt.ip6.vtf = htonl ((6 << 28) | (0 << 20) | 0);
|
||||
/*pkt.ip6.version = 6;
|
||||
pkt.ip6.traffic_class = 0;
|
||||
pkt.ip6.flow_label = 0;*/
|
||||
pkt.ip6.len = htons(sizeof(struct icmpv6_header) + sizeof(struct icmpv6_echo));
|
||||
pkt.ip6.next_header = 0x3a; // ipv6-icmp
|
||||
pkt.ip6.hop_limit = 2;
|
||||
|
||||
uint8_t ipv6_src[] = {
|
||||
0xfe, 0x80, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x01
|
||||
};
|
||||
uint8_t ipv6_dest[] = {
|
||||
0xfe, 0x80, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x50, 0x5d, 0x18, 0xfb,
|
||||
0x5e, 0x52, 0xec, 0xc0,
|
||||
};
|
||||
memcpy(pkt.ip6.src, ipv6_src, sizeof(pkt.ip6.src));
|
||||
memcpy(pkt.ip6.dest, ipv6_dest, sizeof(pkt.ip6.dest));
|
||||
|
||||
pkt.icmp.type = 129; // icmp reply
|
||||
pkt.icmp.checksum = 0;
|
||||
|
||||
pkt.echo.identifier = 0;
|
||||
pkt.echo.sequence = 0;
|
||||
|
||||
pkt.icmp.checksum = calc_icmpv6_checksum(&pkt.ip6, &pkt.icmp, sizeof(struct icmpv6_header) + sizeof(struct icmpv6_echo));
|
||||
|
||||
pkt.ethernet_frame_check = 0xdeadbeef;
|
||||
|
||||
printf("sizeof(pkt) = %lu, pointer %p\n", sizeof(pkt), &pkt);
|
||||
printf("checksum %#x\n", pkt.icmp.checksum);
|
||||
|
||||
int i;
|
||||
for (i=0; i < sizeof(pkt); i++) {
|
||||
printf("%02x ", *(((uint8_t *)&pkt) + i));
|
||||
}
|
||||
printf("\n%d", i);
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user