coppino/ipv6.ino

110 lines
3.0 KiB
C++

#include "ipv6.h"
namespace ipv6 {
/******** costants ********/
IPv6Addr ALL_NODES_ADDRESS("\xff\x02\x00\x00\x00\x00\x00\x00\x01"); /* ff02::1 */
/******** IPv6Addr ********/
IPv6Addr::IPv6Addr() {;}
IPv6Addr::IPv6Addr(const char* address) {
this->deserialize(address);
}
void IPv6Addr::deserialize(const char* address) {
memcpy(this->address, address, 16);
}
const char* IPv6Addr::serialize() {
return this->address;
}
/******** IPv6Packet ********/
char* IPv6Packet::serialize() { /* do we actually need these function? everything is already store in a tokenized/serialized form */
return packet;
}
void IPv6Packet::deserialize(const char* buffer, uint8_t len) {
memcpy(packet, buffer, len);
}
void IPv6Packet::setNextHeader(uint8_t next_header) {
*(packet + 6) = next_header;
}
void IPv6Packet::setSrcAddress(IPv6Addr& address) {
memcpy(packet + 8, (void*)&address, 16);
}
void IPv6Packet::setDstAddress(IPv6Addr& address) {
memcpy(packet + 24, (void*)&address, 16);
}
void IPv6Packet::setPayload(char* payload, uint8_t len) {
memset(packet, 0, LEN);
ipv6_packet_header* header = (ipv6_packet_header*)packet;
memcpy(header->field, "\x60\x00\x00\x00", 4);
memcpy(header->len + 1, (char*)&len, 1);
header->hop_limit = 64;
memcpy(packet + sizeof(ipv6_packet_header), payload, len);
}
void IPv6Packet::doAction() {
/* if destination is my address, or destination is "all nodes" address, then... */
if ((memcmp(&(ALL_NODES_ADDRESS), packet + 24, 16) == 0) || (memcmp(&(coppino::address), packet + 24, 16) == 0)) {
int len = ((*(packet + 4)) << 8) + (*(packet + 5));
switch(*(packet + 6)) { /* next header */
case 58:
handleICMP(packet + 8, packet + 24, packet + 40, len);
break;
case 17:
// handleUDP(packet + 40, len);
break;
default:
/* no other protocols are known here, sorry :-) */
break;
}
}
}
void handleICMP(const char* src_addr, const char* dst_addr, char* packet, int len) {
uint8_t type = *(packet);
uint32_t checksum = ((*(packet + 2)) << 8) + (*(packet + 3));
uint16_t part;
IPv6Addr dst;
int i;
switch (type) {
case 128:
/* TODO compute checksum, and assert validity of incoming message */
/* then... */
/* Build an echo reply:
* the reply has the same exact format of the request,
* except for Type and Checksum */
*(packet) = 129; /* echo reply type */
*(packet + 2) = *(packet + 3) = 0; /* zero-checksum */
checksum = coppino::compute_checksum(src_addr, dst_addr, 58, packet, len);
memcpy(packet + 2, &checksum, 2);
IPv6Packet reply_packet;
reply_packet.setPayload(packet, len);
reply_packet.setSrcAddress(coppino::address);
dst.deserialize(src_addr);
reply_packet.setDstAddress(dst);
reply_packet.setNextHeader(58); // ICMPv6
slip::send((void*)&reply_packet, 40 + len);
break;
default:
/* no other types have been implemented */
break;
}
return;
}
}