#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; } }