Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions src/EtherSia.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "MACAddress.h"
#include "IPv6Address.h"
#include "IPv6Packet.h"
#include "IPv6Prefix.h"
#include "Socket.h"
#include "UDPSocket.h"

Expand Down Expand Up @@ -90,6 +91,28 @@ class EtherSia {
_autoConfigurationEnabled = true;
}

/**
* Restricts autoconfiguration to a specified prefix,
* which Router Advertisements must be contained by.
*
* @note autoconfig restriction is disabled by default
* @param prefix the prefix to restrict to
*/
inline void enablePrefixRestriction(IPv6Prefix *prefix) {
memcpy(_whitelistedPrefix, prefix, sizeof(IPv6Prefix));
_prefixRestrictionEnabled = true;
}

/**
* Disables autoconfiguration restriction.
*
* @note autoconfig restriction is disabled by default
*/
inline void disablePrefixRestriction() {
memset(_whitelistedPrefix, 0, sizeof(IPv6Prefix));
_prefixRestrictionEnabled = false;
}

/**
* Manually set the global IPv6 address for the Ethernet Interface
* from an IPv6Address object
Expand Down Expand Up @@ -373,6 +396,7 @@ class EtherSia {
IPv6Address _linkLocalAddress; /**< The IPv6 Link-local address of the Ethernet Interface */
IPv6Address _globalAddress; /**< The IPv6 Global address of the Ethernet Interface */
IPv6Address _dnsServerAddress; /**< The IPv6 address of the configured DNS server */
IPv6Prefix _whitelistedPrefix; /**< The whitelisted IPv6 Prefix */

/** The MAC address of this Ethernet controller */
MACAddress _localMac;
Expand All @@ -392,6 +416,9 @@ class EtherSia {
/** Flag indicating if the buffer contains a valid packet we received */
boolean _autoConfigurationEnabled;

/** Flag indicating if a whitelisted Prefix is enabled */
boolean _prefixRestrictionEnabled;

/**
* Checks the Ethernet Layer 2 addresses
* @return true if packet should be accepted
Expand Down
162 changes: 162 additions & 0 deletions src/IPv6Prefix.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
#include <Arduino.h>
#include "MACAddress.h"
#include "IPv6Address.h"
#include "IPv6Prefix.h"
#include "util.h"

IPv6Prefix::IPv6Prefix()
{
setZero();
}

IPv6Prefix::IPv6Prefix(const IPv6Address *address, const uint8_t length) {
memcpy(_address, address, sizeof(IPv6Address));
_length = length;
}

IPv6Prefix::IPv6Prefix(const char *prefixstr)
{
fromString(prefixstr);
}

IPv6Prefix::IPv6Prefix(const __FlashStringHelper *prefixstr)
{
fromString(prefixstr);
}

boolean IPv6Prefix::fromString(const char *prefixstr)
{
setZero();

bool size_reached = false;
int8_t address_chars_read = 0;
int8_t prefix_chars_read = 0;
uint8_t prefix_chars[3];
char address[45];
for (uint8_t i = 0; i < strlen(prefixstr); i++) {
if (address_chars_read > 45) {
// Aboort if more than 45 Addres characters are read
return false;
} else if (!size_reached && prefixstr[i] == '/') {
// Begin to read prefix if seperator is read
size_reached = true;
// Zero address memory and write the read address to it
memset(address, 0, 45);
memcpy((void *) address, prefixstr, address_chars_read);
// Abort if address is invalid
if (_address.fromString(address) != true) return false;
} else if (!size_reached) {
// Increment address character counter
address_chars_read++;
} else if (size_reached) {
if(prefixstr[i] >= 48 && prefixstr[i] <= 57 && prefix_chars_read < 3) {
// Read prefix size chars
prefix_chars[prefix_chars_read] = prefixstr[i] - 48;
prefix_chars_read++;
} else {
// Abort on invalid characters and more than 4 prefix characters
return false;
}
}
}
uint8_t multiplier = 1;
uint8_t length = 0;
for (int8_t i = prefix_chars_read; i > 0; i--) {
// Calculate Prefix size from characters
length += prefix_chars[i - 1] * multiplier;
multiplier = multiplier * 10;
}
return setLength(length);
}

boolean IPv6Prefix::fromString(const __FlashStringHelper *prefixstr)
{
char ramStr[44];
// Copy the string from flash program memory into RAM
strcpy_P(ramStr, (const char*)prefixstr);
return fromString(ramStr);
}

const IPv6Address* IPv6Prefix::address() const
{
return &_address;
}

uint8_t IPv6Prefix::getLength() const
{
return _length;
}

boolean IPv6Prefix::setLength(uint8_t prefix_length)
{
// Abort and return false if size is greater than 128
if(prefix_length > 128) return false;
// save it otherwise
_length = prefix_length;

// Bits to mask (intial value == prefix_length)
uint8_t to_mask = this->getLength();
for(uint8_t i=0; i<16; i++) {
uint8_t mask = 0xFF;
if(to_mask < 8 ) {
uint8_t bit_remove = 8 - to_mask;
for(uint8_t j = 0; j < bit_remove; j++) {
mask = mask - (1 << j);
}
to_mask = 0;
} else {
to_mask = to_mask - 8;
}
// mask address
this->_address[i] = this->_address[i] & mask;
}

return true;
}

boolean IPv6Prefix::contains(const IPv6Prefix *prefix)
{
if(prefix->getLength() < this->getLength()) {
// If candidate prefix is smaller than current prefix, return false
return false;
}

IPv6Prefix candidate;
memcpy(candidate, prefix, sizeof(IPv6Prefix));
candidate.setLength(this->getLength());
return (candidate == *(this));
}

IPv6Prefix::operator uint8_t*()
{
return _address;
}

void IPv6Prefix::setZero()
{
_address.setZero();
_length = 0;
}

boolean IPv6Prefix::operator==(const IPv6Prefix& prefix) const
{
return *(address()) == *(prefix.address()) && getLength() == prefix.getLength();
}

boolean IPv6Prefix::operator!=(const IPv6Prefix& address) const
{
return !(*this == address);
}

void IPv6Prefix::print(Print &p) const
{
_address.print(p);
p.print("/");
p.print(this->_length);
}

void IPv6Prefix::println(Print &p) const
{
this->print(p);
p.println();
}
126 changes: 126 additions & 0 deletions src/IPv6Prefix.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
/**
* Header file for the IPv6Prefix class
* @file IPv6Prefix.h
*/

#ifndef IPv6Prefix_H
#define IPv6Prefix_H

#include <stdint.h>
#include "IPv6Address.h"

/**
* Class for the storage and manipulation of IPv6 prefixes.
*/
class IPv6Prefix {
private:
IPv6Address _address;
uint8_t _length;

public:
/**
* Constructor for a new / all-zero IPv6 /0 prefix
*/
IPv6Prefix();

/**
* Constructor from a IPv6 address and prefix length
* @param address the prefixes address
* @param length the prefixes length
*/
IPv6Prefix(const IPv6Address *address, const uint8_t length);

/**
* Constructor from a human readable IPv6 prefix string
* @param prefixstr the prefix to parse
*/
IPv6Prefix(const char *prefixstr);

/**
* Constructor from a human readable IPv6 prefix Flash string (use the F() macro)
* @param prefixstr the prefix to parse
*/
IPv6Prefix(const __FlashStringHelper *prefixstr);

/**
* Set prefix to the a human readable IPv6 string
* The prefix string can contain double colon :: notation to save space
* @param prefixstr an IPv6 prefix as a null-terminated string
* @return true if the string was parsed successfully
*/
boolean fromString(const char *prefixstr);

/**
* Set prefix to the a human readable IPv6 Flash string (use the F() macro)
* The prefix string can contain double colon :: notation to save space
* @param prefixstr an IPv6 prefix as a null-terminated string
* @return true if the string was parsed successfully
*/
boolean fromString(const __FlashStringHelper *prefixstr);

/**
* Returns the prefix address
* @return the prefix address
*/
const IPv6Address* address() const;

/**
* Returns the prefix length
* @return the prefix length
*/
uint8_t getLength() const ;

/**
* Sets the prefix length
* @param prefix_length the new prefix length
* @return returns true if new length is valid, false if otherwise
*/
boolean setLength(uint8_t prefix_length);

/**
* Checks if another IPv6 Prefix is contained by the prefix
* @param prefix the prefix to be checked
* @return true if prefix is contained, false if not
*/
boolean contains(const IPv6Prefix *prefix);

/**
* Cast the IPv6 prefix to an array of octets.
*/
operator uint8_t*();

/**
* Set the prefix to all-zeros (::/0)
*/
void setZero();

/**
* Check if the prefix equals another IPv6 prefix.
* @param prefix the second prefix to compare to
* @return true if the two prefixes are the same
*/
boolean operator==(const IPv6Prefix& prefix) const;

/**
* Check if the prefix is not equal to another IPv6 prefix.
* @param prefix the second prefix to compare to
* @return true if the two prefixes are the same
*/
boolean operator!=(const IPv6Prefix& prefix) const;

/**
* Print a IPv6 prefix to a stream as a human readable string.
* @param print The stream to print to (defaults to Serial)
*/
void print(Print &print=Serial) const;

/**
* Print a IPv6 prefix to a stream with line ending.
* @param print The stream to print to (defaults to Serial)
*/
void println(Print &print=Serial) const;

} __attribute__((__packed__));

#endif

7 changes: 7 additions & 0 deletions src/icmp6.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,13 @@ void EtherSia::icmp6ProcessRA()
_routerMac = *((MACAddress*)&ptr[2]);
break;
case ICMP6_OPTION_PREFIX_INFORMATION:
if(_prefixRestrictionEnabled == true) {
struct icmp6_prefix_information *icmp_p = (struct icmp6_prefix_information*)&ptr[2];
IPv6Prefix advertised_prefix(&icmp_p->prefix, icmp_p->prefix_length);
if(!_whitelistedPrefix.contains(&advertised_prefix)) {
return;
}
}
icmp6ProcessPrefix(
(struct icmp6_prefix_information*)&ptr[2]
);
Expand Down
Loading