adding comments here and there
This commit is contained in:
parent
5c7b1ffc99
commit
260f537125
@ -3,6 +3,7 @@
|
|||||||
#include "slip.h"
|
#include "slip.h"
|
||||||
#include "udp.h"
|
#include "udp.h"
|
||||||
|
|
||||||
|
/* an UDP application, which simply replies HELLO-WORLD-UDP */
|
||||||
int udp_server(char* output_buffer, const char* input_buffer, int len) {
|
int udp_server(char* output_buffer, const char* input_buffer, int len) {
|
||||||
const char msg[] = "HELLO-WORLD-UDP\n";
|
const char msg[] = "HELLO-WORLD-UDP\n";
|
||||||
digitalWrite(13, !digitalRead(13));
|
digitalWrite(13, !digitalRead(13));
|
||||||
@ -13,9 +14,24 @@ int udp_server(char* output_buffer, const char* input_buffer, int len) {
|
|||||||
void setup() {
|
void setup() {
|
||||||
pinMode(13, OUTPUT);
|
pinMode(13, OUTPUT);
|
||||||
|
|
||||||
|
/* setup serial for Internet connectivity
|
||||||
|
* attach a SLIP daemon on the other endpoint; a good one is `tunslip6` by Contiki
|
||||||
|
* $ tunslip6 -s /dev/ttyUSB0 -L -v5 -B 19200 2001:db8:1324::1/64
|
||||||
|
* Note: the address given is the one on the host it is running on
|
||||||
|
*/
|
||||||
Serial.begin(19200);
|
Serial.begin(19200);
|
||||||
memcpy(&coppino::address, "\x20\x01\x04\x70\xc8\x44\x00\x31\x00\x00\x00\x00\x00\x00\xca\xfe", 16);
|
|
||||||
|
|
||||||
|
/* set unique identifier of network hardware. It MUST be unique!
|
||||||
|
* For example, this could be your microcontroller serial number
|
||||||
|
* Note: pay attention to enter exactly 64 bits / 8 bytes
|
||||||
|
*/
|
||||||
|
ipv6::setEUI("\xde\xad\xbe\xef\x12\x34\x56\x78");
|
||||||
|
/* enable or disable IPv6 Stateless Auto-Configuration (SLAAC) */
|
||||||
|
ipv6::SLAAC(false);
|
||||||
|
/* set global address -- will be overwritten if SLAAC is enabled and a Router Advertisement is received */
|
||||||
|
ipv6::setGlobalAddress("\x20\x01\x04\x70\xc8\x44\x00\x31\x00\x00\x00\x00\x00\x00\xca\xfe");
|
||||||
|
|
||||||
|
/* start a server un UDP port 80 */
|
||||||
udp::set_handler(80, udp_server);
|
udp::set_handler(80, udp_server);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,12 +5,6 @@
|
|||||||
|
|
||||||
namespace coppino {
|
namespace coppino {
|
||||||
const uint8_t LEN = 128;
|
const uint8_t LEN = 128;
|
||||||
extern ipv6::IPv6Addr address;
|
|
||||||
/* netmask:
|
|
||||||
* no netmask is needed, because everything is sent over TTL UART
|
|
||||||
* gateway:
|
|
||||||
* the same as above
|
|
||||||
*/
|
|
||||||
|
|
||||||
void handler(void);
|
void handler(void);
|
||||||
void hexdump(const char* pointer, int len);
|
void hexdump(const char* pointer, int len);
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
#include "coppino.h"
|
#include "coppino.h"
|
||||||
|
|
||||||
namespace coppino {
|
namespace coppino {
|
||||||
ipv6::IPv6Addr address;
|
|
||||||
|
|
||||||
void handler() {
|
void handler() {
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
|
24
ipv6.h
24
ipv6.h
@ -2,17 +2,18 @@
|
|||||||
#define COPPINO_IPV6_H
|
#define COPPINO_IPV6_H
|
||||||
|
|
||||||
namespace ipv6 {
|
namespace ipv6 {
|
||||||
|
/* maximum length for an IPv6 packet */
|
||||||
const uint8_t LEN = 128;
|
const uint8_t LEN = 128;
|
||||||
|
|
||||||
|
/* ICMP Types */
|
||||||
const uint8_t ICMP_ECHO_REQUEST_TYPE = 128;
|
const uint8_t ICMP_ECHO_REQUEST_TYPE = 128;
|
||||||
const uint8_t ICMP_ECHO_REPLY_TYPE = 129;
|
const uint8_t ICMP_ECHO_REPLY_TYPE = 129;
|
||||||
const uint8_t ICMP_RADV_TYPE = 134;
|
const uint8_t ICMP_RADV_TYPE = 134;
|
||||||
|
|
||||||
|
/* Next-Header Types */
|
||||||
const uint8_t NH_ICMP = 58;
|
const uint8_t NH_ICMP = 58;
|
||||||
const uint8_t NH_UDP = 17;
|
const uint8_t NH_UDP = 17;
|
||||||
|
|
||||||
extern uint8_t HOP_LIMIT;
|
|
||||||
|
|
||||||
class IPv6Addr {
|
class IPv6Addr {
|
||||||
private:
|
private:
|
||||||
char address[16];
|
char address[16];
|
||||||
@ -21,18 +22,8 @@ namespace ipv6 {
|
|||||||
IPv6Addr(const char* address);
|
IPv6Addr(const char* address);
|
||||||
};
|
};
|
||||||
|
|
||||||
extern const IPv6Addr LINK_LOCAL_ADDRESS;
|
|
||||||
extern const IPv6Addr ALL_NODES_ADDRESS;
|
extern const IPv6Addr ALL_NODES_ADDRESS;
|
||||||
|
|
||||||
struct ipv6_packet_header {
|
|
||||||
char field[4];
|
|
||||||
char len[2];
|
|
||||||
char next_header;
|
|
||||||
char hop_limit;
|
|
||||||
IPv6Addr src_addr;
|
|
||||||
IPv6Addr dst_addr;
|
|
||||||
}__attribute__((packed));
|
|
||||||
|
|
||||||
class IPv6Packet {
|
class IPv6Packet {
|
||||||
private:
|
private:
|
||||||
char packet[LEN];
|
char packet[LEN];
|
||||||
@ -53,6 +44,7 @@ namespace ipv6 {
|
|||||||
void doAction();
|
void doAction();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* incoming and outgoing packets buffer */
|
||||||
extern IPv6Packet packetin;
|
extern IPv6Packet packetin;
|
||||||
extern IPv6Packet packetout;
|
extern IPv6Packet packetout;
|
||||||
|
|
||||||
@ -69,6 +61,7 @@ namespace ipv6 {
|
|||||||
int len /* IPv6 payload length */
|
int len /* IPv6 payload length */
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/* RFC 4861 -- begin */
|
||||||
struct ICMPv6_RADV {
|
struct ICMPv6_RADV {
|
||||||
uint8_t type;
|
uint8_t type;
|
||||||
uint8_t code;
|
uint8_t code;
|
||||||
@ -95,6 +88,11 @@ namespace ipv6 {
|
|||||||
uint32_t reserved2;
|
uint32_t reserved2;
|
||||||
char prefix[16];
|
char prefix[16];
|
||||||
};
|
};
|
||||||
|
/* RFC 4861 -- end */
|
||||||
|
|
||||||
|
void setEUI(const char* eui); /* 64bit Extended Unique Identifier */
|
||||||
|
void SLAAC(bool enable); /* enable IPv6 automatic prefix configuration (listens for RADV) */
|
||||||
|
void setGlobalAddress(const char* address); /* global IPv6 address, manually configured */
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
30
ipv6.ino
30
ipv6.ino
@ -4,16 +4,30 @@
|
|||||||
namespace ipv6 {
|
namespace ipv6 {
|
||||||
/******** costants ********/
|
/******** costants ********/
|
||||||
const IPv6Addr ALL_NODES_ADDRESS("\xff\x02\x00\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\x00\x01"); /* ff02::1 */
|
||||||
const IPv6Addr LINK_LOCAL_ADDRESS("\xfe\x80\x00\x00\x00\x00\x00\x00\xde\xad\xbe\xef\x12\x34\x56\x78"); /* fe80::dead:beef:1234:5678 */ /* TODO */
|
|
||||||
|
|
||||||
/******** variables ********/
|
/******** variables ********/
|
||||||
uint8_t HOP_LIMIT = 64;
|
uint8_t HOP_LIMIT = 64;
|
||||||
|
IPv6Addr LINK_LOCAL_ADDRESS;
|
||||||
|
IPv6Addr GLOBAL_ADDRESS;
|
||||||
|
bool slaac_enable;
|
||||||
|
|
||||||
/******** buffer ********/
|
/******** buffers ********/
|
||||||
IPv6Packet packetin;
|
IPv6Packet packetin;
|
||||||
IPv6Packet packetout;
|
IPv6Packet packetout;
|
||||||
|
|
||||||
/******** FUNCTIONS *******/
|
/******** FUNCTIONS *******/
|
||||||
|
void setEUI(const char* eui) {
|
||||||
|
memset(&LINK_LOCAL_ADDRESS, 0, 16);
|
||||||
|
memcpy(&LINK_LOCAL_ADDRESS, "\xfe\x80", 2);
|
||||||
|
memcpy( ((char*)&LINK_LOCAL_ADDRESS) + 8 , eui, 8);
|
||||||
|
}
|
||||||
|
void SLAAC(bool enable) {
|
||||||
|
slaac_enable = enable;
|
||||||
|
}
|
||||||
|
void setGlobalAddress(const char* address) {
|
||||||
|
memcpy(&GLOBAL_ADDRESS, address, 16);
|
||||||
|
}
|
||||||
|
|
||||||
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];
|
||||||
uint32_t total;
|
uint32_t total;
|
||||||
@ -120,7 +134,7 @@ void IPv6Packet::doAction() {
|
|||||||
if (
|
if (
|
||||||
(memcmp(&(ALL_NODES_ADDRESS), packet + 24, 16) == 0) ||
|
(memcmp(&(ALL_NODES_ADDRESS), packet + 24, 16) == 0) ||
|
||||||
(memcmp(&(LINK_LOCAL_ADDRESS), packet + 24, 16) == 0) ||
|
(memcmp(&(LINK_LOCAL_ADDRESS), packet + 24, 16) == 0) ||
|
||||||
(memcmp(&(coppino::address), packet + 24, 16) == 0)) {
|
(memcmp(&(GLOBAL_ADDRESS), packet + 24, 16) == 0)) {
|
||||||
int ilen = this->getLen(); /* input payload length */
|
int ilen = this->getLen(); /* input payload length */
|
||||||
int olen; /* output payload length */
|
int olen; /* output payload length */
|
||||||
|
|
||||||
@ -149,9 +163,12 @@ void IPv6Packet::doAction() {
|
|||||||
/* no other protocols are known here, sorry :-) */
|
/* no other protocols are known here, sorry :-) */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
} /* ...else discard packet */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* handles ICMP and (possibly) generate a reply
|
||||||
|
* returns length of generated packet (written to output_buffer), or -1 if there is no reply packet
|
||||||
|
*/
|
||||||
int handleICMP(char* output_buffer, const char* input_buffer, int len) {
|
int handleICMP(char* output_buffer, const char* input_buffer, int len) {
|
||||||
uint8_t type = *(input_buffer);
|
uint8_t type = *(input_buffer);
|
||||||
|
|
||||||
@ -190,7 +207,7 @@ int handleICMP(char* output_buffer, const char* input_buffer, int len) {
|
|||||||
memcpy(output_buffer + 2, &checksum, 2);
|
memcpy(output_buffer + 2, &checksum, 2);
|
||||||
return len;
|
return len;
|
||||||
|
|
||||||
} else if (type == ICMP_RADV_TYPE) { /* if it is IVMPc6 Router Advertisement, then... */
|
} else if (type == ICMP_RADV_TYPE && slaac_enable) { /* if it is IVMPc6 Router Advertisement, then... */
|
||||||
ICMPv6_RADV* radv = (ICMPv6_RADV*)input_buffer;
|
ICMPv6_RADV* radv = (ICMPv6_RADV*)input_buffer;
|
||||||
HOP_LIMIT = (radv->cur_hop_limit != 0) ? radv->cur_hop_limit : 64;
|
HOP_LIMIT = (radv->cur_hop_limit != 0) ? radv->cur_hop_limit : 64;
|
||||||
|
|
||||||
@ -198,13 +215,12 @@ int handleICMP(char* output_buffer, const char* input_buffer, int len) {
|
|||||||
ICMPv6_RADV_Option* option = (ICMPv6_RADV_Option*) (radv + 1);
|
ICMPv6_RADV_Option* option = (ICMPv6_RADV_Option*) (radv + 1);
|
||||||
option != input_buffer + len;
|
option != input_buffer + len;
|
||||||
option = (ICMPv6_RADV_Option*) ( ((char*)(option)) + option->len )) {
|
option = (ICMPv6_RADV_Option*) ( ((char*)(option)) + option->len )) {
|
||||||
digitalWrite(13, !digitalRead(13));
|
|
||||||
if (option->type == 3 && option->len == 4) { /* if it is a ICMPv6 Prefix Information, then... */
|
if (option->type == 3 && option->len == 4) { /* if it is a ICMPv6 Prefix Information, then... */
|
||||||
ICMPv6_RADV_PrefixInformation* p = (ICMPv6_RADV_PrefixInformation*) option;
|
ICMPv6_RADV_PrefixInformation* p = (ICMPv6_RADV_PrefixInformation*) option;
|
||||||
|
|
||||||
if (p->prefix_length != 64) continue; /* only /64 prefix is supported */
|
if (p->prefix_length != 64) continue; /* only /64 prefix is supported */
|
||||||
if (! (p->la_flags & 0x40)) continue; /* only SLAAC is supported */
|
if (! (p->la_flags & 0x40)) continue; /* only SLAAC is supported */
|
||||||
memcpy(&coppino::address, p->prefix, 8); /* set prefix -- leave host bits unchanged */
|
memcpy(&GLOBAL_ADDRESS, p->prefix, 8); /* set prefix -- leave host bits unchanged */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user