From 339de9322fd099272e7cc31687837fdfb8591c95 Mon Sep 17 00:00:00 2001 From: giomba Date: Tue, 24 Dec 2019 17:59:51 +0100 Subject: [PATCH] software engineering for best resource management actually only one packet is managed at a time, then a packetin+packetout buffer area has been created for IPv6 packets. Upper layers can then access this data by means of pointer, avoiding further allocations on the stack. Obviously, packetin is read-only (eg. upper layers can only read it) --- coppino.ino | 7 ++--- ipv6.h | 8 +++++- ipv6.ino | 75 +++++++++++++++++++++++++++++++++++++---------------- 3 files changed, 62 insertions(+), 28 deletions(-) diff --git a/coppino.ino b/coppino.ino index b473daa..144050f 100644 --- a/coppino.ino +++ b/coppino.ino @@ -4,13 +4,10 @@ namespace coppino { ipv6::IPv6Addr address; void handler() { - - char buffer[LEN]; int r; - while ((r = slip::recv(buffer, LEN)) != -1) { - ipv6::IPv6Packet packet(buffer, r); - packet.doAction(); + while ((r = slip::recv((char*)&ipv6::packetin, LEN)) != -1) { + ipv6::packetin.doAction(); } } diff --git a/ipv6.h b/ipv6.h index 8c2e592..15764d5 100644 --- a/ipv6.h +++ b/ipv6.h @@ -35,8 +35,11 @@ namespace ipv6 { public: IPv6Packet(); IPv6Packet(const char* buffer, int len); + void IPv6Packet::setLen(int len); void setSrcAddress(const IPv6Addr* address); + const IPv6Addr* getSrcAddress(); void setDstAddress(const IPv6Addr* address); + const IPv6Addr* getDstAddress(); void setNextHeader(uint8_t next_header); void setFlow(const char* flow); void setPayload(char* payload, int len); @@ -44,8 +47,11 @@ namespace ipv6 { void doAction(); }; + extern IPv6Packet packetin; + extern IPv6Packet packetout; + /* Note: content of message may be changed */ - void handleICMP(const IPv6Addr* src, const IPv6Addr* dst, const char* flow, char* message, int len); + int handleICMP(char* output_buffer, const char* input_buffer, int len); /* Compute internet checksum. Actually it is not so straightforward: */ uint16_t compute_checksum( diff --git a/ipv6.ino b/ipv6.ino index 8dfd247..74ae7c3 100644 --- a/ipv6.ino +++ b/ipv6.ino @@ -5,6 +5,10 @@ namespace ipv6 { /******** costants ********/ const IPv6Addr ALL_NODES_ADDRESS("\xff\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01"); /* ff02::1 */ +/******** buffer ********/ +IPv6Packet packetin; +IPv6Packet packetout; + /******** FUNCTIONS *******/ uint16_t compute_checksum(const IPv6Addr* src_addr, const IPv6Addr* dst_addr, uint8_t next_header, int upper_len, const char* payload, int len) { char buffer[LEN]; @@ -67,6 +71,11 @@ void IPv6Packet::setNextHeader(uint8_t next_header) { *(packet + 6) = next_header; } +void IPv6Packet::setLen(int len) { + *(packet + 4) = len >> 8; + *(packet + 5) = len & 0xff; +} + void IPv6Packet::setSrcAddress(const IPv6Addr* address) { memcpy(packet + 8, address, 16); } @@ -74,6 +83,13 @@ void IPv6Packet::setDstAddress(const IPv6Addr* address) { memcpy(packet + 24, address, 16); } +const IPv6Addr* IPv6Packet::getSrcAddress() { + return (const IPv6Addr*) (packet + 8); +} +const IPv6Addr* IPv6Packet::getDstAddress() { + return (const IPv6Addr*) (packet + 24); +} + void IPv6Packet::setFlow(const char* flow) { /* three bytes 4 most significant bits are ignored @@ -91,14 +107,22 @@ void IPv6Packet::setPayload(char* payload, int 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)); + int ilen = ((*(packet + 4)) << 8) + (*(packet + 5)); /* input payload length */ + int olen; /* output payload length */ switch(*(packet + 6)) { /* next header */ case NH_ICMP: - handleICMP((IPv6Addr*)(packet + 8), (IPv6Addr*)(packet + 24), packet + 1, packet + 40, len); + if ((olen = handleICMP((char*)&packetout + 40, packet + 40, ilen)) != -1) { + packetout.setLen(olen); + packetout.setFlow((char*)&packetin + 1); + packetout.setSrcAddress(packetin.getDstAddress()); + packetout.setDstAddress(packetin.getSrcAddress()); + packetout.setNextHeader(NH_ICMP); + slip::send((void*)&packetout, 40 + olen); + } break; case NH_UDP: - udp::handleUDP((IPv6Addr*)(packet + 8), (IPv6Addr*)(packet + 24), packet + 1, packet + 40, len); + //udp::handleUDP((IPv6Addr*)(packet + 8), (IPv6Addr*)(packet + 24), packet + 1, packet + 40, len); break; default: /* no other protocols are known here, sorry :-) */ @@ -107,38 +131,45 @@ void IPv6Packet::doAction() { } } -void handleICMP(const IPv6Addr* src_addr, const IPv6Addr* dst_addr, const char* flow, char* packet, int len) { - uint8_t type = *(packet); +int handleICMP(char* output_buffer, const char* input_buffer, int len) { //const IPv6Addr* src_addr, const IPv6Addr* dst_addr, const char* flow, char* packet, int len) { + uint8_t type = *(input_buffer); if (type == ICMP_ECHO_REQUEST_TYPE) { /* if it is ICMPv6 Echo Request, then... */ /* compute checksum, and assert validity of incoming message */ char received_checksum[2]; - memcpy(received_checksum, packet + 2, 2); + memcpy(received_checksum, input_buffer + 2, 2); - memset(packet + 2, 0, 2); /* zero-checksum */ - uint16_t computed_checksum = compute_checksum(src_addr, dst_addr, NH_ICMP, len, packet, len); + memcpy(output_buffer, input_buffer, len); + memset(output_buffer + 2, 0, 2); /* zero-checksum */ + uint16_t computed_checksum = compute_checksum( + packetin.getSrcAddress(), + packetin.getDstAddress(), + NH_ICMP, + len, + output_buffer, + len); if (memcmp(&computed_checksum, received_checksum, 2) == 0) { /* if checksum is valid, then... */ /* Build an echo reply: * the reply has the same exact format of the request, * except for Type and Checksum */ - *(packet) = ICMP_ECHO_REPLY_TYPE; - memset(packet + 2, 0, 2); /* zero-checksum */ + *(output_buffer) = ICMP_ECHO_REPLY_TYPE; + memset(output_buffer + 2, 0, 2); /* zero-checksum */ - uint16_t checksum = compute_checksum(src_addr, dst_addr, NH_ICMP, len, packet, len); - memcpy(packet + 2, &checksum, 2); - - IPv6Packet reply_packet; - reply_packet.setPayload(packet, len); - reply_packet.setFlow(flow); - - reply_packet.setSrcAddress(dst_addr); - reply_packet.setDstAddress(src_addr); - reply_packet.setNextHeader(NH_ICMP); - slip::send((void*)&reply_packet, 40 + len); + uint16_t checksum = compute_checksum( + packetin.getDstAddress(), + packetin.getSrcAddress(), + NH_ICMP, + len, + output_buffer, + len); + memcpy(output_buffer + 2, &checksum, 2); + + return len; } } - return; + + return -1; } }