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)
This commit is contained in:
parent
ba2f76f7e6
commit
339de9322f
@ -4,13 +4,10 @@ namespace coppino {
|
|||||||
ipv6::IPv6Addr address;
|
ipv6::IPv6Addr address;
|
||||||
|
|
||||||
void handler() {
|
void handler() {
|
||||||
|
|
||||||
char buffer[LEN];
|
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
while ((r = slip::recv(buffer, LEN)) != -1) {
|
while ((r = slip::recv((char*)&ipv6::packetin, LEN)) != -1) {
|
||||||
ipv6::IPv6Packet packet(buffer, r);
|
ipv6::packetin.doAction();
|
||||||
packet.doAction();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
8
ipv6.h
8
ipv6.h
@ -35,8 +35,11 @@ namespace ipv6 {
|
|||||||
public:
|
public:
|
||||||
IPv6Packet();
|
IPv6Packet();
|
||||||
IPv6Packet(const char* buffer, int len);
|
IPv6Packet(const char* buffer, int len);
|
||||||
|
void IPv6Packet::setLen(int len);
|
||||||
void setSrcAddress(const IPv6Addr* address);
|
void setSrcAddress(const IPv6Addr* address);
|
||||||
|
const IPv6Addr* getSrcAddress();
|
||||||
void setDstAddress(const IPv6Addr* address);
|
void setDstAddress(const IPv6Addr* address);
|
||||||
|
const IPv6Addr* getDstAddress();
|
||||||
void setNextHeader(uint8_t next_header);
|
void setNextHeader(uint8_t next_header);
|
||||||
void setFlow(const char* flow);
|
void setFlow(const char* flow);
|
||||||
void setPayload(char* payload, int len);
|
void setPayload(char* payload, int len);
|
||||||
@ -44,8 +47,11 @@ namespace ipv6 {
|
|||||||
void doAction();
|
void doAction();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
extern IPv6Packet packetin;
|
||||||
|
extern IPv6Packet packetout;
|
||||||
|
|
||||||
/* Note: content of message may be changed */
|
/* 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: */
|
/* Compute internet checksum. Actually it is not so straightforward: */
|
||||||
uint16_t compute_checksum(
|
uint16_t compute_checksum(
|
||||||
|
73
ipv6.ino
73
ipv6.ino
@ -5,6 +5,10 @@ namespace ipv6 {
|
|||||||
/******** costants ********/
|
/******** costants ********/
|
||||||
const IPv6Addr ALL_NODES_ADDRESS("\xff\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01"); /* ff02::1 */
|
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 *******/
|
/******** 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) {
|
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];
|
char buffer[LEN];
|
||||||
@ -67,6 +71,11 @@ void IPv6Packet::setNextHeader(uint8_t next_header) {
|
|||||||
*(packet + 6) = 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) {
|
void IPv6Packet::setSrcAddress(const IPv6Addr* address) {
|
||||||
memcpy(packet + 8, address, 16);
|
memcpy(packet + 8, address, 16);
|
||||||
}
|
}
|
||||||
@ -74,6 +83,13 @@ void IPv6Packet::setDstAddress(const IPv6Addr* address) {
|
|||||||
memcpy(packet + 24, address, 16);
|
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) {
|
void IPv6Packet::setFlow(const char* flow) {
|
||||||
/* three bytes
|
/* three bytes
|
||||||
4 most significant bits are ignored
|
4 most significant bits are ignored
|
||||||
@ -91,14 +107,22 @@ void IPv6Packet::setPayload(char* payload, int len) {
|
|||||||
void IPv6Packet::doAction() {
|
void IPv6Packet::doAction() {
|
||||||
/* if destination is my address, or destination is "all nodes" address, then... */
|
/* 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)) {
|
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 */
|
switch(*(packet + 6)) { /* next header */
|
||||||
case NH_ICMP:
|
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;
|
break;
|
||||||
case NH_UDP:
|
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;
|
break;
|
||||||
default:
|
default:
|
||||||
/* no other protocols are known here, sorry :-) */
|
/* 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) {
|
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 = *(packet);
|
uint8_t type = *(input_buffer);
|
||||||
|
|
||||||
if (type == ICMP_ECHO_REQUEST_TYPE) { /* if it is ICMPv6 Echo Request, then... */
|
if (type == ICMP_ECHO_REQUEST_TYPE) { /* if it is ICMPv6 Echo Request, then... */
|
||||||
/* compute checksum, and assert validity of incoming message */
|
/* compute checksum, and assert validity of incoming message */
|
||||||
char received_checksum[2];
|
char received_checksum[2];
|
||||||
memcpy(received_checksum, packet + 2, 2);
|
memcpy(received_checksum, input_buffer + 2, 2);
|
||||||
|
|
||||||
memset(packet + 2, 0, 2); /* zero-checksum */
|
memcpy(output_buffer, input_buffer, len);
|
||||||
uint16_t computed_checksum = compute_checksum(src_addr, dst_addr, NH_ICMP, len, packet, 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... */
|
if (memcmp(&computed_checksum, received_checksum, 2) == 0) { /* if checksum is valid, then... */
|
||||||
/* Build an echo reply:
|
/* Build an echo reply:
|
||||||
* the reply has the same exact format of the request,
|
* the reply has the same exact format of the request,
|
||||||
* except for Type and Checksum */
|
* except for Type and Checksum */
|
||||||
*(packet) = ICMP_ECHO_REPLY_TYPE;
|
*(output_buffer) = ICMP_ECHO_REPLY_TYPE;
|
||||||
memset(packet + 2, 0, 2); /* zero-checksum */
|
memset(output_buffer + 2, 0, 2); /* zero-checksum */
|
||||||
|
|
||||||
uint16_t checksum = compute_checksum(src_addr, dst_addr, NH_ICMP, len, packet, len);
|
uint16_t checksum = compute_checksum(
|
||||||
memcpy(packet + 2, &checksum, 2);
|
packetin.getDstAddress(),
|
||||||
|
packetin.getSrcAddress(),
|
||||||
|
NH_ICMP,
|
||||||
|
len,
|
||||||
|
output_buffer,
|
||||||
|
len);
|
||||||
|
memcpy(output_buffer + 2, &checksum, 2);
|
||||||
|
|
||||||
IPv6Packet reply_packet;
|
return len;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user