Repository navigation
Expand file tree
/
Copy pathipv6.cpp
More file actions
147 lines (114 loc) · 4.62 KB
/
Copy pathipv6.cpp
File metadata and controls
147 lines (114 loc) · 4.62 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
#include "ipv6.h"
#include "binary_trie.h"
#include "config.h"
#include "ethernet.h"
#include "icmpv6.h"
#include "log.h"
#include "my_buf.h"
#include "nat.h"
#include "nd.h"
#include "utils.h"
/**
* IPv6パケットの受信処理
* @param input_dev
* @param buffer
* @param len
*/
char ipv6ascii[4*16+15+1];
char* ipv6toascii(ipv6_addr addr){
sprintf(ipv6ascii, "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x", ntohs(addr.per_16.int1), ntohs(addr.per_16.int2), ntohs(addr.per_16.int3),
ntohs(addr.per_16.int4), ntohs(addr.per_16.int5), ntohs(addr.per_16.int6), ntohs(addr.per_16.int7),
ntohs(addr.per_16.int8));
return ipv6ascii;
}
/**
* 自分宛のIPパケットの処理
* @param input_dev
* @param ip_packet
* @param len
*/
void ipv6_input_to_ours(net_device *input_dev, ipv6_header *packet, size_t len) {
switch (packet->next_hdr) {
case IPV6_PROTOCOL_NUM_ICMP:
return icmpv6_input(input_dev->ipv6_dev, packet->src_addr, packet->dest_addr, ((uint8_t *)packet) + sizeof(ipv6_header), len - sizeof(ipv6_header));
default:
break;
}
}
void ipv6_input(net_device *input_dev, uint8_t *buffer, ssize_t len) {
if(input_dev->ipv6_dev == nullptr){
LOG_IPV6("Received IPv6 packet from non ipv6 device %s\n", input_dev->name);
return;
}
if (len < sizeof(ipv6_addr)) {
LOG_IPV6("Received IPv6 packet too short from %s\n", input_dev->name);
return;
}
// 送られてきたバッファをキャストして扱う
ipv6_header *packet = reinterpret_cast<ipv6_header *>(buffer);
if (packet->ver_tc_fl & 0b1111 != 6) {
return;
}
LOG_IPV6("Next header: 0x%02x\n", packet->next_hdr);
LOG_IPV6("Src: %s\n", ipv6toascii(packet->src_addr));
LOG_IPV6("Dst: %s\n", ipv6toascii(packet->dest_addr));
// 宛先IPアドレスをルータが持ってるか調べる
for (net_device *dev = net_dev_list; dev; dev = dev->next) {
if (dev->ipv6_dev != nullptr) {
// 宛先IPアドレスがルータの持っているIPアドレスの処理
if (memcmp(&dev->ipv6_dev->address, &packet->dest_addr, 16) == 0) {
return ipv6_input_to_ours(dev, packet, len); // 自分宛の通信として処理
}
}
}
// ルーティングのための処理
}
void ipv6_encap_dev_output(net_device* output_dev, const uint8_t* dest_mac_addr, ipv6_addr dest_addr, my_buf* buffer, uint8_t next_hdr_num){
// 連結リストをたどってIPヘッダで必要なIPパケットの全長を算出する
uint16_t payload_len = 0;
my_buf *current = buffer;
while (current != nullptr) {
payload_len += current->len;
current = current->next;
}
// IPv6ヘッダ用のバッファを確保する
my_buf *v6h_mybuf = my_buf::create(sizeof(ipv6_header));
buffer->add_header(v6h_mybuf); // 包んで送るデータにヘッダとして連結する
// IPヘッダの各項目を設定
ipv6_header *v6h_buf = reinterpret_cast<ipv6_header *>(v6h_mybuf->buffer);
v6h_buf->ver_tc_fl = 0x60;
v6h_buf->payload_len = htons(payload_len);
v6h_buf->next_hdr = next_hdr_num;
v6h_buf->hop_limit = 0xff;
v6h_buf->src_addr = output_dev->ipv6_dev->address;
v6h_buf->dest_addr = dest_addr;
ethernet_encapsulate_output(output_dev, dest_mac_addr, v6h_mybuf, ETHER_TYPE_IPV6);
}
void ipv6_output_to_nexthop(ipv6_addr dest_addr, ipv6_addr src_addr, my_buf* buffer){
nd_table_entry *entry = search_nd_table_entry(dest_addr);
if(entry != nullptr){
LOG_IP("Found entry!\n");
ethernet_encapsulate_output(entry->dev, entry->mac_addr, buffer, ETHER_TYPE_IPV6);
}
}
void ipv6_encap_output(ipv6_addr dest_addr, ipv6_addr src_addr, my_buf* buffer, uint8_t next_hdr_num){
// 連結リストをたどってIPヘッダで必要なIPパケットの全長を算出する
uint16_t payload_len = 0;
my_buf *current = buffer;
while (current != nullptr) {
payload_len += current->len;
current = current->next;
}
// IPv6ヘッダ用のバッファを確保する
my_buf *v6h_mybuf = my_buf::create(sizeof(ipv6_header));
buffer->add_header(v6h_mybuf); // 包んで送るデータにヘッダとして連結する
// IPヘッダの各項目を設定
ipv6_header *v6h_buf = reinterpret_cast<ipv6_header *>(v6h_mybuf->buffer);
v6h_buf->ver_tc_fl = 0x60;
v6h_buf->payload_len = htons(payload_len);
v6h_buf->next_hdr = next_hdr_num;
v6h_buf->hop_limit = 0xff;
v6h_buf->src_addr = src_addr;
v6h_buf->dest_addr = dest_addr;
ipv6_output_to_nexthop(dest_addr, src_addr, v6h_mybuf);
}