use dynamic sleep for loop
This commit is contained in:
commit
428131e8a8
14
.gitattributes
vendored
Normal file
14
.gitattributes
vendored
Normal file
|
@ -0,0 +1,14 @@
|
|||
# Set the default behavior, in case people don't have core.autocrlf set.
|
||||
* text=auto whitespace=trailing-space
|
||||
|
||||
# Explicitly declare text files you want to always be normalized and converted
|
||||
# to native line endings on checkout.
|
||||
*.c text
|
||||
*.h text
|
||||
*.java text
|
||||
|
||||
# Denote all files that are truly binary and should not be modified.
|
||||
*.png binary
|
||||
*.jpg binary
|
||||
*.ihex binary
|
||||
*.s37 binary
|
37
.gitignore
vendored
37
.gitignore
vendored
|
@ -4,6 +4,7 @@
|
|||
*.png
|
||||
*.log
|
||||
*.elf
|
||||
*.zip
|
||||
*.d
|
||||
*.ihex
|
||||
*.pyc
|
||||
|
@ -24,12 +25,15 @@
|
|||
*.c128
|
||||
*.c64
|
||||
*.cc2538dk
|
||||
*.remote
|
||||
*.zoul
|
||||
*.jn516x
|
||||
*.srf06-cc26xx
|
||||
*.ev-aducrf101mkxz
|
||||
*.report
|
||||
summary
|
||||
*.summary
|
||||
*.runerr
|
||||
*.runlog
|
||||
*.faillog
|
||||
*.orig
|
||||
*~
|
||||
|
@ -38,6 +42,7 @@ obj_*
|
|||
symbols.*
|
||||
Makefile.target
|
||||
doc/html
|
||||
doc/latex
|
||||
patches-*
|
||||
tools/tunslip
|
||||
tools/tunslip6
|
||||
|
@ -86,9 +91,39 @@ contiki-cc2530dk.lib
|
|||
*.d71
|
||||
*.d81
|
||||
|
||||
# Cooja Build Artifacts
|
||||
*.cooja
|
||||
|
||||
#regression tests artifacts
|
||||
*.testlog
|
||||
*.log.prog
|
||||
regression-tests/[0-9][0-9]-*/report
|
||||
regression-tests/[0-9][0-9]-*/org/
|
||||
|
||||
# rl78 build artifacts
|
||||
*.eval-adf7xxxmb4z
|
||||
*.eval-adf7xxxmb4z.srec
|
||||
|
||||
# cscope files
|
||||
cscope.*
|
||||
|
||||
# vim swap files
|
||||
*.swp
|
||||
*.swo
|
||||
|
||||
# x86 UEFI files
|
||||
cpu/x86/uefi/Makefile.uefi
|
||||
cpu/x86/uefi/edk2
|
||||
|
||||
# galileo bsp files
|
||||
platform/galileo/bsp/libc/Makefile.libc
|
||||
platform/galileo/bsp/libc/i586-elf/
|
||||
platform/galileo/bsp/libc/newlib-2.2.0-1*
|
||||
platform/galileo/bsp/grub/src/
|
||||
platform/galileo/bsp/grub/bin/
|
||||
|
||||
# galileo build and debug artefacts
|
||||
*.galileo
|
||||
*.galileo.dll
|
||||
*.galileo.efi
|
||||
LOG_OPENOCD
|
||||
|
|
5
.gitmodules
vendored
5
.gitmodules
vendored
|
@ -11,6 +11,9 @@
|
|||
path = cpu/cc26xx-cc13xx/lib/cc26xxware
|
||||
url = https://github.com/g-oikonomou/cc26xxware.git
|
||||
[submodule "cpu/cc26xx-cc13xx/lib/cc13xxware"]
|
||||
path = cpu/cc26xx-cc13xx/lib/cc13xxware
|
||||
path = cpu/cc26xx-c../.gitmodulesc13xx/lib/cc13xxware
|
||||
url = https://github.com/g-oikonomou/cc13xxware.git
|
||||
[submodule "platform/stm32nucleo-spirit1/stm32cube-lib"]
|
||||
path = platform/stm32nucleo-spirit1/stm32cube-lib
|
||||
url = https://github.com/STclab/stm32nucleo-spirit1-lib
|
||||
|
||||
|
|
21
.travis.yml
21
.travis.yml
|
@ -17,7 +17,7 @@ before_script:
|
|||
|
||||
## Install msp430 toolchain
|
||||
- sudo apt-get -qq install lib32z1
|
||||
- $WGET http://adamdunkels.github.io/contiki-fork/mspgcc-4.7.0-compiled.tar.bz2 &&
|
||||
- $WGET http://simonduq.github.io/resources/mspgcc-4.7.2-compiled.tar.bz2 &&
|
||||
tar xjf mspgcc*.tar.bz2 -C /tmp/ &&
|
||||
sudo cp -f -r /tmp/msp430/* /usr/local/ &&
|
||||
rm -rf /tmp/msp430 mspgcc*.tar.bz2 &&
|
||||
|
@ -36,6 +36,7 @@ before_script:
|
|||
tar xjf arm-2008q3*.tar.bz2 -C /tmp/ &&
|
||||
sudo cp -f -r /tmp/arm-2008q3/* /usr/ &&
|
||||
rm -rf /tmp/arm-2008q3 arm-2008q3*.tar.bz2 &&
|
||||
sudo apt-get -qq install libconfig-dev uuid-dev libqrencode-dev &&
|
||||
arm-none-eabi-gcc --version ;
|
||||
fi
|
||||
|
||||
|
@ -73,6 +74,22 @@ before_script:
|
|||
cc65 --version ;
|
||||
fi
|
||||
|
||||
## Install NXP toolchain
|
||||
- if [ ${BUILD_ARCH:-0} = jn516x ] ; then
|
||||
$WGET http://simonduq.github.io/resources/ba-elf-gcc-4.7.4-part1.tar.bz2 &&
|
||||
$WGET http://simonduq.github.io/resources/ba-elf-gcc-4.7.4-part2.tar.bz2 &&
|
||||
$WGET http://simonduq.github.io/resources/jn516x-sdk-4163.tar.bz2 &&
|
||||
mkdir /tmp/jn516x-sdk /tmp/ba-elf-gcc &&
|
||||
tar xjf jn516x-sdk-*.tar.bz2 -C /tmp/jn516x-sdk &&
|
||||
tar xjf ba-elf-gcc-*part1.tar.bz2 -C /tmp/ba-elf-gcc &&
|
||||
tar xjf ba-elf-gcc-*part2.tar.bz2 -C /tmp/ba-elf-gcc &&
|
||||
sudo cp -f -r /tmp/jn516x-sdk /usr/ &&
|
||||
sudo cp -f -r /tmp/ba-elf-gcc /usr/ &&
|
||||
export PATH=/usr/ba-elf-gcc/bin:$PATH &&
|
||||
rm -rf /tmp/ba-elf-gcc* /tmp/jn516x-sdk* &&
|
||||
ba-elf-gcc --version ;
|
||||
fi
|
||||
|
||||
## Compile cooja.jar only when it's going to be needed
|
||||
- if [ ${BUILD_CATEGORY:-sim} = sim ] ; then
|
||||
java -version &&
|
||||
|
@ -103,6 +120,7 @@ env:
|
|||
- BUILD_TYPE='collect'
|
||||
- BUILD_TYPE='collect-lossy'
|
||||
- BUILD_TYPE='rpl'
|
||||
- BUILD_TYPE='large-rpl'
|
||||
- BUILD_TYPE='rime'
|
||||
- BUILD_TYPE='ipv6'
|
||||
- BUILD_TYPE='ip64' MAKE_TARGETS='cooja'
|
||||
|
@ -119,5 +137,6 @@ env:
|
|||
- BUILD_TYPE='compile-arm-apcs-ports' BUILD_CATEGORY='compile' BUILD_ARCH='arm-apcs'
|
||||
- BUILD_TYPE='compile-6502-ports' BUILD_CATEGORY='compile' BUILD_ARCH='6502'
|
||||
- BUILD_TYPE='compile-arm-ports' BUILD_CATEGORY='compile' BUILD_ARCH='arm-aapcs'
|
||||
- BUILD_TYPE='compile-nxp-ports' BUILD_CATEGORY='compile' BUILD_ARCH='jn516x'
|
||||
- BUILD_TYPE='slip-radio' MAKE_TARGETS='cooja'
|
||||
- BUILD_TYPE='llsec' MAKE_TARGETS='cooja'
|
||||
|
|
|
@ -24,7 +24,7 @@ static char send_udp = 0;
|
|||
static const char *prompt = "contiki> ";
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static char * CC_FASTCALL
|
||||
static char *
|
||||
n(uint16_t num, char *ptr)
|
||||
{
|
||||
uint16_t d;
|
||||
|
|
10
apps/codeprop/Makefile.codeprop-tmp
Normal file
10
apps/codeprop/Makefile.codeprop-tmp
Normal file
|
@ -0,0 +1,10 @@
|
|||
codeprop-tmp_src = codeprop-tmp.c
|
||||
|
||||
# Enable LARGE MEMORY MODEL supports for WISMOTE and EXP5438 platform
|
||||
ifeq ($(TARGET),wismote)
|
||||
TARGET_MEMORY_MODEL = large
|
||||
endif
|
||||
|
||||
ifeq ($(TARGET),exp5438)
|
||||
TARGET_MEMORY_MODEL = large
|
||||
endif
|
|
@ -58,9 +58,9 @@ LIST(observers_list);
|
|||
/*---------------------------------------------------------------------------*/
|
||||
/*- Internal API ------------------------------------------------------------*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
coap_observer_t *
|
||||
coap_add_observer(uip_ipaddr_t *addr, uint16_t port, const uint8_t *token,
|
||||
size_t token_len, const char *uri)
|
||||
static coap_observer_t *
|
||||
add_observer(uip_ipaddr_t *addr, uint16_t port, const uint8_t *token,
|
||||
size_t token_len, const char *uri, int uri_len)
|
||||
{
|
||||
/* Remove existing observe relationship, if any. */
|
||||
coap_remove_observer_by_uri(addr, port, uri);
|
||||
|
@ -68,7 +68,12 @@ coap_add_observer(uip_ipaddr_t *addr, uint16_t port, const uint8_t *token,
|
|||
coap_observer_t *o = memb_alloc(&observers_memb);
|
||||
|
||||
if(o) {
|
||||
o->url = uri;
|
||||
int max = sizeof(o->url) - 1;
|
||||
if(max > uri_len) {
|
||||
max = uri_len;
|
||||
}
|
||||
memcpy(o->url, uri, max);
|
||||
o->url[max] = 0;
|
||||
uip_ipaddr_copy(&o->addr, addr);
|
||||
o->port = port;
|
||||
o->token_len = token_len;
|
||||
|
@ -177,18 +182,47 @@ coap_remove_observer_by_mid(uip_ipaddr_t *addr, uint16_t port, uint16_t mid)
|
|||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
coap_notify_observers(resource_t *resource)
|
||||
{
|
||||
coap_notify_observers_sub(resource, NULL);
|
||||
}
|
||||
void
|
||||
coap_notify_observers_sub(resource_t *resource, const char *subpath)
|
||||
{
|
||||
/* build notification */
|
||||
coap_packet_t notification[1]; /* this way the packet can be treated as pointer as usual */
|
||||
coap_init_message(notification, COAP_TYPE_NON, CONTENT_2_05, 0);
|
||||
coap_packet_t request[1]; /* this way the packet can be treated as pointer as usual */
|
||||
coap_observer_t *obs = NULL;
|
||||
int url_len, obs_url_len;
|
||||
char url[COAP_OBSERVER_URL_LEN];
|
||||
|
||||
PRINTF("Observe: Notification from %s\n", resource->url);
|
||||
url_len = strlen(resource->url);
|
||||
strncpy(url, resource->url, COAP_OBSERVER_URL_LEN - 1);
|
||||
if(url_len < COAP_OBSERVER_URL_LEN - 1 && subpath != NULL) {
|
||||
strncpy(&url[url_len], subpath, COAP_OBSERVER_URL_LEN - url_len - 1);
|
||||
}
|
||||
/* Ensure url is null terminated because strncpy does not guarantee this */
|
||||
url[COAP_OBSERVER_URL_LEN - 1] = '\0';
|
||||
/* url now contains the notify URL that needs to match the observer */
|
||||
PRINTF("Observe: Notification from %s\n", url);
|
||||
|
||||
coap_init_message(notification, COAP_TYPE_NON, CONTENT_2_05, 0);
|
||||
/* create a "fake" request for the URI */
|
||||
coap_init_message(request, COAP_TYPE_CON, COAP_GET, 0);
|
||||
coap_set_header_uri_path(request, url);
|
||||
|
||||
/* iterate over observers */
|
||||
url_len = strlen(url);
|
||||
for(obs = (coap_observer_t *)list_head(observers_list); obs;
|
||||
obs = obs->next) {
|
||||
if(obs->url == resource->url) { /* using RESOURCE url pointer as handle */
|
||||
obs_url_len = strlen(obs->url);
|
||||
|
||||
/* Do a match based on the parent/sub-resource match so that it is
|
||||
possible to do parent-node observe */
|
||||
if((obs_url_len == url_len
|
||||
|| (obs_url_len > url_len
|
||||
&& (resource->flags & HAS_SUB_RESOURCES)
|
||||
&& obs->url[url_len] == '/'))
|
||||
&& strncmp(url, obs->url, url_len) == 0) {
|
||||
coap_transaction_t *transaction = NULL;
|
||||
|
||||
/*TODO implement special transaction for CON, sharing the same buffer to allow for more observers */
|
||||
|
@ -209,7 +243,7 @@ coap_notify_observers(resource_t *resource)
|
|||
/* prepare response */
|
||||
notification->mid = transaction->mid;
|
||||
|
||||
resource->get_handler(NULL, notification,
|
||||
resource->get_handler(request, notification,
|
||||
transaction->packet + COAP_MAX_HEADER_SIZE,
|
||||
REST_MAX_CHUNK_SIZE, NULL);
|
||||
|
||||
|
@ -234,14 +268,12 @@ coap_observe_handler(resource_t *resource, void *request, void *response)
|
|||
coap_packet_t *const coap_res = (coap_packet_t *)response;
|
||||
coap_observer_t * obs;
|
||||
|
||||
static char content[16];
|
||||
|
||||
if(coap_req->code == COAP_GET && coap_res->code < 128) { /* GET request and response without error code */
|
||||
if(IS_OPTION(coap_req, COAP_OPTION_OBSERVE)) {
|
||||
if(coap_req->observe == 0) {
|
||||
obs = coap_add_observer(&UIP_IP_BUF->srcipaddr, UIP_UDP_BUF->srcport,
|
||||
coap_req->token, coap_req->token_len,
|
||||
resource->url);
|
||||
obs = add_observer(&UIP_IP_BUF->srcipaddr, UIP_UDP_BUF->srcport,
|
||||
coap_req->token, coap_req->token_len,
|
||||
coap_req->uri_path, coap_req->uri_path_len);
|
||||
if(obs) {
|
||||
coap_set_header_observe(coap_res, (obs->obs_counter)++);
|
||||
/*
|
||||
|
@ -249,13 +281,14 @@ coap_observe_handler(resource_t *resource, void *request, void *response)
|
|||
* A subscription should return the same representation as a normal GET.
|
||||
* Uncomment if you want an information about the avaiable observers.
|
||||
*/
|
||||
/*
|
||||
* coap_set_payload(coap_res,
|
||||
* content,
|
||||
* snprintf(content, sizeof(content), "Added %u/%u",
|
||||
* list_length(observers_list),
|
||||
* COAP_MAX_OBSERVERS));
|
||||
*/
|
||||
#if 0
|
||||
static char content[16];
|
||||
coap_set_payload(coap_res,
|
||||
content,
|
||||
snprintf(content, sizeof(content), "Added %u/%u",
|
||||
list_length(observers_list),
|
||||
COAP_MAX_OBSERVERS));
|
||||
#endif
|
||||
} else {
|
||||
coap_res->code = SERVICE_UNAVAILABLE_5_03;
|
||||
coap_set_payload(coap_res, "TooManyObservers", 16);
|
||||
|
|
|
@ -43,6 +43,8 @@
|
|||
#include "er-coap-transactions.h"
|
||||
#include "stimer.h"
|
||||
|
||||
#define COAP_OBSERVER_URL_LEN 20
|
||||
|
||||
typedef struct coap_observable {
|
||||
uint32_t observe_clock;
|
||||
struct stimer orphan_timer;
|
||||
|
@ -54,7 +56,7 @@ typedef struct coap_observable {
|
|||
typedef struct coap_observer {
|
||||
struct coap_observer *next; /* for LIST */
|
||||
|
||||
const char *url;
|
||||
char url[COAP_OBSERVER_URL_LEN];
|
||||
uip_ipaddr_t addr;
|
||||
uint16_t port;
|
||||
uint8_t token_len;
|
||||
|
@ -68,11 +70,6 @@ typedef struct coap_observer {
|
|||
} coap_observer_t;
|
||||
|
||||
list_t coap_get_observers(void);
|
||||
|
||||
coap_observer_t *coap_add_observer(uip_ipaddr_t *addr, uint16_t port,
|
||||
const uint8_t *token, size_t token_len,
|
||||
const char *url);
|
||||
|
||||
void coap_remove_observer(coap_observer_t *o);
|
||||
int coap_remove_observer_by_client(uip_ipaddr_t *addr, uint16_t port);
|
||||
int coap_remove_observer_by_token(uip_ipaddr_t *addr, uint16_t port,
|
||||
|
@ -83,6 +80,7 @@ int coap_remove_observer_by_mid(uip_ipaddr_t *addr, uint16_t port,
|
|||
uint16_t mid);
|
||||
|
||||
void coap_notify_observers(resource_t *resource);
|
||||
void coap_notify_observers_sub(resource_t *resource, const char *subpath);
|
||||
|
||||
void coap_observe_handler(resource_t *resource, void *request,
|
||||
void *response);
|
||||
|
|
|
@ -124,7 +124,7 @@ well_known_core_get_handler(void *request, void *response, uint8_t *buffer,
|
|||
continue;
|
||||
}
|
||||
end = attrib + strlen(attrib);
|
||||
} else {
|
||||
} else if(resource->attributes != NULL) {
|
||||
attrib = strstr(resource->attributes, filter);
|
||||
if(attrib == NULL
|
||||
|| (attrib[strlen(filter)] != '='
|
||||
|
@ -159,8 +159,8 @@ well_known_core_get_handler(void *request, void *response, uint8_t *buffer,
|
|||
}
|
||||
#endif
|
||||
|
||||
PRINTF("res: /%s (%p)\npos: s%d, o%ld, b%d\n", resource->url, resource,
|
||||
strpos, *offset, bufpos);
|
||||
PRINTF("res: /%s (%p)\npos: s%zu, o%ld, b%zu\n", resource->url, resource,
|
||||
strpos, (long)*offset, bufpos);
|
||||
|
||||
if(strpos > 0) {
|
||||
ADD_CHAR_IF_POSSIBLE(',');
|
||||
|
@ -170,7 +170,7 @@ well_known_core_get_handler(void *request, void *response, uint8_t *buffer,
|
|||
ADD_STRING_IF_POSSIBLE(resource->url, >=);
|
||||
ADD_CHAR_IF_POSSIBLE('>');
|
||||
|
||||
if(resource->attributes[0]) {
|
||||
if(resource->attributes != NULL && resource->attributes[0]) {
|
||||
ADD_CHAR_IF_POSSIBLE(';');
|
||||
ADD_STRING_IF_POSSIBLE(resource->attributes, >);
|
||||
}
|
||||
|
@ -183,7 +183,7 @@ well_known_core_get_handler(void *request, void *response, uint8_t *buffer,
|
|||
}
|
||||
|
||||
if(bufpos > 0) {
|
||||
PRINTF("BUF %d: %.*s\n", bufpos, bufpos, (char *)buffer);
|
||||
PRINTF("BUF %zu: %.*s\n", bufpos, (int)bufpos, (char *)buffer);
|
||||
|
||||
coap_set_payload(response, buffer, bufpos);
|
||||
coap_set_header_content_format(response, APPLICATION_LINK_FORMAT);
|
||||
|
|
|
@ -113,15 +113,9 @@ coap_send_transaction(coap_transaction_t *t)
|
|||
(float)t->retrans_timer.timer.interval / CLOCK_SECOND);
|
||||
}
|
||||
|
||||
/*FIXME
|
||||
* Hack: Setting timer for responsible process.
|
||||
* Maybe there is a better way, but avoid posting everything to the process.
|
||||
*/
|
||||
struct process *process_actual = PROCESS_CURRENT();
|
||||
|
||||
process_current = transaction_handler_process;
|
||||
PROCESS_CONTEXT_BEGIN(transaction_handler_process);
|
||||
etimer_restart(&t->retrans_timer); /* interval updated above */
|
||||
process_current = process_actual;
|
||||
PROCESS_CONTEXT_END(transaction_handler_process);
|
||||
|
||||
t = NULL;
|
||||
} else {
|
||||
|
|
|
@ -113,19 +113,21 @@ coap_set_option_header(unsigned int delta, size_t length, uint8_t *buffer)
|
|||
|
||||
buffer[0] = coap_option_nibble(delta) << 4 | coap_option_nibble(length);
|
||||
|
||||
/* avoids code duplication without function overhead */
|
||||
unsigned int *x = δ
|
||||
if(delta > 268) {
|
||||
buffer[++written] = ((delta - 269) >> 8) & 0xff;
|
||||
buffer[++written] = (delta - 269) & 0xff;
|
||||
} else if(delta > 12) {
|
||||
buffer[++written] = (delta - 13);
|
||||
}
|
||||
|
||||
do {
|
||||
if(*x > 268) {
|
||||
buffer[++written] = (*x - 269) >> 8;
|
||||
buffer[++written] = (*x - 269);
|
||||
} else if(*x > 12) {
|
||||
buffer[++written] = (*x - 13);
|
||||
}
|
||||
} while(x != &length && (x = &length));
|
||||
if(length > 268) {
|
||||
buffer[++written] = ((length - 269) >> 8) & 0xff;
|
||||
buffer[++written] = (length - 269) & 0xff;
|
||||
} else if(length > 12) {
|
||||
buffer[++written] = (length - 13);
|
||||
}
|
||||
|
||||
PRINTF("WRITTEN %u B opt header\n", 1 + written);
|
||||
PRINTF("WRITTEN %zu B opt header\n", 1 + written);
|
||||
|
||||
return ++written;
|
||||
}
|
||||
|
@ -148,7 +150,7 @@ coap_serialize_int_option(unsigned int number, unsigned int current_number,
|
|||
if(0xFFFFFFFF & value) {
|
||||
++i;
|
||||
}
|
||||
PRINTF("OPTION %u (delta %u, len %u)\n", number, number - current_number,
|
||||
PRINTF("OPTION %u (delta %u, len %zu)\n", number, number - current_number,
|
||||
i);
|
||||
|
||||
i = coap_set_option_header(number - current_number, i, buffer);
|
||||
|
@ -175,8 +177,8 @@ coap_serialize_array_option(unsigned int number, unsigned int current_number,
|
|||
{
|
||||
size_t i = 0;
|
||||
|
||||
PRINTF("ARRAY type %u, len %u, full [%.*s]\n", number, length, length,
|
||||
array);
|
||||
PRINTF("ARRAY type %u, len %zu, full [%.*s]\n", number, length,
|
||||
(int)length, array);
|
||||
|
||||
if(split_char != '\0') {
|
||||
int j;
|
||||
|
@ -185,7 +187,7 @@ coap_serialize_array_option(unsigned int number, unsigned int current_number,
|
|||
size_t temp_length;
|
||||
|
||||
for(j = 0; j <= length + 1; ++j) {
|
||||
PRINTF("STEP %u/%u (%c)\n", j, length, array[j]);
|
||||
PRINTF("STEP %u/%zu (%c)\n", j, length, array[j]);
|
||||
if(array[j] == split_char || j == length) {
|
||||
part_end = array + j;
|
||||
temp_length = part_end - part_start;
|
||||
|
@ -195,8 +197,8 @@ coap_serialize_array_option(unsigned int number, unsigned int current_number,
|
|||
memcpy(&buffer[i], part_start, temp_length);
|
||||
i += temp_length;
|
||||
|
||||
PRINTF("OPTION type %u, delta %u, len %u, part [%.*s]\n", number,
|
||||
number - current_number, i, temp_length, part_start);
|
||||
PRINTF("OPTION type %u, delta %u, len %zu, part [%.*s]\n", number,
|
||||
number - current_number, i, (int)temp_length, part_start);
|
||||
|
||||
++j; /* skip the splitter */
|
||||
current_number = number;
|
||||
|
@ -208,7 +210,7 @@ coap_serialize_array_option(unsigned int number, unsigned int current_number,
|
|||
memcpy(&buffer[i], array, length);
|
||||
i += length;
|
||||
|
||||
PRINTF("OPTION type %u, delta %u, len %u\n", number,
|
||||
PRINTF("OPTION type %u, delta %u, len %zu\n", number,
|
||||
number - current_number, length);
|
||||
}
|
||||
|
||||
|
@ -332,7 +334,7 @@ coap_serialize_message(void *packet, uint8_t *buffer)
|
|||
|
||||
/* empty packet, dont need to do more stuff */
|
||||
if(!coap_pkt->code) {
|
||||
PRINTF("-Done serializing empty message at %p-\n", option);
|
||||
PRINTF("-Done serializing empty message at %p-\n", coap_pkt->buffer);
|
||||
return 4;
|
||||
}
|
||||
|
||||
|
@ -368,6 +370,7 @@ coap_serialize_message(void *packet, uint8_t *buffer)
|
|||
"Location-Path");
|
||||
COAP_SERIALIZE_STRING_OPTION(COAP_OPTION_URI_PATH, uri_path, '/',
|
||||
"Uri-Path");
|
||||
PRINTF("Serialize content format: %d\n", coap_pkt->content_format);
|
||||
COAP_SERIALIZE_INT_OPTION(COAP_OPTION_CONTENT_FORMAT, content_format,
|
||||
"Content-Format");
|
||||
COAP_SERIALIZE_INT_OPTION(COAP_OPTION_MAX_AGE, max_age, "Max-Age");
|
||||
|
@ -403,8 +406,9 @@ coap_serialize_message(void *packet, uint8_t *buffer)
|
|||
}
|
||||
|
||||
PRINTF("-Done %u B (header len %u, payload len %u)-\n",
|
||||
coap_pkt->payload_len + option - buffer, option - buffer,
|
||||
coap_pkt->payload_len);
|
||||
(unsigned int)(coap_pkt->payload_len + option - buffer),
|
||||
(unsigned int)(option - buffer),
|
||||
(unsigned int)coap_pkt->payload_len);
|
||||
|
||||
PRINTF("Dump [0x%02X %02X %02X %02X %02X %02X %02X %02X]\n",
|
||||
coap_pkt->buffer[0],
|
||||
|
@ -451,10 +455,8 @@ coap_parse_message(void *packet, uint8_t *data, uint16_t data_len)
|
|||
>> COAP_HEADER_VERSION_POSITION;
|
||||
coap_pkt->type = (COAP_HEADER_TYPE_MASK & coap_pkt->buffer[0])
|
||||
>> COAP_HEADER_TYPE_POSITION;
|
||||
coap_pkt->token_len =
|
||||
MIN(COAP_TOKEN_LEN,
|
||||
(COAP_HEADER_TOKEN_LEN_MASK & coap_pkt->
|
||||
buffer[0]) >> COAP_HEADER_TOKEN_LEN_POSITION);
|
||||
coap_pkt->token_len = (COAP_HEADER_TOKEN_LEN_MASK & coap_pkt->buffer[0])
|
||||
>> COAP_HEADER_TOKEN_LEN_POSITION;
|
||||
coap_pkt->code = coap_pkt->buffer[1];
|
||||
coap_pkt->mid = coap_pkt->buffer[2] << 8 | coap_pkt->buffer[3];
|
||||
|
||||
|
@ -463,6 +465,11 @@ coap_parse_message(void *packet, uint8_t *data, uint16_t data_len)
|
|||
return BAD_REQUEST_4_00;
|
||||
}
|
||||
|
||||
if(coap_pkt->token_len > COAP_TOKEN_LEN) {
|
||||
coap_error_message = "Token Length must not be more than 8";
|
||||
return BAD_REQUEST_4_00;
|
||||
}
|
||||
|
||||
uint8_t *current_option = data + COAP_HEADER_LEN;
|
||||
|
||||
memcpy(coap_pkt->token, current_option, coap_pkt->token_len);
|
||||
|
@ -500,25 +507,31 @@ coap_parse_message(void *packet, uint8_t *data, uint16_t data_len)
|
|||
option_length = current_option[0] & 0x0F;
|
||||
++current_option;
|
||||
|
||||
/* avoids code duplication without function overhead */
|
||||
unsigned int *x = &option_delta;
|
||||
if(option_delta == 13) {
|
||||
option_delta += current_option[0];
|
||||
++current_option;
|
||||
} else if(option_delta == 14) {
|
||||
option_delta += 255;
|
||||
option_delta += current_option[0] << 8;
|
||||
++current_option;
|
||||
option_delta += current_option[0];
|
||||
++current_option;
|
||||
}
|
||||
|
||||
do {
|
||||
if(*x == 13) {
|
||||
*x += current_option[0];
|
||||
++current_option;
|
||||
} else if(*x == 14) {
|
||||
*x += 255;
|
||||
*x += current_option[0] << 8;
|
||||
++current_option;
|
||||
*x += current_option[0];
|
||||
++current_option;
|
||||
}
|
||||
} while(x != &option_length && (x = &option_length));
|
||||
if(option_length == 13) {
|
||||
option_length += current_option[0];
|
||||
++current_option;
|
||||
} else if(option_length == 14) {
|
||||
option_length += 255;
|
||||
option_length += current_option[0] << 8;
|
||||
++current_option;
|
||||
option_length += current_option[0];
|
||||
++current_option;
|
||||
}
|
||||
|
||||
option_number += option_delta;
|
||||
|
||||
PRINTF("OPTION %u (delta %u, len %u): ", option_number, option_delta,
|
||||
PRINTF("OPTION %u (delta %u, len %zu): ", option_number, option_delta,
|
||||
option_length);
|
||||
|
||||
SET_OPTION(coap_pkt, option_number);
|
||||
|
@ -532,7 +545,7 @@ coap_parse_message(void *packet, uint8_t *data, uint16_t data_len)
|
|||
case COAP_OPTION_MAX_AGE:
|
||||
coap_pkt->max_age = coap_parse_int_option(current_option,
|
||||
option_length);
|
||||
PRINTF("Max-Age [%lu]\n", coap_pkt->max_age);
|
||||
PRINTF("Max-Age [%lu]\n", (unsigned long)coap_pkt->max_age);
|
||||
break;
|
||||
case COAP_OPTION_ETAG:
|
||||
coap_pkt->etag_len = MIN(COAP_ETAG_LEN, option_length);
|
||||
|
@ -569,7 +582,7 @@ coap_parse_message(void *packet, uint8_t *data, uint16_t data_len)
|
|||
coap_pkt->proxy_uri = (char *)current_option;
|
||||
coap_pkt->proxy_uri_len = option_length;
|
||||
#endif
|
||||
PRINTF("Proxy-Uri NOT IMPLEMENTED [%.*s]\n", coap_pkt->proxy_uri_len,
|
||||
PRINTF("Proxy-Uri NOT IMPLEMENTED [%.*s]\n", (int)coap_pkt->proxy_uri_len,
|
||||
coap_pkt->proxy_uri);
|
||||
coap_error_message = "This is a constrained server (Contiki)";
|
||||
return PROXYING_NOT_SUPPORTED_5_05;
|
||||
|
@ -580,7 +593,7 @@ coap_parse_message(void *packet, uint8_t *data, uint16_t data_len)
|
|||
coap_pkt->proxy_scheme_len = option_length;
|
||||
#endif
|
||||
PRINTF("Proxy-Scheme NOT IMPLEMENTED [%.*s]\n",
|
||||
coap_pkt->proxy_scheme_len, coap_pkt->proxy_scheme);
|
||||
(int)coap_pkt->proxy_scheme_len, coap_pkt->proxy_scheme);
|
||||
coap_error_message = "This is a constrained server (Contiki)";
|
||||
return PROXYING_NOT_SUPPORTED_5_05;
|
||||
break;
|
||||
|
@ -588,7 +601,8 @@ coap_parse_message(void *packet, uint8_t *data, uint16_t data_len)
|
|||
case COAP_OPTION_URI_HOST:
|
||||
coap_pkt->uri_host = (char *)current_option;
|
||||
coap_pkt->uri_host_len = option_length;
|
||||
PRINTF("Uri-Host [%.*s]\n", coap_pkt->uri_host_len, coap_pkt->uri_host);
|
||||
PRINTF("Uri-Host [%.*s]\n", (int)coap_pkt->uri_host_len,
|
||||
coap_pkt->uri_host);
|
||||
break;
|
||||
case COAP_OPTION_URI_PORT:
|
||||
coap_pkt->uri_port = coap_parse_int_option(current_option,
|
||||
|
@ -600,14 +614,14 @@ coap_parse_message(void *packet, uint8_t *data, uint16_t data_len)
|
|||
coap_merge_multi_option((char **)&(coap_pkt->uri_path),
|
||||
&(coap_pkt->uri_path_len), current_option,
|
||||
option_length, '/');
|
||||
PRINTF("Uri-Path [%.*s]\n", coap_pkt->uri_path_len, coap_pkt->uri_path);
|
||||
PRINTF("Uri-Path [%.*s]\n", (int)coap_pkt->uri_path_len, coap_pkt->uri_path);
|
||||
break;
|
||||
case COAP_OPTION_URI_QUERY:
|
||||
/* coap_merge_multi_option() operates in-place on the IPBUF, but final packet field should be const string -> cast to string */
|
||||
coap_merge_multi_option((char **)&(coap_pkt->uri_query),
|
||||
&(coap_pkt->uri_query_len), current_option,
|
||||
option_length, '&');
|
||||
PRINTF("Uri-Query [%.*s]\n", coap_pkt->uri_query_len,
|
||||
PRINTF("Uri-Query [%.*s]\n", (int)coap_pkt->uri_query_len,
|
||||
coap_pkt->uri_query);
|
||||
break;
|
||||
|
||||
|
@ -616,7 +630,7 @@ coap_parse_message(void *packet, uint8_t *data, uint16_t data_len)
|
|||
coap_merge_multi_option((char **)&(coap_pkt->location_path),
|
||||
&(coap_pkt->location_path_len), current_option,
|
||||
option_length, '/');
|
||||
PRINTF("Location-Path [%.*s]\n", coap_pkt->location_path_len,
|
||||
PRINTF("Location-Path [%.*s]\n", (int)coap_pkt->location_path_len,
|
||||
coap_pkt->location_path);
|
||||
break;
|
||||
case COAP_OPTION_LOCATION_QUERY:
|
||||
|
@ -624,14 +638,14 @@ coap_parse_message(void *packet, uint8_t *data, uint16_t data_len)
|
|||
coap_merge_multi_option((char **)&(coap_pkt->location_query),
|
||||
&(coap_pkt->location_query_len), current_option,
|
||||
option_length, '&');
|
||||
PRINTF("Location-Query [%.*s]\n", coap_pkt->location_query_len,
|
||||
PRINTF("Location-Query [%.*s]\n", (int)coap_pkt->location_query_len,
|
||||
coap_pkt->location_query);
|
||||
break;
|
||||
|
||||
case COAP_OPTION_OBSERVE:
|
||||
coap_pkt->observe = coap_parse_int_option(current_option,
|
||||
option_length);
|
||||
PRINTF("Observe [%lu]\n", coap_pkt->observe);
|
||||
PRINTF("Observe [%lu]\n", (unsigned long)coap_pkt->observe);
|
||||
break;
|
||||
case COAP_OPTION_BLOCK2:
|
||||
coap_pkt->block2_num = coap_parse_int_option(current_option,
|
||||
|
@ -641,7 +655,8 @@ coap_parse_message(void *packet, uint8_t *data, uint16_t data_len)
|
|||
coap_pkt->block2_offset = (coap_pkt->block2_num & ~0x0000000F)
|
||||
<< (coap_pkt->block2_num & 0x07);
|
||||
coap_pkt->block2_num >>= 4;
|
||||
PRINTF("Block2 [%lu%s (%u B/blk)]\n", coap_pkt->block2_num,
|
||||
PRINTF("Block2 [%lu%s (%u B/blk)]\n",
|
||||
(unsigned long)coap_pkt->block2_num,
|
||||
coap_pkt->block2_more ? "+" : "", coap_pkt->block2_size);
|
||||
break;
|
||||
case COAP_OPTION_BLOCK1:
|
||||
|
@ -652,16 +667,17 @@ coap_parse_message(void *packet, uint8_t *data, uint16_t data_len)
|
|||
coap_pkt->block1_offset = (coap_pkt->block1_num & ~0x0000000F)
|
||||
<< (coap_pkt->block1_num & 0x07);
|
||||
coap_pkt->block1_num >>= 4;
|
||||
PRINTF("Block1 [%lu%s (%u B/blk)]\n", coap_pkt->block1_num,
|
||||
PRINTF("Block1 [%lu%s (%u B/blk)]\n",
|
||||
(unsigned long)coap_pkt->block1_num,
|
||||
coap_pkt->block1_more ? "+" : "", coap_pkt->block1_size);
|
||||
break;
|
||||
case COAP_OPTION_SIZE2:
|
||||
coap_pkt->size2 = coap_parse_int_option(current_option, option_length);
|
||||
PRINTF("Size2 [%lu]\n", coap_pkt->size2);
|
||||
PRINTF("Size2 [%lu]\n", (unsigned long)coap_pkt->size2);
|
||||
break;
|
||||
case COAP_OPTION_SIZE1:
|
||||
coap_pkt->size1 = coap_parse_int_option(current_option, option_length);
|
||||
PRINTF("Size1 [%lu]\n", coap_pkt->size1);
|
||||
PRINTF("Size1 [%lu]\n", (unsigned long)coap_pkt->size1);
|
||||
break;
|
||||
default:
|
||||
PRINTF("unknown (%u)\n", option_number);
|
||||
|
@ -744,7 +760,7 @@ coap_set_header_content_format(void *packet, unsigned int format)
|
|||
{
|
||||
coap_packet_t *const coap_pkt = (coap_packet_t *)packet;
|
||||
|
||||
coap_pkt->content_format = (coap_content_format_t)format;
|
||||
coap_pkt->content_format = format;
|
||||
SET_OPTION(coap_pkt, COAP_OPTION_CONTENT_FORMAT);
|
||||
return 1;
|
||||
}
|
||||
|
@ -765,7 +781,7 @@ coap_set_header_accept(void *packet, unsigned int accept)
|
|||
{
|
||||
coap_packet_t *const coap_pkt = (coap_packet_t *)packet;
|
||||
|
||||
coap_pkt->accept = (coap_content_format_t)accept;
|
||||
coap_pkt->accept = accept;
|
||||
SET_OPTION(coap_pkt, COAP_OPTION_ACCEPT);
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -93,7 +93,7 @@ typedef struct {
|
|||
|
||||
uint8_t options[COAP_OPTION_SIZE1 / OPTION_MAP_SIZE + 1]; /* bitmap to check if option is set */
|
||||
|
||||
coap_content_format_t content_format; /* parse options once and store; allows setting options in random order */
|
||||
uint16_t content_format; /* parse options once and store; allows setting options in random order */
|
||||
uint32_t max_age;
|
||||
uint8_t etag_len;
|
||||
uint8_t etag[COAP_ETAG_LEN];
|
||||
|
@ -111,7 +111,7 @@ typedef struct {
|
|||
size_t uri_path_len;
|
||||
const char *uri_path;
|
||||
int32_t observe;
|
||||
coap_content_format_t accept;
|
||||
uint16_t accept;
|
||||
uint8_t if_match_len;
|
||||
uint8_t if_match[COAP_ETAG_LEN];
|
||||
uint32_t block2_num;
|
||||
|
@ -135,13 +135,13 @@ typedef struct {
|
|||
/* option format serialization */
|
||||
#define COAP_SERIALIZE_INT_OPTION(number, field, text) \
|
||||
if(IS_OPTION(coap_pkt, number)) { \
|
||||
PRINTF(text " [%u]\n", coap_pkt->field); \
|
||||
PRINTF(text " [%u]\n", (unsigned int)coap_pkt->field); \
|
||||
option += coap_serialize_int_option(number, current_number, option, coap_pkt->field); \
|
||||
current_number = number; \
|
||||
}
|
||||
#define COAP_SERIALIZE_BYTE_OPTION(number, field, text) \
|
||||
if(IS_OPTION(coap_pkt, number)) { \
|
||||
PRINTF(text " %u [0x%02X%02X%02X%02X%02X%02X%02X%02X]\n", coap_pkt->field##_len, \
|
||||
PRINTF(text " %u [0x%02X%02X%02X%02X%02X%02X%02X%02X]\n", (unsigned int)coap_pkt->field##_len, \
|
||||
coap_pkt->field[0], \
|
||||
coap_pkt->field[1], \
|
||||
coap_pkt->field[2], \
|
||||
|
@ -156,18 +156,18 @@ typedef struct {
|
|||
}
|
||||
#define COAP_SERIALIZE_STRING_OPTION(number, field, splitter, text) \
|
||||
if(IS_OPTION(coap_pkt, number)) { \
|
||||
PRINTF(text " [%.*s]\n", coap_pkt->field##_len, coap_pkt->field); \
|
||||
PRINTF(text " [%.*s]\n", (int)coap_pkt->field##_len, coap_pkt->field); \
|
||||
option += coap_serialize_array_option(number, current_number, option, (uint8_t *)coap_pkt->field, coap_pkt->field##_len, splitter); \
|
||||
current_number = number; \
|
||||
}
|
||||
#define COAP_SERIALIZE_BLOCK_OPTION(number, field, text) \
|
||||
if(IS_OPTION(coap_pkt, number)) \
|
||||
{ \
|
||||
PRINTF(text " [%lu%s (%u B/blk)]\n", coap_pkt->field##_num, coap_pkt->field##_more ? "+" : "", coap_pkt->field##_size); \
|
||||
PRINTF(text " [%lu%s (%u B/blk)]\n", (unsigned long)coap_pkt->field##_num, coap_pkt->field##_more ? "+" : "", coap_pkt->field##_size); \
|
||||
uint32_t block = coap_pkt->field##_num << 4; \
|
||||
if(coap_pkt->field##_more) { block |= 0x8; } \
|
||||
block |= 0xF & coap_log_2(coap_pkt->field##_size / 16); \
|
||||
PRINTF(text " encoded: 0x%lX\n", block); \
|
||||
PRINTF(text " encoded: 0x%lX\n", (unsigned long)block); \
|
||||
option += coap_serialize_int_option(number, current_number, option, block); \
|
||||
current_number = number; \
|
||||
}
|
||||
|
|
1
apps/orchestra/Makefile.orchestra
Normal file
1
apps/orchestra/Makefile.orchestra
Normal file
|
@ -0,0 +1 @@
|
|||
orchestra_src = orchestra.c orchestra-rule-default-common.c orchestra-rule-eb-per-time-source.c orchestra-rule-unicast-per-neighbor.c
|
51
apps/orchestra/README.md
Normal file
51
apps/orchestra/README.md
Normal file
|
@ -0,0 +1,51 @@
|
|||
# Orchestra
|
||||
|
||||
## Overview
|
||||
|
||||
Orchestra is an autonomous scheduling solution for TSCH, where nodes maintain
|
||||
their own schedule solely based on their local RPL state. There is no centralized
|
||||
scheduler nor negociatoin with neighbors, i.e. no traffic overhead. The default
|
||||
Orchestra rules can be used out-of-box in any RPL network, reducing contention
|
||||
to a low level. Orchestra is described and evaluated in
|
||||
[*Orchestra: Robust Mesh Networks Through Autonomously Scheduled TSCH*](http://www.simonduquennoy.net/papers/duquennoy15orchestra.pdf), ACM SenSys'15.
|
||||
|
||||
## Requirements
|
||||
|
||||
Orchestra requires a system running TSCH and RPL.
|
||||
For sender-based unicast slots (`ORCHESTRA_UNICAST_SENDER_BASED`), it requires
|
||||
RPL with downwards routing enabled (relies on DAO).
|
||||
|
||||
## Getting Started
|
||||
|
||||
To use Orchestra, add a couple global definitions, e.g in your `project-conf.h` file.
|
||||
|
||||
Disable 6TiSCH minimal schedule:
|
||||
|
||||
`#define TSCH_SCHEDULE_CONF_WITH_6TISCH_MINIMAL 0`
|
||||
|
||||
Enable TSCH link selector (allows Orchestra to assign TSCH links to outgoing packets):
|
||||
|
||||
`#define TSCH_CONF_WITH_LINK_SELECTOR 1`
|
||||
|
||||
Set up the following callbacks:
|
||||
|
||||
```
|
||||
#define TSCH_CALLBACK_NEW_TIME_SOURCE orchestra_callback_new_time_source
|
||||
#define TSCH_CALLBACK_PACKET_READY orchestra_callback_packet_ready
|
||||
#define NETSTACK_CONF_ROUTING_NEIGHBOR_ADDED_CALLBACK orchestra_callback_child_added
|
||||
#define NETSTACK_CONF_ROUTING_NEIGHBOR_REMOVED_CALLBACK orchestra_callback_child_removed
|
||||
```
|
||||
|
||||
To use Orchestra, fist add it to your makefile `APPS` with `APPS += orchestra`.
|
||||
|
||||
Finally:
|
||||
* add Orchestra to your makefile `APPS` with `APPS += orchestra`;
|
||||
* start Orchestra by calling `orchestra_init()` from your application, after
|
||||
including `#include "orchestra.h"`.
|
||||
|
||||
## Configuration
|
||||
|
||||
Orchestra comes with a number of pre-installed rules, `orchestra-rule-*.c`.
|
||||
You can define your own by using any of these as a template.
|
||||
A default Orchestra configuration is described in `orchestra-conf.h`, define your own
|
||||
`ORCHESTRA_CONF_*` macros to override modify the rule set and change rules configuration.
|
105
apps/orchestra/orchestra-conf.h
Normal file
105
apps/orchestra/orchestra-conf.h
Normal file
|
@ -0,0 +1,105 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the Institute nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
* Orchestra configuration
|
||||
*
|
||||
* \author Simon Duquennoy <simonduq@sics.se>
|
||||
*/
|
||||
|
||||
#ifndef __ORCHESTRA_CONF_H__
|
||||
#define __ORCHESTRA_CONF_H__
|
||||
|
||||
#ifdef ORCHESTRA_CONF_RULES
|
||||
#define ORCHESTRA_RULES ORCHESTRA_CONF_RULES
|
||||
#else /* ORCHESTRA_CONF_RULES */
|
||||
/* A default configuration with:
|
||||
* - a sender-based slotframe for EB transmission
|
||||
* - a sender-based or receiver-based slotframe for unicast to RPL parents and children
|
||||
* - a common shared slotframe for any other traffic (mostly broadcast)
|
||||
* */
|
||||
#define ORCHESTRA_RULES { &eb_per_time_source, \
|
||||
&unicast_per_neighbor, \
|
||||
&default_common, \
|
||||
}
|
||||
#endif /* ORCHESTRA_CONF_RULES */
|
||||
|
||||
/* Length of the various slotframes. Tune to balance network capacity,
|
||||
* contention, energy, latency. */
|
||||
#ifdef ORCHESTRA_CONF_EBSF_PERIOD
|
||||
#define ORCHESTRA_EBSF_PERIOD ORCHESTRA_CONF_EBSF_PERIOD
|
||||
#else /* ORCHESTRA_CONF_EBSF_PERIOD */
|
||||
#define ORCHESTRA_EBSF_PERIOD 397
|
||||
#endif /* ORCHESTRA_CONF_EBSF_PERIOD */
|
||||
|
||||
#ifdef ORCHESTRA_CONF_COMMON_SHARED_PERIOD
|
||||
#define ORCHESTRA_COMMON_SHARED_PERIOD ORCHESTRA_CONF_COMMON_SHARED_PERIOD
|
||||
#else /* ORCHESTRA_CONF_COMMON_SHARED_PERIOD */
|
||||
#define ORCHESTRA_COMMON_SHARED_PERIOD 31
|
||||
#endif /* ORCHESTRA_CONF_COMMON_SHARED_PERIOD */
|
||||
|
||||
#ifdef ORCHESTRA_CONF_UNICAST_PERIOD
|
||||
#define ORCHESTRA_UNICAST_PERIOD ORCHESTRA_CONF_UNICAST_PERIOD
|
||||
#else /* ORCHESTRA_CONF_UNICAST_PERIOD */
|
||||
#define ORCHESTRA_UNICAST_PERIOD 17
|
||||
#endif /* ORCHESTRA_CONF_UNICAST_PERIOD */
|
||||
|
||||
/* Is the per-neighbor unicast slotframe sender-based (if not, it is receiver-based).
|
||||
* Note: sender-based works only with RPL storing mode as it relies on DAO and
|
||||
* routing entries to keep track of children and parents. */
|
||||
#ifdef ORCHESTRA_CONF_UNICAST_SENDER_BASED
|
||||
#define ORCHESTRA_UNICAST_SENDER_BASED ORCHESTRA_CONF_UNICAST_SENDER_BASED
|
||||
#else /* ORCHESTRA_CONF_UNICAST_SENDER_BASED */
|
||||
#define ORCHESTRA_UNICAST_SENDER_BASED 0
|
||||
#endif /* ORCHESTRA_CONF_UNICAST_SENDER_BASED */
|
||||
|
||||
/* The hash function used to assign timeslot to a given node (based on its link-layer address) */
|
||||
#ifdef ORCHESTRA_CONF_LINKADDR_HASH
|
||||
#define ORCHESTRA_LINKADDR_HASH ORCHESTRA_CONF_LINKADDR_HASH
|
||||
#else /* ORCHESTRA_CONF_LINKADDR_HASH */
|
||||
#define ORCHESTRA_LINKADDR_HASH(addr) ((addr != NULL) ? (addr)->u8[LINKADDR_SIZE - 1] : -1)
|
||||
#endif /* ORCHESTRA_CONF_LINKADDR_HASH */
|
||||
|
||||
/* The maximum hash */
|
||||
#ifdef ORCHESTRA_CONF_MAX_HASH
|
||||
#define ORCHESTRA_MAX_HASH ORCHESTRA_CONF_MAX_HASH
|
||||
#else /* ORCHESTRA_CONF_MAX_HASH */
|
||||
#define ORCHESTRA_MAX_HASH 0x7fff
|
||||
#endif /* ORCHESTRA_CONF_MAX_HASH */
|
||||
|
||||
/* Is the "hash" function collision-free? (e.g. it maps to unique node-ids) */
|
||||
#ifdef ORCHESTRA_CONF_COLLISION_FREE_HASH
|
||||
#define ORCHESTRA_COLLISION_FREE_HASH ORCHESTRA_CONF_COLLISION_FREE_HASH
|
||||
#else /* ORCHESTRA_CONF_COLLISION_FREE_HASH */
|
||||
#define ORCHESTRA_COLLISION_FREE_HASH 0 /* Set to 1 if ORCHESTRA_LINKADDR_HASH returns unique hashes */
|
||||
#endif /* ORCHESTRA_CONF_COLLISION_FREE_HASH */
|
||||
|
||||
#endif /* __ORCHESTRA_CONF_H__ */
|
86
apps/orchestra/orchestra-rule-default-common.c
Normal file
86
apps/orchestra/orchestra-rule-default-common.c
Normal file
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the Institute nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
/**
|
||||
* \file
|
||||
* Orchestra: a slotframe with a single shared link, common to all nodes
|
||||
* in the network, used for unicast and broadcast.
|
||||
*
|
||||
* \author Simon Duquennoy <simonduq@sics.se>
|
||||
*/
|
||||
|
||||
#include "contiki.h"
|
||||
#include "orchestra.h"
|
||||
|
||||
static uint16_t slotframe_handle = 0;
|
||||
static uint16_t channel_offset = 0;
|
||||
|
||||
#if ORCHESTRA_EBSF_PERIOD > 0
|
||||
/* There is a slotframe for EBs, use this slotframe for non-EB traffic only */
|
||||
#define ORCHESTRA_COMMON_SHARED_TYPE LINK_TYPE_NORMAL
|
||||
#else
|
||||
/* There is no slotframe for EBs, use this slotframe both EB and non-EB traffic */
|
||||
#define ORCHESTRA_COMMON_SHARED_TYPE LINK_TYPE_ADVERTISING
|
||||
#endif
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static int
|
||||
select_packet(uint16_t *slotframe, uint16_t *timeslot)
|
||||
{
|
||||
/* We are the default slotframe, select anything */
|
||||
if(slotframe != NULL) {
|
||||
*slotframe = slotframe_handle;
|
||||
}
|
||||
if(timeslot != NULL) {
|
||||
*timeslot = 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
init(uint16_t sf_handle)
|
||||
{
|
||||
slotframe_handle = sf_handle;
|
||||
channel_offset = slotframe_handle;
|
||||
/* Default slotframe: for broadcast or unicast to neighbors we
|
||||
* do not have a link to */
|
||||
struct tsch_slotframe *sf_common = tsch_schedule_add_slotframe(slotframe_handle, ORCHESTRA_COMMON_SHARED_PERIOD);
|
||||
tsch_schedule_add_link(sf_common,
|
||||
LINK_OPTION_RX | LINK_OPTION_TX | LINK_OPTION_SHARED,
|
||||
ORCHESTRA_COMMON_SHARED_TYPE, &tsch_broadcast_address,
|
||||
0, channel_offset);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
struct orchestra_rule default_common = {
|
||||
init,
|
||||
NULL,
|
||||
select_packet,
|
||||
NULL,
|
||||
NULL,
|
||||
};
|
116
apps/orchestra/orchestra-rule-eb-per-time-source.c
Normal file
116
apps/orchestra/orchestra-rule-eb-per-time-source.c
Normal file
|
@ -0,0 +1,116 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the Institute nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
/**
|
||||
* \file
|
||||
|
||||
* Orchestra: a slotframe dedicated to transmission of EBs.
|
||||
* Nodes transmit at a timeslot defined as hash(MAC) % ORCHESTRA_EBSF_PERIOD
|
||||
* Nodes listen at a timeslot defined as hash(time_source.MAC) % ORCHESTRA_EBSF_PERIOD
|
||||
* \author Simon Duquennoy <simonduq@sics.se>
|
||||
*/
|
||||
|
||||
#include "contiki.h"
|
||||
#include "orchestra.h"
|
||||
#include "net/packetbuf.h"
|
||||
|
||||
static uint16_t slotframe_handle = 0;
|
||||
static uint16_t channel_offset = 0;
|
||||
static struct tsch_slotframe *sf_eb;
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static uint16_t
|
||||
get_node_timeslot(const linkaddr_t *addr)
|
||||
{
|
||||
#if ORCHESTRA_EBSF_PERIOD > 0
|
||||
return ORCHESTRA_LINKADDR_HASH(addr) % ORCHESTRA_EBSF_PERIOD;
|
||||
#else
|
||||
return 0xffff;
|
||||
#endif
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static int
|
||||
select_packet(uint16_t *slotframe, uint16_t *timeslot)
|
||||
{
|
||||
/* Select EBs only */
|
||||
if(packetbuf_attr(PACKETBUF_ATTR_FRAME_TYPE) == FRAME802154_BEACONFRAME) {
|
||||
if(slotframe != NULL) {
|
||||
*slotframe = slotframe_handle;
|
||||
}
|
||||
if(timeslot != NULL) {
|
||||
*timeslot = get_node_timeslot(&linkaddr_node_addr);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
new_time_source(const struct tsch_neighbor *old, const struct tsch_neighbor *new)
|
||||
{
|
||||
uint16_t old_ts = get_node_timeslot(&old->addr);
|
||||
uint16_t new_ts = get_node_timeslot(&new->addr);
|
||||
|
||||
if(new_ts == old_ts) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(old_ts != 0xffff) {
|
||||
/* Stop listening to the old time source's EBs */
|
||||
tsch_schedule_remove_link_by_timeslot(sf_eb, old_ts);
|
||||
}
|
||||
if(new_ts != 0xffff) {
|
||||
/* Listen to the time source's EBs */
|
||||
tsch_schedule_add_link(sf_eb,
|
||||
LINK_OPTION_RX,
|
||||
LINK_TYPE_ADVERTISING_ONLY, NULL,
|
||||
new_ts, 0);
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
init(uint16_t sf_handle)
|
||||
{
|
||||
slotframe_handle = sf_handle;
|
||||
channel_offset = sf_handle;
|
||||
sf_eb = tsch_schedule_add_slotframe(slotframe_handle, ORCHESTRA_EBSF_PERIOD);
|
||||
/* EB link: every neighbor uses its own to avoid contention */
|
||||
tsch_schedule_add_link(sf_eb,
|
||||
LINK_OPTION_TX,
|
||||
LINK_TYPE_ADVERTISING_ONLY, &tsch_broadcast_address,
|
||||
get_node_timeslot(&linkaddr_node_addr), 0);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
struct orchestra_rule eb_per_time_source = {
|
||||
init,
|
||||
new_time_source,
|
||||
select_packet,
|
||||
NULL,
|
||||
NULL,
|
||||
};
|
194
apps/orchestra/orchestra-rule-unicast-per-neighbor.c
Normal file
194
apps/orchestra/orchestra-rule-unicast-per-neighbor.c
Normal file
|
@ -0,0 +1,194 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the Institute nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
/**
|
||||
* \file
|
||||
* Orchestra: a slotframe dedicated to unicast data transmission.
|
||||
* If sender-based:
|
||||
* Nodes listen at a timeslot defined as hash(MAC) % ORCHESTRA_SB_UNICAST_PERIOD
|
||||
* Nodes transmit at: for each nbr in RPL children and RPL preferred parent,
|
||||
* hash(nbr.MAC) % ORCHESTRA_SB_UNICAST_PERIOD
|
||||
* If receiver-based: the opposite
|
||||
*
|
||||
* \author Simon Duquennoy <simonduq@sics.se>
|
||||
*/
|
||||
|
||||
#include "contiki.h"
|
||||
#include "orchestra.h"
|
||||
#include "net/ipv6/uip-ds6-route.h"
|
||||
#include "net/packetbuf.h"
|
||||
|
||||
#if ORCHESTRA_UNICAST_SENDER_BASED && ORCHESTRA_COLLISION_FREE_HASH
|
||||
#define UNICAST_SLOT_SHARED_FLAG ((ORCHESTRA_UNICAST_PERIOD < (ORCHESTRA_MAX_HASH + 1)) ? LINK_OPTION_SHARED : 0)
|
||||
#else
|
||||
#define UNICAST_SLOT_SHARED_FLAG LINK_OPTION_SHARED
|
||||
#endif
|
||||
|
||||
static uint16_t slotframe_handle = 0;
|
||||
static uint16_t channel_offset = 0;
|
||||
static struct tsch_slotframe *sf_unicast;
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static uint16_t
|
||||
get_node_timeslot(const linkaddr_t *addr)
|
||||
{
|
||||
if(addr != NULL && ORCHESTRA_UNICAST_PERIOD > 0) {
|
||||
return ORCHESTRA_LINKADDR_HASH(addr) % ORCHESTRA_UNICAST_PERIOD;
|
||||
} else {
|
||||
return 0xffff;
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static int
|
||||
neighbor_has_uc_link(const linkaddr_t *linkaddr)
|
||||
{
|
||||
if(linkaddr != NULL && !linkaddr_cmp(linkaddr, &linkaddr_null)) {
|
||||
if((orchestra_parent_knows_us || !ORCHESTRA_UNICAST_SENDER_BASED)
|
||||
&& linkaddr_cmp(&orchestra_parent_linkaddr, linkaddr)) {
|
||||
return 1;
|
||||
}
|
||||
if(nbr_table_get_from_lladdr(nbr_routes, (linkaddr_t *)linkaddr) != NULL) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
add_uc_link(const linkaddr_t *linkaddr)
|
||||
{
|
||||
if(linkaddr != NULL) {
|
||||
uint16_t timeslot = get_node_timeslot(linkaddr);
|
||||
tsch_schedule_add_link(sf_unicast,
|
||||
ORCHESTRA_UNICAST_SENDER_BASED ? LINK_OPTION_RX : LINK_OPTION_TX | UNICAST_SLOT_SHARED_FLAG,
|
||||
LINK_TYPE_NORMAL, &tsch_broadcast_address,
|
||||
timeslot, channel_offset);
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
remove_uc_link(const linkaddr_t *linkaddr)
|
||||
{
|
||||
uint16_t timeslot;
|
||||
struct tsch_link *l;
|
||||
|
||||
if(linkaddr == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
timeslot = get_node_timeslot(linkaddr);
|
||||
l = tsch_schedule_get_link_by_timeslot(sf_unicast, timeslot);
|
||||
if(l == NULL) {
|
||||
return;
|
||||
}
|
||||
/* Does our current parent need this timeslot? */
|
||||
if(timeslot == get_node_timeslot(&orchestra_parent_linkaddr)) {
|
||||
/* Yes, this timeslot is being used, return */
|
||||
return;
|
||||
}
|
||||
/* Does any other child need this timeslot?
|
||||
* (lookup all route next hops) */
|
||||
nbr_table_item_t *item = nbr_table_head(nbr_routes);
|
||||
while(item != NULL) {
|
||||
linkaddr_t *addr = nbr_table_get_lladdr(nbr_routes, item);
|
||||
if(timeslot == get_node_timeslot(addr)) {
|
||||
/* Yes, this timeslot is being used, return */
|
||||
return;
|
||||
}
|
||||
item = nbr_table_next(nbr_routes, item);
|
||||
}
|
||||
tsch_schedule_remove_link(sf_unicast, l);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
child_added(const linkaddr_t *linkaddr)
|
||||
{
|
||||
add_uc_link(linkaddr);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
child_removed(const linkaddr_t *linkaddr)
|
||||
{
|
||||
remove_uc_link(linkaddr);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static int
|
||||
select_packet(uint16_t *slotframe, uint16_t *timeslot)
|
||||
{
|
||||
/* Select data packets we have a unicast link to */
|
||||
const linkaddr_t *dest = packetbuf_addr(PACKETBUF_ADDR_RECEIVER);
|
||||
if(packetbuf_attr(PACKETBUF_ATTR_FRAME_TYPE) == FRAME802154_DATAFRAME
|
||||
&& neighbor_has_uc_link(dest)) {
|
||||
if(slotframe != NULL) {
|
||||
*slotframe = slotframe_handle;
|
||||
}
|
||||
if(timeslot != NULL) {
|
||||
*timeslot = ORCHESTRA_UNICAST_SENDER_BASED ? get_node_timeslot(&linkaddr_node_addr) : get_node_timeslot(dest);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
new_time_source(const struct tsch_neighbor *old, const struct tsch_neighbor *new)
|
||||
{
|
||||
if(new != old) {
|
||||
const linkaddr_t *new_addr = new != NULL ? &new->addr : NULL;
|
||||
if(new_addr != NULL) {
|
||||
linkaddr_copy(&orchestra_parent_linkaddr, new_addr);
|
||||
} else {
|
||||
linkaddr_copy(&orchestra_parent_linkaddr, &linkaddr_null);
|
||||
}
|
||||
remove_uc_link(new_addr);
|
||||
add_uc_link(new_addr);
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
init(uint16_t sf_handle)
|
||||
{
|
||||
slotframe_handle = sf_handle;
|
||||
channel_offset = sf_handle;
|
||||
/* Slotframe for unicast transmissions */
|
||||
sf_unicast = tsch_schedule_add_slotframe(slotframe_handle, ORCHESTRA_UNICAST_PERIOD);
|
||||
uint16_t timeslot = get_node_timeslot(&linkaddr_node_addr);
|
||||
tsch_schedule_add_link(sf_unicast,
|
||||
ORCHESTRA_UNICAST_SENDER_BASED ? LINK_OPTION_TX | UNICAST_SLOT_SHARED_FLAG: LINK_OPTION_RX,
|
||||
LINK_TYPE_NORMAL, &tsch_broadcast_address,
|
||||
timeslot, channel_offset);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
struct orchestra_rule unicast_per_neighbor = {
|
||||
init,
|
||||
new_time_source,
|
||||
select_packet,
|
||||
child_added,
|
||||
child_removed,
|
||||
};
|
166
apps/orchestra/orchestra.c
Normal file
166
apps/orchestra/orchestra.c
Normal file
|
@ -0,0 +1,166 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the Institute nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
* Orchestra: an autonomous scheduler for TSCH exploiting RPL state.
|
||||
* See "Orchestra: Robust Mesh Networks Through Autonomously Scheduled TSCH", ACM SenSys'15
|
||||
*
|
||||
* \author Simon Duquennoy <simonduq@sics.se>
|
||||
*/
|
||||
|
||||
#include "contiki.h"
|
||||
#include "orchestra.h"
|
||||
#include "net/packetbuf.h"
|
||||
#include "net/ipv6/uip-icmp6.h"
|
||||
#include "net/rpl/rpl-private.h"
|
||||
#include "net/rime/rime.h" /* Needed for so-called rime-sniffer */
|
||||
|
||||
#define DEBUG DEBUG_PRINT
|
||||
#include "net/ip/uip-debug.h"
|
||||
|
||||
/* A net-layer sniffer for packets sent and received */
|
||||
static void orchestra_packet_received(void);
|
||||
static void orchestra_packet_sent(int mac_status);
|
||||
RIME_SNIFFER(orchestra_sniffer, orchestra_packet_received, orchestra_packet_sent);
|
||||
|
||||
/* The current RPL preferred parent's link-layer address */
|
||||
linkaddr_t orchestra_parent_linkaddr;
|
||||
/* Set to one only after getting an ACK for a DAO sent to our preferred parent */
|
||||
int orchestra_parent_knows_us = 0;
|
||||
|
||||
/* The set of Orchestra rules in use */
|
||||
const struct orchestra_rule *all_rules[] = ORCHESTRA_RULES;
|
||||
#define NUM_RULES (sizeof(all_rules) / sizeof(struct orchestra_rule *))
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
orchestra_packet_received(void)
|
||||
{
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
orchestra_packet_sent(int mac_status)
|
||||
{
|
||||
/* Check if our parent just ACKed a DAO */
|
||||
if(orchestra_parent_knows_us == 0
|
||||
&& mac_status == MAC_TX_OK
|
||||
&& packetbuf_attr(PACKETBUF_ATTR_NETWORK_ID) == UIP_PROTO_ICMP6
|
||||
&& packetbuf_attr(PACKETBUF_ATTR_CHANNEL) == (ICMP6_RPL << 8 | RPL_CODE_DAO)) {
|
||||
if(!linkaddr_cmp(&orchestra_parent_linkaddr, &linkaddr_null)
|
||||
&& linkaddr_cmp(&orchestra_parent_linkaddr, packetbuf_addr(PACKETBUF_ADDR_RECEIVER))) {
|
||||
orchestra_parent_knows_us = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
orchestra_callback_child_added(const linkaddr_t *addr)
|
||||
{
|
||||
/* Notify all Orchestra rules that a child was added */
|
||||
int i;
|
||||
for(i = 0; i < NUM_RULES; i++) {
|
||||
if(all_rules[i]->child_added != NULL) {
|
||||
all_rules[i]->child_added(addr);
|
||||
}
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
orchestra_callback_child_removed(const linkaddr_t *addr)
|
||||
{
|
||||
/* Notify all Orchestra rules that a child was removed */
|
||||
int i;
|
||||
for(i = 0; i < NUM_RULES; i++) {
|
||||
if(all_rules[i]->child_removed != NULL) {
|
||||
all_rules[i]->child_removed(addr);
|
||||
}
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
orchestra_callback_packet_ready(void)
|
||||
{
|
||||
int i;
|
||||
/* By default, use any slotframe, any timeslot */
|
||||
uint16_t slotframe = 9;
|
||||
uint16_t timeslot = 0xffff;
|
||||
|
||||
/* Loop over all rules until finding one able to handle the packet */
|
||||
for(i = 0; i < NUM_RULES; i++) {
|
||||
if(all_rules[i]->select_packet != NULL) {
|
||||
if(all_rules[i]->select_packet(&slotframe, ×lot)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if TSCH_WITH_LINK_SELECTOR
|
||||
packetbuf_set_attr(PACKETBUF_ATTR_TSCH_SLOTFRAME, slotframe);
|
||||
packetbuf_set_attr(PACKETBUF_ATTR_TSCH_TIMESLOT, timeslot);
|
||||
#endif
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
orchestra_callback_new_time_source(const struct tsch_neighbor *old, const struct tsch_neighbor *new)
|
||||
{
|
||||
/* Orchestra assumes that the time source is also the RPL parent.
|
||||
* This is the case if the following is set:
|
||||
* #define RPL_CALLBACK_PARENT_SWITCH tsch_rpl_callback_parent_switch
|
||||
* */
|
||||
|
||||
int i;
|
||||
if(new != old) {
|
||||
orchestra_parent_knows_us = 0;
|
||||
}
|
||||
for(i = 0; i < NUM_RULES; i++) {
|
||||
if(all_rules[i]->new_time_source != NULL) {
|
||||
all_rules[i]->new_time_source(old, new);
|
||||
}
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
orchestra_init(void)
|
||||
{
|
||||
int i;
|
||||
/* Snoop on packet transmission to know if our parent knows about us
|
||||
* (i.e. has ACKed at one of our DAOs since we decided to use it as a parent) */
|
||||
rime_sniffer_add(&orchestra_sniffer);
|
||||
linkaddr_copy(&orchestra_parent_linkaddr, &linkaddr_null);
|
||||
/* Initialize all Orchestra rules */
|
||||
for(i = 0; i < NUM_RULES; i++) {
|
||||
if(all_rules[i]->init != NULL) {
|
||||
PRINTF("Orchestra: initializing rule %u\n", i);
|
||||
all_rules[i]->init(i);
|
||||
}
|
||||
}
|
||||
PRINTF("Orchestra: initialization done\n");
|
||||
}
|
74
apps/orchestra/orchestra.h
Normal file
74
apps/orchestra/orchestra.h
Normal file
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the Institute nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
* Orchestra header file
|
||||
*
|
||||
* \author Simon Duquennoy <simonduq@sics.se>
|
||||
*/
|
||||
|
||||
#ifndef __ORCHESTRA_H__
|
||||
#define __ORCHESTRA_H__
|
||||
|
||||
#include "net/mac/tsch/tsch.h"
|
||||
#include "net/mac/tsch/tsch-conf.h"
|
||||
#include "net/mac/tsch/tsch-schedule.h"
|
||||
#include "orchestra-conf.h"
|
||||
|
||||
/* The structure of an Orchestra rule */
|
||||
struct orchestra_rule {
|
||||
void (* init)(uint16_t slotframe_handle);
|
||||
void (* new_time_source)(const struct tsch_neighbor *old, const struct tsch_neighbor *new);
|
||||
int (* select_packet)(uint16_t *slotframe, uint16_t *timeslot);
|
||||
void (* child_added)(const linkaddr_t *addr);
|
||||
void (* child_removed)(const linkaddr_t *addr);
|
||||
};
|
||||
|
||||
struct orchestra_rule eb_per_time_source;
|
||||
struct orchestra_rule unicast_per_neighbor;
|
||||
struct orchestra_rule default_common;
|
||||
|
||||
extern linkaddr_t orchestra_parent_linkaddr;
|
||||
extern int orchestra_parent_knows_us;
|
||||
|
||||
/* Call from application to start Orchestra */
|
||||
void orchestra_init(void);
|
||||
/* Callbacks requied for Orchestra to operate */
|
||||
/* Set with #define TSCH_CALLBACK_PACKET_READY orchestra_callback_packet_ready */
|
||||
void orchestra_callback_packet_ready(void);
|
||||
/* Set with #define TSCH_CALLBACK_NEW_TIME_SOURCE orchestra_callback_new_time_source */
|
||||
void orchestra_callback_new_time_source(const struct tsch_neighbor *old, const struct tsch_neighbor *new);
|
||||
/* Set with #define NETSTACK_CONF_ROUTING_NEIGHBOR_ADDED_CALLBACK orchestra_callback_child_added */
|
||||
void orchestra_callback_child_added(const linkaddr_t *addr);
|
||||
/* Set with #define NETSTACK_CONF_ROUTING_NEIGHBOR_REMOVED_CALLBACK orchestra_callback_child_removed */
|
||||
void orchestra_callback_child_removed(const linkaddr_t *addr);
|
||||
|
||||
#endif /* __ORCHESTRA_H__ */
|
|
@ -48,15 +48,15 @@
|
|||
|
||||
struct powertrace_sniff_stats {
|
||||
struct powertrace_sniff_stats *next;
|
||||
uint32_t num_input, num_output;
|
||||
uint32_t input_txtime, input_rxtime;
|
||||
uint32_t output_txtime, output_rxtime;
|
||||
unsigned long num_input, num_output;
|
||||
unsigned long input_txtime, input_rxtime;
|
||||
unsigned long output_txtime, output_rxtime;
|
||||
#if NETSTACK_CONF_WITH_IPV6
|
||||
uint16_t proto; /* includes proto + possibly flags */
|
||||
#endif
|
||||
uint16_t channel;
|
||||
uint32_t last_input_txtime, last_input_rxtime;
|
||||
uint32_t last_output_txtime, last_output_rxtime;
|
||||
unsigned long last_input_txtime, last_input_rxtime;
|
||||
unsigned long last_output_txtime, last_output_rxtime;
|
||||
};
|
||||
|
||||
#define INPUT 1
|
||||
|
@ -72,17 +72,17 @@ PROCESS(powertrace_process, "Periodic power output");
|
|||
void
|
||||
powertrace_print(char *str)
|
||||
{
|
||||
static uint32_t last_cpu, last_lpm, last_transmit, last_listen;
|
||||
static uint32_t last_idle_transmit, last_idle_listen;
|
||||
static unsigned long last_cpu, last_lpm, last_transmit, last_listen;
|
||||
static unsigned long last_idle_transmit, last_idle_listen;
|
||||
|
||||
uint32_t cpu, lpm, transmit, listen;
|
||||
uint32_t all_cpu, all_lpm, all_transmit, all_listen;
|
||||
uint32_t idle_transmit, idle_listen;
|
||||
uint32_t all_idle_transmit, all_idle_listen;
|
||||
unsigned long cpu, lpm, transmit, listen;
|
||||
unsigned long all_cpu, all_lpm, all_transmit, all_listen;
|
||||
unsigned long idle_transmit, idle_listen;
|
||||
unsigned long all_idle_transmit, all_idle_listen;
|
||||
|
||||
static uint32_t seqno;
|
||||
static unsigned long seqno;
|
||||
|
||||
uint32_t time, all_time, radio, all_radio;
|
||||
unsigned long time, all_time, radio, all_radio;
|
||||
|
||||
struct powertrace_sniff_stats *s;
|
||||
|
||||
|
@ -287,13 +287,8 @@ output_sniffer(int mac_status)
|
|||
static void
|
||||
sniffprint(char *prefix, int seqno)
|
||||
{
|
||||
const linkaddr_t *sender, *receiver, *esender, *ereceiver;
|
||||
|
||||
sender = packetbuf_addr(PACKETBUF_ADDR_SENDER);
|
||||
receiver = packetbuf_addr(PACKETBUF_ADDR_RECEIVER);
|
||||
const linkaddr_t *esender;
|
||||
esender = packetbuf_addr(PACKETBUF_ADDR_ESENDER);
|
||||
ereceiver = packetbuf_addr(PACKETBUF_ADDR_ERECEIVER);
|
||||
|
||||
|
||||
printf("%lu %s %d %u %d %d %d.%d %u %u\n",
|
||||
clock_time(),
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
/*
|
||||
* Copyright (c) 2003, Adam Dunkels.
|
||||
* All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials provided
|
||||
* with the distribution.
|
||||
* with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote
|
||||
* products derived from this software without specific prior
|
||||
* written permission.
|
||||
* written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
||||
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
|
@ -25,7 +25,7 @@
|
|||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the Contiki desktop OS
|
||||
*
|
||||
|
@ -35,7 +35,7 @@
|
|||
/**
|
||||
* \file
|
||||
* The program handler, used for loading programs and starting the
|
||||
* screensaver.
|
||||
* screensaver.
|
||||
* \author Adam Dunkels <adam@dunkels.com>
|
||||
*
|
||||
* The Contiki program handler is responsible for the Contiki menu and
|
||||
|
@ -45,7 +45,7 @@
|
|||
* The program handler also is responsible for starting the
|
||||
* screensaver when the CTK detects that it should be started.
|
||||
*/
|
||||
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
@ -161,7 +161,7 @@ char program_handler_screensaver[20];
|
|||
/*-----------------------------------------------------------------------------------*/
|
||||
void
|
||||
program_handler_add(struct dsc *dsc, char *menuname,
|
||||
unsigned char desktop)
|
||||
unsigned char desktop)
|
||||
{
|
||||
contikidsc[contikidsclast++] = dsc;
|
||||
ctk_menuitem_add(&contikimenu, menuname);
|
||||
|
@ -228,7 +228,7 @@ program_handler_load(char *name, char *arg)
|
|||
{
|
||||
#ifdef WITH_LOADER_ARCH
|
||||
struct pnarg *pnarg;
|
||||
|
||||
|
||||
pnarg = pnarg_copy(name, arg);
|
||||
if(pnarg != NULL) {
|
||||
process_post(&program_handler_process, LOADER_EVENT_DISPLAY_NAME, pnarg);
|
||||
|
@ -246,6 +246,7 @@ program_handler_load(char *name, char *arg)
|
|||
#else /* WITH_LOADER_ARCH */
|
||||
#define RUN(prg, process, arg) process_start(process, arg)
|
||||
#endif /* WITH_LOADER_ARCH */
|
||||
#if CTK_CONF_SCREENSAVER
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/**
|
||||
* Configures the name of the screensaver to be loaded when
|
||||
|
@ -255,7 +256,6 @@ program_handler_load(char *name, char *arg)
|
|||
* should be used.
|
||||
*/
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
#if CTK_CONF_SCREENSAVER
|
||||
void
|
||||
program_handler_setscreensaver(char *name)
|
||||
{
|
||||
|
@ -272,17 +272,17 @@ static void
|
|||
make_windows(void)
|
||||
{
|
||||
ctk_window_new(&runwindow, 16, 3, "Run");
|
||||
|
||||
|
||||
CTK_WIDGET_ADD(&runwindow, &namelabel);
|
||||
CTK_WIDGET_ADD(&runwindow, &nameentry);
|
||||
CTK_WIDGET_ADD(&runwindow, &loadbutton);
|
||||
|
||||
|
||||
CTK_WIDGET_FOCUS(&runwindow, &nameentry);
|
||||
|
||||
|
||||
ctk_dialog_new(&loadingdialog, 25, 1);
|
||||
CTK_WIDGET_ADD(&loadingdialog, &loadingmsg);
|
||||
CTK_WIDGET_ADD(&loadingdialog, &loadingname);
|
||||
|
||||
|
||||
ctk_dialog_new(&errordialog, 22, 8);
|
||||
CTK_WIDGET_ADD(&errordialog, &errormsg);
|
||||
CTK_WIDGET_ADD(&errordialog, &errorfilelabel);
|
||||
|
@ -302,20 +302,20 @@ PROCESS_THREAD(program_handler_process, ev, data)
|
|||
struct dsc **dscp;
|
||||
|
||||
PROCESS_BEGIN();
|
||||
|
||||
|
||||
/* Create the menus */
|
||||
ctk_menu_add(&contikimenu);
|
||||
#if WITH_LOADER_ARCH
|
||||
runmenuitem = ctk_menuitem_add(&contikimenu, "Run program...");
|
||||
|
||||
|
||||
make_windows();
|
||||
#endif /* WITH_LOADER_ARCH */
|
||||
#if QUIT_MENU
|
||||
quitmenuitem = ctk_menuitem_add(&contikimenu, "Quit");
|
||||
#endif /* QUIT_MENU */
|
||||
|
||||
|
||||
displayname = NULL;
|
||||
|
||||
|
||||
#if CTK_CONF_SCREENSAVER
|
||||
program_handler_screensaver[0] = 0;
|
||||
#endif /* CTK_CONF_SCREENSAVER */
|
||||
|
@ -325,106 +325,106 @@ PROCESS_THREAD(program_handler_process, ev, data)
|
|||
if(ev == ctk_signal_button_activate) {
|
||||
#ifdef WITH_LOADER_ARCH
|
||||
if(data == (process_data_t)&loadbutton) {
|
||||
ctk_window_close(&runwindow);
|
||||
program_handler_load(name, NULL);
|
||||
ctk_window_close(&runwindow);
|
||||
program_handler_load(name, NULL);
|
||||
} else if(data == (process_data_t)&errorokbutton) {
|
||||
ctk_dialog_close();
|
||||
ctk_dialog_close();
|
||||
}
|
||||
#endif /* WITH_LOADER_ARCH */
|
||||
#if QUIT_MENU
|
||||
if(data == (process_data_t)&quityesbutton) {
|
||||
ctk_draw_init();
|
||||
exit(EXIT_SUCCESS);
|
||||
ctk_draw_init();
|
||||
exit(EXIT_SUCCESS);
|
||||
} else if(data == (process_data_t)&quitnobutton) {
|
||||
ctk_dialog_close();
|
||||
ctk_dialog_close();
|
||||
}
|
||||
#endif /* QUIT_MENU */
|
||||
dscp = &contikidsc[0];
|
||||
for(i = 0; i < CTK_MAXMENUITEMS; ++i) {
|
||||
if(*dscp != NULL
|
||||
for(i = 0; i < CTK_MAXMENUITEMS; ++i) {
|
||||
if(*dscp != NULL
|
||||
#if CTK_CONF_ICONS
|
||||
&& data == (process_data_t)(*dscp)->icon
|
||||
&& data == (process_data_t)(*dscp)->icon
|
||||
#endif /* CTK_CONF_ICONS */
|
||||
) {
|
||||
RUN((*dscp)->prgname, (*dscp)->process, NULL);
|
||||
break;
|
||||
}
|
||||
++dscp;
|
||||
) {
|
||||
RUN((*dscp)->prgname, (*dscp)->process, NULL);
|
||||
break;
|
||||
}
|
||||
++dscp;
|
||||
}
|
||||
} else if(ev == ctk_signal_menu_activate) {
|
||||
if((struct ctk_menu *)data == &contikimenu) {
|
||||
#if WITH_LOADER_ARCH
|
||||
dsc = contikidsc[contikimenu.active];
|
||||
if(dsc != NULL) {
|
||||
RUN(dsc->prgname, dsc->process, NULL);
|
||||
} else if(contikimenu.active == runmenuitem) {
|
||||
make_windows();
|
||||
ctk_window_close(&runwindow);
|
||||
ctk_window_open(&runwindow);
|
||||
CTK_WIDGET_FOCUS(&runwindow, &nameentry);
|
||||
}
|
||||
dsc = contikidsc[contikimenu.active];
|
||||
if(dsc != NULL) {
|
||||
RUN(dsc->prgname, dsc->process, NULL);
|
||||
} else if(contikimenu.active == runmenuitem) {
|
||||
make_windows();
|
||||
ctk_window_close(&runwindow);
|
||||
ctk_window_open(&runwindow);
|
||||
CTK_WIDGET_FOCUS(&runwindow, &nameentry);
|
||||
}
|
||||
#else /* WITH_LOADER_ARCH */
|
||||
if(contikidsc[contikimenu.active] != NULL) {
|
||||
RUN(contikidsc[contikimenu.active]->prgname,
|
||||
contikidsc[contikimenu.active]->process,
|
||||
NULL);
|
||||
}
|
||||
if(contikidsc[contikimenu.active] != NULL) {
|
||||
RUN(contikidsc[contikimenu.active]->prgname,
|
||||
contikidsc[contikimenu.active]->process,
|
||||
NULL);
|
||||
}
|
||||
#endif /* WITH_LOADER_ARCH */
|
||||
#if QUIT_MENU
|
||||
if(contikimenu.active == quitmenuitem) {
|
||||
ctk_dialog_new(&quitdialog, 24, 5);
|
||||
CTK_WIDGET_ADD(&quitdialog, &quitdialoglabel);
|
||||
CTK_WIDGET_ADD(&quitdialog, &quityesbutton);
|
||||
CTK_WIDGET_ADD(&quitdialog, &quitnobutton);
|
||||
CTK_WIDGET_FOCUS(&quitdialog, &quitnobutton);
|
||||
ctk_dialog_open(&quitdialog);
|
||||
}
|
||||
if(contikimenu.active == quitmenuitem) {
|
||||
ctk_dialog_new(&quitdialog, 24, 5);
|
||||
CTK_WIDGET_ADD(&quitdialog, &quitdialoglabel);
|
||||
CTK_WIDGET_ADD(&quitdialog, &quityesbutton);
|
||||
CTK_WIDGET_ADD(&quitdialog, &quitnobutton);
|
||||
CTK_WIDGET_FOCUS(&quitdialog, &quitnobutton);
|
||||
ctk_dialog_open(&quitdialog);
|
||||
}
|
||||
#endif /* QUIT_MENU */
|
||||
}
|
||||
#if CTK_CONF_SCREENSAVER
|
||||
} else if(ev == ctk_signal_screensaver_start) {
|
||||
#if WITH_LOADER_ARCH
|
||||
if(program_handler_screensaver[0] != 0) {
|
||||
program_handler_load(program_handler_screensaver, NULL);
|
||||
program_handler_load(program_handler_screensaver, NULL);
|
||||
}
|
||||
#endif /* WITH_LOADER_ARCH */
|
||||
#endif /* CTK_CONF_SCREENSAVER */
|
||||
} else if(ev == LOADER_EVENT_DISPLAY_NAME) {
|
||||
#if WITH_LOADER_ARCH
|
||||
if(displayname == NULL) {
|
||||
make_windows();
|
||||
|
||||
ctk_label_set_text(&loadingname, ((struct pnarg *)data)->name);
|
||||
ctk_dialog_open(&loadingdialog);
|
||||
process_post(&program_handler_process, LOADER_EVENT_LOAD, data);
|
||||
displayname = data;
|
||||
make_windows();
|
||||
|
||||
ctk_label_set_text(&loadingname, ((struct pnarg *)data)->name);
|
||||
ctk_dialog_open(&loadingdialog);
|
||||
process_post(&program_handler_process, LOADER_EVENT_LOAD, data);
|
||||
displayname = data;
|
||||
} else {
|
||||
/* Try again. */
|
||||
process_post(&program_handler_process, LOADER_EVENT_DISPLAY_NAME, data);
|
||||
/* Try again. */
|
||||
process_post(&program_handler_process, LOADER_EVENT_DISPLAY_NAME, data);
|
||||
}
|
||||
#endif /* WITH_LOADER_ARCH */
|
||||
} else if(ev == LOADER_EVENT_LOAD) {
|
||||
#if WITH_LOADER_ARCH
|
||||
if(displayname == data) {
|
||||
ctk_dialog_close();
|
||||
displayname = NULL;
|
||||
log_message("Loading ", ((struct pnarg *)data)->name);
|
||||
err = LOADER_LOAD(((struct pnarg *)data)->name,
|
||||
((struct pnarg *)data)->arg);
|
||||
if(err != LOADER_OK) {
|
||||
make_windows();
|
||||
errorfilename[0] = '"';
|
||||
strncpy(errorfilename + 1, ((struct pnarg *)data)->name,
|
||||
sizeof(errorfilename) - 2);
|
||||
errorfilename[1 + strlen(((struct pnarg *)data)->name)] = '"';
|
||||
ctk_label_set_text(&errortype, (char *)errormsgs[err]);
|
||||
ctk_dialog_open(&errordialog);
|
||||
log_message((char *)errormsgs[err], errorfilename);
|
||||
}
|
||||
pnarg_free(data);
|
||||
ctk_dialog_close();
|
||||
displayname = NULL;
|
||||
log_message("Loading ", ((struct pnarg *)data)->name);
|
||||
err = LOADER_LOAD(((struct pnarg *)data)->name,
|
||||
((struct pnarg *)data)->arg);
|
||||
if(err != LOADER_OK) {
|
||||
make_windows();
|
||||
errorfilename[0] = '"';
|
||||
strncpy(errorfilename + 1, ((struct pnarg *)data)->name,
|
||||
sizeof(errorfilename) - 2);
|
||||
errorfilename[1 + strlen(((struct pnarg *)data)->name)] = '"';
|
||||
ctk_label_set_text(&errortype, (char *)errormsgs[err]);
|
||||
ctk_dialog_open(&errordialog);
|
||||
log_message((char *)errormsgs[err], errorfilename);
|
||||
}
|
||||
pnarg_free(data);
|
||||
} else {
|
||||
/* Try again. */
|
||||
process_post(&program_handler_process, LOADER_EVENT_DISPLAY_NAME, data);
|
||||
/* Try again. */
|
||||
process_post(&program_handler_process, LOADER_EVENT_DISPLAY_NAME, data);
|
||||
}
|
||||
#endif /* WITH_LOADEER_ARCH */
|
||||
}
|
||||
|
|
|
@ -70,6 +70,15 @@ LIST(restful_periodic_services);
|
|||
void
|
||||
rest_init_engine(void)
|
||||
{
|
||||
/* avoid initializing twice */
|
||||
static uint8_t initialized = 0;
|
||||
|
||||
if(initialized) {
|
||||
PRINTF("REST engine process already running - double initialization?\n");
|
||||
return;
|
||||
}
|
||||
initialized = 1;
|
||||
|
||||
list_init(restful_services);
|
||||
|
||||
REST.set_service_callback(rest_invoke_restful_service);
|
||||
|
@ -124,15 +133,19 @@ rest_invoke_restful_service(void *request, void *response, uint8_t *buffer,
|
|||
|
||||
resource_t *resource = NULL;
|
||||
const char *url = NULL;
|
||||
int url_len, res_url_len;
|
||||
|
||||
url_len = REST.get_url(request, &url);
|
||||
for(resource = (resource_t *)list_head(restful_services);
|
||||
resource; resource = resource->next) {
|
||||
|
||||
/* if the web service handles that kind of requests and urls matches */
|
||||
if((REST.get_url(request, &url) == strlen(resource->url)
|
||||
|| (REST.get_url(request, &url) > strlen(resource->url)
|
||||
&& (resource->flags & HAS_SUB_RESOURCES)))
|
||||
&& strncmp(resource->url, url, strlen(resource->url)) == 0) {
|
||||
res_url_len = strlen(resource->url);
|
||||
if((url_len == res_url_len
|
||||
|| (url_len > res_url_len
|
||||
&& (resource->flags & HAS_SUB_RESOURCES)
|
||||
&& url[res_url_len] == '/'))
|
||||
&& strncmp(resource->url, url, res_url_len) == 0) {
|
||||
found = 1;
|
||||
rest_resource_flags_t method = REST.get_method_type(request);
|
||||
|
||||
|
|
|
@ -332,14 +332,10 @@ static void
|
|||
parse_incoming_packet(const uint8_t *buf, int len)
|
||||
{
|
||||
int numregs;
|
||||
int flags;
|
||||
int i;
|
||||
int bufptr;
|
||||
|
||||
numregs = buf[MSG_NUMREGS_OFFSET];
|
||||
flags = buf[MSG_FLAGS_OFFSET];
|
||||
|
||||
/* printf("parse_incoming_packet Numregs %d flags %d\n", numregs, flags);*/
|
||||
|
||||
bufptr = MSG_ADDRS_OFFSET;
|
||||
for(i = 0; i < numregs; ++i) {
|
||||
|
|
|
@ -50,6 +50,7 @@
|
|||
#define HAVE_ALLOCA 0
|
||||
#else
|
||||
#define HAVE_ALLOCA 1
|
||||
#include <alloca.h>
|
||||
#endif
|
||||
|
||||
#define DEBUG 0
|
||||
|
|
|
@ -71,7 +71,7 @@ PROCESS_THREAD(shell_poke_process, ev, data)
|
|||
PROCESS_EXIT();
|
||||
}
|
||||
|
||||
address = (uint8_t *)(int)shell_strtolong(args, &next);
|
||||
address = (uint8_t *)(uintptr_t)shell_strtolong(args, &next);
|
||||
if(next == args) {
|
||||
shell_output_str(&poke_command, "usage 1", "");
|
||||
PROCESS_EXIT();
|
||||
|
@ -106,7 +106,7 @@ PROCESS_THREAD(shell_peek_process, ev, data)
|
|||
PROCESS_EXIT();
|
||||
}
|
||||
|
||||
address = (uint8_t *)(int)shell_strtolong(args, &next);
|
||||
address = (uint8_t *)(uintptr_t)shell_strtolong(args, &next);
|
||||
if(next == args) {
|
||||
shell_output_str(&peek_command, "usage 1", "");
|
||||
PROCESS_EXIT();
|
||||
|
|
|
@ -128,8 +128,8 @@ memcpy_misaligned(void *dest, const void *source, int len)
|
|||
int i;
|
||||
uint8_t *destptr;
|
||||
const uint8_t *sourceptr;
|
||||
if(((int)dest & 1) == 1 ||
|
||||
((int)source & 1) == 1) {
|
||||
if(((uintptr_t)dest & 1) == 1 ||
|
||||
((uintptr_t)source & 1) == 1) {
|
||||
destptr = dest;
|
||||
sourceptr = source;
|
||||
for(i = 0; i < len; ++i) {
|
||||
|
|
|
@ -129,7 +129,7 @@ PROCESS_THREAD(shell_netcmd_process, ev, data)
|
|||
|
||||
/* Terminate the string with a NUL character. */
|
||||
msg->netcmd[len] = 0;
|
||||
msg->crc = crc16_data(msg->netcmd, len, 0);
|
||||
msg->crc = crc16_data((unsigned char *)msg->netcmd, len, 0);
|
||||
printf("netcmd sending '%s'\n", msg->netcmd);
|
||||
trickle_send(&trickle);
|
||||
}
|
||||
|
@ -157,7 +157,7 @@ recv_trickle(struct trickle_conn *c)
|
|||
msg->netcmd[len] = 0;
|
||||
memcpy(&crc, &msg->crc, sizeof(crc));
|
||||
|
||||
if(crc == crc16_data(msg->netcmd, len, 0)) {
|
||||
if(crc == crc16_data((unsigned char *)msg->netcmd, len, 0)) {
|
||||
/* Start the server process with the incoming command. */
|
||||
process_start(&shell_netcmd_server_process, (void *)msg->netcmd);
|
||||
}
|
||||
|
|
|
@ -133,7 +133,7 @@ PROCESS_THREAD(shell_sendcmd_process, ev, data)
|
|||
|
||||
/* Terminate the string with a NUL character. */
|
||||
msg->sendcmd[len] = 0;
|
||||
msg->crc = crc16_data(msg->sendcmd, len, 0);
|
||||
msg->crc = crc16_data((unsigned char *)msg->sendcmd, len, 0);
|
||||
/* printf("sendcmd sending '%s'\n", msg->sendcmd);*/
|
||||
unicast_send(&uc, &addr);
|
||||
|
||||
|
@ -160,7 +160,7 @@ recv_uc(struct unicast_conn *c, const linkaddr_t *from)
|
|||
msg->sendcmd[len] = 0;
|
||||
memcpy(&crc, &msg->crc, sizeof(crc));
|
||||
|
||||
if(crc == crc16_data(msg->sendcmd, len, 0)) {
|
||||
if(crc == crc16_data((unsigned char *)msg->sendcmd, len, 0)) {
|
||||
/* Start the server process with the incoming command. */
|
||||
process_start(&shell_sendcmd_server_process, (void *)msg->sendcmd);
|
||||
}
|
||||
|
|
|
@ -301,7 +301,7 @@ recv_collect(const linkaddr_t *originator, uint8_t seqno, uint8_t hops)
|
|||
|
||||
/* Copy the collect message header. */
|
||||
memcpy(&collect_msg, packetbuf_dataptr(), sizeof(collect_msg));
|
||||
dataptr = ((struct collect_msg *)packetbuf_dataptr())->data;
|
||||
dataptr = (char *)((struct collect_msg *)packetbuf_dataptr())->data;
|
||||
|
||||
#if TIMESYNCH_CONF_ENABLED
|
||||
latency = timesynch_time() - collect_msg.timestamp;
|
||||
|
@ -321,7 +321,7 @@ recv_collect(const linkaddr_t *originator, uint8_t seqno, uint8_t hops)
|
|||
if(packetbuf_datalen() >= COLLECT_MSG_HDRSIZE) {
|
||||
len = packetbuf_datalen() - COLLECT_MSG_HDRSIZE;
|
||||
|
||||
if(collect_msg.crc == crc16_data(dataptr, len, 0)) {
|
||||
if(collect_msg.crc == crc16_data((unsigned char *)dataptr, len, 0)) {
|
||||
msg.len = 5 + (packetbuf_datalen() - COLLECT_MSG_HDRSIZE) / 2;
|
||||
linkaddr_copy((linkaddr_t *)&msg.originator, originator);
|
||||
msg.seqno = seqno;
|
||||
|
|
|
@ -158,7 +158,6 @@ PROCESS_THREAD(shell_repeat_server_process, ev, data)
|
|||
static char *command;
|
||||
static struct process *started_process;
|
||||
char command_copy[MAX_COMMANDLENGTH];
|
||||
int ret;
|
||||
|
||||
if(ev == shell_event_input) {
|
||||
goto exit;
|
||||
|
@ -172,7 +171,7 @@ PROCESS_THREAD(shell_repeat_server_process, ev, data)
|
|||
data == &shell_repeat_process);
|
||||
{
|
||||
strncpy(command_copy, command, MAX_COMMANDLENGTH);
|
||||
ret = shell_start_command(command_copy, (int)strlen(command_copy),
|
||||
shell_start_command(command_copy, (int)strlen(command_copy),
|
||||
&repeat_command, &started_process);
|
||||
|
||||
if(started_process != NULL &&
|
||||
|
@ -202,11 +201,10 @@ repeat_print_usage(void)
|
|||
/*---------------------------------------------------------------------------*/
|
||||
PROCESS_THREAD(shell_repeat_process, ev, data)
|
||||
{
|
||||
static int reps, period, period_left;
|
||||
static int reps, period;
|
||||
static char command[MAX_COMMANDLENGTH];
|
||||
static struct etimer etimer;
|
||||
static int i;
|
||||
static clock_time_t start_time;
|
||||
const char *args, *next;
|
||||
|
||||
if(ev == shell_event_input) {
|
||||
|
@ -258,7 +256,6 @@ PROCESS_THREAD(shell_repeat_process, ev, data)
|
|||
/* printf("repeats %d period %d command '%s'\n",
|
||||
reps, period, command);*/
|
||||
|
||||
start_time = clock_time();
|
||||
etimer_set(&etimer, CLOCK_SECOND * period);
|
||||
for(i = 0; reps == 0 || i < reps; ++i) {
|
||||
|
||||
|
@ -291,7 +288,6 @@ PROCESS_THREAD(shell_randwait_process, ev, data)
|
|||
static struct etimer etimer;
|
||||
static struct process *started_process;
|
||||
const char *args, *next;
|
||||
int ret;
|
||||
|
||||
/* if(ev == shell_event_input) {
|
||||
struct shell_input *input;
|
||||
|
@ -339,7 +335,7 @@ PROCESS_THREAD(shell_randwait_process, ev, data)
|
|||
/* printf("Starting '%s' child %p (%s)\n", command, randwait_command.child, */
|
||||
/* randwait_command.child == NULL? "null": randwait_command.child->command); */
|
||||
|
||||
ret = shell_start_command(command, (int)strlen(command),
|
||||
shell_start_command(command, (int)strlen(command),
|
||||
randwait_command.child, &started_process);
|
||||
|
||||
if(started_process != NULL &&
|
||||
|
|
|
@ -51,7 +51,7 @@
|
|||
#define SHELL_VARS_RAM_END SHELL_VARS_CONF_RAM_END
|
||||
#else /* SHELL_VARS_CONF_RAM_BEGIN */
|
||||
#define SHELL_VARS_RAM_BEGIN 0
|
||||
#define SHELL_VARS_RAM_END (unsigned int)-1
|
||||
#define SHELL_VARS_RAM_END (uintptr_t)-1
|
||||
#endif /* SHELL_VARS_CONF_RAM_BEGIN */
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
@ -77,8 +77,8 @@ PROCESS_THREAD(shell_vars_process, ev, data)
|
|||
|
||||
for(i = 0; i < symbols_nelts; ++i) {
|
||||
if(symbols[i].name != NULL &&
|
||||
(unsigned int)symbols[i].value >= SHELL_VARS_RAM_BEGIN &&
|
||||
(unsigned int)symbols[i].value <= SHELL_VARS_RAM_END) {
|
||||
(uintptr_t)symbols[i].value >= SHELL_VARS_RAM_BEGIN &&
|
||||
(uintptr_t)symbols[i].value <= SHELL_VARS_RAM_END) {
|
||||
shell_output_str(&vars_command, (char *)symbols[i].name, "");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -222,7 +222,7 @@ static const char *tags[] = {
|
|||
};
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
static unsigned char CC_FASTCALL
|
||||
static unsigned char
|
||||
iswhitespace(char c)
|
||||
{
|
||||
return (c == ISO_space ||
|
||||
|
@ -255,7 +255,7 @@ htmlparser_init(void)
|
|||
#endif /* WWW_CONF_FORMS */
|
||||
}
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
static char CC_FASTCALL
|
||||
static char
|
||||
lowercase(char c)
|
||||
{
|
||||
/* XXX: This is a *brute force* approach to lower-case
|
||||
|
@ -276,7 +276,7 @@ endtagfound(void)
|
|||
s.tagattrparam[s.tagattrparamptr] = 0;
|
||||
}
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
static void CC_FASTCALL
|
||||
static void
|
||||
switch_majorstate(unsigned char newstate)
|
||||
{
|
||||
if(s.majorstate != newstate) {
|
||||
|
@ -286,7 +286,7 @@ switch_majorstate(unsigned char newstate)
|
|||
}
|
||||
}
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
static void CC_FASTCALL
|
||||
static void
|
||||
add_char(unsigned char c)
|
||||
{
|
||||
if(s.wordlen < WWW_CONF_WEBPAGE_WIDTH - 1 && c < 0x80) {
|
||||
|
@ -320,7 +320,7 @@ newline(void)
|
|||
htmlparser_newline();
|
||||
}
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
static unsigned char CC_FASTCALL
|
||||
static unsigned char
|
||||
find_tag(char *tag)
|
||||
{
|
||||
static unsigned char first, last, i, tabi;
|
||||
|
@ -521,7 +521,7 @@ parse_tag(void)
|
|||
}
|
||||
}
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
static uint16_t CC_FASTCALL
|
||||
static uint16_t
|
||||
parse_word(char *data, uint8_t dlen)
|
||||
{
|
||||
static uint8_t i;
|
||||
|
|
|
@ -200,7 +200,7 @@ window_copy(int curptr, const char *data, unsigned char datalen)
|
|||
len = windowend - windowstart;
|
||||
}
|
||||
|
||||
strncpy(windowptr + windowstart, data, len);
|
||||
strncpy((char *)(windowptr + windowstart), data, len);
|
||||
windowstart += len;
|
||||
|
||||
return curptr + datalen;
|
||||
|
@ -217,7 +217,7 @@ senddata(void)
|
|||
windowstart = s.getrequestptr;
|
||||
curptr = 0;
|
||||
windowend = windowstart + uip_mss();
|
||||
windowptr = (char *)uip_appdata - windowstart;
|
||||
windowptr = (unsigned char *)uip_appdata - windowstart;
|
||||
|
||||
curptr = window_copy(curptr, http_get, sizeof(http_get) - 1);
|
||||
curptr = window_copy(curptr, s.file, (unsigned char)strlen(s.file));
|
||||
|
@ -479,6 +479,11 @@ webclient_appcall(void *state)
|
|||
|
||||
if(uip_closed()) {
|
||||
tcp_markconn(uip_conn, NULL);
|
||||
/* Client requested close takes precedence over server initiated close. */
|
||||
if(s.state == WEBCLIENT_STATE_CLOSE) {
|
||||
webclient_closed();
|
||||
return;
|
||||
}
|
||||
switch(s.httpflag) {
|
||||
case HTTPFLAG_HTTPS:
|
||||
/* Send some info to the user. */
|
||||
|
|
|
@ -34,12 +34,14 @@
|
|||
|
||||
#include <string.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "ctk/ctk.h"
|
||||
#include "ctk/ctk-textentry-cmdline.h"
|
||||
#include "contiki-net.h"
|
||||
#include "lib/petsciiconv.h"
|
||||
#include "sys/arg.h"
|
||||
#include "sys/log.h"
|
||||
#if WWW_CONF_WITH_WGET
|
||||
#include "program-handler.h"
|
||||
#endif /* WWW_CONF_WITH_WGET */
|
||||
|
@ -50,13 +52,8 @@
|
|||
|
||||
#include "www.h"
|
||||
|
||||
#if 1
|
||||
#define PRINTF(x)
|
||||
#else
|
||||
#include <stdio.h>
|
||||
#define PRINTF(x) printf x
|
||||
#endif
|
||||
|
||||
/* Explicitly declare itoa as it is non-standard and not necessarily in stdlib.h */
|
||||
char *itoa(int value, char *str, int base);
|
||||
|
||||
/* The array that holds the current URL. */
|
||||
static char url[WWW_CONF_MAX_URLLEN + 1];
|
||||
|
@ -196,7 +193,7 @@ PROCESS(www_process, "Web browser");
|
|||
|
||||
AUTOSTART_PROCESSES(&www_process);
|
||||
|
||||
static void CC_FASTCALL formsubmit(struct inputattrib *trigger);
|
||||
static void formsubmit(struct inputattrib *trigger);
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* make_window()
|
||||
|
@ -232,7 +229,7 @@ redraw_window(void)
|
|||
ctk_window_redraw(&mainwindow);
|
||||
}
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
static char * CC_FASTCALL
|
||||
static char *
|
||||
add_pageattrib(unsigned size)
|
||||
{
|
||||
char *ptr;
|
||||
|
@ -246,7 +243,7 @@ add_pageattrib(unsigned size)
|
|||
}
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
#if WWW_CONF_FORMS
|
||||
static void CC_FASTCALL
|
||||
static void
|
||||
add_forminput(struct inputattrib *inputptr)
|
||||
{
|
||||
inputptr->nextptr = NULL;
|
||||
|
@ -285,13 +282,24 @@ start_loading(void)
|
|||
clear_page();
|
||||
}
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
static void CC_FASTCALL
|
||||
static void
|
||||
show_statustext(char *text)
|
||||
{
|
||||
ctk_label_set_text(&statustext, text);
|
||||
CTK_WIDGET_REDRAW(&statustext);
|
||||
}
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
static void
|
||||
end_page(char *status, void *focus)
|
||||
{
|
||||
show_statustext(status);
|
||||
petsciiconv_topetscii(webpageptr - x, x);
|
||||
CTK_WIDGET_FOCUS(&mainwindow, focus);
|
||||
redraw_window();
|
||||
log_message("Page attribs free: ", itoa(pageattribs + sizeof(pageattribs) - pageattribptr,
|
||||
pageattribs + sizeof(pageattribs) - 5, 10));
|
||||
}
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* open_url():
|
||||
*
|
||||
* Called when the URL present in the global "url" variable should be
|
||||
|
@ -389,7 +397,7 @@ open_url(void)
|
|||
* Will format a link from the current web pages so that it suits the
|
||||
* open_url() function.
|
||||
*/
|
||||
static void CC_FASTCALL
|
||||
static void
|
||||
set_link(char *link)
|
||||
{
|
||||
register char *urlptr;
|
||||
|
@ -609,7 +617,7 @@ PROCESS_THREAD(www_process, ev, data)
|
|||
* "url" variable and the visible "editurl" (which is shown in the URL
|
||||
* text entry widget in the browser window).
|
||||
*/
|
||||
static void CC_FASTCALL
|
||||
static void
|
||||
set_url(char *host, uint16_t port, char *file)
|
||||
{
|
||||
char *urlptr;
|
||||
|
@ -660,10 +668,7 @@ webclient_timedout(void)
|
|||
void
|
||||
webclient_closed(void)
|
||||
{
|
||||
show_statustext("Stopped");
|
||||
petsciiconv_topetscii(webpageptr - x, x);
|
||||
CTK_WIDGET_FOCUS(&mainwindow, &downbutton);
|
||||
redraw_window();
|
||||
end_page("Stopped", &downbutton);
|
||||
}
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* webclient_connected():
|
||||
|
@ -710,6 +715,7 @@ webclient_datahandler(char *data, uint16_t len)
|
|||
" Would you like to download instead?");
|
||||
CTK_WIDGET_ADD(&mainwindow, &wgetnobutton);
|
||||
CTK_WIDGET_ADD(&mainwindow, &wgetyesbutton);
|
||||
CTK_WIDGET_FOCUS(&mainwindow, &wgetyesbutton);
|
||||
redraw_window();
|
||||
#endif /* CTK_CONF_WINDOWS */
|
||||
#endif /* WWW_CONF_WITH_WGET || WWW_CONF_WGET_EXEC */
|
||||
|
@ -721,14 +727,11 @@ webclient_datahandler(char *data, uint16_t len)
|
|||
|
||||
if(data == NULL) {
|
||||
loading = 0;
|
||||
show_statustext("Done");
|
||||
petsciiconv_topetscii(webpageptr - x, x);
|
||||
CTK_WIDGET_FOCUS(&mainwindow, &urlentry);
|
||||
redraw_window();
|
||||
end_page("Done", &urlentry);
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
static void CC_FASTCALL
|
||||
static void
|
||||
add_pagewidget(char *text, unsigned char size, char *attrib, unsigned char type,
|
||||
unsigned char border)
|
||||
{
|
||||
|
@ -842,7 +845,9 @@ add_pagewidget(char *text, unsigned char size, char *attrib, unsigned char type,
|
|||
void
|
||||
htmlparser_newline(void)
|
||||
{
|
||||
#ifdef WITH_PETSCII
|
||||
char *wptr;
|
||||
#endif /* WITH_PETSCII */
|
||||
|
||||
if(++newlines > 2) {
|
||||
return;
|
||||
|
@ -862,8 +867,10 @@ htmlparser_newline(void)
|
|||
++y;
|
||||
x = 0;
|
||||
|
||||
#ifdef WITH_PETSCII
|
||||
wptr = webpageptr - WWW_CONF_WEBPAGE_WIDTH;
|
||||
petsciiconv_topetscii(wptr, WWW_CONF_WEBPAGE_WIDTH);
|
||||
#endif /* WITH_PETSCII */
|
||||
|
||||
if(y == WWW_CONF_WEBPAGE_HEIGHT) {
|
||||
loading = 0;
|
||||
|
@ -935,7 +942,7 @@ htmlparser_inputfield(unsigned char type, unsigned char size, char *text, char *
|
|||
}
|
||||
}
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
static void CC_FASTCALL
|
||||
static void
|
||||
add_query(char delimiter, char *string)
|
||||
{
|
||||
static char *query;
|
||||
|
@ -963,7 +970,7 @@ add_query(char delimiter, char *string)
|
|||
query += length;
|
||||
}
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
static void CC_FASTCALL
|
||||
static void
|
||||
formsubmit(struct inputattrib *trigger)
|
||||
{
|
||||
struct inputattrib *input;
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
<html><head><link rel="stylesheet" type="text/css" href="s.css"></head><body><center>
|
||||
%! tictac
|
||||
<html><head><link rel="stylesheet" type="text/css" href="s.css"></head><body><center>
|
||||
%! tictac
|
||||
</center></body></html>
|
|
@ -1,3 +1,3 @@
|
|||
<html><head><link rel="stylesheet" type="text/css" href="s.css"></head><body><center>
|
||||
%! tictac
|
||||
<html><head><link rel="stylesheet" type="text/css" href="s.css"></head><body><center>
|
||||
%! tictac
|
||||
</center></body></html>
|
|
@ -80,7 +80,7 @@ urlconv_tofilename(char *dest, char *source, unsigned char maxlen)
|
|||
*dest = ISO_slash;
|
||||
strncpy(dest + 1, wwwroot, wwwrootlen);
|
||||
len = 0;
|
||||
from = source; to = dest + wwwrootlen;
|
||||
from = (unsigned char *)source; to = (unsigned char *)dest + wwwrootlen;
|
||||
maxlen -= 2 + wwwrootlen;
|
||||
do {
|
||||
c = *(from++);
|
||||
|
@ -139,7 +139,7 @@ urlconv_tofilename(char *dest, char *source, unsigned char maxlen)
|
|||
}
|
||||
} while(c);
|
||||
if(*to == ISO_slash && (len + sizeof(http_index_htm) - 3) < maxlen) {
|
||||
strcpy(to, http_index_htm); // add index.htm
|
||||
strcpy((char *)to, http_index_htm); // add index.htm
|
||||
} else {
|
||||
++to;
|
||||
*to = 0;
|
||||
|
|
|
@ -192,10 +192,24 @@
|
|||
#define NBR_TABLE_CONF_MAX_NEIGHBORS 8
|
||||
#endif /* NBR_TABLE_CONF_MAX_NEIGHBORS */
|
||||
|
||||
/* UIP_CONF_ND6_SEND_RA enables standard IPv6 Router Advertisement.
|
||||
* We enable it by default when IPv6 is used without RPL. */
|
||||
#ifndef UIP_CONF_ND6_SEND_RA
|
||||
#define UIP_CONF_ND6_SEND_RA (NETSTACK_CONF_WITH_IPV6 && !UIP_CONF_IPV6_RPL)
|
||||
#endif /* UIP_CONF_ND6_SEND_RA */
|
||||
|
||||
/* UIP_CONF_ND6_SEND_NA enables standard IPv6 Neighbor Discovery Protocol.
|
||||
This is unneeded when RPL is used. Disable to save ROM and a little RAM. */
|
||||
We enable it by default when IPv6 is used without RPL.
|
||||
With RPL, the neighbor cache (link-local IPv6 <-> MAC address mapping)
|
||||
is fed whenever receiving DIO and DAO messages. This is always sufficient
|
||||
for RPL routing, i.e. to send to the preferred parent or any child.
|
||||
Link-local unicast to other neighbors may, however, not be possible if
|
||||
we never receive any DIO from them. This may happen if the link from the
|
||||
neighbor to us is weak, if DIO transmissions are suppressed (Trickle
|
||||
timer) or if the neighbor chooses not to transmit DIOs because it is
|
||||
a leaf node or for any reason. */
|
||||
#ifndef UIP_CONF_ND6_SEND_NA
|
||||
#define UIP_CONF_ND6_SEND_NA 1
|
||||
#define UIP_CONF_ND6_SEND_NA (NETSTACK_CONF_WITH_IPV6 && !UIP_CONF_IPV6_RPL)
|
||||
#endif /* UIP_CONF_ND6_SEND_NA */
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
|
|
@ -155,14 +155,14 @@ ctk_filedialog_eventhandler(struct ctk_filedialog_state *s,
|
|||
}
|
||||
return 1;
|
||||
} else if(ev == ctk_signal_keypress) {
|
||||
if((ctk_arch_key_t)data == CH_CURS_UP) {
|
||||
if((char)(size_t)data == CH_CURS_UP) {
|
||||
clearptr();
|
||||
if(fileptr > 0) {
|
||||
--fileptr;
|
||||
}
|
||||
showptr();
|
||||
return 1;
|
||||
} else if((ctk_arch_key_t)data == CH_CURS_DOWN) {
|
||||
} else if((char)(size_t)data == CH_CURS_DOWN) {
|
||||
clearptr();
|
||||
if(fileptr < FILES_HEIGHT - 1) {
|
||||
++fileptr;
|
||||
|
|
|
@ -185,7 +185,7 @@ unsigned short ctk_screensaver_timeout = (5*60);
|
|||
static struct timer timer;
|
||||
#endif /* CTK_CONF_SCREENSAVER */
|
||||
|
||||
static void CC_FASTCALL
|
||||
static void
|
||||
textentry_input(ctk_arch_key_t c,
|
||||
CC_REGISTER_ARG struct ctk_textentry *t);
|
||||
|
||||
|
@ -555,7 +555,7 @@ ctk_menu_remove(struct ctk_menu *menu)
|
|||
* \param clipy2 The lower bound of the clip interval
|
||||
*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void CC_FASTCALL
|
||||
static void
|
||||
do_redraw_all(unsigned char clipy1, unsigned char clipy2)
|
||||
{
|
||||
#if CTK_CONF_WINDOWS
|
||||
|
@ -818,7 +818,7 @@ ctk_menuitem_add(CC_REGISTER_ARG struct ctk_menu *menu, char *name)
|
|||
* \param w The widget that should be redrawn.
|
||||
*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void CC_FASTCALL
|
||||
static void
|
||||
add_redrawwidget(struct ctk_widget *w)
|
||||
{
|
||||
static unsigned char i;
|
||||
|
@ -852,7 +852,9 @@ add_redrawwidget(struct ctk_widget *w)
|
|||
static void
|
||||
widget_redraw(struct ctk_widget *widget)
|
||||
{
|
||||
#if CTK_CONF_WINDOWS
|
||||
struct ctk_window *window;
|
||||
#endif /* CTK_CONF_WINDOWS */
|
||||
|
||||
if(mode != CTK_MODE_NORMAL || widget == NULL) {
|
||||
return;
|
||||
|
@ -870,8 +872,8 @@ widget_redraw(struct ctk_widget *widget)
|
|||
if(menus.open == NULL)
|
||||
#endif /* CTK_CONF_MENUS */
|
||||
{
|
||||
window = widget->window;
|
||||
#if CTK_CONF_WINDOWS
|
||||
window = widget->window;
|
||||
if(window == dialog) {
|
||||
ctk_draw_widget(widget, CTK_FOCUS_DIALOG, 0, height);
|
||||
} else if(dialog == NULL &&
|
||||
|
@ -921,7 +923,7 @@ ctk_widget_redraw(struct ctk_widget *widget)
|
|||
* \param widget The widget to be added.
|
||||
*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void CC_FASTCALL
|
||||
void
|
||||
ctk_widget_add(CC_REGISTER_ARG struct ctk_window *window,
|
||||
CC_REGISTER_ARG struct ctk_widget *widget)
|
||||
{
|
||||
|
@ -973,7 +975,7 @@ ctk_desktop_height(struct ctk_desktop *d)
|
|||
* \param focus The widget to be focused.
|
||||
*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void CC_FASTCALL
|
||||
static void
|
||||
select_widget(struct ctk_widget *focus)
|
||||
{
|
||||
struct ctk_window *window;
|
||||
|
@ -1001,7 +1003,7 @@ select_widget(struct ctk_widget *focus)
|
|||
#define DOWN 1
|
||||
#define LEFT 2
|
||||
#define RIGHT 3
|
||||
static void CC_FASTCALL
|
||||
static void
|
||||
switch_focus_widget(unsigned char direction)
|
||||
{
|
||||
#if CTK_CONF_WINDOWS
|
||||
|
@ -1126,7 +1128,7 @@ switch_menu_item(unsigned char updown)
|
|||
}
|
||||
#endif /* CTK_CONF_MENUS */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static unsigned char CC_FASTCALL
|
||||
static unsigned char
|
||||
activate(CC_REGISTER_ARG struct ctk_widget *w)
|
||||
{
|
||||
if(w->type == CTK_WIDGET_BUTTON) {
|
||||
|
@ -1183,7 +1185,7 @@ ctk_textentry_input_null(ctk_arch_key_t c, struct ctk_textentry *t)
|
|||
}
|
||||
#endif /* SDCC */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void CC_FASTCALL
|
||||
static void
|
||||
textentry_input(ctk_arch_key_t c, CC_REGISTER_ARG struct ctk_textentry *t)
|
||||
{
|
||||
register char *cptr, *cptr2;
|
||||
|
|
|
@ -743,8 +743,8 @@ void ctk_icon_add(struct ctk_widget *icon, struct process *p);
|
|||
*/
|
||||
#define CTK_WIDGET_ADD(win, widg) \
|
||||
ctk_widget_add(win, (struct ctk_widget *)widg)
|
||||
CCIF void CC_FASTCALL ctk_widget_add(struct ctk_window *window,
|
||||
struct ctk_widget *widget);
|
||||
CCIF void ctk_widget_add(struct ctk_window *window,
|
||||
struct ctk_widget *widget);
|
||||
|
||||
/**
|
||||
* Set focus to a widget.
|
||||
|
|
|
@ -150,6 +150,12 @@ enum {
|
|||
/* Received signal strength indicator in dBm. */
|
||||
RADIO_PARAM_RSSI,
|
||||
|
||||
/* RSSI of the last received packet */
|
||||
RADIO_PARAM_LAST_RSSI,
|
||||
|
||||
/* Link quality of the last received packet */
|
||||
RADIO_PARAM_LAST_LINK_QUALITY,
|
||||
|
||||
/*
|
||||
* Long (64 bits) address for the radio, which is used by the address filter.
|
||||
* The address is specified in network byte order.
|
||||
|
@ -159,6 +165,11 @@ enum {
|
|||
*/
|
||||
RADIO_PARAM_64BIT_ADDR,
|
||||
|
||||
/* Last packet timestamp, of type rtimer_clock_t.
|
||||
* Because this parameter value mat be larger than what fits in radio_value_t,
|
||||
* it needs to be used with radio.get_object()/set_object(). */
|
||||
RADIO_PARAM_LAST_PACKET_TIMESTAMP,
|
||||
|
||||
/* Constants (read only) */
|
||||
|
||||
/* The lowest radio channel. */
|
||||
|
@ -192,6 +203,7 @@ enum {
|
|||
*/
|
||||
#define RADIO_RX_MODE_ADDRESS_FILTER (1 << 0)
|
||||
#define RADIO_RX_MODE_AUTOACK (1 << 1)
|
||||
#define RADIO_RX_MODE_POLL_MODE (1 << 2)
|
||||
|
||||
/**
|
||||
* The radio transmission mode controls whether transmissions should
|
||||
|
|
|
@ -293,7 +293,7 @@ PROCESS_THREAD(slip_process, ev, data)
|
|||
tcpip_input();
|
||||
#endif
|
||||
} else {
|
||||
uip_len = 0;
|
||||
uip_clear_buf();
|
||||
SLIP_STATISTICS(slip_ip_drop++);
|
||||
}
|
||||
#else /* NETSTACK_CONF_WITH_IPV6 */
|
||||
|
|
|
@ -71,12 +71,8 @@ static uint8_t round_keys[11][AES_128_KEY_LENGTH];
|
|||
static uint8_t
|
||||
galois_mul2(uint8_t value)
|
||||
{
|
||||
if(value >> 7) {
|
||||
value = value << 1;
|
||||
return value ^ 0x1b;
|
||||
} else {
|
||||
return value << 1;
|
||||
}
|
||||
uint8_t xor_val = (value >> 7) * 0x1b;
|
||||
return ((value << 1) ^ xor_val);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
|
@ -171,17 +167,6 @@ encrypt(uint8_t *state)
|
|||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
aes_128_padded_encrypt(uint8_t *plaintext_and_result, uint8_t plaintext_len)
|
||||
{
|
||||
uint8_t block[AES_128_BLOCK_SIZE];
|
||||
|
||||
memset(block, 0, AES_128_BLOCK_SIZE);
|
||||
memcpy(block, plaintext_and_result, plaintext_len);
|
||||
AES_128.encrypt(block);
|
||||
memcpy(plaintext_and_result, block, plaintext_len);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
aes_128_set_padded_key(uint8_t *key, uint8_t key_len)
|
||||
{
|
||||
uint8_t block[AES_128_BLOCK_SIZE];
|
||||
|
|
|
@ -37,8 +37,8 @@
|
|||
* Konrad Krentz <konrad.krentz@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef AES_H_
|
||||
#define AES_H_
|
||||
#ifndef AES_128_H_
|
||||
#define AES_128_H_
|
||||
|
||||
#include "contiki.h"
|
||||
|
||||
|
@ -67,11 +67,6 @@ struct aes_128_driver {
|
|||
void (* encrypt)(uint8_t *plaintext_and_result);
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Pads the plaintext with zeroes before calling AES_128.encrypt
|
||||
*/
|
||||
void aes_128_padded_encrypt(uint8_t *plaintext_and_result, uint8_t plaintext_len);
|
||||
|
||||
/**
|
||||
* \brief Pads the key with zeroes before calling AES_128.set_key
|
||||
*/
|
||||
|
@ -79,4 +74,4 @@ void aes_128_set_padded_key(uint8_t *key, uint8_t key_len);
|
|||
|
||||
extern const struct aes_128_driver AES_128;
|
||||
|
||||
#endif /* AES_H_ */
|
||||
#endif /* AES_128_H_ */
|
||||
|
|
|
@ -48,14 +48,11 @@
|
|||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
set_nonce(uint8_t *iv,
|
||||
set_iv(uint8_t *iv,
|
||||
uint8_t flags,
|
||||
const uint8_t *nonce,
|
||||
uint8_t counter)
|
||||
{
|
||||
/* 1 byte|| 8 bytes || 4 bytes || 1 byte || 2 bytes */
|
||||
/* flags || extended_source_address || frame_counter || sec_lvl || counter */
|
||||
|
||||
iv[0] = flags;
|
||||
memcpy(iv + 1, nonce, CCM_STAR_NONCE_LENGTH);
|
||||
iv[14] = 0;
|
||||
|
@ -73,7 +70,7 @@ ctr_step(const uint8_t *nonce,
|
|||
uint8_t a[AES_128_BLOCK_SIZE];
|
||||
uint8_t i;
|
||||
|
||||
set_nonce(a, CCM_STAR_ENCRYPTION_FLAGS, nonce, counter);
|
||||
set_iv(a, CCM_STAR_ENCRYPTION_FLAGS, nonce, counter);
|
||||
AES_128.encrypt(a);
|
||||
|
||||
for(i = 0; (pos + i < m_len) && (i < AES_128_BLOCK_SIZE); i++) {
|
||||
|
@ -82,9 +79,9 @@ ctr_step(const uint8_t *nonce,
|
|||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
mic(const uint8_t *m, uint8_t m_len,
|
||||
const uint8_t *nonce,
|
||||
const uint8_t *a, uint8_t a_len,
|
||||
mic(const uint8_t *nonce,
|
||||
const uint8_t *m, uint8_t m_len,
|
||||
const uint8_t *a, uint8_t a_len,
|
||||
uint8_t *result,
|
||||
uint8_t mic_len)
|
||||
{
|
||||
|
@ -92,10 +89,10 @@ mic(const uint8_t *m, uint8_t m_len,
|
|||
uint8_t pos;
|
||||
uint8_t i;
|
||||
|
||||
set_nonce(x, CCM_STAR_AUTH_FLAGS(a_len, mic_len), nonce, m_len);
|
||||
set_iv(x, CCM_STAR_AUTH_FLAGS(a_len, mic_len), nonce, m_len);
|
||||
AES_128.encrypt(x);
|
||||
|
||||
if(a_len > 0) {
|
||||
if(a_len) {
|
||||
x[1] = x[1] ^ a_len;
|
||||
for(i = 2; (i - 2 < a_len) && (i < AES_128_BLOCK_SIZE); i++) {
|
||||
x[i] ^= a[i - 2];
|
||||
|
@ -113,8 +110,7 @@ mic(const uint8_t *m, uint8_t m_len,
|
|||
}
|
||||
}
|
||||
|
||||
if(m_len > 0) {
|
||||
m = a + a_len;
|
||||
if(m_len) {
|
||||
pos = 0;
|
||||
while(pos < m_len) {
|
||||
for(i = 0; (pos + i < m_len) && (i < AES_128_BLOCK_SIZE); i++) {
|
||||
|
@ -131,7 +127,7 @@ mic(const uint8_t *m, uint8_t m_len,
|
|||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
ctr(uint8_t *m, uint8_t m_len, const uint8_t* nonce)
|
||||
ctr(const uint8_t *nonce, uint8_t *m, uint8_t m_len)
|
||||
{
|
||||
uint8_t pos;
|
||||
uint8_t counter;
|
||||
|
@ -144,13 +140,38 @@ ctr(uint8_t *m, uint8_t m_len, const uint8_t* nonce)
|
|||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void set_key(const uint8_t *key) {
|
||||
AES_128.set_key((uint8_t*)key);
|
||||
static void
|
||||
set_key(const uint8_t *key)
|
||||
{
|
||||
AES_128.set_key(key);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
aead(const uint8_t* nonce,
|
||||
uint8_t* m, uint8_t m_len,
|
||||
const uint8_t* a, uint8_t a_len,
|
||||
uint8_t *result, uint8_t mic_len,
|
||||
int forward)
|
||||
{
|
||||
if(!forward) {
|
||||
/* decrypt */
|
||||
ctr(nonce, m, m_len);
|
||||
}
|
||||
|
||||
mic(nonce,
|
||||
m, m_len,
|
||||
a, a_len,
|
||||
result,
|
||||
mic_len);
|
||||
|
||||
if(forward) {
|
||||
/* encrypt */
|
||||
ctr(nonce, m, m_len);
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
const struct ccm_star_driver ccm_star_driver = {
|
||||
mic,
|
||||
ctr,
|
||||
set_key
|
||||
set_key,
|
||||
aead
|
||||
};
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
|
|
@ -55,34 +55,26 @@
|
|||
*/
|
||||
struct ccm_star_driver {
|
||||
|
||||
/**
|
||||
* \brief Generates a MIC over the data supplied.
|
||||
* \param data The data buffer to read.
|
||||
* \param data_length The data buffer length.
|
||||
* \param nonce The nonce to use. CCM_STAR_NONCE_LENGTH bytes long.
|
||||
* \param result The generated MIC will be put here
|
||||
* \param mic_len The size of the MIC to be generated. <= 16.
|
||||
*/
|
||||
void (* mic)(const uint8_t* data, uint8_t data_length,
|
||||
const uint8_t* nonce,
|
||||
const uint8_t* add, uint8_t add_len,
|
||||
uint8_t *result,
|
||||
uint8_t mic_len);
|
||||
|
||||
/**
|
||||
* \brief XORs the frame in the packetbuf with the key stream.
|
||||
* \param data The data buffer to read.
|
||||
* \param data_length The data buffer length.
|
||||
* \param nonce The nonce to use. CCM_STAR_NONCE_LENGTH bytes long.
|
||||
*/
|
||||
void (* ctr)( uint8_t* data, uint8_t data_length,
|
||||
const uint8_t* nonce);
|
||||
|
||||
/**
|
||||
* \brief Sets the key in use. Default implementation calls AES_128.set_key()
|
||||
* \param key The key to use.
|
||||
* \brief Sets the key in use. Default implementation calls AES_128.set_key().
|
||||
* \param key The key to use.
|
||||
*/
|
||||
void (* set_key)(const uint8_t* key);
|
||||
|
||||
/**
|
||||
* \brief Combines authentication and encryption.
|
||||
* \param nonce The nonce to use. CCM_STAR_NONCE_LENGTH bytes long.
|
||||
* \param m message to encrypt or decrypt
|
||||
* \param a Additional authenticated data
|
||||
* \param result The generated MIC will be put here
|
||||
* \param mic_len The size of the MIC to be generated. <= 16.
|
||||
* \param forward != 0 if used in forward direction.
|
||||
*/
|
||||
void (* aead)(const uint8_t* nonce,
|
||||
uint8_t* m, uint8_t m_len,
|
||||
const uint8_t* a, uint8_t a_len,
|
||||
uint8_t *result, uint8_t mic_len,
|
||||
int forward);
|
||||
};
|
||||
|
||||
extern const struct ccm_star_driver CCM_STAR;
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
*/
|
||||
|
||||
#include "lib/ringbuf.h"
|
||||
#include <sys/cc.h>
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
ringbuf_init(struct ringbuf *r, uint8_t *dataptr, uint8_t size)
|
||||
|
@ -63,8 +64,15 @@ ringbuf_put(struct ringbuf *r, uint8_t c)
|
|||
if(((r->put_ptr - r->get_ptr) & r->mask) == r->mask) {
|
||||
return 0;
|
||||
}
|
||||
r->data[r->put_ptr] = c;
|
||||
r->put_ptr = (r->put_ptr + 1) & r->mask;
|
||||
/*
|
||||
* CC_ACCESS_NOW is used because the compiler is allowed to reorder
|
||||
* the access to non-volatile variables.
|
||||
* In this case a reader might read from the moved index/ptr before
|
||||
* its value (c) is written. Reordering makes little sense, but
|
||||
* better safe than sorry.
|
||||
*/
|
||||
CC_ACCESS_NOW(uint8_t, r->data[r->put_ptr]) = c;
|
||||
CC_ACCESS_NOW(uint8_t, r->put_ptr) = (r->put_ptr + 1) & r->mask;
|
||||
return 1;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
@ -84,8 +92,17 @@ ringbuf_get(struct ringbuf *r)
|
|||
most platforms, but C does not guarantee this.
|
||||
*/
|
||||
if(((r->put_ptr - r->get_ptr) & r->mask) > 0) {
|
||||
c = r->data[r->get_ptr];
|
||||
r->get_ptr = (r->get_ptr + 1) & r->mask;
|
||||
/*
|
||||
* CC_ACCESS_NOW is used because the compiler is allowed to reorder
|
||||
* the access to non-volatile variables.
|
||||
* In this case the memory might be freed and overwritten by
|
||||
* increasing get_ptr before the value was copied to c.
|
||||
* Opposed to the put-operation this would even make sense,
|
||||
* because the register used for mask can be reused to save c
|
||||
* (on some architectures).
|
||||
*/
|
||||
c = CC_ACCESS_NOW(uint8_t, r->data[r->get_ptr]);
|
||||
CC_ACCESS_NOW(uint8_t, r->get_ptr) = (r->get_ptr + 1) & r->mask;
|
||||
return c;
|
||||
} else {
|
||||
return -1;
|
||||
|
|
149
core/lib/ringbufindex.c
Normal file
149
core/lib/ringbufindex.c
Normal file
|
@ -0,0 +1,149 @@
|
|||
/*
|
||||
* Copyright (c) 2015, SICS Swedish ICT.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the Institute nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the Contiki operating system.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
* ringbufindex library. Implements basic support for ring buffers
|
||||
* of any type, as opposed to the core/lib/ringbuf module which
|
||||
* is only for byte arrays. Simply returns index in the ringbuf
|
||||
* rather than actual elements. The ringbuf size must be power of two.
|
||||
* Like the original ringbuf, this module implements atomic put and get.
|
||||
* \author
|
||||
* Simon Duquennoy <simonduq@sics.se>
|
||||
* based on Contiki's core/lib/ringbuf library by Adam Dunkels
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "lib/ringbufindex.h"
|
||||
|
||||
/* Initialize a ring buffer. The size must be a power of two */
|
||||
void
|
||||
ringbufindex_init(struct ringbufindex *r, uint8_t size)
|
||||
{
|
||||
r->mask = size - 1;
|
||||
r->put_ptr = 0;
|
||||
r->get_ptr = 0;
|
||||
}
|
||||
/* Put one element to the ring buffer */
|
||||
int
|
||||
ringbufindex_put(struct ringbufindex *r)
|
||||
{
|
||||
/* Check if buffer is full. If it is full, return 0 to indicate that
|
||||
the element was not inserted.
|
||||
|
||||
XXX: there is a potential risk for a race condition here, because
|
||||
the ->get_ptr field may be written concurrently by the
|
||||
ringbufindex_get() function. To avoid this, access to ->get_ptr must
|
||||
be atomic. We use an uint8_t type, which makes access atomic on
|
||||
most platforms, but C does not guarantee this.
|
||||
*/
|
||||
if(((r->put_ptr - r->get_ptr) & r->mask) == r->mask) {
|
||||
return 0;
|
||||
}
|
||||
r->put_ptr = (r->put_ptr + 1) & r->mask;
|
||||
return 1;
|
||||
}
|
||||
/* Check if there is space to put an element.
|
||||
* Return the index where the next element is to be added */
|
||||
int
|
||||
ringbufindex_peek_put(const struct ringbufindex *r)
|
||||
{
|
||||
/* Check if there are bytes in the buffer. If so, we return the
|
||||
first one. If there are no bytes left, we return -1.
|
||||
*/
|
||||
if(((r->put_ptr - r->get_ptr) & r->mask) == r->mask) {
|
||||
return -1;
|
||||
}
|
||||
return (r->put_ptr + 1) & r->mask;
|
||||
}
|
||||
/* Remove the first element and return its index */
|
||||
int
|
||||
ringbufindex_get(struct ringbufindex *r)
|
||||
{
|
||||
int get_ptr;
|
||||
|
||||
/* Check if there are bytes in the buffer. If so, we return the
|
||||
first one and increase the pointer. If there are no bytes left, we
|
||||
return -1.
|
||||
|
||||
XXX: there is a potential risk for a race condition here, because
|
||||
the ->put_ptr field may be written concurrently by the
|
||||
ringbufindex_put() function. To avoid this, access to ->get_ptr must
|
||||
be atomic. We use an uint8_t type, which makes access atomic on
|
||||
most platforms, but C does not guarantee this.
|
||||
*/
|
||||
if(((r->put_ptr - r->get_ptr) & r->mask) > 0) {
|
||||
get_ptr = r->get_ptr;
|
||||
r->get_ptr = (r->get_ptr + 1) & r->mask;
|
||||
return get_ptr;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
/* Return the index of the first element
|
||||
* (which will be removed if calling ringbufindex_peek) */
|
||||
int
|
||||
ringbufindex_peek_get(const struct ringbufindex *r)
|
||||
{
|
||||
/* Check if there are bytes in the buffer. If so, we return the
|
||||
first one. If there are no bytes left, we return -1.
|
||||
*/
|
||||
if(((r->put_ptr - r->get_ptr) & r->mask) > 0) {
|
||||
return (r->get_ptr + 1) & r->mask;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
/* Return the ring buffer size */
|
||||
int
|
||||
ringbufindex_size(const struct ringbufindex *r)
|
||||
{
|
||||
return r->mask + 1;
|
||||
}
|
||||
/* Return the number of elements currently in the ring buffer */
|
||||
int
|
||||
ringbufindex_elements(const struct ringbufindex *r)
|
||||
{
|
||||
return (r->put_ptr - r->get_ptr) & r->mask;
|
||||
}
|
||||
/* Is the ring buffer full? */
|
||||
int
|
||||
ringbufindex_full(const struct ringbufindex *r)
|
||||
{
|
||||
return ((r->put_ptr - r->get_ptr) & r->mask) == r->mask;
|
||||
}
|
||||
/* Is the ring buffer empty? */
|
||||
int
|
||||
ringbufindex_empty(const struct ringbufindex *r)
|
||||
{
|
||||
return ringbufindex_elements(r) == 0;
|
||||
}
|
72
core/lib/ringbufindex.h
Normal file
72
core/lib/ringbufindex.h
Normal file
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* Copyright (c) 2015, SICS Swedish ICT.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the Institute nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the Contiki operating system.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
* Header file for the ringbufindex library
|
||||
* \author
|
||||
* Simon Duquennoy <simonduq@sics.se>
|
||||
*/
|
||||
|
||||
#ifndef __RINGBUFINDEX_H__
|
||||
#define __RINGBUFINDEX_H__
|
||||
|
||||
#include "contiki-conf.h"
|
||||
|
||||
struct ringbufindex {
|
||||
uint8_t mask;
|
||||
/* These must be 8-bit quantities to avoid race conditions. */
|
||||
uint8_t put_ptr, get_ptr;
|
||||
};
|
||||
|
||||
/* Initialize a ring buffer. The size must be a power of two */
|
||||
void ringbufindex_init(struct ringbufindex *r, uint8_t size);
|
||||
/* Put one element to the ring buffer */
|
||||
int ringbufindex_put(struct ringbufindex *r);
|
||||
/* Check if there is space to put an element.
|
||||
* Return the index where the next element is to be added */
|
||||
int ringbufindex_peek_put(const struct ringbufindex *r);
|
||||
/* Remove the first element and return its index */
|
||||
int ringbufindex_get(struct ringbufindex *r);
|
||||
/* Return the index of the first element
|
||||
* (which will be removed if calling ringbufindex_peek) */
|
||||
int ringbufindex_peek_get(const struct ringbufindex *r);
|
||||
/* Return the ring buffer size */
|
||||
int ringbufindex_size(const struct ringbufindex *r);
|
||||
/* Return the number of elements currently in the ring buffer */
|
||||
int ringbufindex_elements(const struct ringbufindex *r);
|
||||
/* Is the ring buffer full? */
|
||||
int ringbufindex_full(const struct ringbufindex *r);
|
||||
/* Is the ring buffer empty? */
|
||||
int ringbufindex_empty(const struct ringbufindex *r);
|
||||
|
||||
#endif /* __RINGBUFINDEX_H__ */
|
810
core/loader/elfloader-msp430x.c
Normal file
810
core/loader/elfloader-msp430x.c
Normal file
|
@ -0,0 +1,810 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Indian Institute of Science
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the Institute nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the Contiki operating system.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
* MSP430x elfloader.
|
||||
* \author
|
||||
* Sumankumar Panchal <suman@ece.iisc.ernet.in>
|
||||
*
|
||||
*/
|
||||
|
||||
#include "contiki.h"
|
||||
#include "loader/elfloader.h"
|
||||
#include "loader/elfloader-arch.h"
|
||||
#include "cfs/cfs.h"
|
||||
#include "loader/symtab.h"
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include "dev/flash.h"
|
||||
|
||||
#define DEBUG 0
|
||||
#if DEBUG
|
||||
#include <stdio.h>
|
||||
#define PRINTF(...) printf(__VA_ARGS__)
|
||||
#else
|
||||
#define PRINTF(...) do {} while(0)
|
||||
#endif
|
||||
|
||||
#define EI_NIDENT 16
|
||||
|
||||
struct elf32_ehdr {
|
||||
unsigned char e_ident[EI_NIDENT]; /* ident bytes */
|
||||
elf32_half e_type; /* file type */
|
||||
elf32_half e_machine; /* target machine */
|
||||
elf32_word e_version; /* file version */
|
||||
elf32_addr e_entry; /* start address */
|
||||
elf32_off e_phoff; /* phdr file offset */
|
||||
elf32_off e_shoff; /* shdr file offset */
|
||||
elf32_word e_flags; /* file flags */
|
||||
elf32_half e_ehsize; /* sizeof ehdr */
|
||||
elf32_half e_phentsize; /* sizeof phdr */
|
||||
elf32_half e_phnum; /* number phdrs */
|
||||
elf32_half e_shentsize; /* sizeof shdr */
|
||||
elf32_half e_shnum; /* number shdrs */
|
||||
elf32_half e_shstrndx; /* shdr string index */
|
||||
};
|
||||
|
||||
/* Values for e_type. */
|
||||
#define ET_NONE 0 /* Unknown type. */
|
||||
#define ET_REL 1 /* Relocatable. */
|
||||
#define ET_EXEC 2 /* Executable. */
|
||||
#define ET_DYN 3 /* Shared object. */
|
||||
#define ET_CORE 4 /* Core file. */
|
||||
|
||||
struct elf32_shdr {
|
||||
elf32_word sh_name; /* section name */
|
||||
elf32_word sh_type; /* SHT_... */
|
||||
elf32_word sh_flags; /* SHF_... */
|
||||
elf32_addr sh_addr; /* virtual address */
|
||||
elf32_off sh_offset; /* file offset */
|
||||
elf32_word sh_size; /* section size */
|
||||
elf32_word sh_link; /* misc info */
|
||||
elf32_word sh_info; /* misc info */
|
||||
elf32_word sh_addralign; /* memory alignment */
|
||||
elf32_word sh_entsize; /* entry size if table */
|
||||
};
|
||||
|
||||
/* sh_type */
|
||||
#define SHT_NULL 0 /* inactive */
|
||||
#define SHT_PROGBITS 1 /* program defined information */
|
||||
#define SHT_SYMTAB 2 /* symbol table section */
|
||||
#define SHT_STRTAB 3 /* string table section */
|
||||
#define SHT_RELA 4 /* relocation section with addends*/
|
||||
#define SHT_HASH 5 /* symbol hash table section */
|
||||
#define SHT_DYNAMIC 6 /* dynamic section */
|
||||
#define SHT_NOTE 7 /* note section */
|
||||
#define SHT_NOBITS 8 /* no space section */
|
||||
#define SHT_REL 9 /* relation section without addends */
|
||||
#define SHT_SHLIB 10 /* reserved - purpose unknown */
|
||||
#define SHT_DYNSYM 11 /* dynamic symbol table section */
|
||||
#define SHT_LOPROC 0x70000000 /* reserved range for processor */
|
||||
#define SHT_HIPROC 0x7fffffff /* specific section header types */
|
||||
#define SHT_LOUSER 0x80000000 /* reserved range for application */
|
||||
#define SHT_HIUSER 0xffffffff /* specific indexes */
|
||||
|
||||
struct elf32_rel {
|
||||
elf32_addr r_offset; /* Location to be relocated. */
|
||||
elf32_word r_info; /* Relocation type and symbol index. */
|
||||
};
|
||||
|
||||
struct elf32_sym {
|
||||
elf32_word st_name; /* String table index of name. */
|
||||
elf32_addr st_value; /* Symbol value. */
|
||||
elf32_word st_size; /* Size of associated object. */
|
||||
unsigned char st_info; /* Type and binding information. */
|
||||
unsigned char st_other; /* Reserved (not used). */
|
||||
elf32_half st_shndx; /* Section index of symbol. */
|
||||
};
|
||||
|
||||
#define ELF32_R_SYM(info) ((info) >> 8)
|
||||
|
||||
struct relevant_section {
|
||||
unsigned char number;
|
||||
unsigned int offset;
|
||||
char *address;
|
||||
};
|
||||
|
||||
char elfloader_unknown[30]; /* Name that caused link error. */
|
||||
|
||||
struct process *const *elfloader_autostart_processes;
|
||||
|
||||
static struct relevant_section bss, data, rodata, rodatafar, text, textfar;
|
||||
|
||||
static const unsigned char elf_magic_header[] =
|
||||
{ 0x7f, 0x45, 0x4c, 0x46, /* 0x7f, 'E', 'L', 'F' */
|
||||
0x01, /* Only 32-bit objects. */
|
||||
0x01, /* Only LSB data. */
|
||||
0x01, /* Only ELF version 1. */
|
||||
};
|
||||
|
||||
/* relocation type */
|
||||
#define R_MSP430_NONE 0
|
||||
#define R_MSP430_32 1
|
||||
#define R_MSP430_10_PCREL 2
|
||||
#define R_MSP430_16 3
|
||||
#define R_MSP430_16_PCREL 4
|
||||
#define R_MSP430_16_BYTE 5
|
||||
#define R_MSP430_16_PCREL_BYTE 6
|
||||
#define R_MSP430_2X_PCREL 7
|
||||
#define R_MSP430_RL_PCREL 8
|
||||
#define R_MSP430X_SRC_BYTE 9
|
||||
#define R_MSP430X_SRC 10
|
||||
#define R_MSP430X_DST_BYTE 11
|
||||
#define R_MSP430X_DST 12
|
||||
#define R_MSP430X_DST_2ND_BYTE 13
|
||||
#define R_MSP430X_DST_2ND 14
|
||||
#define R_MSP430X_PCREL_SRC_BYTE 15
|
||||
#define R_MSP430X_PCREL_SRC 16
|
||||
#define R_MSP430X_PCREL_DST_BYTE 17
|
||||
#define R_MSP430X_PCREL_DST 18
|
||||
#define R_MSP430X_PCREL_DST_2ND 19
|
||||
#define R_MSP430X_PCREL_DST_2ND_BYTE 20
|
||||
#define R_MSP430X_S_BYTE 21
|
||||
#define R_MSP430X_S 22
|
||||
#define R_MSP430X_D_BYTE 23
|
||||
#define R_MSP430X_D 24
|
||||
#define R_MSP430X_PCREL_D 25
|
||||
#define R_MSP430X_INDXD 26
|
||||
#define R_MSP430X_PCREL_INDXD 27
|
||||
#define R_MSP430_10 28
|
||||
|
||||
#define ELF32_R_TYPE(info) ((unsigned char)(info))
|
||||
|
||||
static uint16_t datamemory_aligned[ELFLOADER_DATAMEMORY_SIZE / 2 + 1];
|
||||
static uint8_t *datamemory = (uint8_t *)datamemory_aligned;
|
||||
#if ELFLOADER_CONF_TEXT_IN_ROM
|
||||
static const char textmemory[ELFLOADER_TEXTMEMORY_SIZE] = { 0 };
|
||||
#else /* ELFLOADER_CONF_TEXT_IN_ROM */
|
||||
static char textmemory[ELFLOADER_TEXTMEMORY_SIZE];
|
||||
#endif /* ELFLOADER_CONF_TEXT_IN_ROM */
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
seek_read(int fd, unsigned int offset, char *buf, int len)
|
||||
{
|
||||
cfs_seek(fd, offset, CFS_SEEK_SET);
|
||||
cfs_read(fd, buf, len);
|
||||
#if DEBUG
|
||||
{
|
||||
int i;
|
||||
PRINTF("seek_read: Read len %d from offset %d\n",
|
||||
len, offset);
|
||||
for(i = 0; i < len; ++i) {
|
||||
PRINTF("%02x ", buf[i]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
#endif /* DEBUG */
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void *
|
||||
find_local_symbol(int fd, const char *symbol,
|
||||
unsigned int symtab, unsigned short symtabsize,
|
||||
unsigned int strtab)
|
||||
{
|
||||
struct elf32_sym s;
|
||||
unsigned int a;
|
||||
char name[30];
|
||||
struct relevant_section *sect;
|
||||
|
||||
for(a = symtab; a < symtab + symtabsize; a += sizeof(s)) {
|
||||
seek_read(fd, a, (char *)&s, sizeof(s));
|
||||
if(s.st_name != 0) {
|
||||
seek_read(fd, strtab + s.st_name, name, sizeof(name));
|
||||
if(strcmp(name, symbol) == 0) {
|
||||
if(s.st_shndx == bss.number) {
|
||||
sect = &bss;
|
||||
} else if(s.st_shndx == data.number) {
|
||||
sect = &data;
|
||||
} else if(s.st_shndx == rodatafar.number) {
|
||||
sect = &rodatafar;
|
||||
} else if(s.st_shndx == textfar.number) {
|
||||
sect = &textfar;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
return &(sect->address[s.st_value]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static int
|
||||
relocate_section(int fd,
|
||||
unsigned int section, unsigned short size,
|
||||
unsigned int sectionaddr,
|
||||
char *sectionbase,
|
||||
unsigned int strs,
|
||||
unsigned int strtab,
|
||||
unsigned int symtab, unsigned short symtabsize,
|
||||
unsigned char using_relas)
|
||||
{
|
||||
/*
|
||||
* sectionbase added; runtime start address of current section
|
||||
*/
|
||||
struct elf32_rela rela; /* Now used both for rel and rela data! */
|
||||
int rel_size = 0;
|
||||
struct elf32_sym s;
|
||||
unsigned int a;
|
||||
char name[30];
|
||||
char *addr;
|
||||
struct relevant_section *sect;
|
||||
|
||||
/* determine correct relocation entry sizes */
|
||||
if(using_relas) {
|
||||
rel_size = sizeof(struct elf32_rela);
|
||||
} else {
|
||||
rel_size = sizeof(struct elf32_rel);
|
||||
}
|
||||
|
||||
for(a = section; a < section + size; a += rel_size) {
|
||||
seek_read(fd, a, (char *)&rela, rel_size);
|
||||
seek_read(fd,
|
||||
symtab + sizeof(struct elf32_sym) * ELF32_R_SYM(rela.r_info),
|
||||
(char *)&s, sizeof(s));
|
||||
if(s.st_name != 0) {
|
||||
seek_read(fd, strtab + s.st_name, name, sizeof(name));
|
||||
PRINTF("name: %s\n", name);
|
||||
addr = (char *)symtab_lookup(name);
|
||||
if(addr == NULL) {
|
||||
PRINTF("name not found in global: %s\n", name);
|
||||
addr = find_local_symbol(fd, name, symtab, symtabsize, strtab);
|
||||
PRINTF("found address %p\n", addr);
|
||||
}
|
||||
if(addr == NULL) {
|
||||
if(s.st_shndx == bss.number) {
|
||||
sect = &bss;
|
||||
} else if(s.st_shndx == data.number) {
|
||||
sect = &data;
|
||||
} else if(s.st_shndx == rodatafar.number) {
|
||||
sect = &rodatafar;
|
||||
} else if(s.st_shndx == textfar.number) {
|
||||
sect = &textfar;
|
||||
} else {
|
||||
PRINTF("elfloader unknown name: '%30s'\n", name);
|
||||
memcpy(elfloader_unknown, name, sizeof(elfloader_unknown));
|
||||
elfloader_unknown[sizeof(elfloader_unknown) - 1] = 0;
|
||||
return ELFLOADER_SYMBOL_NOT_FOUND;
|
||||
}
|
||||
|
||||
addr = sect->address;
|
||||
}
|
||||
} else {
|
||||
if(s.st_shndx == bss.number) {
|
||||
sect = &bss;
|
||||
} else if(s.st_shndx == data.number) {
|
||||
sect = &data;
|
||||
} else if(s.st_shndx == rodatafar.number) {
|
||||
sect = &rodatafar;
|
||||
} else if(s.st_shndx == textfar.number) {
|
||||
sect = &textfar;
|
||||
} else {
|
||||
return ELFLOADER_SEGMENT_NOT_FOUND;
|
||||
}
|
||||
|
||||
addr = sect->address;
|
||||
}
|
||||
|
||||
if(!using_relas) {
|
||||
/* copy addend to rela structure */
|
||||
seek_read(fd, sectionaddr + rela.r_offset, (char *)&rela.r_addend, 4);
|
||||
}
|
||||
|
||||
elfloader_arch_relocate(fd, sectionaddr, sectionbase, &rela, addr);
|
||||
}
|
||||
|
||||
return ELFLOADER_OK;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void *
|
||||
find_program_processes(int fd,
|
||||
unsigned int symtab, unsigned short size,
|
||||
unsigned int strtab)
|
||||
{
|
||||
struct elf32_sym s;
|
||||
unsigned int a;
|
||||
char name[30];
|
||||
|
||||
for(a = symtab; a < symtab + size; a += sizeof(s)) {
|
||||
seek_read(fd, a, (char *)&s, sizeof(s));
|
||||
|
||||
if(s.st_name != 0) {
|
||||
seek_read(fd, strtab + s.st_name, name, sizeof(name));
|
||||
if(strcmp(name, "autostart_processes") == 0) {
|
||||
return &data.address[s.st_value];
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
elfloader_init(void)
|
||||
{
|
||||
elfloader_autostart_processes = NULL;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
int
|
||||
elfloader_load(int fd)
|
||||
{
|
||||
struct elf32_ehdr ehdr;
|
||||
struct elf32_shdr shdr;
|
||||
struct elf32_shdr strtable;
|
||||
unsigned int strs;
|
||||
unsigned int shdrptr;
|
||||
unsigned int nameptr;
|
||||
char name[17];
|
||||
|
||||
int i;
|
||||
unsigned short shdrnum, shdrsize;
|
||||
|
||||
unsigned char using_relas = -1;
|
||||
unsigned short textoff = 0, textfaroff = 0, textsize, textfarsize,
|
||||
textrelaoff = 0, textrelasize, textfarrelaoff = 0, textfarrelasize;
|
||||
unsigned short dataoff = 0, datasize, datarelaoff = 0, datarelasize;
|
||||
unsigned short rodataoff = 0, rodatafaroff = 0, rodatasize, rodatafarsize,
|
||||
rodatarelaoff = 0, rodatarelasize, rodatafarrelaoff = 0,
|
||||
rodatafarrelasize;
|
||||
unsigned short symtaboff = 0, symtabsize;
|
||||
unsigned short strtaboff = 0, strtabsize;
|
||||
unsigned short bsssize = 0;
|
||||
|
||||
struct process **process;
|
||||
int ret;
|
||||
|
||||
elfloader_unknown[0] = 0;
|
||||
|
||||
/* The ELF header is located at the start of the buffer. */
|
||||
seek_read(fd, 0, (char *)&ehdr, sizeof(ehdr));
|
||||
|
||||
/* Make sure that we have a correct and compatible ELF header. */
|
||||
if(memcmp(ehdr.e_ident, elf_magic_header, sizeof(elf_magic_header)) != 0) {
|
||||
PRINTF("ELF header problems\n");
|
||||
return ELFLOADER_BAD_ELF_HEADER;
|
||||
}
|
||||
|
||||
/* Grab the section header. */
|
||||
shdrptr = ehdr.e_shoff;
|
||||
seek_read(fd, shdrptr, (char *)&shdr, sizeof(shdr));
|
||||
|
||||
/* Get the size and number of entries of the section header. */
|
||||
shdrsize = ehdr.e_shentsize;
|
||||
shdrnum = ehdr.e_shnum;
|
||||
|
||||
PRINTF("Section header: size %d num %d\n", shdrsize, shdrnum);
|
||||
|
||||
/* The string table section: holds the names of the sections. */
|
||||
seek_read(fd, ehdr.e_shoff + shdrsize * ehdr.e_shstrndx,
|
||||
(char *)&strtable, sizeof(strtable));
|
||||
|
||||
/*
|
||||
* Get a pointer to the actual table of strings. This table holds
|
||||
* the names of the sections, not the names of other symbols in the
|
||||
* file (these are in the sybtam section).
|
||||
*/
|
||||
strs = strtable.sh_offset;
|
||||
|
||||
PRINTF("Strtable offset %d\n", strs);
|
||||
|
||||
/*
|
||||
* Go through all sections and pick out the relevant ones. The
|
||||
* ".text" and ".far.text" segments holds the actual code from
|
||||
* the ELF file. The ".data" segment contains initialized data.
|
||||
* The ".bss" segment holds the size of the unitialized data segment.
|
||||
* The ".rodata" and ".far.rodata" segments contains constant data.
|
||||
* The ".rela[a].text" and ".rela[a].far.text" segments contains
|
||||
* relocation information for the contents of the ".text" and
|
||||
* ".far.text" segments, respectively. The ".rela[a].rodata" and
|
||||
* ".rela[a].far.rodata" segments contains relocation information
|
||||
* for the contents of the ".rodata" and ".far.rodata" segments,
|
||||
* respectively. The ".rela[a].data" segment contains relocation
|
||||
* information for the contents of the ".data" segment. The ".symtab"
|
||||
* segment contains the symbol table for this file. The ".strtab"
|
||||
* segment points to the actual string names used by the symbol table.
|
||||
*
|
||||
* In addition to grabbing pointers to the relevant sections, we
|
||||
* also save the section number for resolving addresses in the
|
||||
* relocator code.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Initialize the segment sizes to zero so that we can check if
|
||||
* their sections was found in the file or not.
|
||||
*/
|
||||
textsize = textfarsize = textrelasize = textfarrelasize =
|
||||
datasize = datarelasize = rodatasize = rodatafarsize =
|
||||
rodatarelasize = rodatafarrelasize = symtabsize = strtabsize = 0;
|
||||
|
||||
bss.number = data.number = rodata.number = rodatafar.number =
|
||||
text.number = textfar.number = -1;
|
||||
|
||||
shdrptr = ehdr.e_shoff;
|
||||
for(i = 0; i < shdrnum; ++i) {
|
||||
seek_read(fd, shdrptr, (char *)&shdr, sizeof(shdr));
|
||||
|
||||
/* The name of the section is contained in the strings table. */
|
||||
nameptr = strs + shdr.sh_name;
|
||||
seek_read(fd, nameptr, name, sizeof(name));
|
||||
PRINTF("Section shdrptr 0x%x, %d + %d type %d\n",
|
||||
shdrptr,
|
||||
strs, shdr.sh_name,
|
||||
(int)shdr.sh_type);
|
||||
/*
|
||||
* Match the name of the section with a predefined set of names
|
||||
* (.text, .far.text, .data, .bss, .rodata, .far.rodata, .rela.text, .rela.far.text,
|
||||
* .rela.data, .rela.rodata, .rela.far.rodata, .symtab, and .strtab).
|
||||
*/
|
||||
|
||||
if(shdr.sh_type == SHT_SYMTAB) {
|
||||
PRINTF("symtab\n");
|
||||
symtaboff = shdr.sh_offset;
|
||||
symtabsize = shdr.sh_size;
|
||||
} else if(shdr.sh_type == SHT_STRTAB) {
|
||||
PRINTF("strtab\n");
|
||||
strtaboff = shdr.sh_offset;
|
||||
strtabsize = shdr.sh_size;
|
||||
} else if(strncmp(name, ".text", 5) == 0) {
|
||||
textoff = shdr.sh_offset;
|
||||
textsize = shdr.sh_size;
|
||||
text.number = i;
|
||||
text.offset = textoff;
|
||||
} else if(strncmp(name, ".far.text", 9) == 0) {
|
||||
textfaroff = shdr.sh_offset;
|
||||
textfarsize = shdr.sh_size;
|
||||
textfar.number = i;
|
||||
textfar.offset = textfaroff;
|
||||
} else if(strncmp(name, ".rel.text", 9) == 0) {
|
||||
using_relas = 0;
|
||||
textrelaoff = shdr.sh_offset;
|
||||
textrelasize = shdr.sh_size;
|
||||
} else if(strncmp(name, ".rela.text", 10) == 0) {
|
||||
using_relas = 1;
|
||||
textrelaoff = shdr.sh_offset;
|
||||
textrelasize = shdr.sh_size;
|
||||
} else if(strncmp(name, ".rela.far.text", 14) == 0) {
|
||||
using_relas = 1;
|
||||
textfarrelaoff = shdr.sh_offset;
|
||||
textfarrelasize = shdr.sh_size;
|
||||
} else if(strncmp(name, ".data", 5) == 0) {
|
||||
dataoff = shdr.sh_offset;
|
||||
datasize = shdr.sh_size;
|
||||
data.number = i;
|
||||
data.offset = dataoff;
|
||||
} else if(strncmp(name, ".rodata", 7) == 0) {
|
||||
/* read-only data handled the same way as regular text section */
|
||||
rodataoff = shdr.sh_offset;
|
||||
rodatasize = shdr.sh_size;
|
||||
rodata.number = i;
|
||||
rodata.offset = rodataoff;
|
||||
} else if(strncmp(name, ".far.rodata", 11) == 0) {
|
||||
rodatafaroff = shdr.sh_offset;
|
||||
rodatafarsize = shdr.sh_size;
|
||||
rodatafar.number = i;
|
||||
rodatafar.offset = rodataoff;
|
||||
} else if(strncmp(name, ".rel.rodata", 11) == 0) {
|
||||
/* using elf32_rel instead of rela */
|
||||
using_relas = 0;
|
||||
rodatarelaoff = shdr.sh_offset;
|
||||
rodatarelasize = shdr.sh_size;
|
||||
} else if(strncmp(name, ".rela.rodata", 12) == 0) {
|
||||
using_relas = 1;
|
||||
rodatarelaoff = shdr.sh_offset;
|
||||
rodatarelasize = shdr.sh_size;
|
||||
} else if(strncmp(name, ".rela.far.rodata", 16) == 0) {
|
||||
using_relas = 1;
|
||||
rodatafarrelaoff = shdr.sh_offset;
|
||||
rodatafarrelasize = shdr.sh_size;
|
||||
} else if(strncmp(name, ".rel.data", 9) == 0) {
|
||||
/* using elf32_rel instead of rela */
|
||||
using_relas = 0;
|
||||
datarelaoff = shdr.sh_offset;
|
||||
datarelasize = shdr.sh_size;
|
||||
} else if(strncmp(name, ".rela.data", 10) == 0) {
|
||||
using_relas = 1;
|
||||
datarelaoff = shdr.sh_offset;
|
||||
datarelasize = shdr.sh_size;
|
||||
} else if(strncmp(name, ".bss", 4) == 0) {
|
||||
bsssize = shdr.sh_size;
|
||||
bss.number = i;
|
||||
bss.offset = 0;
|
||||
}
|
||||
|
||||
/* Move on to the next section header. */
|
||||
shdrptr += shdrsize;
|
||||
}
|
||||
if(symtabsize == 0) {
|
||||
return ELFLOADER_NO_SYMTAB;
|
||||
}
|
||||
if(strtabsize == 0) {
|
||||
return ELFLOADER_NO_STRTAB;
|
||||
}
|
||||
if(textfarsize == 0) {
|
||||
return ELFLOADER_NO_TEXT;
|
||||
}
|
||||
|
||||
PRINTF("before allocate ram\n");
|
||||
bss.address = (char *)elfloader_arch_allocate_ram(bsssize + datasize);
|
||||
data.address = (char *)bss.address + bsssize;
|
||||
PRINTF("before allocate rom\n");
|
||||
textfar.address = (char *)elfloader_arch_allocate_rom(textfarsize + rodatafarsize);
|
||||
rodatafar.address = (char *)textfar.address + textfarsize;
|
||||
|
||||
PRINTF("bss base address: bss.address = 0x%08x\n", bss.address);
|
||||
PRINTF("data base address: data.address = 0x%08x\n", data.address);
|
||||
PRINTF("textfar base address: textfar.address = 0x%08x\n", textfar.address);
|
||||
PRINTF("rodatafar base address: rodatafar.address = 0x%08x\n", rodatafar.address);
|
||||
|
||||
/* If we have text segment relocations, we process them. */
|
||||
PRINTF("elfloader: relocate textfar\n");
|
||||
if(textfarrelasize > 0) {
|
||||
ret = relocate_section(fd,
|
||||
textfarrelaoff, textfarrelasize,
|
||||
textfaroff,
|
||||
textfar.address,
|
||||
strs,
|
||||
strtaboff,
|
||||
symtaboff, symtabsize, using_relas);
|
||||
if(ret != ELFLOADER_OK) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* If we have any rodata segment relocations, we process them too. */
|
||||
PRINTF("elfloader: relocate rodata\n");
|
||||
if(rodatafarrelasize > 0) {
|
||||
ret = relocate_section(fd,
|
||||
rodatafarrelaoff, rodatafarrelasize,
|
||||
rodatafaroff,
|
||||
rodatafar.address,
|
||||
strs,
|
||||
strtaboff,
|
||||
symtaboff, symtabsize, using_relas);
|
||||
if(ret != ELFLOADER_OK) {
|
||||
PRINTF("elfloader: data failed\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* If we have any data segment relocations, we process them too. */
|
||||
PRINTF("elfloader: relocate data\n");
|
||||
if(datarelasize > 0) {
|
||||
ret = relocate_section(fd,
|
||||
datarelaoff, datarelasize,
|
||||
dataoff,
|
||||
data.address,
|
||||
strs,
|
||||
strtaboff,
|
||||
symtaboff, symtabsize, using_relas);
|
||||
if(ret != ELFLOADER_OK) {
|
||||
PRINTF("elfloader: data failed\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* Write text and rodata segment into flash and data segment into RAM. */
|
||||
elfloader_arch_write_rom(fd, textfaroff, textfarsize, textfar.address);
|
||||
elfloader_arch_write_rom(fd, rodatafaroff, rodatafarsize, rodatafar.address);
|
||||
|
||||
memset(bss.address, 0, bsssize);
|
||||
seek_read(fd, dataoff, data.address, datasize);
|
||||
|
||||
PRINTF("elfloader: autostart search\n");
|
||||
process = (struct process **)find_local_symbol(fd, "autostart_processes",
|
||||
symtaboff, symtabsize, strtaboff);
|
||||
if(process != NULL) {
|
||||
PRINTF("elfloader: autostart found\n");
|
||||
elfloader_autostart_processes = process;
|
||||
return ELFLOADER_OK;
|
||||
} else {
|
||||
PRINTF("elfloader: no autostart\n");
|
||||
process = (struct process **)find_program_processes(fd, symtaboff,
|
||||
symtabsize, strtaboff);
|
||||
if(process != NULL) {
|
||||
PRINTF("elfloader: FOUND PRG\n");
|
||||
}
|
||||
return ELFLOADER_NO_STARTPOINT;
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void *
|
||||
elfloader_arch_allocate_ram(int size)
|
||||
{
|
||||
return datamemory;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void *
|
||||
elfloader_arch_allocate_rom(int size)
|
||||
{
|
||||
#if ELFLOADER_CONF_TEXT_IN_ROM
|
||||
/* Return an 512-byte aligned pointer. */
|
||||
return (char *)
|
||||
((unsigned long)&textmemory[0] & 0xfffffe00) +
|
||||
(((unsigned long)&textmemory[0] & 0x1ff) == 0 ? 0 : 0x200);
|
||||
#else /* ELFLOADER_CONF_TEXT_IN_ROM */
|
||||
return textmemory;
|
||||
#endif /* ELFLOADER_CONF_TEXT_IN_ROM */
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#define READSIZE 32
|
||||
void
|
||||
elfloader_arch_write_rom(int fd, unsigned short textoff, unsigned int size, char *mem)
|
||||
{
|
||||
#if ELFLOADER_CONF_TEXT_IN_ROM
|
||||
int i;
|
||||
unsigned int ptr;
|
||||
unsigned short *flashptr;
|
||||
|
||||
flash_setup();
|
||||
|
||||
flashptr = (unsigned short *)mem;
|
||||
|
||||
cfs_seek(fd, textoff, CFS_SEEK_SET);
|
||||
for(ptr = 0; ptr < size; ptr += READSIZE) {
|
||||
|
||||
/* Read data from file into RAM. */
|
||||
cfs_read(fd, (unsigned char *)datamemory, READSIZE);
|
||||
|
||||
/* Clear flash page on 512 byte boundary. */
|
||||
if((((unsigned short)flashptr) & 0x01ff) == 0) {
|
||||
flash_clear(flashptr);
|
||||
}
|
||||
|
||||
/*
|
||||
* Burn data from RAM into flash ROM. Flash is burned one 16-bit
|
||||
* word at a time, so we need to be careful when incrementing
|
||||
* pointers. The flashptr is already a short pointer, so
|
||||
* incrementing it by one will actually increment the address by
|
||||
* two.
|
||||
*/
|
||||
for(i = 0; i < READSIZE / 2; ++i) {
|
||||
flash_write(flashptr, ((unsigned short *)datamemory)[i]);
|
||||
++flashptr;
|
||||
}
|
||||
}
|
||||
|
||||
flash_done();
|
||||
#else /* ELFLOADER_CONF_TEXT_IN_ROM */
|
||||
cfs_seek(fd, textoff, CFS_SEEK_SET);
|
||||
cfs_read(fd, (unsigned char *)mem, size);
|
||||
#endif /* ELFLOADER_CONF_TEXT_IN_ROM */
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Relocate an MSP430X ELF section. */
|
||||
void
|
||||
elfloader_arch_relocate(int fd, unsigned int sectionoffset,
|
||||
char *sectionaddr,
|
||||
struct elf32_rela *rela, char *addr)
|
||||
{
|
||||
unsigned int type;
|
||||
unsigned char instr[2];
|
||||
|
||||
type = ELF32_R_TYPE(rela->r_info);
|
||||
addr += rela->r_addend;
|
||||
|
||||
switch(type) {
|
||||
case R_MSP430_16:
|
||||
case R_MSP430_16_PCREL:
|
||||
case R_MSP430_16_BYTE:
|
||||
case R_MSP430_16_PCREL_BYTE:
|
||||
cfs_seek(fd, sectionoffset + rela->r_offset, CFS_SEEK_SET);
|
||||
cfs_write(fd, (char *)&addr, 2);
|
||||
break;
|
||||
case R_MSP430_32:
|
||||
cfs_seek(fd, sectionoffset + rela->r_offset, CFS_SEEK_SET);
|
||||
cfs_write(fd, (char *)&addr, 2);
|
||||
break;
|
||||
case R_MSP430X_S:
|
||||
case R_MSP430X_S_BYTE:
|
||||
/* src(19:16) located at positions 11:8 of opcode */
|
||||
/* src(15:0) located just after opcode */
|
||||
cfs_seek(fd, sectionoffset + rela->r_offset, CFS_SEEK_SET);
|
||||
cfs_read(fd, instr, 2);
|
||||
instr[1] = (int)(instr[1]) & 0xf0 | (((long int)addr >> 8) & 0x0f00);
|
||||
instr[0] = (int)(instr[0]) & 0xff;
|
||||
cfs_seek(fd, sectionoffset + rela->r_offset, CFS_SEEK_SET);
|
||||
cfs_write(fd, instr, 2);
|
||||
cfs_write(fd, (char *)&addr, 2);
|
||||
break;
|
||||
case R_MSP430X_D:
|
||||
case R_MSP430X_PCREL_D:
|
||||
case R_MSP430X_D_BYTE:
|
||||
/* dst(19:16) located at positions 3:0 of opcode */
|
||||
/* dst(15:0) located just after opcode */
|
||||
cfs_seek(fd, sectionoffset + rela->r_offset, CFS_SEEK_SET);
|
||||
cfs_read(fd, instr, 2);
|
||||
instr[1] = (int)(instr[1]) & 0xff;
|
||||
instr[0] = (int)(instr[0]) & 0xf0 | (((long int)addr >> 16) & 0x000f);
|
||||
cfs_seek(fd, sectionoffset + rela->r_offset, CFS_SEEK_SET);
|
||||
cfs_write(fd, instr, 2);
|
||||
cfs_write(fd, (char *)&addr, 2);
|
||||
break;
|
||||
case R_MSP430X_PCREL_SRC_BYTE:
|
||||
case R_MSP430X_SRC_BYTE:
|
||||
case R_MSP430X_PCREL_SRC:
|
||||
case R_MSP430X_SRC:
|
||||
/* src(19:16) located at positions 10:7 of extension word */
|
||||
/* src(15:0) located just after opcode */
|
||||
cfs_seek(fd, sectionoffset + rela->r_offset, CFS_SEEK_SET);
|
||||
cfs_read(fd, instr, 2);
|
||||
/* 4 most-significant bits */
|
||||
instr[1] = (int)(instr[1]) & 0xf8 | (((long int)addr >> 9) & 0x0780);
|
||||
instr[0] = (int)(instr[0]) & 0x7f | (((long int)addr >> 9) & 0x0780);
|
||||
cfs_seek(fd, sectionoffset + rela->r_offset, CFS_SEEK_SET);
|
||||
cfs_write(fd, instr, 2);
|
||||
/* 16 least-significant bits */
|
||||
cfs_seek(fd, sectionoffset + rela->r_offset + 0x04, CFS_SEEK_SET);
|
||||
cfs_write(fd, (char *)&addr, 2);
|
||||
break;
|
||||
case R_MSP430X_DST_BYTE:
|
||||
case R_MSP430X_PCREL_DST_BYTE:
|
||||
case R_MSP430X_DST:
|
||||
case R_MSP430X_PCREL_DST:
|
||||
/* dst(19:16) located at positions 3:0 of extension word */
|
||||
/* dst(15:0) located just after opcode */
|
||||
cfs_seek(fd, sectionoffset + rela->r_offset, CFS_SEEK_SET);
|
||||
cfs_read(fd, instr, 2);
|
||||
instr[1] = (int)(instr[1]) & 0xff;
|
||||
instr[0] = (int)(instr[0]) & 0xf0 | (((long int)addr >> 16) & 0x000f);
|
||||
cfs_seek(fd, sectionoffset + rela->r_offset, CFS_SEEK_SET);
|
||||
cfs_write(fd, instr, 2);
|
||||
cfs_seek(fd, sectionoffset + rela->r_offset + 0x04, CFS_SEEK_SET);
|
||||
cfs_write(fd, (char *)&addr, 2);
|
||||
break;
|
||||
case R_MSP430X_DST_2ND:
|
||||
case R_MSP430X_PCREL_DST_2ND:
|
||||
case R_MSP430X_DST_2ND_BYTE:
|
||||
case R_MSP430X_PCREL_DST_2ND_BYTE:
|
||||
/* dst(19:16) located at positions 3:0 of extension word */
|
||||
/* dst(15:0) located after src(15:0) */
|
||||
cfs_seek(fd, sectionoffset + rela->r_offset, CFS_SEEK_SET);
|
||||
cfs_read(fd, instr, 2);
|
||||
instr[1] = (int)(instr[1]) & 0xff;
|
||||
instr[0] = (int)(instr[0]) & 0xf0 | (((long int)addr >> 16) & 0x000f);
|
||||
cfs_seek(fd, sectionoffset + rela->r_offset, CFS_SEEK_SET);
|
||||
cfs_write(fd, instr, 2);
|
||||
cfs_seek(fd, sectionoffset + rela->r_offset + 0x06, CFS_SEEK_SET);
|
||||
cfs_write(fd, (char *)&addr, 2);
|
||||
break;
|
||||
case R_MSP430X_INDXD:
|
||||
case R_MSP430X_PCREL_INDXD:
|
||||
cfs_seek(fd, sectionoffset + rela->r_offset + 0x02, CFS_SEEK_SET);
|
||||
cfs_write(fd, (char *)&addr, 2);
|
||||
break;
|
||||
default:
|
||||
PRINTF("Unknown relocation type!\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
|
@ -34,6 +34,20 @@
|
|||
|
||||
#include "net/ip/uip.h"
|
||||
|
||||
|
||||
/**
|
||||
* \brief Is IPv4-mapped Address
|
||||
*
|
||||
* See https://tools.ietf.org/html/rfc6890#page-14
|
||||
*/
|
||||
#define ip64_addr_is_ipv4_mapped_addr(a) \
|
||||
((((a)->u16[0]) == 0) && \
|
||||
(((a)->u16[1]) == 0) && \
|
||||
(((a)->u16[2]) == 0) && \
|
||||
(((a)->u16[3]) == 0) && \
|
||||
(((a)->u16[4]) == 0) && \
|
||||
(((a)->u16[5]) == 0xFFFF))
|
||||
|
||||
void ip64_addr_copy4(uip_ip4addr_t *dest, const uip_ip4addr_t *src);
|
||||
|
||||
void ip64_addr_copy6(uip_ip6addr_t *dest, const uip_ip6addr_t *src);
|
||||
|
|
|
@ -501,7 +501,7 @@ mdns_write_announce_records(unsigned char *queryptr, uint8_t *count)
|
|||
for(i = 0; i < UIP_DS6_ADDR_NB; ++i) {
|
||||
if(uip_ds6_if.addr_list[i].isused
|
||||
#if !RESOLV_CONF_MDNS_INCLUDE_GLOBAL_V6_ADDRS
|
||||
&& uip_is_addr_link_local(&uip_ds6_if.addr_list[i].ipaddr)
|
||||
&& uip_is_addr_linklocal(&uip_ds6_if.addr_list[i].ipaddr)
|
||||
#endif
|
||||
) {
|
||||
if(!*count) {
|
||||
|
|
|
@ -155,6 +155,7 @@ unsigned char tcpip_is_forwarding; /* Forwarding right now? */
|
|||
PROCESS(tcpip_process, "TCP/IP stack");
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#if UIP_TCP || UIP_CONF_IP_FORWARD
|
||||
static void
|
||||
start_periodic_tcp_timer(void)
|
||||
{
|
||||
|
@ -162,6 +163,7 @@ start_periodic_tcp_timer(void)
|
|||
etimer_restart(&periodic);
|
||||
}
|
||||
}
|
||||
#endif /* UIP_TCP || UIP_CONF_IP_FORWARD */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
check_for_tcp_syn(void)
|
||||
|
@ -183,30 +185,17 @@ check_for_tcp_syn(void)
|
|||
static void
|
||||
packet_input(void)
|
||||
{
|
||||
#if UIP_CONF_IP_FORWARD
|
||||
if(uip_len > 0) {
|
||||
|
||||
#if UIP_CONF_IP_FORWARD
|
||||
tcpip_is_forwarding = 1;
|
||||
if(uip_fw_forward() == UIP_FW_LOCAL) {
|
||||
if(uip_fw_forward() != UIP_FW_LOCAL) {
|
||||
tcpip_is_forwarding = 0;
|
||||
check_for_tcp_syn();
|
||||
uip_input();
|
||||
if(uip_len > 0) {
|
||||
#if UIP_CONF_TCP_SPLIT
|
||||
uip_split_output();
|
||||
#else /* UIP_CONF_TCP_SPLIT */
|
||||
#if NETSTACK_CONF_WITH_IPV6
|
||||
tcpip_ipv6_output();
|
||||
#else
|
||||
PRINTF("tcpip packet_input forward output len %d\n", uip_len);
|
||||
tcpip_output();
|
||||
#endif
|
||||
#endif /* UIP_CONF_TCP_SPLIT */
|
||||
}
|
||||
return;
|
||||
}
|
||||
tcpip_is_forwarding = 0;
|
||||
}
|
||||
#else /* UIP_CONF_IP_FORWARD */
|
||||
if(uip_len > 0) {
|
||||
#endif /* UIP_CONF_IP_FORWARD */
|
||||
|
||||
check_for_tcp_syn();
|
||||
uip_input();
|
||||
if(uip_len > 0) {
|
||||
|
@ -215,14 +204,13 @@ packet_input(void)
|
|||
#else /* UIP_CONF_TCP_SPLIT */
|
||||
#if NETSTACK_CONF_WITH_IPV6
|
||||
tcpip_ipv6_output();
|
||||
#else
|
||||
#else /* NETSTACK_CONF_WITH_IPV6 */
|
||||
PRINTF("tcpip packet_input output len %d\n", uip_len);
|
||||
tcpip_output();
|
||||
#endif
|
||||
#endif /* NETSTACK_CONF_WITH_IPV6 */
|
||||
#endif /* UIP_CONF_TCP_SPLIT */
|
||||
}
|
||||
}
|
||||
#endif /* UIP_CONF_IP_FORWARD */
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#if UIP_TCP
|
||||
|
@ -529,10 +517,7 @@ void
|
|||
tcpip_input(void)
|
||||
{
|
||||
process_post_synch(&tcpip_process, PACKET_INPUT, NULL);
|
||||
uip_len = 0;
|
||||
#if NETSTACK_CONF_WITH_IPV6
|
||||
uip_ext_len = 0;
|
||||
#endif /*NETSTACK_CONF_WITH_IPV6*/
|
||||
uip_clear_buf();
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#if NETSTACK_CONF_WITH_IPV6
|
||||
|
@ -548,13 +533,13 @@ tcpip_ipv6_output(void)
|
|||
|
||||
if(uip_len > UIP_LINK_MTU) {
|
||||
UIP_LOG("tcpip_ipv6_output: Packet to big");
|
||||
uip_len = 0;
|
||||
uip_clear_buf();
|
||||
return;
|
||||
}
|
||||
|
||||
if(uip_is_addr_unspecified(&UIP_IP_BUF->destipaddr)){
|
||||
UIP_LOG("tcpip_ipv6_output: Destination address unspecified");
|
||||
uip_len = 0;
|
||||
uip_clear_buf();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -587,11 +572,20 @@ tcpip_ipv6_output(void)
|
|||
/* This should be copied from the ext header... */
|
||||
UIP_IP_BUF->proto = proto;
|
||||
}
|
||||
UIP_FALLBACK_INTERFACE.output();
|
||||
/* Inform the other end that the destination is not reachable. If it's
|
||||
* not informed routes might get lost unexpectedly until there's a need
|
||||
* to send a new packet to the peer */
|
||||
if(UIP_FALLBACK_INTERFACE.output() < 0) {
|
||||
PRINTF("FALLBACK: output error. Reporting DST UNREACH\n");
|
||||
uip_icmp6_error_output(ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_ADDR, 0);
|
||||
uip_flags = 0;
|
||||
tcpip_ipv6_output();
|
||||
return;
|
||||
}
|
||||
#else
|
||||
PRINTF("tcpip_ipv6_output: Destination off-link but no route\n");
|
||||
#endif /* !UIP_FALLBACK_INTERFACE */
|
||||
uip_len = 0;
|
||||
uip_clear_buf();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -643,7 +637,7 @@ tcpip_ipv6_output(void)
|
|||
|
||||
#if UIP_CONF_IPV6_RPL
|
||||
if(rpl_update_header_final(nexthop)) {
|
||||
uip_len = 0;
|
||||
uip_clear_buf();
|
||||
return;
|
||||
}
|
||||
#endif /* UIP_CONF_IPV6_RPL */
|
||||
|
@ -651,7 +645,7 @@ tcpip_ipv6_output(void)
|
|||
if(nbr == NULL) {
|
||||
#if UIP_ND6_SEND_NA
|
||||
if((nbr = uip_ds6_nbr_add(nexthop, NULL, 0, NBR_INCOMPLETE)) == NULL) {
|
||||
uip_len = 0;
|
||||
uip_clear_buf();
|
||||
return;
|
||||
} else {
|
||||
#if UIP_CONF_IPV6_QUEUE_PKT
|
||||
|
@ -675,7 +669,11 @@ tcpip_ipv6_output(void)
|
|||
|
||||
stimer_set(&nbr->sendns, uip_ds6_if.retrans_timer / 1000);
|
||||
nbr->nscount = 1;
|
||||
/* Send the first NS try from here (multicast destination IP address). */
|
||||
}
|
||||
#else /* UIP_ND6_SEND_NA */
|
||||
uip_len = 0;
|
||||
return;
|
||||
#endif /* UIP_ND6_SEND_NA */
|
||||
} else {
|
||||
#if UIP_ND6_SEND_NA
|
||||
|
@ -689,7 +687,7 @@ tcpip_ipv6_output(void)
|
|||
uip_packetqueue_set_buflen(&nbr->packethandle, uip_len);
|
||||
}
|
||||
#endif /*UIP_CONF_IPV6_QUEUE_PKT*/
|
||||
uip_len = 0;
|
||||
uip_clear_buf();
|
||||
return;
|
||||
}
|
||||
/* Send in parallel if we are running NUD (nbc state is either STALE,
|
||||
|
@ -719,15 +717,13 @@ tcpip_ipv6_output(void)
|
|||
}
|
||||
#endif /*UIP_CONF_IPV6_QUEUE_PKT*/
|
||||
|
||||
uip_len = 0;
|
||||
uip_clear_buf();
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
/* Multicast IP destination address. */
|
||||
tcpip_output(NULL);
|
||||
uip_len = 0;
|
||||
uip_ext_len = 0;
|
||||
uip_clear_buf();
|
||||
}
|
||||
#endif /* NETSTACK_CONF_WITH_IPV6 */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
*/
|
||||
|
||||
#include "net/ip/uip-debug.h"
|
||||
#include "net/ip/ip64-addr.h"
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
|
@ -53,20 +54,38 @@ uip_debug_ipaddr_print(const uip_ipaddr_t *addr)
|
|||
return;
|
||||
}
|
||||
#if NETSTACK_CONF_WITH_IPV6
|
||||
for(i = 0, f = 0; i < sizeof(uip_ipaddr_t); i += 2) {
|
||||
a = (addr->u8[i] << 8) + addr->u8[i + 1];
|
||||
if(a == 0 && f >= 0) {
|
||||
if(f++ == 0) {
|
||||
PRINTA("::");
|
||||
if(ip64_addr_is_ipv4_mapped_addr(addr)) {
|
||||
/*
|
||||
* Printing IPv4-mapped addresses is done according to RFC 3513 [1]
|
||||
*
|
||||
* "An alternative form that is sometimes more
|
||||
* convenient when dealing with a mixed environment
|
||||
* of IPv4 and IPv6 nodes is x:x:x:x:x:x:d.d.d.d,
|
||||
* where the 'x's are the hexadecimal values of the
|
||||
* six high-order 16-bit pieces of the address, and
|
||||
* the 'd's are the decimal values of the four
|
||||
* low-order 8-bit pieces of the address (standard
|
||||
* IPv4 representation)."
|
||||
*
|
||||
* [1] https://tools.ietf.org/html/rfc3513#page-5
|
||||
*/
|
||||
PRINTA("::FFFF:%u.%u.%u.%u", addr->u8[12], addr->u8[13], addr->u8[14], addr->u8[15]);
|
||||
} else {
|
||||
for(i = 0, f = 0; i < sizeof(uip_ipaddr_t); i += 2) {
|
||||
a = (addr->u8[i] << 8) + addr->u8[i + 1];
|
||||
if(a == 0 && f >= 0) {
|
||||
if(f++ == 0) {
|
||||
PRINTA("::");
|
||||
}
|
||||
} else {
|
||||
if(f > 0) {
|
||||
f = -1;
|
||||
} else if(i > 0) {
|
||||
PRINTA(":");
|
||||
}
|
||||
PRINTA("%x", a);
|
||||
}
|
||||
} else {
|
||||
if(f > 0) {
|
||||
f = -1;
|
||||
} else if(i > 0) {
|
||||
PRINTA(":");
|
||||
}
|
||||
PRINTA("%x", a);
|
||||
}
|
||||
}
|
||||
}
|
||||
#else /* NETSTACK_CONF_WITH_IPV6 */
|
||||
PRINTA("%u.%u.%u.%u", addr->u8[0], addr->u8[1], addr->u8[2], addr->u8[3]);
|
||||
|
|
|
@ -54,9 +54,9 @@ uip_udp_packet_send(struct uip_udp_conn *c, const void *data, int len)
|
|||
if(data != NULL) {
|
||||
uip_udp_conn = c;
|
||||
uip_slen = len;
|
||||
memcpy(&uip_buf[UIP_LLH_LEN + UIP_IPUDPH_LEN], data,
|
||||
len > UIP_BUFSIZE - UIP_LLH_LEN - UIP_IPUDPH_LEN?
|
||||
UIP_BUFSIZE - UIP_LLH_LEN - UIP_IPUDPH_LEN: len);
|
||||
memmove(&uip_buf[UIP_LLH_LEN + UIP_IPUDPH_LEN], data,
|
||||
len > UIP_BUFSIZE - UIP_LLH_LEN - UIP_IPUDPH_LEN?
|
||||
UIP_BUFSIZE - UIP_LLH_LEN - UIP_IPUDPH_LEN: len);
|
||||
uip_process(UIP_UDP_SEND_CONN);
|
||||
|
||||
#if UIP_CONF_IPV6_MULTICAST
|
||||
|
|
|
@ -64,17 +64,11 @@
|
|||
#define UIP_TCPH_LEN 20 /* Size of TCP header */
|
||||
#define UIP_ICMPH_LEN 4 /* Size of ICMP header */
|
||||
|
||||
#define UIP_IPUDPH_LEN (UIP_UDPH_LEN + UIP_IPH_LEN) /* Size of IP +
|
||||
* UDP
|
||||
* header */
|
||||
#define UIP_IPTCPH_LEN (UIP_TCPH_LEN + UIP_IPH_LEN) /* Size of IP +
|
||||
* TCP
|
||||
* header */
|
||||
#define UIP_IPUDPH_LEN (UIP_UDPH_LEN + UIP_IPH_LEN) /* Size of IP + UDP header */
|
||||
#define UIP_IPTCPH_LEN (UIP_TCPH_LEN + UIP_IPH_LEN) /* Size of IP + TCP header */
|
||||
#define UIP_TCPIP_HLEN UIP_IPTCPH_LEN
|
||||
#define UIP_IPICMPH_LEN (UIP_IPH_LEN + UIP_ICMPH_LEN) /* size of ICMP
|
||||
+ IP header */
|
||||
#define UIP_LLIPH_LEN (UIP_LLH_LEN + UIP_IPH_LEN) /* size of L2
|
||||
+ IP header */
|
||||
#define UIP_IPICMPH_LEN (UIP_IPH_LEN + UIP_ICMPH_LEN) /* Size of ICMP + IP header */
|
||||
#define UIP_LLIPH_LEN (UIP_LLH_LEN + UIP_IPH_LEN) /* Size of L2 + IP header */
|
||||
#if NETSTACK_CONF_WITH_IPV6
|
||||
/**
|
||||
* The sums below are quite used in ND. When used for uip_buf, we
|
||||
|
@ -99,12 +93,12 @@
|
|||
*
|
||||
*/
|
||||
typedef union uip_ip4addr_t {
|
||||
uint8_t u8[4]; /* Initializer, must come first. */
|
||||
uint8_t u8[4]; /* Initializer, must come first. */
|
||||
uint16_t u16[2];
|
||||
} uip_ip4addr_t;
|
||||
|
||||
typedef union uip_ip6addr_t {
|
||||
uint8_t u8[16]; /* Initializer, must come first. */
|
||||
uint8_t u8[16]; /* Initializer, must come first. */
|
||||
uint16_t u16[8];
|
||||
} uip_ip6addr_t;
|
||||
|
||||
|
@ -142,15 +136,18 @@ typedef struct uip_eth_addr {
|
|||
typedef uip_802154_longaddr uip_lladdr_t;
|
||||
#define UIP_802154_SHORTADDR_LEN 2
|
||||
#define UIP_802154_LONGADDR_LEN 8
|
||||
/** \brief Link layer address length */
|
||||
#define UIP_LLADDR_LEN UIP_802154_LONGADDR_LEN
|
||||
#else /*UIP_CONF_LL_802154*/
|
||||
#if UIP_CONF_LL_80211
|
||||
/** \brief 802.11 address */
|
||||
typedef uip_80211_addr uip_lladdr_t;
|
||||
/** \brief Link layer address length */
|
||||
#define UIP_LLADDR_LEN 6
|
||||
#else /*UIP_CONF_LL_80211*/
|
||||
/** \brief Ethernet address */
|
||||
typedef uip_eth_addr uip_lladdr_t;
|
||||
/** \brief Link layer address length */
|
||||
#define UIP_LLADDR_LEN 6
|
||||
#endif /*UIP_CONF_LL_80211*/
|
||||
#endif /*UIP_CONF_LL_802154*/
|
||||
|
@ -1057,7 +1054,7 @@ struct uip_udp_conn *uip_udp_new(const uip_ipaddr_t *ripaddr, uint16_t rport);
|
|||
* \hideinitializer
|
||||
*/
|
||||
#define uip_ip4addr_cmp(addr1, addr2) ((addr1)->u16[0] == (addr2)->u16[0] && \
|
||||
(addr1)->u16[1] == (addr2)->u16[1])
|
||||
(addr1)->u16[1] == (addr2)->u16[1])
|
||||
#define uip_ip6addr_cmp(addr1, addr2) (memcmp(addr1, addr2, sizeof(uip_ip6addr_t)) == 0)
|
||||
|
||||
#if NETSTACK_CONF_WITH_IPV6
|
||||
|
@ -1326,6 +1323,22 @@ extern uint8_t uip_ext_len;
|
|||
extern uint16_t uip_urglen, uip_surglen;
|
||||
#endif /* UIP_URGDATA > 0 */
|
||||
|
||||
/*
|
||||
* Clear uIP buffer
|
||||
*
|
||||
* This function clears the uIP buffer by reseting the uip_len and
|
||||
* uip_ext_len pointers.
|
||||
*/
|
||||
#if NETSTACK_CONF_WITH_IPV6
|
||||
#define uip_clear_buf() { \
|
||||
uip_len = 0; \
|
||||
uip_ext_len = 0; \
|
||||
}
|
||||
#else /*NETSTACK_CONF_WITH_IPV6*/
|
||||
#define uip_clear_buf() { \
|
||||
uip_len = 0; \
|
||||
}
|
||||
#endif /*NETSTACK_CONF_WITH_IPV6*/
|
||||
|
||||
/**
|
||||
* Representation of a uIP TCP connection.
|
||||
|
@ -1342,29 +1355,23 @@ struct uip_conn {
|
|||
|
||||
uint16_t lport; /**< The local TCP port, in network byte order. */
|
||||
uint16_t rport; /**< The local remote TCP port, in network byte
|
||||
order. */
|
||||
order. */
|
||||
|
||||
uint8_t rcv_nxt[4]; /**< The sequence number that we expect to
|
||||
receive next. */
|
||||
uint8_t snd_nxt[4]; /**< The sequence number that was last sent by
|
||||
us. */
|
||||
receive next. */
|
||||
uint8_t snd_nxt[4]; /**< The sequence number that was last sent by us. */
|
||||
uint16_t len; /**< Length of the data that was previously sent. */
|
||||
uint16_t mss; /**< Current maximum segment size for the
|
||||
connection. */
|
||||
uint16_t initialmss; /**< Initial maximum segment size for the
|
||||
connection. */
|
||||
uint8_t sa; /**< Retransmission time-out calculation state
|
||||
variable. */
|
||||
uint8_t sv; /**< Retransmission time-out calculation state
|
||||
variable. */
|
||||
uint16_t mss; /**< Current maximum segment size for the connection. */
|
||||
uint16_t initialmss; /**< Initial maximum segment size for the connection. */
|
||||
uint8_t sa; /**< Retransmission time-out calculation state variable. */
|
||||
uint8_t sv; /**< Retransmission time-out calculation state variable. */
|
||||
uint8_t rto; /**< Retransmission time-out. */
|
||||
uint8_t tcpstateflags; /**< TCP state and flags. */
|
||||
uint8_t timer; /**< The retransmission timer. */
|
||||
uint8_t nrtx; /**< The number of retransmissions for the last
|
||||
segment sent. */
|
||||
segment sent. */
|
||||
|
||||
/** The application state. */
|
||||
uip_tcp_appstate_t appstate;
|
||||
uip_tcp_appstate_t appstate; /** The application state. */
|
||||
};
|
||||
|
||||
|
||||
|
@ -1413,7 +1420,13 @@ extern struct uip_udp_conn uip_udp_conns[UIP_UDP_CONNS];
|
|||
|
||||
struct uip_fallback_interface {
|
||||
void (*init)(void);
|
||||
void (*output)(void);
|
||||
/**
|
||||
* \retval >=0
|
||||
* in case of success
|
||||
* \retval <0
|
||||
* in case of failure
|
||||
*/
|
||||
int (*output)(void);
|
||||
};
|
||||
|
||||
#if UIP_CONF_ICMP6
|
||||
|
@ -1442,51 +1455,43 @@ extern struct uip_stats uip_stat;
|
|||
*/
|
||||
struct uip_stats {
|
||||
struct {
|
||||
uip_stats_t recv; /**< Number of received packets at the IP
|
||||
layer. */
|
||||
uip_stats_t sent; /**< Number of sent packets at the IP
|
||||
layer. */
|
||||
uip_stats_t forwarded;/**< Number of forwarded packets at the IP
|
||||
layer. */
|
||||
uip_stats_t drop; /**< Number of dropped packets at the IP
|
||||
layer. */
|
||||
uip_stats_t recv; /**< Number of received packets at the IP layer. */
|
||||
uip_stats_t sent; /**< Number of sent packets at the IP layer. */
|
||||
uip_stats_t forwarded;/**< Number of forwarded packets at the IP layer. */
|
||||
uip_stats_t drop; /**< Number of dropped packets at the IP layer. */
|
||||
uip_stats_t vhlerr; /**< Number of packets dropped due to wrong
|
||||
IP version or header length. */
|
||||
IP version or header length. */
|
||||
uip_stats_t hblenerr; /**< Number of packets dropped due to wrong
|
||||
IP length, high byte. */
|
||||
IP length, high byte. */
|
||||
uip_stats_t lblenerr; /**< Number of packets dropped due to wrong
|
||||
IP length, low byte. */
|
||||
IP length, low byte. */
|
||||
uip_stats_t fragerr; /**< Number of packets dropped because they
|
||||
were IP fragments. */
|
||||
were IP fragments. */
|
||||
uip_stats_t chkerr; /**< Number of packets dropped due to IP
|
||||
checksum errors. */
|
||||
checksum errors. */
|
||||
uip_stats_t protoerr; /**< Number of packets dropped because they
|
||||
were neither ICMP, UDP nor TCP. */
|
||||
were neither ICMP, UDP nor TCP. */
|
||||
} ip; /**< IP statistics. */
|
||||
struct {
|
||||
uip_stats_t recv; /**< Number of received ICMP packets. */
|
||||
uip_stats_t sent; /**< Number of sent ICMP packets. */
|
||||
uip_stats_t drop; /**< Number of dropped ICMP packets. */
|
||||
uip_stats_t typeerr; /**< Number of ICMP packets with a wrong
|
||||
type. */
|
||||
uip_stats_t chkerr; /**< Number of ICMP packets with a bad
|
||||
checksum. */
|
||||
uip_stats_t typeerr; /**< Number of ICMP packets with a wrong type. */
|
||||
uip_stats_t chkerr; /**< Number of ICMP packets with a bad checksum. */
|
||||
} icmp; /**< ICMP statistics. */
|
||||
#if UIP_TCP
|
||||
struct {
|
||||
uip_stats_t recv; /**< Number of recived TCP segments. */
|
||||
uip_stats_t sent; /**< Number of sent TCP segments. */
|
||||
uip_stats_t drop; /**< Number of dropped TCP segments. */
|
||||
uip_stats_t chkerr; /**< Number of TCP segments with a bad
|
||||
checksum. */
|
||||
uip_stats_t ackerr; /**< Number of TCP segments with a bad ACK
|
||||
number. */
|
||||
uip_stats_t chkerr; /**< Number of TCP segments with a bad checksum. */
|
||||
uip_stats_t ackerr; /**< Number of TCP segments with a bad ACK number. */
|
||||
uip_stats_t rst; /**< Number of received TCP RST (reset) segments. */
|
||||
uip_stats_t rexmit; /**< Number of retransmitted TCP segments. */
|
||||
uip_stats_t syndrop; /**< Number of dropped SYNs because too few
|
||||
connections were available. */
|
||||
connections were available. */
|
||||
uip_stats_t synrst; /**< Number of SYNs for closed ports,
|
||||
triggering a RST. */
|
||||
triggering a RST. */
|
||||
} tcp; /**< TCP statistics. */
|
||||
#endif
|
||||
#if UIP_UDP
|
||||
|
@ -1495,7 +1500,7 @@ struct uip_stats {
|
|||
uip_stats_t recv; /**< Number of recived UDP segments. */
|
||||
uip_stats_t sent; /**< Number of sent UDP segments. */
|
||||
uip_stats_t chkerr; /**< Number of UDP segments with a bad
|
||||
checksum. */
|
||||
checksum. */
|
||||
} udp; /**< UDP statistics. */
|
||||
#endif /* UIP_UDP */
|
||||
#if NETSTACK_CONF_WITH_IPV6
|
||||
|
@ -1532,33 +1537,33 @@ CCIF extern uint8_t uip_flags;
|
|||
functions/macros. */
|
||||
|
||||
#define UIP_ACKDATA 1 /* Signifies that the outstanding data was
|
||||
acked and the application should send
|
||||
out new data instead of retransmitting
|
||||
the last data. */
|
||||
acked and the application should send
|
||||
out new data instead of retransmitting
|
||||
the last data. */
|
||||
#define UIP_NEWDATA 2 /* Flags the fact that the peer has sent
|
||||
us new data. */
|
||||
us new data. */
|
||||
#define UIP_REXMIT 4 /* Tells the application to retransmit the
|
||||
data that was last sent. */
|
||||
data that was last sent. */
|
||||
#define UIP_POLL 8 /* Used for polling the application, to
|
||||
check if the application has data that
|
||||
it wants to send. */
|
||||
check if the application has data that
|
||||
it wants to send. */
|
||||
#define UIP_CLOSE 16 /* The remote host has closed the
|
||||
connection, thus the connection has
|
||||
gone away. Or the application signals
|
||||
that it wants to close the
|
||||
connection. */
|
||||
connection, thus the connection has
|
||||
gone away. Or the application signals
|
||||
that it wants to close the
|
||||
connection. */
|
||||
#define UIP_ABORT 32 /* The remote host has aborted the
|
||||
connection, thus the connection has
|
||||
gone away. Or the application signals
|
||||
that it wants to abort the
|
||||
connection. */
|
||||
connection, thus the connection has
|
||||
gone away. Or the application signals
|
||||
that it wants to abort the
|
||||
connection. */
|
||||
#define UIP_CONNECTED 64 /* We have got a connection from a remote
|
||||
host and have set up a new connection
|
||||
for it, or an active connection has
|
||||
been successfully established. */
|
||||
|
||||
#define UIP_TIMEDOUT 128 /* The connection has been aborted due to
|
||||
too many retransmissions. */
|
||||
too many retransmissions. */
|
||||
|
||||
|
||||
/**
|
||||
|
@ -1584,16 +1589,16 @@ void uip_process(uint8_t flag);
|
|||
the macros defined in this file. */
|
||||
|
||||
#define UIP_DATA 1 /* Tells uIP that there is incoming
|
||||
data in the uip_buf buffer. The
|
||||
length of the data is stored in the
|
||||
global variable uip_len. */
|
||||
data in the uip_buf buffer. The
|
||||
length of the data is stored in the
|
||||
global variable uip_len. */
|
||||
#define UIP_TIMER 2 /* Tells uIP that the periodic timer
|
||||
has fired. */
|
||||
has fired. */
|
||||
#define UIP_POLL_REQUEST 3 /* Tells uIP that a connection should
|
||||
be polled. */
|
||||
be polled. */
|
||||
#define UIP_UDP_SEND_CONN 4 /* Tells uIP that a UDP datagram
|
||||
should be constructed in the
|
||||
uip_buf buffer. */
|
||||
should be constructed in the
|
||||
uip_buf buffer. */
|
||||
#if UIP_UDP
|
||||
#define UIP_UDP_TIMER 5
|
||||
#endif /* UIP_UDP */
|
||||
|
@ -2000,8 +2005,9 @@ CCIF extern uip_lladdr_t uip_lladdr;
|
|||
(((a)->u8[15]) == 0x02))
|
||||
|
||||
/**
|
||||
* \brief Checks whether the address a is link local.
|
||||
* a is of type uip_ipaddr_t
|
||||
* \brief is addr (a) a link local unicast address, see RFC3513
|
||||
* i.e. is (a) on prefix FE80::/10
|
||||
* a is of type uip_ipaddr_t*
|
||||
*/
|
||||
#define uip_is_addr_linklocal(a) \
|
||||
((a)->u8[0] == 0xfe && \
|
||||
|
@ -2054,15 +2060,6 @@ CCIF extern uip_lladdr_t uip_lladdr;
|
|||
(((b)->u8[13]) = ((a)->u8[13])); \
|
||||
(((b)->u16[7]) = ((a)->u16[7]))
|
||||
|
||||
/**
|
||||
* \brief is addr (a) a link local unicast address, see RFC3513
|
||||
* i.e. is (a) on prefix FE80::/10
|
||||
* a is of type uip_ipaddr_t*
|
||||
*/
|
||||
#define uip_is_addr_link_local(a) \
|
||||
((((a)->u8[0]) == 0xFE) && \
|
||||
(((a)->u8[1]) == 0x80))
|
||||
|
||||
/**
|
||||
* \brief was addr (a) forged based on the mac address m
|
||||
* a type is uip_ipaddr_t
|
||||
|
|
|
@ -35,9 +35,14 @@
|
|||
#include "ip64-tap-driver.h"
|
||||
#include "ip64-eth-interface.h"
|
||||
|
||||
#define IP64_CONF_UIP_FALLBACK_INTERFACE ip64_eth_interface
|
||||
#define IP64_CONF_INPUT ip64_eth_interface_input
|
||||
#define IP64_CONF_UIP_FALLBACK_INTERFACE ip64_eth_interface
|
||||
#define IP64_CONF_INPUT ip64_eth_interface_input
|
||||
|
||||
#define IP64_CONF_ETH_DRIVER ip64_tap_driver
|
||||
#define IP64_CONF_ETH_DRIVER ip64_tap_driver
|
||||
|
||||
/*
|
||||
* In contrast to the mandatory parameters above, IP64_CONF_DHCP is an
|
||||
* optional configuration parameter. The default value is set in ip64.h
|
||||
*/
|
||||
/* #define IP64_CONF_DHCP 1 */
|
||||
#endif /* IP64_CONF_H */
|
||||
|
|
|
@ -84,7 +84,7 @@ init(void)
|
|||
printf("ip64-eth-interface: init\n");
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
static int
|
||||
output(void)
|
||||
{
|
||||
int len, ret;
|
||||
|
@ -114,7 +114,7 @@ output(void)
|
|||
printf("Create request\n");
|
||||
len = ip64_arp_create_arp_request(ip64_packet_buffer,
|
||||
&ip64_packet_buffer[sizeof(struct ip64_eth_hdr)]);
|
||||
IP64_ETH_DRIVER.output(ip64_packet_buffer, len);
|
||||
return IP64_ETH_DRIVER.output(ip64_packet_buffer, len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -59,7 +59,7 @@ input_callback(void)
|
|||
/*PRINTF("SIN: %u\n", uip_len);*/
|
||||
if(uip_buf[0] == '!') {
|
||||
PRINTF("Got configuration message of type %c\n", uip_buf[1]);
|
||||
uip_len = 0;
|
||||
uip_clear_buf();
|
||||
#if 0
|
||||
if(uip_buf[1] == 'P') {
|
||||
uip_ipaddr_t prefix;
|
||||
|
@ -87,7 +87,7 @@ input_callback(void)
|
|||
slip_send();
|
||||
|
||||
}
|
||||
uip_len = 0;
|
||||
uip_clear_buf();
|
||||
} else {
|
||||
|
||||
/* Save the last sender received over SLIP to avoid bouncing the
|
||||
|
@ -101,7 +101,7 @@ input_callback(void)
|
|||
uip_len = len;
|
||||
/* PRINTF("send len %d\n", len); */
|
||||
} else {
|
||||
uip_len = 0;
|
||||
uip_clear_buf();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -115,7 +115,7 @@ init(void)
|
|||
slip_set_input_callback(input_callback);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
static int
|
||||
output(void)
|
||||
{
|
||||
int len;
|
||||
|
@ -138,8 +138,10 @@ output(void)
|
|||
memcpy(&uip_buf[UIP_LLH_LEN], ip64_packet_buffer, len);
|
||||
uip_len = len;
|
||||
slip_send();
|
||||
return len;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
const struct uip_fallback_interface ip64_slip_interface = {
|
||||
|
|
|
@ -188,7 +188,7 @@ ip64_init(void)
|
|||
|
||||
PRINTF("ip64_init\n");
|
||||
IP64_ETH_DRIVER.init();
|
||||
#if IP64_CONF_DHCP
|
||||
#if IP64_DHCP
|
||||
ip64_ipv4_dhcp_init();
|
||||
#endif /* IP64_CONF_DHCP */
|
||||
|
||||
|
@ -894,14 +894,14 @@ ip64_hostaddr_is_configured(void)
|
|||
static void
|
||||
interface_init(void)
|
||||
{
|
||||
IP64_CONF_UIP_FALLBACK_INTERFACE.init();
|
||||
IP64_UIP_FALLBACK_INTERFACE.init();
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
interface_output(void)
|
||||
{
|
||||
PRINTF("ip64: interface_output len %d\n", uip_len);
|
||||
IP64_CONF_UIP_FALLBACK_INTERFACE.output();
|
||||
IP64_UIP_FALLBACK_INTERFACE.output();
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
const struct uip_fallback_interface ip64_uip_fallback_interface = {
|
||||
|
|
|
@ -36,12 +36,12 @@
|
|||
|
||||
void ip64_init(void);
|
||||
int ip64_6to4(const uint8_t *ipv6packet, const uint16_t ipv6len,
|
||||
uint8_t *resultpacket);
|
||||
uint8_t *resultpacket);
|
||||
int ip64_4to6(const uint8_t *ipv4packet, const uint16_t ipv4len,
|
||||
uint8_t *resultpacket);
|
||||
uint8_t *resultpacket);
|
||||
|
||||
void ip64_set_ipv4_address(const uip_ip4addr_t *ipv4addr,
|
||||
const uip_ip4addr_t *netmask);
|
||||
const uip_ip4addr_t *netmask);
|
||||
void ip64_set_ipv6_address(const uip_ip6addr_t *ipv6addr);
|
||||
|
||||
const uip_ip4addr_t *ip64_get_hostaddr(void);
|
||||
|
@ -71,7 +71,18 @@ extern uint16_t ip64_packet_buffer_maxlen;
|
|||
#define IP64_INPUT IP64_CONF_INPUT
|
||||
#endif /* IP64_CONF_INPUT */
|
||||
|
||||
#ifndef IP64_CONF_UIP_FALLBACK_INTERFACE
|
||||
#error IP64_CONF_UIP_FALLBACK_INTERFACE must be #defined in ip64-conf.h
|
||||
#else /* IP64_CONF_UIP_FALLBACK_INTERFACE */
|
||||
#define IP64_UIP_FALLBACK_INTERFACE IP64_CONF_UIP_FALLBACK_INTERFACE
|
||||
#endif /* IP64_CONF_UIP_FALLBACK_INTERFACE */
|
||||
|
||||
#ifdef IP64_CONF_DHCP
|
||||
#define IP64_DHCP IP64_CONF_DHCP
|
||||
#else /* IP64_CONF_DHCP */
|
||||
/* Enable DHCP per default */
|
||||
#define IP64_DHCP 1
|
||||
#endif /* IP64_CONF_DHCP */
|
||||
|
||||
#endif /* IP64_H */
|
||||
|
||||
|
|
|
@ -229,7 +229,7 @@ time_exceeded(void)
|
|||
/* We don't send out ICMP errors for ICMP messages (unless they are pings). */
|
||||
if(ICMPBUF->proto == UIP_PROTO_ICMP &&
|
||||
ICMPBUF->type != ICMP_ECHO) {
|
||||
uip_len = 0;
|
||||
uip_clear_buf();
|
||||
return;
|
||||
}
|
||||
/* Copy fields from packet header into payload of this ICMP packet. */
|
||||
|
|
|
@ -436,6 +436,11 @@ uip_connect(const uip_ipaddr_t *ripaddr, uint16_t rport)
|
|||
conn->snd_nxt[2] = iss[2];
|
||||
conn->snd_nxt[3] = iss[3];
|
||||
|
||||
conn->rcv_nxt[0] = 0;
|
||||
conn->rcv_nxt[1] = 0;
|
||||
conn->rcv_nxt[2] = 0;
|
||||
conn->rcv_nxt[3] = 0;
|
||||
|
||||
conn->initialmss = conn->mss = UIP_TCP_MSS;
|
||||
|
||||
conn->len = 1; /* TCP length of the SYN is one. */
|
||||
|
@ -709,7 +714,7 @@ uip_process(uint8_t flag)
|
|||
}
|
||||
|
||||
/* Reset the length variables. */
|
||||
uip_len = 0;
|
||||
uip_clear_buf();
|
||||
uip_slen = 0;
|
||||
|
||||
#if UIP_TCP
|
||||
|
@ -1367,10 +1372,10 @@ uip_process(uint8_t flag)
|
|||
uip_connr->len = 1;
|
||||
|
||||
/* rcv_nxt should be the seqno from the incoming packet + 1. */
|
||||
uip_connr->rcv_nxt[3] = BUF->seqno[3];
|
||||
uip_connr->rcv_nxt[2] = BUF->seqno[2];
|
||||
uip_connr->rcv_nxt[1] = BUF->seqno[1];
|
||||
uip_connr->rcv_nxt[0] = BUF->seqno[0];
|
||||
uip_connr->rcv_nxt[1] = BUF->seqno[1];
|
||||
uip_connr->rcv_nxt[2] = BUF->seqno[2];
|
||||
uip_connr->rcv_nxt[3] = BUF->seqno[3];
|
||||
uip_add_rcv_nxt(1);
|
||||
|
||||
/* Parse the TCP MSS option, if present. */
|
||||
|
@ -1589,7 +1594,7 @@ uip_process(uint8_t flag)
|
|||
uip_add_rcv_nxt(1);
|
||||
uip_flags = UIP_CONNECTED | UIP_NEWDATA;
|
||||
uip_connr->len = 0;
|
||||
uip_len = 0;
|
||||
uip_clear_buf();
|
||||
uip_slen = 0;
|
||||
UIP_APPCALL();
|
||||
goto appsend;
|
||||
|
@ -1934,7 +1939,7 @@ uip_process(uint8_t flag)
|
|||
return;
|
||||
|
||||
drop:
|
||||
uip_len = 0;
|
||||
uip_clear_buf();
|
||||
uip_flags = 0;
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -284,10 +284,10 @@ uip_arp_arpin(void)
|
|||
{
|
||||
|
||||
if(uip_len < sizeof(struct arp_hdr)) {
|
||||
uip_len = 0;
|
||||
uip_clear_buf();
|
||||
return;
|
||||
}
|
||||
uip_len = 0;
|
||||
uip_clear_buf();
|
||||
|
||||
switch(BUF->opcode) {
|
||||
case UIP_HTONS(ARP_REQUEST):
|
||||
|
|
|
@ -1100,7 +1100,7 @@ icmp_input()
|
|||
uint16_t val;
|
||||
|
||||
#if UIP_CONF_IPV6_CHECKS
|
||||
if(!uip_is_addr_link_local(&UIP_IP_BUF->srcipaddr)) {
|
||||
if(!uip_is_addr_linklocal(&UIP_IP_BUF->srcipaddr)) {
|
||||
PRINTF("ROLL TM: ICMPv6 In, bad source ");
|
||||
PRINT6ADDR(&UIP_IP_BUF->srcipaddr);
|
||||
PRINTF(" to ");
|
||||
|
@ -1383,8 +1383,7 @@ out()
|
|||
|
||||
drop:
|
||||
uip_slen = 0;
|
||||
uip_len = 0;
|
||||
uip_ext_len = 0;
|
||||
uip_clear_buf();
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static uint8_t
|
||||
|
|
|
@ -81,7 +81,7 @@ mcast_fwd(void *p)
|
|||
uip_len = mcast_len;
|
||||
UIP_IP_BUF->ttl--;
|
||||
tcpip_output(NULL);
|
||||
uip_len = 0;
|
||||
uip_clear_buf();
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static uint8_t
|
||||
|
|
|
@ -52,9 +52,9 @@
|
|||
* FOR HC-06 COMPLIANCE TODO:
|
||||
* -Add compression options to UDP, currently only supports
|
||||
* both ports compressed or both ports elided
|
||||
*
|
||||
*
|
||||
* -Verify TC/FL compression works
|
||||
*
|
||||
*
|
||||
* -Add stateless multicast option
|
||||
*/
|
||||
|
||||
|
@ -317,7 +317,7 @@ set_packet_attrs()
|
|||
|
||||
/** Addresses contexts for IPHC. */
|
||||
#if SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS > 0
|
||||
static struct sicslowpan_addr_context
|
||||
static struct sicslowpan_addr_context
|
||||
addr_contexts[SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS];
|
||||
#endif
|
||||
|
||||
|
@ -381,7 +381,7 @@ addr_context_lookup_by_prefix(uip_ipaddr_t *ipaddr)
|
|||
static struct sicslowpan_addr_context*
|
||||
addr_context_lookup_by_number(uint8_t number)
|
||||
{
|
||||
/* Remove code to avoid warnings and save flash if no context is used */
|
||||
/* Remove code to avoid warnings and save flash if no context is used */
|
||||
#if SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS > 0
|
||||
int i;
|
||||
for(i = 0; i < SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS; i++) {
|
||||
|
@ -540,11 +540,11 @@ compress_hdr_hc06(linkaddr_t *link_destaddr)
|
|||
* We have to process both in the same time as the offset of traffic class
|
||||
* depends on the presence of version and flow label
|
||||
*/
|
||||
|
||||
|
||||
/* hc06 format of tc is ECN | DSCP , original is DSCP | ECN */
|
||||
tmp = (UIP_IP_BUF->vtc << 4) | (UIP_IP_BUF->tcflow >> 4);
|
||||
tmp = ((tmp & 0x03) << 6) | (tmp >> 2);
|
||||
|
||||
|
||||
if(((UIP_IP_BUF->tcflow & 0x0F) == 0) &&
|
||||
(UIP_IP_BUF->flow == 0)) {
|
||||
/* flow label can be compressed */
|
||||
|
@ -585,7 +585,7 @@ compress_hdr_hc06(linkaddr_t *link_destaddr)
|
|||
iphc0 |= SICSLOWPAN_IPHC_NH_C;
|
||||
}
|
||||
#endif /*UIP_CONF_UDP*/
|
||||
#ifdef SICSLOWPAN_NH_COMPRESSOR
|
||||
#ifdef SICSLOWPAN_NH_COMPRESSOR
|
||||
if(SICSLOWPAN_NH_COMPRESSOR.is_compressable(UIP_IP_BUF->proto)) {
|
||||
iphc0 |= SICSLOWPAN_IPHC_NH_C;
|
||||
}
|
||||
|
@ -627,7 +627,7 @@ compress_hdr_hc06(linkaddr_t *link_destaddr)
|
|||
!= NULL) {
|
||||
/* elide the prefix - indicate by CID and set context + SAC */
|
||||
PRINTF("IPHC: compressing src with context - setting CID & SAC ctx: %d\n",
|
||||
context->number);
|
||||
context->number);
|
||||
iphc1 |= SICSLOWPAN_IPHC_CID | SICSLOWPAN_IPHC_SAC;
|
||||
PACKETBUF_IPHC_BUF[2] |= context->number << 4;
|
||||
/* compession compare with this nodes address (source) */
|
||||
|
@ -635,10 +635,10 @@ compress_hdr_hc06(linkaddr_t *link_destaddr)
|
|||
iphc1 |= compress_addr_64(SICSLOWPAN_IPHC_SAM_BIT,
|
||||
&UIP_IP_BUF->srcipaddr, &uip_lladdr);
|
||||
/* No context found for this address */
|
||||
} else if(uip_is_addr_link_local(&UIP_IP_BUF->srcipaddr) &&
|
||||
UIP_IP_BUF->destipaddr.u16[1] == 0 &&
|
||||
UIP_IP_BUF->destipaddr.u16[2] == 0 &&
|
||||
UIP_IP_BUF->destipaddr.u16[3] == 0) {
|
||||
} else if(uip_is_addr_linklocal(&UIP_IP_BUF->srcipaddr) &&
|
||||
UIP_IP_BUF->destipaddr.u16[1] == 0 &&
|
||||
UIP_IP_BUF->destipaddr.u16[2] == 0 &&
|
||||
UIP_IP_BUF->destipaddr.u16[3] == 0) {
|
||||
iphc1 |= compress_addr_64(SICSLOWPAN_IPHC_SAM_BIT,
|
||||
&UIP_IP_BUF->srcipaddr, &uip_lladdr);
|
||||
} else {
|
||||
|
@ -684,12 +684,13 @@ compress_hdr_hc06(linkaddr_t *link_destaddr)
|
|||
/* compession compare with link adress (destination) */
|
||||
|
||||
iphc1 |= compress_addr_64(SICSLOWPAN_IPHC_DAM_BIT,
|
||||
&UIP_IP_BUF->destipaddr, (uip_lladdr_t *)link_destaddr);
|
||||
&UIP_IP_BUF->destipaddr,
|
||||
(uip_lladdr_t *)link_destaddr);
|
||||
/* No context found for this address */
|
||||
} else if(uip_is_addr_link_local(&UIP_IP_BUF->destipaddr) &&
|
||||
UIP_IP_BUF->destipaddr.u16[1] == 0 &&
|
||||
UIP_IP_BUF->destipaddr.u16[2] == 0 &&
|
||||
UIP_IP_BUF->destipaddr.u16[3] == 0) {
|
||||
} else if(uip_is_addr_linklocal(&UIP_IP_BUF->destipaddr) &&
|
||||
UIP_IP_BUF->destipaddr.u16[1] == 0 &&
|
||||
UIP_IP_BUF->destipaddr.u16[2] == 0 &&
|
||||
UIP_IP_BUF->destipaddr.u16[3] == 0) {
|
||||
iphc1 |= compress_addr_64(SICSLOWPAN_IPHC_DAM_BIT,
|
||||
&UIP_IP_BUF->destipaddr, (uip_lladdr_t *)link_destaddr);
|
||||
} else {
|
||||
|
@ -706,7 +707,7 @@ compress_hdr_hc06(linkaddr_t *link_destaddr)
|
|||
/* UDP header compression */
|
||||
if(UIP_IP_BUF->proto == UIP_PROTO_UDP) {
|
||||
PRINTF("IPHC: Uncompressed UDP ports on send side: %x, %x\n",
|
||||
UIP_HTONS(UIP_UDP_BUF->srcport), UIP_HTONS(UIP_UDP_BUF->destport));
|
||||
UIP_HTONS(UIP_UDP_BUF->srcport), UIP_HTONS(UIP_UDP_BUF->destport));
|
||||
/* Mask out the last 4 bits can be used as a mask */
|
||||
if(((UIP_HTONS(UIP_UDP_BUF->srcport) & 0xfff0) == SICSLOWPAN_UDP_4_BIT_PORT_MIN) &&
|
||||
((UIP_HTONS(UIP_UDP_BUF->destport) & 0xfff0) == SICSLOWPAN_UDP_4_BIT_PORT_MIN)) {
|
||||
|
@ -714,10 +715,10 @@ compress_hdr_hc06(linkaddr_t *link_destaddr)
|
|||
*hc06_ptr = SICSLOWPAN_NHC_UDP_CS_P_11;
|
||||
PRINTF("IPHC: remove 12 b of both source & dest with prefix 0xFOB\n");
|
||||
*(hc06_ptr + 1) =
|
||||
(uint8_t)((UIP_HTONS(UIP_UDP_BUF->srcport) -
|
||||
SICSLOWPAN_UDP_4_BIT_PORT_MIN) << 4) +
|
||||
(uint8_t)((UIP_HTONS(UIP_UDP_BUF->destport) -
|
||||
SICSLOWPAN_UDP_4_BIT_PORT_MIN));
|
||||
(uint8_t)((UIP_HTONS(UIP_UDP_BUF->srcport) -
|
||||
SICSLOWPAN_UDP_4_BIT_PORT_MIN) << 4) +
|
||||
(uint8_t)((UIP_HTONS(UIP_UDP_BUF->destport) -
|
||||
SICSLOWPAN_UDP_4_BIT_PORT_MIN));
|
||||
hc06_ptr += 2;
|
||||
} else if((UIP_HTONS(UIP_UDP_BUF->destport) & 0xff00) == SICSLOWPAN_UDP_8_BIT_PORT_MIN) {
|
||||
/* we can compress 8 bits of dest, leave source. */
|
||||
|
@ -725,16 +726,16 @@ compress_hdr_hc06(linkaddr_t *link_destaddr)
|
|||
PRINTF("IPHC: leave source, remove 8 bits of dest with prefix 0xF0\n");
|
||||
memcpy(hc06_ptr + 1, &UIP_UDP_BUF->srcport, 2);
|
||||
*(hc06_ptr + 3) =
|
||||
(uint8_t)((UIP_HTONS(UIP_UDP_BUF->destport) -
|
||||
SICSLOWPAN_UDP_8_BIT_PORT_MIN));
|
||||
(uint8_t)((UIP_HTONS(UIP_UDP_BUF->destport) -
|
||||
SICSLOWPAN_UDP_8_BIT_PORT_MIN));
|
||||
hc06_ptr += 4;
|
||||
} else if((UIP_HTONS(UIP_UDP_BUF->srcport) & 0xff00) == SICSLOWPAN_UDP_8_BIT_PORT_MIN) {
|
||||
/* we can compress 8 bits of src, leave dest. Copy compressed port */
|
||||
*hc06_ptr = SICSLOWPAN_NHC_UDP_CS_P_10;
|
||||
PRINTF("IPHC: remove 8 bits of source with prefix 0xF0, leave dest. hch: %i\n", *hc06_ptr);
|
||||
*(hc06_ptr + 1) =
|
||||
(uint8_t)((UIP_HTONS(UIP_UDP_BUF->srcport) -
|
||||
SICSLOWPAN_UDP_8_BIT_PORT_MIN));
|
||||
(uint8_t)((UIP_HTONS(UIP_UDP_BUF->srcport) -
|
||||
SICSLOWPAN_UDP_8_BIT_PORT_MIN));
|
||||
memcpy(hc06_ptr + 2, &UIP_UDP_BUF->destport, 2);
|
||||
hc06_ptr += 4;
|
||||
} else {
|
||||
|
@ -811,13 +812,13 @@ uncompress_hdr_hc06(uint16_t ip_len)
|
|||
SICSLOWPAN_IP_BUF->vtc = 0x60 | ((tmp >> 2) & 0x0f);
|
||||
/* ECN rolled down two steps + lowest DSCP bits at top two bits */
|
||||
SICSLOWPAN_IP_BUF->tcflow = ((tmp >> 2) & 0x30) | (tmp << 6) |
|
||||
(SICSLOWPAN_IP_BUF->tcflow & 0x0f);
|
||||
(SICSLOWPAN_IP_BUF->tcflow & 0x0f);
|
||||
} else {
|
||||
/* Traffic class is compressed (set version and no TC)*/
|
||||
SICSLOWPAN_IP_BUF->vtc = 0x60;
|
||||
/* highest flow label bits + ECN bits */
|
||||
SICSLOWPAN_IP_BUF->tcflow = (*hc06_ptr & 0x0F) |
|
||||
((*hc06_ptr >> 2) & 0x30);
|
||||
((*hc06_ptr >> 2) & 0x30);
|
||||
memcpy(&SICSLOWPAN_IP_BUF->flow, hc06_ptr + 1, 2);
|
||||
hc06_ptr += 3;
|
||||
}
|
||||
|
@ -908,14 +909,13 @@ uncompress_hdr_hc06(uint16_t ip_len)
|
|||
/* no multicast */
|
||||
/* Context based */
|
||||
if(iphc1 & SICSLOWPAN_IPHC_DAC) {
|
||||
uint8_t dci = (iphc1 & SICSLOWPAN_IPHC_CID) ?
|
||||
PACKETBUF_IPHC_BUF[2] & 0x0f : 0;
|
||||
uint8_t dci = (iphc1 & SICSLOWPAN_IPHC_CID) ? PACKETBUF_IPHC_BUF[2] & 0x0f : 0;
|
||||
context = addr_context_lookup_by_number(dci);
|
||||
|
||||
/* all valid cases below need the context! */
|
||||
if(context == NULL) {
|
||||
PRINTF("sicslowpan uncompress_hdr: error context not found\n");
|
||||
return;
|
||||
PRINTF("sicslowpan uncompress_hdr: error context not found\n");
|
||||
return;
|
||||
}
|
||||
uncompress_addr(&SICSLOWPAN_IP_BUF->destipaddr, context->prefix,
|
||||
unc_ctxconf[tmp],
|
||||
|
@ -939,56 +939,56 @@ uncompress_hdr_hc06(uint16_t ip_len)
|
|||
PRINTF("IPHC: Incoming header value: %i\n", *hc06_ptr);
|
||||
switch(*hc06_ptr & SICSLOWPAN_NHC_UDP_CS_P_11) {
|
||||
case SICSLOWPAN_NHC_UDP_CS_P_00:
|
||||
/* 1 byte for NHC, 4 byte for ports, 2 bytes chksum */
|
||||
memcpy(&SICSLOWPAN_UDP_BUF->srcport, hc06_ptr + 1, 2);
|
||||
memcpy(&SICSLOWPAN_UDP_BUF->destport, hc06_ptr + 3, 2);
|
||||
PRINTF("IPHC: Uncompressed UDP ports (ptr+5): %x, %x\n",
|
||||
UIP_HTONS(SICSLOWPAN_UDP_BUF->srcport), UIP_HTONS(SICSLOWPAN_UDP_BUF->destport));
|
||||
hc06_ptr += 5;
|
||||
break;
|
||||
/* 1 byte for NHC, 4 byte for ports, 2 bytes chksum */
|
||||
memcpy(&SICSLOWPAN_UDP_BUF->srcport, hc06_ptr + 1, 2);
|
||||
memcpy(&SICSLOWPAN_UDP_BUF->destport, hc06_ptr + 3, 2);
|
||||
PRINTF("IPHC: Uncompressed UDP ports (ptr+5): %x, %x\n",
|
||||
UIP_HTONS(SICSLOWPAN_UDP_BUF->srcport), UIP_HTONS(SICSLOWPAN_UDP_BUF->destport));
|
||||
hc06_ptr += 5;
|
||||
break;
|
||||
|
||||
case SICSLOWPAN_NHC_UDP_CS_P_01:
|
||||
/* 1 byte for NHC + source 16bit inline, dest = 0xF0 + 8 bit inline */
|
||||
PRINTF("IPHC: Decompressing destination\n");
|
||||
memcpy(&SICSLOWPAN_UDP_BUF->srcport, hc06_ptr + 1, 2);
|
||||
SICSLOWPAN_UDP_BUF->destport = UIP_HTONS(SICSLOWPAN_UDP_8_BIT_PORT_MIN + (*(hc06_ptr + 3)));
|
||||
PRINTF("IPHC: Uncompressed UDP ports (ptr+4): %x, %x\n",
|
||||
UIP_HTONS(SICSLOWPAN_UDP_BUF->srcport), UIP_HTONS(SICSLOWPAN_UDP_BUF->destport));
|
||||
hc06_ptr += 4;
|
||||
break;
|
||||
PRINTF("IPHC: Decompressing destination\n");
|
||||
memcpy(&SICSLOWPAN_UDP_BUF->srcport, hc06_ptr + 1, 2);
|
||||
SICSLOWPAN_UDP_BUF->destport = UIP_HTONS(SICSLOWPAN_UDP_8_BIT_PORT_MIN + (*(hc06_ptr + 3)));
|
||||
PRINTF("IPHC: Uncompressed UDP ports (ptr+4): %x, %x\n",
|
||||
UIP_HTONS(SICSLOWPAN_UDP_BUF->srcport), UIP_HTONS(SICSLOWPAN_UDP_BUF->destport));
|
||||
hc06_ptr += 4;
|
||||
break;
|
||||
|
||||
case SICSLOWPAN_NHC_UDP_CS_P_10:
|
||||
/* 1 byte for NHC + source = 0xF0 + 8bit inline, dest = 16 bit inline*/
|
||||
PRINTF("IPHC: Decompressing source\n");
|
||||
SICSLOWPAN_UDP_BUF->srcport = UIP_HTONS(SICSLOWPAN_UDP_8_BIT_PORT_MIN +
|
||||
(*(hc06_ptr + 1)));
|
||||
memcpy(&SICSLOWPAN_UDP_BUF->destport, hc06_ptr + 2, 2);
|
||||
PRINTF("IPHC: Uncompressed UDP ports (ptr+4): %x, %x\n",
|
||||
UIP_HTONS(SICSLOWPAN_UDP_BUF->srcport), UIP_HTONS(SICSLOWPAN_UDP_BUF->destport));
|
||||
hc06_ptr += 4;
|
||||
break;
|
||||
PRINTF("IPHC: Decompressing source\n");
|
||||
SICSLOWPAN_UDP_BUF->srcport = UIP_HTONS(SICSLOWPAN_UDP_8_BIT_PORT_MIN +
|
||||
(*(hc06_ptr + 1)));
|
||||
memcpy(&SICSLOWPAN_UDP_BUF->destport, hc06_ptr + 2, 2);
|
||||
PRINTF("IPHC: Uncompressed UDP ports (ptr+4): %x, %x\n",
|
||||
UIP_HTONS(SICSLOWPAN_UDP_BUF->srcport), UIP_HTONS(SICSLOWPAN_UDP_BUF->destport));
|
||||
hc06_ptr += 4;
|
||||
break;
|
||||
|
||||
case SICSLOWPAN_NHC_UDP_CS_P_11:
|
||||
/* 1 byte for NHC, 1 byte for ports */
|
||||
SICSLOWPAN_UDP_BUF->srcport = UIP_HTONS(SICSLOWPAN_UDP_4_BIT_PORT_MIN +
|
||||
(*(hc06_ptr + 1) >> 4));
|
||||
SICSLOWPAN_UDP_BUF->destport = UIP_HTONS(SICSLOWPAN_UDP_4_BIT_PORT_MIN +
|
||||
((*(hc06_ptr + 1)) & 0x0F));
|
||||
PRINTF("IPHC: Uncompressed UDP ports (ptr+2): %x, %x\n",
|
||||
UIP_HTONS(SICSLOWPAN_UDP_BUF->srcport), UIP_HTONS(SICSLOWPAN_UDP_BUF->destport));
|
||||
hc06_ptr += 2;
|
||||
break;
|
||||
/* 1 byte for NHC, 1 byte for ports */
|
||||
SICSLOWPAN_UDP_BUF->srcport = UIP_HTONS(SICSLOWPAN_UDP_4_BIT_PORT_MIN +
|
||||
(*(hc06_ptr + 1) >> 4));
|
||||
SICSLOWPAN_UDP_BUF->destport = UIP_HTONS(SICSLOWPAN_UDP_4_BIT_PORT_MIN +
|
||||
((*(hc06_ptr + 1)) & 0x0F));
|
||||
PRINTF("IPHC: Uncompressed UDP ports (ptr+2): %x, %x\n",
|
||||
UIP_HTONS(SICSLOWPAN_UDP_BUF->srcport), UIP_HTONS(SICSLOWPAN_UDP_BUF->destport));
|
||||
hc06_ptr += 2;
|
||||
break;
|
||||
|
||||
default:
|
||||
PRINTF("sicslowpan uncompress_hdr: error unsupported UDP compression\n");
|
||||
return;
|
||||
PRINTF("sicslowpan uncompress_hdr: error unsupported UDP compression\n");
|
||||
return;
|
||||
}
|
||||
if(!checksum_compressed) { /* has_checksum, default */
|
||||
memcpy(&SICSLOWPAN_UDP_BUF->udpchksum, hc06_ptr, 2);
|
||||
hc06_ptr += 2;
|
||||
PRINTF("IPHC: sicslowpan uncompress_hdr: checksum included\n");
|
||||
memcpy(&SICSLOWPAN_UDP_BUF->udpchksum, hc06_ptr, 2);
|
||||
hc06_ptr += 2;
|
||||
PRINTF("IPHC: sicslowpan uncompress_hdr: checksum included\n");
|
||||
} else {
|
||||
PRINTF("IPHC: sicslowpan uncompress_hdr: checksum *NOT* included\n");
|
||||
PRINTF("IPHC: sicslowpan uncompress_hdr: checksum *NOT* included\n");
|
||||
}
|
||||
uncomp_hdr_len += UIP_UDPH_LEN;
|
||||
}
|
||||
|
@ -1000,7 +1000,7 @@ uncompress_hdr_hc06(uint16_t ip_len)
|
|||
}
|
||||
|
||||
packetbuf_hdr_len = hc06_ptr - packetbuf_ptr;
|
||||
|
||||
|
||||
/* IP length field. */
|
||||
if(ip_len == 0) {
|
||||
int len = packetbuf_datalen() - packetbuf_hdr_len + uncomp_hdr_len - UIP_IPH_LEN;
|
||||
|
@ -1012,7 +1012,7 @@ uncompress_hdr_hc06(uint16_t ip_len)
|
|||
SICSLOWPAN_IP_BUF->len[0] = (ip_len - UIP_IPH_LEN) >> 8;
|
||||
SICSLOWPAN_IP_BUF->len[1] = (ip_len - UIP_IPH_LEN) & 0x00FF;
|
||||
}
|
||||
|
||||
|
||||
/* length field in UDP header */
|
||||
if(SICSLOWPAN_IP_BUF->proto == UIP_PROTO_UDP) {
|
||||
memcpy(&SICSLOWPAN_UDP_BUF->udplen, &SICSLOWPAN_IP_BUF->len[0], 2);
|
||||
|
@ -1046,12 +1046,14 @@ uncompress_hdr_hc06(uint16_t ip_len)
|
|||
* - Both src and dest interface ID are recoverable from lower layer
|
||||
* header
|
||||
* - Next header is either ICMP, UDP or TCP
|
||||
*
|
||||
* Moreover, if next header is UDP, we try to compress it using HC_UDP.
|
||||
* This is feasible is both ports are between F0B0 and F0B0 + 15\n\n
|
||||
* This is feasible is both ports are between F0B0 and F0B0 + 15.
|
||||
*
|
||||
*
|
||||
* Resulting header structure:
|
||||
* - For ICMP, TCP, non compressed UDP\n
|
||||
* HC1 encoding = 11111010 (UDP) 11111110 (TCP) 11111100 (ICMP)\n
|
||||
* - For ICMP, TCP, non compressed UDP\n
|
||||
* HC1 encoding = 11111010 (UDP) 11111110 (TCP) 11111100 (ICMP)\n
|
||||
* \verbatim
|
||||
* 1 2 3
|
||||
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
|
@ -1062,8 +1064,8 @@ uncompress_hdr_hc06(uint16_t ip_len)
|
|||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* \endverbatim
|
||||
*
|
||||
* - For compressed UDP
|
||||
* HC1 encoding = 11111011, HC_UDP encoding = 11100000\n
|
||||
* - For compressed UDP\n
|
||||
* HC1 encoding = 11111011, HC_UDP encoding = 11100000\n
|
||||
* \verbatim
|
||||
* 1 2 3
|
||||
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
|
@ -1087,9 +1089,9 @@ compress_hdr_hc1(linkaddr_t *link_destaddr)
|
|||
if(UIP_IP_BUF->vtc != 0x60 ||
|
||||
UIP_IP_BUF->tcflow != 0 ||
|
||||
UIP_IP_BUF->flow != 0 ||
|
||||
!uip_is_addr_link_local(&UIP_IP_BUF->srcipaddr) ||
|
||||
!uip_is_addr_linklocal(&UIP_IP_BUF->srcipaddr) ||
|
||||
!uip_is_addr_mac_addr_based(&UIP_IP_BUF->srcipaddr, &uip_lladdr) ||
|
||||
!uip_is_addr_link_local(&UIP_IP_BUF->destipaddr) ||
|
||||
!uip_is_addr_linklocal(&UIP_IP_BUF->destipaddr) ||
|
||||
!uip_is_addr_mac_addr_based(&UIP_IP_BUF->destipaddr,
|
||||
(uip_lladdr_t *)link_destaddr) ||
|
||||
(UIP_IP_BUF->proto != UIP_PROTO_ICMP6 &&
|
||||
|
@ -1144,7 +1146,7 @@ compress_hdr_hc1(linkaddr_t *link_destaddr)
|
|||
UIP_HTONS(UIP_UDP_BUF->destport) < SICSLOWPAN_UDP_PORT_MAX) {
|
||||
/* HC1 encoding */
|
||||
PACKETBUF_HC1_HC_UDP_PTR[PACKETBUF_HC1_HC_UDP_HC1_ENCODING] = 0xFB;
|
||||
|
||||
|
||||
/* HC_UDP encoding, ttl, src and dest ports, checksum */
|
||||
PACKETBUF_HC1_HC_UDP_PTR[PACKETBUF_HC1_HC_UDP_UDP_ENCODING] = 0xE0;
|
||||
PACKETBUF_HC1_HC_UDP_PTR[PACKETBUF_HC1_HC_UDP_TTL] = UIP_IP_BUF->ttl;
|
||||
|
@ -1192,17 +1194,17 @@ uncompress_hdr_hc1(uint16_t ip_len)
|
|||
SICSLOWPAN_IP_BUF->vtc = 0x60;
|
||||
SICSLOWPAN_IP_BUF->tcflow = 0;
|
||||
SICSLOWPAN_IP_BUF->flow = 0;
|
||||
|
||||
|
||||
/* src and dest ip addresses */
|
||||
uip_ip6addr(&SICSLOWPAN_IP_BUF->srcipaddr, 0xfe80, 0, 0, 0, 0, 0, 0, 0);
|
||||
uip_ds6_set_addr_iid(&SICSLOWPAN_IP_BUF->srcipaddr,
|
||||
(uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_SENDER));
|
||||
(uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_SENDER));
|
||||
uip_ip6addr(&SICSLOWPAN_IP_BUF->destipaddr, 0xfe80, 0, 0, 0, 0, 0, 0, 0);
|
||||
uip_ds6_set_addr_iid(&SICSLOWPAN_IP_BUF->destipaddr,
|
||||
(uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_RECEIVER));
|
||||
|
||||
(uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_RECEIVER));
|
||||
|
||||
uncomp_hdr_len += UIP_IPH_LEN;
|
||||
|
||||
|
||||
/* Next header field */
|
||||
switch(PACKETBUF_HC1_PTR[PACKETBUF_HC1_ENCODING] & 0x06) {
|
||||
case SICSLOWPAN_HC1_NH_ICMP6:
|
||||
|
@ -1248,7 +1250,7 @@ uncompress_hdr_hc1(uint16_t ip_len)
|
|||
/* this shouldn't happen, drop */
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/* IP length field. */
|
||||
if(ip_len == 0) {
|
||||
int len = packetbuf_datalen() - packetbuf_hdr_len + uncomp_hdr_len - UIP_IPH_LEN;
|
||||
|
@ -1363,8 +1365,10 @@ output(const uip_lladdr_t *localdest)
|
|||
/* The MAC address of the destination of the packet */
|
||||
linkaddr_t dest;
|
||||
|
||||
#if SICSLOWPAN_CONF_FRAG
|
||||
/* Number of bytes processed. */
|
||||
uint16_t processed_ip_out_len;
|
||||
#endif /* SICSLOWPAN_CONF_FRAG */
|
||||
|
||||
/* init */
|
||||
uncomp_hdr_len = 0;
|
||||
|
@ -1410,7 +1414,7 @@ output(const uip_lladdr_t *localdest)
|
|||
} else {
|
||||
linkaddr_copy(&dest, (const linkaddr_t *)localdest);
|
||||
}
|
||||
|
||||
|
||||
PRINTFO("sicslowpan output: sending packet len %d\n", uip_len);
|
||||
|
||||
if(uip_len >= COMPRESSION_THRESHOLD) {
|
||||
|
@ -1443,7 +1447,7 @@ output(const uip_lladdr_t *localdest)
|
|||
#else /* USE_FRAMER_HDRLEN */
|
||||
framer_hdrlen = 21;
|
||||
#endif /* USE_FRAMER_HDRLEN */
|
||||
max_payload = MAC_MAX_PAYLOAD - framer_hdrlen - NETSTACK_LLSEC.get_overhead();
|
||||
max_payload = MAC_MAX_PAYLOAD - framer_hdrlen;
|
||||
|
||||
if((int)uip_len - (int)uncomp_hdr_len > max_payload - (int)packetbuf_hdr_len) {
|
||||
#if SICSLOWPAN_CONF_FRAG
|
||||
|
@ -1455,7 +1459,7 @@ output(const uip_lladdr_t *localdest)
|
|||
* IPv6/HC1/HC06/HC_UDP dispatchs/headers.
|
||||
* The following fragments contain only the fragn dispatch.
|
||||
*/
|
||||
int estimated_fragments = ((int)uip_len) / ((int)MAC_MAX_PAYLOAD - SICSLOWPAN_FRAGN_HDR_LEN) + 1;
|
||||
int estimated_fragments = ((int)uip_len) / (max_payload - SICSLOWPAN_FRAGN_HDR_LEN) + 1;
|
||||
int freebuf = queuebuf_numfree() - 1;
|
||||
PRINTFO("uip_len: %d, fragments: %d, free bufs: %d\n", uip_len, estimated_fragments, freebuf);
|
||||
if(freebuf < estimated_fragments) {
|
||||
|
@ -1510,7 +1514,7 @@ output(const uip_lladdr_t *localdest)
|
|||
|
||||
/* set processed_ip_out_len to what we already sent from the IP payload*/
|
||||
processed_ip_out_len = packetbuf_payload_len + uncomp_hdr_len;
|
||||
|
||||
|
||||
/*
|
||||
* Create following fragments
|
||||
* Datagram tag is already in the buffer, we need to set the
|
||||
|
@ -1525,7 +1529,7 @@ output(const uip_lladdr_t *localdest)
|
|||
while(processed_ip_out_len < uip_len) {
|
||||
PRINTFO("sicslowpan output: fragment ");
|
||||
PACKETBUF_FRAG_PTR[PACKETBUF_FRAG_OFFSET] = processed_ip_out_len >> 3;
|
||||
|
||||
|
||||
/* Copy payload and send */
|
||||
if(uip_len - processed_ip_out_len < packetbuf_payload_len) {
|
||||
/* last fragment */
|
||||
|
@ -1575,7 +1579,6 @@ output(const uip_lladdr_t *localdest)
|
|||
|
||||
/*--------------------------------------------------------------------*/
|
||||
/** \brief Process a received 6lowpan packet.
|
||||
* \param r The MAC layer
|
||||
*
|
||||
* The 6lowpan packet is put in packetbuf by the MAC. If its a frag1 or
|
||||
* a non-fragmented packet we first uncompress the IP header. The
|
||||
|
@ -1593,8 +1596,8 @@ input(void)
|
|||
uint16_t frag_size = 0;
|
||||
/* offset of the fragment in the IP packet */
|
||||
uint8_t frag_offset = 0;
|
||||
uint8_t is_fragment = 0;
|
||||
#if SICSLOWPAN_CONF_FRAG
|
||||
uint8_t is_fragment = 0;
|
||||
/* tag of the fragment */
|
||||
uint16_t frag_tag = 0;
|
||||
uint8_t first_fragment = 0, last_fragment = 0;
|
||||
|
@ -1757,8 +1760,8 @@ input(void)
|
|||
PACKETBUF_HC1_PTR[PACKETBUF_HC1_DISPATCH]);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#if SICSLOWPAN_CONF_FRAG
|
||||
copypayload:
|
||||
#endif /*SICSLOWPAN_CONF_FRAG*/
|
||||
|
@ -1789,7 +1792,7 @@ input(void)
|
|||
}
|
||||
|
||||
memcpy((uint8_t *)SICSLOWPAN_IP_BUF + uncomp_hdr_len + (uint16_t)(frag_offset << 3), packetbuf_ptr + packetbuf_hdr_len, packetbuf_payload_len);
|
||||
|
||||
|
||||
/* update processed_ip_in_len if fragment, sicslowpan_len otherwise */
|
||||
|
||||
#if SICSLOWPAN_CONF_FRAG
|
||||
|
@ -1871,13 +1874,13 @@ sicslowpan_init(void)
|
|||
* The platform contiki-conf.h file can override this using e.g.
|
||||
* #define SICSLOWPAN_CONF_ADDR_CONTEXT_0 {addr_contexts[0].prefix[0]=0xbb;addr_contexts[0].prefix[1]=0xbb;}
|
||||
*/
|
||||
#if SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS > 0
|
||||
#if SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS > 0
|
||||
addr_contexts[0].used = 1;
|
||||
addr_contexts[0].number = 0;
|
||||
#ifdef SICSLOWPAN_CONF_ADDR_CONTEXT_0
|
||||
SICSLOWPAN_CONF_ADDR_CONTEXT_0;
|
||||
SICSLOWPAN_CONF_ADDR_CONTEXT_0;
|
||||
#else
|
||||
addr_contexts[0].prefix[0] = 0xaa;
|
||||
addr_contexts[0].prefix[0] = 0xaa;
|
||||
addr_contexts[0].prefix[1] = 0xaa;
|
||||
#endif
|
||||
#endif /* SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS > 0 */
|
||||
|
@ -1887,23 +1890,22 @@ sicslowpan_init(void)
|
|||
int i;
|
||||
for(i = 1; i < SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS; i++) {
|
||||
#ifdef SICSLOWPAN_CONF_ADDR_CONTEXT_1
|
||||
if (i==1) {
|
||||
addr_contexts[1].used = 1;
|
||||
addr_contexts[1].number = 1;
|
||||
SICSLOWPAN_CONF_ADDR_CONTEXT_1;
|
||||
if (i==1) {
|
||||
addr_contexts[1].used = 1;
|
||||
addr_contexts[1].number = 1;
|
||||
SICSLOWPAN_CONF_ADDR_CONTEXT_1;
|
||||
#ifdef SICSLOWPAN_CONF_ADDR_CONTEXT_2
|
||||
} else if (i==2) {
|
||||
addr_contexts[2].used = 1;
|
||||
addr_contexts[2].number = 2;
|
||||
SICSLOWPAN_CONF_ADDR_CONTEXT_2;
|
||||
addr_contexts[2].used = 1;
|
||||
addr_contexts[2].number = 2;
|
||||
SICSLOWPAN_CONF_ADDR_CONTEXT_2;
|
||||
#endif
|
||||
} else {
|
||||
addr_contexts[i].used = 0;
|
||||
}
|
||||
}
|
||||
#else
|
||||
addr_contexts[i].used = 0;
|
||||
#endif /* SICSLOWPAN_CONF_ADDR_CONTEXT_1 */
|
||||
|
||||
}
|
||||
}
|
||||
#endif /* SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS > 1 */
|
||||
|
|
|
@ -203,18 +203,18 @@ uip_ds6_link_neighbor_callback(int status, int numtx)
|
|||
#if UIP_DS6_LL_NUD
|
||||
/* From RFC4861, page 72, last paragraph of section 7.3.3:
|
||||
*
|
||||
* "In some cases, link-specific information may indicate that a path to
|
||||
* a neighbor has failed (e.g., the resetting of a virtual circuit). In
|
||||
* such cases, link-specific information may be used to purge Neighbor
|
||||
* Cache entries before the Neighbor Unreachability Detection would do
|
||||
* so. However, link-specific information MUST NOT be used to confirm
|
||||
* the reachability of a neighbor; such information does not provide
|
||||
* end-to-end confirmation between neighboring IP layers."
|
||||
* "In some cases, link-specific information may indicate that a path to
|
||||
* a neighbor has failed (e.g., the resetting of a virtual circuit). In
|
||||
* such cases, link-specific information may be used to purge Neighbor
|
||||
* Cache entries before the Neighbor Unreachability Detection would do
|
||||
* so. However, link-specific information MUST NOT be used to confirm
|
||||
* the reachability of a neighbor; such information does not provide
|
||||
* end-to-end confirmation between neighboring IP layers."
|
||||
*
|
||||
* However, we assume that receiving a link layer ack ensures the delivery
|
||||
* of the transmitted packed to the IP stack of the neighbour. This is a
|
||||
* fair assumption and allows battery powered nodes save some battery by
|
||||
* not re-testing the state of a neighbour periodically if it
|
||||
* of the transmitted packed to the IP stack of the neighbour. This is a
|
||||
* fair assumption and allows battery powered nodes save some battery by
|
||||
* not re-testing the state of a neighbour periodically if it
|
||||
* acknowledges link packets. */
|
||||
if(status == MAC_TX_OK) {
|
||||
uip_ds6_nbr_t *nbr;
|
||||
|
@ -231,10 +231,10 @@ uip_ds6_link_neighbor_callback(int status, int numtx)
|
|||
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** Periodic processing on neighbors */
|
||||
void
|
||||
uip_ds6_neighbor_periodic(void)
|
||||
{
|
||||
/* Periodic processing on neighbors */
|
||||
uip_ds6_nbr_t *nbr = nbr_table_head(ds6_neighbors);
|
||||
while(nbr != NULL) {
|
||||
switch(nbr->state) {
|
||||
|
|
|
@ -47,12 +47,22 @@
|
|||
|
||||
#include <string.h>
|
||||
|
||||
/* A configurable function called after adding a new neighbor as next hop */
|
||||
#ifdef NETSTACK_CONF_ROUTING_NEIGHBOR_ADDED_CALLBACK
|
||||
void NETSTACK_CONF_ROUTING_NEIGHBOR_ADDED_CALLBACK(const linkaddr_t *addr);
|
||||
#endif /* NETSTACK_CONF_ROUTING_NEIGHBOR_ADDED_CALLBACK */
|
||||
|
||||
/* A configurable function called after removing a next hop neighbor */
|
||||
#ifdef NETSTACK_CONF_ROUTING_NEIGHBOR_REMOVED_CALLBACK
|
||||
void NETSTACK_CONF_ROUTING_NEIGHBOR_REMOVED_CALLBACK(const linkaddr_t *addr);
|
||||
#endif /* NETSTACK_CONF_ROUTING_NEIGHBOR_REMOVED_CALLBACK */
|
||||
|
||||
/* The nbr_routes holds a neighbor table to be able to maintain
|
||||
information about what routes go through what neighbor. This
|
||||
neighbor table is registered with the central nbr-table repository
|
||||
so that it will be maintained along with the rest of the neighbor
|
||||
tables in the system. */
|
||||
NBR_TABLE(struct uip_ds6_route_neighbor_routes, nbr_routes);
|
||||
NBR_TABLE_GLOBAL(struct uip_ds6_route_neighbor_routes, nbr_routes);
|
||||
MEMB(neighborroutememb, struct uip_ds6_route_neighbor_route, UIP_DS6_ROUTE_NB);
|
||||
|
||||
/* Each route is repressented by a uip_ds6_route_t structure and
|
||||
|
@ -335,6 +345,9 @@ uip_ds6_route_add(uip_ipaddr_t *ipaddr, uint8_t length,
|
|||
return NULL;
|
||||
}
|
||||
LIST_STRUCT_INIT(routes, route_list);
|
||||
#ifdef NETSTACK_CONF_ROUTING_NEIGHBOR_ADDED_CALLBACK
|
||||
NETSTACK_CONF_ROUTING_NEIGHBOR_ADDED_CALLBACK((const linkaddr_t *)nexthop_lladdr);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Allocate a routing entry and populate it. */
|
||||
|
@ -367,6 +380,9 @@ uip_ds6_route_add(uip_ipaddr_t *ipaddr, uint8_t length,
|
|||
num_routes++;
|
||||
|
||||
PRINTF("uip_ds6_route_add num %d\n", num_routes);
|
||||
|
||||
/* lock this entry so that nexthop is not removed */
|
||||
nbr_table_lock(nbr_routes, routes);
|
||||
}
|
||||
|
||||
uip_ipaddr_copy(&(r->ipaddr), ipaddr);
|
||||
|
@ -423,9 +439,19 @@ uip_ds6_route_rm(uip_ds6_route_t *route)
|
|||
list_remove(route->neighbor_routes->route_list, neighbor_route);
|
||||
if(list_head(route->neighbor_routes->route_list) == NULL) {
|
||||
/* If this was the only route using this neighbor, remove the
|
||||
neibhor from the table */
|
||||
neighbor from the table - this implicitly unlocks nexthop */
|
||||
#if (DEBUG) & DEBUG_ANNOTATE
|
||||
uip_ipaddr_t *nexthop = uip_ds6_route_nexthop(route);
|
||||
if(nexthop != NULL) {
|
||||
ANNOTATE("#L %u 0\n", nexthop->u8[sizeof(uip_ipaddr_t) - 1]);
|
||||
}
|
||||
#endif /* (DEBUG) & DEBUG_ANNOTATE */
|
||||
PRINTF("uip_ds6_route_rm: removing neighbor too\n");
|
||||
nbr_table_remove(nbr_routes, route->neighbor_routes->route_list);
|
||||
#ifdef NETSTACK_CONF_ROUTING_NEIGHBOR_REMOVED_CALLBACK
|
||||
NETSTACK_CONF_ROUTING_NEIGHBOR_REMOVED_CALLBACK(
|
||||
(const linkaddr_t *)nbr_table_get_lladdr(nbr_routes, route->neighbor_routes->route_list));
|
||||
#endif
|
||||
}
|
||||
memb_free(&routememb, route);
|
||||
memb_free(&neighborroutememb, neighbor_route);
|
||||
|
@ -437,25 +463,6 @@ uip_ds6_route_rm(uip_ds6_route_t *route)
|
|||
#if UIP_DS6_NOTIFICATIONS
|
||||
call_route_callback(UIP_DS6_NOTIFICATION_ROUTE_RM,
|
||||
&route->ipaddr, uip_ds6_route_nexthop(route));
|
||||
#endif
|
||||
#if 0 //(DEBUG & DEBUG_ANNOTATE) == DEBUG_ANNOTATE
|
||||
/* we need to check if this was the last route towards "nexthop" */
|
||||
/* if so - remove that link (annotation) */
|
||||
uip_ds6_route_t *r;
|
||||
for(r = uip_ds6_route_head();
|
||||
r != NULL;
|
||||
r = uip_ds6_route_next(r)) {
|
||||
uip_ipaddr_t *nextr, *nextroute;
|
||||
nextr = uip_ds6_route_nexthop(r);
|
||||
nextroute = uip_ds6_route_nexthop(route);
|
||||
if(nextr != NULL &&
|
||||
nextroute != NULL &&
|
||||
uip_ipaddr_cmp(nextr, nextroute)) {
|
||||
/* we found another link using the specific nexthop, so keep the #L */
|
||||
return;
|
||||
}
|
||||
}
|
||||
ANNOTATE("#L %u 0\n", uip_ds6_route_nexthop(route)->u8[sizeof(uip_ipaddr_t) - 1]);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -40,9 +40,13 @@
|
|||
#ifndef UIP_DS6_ROUTE_H
|
||||
#define UIP_DS6_ROUTE_H
|
||||
|
||||
#include "net/ip/uip.h"
|
||||
#include "net/nbr-table.h"
|
||||
#include "sys/stimer.h"
|
||||
#include "lib/list.h"
|
||||
|
||||
NBR_TABLE_DECLARE(nbr_routes);
|
||||
|
||||
void uip_ds6_route_init(void);
|
||||
|
||||
#ifndef UIP_CONF_UIP_DS6_NOTIFICATIONS
|
||||
|
|
|
@ -53,23 +53,23 @@
|
|||
#define DEBUG DEBUG_NONE
|
||||
#include "net/ip/uip-debug.h"
|
||||
|
||||
struct etimer uip_ds6_timer_periodic; /** \brief Timer for maintenance of data structures */
|
||||
struct etimer uip_ds6_timer_periodic; /**< Timer for maintenance of data structures */
|
||||
|
||||
#if UIP_CONF_ROUTER
|
||||
struct stimer uip_ds6_timer_ra; /** \brief RA timer, to schedule RA sending */
|
||||
struct stimer uip_ds6_timer_ra; /**< RA timer, to schedule RA sending */
|
||||
#if UIP_ND6_SEND_RA
|
||||
static uint8_t racount; /** \brief number of RA already sent */
|
||||
static uint16_t rand_time; /** \brief random time value for timers */
|
||||
static uint8_t racount; /**< number of RA already sent */
|
||||
static uint16_t rand_time; /**< random time value for timers */
|
||||
#endif
|
||||
#else /* UIP_CONF_ROUTER */
|
||||
struct etimer uip_ds6_timer_rs; /** \brief RS timer, to schedule RS sending */
|
||||
static uint8_t rscount; /** \brief number of rs already sent */
|
||||
struct etimer uip_ds6_timer_rs; /**< RS timer, to schedule RS sending */
|
||||
static uint8_t rscount; /**< number of rs already sent */
|
||||
#endif /* UIP_CONF_ROUTER */
|
||||
|
||||
/** \name "DS6" Data structures */
|
||||
/** @{ */
|
||||
uip_ds6_netif_t uip_ds6_if; /** \brief The single interface */
|
||||
uip_ds6_prefix_t uip_ds6_prefix_list[UIP_DS6_PREFIX_NB]; /** \brief Prefix list */
|
||||
uip_ds6_netif_t uip_ds6_if; /**< The single interface */
|
||||
uip_ds6_prefix_t uip_ds6_prefix_list[UIP_DS6_PREFIX_NB]; /**< Prefix list */
|
||||
|
||||
/* Used by Cooja to enable extraction of addresses from memory.*/
|
||||
uint8_t uip_ds6_addr_size;
|
||||
|
@ -83,7 +83,9 @@ static uip_ipaddr_t loc_fipaddr;
|
|||
/* Pointers used in this file */
|
||||
static uip_ds6_addr_t *locaddr;
|
||||
static uip_ds6_maddr_t *locmaddr;
|
||||
#if UIP_DS6_AADDR_NB
|
||||
static uip_ds6_aaddr_t *locaaddr;
|
||||
#endif /* UIP_DS6_AADDR_NB */
|
||||
static uip_ds6_prefix_t *locprefix;
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
@ -274,7 +276,8 @@ uip_ds6_prefix_add(uip_ipaddr_t *ipaddr, uint8_t ipaddrlen,
|
|||
}
|
||||
PRINTF("Adding prefix ");
|
||||
PRINT6ADDR(&locprefix->ipaddr);
|
||||
PRINTF("length %u, vlifetime%lu\n", ipaddrlen, interval);
|
||||
PRINTF("length %u, vlifetime %lu\n", ipaddrlen, interval);
|
||||
return locprefix;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
@ -294,9 +297,9 @@ uip_ds6_prefix_t *
|
|||
uip_ds6_prefix_lookup(uip_ipaddr_t *ipaddr, uint8_t ipaddrlen)
|
||||
{
|
||||
if(uip_ds6_list_loop((uip_ds6_element_t *)uip_ds6_prefix_list,
|
||||
UIP_DS6_PREFIX_NB, sizeof(uip_ds6_prefix_t),
|
||||
ipaddr, ipaddrlen,
|
||||
(uip_ds6_element_t **)&locprefix) == FOUND) {
|
||||
UIP_DS6_PREFIX_NB, sizeof(uip_ds6_prefix_t),
|
||||
ipaddr, ipaddrlen,
|
||||
(uip_ds6_element_t **)&locprefix) == FOUND) {
|
||||
return locprefix;
|
||||
}
|
||||
return NULL;
|
||||
|
@ -388,7 +391,7 @@ uip_ds6_get_link_local(int8_t state)
|
|||
for(locaddr = uip_ds6_if.addr_list;
|
||||
locaddr < uip_ds6_if.addr_list + UIP_DS6_ADDR_NB; locaddr++) {
|
||||
if(locaddr->isused && (state == -1 || locaddr->state == state)
|
||||
&& (uip_is_addr_link_local(&locaddr->ipaddr))) {
|
||||
&& (uip_is_addr_linklocal(&locaddr->ipaddr))) {
|
||||
return locaddr;
|
||||
}
|
||||
}
|
||||
|
@ -407,7 +410,7 @@ uip_ds6_get_global(int8_t state)
|
|||
for(locaddr = uip_ds6_if.addr_list;
|
||||
locaddr < uip_ds6_if.addr_list + UIP_DS6_ADDR_NB; locaddr++) {
|
||||
if(locaddr->isused && (state == -1 || locaddr->state == state)
|
||||
&& !(uip_is_addr_link_local(&locaddr->ipaddr))) {
|
||||
&& !(uip_is_addr_linklocal(&locaddr->ipaddr))) {
|
||||
return locaddr;
|
||||
}
|
||||
}
|
||||
|
@ -457,6 +460,7 @@ uip_ds6_maddr_lookup(const uip_ipaddr_t *ipaddr)
|
|||
uip_ds6_aaddr_t *
|
||||
uip_ds6_aaddr_add(uip_ipaddr_t *ipaddr)
|
||||
{
|
||||
#if UIP_DS6_AADDR_NB
|
||||
if(uip_ds6_list_loop
|
||||
((uip_ds6_element_t *)uip_ds6_if.aaddr_list, UIP_DS6_AADDR_NB,
|
||||
sizeof(uip_ds6_aaddr_t), ipaddr, 128,
|
||||
|
@ -465,6 +469,7 @@ uip_ds6_aaddr_add(uip_ipaddr_t *ipaddr)
|
|||
uip_ipaddr_copy(&locaaddr->ipaddr, ipaddr);
|
||||
return locaaddr;
|
||||
}
|
||||
#endif /* UIP_DS6_AADDR_NB */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -482,11 +487,13 @@ uip_ds6_aaddr_rm(uip_ds6_aaddr_t *aaddr)
|
|||
uip_ds6_aaddr_t *
|
||||
uip_ds6_aaddr_lookup(uip_ipaddr_t *ipaddr)
|
||||
{
|
||||
#if UIP_DS6_AADDR_NB
|
||||
if(uip_ds6_list_loop((uip_ds6_element_t *)uip_ds6_if.aaddr_list,
|
||||
UIP_DS6_AADDR_NB, sizeof(uip_ds6_aaddr_t), ipaddr, 128,
|
||||
(uip_ds6_element_t **)&locaaddr) == FOUND) {
|
||||
UIP_DS6_AADDR_NB, sizeof(uip_ds6_aaddr_t), ipaddr, 128,
|
||||
(uip_ds6_element_t **)&locaaddr) == FOUND) {
|
||||
return locaaddr;
|
||||
}
|
||||
#endif /* UIP_DS6_AADDR_NB */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -498,13 +505,13 @@ uip_ds6_select_src(uip_ipaddr_t *src, uip_ipaddr_t *dst)
|
|||
uint8_t n = 0;
|
||||
uip_ds6_addr_t *matchaddr = NULL;
|
||||
|
||||
if(!uip_is_addr_link_local(dst) && !uip_is_addr_mcast(dst)) {
|
||||
if(!uip_is_addr_linklocal(dst) && !uip_is_addr_mcast(dst)) {
|
||||
/* find longest match */
|
||||
for(locaddr = uip_ds6_if.addr_list;
|
||||
locaddr < uip_ds6_if.addr_list + UIP_DS6_ADDR_NB; locaddr++) {
|
||||
/* Only preferred global (not link-local) addresses */
|
||||
if(locaddr->isused && locaddr->state == ADDR_PREFERRED &&
|
||||
!uip_is_addr_link_local(&locaddr->ipaddr)) {
|
||||
!uip_is_addr_linklocal(&locaddr->ipaddr)) {
|
||||
n = get_match_length(dst, &locaddr->ipaddr);
|
||||
if(n >= best) {
|
||||
best = n;
|
||||
|
@ -591,7 +598,7 @@ uip_ds6_dad(uip_ds6_addr_t *addr)
|
|||
* If we arrive here it means DAD succeeded, otherwise the dad process
|
||||
* would have been interrupted in ds6_dad_ns/na_input
|
||||
*/
|
||||
PRINTF("DAD succeeded, ipaddr:");
|
||||
PRINTF("DAD succeeded, ipaddr: ");
|
||||
PRINT6ADDR(&addr->ipaddr);
|
||||
PRINTF("\n");
|
||||
|
||||
|
@ -607,7 +614,7 @@ uip_ds6_dad(uip_ds6_addr_t *addr)
|
|||
int
|
||||
uip_ds6_dad_failed(uip_ds6_addr_t *addr)
|
||||
{
|
||||
if(uip_is_addr_link_local(&addr->ipaddr)) {
|
||||
if(uip_is_addr_linklocal(&addr->ipaddr)) {
|
||||
PRINTF("Contiki shutdown, DAD for link local address failed\n");
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -216,9 +216,15 @@ typedef struct uip_ds6_netif {
|
|||
uint32_t reachable_time; /* in msec */
|
||||
uint32_t retrans_timer; /* in msec */
|
||||
uint8_t maxdadns;
|
||||
#if UIP_DS6_ADDR_NB
|
||||
uip_ds6_addr_t addr_list[UIP_DS6_ADDR_NB];
|
||||
#endif /* UIP_DS6_ADDR_NB */
|
||||
#if UIP_DS6_AADDR_NB
|
||||
uip_ds6_aaddr_t aaddr_list[UIP_DS6_AADDR_NB];
|
||||
#endif /* UIP_DS6_AADDR_NB */
|
||||
#if UIP_DS6_MADDR_NB
|
||||
uip_ds6_maddr_t maddr_list[UIP_DS6_MADDR_NB];
|
||||
#endif /* UIP_DS6_MADDR_NB */
|
||||
} uip_ds6_netif_t;
|
||||
|
||||
/** \brief Generic type for a DS6, to use a common loop though all DS */
|
||||
|
@ -276,6 +282,7 @@ uint8_t uip_ds6_is_addr_onlink(uip_ipaddr_t *ipaddr);
|
|||
|
||||
/** \name Unicast address list basic routines */
|
||||
/** @{ */
|
||||
/** \brief Add a unicast address to the interface */
|
||||
uip_ds6_addr_t *uip_ds6_addr_add(uip_ipaddr_t *ipaddr,
|
||||
unsigned long vlifetime, uint8_t type);
|
||||
void uip_ds6_addr_rm(uip_ds6_addr_t *addr);
|
||||
|
|
|
@ -128,9 +128,9 @@ echo_request_input(void)
|
|||
* headers in the request otherwise we need to remove the extension
|
||||
* headers and change a few fields
|
||||
*/
|
||||
PRINTF("Received Echo Request from");
|
||||
PRINTF("Received Echo Request from ");
|
||||
PRINT6ADDR(&UIP_IP_BUF->srcipaddr);
|
||||
PRINTF("to");
|
||||
PRINTF(" to ");
|
||||
PRINT6ADDR(&UIP_IP_BUF->destipaddr);
|
||||
PRINTF("\n");
|
||||
|
||||
|
@ -195,9 +195,9 @@ echo_request_input(void)
|
|||
UIP_ICMP_BUF->icmpchksum = 0;
|
||||
UIP_ICMP_BUF->icmpchksum = ~uip_icmp6chksum();
|
||||
|
||||
PRINTF("Sending Echo Reply to");
|
||||
PRINTF("Sending Echo Reply to ");
|
||||
PRINT6ADDR(&UIP_IP_BUF->destipaddr);
|
||||
PRINTF("from");
|
||||
PRINTF(" from ");
|
||||
PRINT6ADDR(&UIP_IP_BUF->srcipaddr);
|
||||
PRINTF("\n");
|
||||
UIP_STAT(++uip_stat.icmp.sent);
|
||||
|
@ -210,12 +210,12 @@ uip_icmp6_error_output(uint8_t type, uint8_t code, uint32_t param) {
|
|||
/* check if originating packet is not an ICMP error*/
|
||||
if (uip_ext_len) {
|
||||
if(UIP_EXT_BUF->next == UIP_PROTO_ICMP6 && UIP_ICMP_BUF->type < 128){
|
||||
uip_len = 0;
|
||||
uip_clear_buf();
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if(UIP_IP_BUF->proto == UIP_PROTO_ICMP6 && UIP_ICMP_BUF->type < 128){
|
||||
uip_len = 0;
|
||||
uip_clear_buf();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -250,7 +250,7 @@ uip_icmp6_error_output(uint8_t type, uint8_t code, uint32_t param) {
|
|||
/* the source should not be unspecified nor multicast, the check for
|
||||
multicast is done in uip_process */
|
||||
if(uip_is_addr_unspecified(&UIP_IP_BUF->srcipaddr)){
|
||||
uip_len = 0;
|
||||
uip_clear_buf();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -260,7 +260,7 @@ uip_icmp6_error_output(uint8_t type, uint8_t code, uint32_t param) {
|
|||
if(type == ICMP6_PARAM_PROB && code == ICMP6_PARAMPROB_OPTION){
|
||||
uip_ds6_select_src(&UIP_IP_BUF->srcipaddr, &tmp_ipaddr);
|
||||
} else {
|
||||
uip_len = 0;
|
||||
uip_clear_buf();
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
|
@ -282,9 +282,9 @@ uip_icmp6_error_output(uint8_t type, uint8_t code, uint32_t param) {
|
|||
|
||||
UIP_STAT(++uip_stat.icmp.sent);
|
||||
|
||||
PRINTF("Sending ICMPv6 ERROR message type %d code %d to", type, code);
|
||||
PRINTF("Sending ICMPv6 ERROR message type %d code %d to ", type, code);
|
||||
PRINT6ADDR(&UIP_IP_BUF->destipaddr);
|
||||
PRINTF("from");
|
||||
PRINTF(" from ");
|
||||
PRINT6ADDR(&UIP_IP_BUF->srcipaddr);
|
||||
PRINTF("\n");
|
||||
return;
|
||||
|
@ -385,7 +385,7 @@ echo_reply_input(void)
|
|||
}
|
||||
}
|
||||
|
||||
uip_len = 0;
|
||||
uip_clear_buf();
|
||||
return;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
|
|
@ -93,7 +93,7 @@ void uip_log(char *msg);
|
|||
/** \name Pointers to the header structures.
|
||||
* All pointers except UIP_IP_BUF depend on uip_ext_len, which at
|
||||
* packet reception, is the total length of the extension headers.
|
||||
*
|
||||
*
|
||||
* The pointer to ND6 options header also depends on nd6_opt_offset,
|
||||
* which we set in each function.
|
||||
*
|
||||
|
@ -127,11 +127,23 @@ static uip_ds6_addr_t *addr; /** Pointer to an interface address */
|
|||
#if !UIP_CONF_ROUTER // TBD see if we move it to ra_input
|
||||
static uip_nd6_opt_prefix_info *nd6_opt_prefix_info; /** Pointer to prefix information option in uip_buf */
|
||||
static uip_ipaddr_t ipaddr;
|
||||
#endif
|
||||
#if (!UIP_CONF_ROUTER || UIP_ND6_SEND_RA)
|
||||
static uip_ds6_prefix_t *prefix; /** Pointer to a prefix list entry */
|
||||
#endif
|
||||
|
||||
#if UIP_ND6_SEND_NA || UIP_ND6_SEND_RA || !UIP_CONF_ROUTER
|
||||
/*------------------------------------------------------------------*/
|
||||
/* create a llao */
|
||||
/* Copy link-layer address from LLAO option to a word-aligned uip_lladdr_t */
|
||||
static void
|
||||
extract_lladdr_aligned(uip_lladdr_t *dest) {
|
||||
if(dest != NULL && nd6_opt_llao != NULL) {
|
||||
memcpy(dest, &nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], UIP_LLADDR_LEN);
|
||||
}
|
||||
}
|
||||
#endif /* UIP_ND6_SEND_NA || UIP_ND6_SEND_RA || !UIP_CONF_ROUTER */
|
||||
/*------------------------------------------------------------------*/
|
||||
/* create a llao */
|
||||
static void
|
||||
create_llao(uint8_t *llao, uint8_t type) {
|
||||
llao[UIP_ND6_OPT_TYPE_OFFSET] = type;
|
||||
|
@ -153,7 +165,7 @@ ns_input(void)
|
|||
PRINT6ADDR(&UIP_IP_BUF->srcipaddr);
|
||||
PRINTF(" to ");
|
||||
PRINT6ADDR(&UIP_IP_BUF->destipaddr);
|
||||
PRINTF(" with target address");
|
||||
PRINTF(" with target address ");
|
||||
PRINT6ADDR((uip_ipaddr_t *) (&UIP_ND6_NS_BUF->tgtipaddr));
|
||||
PRINTF("\n");
|
||||
UIP_STAT(++uip_stat.nd6.recv);
|
||||
|
@ -189,15 +201,14 @@ ns_input(void)
|
|||
#endif /*UIP_CONF_IPV6_CHECKS */
|
||||
nbr = uip_ds6_nbr_lookup(&UIP_IP_BUF->srcipaddr);
|
||||
if(nbr == NULL) {
|
||||
uip_ds6_nbr_add(&UIP_IP_BUF->srcipaddr,
|
||||
(uip_lladdr_t *)&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET],
|
||||
0, NBR_STALE);
|
||||
uip_lladdr_t lladdr_aligned;
|
||||
extract_lladdr_aligned(&lladdr_aligned);
|
||||
uip_ds6_nbr_add(&UIP_IP_BUF->srcipaddr, &lladdr_aligned, 0, NBR_STALE);
|
||||
} else {
|
||||
uip_lladdr_t *lladdr = (uip_lladdr_t *)uip_ds6_nbr_get_ll(nbr);
|
||||
if(memcmp(&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET],
|
||||
lladdr, UIP_LLADDR_LEN) != 0) {
|
||||
memcpy(lladdr, &nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET],
|
||||
UIP_LLADDR_LEN);
|
||||
lladdr, UIP_LLADDR_LEN) != 0) {
|
||||
memcpy(lladdr, &nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], UIP_LLADDR_LEN);
|
||||
nbr->state = NBR_STALE;
|
||||
} else {
|
||||
if(nbr->state == NBR_INCOMPLETE) {
|
||||
|
@ -321,7 +332,7 @@ create_na:
|
|||
return;
|
||||
|
||||
discard:
|
||||
uip_len = 0;
|
||||
uip_clear_buf();
|
||||
return;
|
||||
}
|
||||
#endif /* UIP_ND6_SEND_NA */
|
||||
|
@ -350,7 +361,7 @@ uip_nd6_ns_output(uip_ipaddr_t * src, uip_ipaddr_t * dest, uip_ipaddr_t * tgt)
|
|||
UIP_IP_BUF->len[0] = 0; /* length will not be more than 255 */
|
||||
/*
|
||||
* check if we add a SLLAO option: for DAD, MUST NOT, for NUD, MAY
|
||||
* (here yes), for Address resolution , MUST
|
||||
* (here yes), for Address resolution , MUST
|
||||
*/
|
||||
if(!(uip_ds6_is_my_addr(tgt))) {
|
||||
if(src != NULL) {
|
||||
|
@ -360,14 +371,14 @@ uip_nd6_ns_output(uip_ipaddr_t * src, uip_ipaddr_t * dest, uip_ipaddr_t * tgt)
|
|||
}
|
||||
if (uip_is_addr_unspecified(&UIP_IP_BUF->srcipaddr)) {
|
||||
PRINTF("Dropping NS due to no suitable source address\n");
|
||||
uip_len = 0;
|
||||
uip_clear_buf();
|
||||
return;
|
||||
}
|
||||
UIP_IP_BUF->len[1] =
|
||||
UIP_ICMPH_LEN + UIP_ND6_NS_LEN + UIP_ND6_OPT_LLAO_LEN;
|
||||
|
||||
create_llao(&uip_buf[uip_l2_l3_icmp_hdr_len + UIP_ND6_NS_LEN],
|
||||
UIP_ND6_OPT_SLLAO);
|
||||
UIP_ND6_OPT_SLLAO);
|
||||
|
||||
uip_len =
|
||||
UIP_IPH_LEN + UIP_ICMPH_LEN + UIP_ND6_NS_LEN + UIP_ND6_OPT_LLAO_LEN;
|
||||
|
@ -381,11 +392,11 @@ uip_nd6_ns_output(uip_ipaddr_t * src, uip_ipaddr_t * dest, uip_ipaddr_t * tgt)
|
|||
UIP_ICMP_BUF->icmpchksum = ~uip_icmp6chksum();
|
||||
|
||||
UIP_STAT(++uip_stat.nd6.sent);
|
||||
PRINTF("Sending NS to");
|
||||
PRINTF("Sending NS to ");
|
||||
PRINT6ADDR(&UIP_IP_BUF->destipaddr);
|
||||
PRINTF("from");
|
||||
PRINTF(" from ");
|
||||
PRINT6ADDR(&UIP_IP_BUF->srcipaddr);
|
||||
PRINTF("with target address");
|
||||
PRINTF(" with target address ");
|
||||
PRINT6ADDR(tgt);
|
||||
PRINTF("\n");
|
||||
return;
|
||||
|
@ -417,18 +428,18 @@ na_input(void)
|
|||
uint8_t is_solicited;
|
||||
uint8_t is_override;
|
||||
|
||||
PRINTF("Received NA from");
|
||||
PRINTF("Received NA from ");
|
||||
PRINT6ADDR(&UIP_IP_BUF->srcipaddr);
|
||||
PRINTF("to");
|
||||
PRINTF(" to ");
|
||||
PRINT6ADDR(&UIP_IP_BUF->destipaddr);
|
||||
PRINTF("with target address");
|
||||
PRINTF(" with target address ");
|
||||
PRINT6ADDR((uip_ipaddr_t *) (&UIP_ND6_NA_BUF->tgtipaddr));
|
||||
PRINTF("\n");
|
||||
UIP_STAT(++uip_stat.nd6.recv);
|
||||
|
||||
/*
|
||||
/*
|
||||
* booleans. the three last one are not 0 or 1 but 0 or 0x80, 0x40, 0x20
|
||||
* but it works. Be careful though, do not use tests such as is_router == 1
|
||||
* but it works. Be careful though, do not use tests such as is_router == 1
|
||||
*/
|
||||
is_llchange = 0;
|
||||
is_router = ((UIP_ND6_NA_BUF->flagsreserved & UIP_ND6_NA_FLAG_ROUTER));
|
||||
|
@ -494,7 +505,7 @@ na_input(void)
|
|||
goto discard;
|
||||
}
|
||||
memcpy(lladdr, &nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET],
|
||||
UIP_LLADDR_LEN);
|
||||
UIP_LLADDR_LEN);
|
||||
if(is_solicited) {
|
||||
nbr->state = NBR_REACHABLE;
|
||||
nbr->nscount = 0;
|
||||
|
@ -517,7 +528,7 @@ na_input(void)
|
|||
|| nd6_opt_llao == 0) {
|
||||
if(nd6_opt_llao != 0) {
|
||||
memcpy(lladdr, &nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET],
|
||||
UIP_LLADDR_LEN);
|
||||
UIP_LLADDR_LEN);
|
||||
}
|
||||
if(is_solicited) {
|
||||
nbr->state = NBR_REACHABLE;
|
||||
|
@ -553,11 +564,11 @@ na_input(void)
|
|||
uip_packetqueue_free(&nbr->packethandle);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
#endif /*UIP_CONF_IPV6_QUEUE_PKT */
|
||||
|
||||
discard:
|
||||
uip_len = 0;
|
||||
uip_clear_buf();
|
||||
return;
|
||||
}
|
||||
#endif /* UIP_ND6_SEND_NA */
|
||||
|
@ -569,9 +580,9 @@ static void
|
|||
rs_input(void)
|
||||
{
|
||||
|
||||
PRINTF("Received RS from");
|
||||
PRINTF("Received RS from ");
|
||||
PRINT6ADDR(&UIP_IP_BUF->srcipaddr);
|
||||
PRINTF("to");
|
||||
PRINTF(" to ");
|
||||
PRINT6ADDR(&UIP_IP_BUF->destipaddr);
|
||||
PRINTF("\n");
|
||||
UIP_STAT(++uip_stat.nd6.recv);
|
||||
|
@ -579,7 +590,7 @@ rs_input(void)
|
|||
|
||||
#if UIP_CONF_IPV6_CHECKS
|
||||
/*
|
||||
* Check hop limit / icmp code
|
||||
* Check hop limit / icmp code
|
||||
* target address must not be multicast
|
||||
* if the NA is solicited, dest must not be multicast
|
||||
*/
|
||||
|
@ -619,18 +630,18 @@ rs_input(void)
|
|||
goto discard;
|
||||
} else {
|
||||
#endif /*UIP_CONF_IPV6_CHECKS */
|
||||
uip_lladdr_t lladdr_aligned;
|
||||
extract_lladdr_aligned(&lladdr_aligned);
|
||||
if((nbr = uip_ds6_nbr_lookup(&UIP_IP_BUF->srcipaddr)) == NULL) {
|
||||
/* we need to add the neighbor */
|
||||
uip_ds6_nbr_add(&UIP_IP_BUF->srcipaddr,
|
||||
(uip_lladdr_t *)&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], 0, NBR_STALE);
|
||||
uip_ds6_nbr_add(&UIP_IP_BUF->srcipaddr, &lladdr_aligned, 0, NBR_STALE);
|
||||
} else {
|
||||
/* If LL address changed, set neighbor state to stale */
|
||||
if(memcmp(&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET],
|
||||
uip_ds6_nbr_get_ll(nbr), UIP_LLADDR_LEN) != 0) {
|
||||
uip_ds6_nbr_t nbr_data = *nbr;
|
||||
uip_ds6_nbr_rm(nbr);
|
||||
nbr = uip_ds6_nbr_add(&UIP_IP_BUF->srcipaddr,
|
||||
(uip_lladdr_t *)&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], 0, NBR_STALE);
|
||||
nbr = uip_ds6_nbr_add(&UIP_IP_BUF->srcipaddr, &lladdr_aligned, 0, NBR_STALE);
|
||||
nbr->reachable = nbr_data.reachable;
|
||||
nbr->sendns = nbr_data.sendns;
|
||||
nbr->nscount = nbr_data.nscount;
|
||||
|
@ -646,7 +657,7 @@ rs_input(void)
|
|||
uip_ds6_send_ra_sollicited();
|
||||
|
||||
discard:
|
||||
uip_len = 0;
|
||||
uip_clear_buf();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -687,7 +698,6 @@ uip_nd6_ra_output(uip_ipaddr_t * dest)
|
|||
nd6_opt_offset = UIP_ND6_RA_LEN;
|
||||
|
||||
|
||||
#if !UIP_CONF_ROUTER
|
||||
/* Prefix list */
|
||||
for(prefix = uip_ds6_prefix_list;
|
||||
prefix < uip_ds6_prefix_list + UIP_DS6_PREFIX_NB; prefix++) {
|
||||
|
@ -704,7 +714,6 @@ uip_nd6_ra_output(uip_ipaddr_t * dest)
|
|||
uip_len += UIP_ND6_OPT_PREFIX_INFO_LEN;
|
||||
}
|
||||
}
|
||||
#endif /* !UIP_CONF_ROUTER */
|
||||
|
||||
/* Source link-layer option */
|
||||
create_llao((uint8_t *)UIP_ND6_OPT_HDR_BUF, UIP_ND6_OPT_SLLAO);
|
||||
|
@ -752,9 +761,9 @@ uip_nd6_ra_output(uip_ipaddr_t * dest)
|
|||
UIP_ICMP_BUF->icmpchksum = ~uip_icmp6chksum();
|
||||
|
||||
UIP_STAT(++uip_stat.nd6.sent);
|
||||
PRINTF("Sending RA to");
|
||||
PRINTF("Sending RA to ");
|
||||
PRINT6ADDR(&UIP_IP_BUF->destipaddr);
|
||||
PRINTF("from");
|
||||
PRINTF(" from ");
|
||||
PRINT6ADDR(&UIP_IP_BUF->srcipaddr);
|
||||
PRINTF("\n");
|
||||
return;
|
||||
|
@ -787,22 +796,22 @@ uip_nd6_rs_output(void)
|
|||
UIP_ICMPH_LEN + UIP_ND6_RS_LEN + UIP_ND6_OPT_LLAO_LEN;
|
||||
|
||||
create_llao(&uip_buf[uip_l2_l3_icmp_hdr_len + UIP_ND6_RS_LEN],
|
||||
UIP_ND6_OPT_SLLAO);
|
||||
UIP_ND6_OPT_SLLAO);
|
||||
}
|
||||
|
||||
UIP_ICMP_BUF->icmpchksum = 0;
|
||||
UIP_ICMP_BUF->icmpchksum = ~uip_icmp6chksum();
|
||||
|
||||
UIP_STAT(++uip_stat.nd6.sent);
|
||||
PRINTF("Sendin RS to");
|
||||
PRINTF("Sendin RS to ");
|
||||
PRINT6ADDR(&UIP_IP_BUF->destipaddr);
|
||||
PRINTF("from");
|
||||
PRINTF(" from ");
|
||||
PRINT6ADDR(&UIP_IP_BUF->srcipaddr);
|
||||
PRINTF("\n");
|
||||
return;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/*
|
||||
/**
|
||||
* Process a Router Advertisement
|
||||
*
|
||||
* - Possible actions when receiving a RA: add router to router list,
|
||||
|
@ -814,16 +823,16 @@ uip_nd6_rs_output(void)
|
|||
void
|
||||
ra_input(void)
|
||||
{
|
||||
PRINTF("Received RA from");
|
||||
PRINTF("Received RA from ");
|
||||
PRINT6ADDR(&UIP_IP_BUF->srcipaddr);
|
||||
PRINTF("to");
|
||||
PRINTF(" to ");
|
||||
PRINT6ADDR(&UIP_IP_BUF->destipaddr);
|
||||
PRINTF("\n");
|
||||
UIP_STAT(++uip_stat.nd6.recv);
|
||||
|
||||
#if UIP_CONF_IPV6_CHECKS
|
||||
if((UIP_IP_BUF->ttl != UIP_ND6_HOP_LIMIT) ||
|
||||
(!uip_is_addr_link_local(&UIP_IP_BUF->srcipaddr)) ||
|
||||
(!uip_is_addr_linklocal(&UIP_IP_BUF->srcipaddr)) ||
|
||||
(UIP_ICMP_BUF->icode != 0)) {
|
||||
PRINTF("RA received is bad");
|
||||
goto discard;
|
||||
|
@ -859,18 +868,18 @@ ra_input(void)
|
|||
nd6_opt_llao = (uint8_t *) UIP_ND6_OPT_HDR_BUF;
|
||||
nbr = uip_ds6_nbr_lookup(&UIP_IP_BUF->srcipaddr);
|
||||
if(nbr == NULL) {
|
||||
nbr = uip_ds6_nbr_add(&UIP_IP_BUF->srcipaddr,
|
||||
(uip_lladdr_t *)&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET],
|
||||
1, NBR_STALE);
|
||||
uip_lladdr_t lladdr_aligned;
|
||||
extract_lladdr_aligned(&lladdr_aligned);
|
||||
nbr = uip_ds6_nbr_add(&UIP_IP_BUF->srcipaddr, &lladdr_aligned, 1, NBR_STALE);
|
||||
} else {
|
||||
uip_lladdr_t *lladdr = (uip_lladdr_t *)uip_ds6_nbr_get_ll(nbr);
|
||||
if(nbr->state == NBR_INCOMPLETE) {
|
||||
nbr->state = NBR_STALE;
|
||||
}
|
||||
if(memcmp(&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET],
|
||||
lladdr, UIP_LLADDR_LEN) != 0) {
|
||||
lladdr, UIP_LLADDR_LEN) != 0) {
|
||||
memcpy(lladdr, &nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET],
|
||||
UIP_LLADDR_LEN);
|
||||
UIP_LLADDR_LEN);
|
||||
nbr->state = NBR_STALE;
|
||||
}
|
||||
nbr->isrouter = 1;
|
||||
|
@ -886,7 +895,7 @@ ra_input(void)
|
|||
nd6_opt_prefix_info = (uip_nd6_opt_prefix_info *) UIP_ND6_OPT_HDR_BUF;
|
||||
if((uip_ntohl(nd6_opt_prefix_info->validlt) >=
|
||||
uip_ntohl(nd6_opt_prefix_info->preferredlt))
|
||||
&& (!uip_is_addr_link_local(&nd6_opt_prefix_info->prefix))) {
|
||||
&& (!uip_is_addr_linklocal(&nd6_opt_prefix_info->prefix))) {
|
||||
/* on-link flag related processing */
|
||||
if(nd6_opt_prefix_info->flagsreserved1 & UIP_ND6_RA_FLAG_ONLINK) {
|
||||
prefix =
|
||||
|
@ -913,9 +922,9 @@ ra_input(void)
|
|||
prefix->isinfinite = 1;
|
||||
break;
|
||||
default:
|
||||
PRINTF("Updating timer of prefix");
|
||||
PRINTF("Updating timer of prefix ");
|
||||
PRINT6ADDR(&prefix->ipaddr);
|
||||
PRINTF("new value %lu\n", uip_ntohl(nd6_opt_prefix_info->validlt));
|
||||
PRINTF(" new value %lu\n", uip_ntohl(nd6_opt_prefix_info->validlt));
|
||||
stimer_set(&prefix->vlifetime,
|
||||
uip_ntohl(nd6_opt_prefix_info->validlt));
|
||||
prefix->isinfinite = 0;
|
||||
|
@ -928,7 +937,7 @@ ra_input(void)
|
|||
if((nd6_opt_prefix_info->flagsreserved1 & UIP_ND6_RA_FLAG_AUTONOMOUS)
|
||||
&& (nd6_opt_prefix_info->validlt != 0)
|
||||
&& (nd6_opt_prefix_info->preflen == UIP_DEFAULT_PREFIX_LEN)) {
|
||||
|
||||
|
||||
uip_ipaddr_copy(&ipaddr, &nd6_opt_prefix_info->prefix);
|
||||
uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr);
|
||||
addr = uip_ds6_addr_lookup(&ipaddr);
|
||||
|
@ -938,9 +947,9 @@ ra_input(void)
|
|||
if((uip_ntohl(nd6_opt_prefix_info->validlt) > 2 * 60 * 60) ||
|
||||
(uip_ntohl(nd6_opt_prefix_info->validlt) >
|
||||
stimer_remaining(&addr->vlifetime))) {
|
||||
PRINTF("Updating timer of address");
|
||||
PRINTF("Updating timer of address ");
|
||||
PRINT6ADDR(&addr->ipaddr);
|
||||
PRINTF("new value %lu\n",
|
||||
PRINTF(" new value %lu\n",
|
||||
uip_ntohl(nd6_opt_prefix_info->validlt));
|
||||
stimer_set(&addr->vlifetime,
|
||||
uip_ntohl(nd6_opt_prefix_info->validlt));
|
||||
|
@ -948,7 +957,7 @@ ra_input(void)
|
|||
stimer_set(&addr->vlifetime, 2 * 60 * 60);
|
||||
PRINTF("Updating timer of address ");
|
||||
PRINT6ADDR(&addr->ipaddr);
|
||||
PRINTF("new value %lu\n", (unsigned long)(2 * 60 * 60));
|
||||
PRINTF(" new value %lu\n", (unsigned long)(2 * 60 * 60));
|
||||
}
|
||||
addr->isinfinite = 0;
|
||||
} else {
|
||||
|
@ -1029,7 +1038,7 @@ ra_input(void)
|
|||
#endif /*UIP_CONF_IPV6_QUEUE_PKT */
|
||||
|
||||
discard:
|
||||
uip_len = 0;
|
||||
uip_clear_buf();
|
||||
return;
|
||||
}
|
||||
#endif /* !UIP_CONF_ROUTER */
|
||||
|
|
|
@ -59,9 +59,12 @@
|
|||
|
||||
/** \name RFC 4861 Host constant */
|
||||
/** @{ */
|
||||
/** \brief Maximum router solicitation delay */
|
||||
#define UIP_ND6_MAX_RTR_SOLICITATION_DELAY 1
|
||||
/** \brief Router solicitation interval */
|
||||
#define UIP_ND6_RTR_SOLICITATION_INTERVAL 4
|
||||
#define UIP_ND6_MAX_RTR_SOLICITATIONS 3
|
||||
/** \brief Maximum router solicitations */
|
||||
#define UIP_ND6_MAX_RTR_SOLICITATIONS 3
|
||||
/** @} */
|
||||
|
||||
/** \name RFC 4861 Router constants */
|
||||
|
@ -128,9 +131,9 @@
|
|||
#endif
|
||||
|
||||
#ifdef UIP_CONF_ND6_RETRANS_TIMER
|
||||
#define UIP_ND6_RETRANS_TIMER UIP_CONF_ND6_RETRANS_TIMER
|
||||
#define UIP_ND6_RETRANS_TIMER UIP_CONF_ND6_RETRANS_TIMER
|
||||
#else
|
||||
#define UIP_ND6_RETRANS_TIMER 1000
|
||||
#define UIP_ND6_RETRANS_TIMER 1000
|
||||
#endif
|
||||
|
||||
#define UIP_ND6_DELAY_FIRST_PROBE_TIME 5
|
||||
|
|
|
@ -103,7 +103,7 @@ void uip_log(char *msg);
|
|||
#if UIP_STATISTICS == 1
|
||||
struct uip_stats uip_stat;
|
||||
#endif /* UIP_STATISTICS == 1 */
|
||||
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/**
|
||||
|
@ -288,7 +288,10 @@ struct uip_icmp6_conn uip_icmp6_conns;
|
|||
/*---------------------------------------------------------------------------*/
|
||||
/* Functions */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#if (!UIP_ARCH_ADD32 && UIP_TCP)
|
||||
#if UIP_TCP
|
||||
#if UIP_ARCH_ADD32
|
||||
void uip_add32(uint8_t *op32, uint16_t op16);
|
||||
#else /* UIP_ARCH_ADD32 */
|
||||
void
|
||||
uip_add32(uint8_t *op32, uint16_t op16)
|
||||
{
|
||||
|
@ -296,15 +299,15 @@ uip_add32(uint8_t *op32, uint16_t op16)
|
|||
uip_acc32[2] = op32[2] + (op16 >> 8);
|
||||
uip_acc32[1] = op32[1];
|
||||
uip_acc32[0] = op32[0];
|
||||
|
||||
|
||||
if(uip_acc32[2] < (op16 >> 8)) {
|
||||
++uip_acc32[1];
|
||||
if(uip_acc32[1] == 0) {
|
||||
++uip_acc32[0];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
if(uip_acc32[3] < (op16 & 0xff)) {
|
||||
++uip_acc32[2];
|
||||
if(uip_acc32[2] == 0) {
|
||||
|
@ -315,8 +318,8 @@ uip_add32(uint8_t *op32, uint16_t op16)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* UIP_ARCH_ADD32 && UIP_TCP */
|
||||
#endif /* UIP_ARCH_ADD32 */
|
||||
#endif /* UIP_TCP */
|
||||
|
||||
#if ! UIP_ARCH_CHKSUM
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
@ -329,7 +332,7 @@ chksum(uint16_t sum, const uint8_t *data, uint16_t len)
|
|||
|
||||
dataptr = data;
|
||||
last_byte = data + len - 1;
|
||||
|
||||
|
||||
while(dataptr < last_byte) { /* At least two more bytes */
|
||||
t = (dataptr[0] << 8) + dataptr[1];
|
||||
sum += t;
|
||||
|
@ -338,7 +341,7 @@ chksum(uint16_t sum, const uint8_t *data, uint16_t len)
|
|||
}
|
||||
dataptr += 2;
|
||||
}
|
||||
|
||||
|
||||
if(dataptr == last_byte) {
|
||||
t = (dataptr[0] << 8) + 0;
|
||||
sum += t;
|
||||
|
@ -383,11 +386,11 @@ upper_layer_chksum(uint8_t proto)
|
|||
*/
|
||||
volatile uint16_t upper_layer_len;
|
||||
uint16_t sum;
|
||||
|
||||
|
||||
upper_layer_len = (((uint16_t)(UIP_IP_BUF->len[0]) << 8) + UIP_IP_BUF->len[1] - uip_ext_len);
|
||||
|
||||
|
||||
PRINTF("Upper layer checksum len: %d from: %d\n", upper_layer_len,
|
||||
UIP_IPH_LEN + UIP_LLH_LEN + uip_ext_len);
|
||||
UIP_IPH_LEN + UIP_LLH_LEN + uip_ext_len);
|
||||
|
||||
/* First sum pseudoheader. */
|
||||
/* IP protocol and length fields. This addition cannot carry. */
|
||||
|
@ -398,7 +401,7 @@ upper_layer_chksum(uint8_t proto)
|
|||
/* Sum TCP header and data. */
|
||||
sum = chksum(sum, &uip_buf[UIP_IPH_LEN + UIP_LLH_LEN + uip_ext_len],
|
||||
upper_layer_len);
|
||||
|
||||
|
||||
return (sum == 0) ? 0xffff : uip_htons(sum);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
@ -406,7 +409,7 @@ uint16_t
|
|||
uip_icmp6chksum(void)
|
||||
{
|
||||
return upper_layer_chksum(UIP_PROTO_ICMP6);
|
||||
|
||||
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#if UIP_TCP
|
||||
|
@ -429,7 +432,7 @@ uip_udpchksum(void)
|
|||
void
|
||||
uip_init(void)
|
||||
{
|
||||
|
||||
|
||||
uip_ds6_init();
|
||||
uip_icmp6_init();
|
||||
uip_nd6_init();
|
||||
|
@ -463,7 +466,7 @@ struct uip_conn *
|
|||
uip_connect(const uip_ipaddr_t *ripaddr, uint16_t rport)
|
||||
{
|
||||
register struct uip_conn *conn, *cconn;
|
||||
|
||||
|
||||
/* Find an unused local port. */
|
||||
again:
|
||||
++lastport;
|
||||
|
@ -500,7 +503,7 @@ uip_connect(const uip_ipaddr_t *ripaddr, uint16_t rport)
|
|||
if(conn == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
conn->tcpstateflags = UIP_SYN_SENT;
|
||||
|
||||
conn->snd_nxt[0] = iss[0];
|
||||
|
@ -514,7 +517,7 @@ uip_connect(const uip_ipaddr_t *ripaddr, uint16_t rport)
|
|||
conn->rcv_nxt[3] = 0;
|
||||
|
||||
conn->initialmss = conn->mss = UIP_TCP_MSS;
|
||||
|
||||
|
||||
conn->len = 1; /* TCP length of the SYN is one. */
|
||||
conn->nrtx = 0;
|
||||
conn->timer = 1; /* Send the SYN next time around. */
|
||||
|
@ -524,7 +527,7 @@ uip_connect(const uip_ipaddr_t *ripaddr, uint16_t rport)
|
|||
conn->lport = uip_htons(lastport);
|
||||
conn->rport = rport;
|
||||
uip_ipaddr_copy(&conn->ripaddr, ripaddr);
|
||||
|
||||
|
||||
return conn;
|
||||
}
|
||||
#endif /* UIP_TCP && UIP_ACTIVE_OPEN */
|
||||
|
@ -535,15 +538,14 @@ remove_ext_hdr(void)
|
|||
/* Remove ext header before TCP/UDP processing. */
|
||||
if(uip_ext_len > 0) {
|
||||
PRINTF("Cutting ext-header before processing (extlen: %d, uiplen: %d)\n",
|
||||
uip_ext_len, uip_len);
|
||||
uip_ext_len, uip_len);
|
||||
if(uip_len < UIP_IPH_LEN + uip_ext_len) {
|
||||
PRINTF("ERROR: uip_len too short compared to ext len\n");
|
||||
uip_ext_len = 0;
|
||||
uip_len = 0;
|
||||
uip_clear_buf();
|
||||
return;
|
||||
}
|
||||
memmove(((uint8_t *)UIP_TCP_BUF), (uint8_t *)UIP_TCP_BUF + uip_ext_len,
|
||||
uip_len - UIP_IPH_LEN - uip_ext_len);
|
||||
uip_len - UIP_IPH_LEN - uip_ext_len);
|
||||
|
||||
uip_len -= uip_ext_len;
|
||||
|
||||
|
@ -559,7 +561,7 @@ struct uip_udp_conn *
|
|||
uip_udp_new(const uip_ipaddr_t *ripaddr, uint16_t rport)
|
||||
{
|
||||
register struct uip_udp_conn *conn;
|
||||
|
||||
|
||||
/* Find an unused local port. */
|
||||
again:
|
||||
++lastport;
|
||||
|
@ -567,7 +569,7 @@ uip_udp_new(const uip_ipaddr_t *ripaddr, uint16_t rport)
|
|||
if(lastport >= 32000) {
|
||||
lastport = 4096;
|
||||
}
|
||||
|
||||
|
||||
for(c = 0; c < UIP_UDP_CONNS; ++c) {
|
||||
if(uip_udp_conns[c].lport == uip_htons(lastport)) {
|
||||
goto again;
|
||||
|
@ -585,7 +587,7 @@ uip_udp_new(const uip_ipaddr_t *ripaddr, uint16_t rport)
|
|||
if(conn == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
conn->lport = UIP_HTONS(lastport);
|
||||
conn->rport = rport;
|
||||
if(ripaddr == NULL) {
|
||||
|
@ -594,7 +596,7 @@ uip_udp_new(const uip_ipaddr_t *ripaddr, uint16_t rport)
|
|||
uip_ipaddr_copy(&conn->ripaddr, ripaddr);
|
||||
}
|
||||
conn->ttl = uip_ds6_if.cur_hop_limit;
|
||||
|
||||
|
||||
return conn;
|
||||
}
|
||||
#endif /* UIP_UDP */
|
||||
|
@ -652,7 +654,7 @@ static uint8_t uip_reassflags;
|
|||
*/
|
||||
|
||||
|
||||
struct etimer uip_reass_timer; /* timer for reassembly */
|
||||
struct etimer uip_reass_timer; /**< Timer for reassembly */
|
||||
uint8_t uip_reass_on; /* equal to 1 if we are currently reassembling a packet */
|
||||
|
||||
static uint32_t uip_id; /* For every packet that is to be fragmented, the source
|
||||
|
@ -666,7 +668,7 @@ uip_reass(void)
|
|||
uint16_t offset=0;
|
||||
uint16_t len;
|
||||
uint16_t i;
|
||||
|
||||
|
||||
/* If ip_reasstmr is zero, no packet is present in the buffer */
|
||||
/* We first write the unfragmentable part of IP header into the reassembly
|
||||
buffer. The reset the other reassembly variables. */
|
||||
|
@ -708,9 +710,9 @@ uip_reass(void)
|
|||
PRINTF("dest ");
|
||||
PRINT6ADDR(&FBUF->destipaddr);
|
||||
PRINTF("next %d\n", UIP_IP_BUF->proto);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* If the offset or the offset + fragment length overflows the
|
||||
reassembly buffer, we discard the entire packet. */
|
||||
if(offset > UIP_REASS_BUFSIZE ||
|
||||
|
@ -742,12 +744,12 @@ uip_reass(void)
|
|||
return uip_len;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Copy the fragment into the reassembly buffer, at the right
|
||||
offset. */
|
||||
memcpy((uint8_t *)FBUF + UIP_IPH_LEN + uip_ext_len + offset,
|
||||
(uint8_t *)UIP_FRAG_BUF + UIP_FRAGH_LEN, len);
|
||||
|
||||
|
||||
/* Update the bitmap. */
|
||||
if(offset >> 6 == (offset + len) >> 6) {
|
||||
uip_reassbitmap[offset >> 6] |=
|
||||
|
@ -758,18 +760,18 @@ uip_reass(void)
|
|||
bytes in the endpoints and fill the stuff inbetween with
|
||||
0xff. */
|
||||
uip_reassbitmap[offset >> 6] |= bitmap_bits[(offset >> 3) & 7];
|
||||
|
||||
|
||||
for(i = (1 + (offset >> 6)); i < ((offset + len) >> 6); ++i) {
|
||||
uip_reassbitmap[i] = 0xff;
|
||||
}
|
||||
uip_reassbitmap[(offset + len) >> 6] |=
|
||||
~bitmap_bits[((offset + len) >> 3) & 7];
|
||||
}
|
||||
|
||||
|
||||
/* Finally, we check if we have a full packet in the buffer. We do
|
||||
this by checking if we have the last fragment and if all bits
|
||||
in the bitmap are set. */
|
||||
|
||||
|
||||
if(uip_reassflags & UIP_REASS_FLAG_LASTFRAG) {
|
||||
/* Check all bytes up to and including all but the last byte in
|
||||
the bitmap. */
|
||||
|
@ -796,9 +798,9 @@ uip_reass(void)
|
|||
UIP_IP_BUF->len[1] = ((uip_reasslen - UIP_IPH_LEN) & 0xff);
|
||||
PRINTF("REASSEMBLED PAQUET %d (%d)\n", uip_reasslen,
|
||||
(UIP_IP_BUF->len[0] << 8) | UIP_IP_BUF->len[1]);
|
||||
|
||||
|
||||
return uip_reasslen;
|
||||
|
||||
|
||||
}
|
||||
} else {
|
||||
PRINTF("Already reassembling another paquet\n");
|
||||
|
@ -825,12 +827,11 @@ uip_reass_over(void)
|
|||
* any RFC, we decided not to include it as it reduces the size of
|
||||
* the packet.
|
||||
*/
|
||||
uip_len = 0;
|
||||
uip_ext_len = 0;
|
||||
uip_clear_buf();
|
||||
memcpy(UIP_IP_BUF, FBUF, UIP_IPH_LEN); /* copy the header for src
|
||||
and dest address*/
|
||||
uip_icmp6_error_output(ICMP6_TIME_EXCEEDED, ICMP6_TIME_EXCEED_REASSEMBLY, 0);
|
||||
|
||||
|
||||
UIP_STAT(++uip_stat.ip.sent);
|
||||
uip_flags = 0;
|
||||
}
|
||||
|
@ -880,14 +881,14 @@ ext_hdr_options_process(void)
|
|||
uip_ext_opt_offset += UIP_EXT_HDR_OPT_PADN_BUF->opt_len + 2;
|
||||
break;
|
||||
case UIP_EXT_HDR_OPT_RPL:
|
||||
/* Fixes situation when a node that is not using RPL
|
||||
* joins a network which does. The received packages will include the
|
||||
* RPL header and processed by the "default" case of the switch
|
||||
* (0x63 & 0xC0 = 0x40). Hence, the packet is discarded as the header
|
||||
* is considered invalid.
|
||||
* Using this fix, the header is ignored, and the next header (if
|
||||
* present) is processed.
|
||||
*/
|
||||
/* Fixes situation when a node that is not using RPL
|
||||
* joins a network which does. The received packages will include the
|
||||
* RPL header and processed by the "default" case of the switch
|
||||
* (0x63 & 0xC0 = 0x40). Hence, the packet is discarded as the header
|
||||
* is considered invalid.
|
||||
* Using this fix, the header is ignored, and the next header (if
|
||||
* present) is processed.
|
||||
*/
|
||||
#if UIP_CONF_IPV6_RPL
|
||||
PRINTF("Processing RPL option\n");
|
||||
if(rpl_verify_header(uip_ext_opt_offset)) {
|
||||
|
@ -948,7 +949,7 @@ uip_process(uint8_t flag)
|
|||
}
|
||||
#endif /* UIP_UDP */
|
||||
uip_sappdata = uip_appdata = &uip_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN];
|
||||
|
||||
|
||||
/* Check if we were invoked because of a poll request for a
|
||||
particular connection. */
|
||||
if(flag == UIP_POLL_REQUEST) {
|
||||
|
@ -971,9 +972,9 @@ uip_process(uint8_t flag)
|
|||
} else if(flag == UIP_TIMER) {
|
||||
/* Reset the length variables. */
|
||||
#if UIP_TCP
|
||||
uip_len = 0;
|
||||
uip_clear_buf();
|
||||
uip_slen = 0;
|
||||
|
||||
|
||||
/* Increase the initial sequence number. */
|
||||
if(++iss[3] == 0) {
|
||||
if(++iss[2] == 0) {
|
||||
|
@ -982,7 +983,7 @@ uip_process(uint8_t flag)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Check if the connection is in a state in which we simply wait
|
||||
* for the connection to time out. If so, we increase the
|
||||
|
@ -1008,7 +1009,7 @@ uip_process(uint8_t flag)
|
|||
uip_connr->tcpstateflags == UIP_SYN_RCVD) &&
|
||||
uip_connr->nrtx == UIP_MAXSYNRTX)) {
|
||||
uip_connr->tcpstateflags = UIP_CLOSED;
|
||||
|
||||
|
||||
/*
|
||||
* We call UIP_APPCALL() with uip_flags set to
|
||||
* UIP_TIMEDOUT to inform the application that the
|
||||
|
@ -1016,18 +1017,18 @@ uip_process(uint8_t flag)
|
|||
*/
|
||||
uip_flags = UIP_TIMEDOUT;
|
||||
UIP_APPCALL();
|
||||
|
||||
|
||||
/* We also send a reset packet to the remote host. */
|
||||
UIP_TCP_BUF->flags = TCP_RST | TCP_ACK;
|
||||
goto tcp_send_nodata;
|
||||
}
|
||||
|
||||
|
||||
/* Exponential backoff. */
|
||||
uip_connr->timer = UIP_RTO << (uip_connr->nrtx > 4?
|
||||
4:
|
||||
uip_connr->nrtx);
|
||||
++(uip_connr->nrtx);
|
||||
|
||||
|
||||
/*
|
||||
* Ok, so we need to retransmit. We do this differently
|
||||
* depending on which state we are in. In ESTABLISHED, we
|
||||
|
@ -1041,14 +1042,14 @@ uip_process(uint8_t flag)
|
|||
case UIP_SYN_RCVD:
|
||||
/* In the SYN_RCVD state, we should retransmit our SYNACK. */
|
||||
goto tcp_send_synack;
|
||||
|
||||
|
||||
#if UIP_ACTIVE_OPEN
|
||||
case UIP_SYN_SENT:
|
||||
/* In the SYN_SENT state, we retransmit out SYN. */
|
||||
UIP_TCP_BUF->flags = 0;
|
||||
goto tcp_send_syn;
|
||||
#endif /* UIP_ACTIVE_OPEN */
|
||||
|
||||
|
||||
case UIP_ESTABLISHED:
|
||||
/*
|
||||
* In the ESTABLISHED state, we call upon the application
|
||||
|
@ -1059,7 +1060,7 @@ uip_process(uint8_t flag)
|
|||
uip_flags = UIP_REXMIT;
|
||||
UIP_APPCALL();
|
||||
goto apprexmit;
|
||||
|
||||
|
||||
case UIP_FIN_WAIT_1:
|
||||
case UIP_CLOSING:
|
||||
case UIP_LAST_ACK:
|
||||
|
@ -1095,12 +1096,12 @@ uip_process(uint8_t flag)
|
|||
}
|
||||
#endif /* UIP_UDP */
|
||||
|
||||
|
||||
|
||||
/* This is where the input processing starts. */
|
||||
UIP_STAT(++uip_stat.ip.recv);
|
||||
|
||||
|
||||
/* Start of IP input header processing code. */
|
||||
|
||||
|
||||
/* Check validity of the IP header. */
|
||||
if((UIP_IP_BUF->vtc & 0xf0) != 0x60) { /* IP version and header length. */
|
||||
UIP_STAT(++uip_stat.ip.drop);
|
||||
|
@ -1116,7 +1117,7 @@ uip_process(uint8_t flag)
|
|||
* the packet has been padded and we set uip_len to the correct
|
||||
* value..
|
||||
*/
|
||||
|
||||
|
||||
if((UIP_IP_BUF->len[0] << 8) + UIP_IP_BUF->len[1] <= uip_len) {
|
||||
uip_len = (UIP_IP_BUF->len[0] << 8) + UIP_IP_BUF->len[1] + UIP_IPH_LEN;
|
||||
/*
|
||||
|
@ -1134,7 +1135,7 @@ uip_process(uint8_t flag)
|
|||
UIP_LOG("ip: packet shorter than reported in IP header.");
|
||||
goto drop;
|
||||
}
|
||||
|
||||
|
||||
PRINTF("IPv6 packet received from ");
|
||||
PRINT6ADDR(&UIP_IP_BUF->srcipaddr);
|
||||
PRINTF(" to ");
|
||||
|
@ -1167,11 +1168,11 @@ uip_process(uint8_t flag)
|
|||
uip_ext_len += (UIP_EXT_BUF->len << 3) + 8;
|
||||
break;
|
||||
case 1:
|
||||
PRINTF("Dropping packet after extension header processing\n");
|
||||
PRINTF("Dropping packet after extension header processing\n");
|
||||
/* silently discard */
|
||||
goto drop;
|
||||
case 2:
|
||||
PRINTF("Sending error message after extension header processing\n");
|
||||
PRINTF("Sending error message after extension header processing\n");
|
||||
/* send icmp error message (created in ext_hdr_options_process)
|
||||
* and discard*/
|
||||
goto send;
|
||||
|
@ -1205,8 +1206,8 @@ uip_process(uint8_t flag)
|
|||
if(!uip_ds6_is_my_addr(&UIP_IP_BUF->destipaddr) &&
|
||||
!uip_ds6_is_my_maddr(&UIP_IP_BUF->destipaddr)) {
|
||||
if(!uip_is_addr_mcast(&UIP_IP_BUF->destipaddr) &&
|
||||
!uip_is_addr_link_local(&UIP_IP_BUF->destipaddr) &&
|
||||
!uip_is_addr_link_local(&UIP_IP_BUF->srcipaddr) &&
|
||||
!uip_is_addr_linklocal(&UIP_IP_BUF->destipaddr) &&
|
||||
!uip_is_addr_linklocal(&UIP_IP_BUF->srcipaddr) &&
|
||||
!uip_is_addr_unspecified(&UIP_IP_BUF->srcipaddr) &&
|
||||
!uip_is_addr_loopback(&UIP_IP_BUF->destipaddr)) {
|
||||
|
||||
|
@ -1240,7 +1241,7 @@ uip_process(uint8_t flag)
|
|||
UIP_STAT(++uip_stat.ip.forwarded);
|
||||
goto send;
|
||||
} else {
|
||||
if((uip_is_addr_link_local(&UIP_IP_BUF->srcipaddr)) &&
|
||||
if((uip_is_addr_linklocal(&UIP_IP_BUF->srcipaddr)) &&
|
||||
(!uip_is_addr_unspecified(&UIP_IP_BUF->srcipaddr)) &&
|
||||
(!uip_is_addr_loopback(&UIP_IP_BUF->destipaddr)) &&
|
||||
(!uip_is_addr_mcast(&UIP_IP_BUF->destipaddr)) &&
|
||||
|
@ -1416,7 +1417,7 @@ uip_process(uint8_t flag)
|
|||
UIP_LOG("ip6: unrecognized header");
|
||||
goto send;
|
||||
/* End of headers processing */
|
||||
|
||||
|
||||
icmp6_input:
|
||||
/* This is IPv6 ICMPv6 processing code. */
|
||||
PRINTF("icmp6_input: length %d type: %d \n", uip_len, UIP_ICMP_BUF->type);
|
||||
|
@ -1456,16 +1457,16 @@ uip_process(uint8_t flag)
|
|||
UIP_STAT(++uip_stat.icmp.drop);
|
||||
UIP_STAT(++uip_stat.icmp.typeerr);
|
||||
UIP_LOG("icmp6: unknown ICMPv6 message.");
|
||||
uip_len = 0;
|
||||
uip_clear_buf();
|
||||
}
|
||||
|
||||
|
||||
if(uip_len > 0) {
|
||||
goto send;
|
||||
} else {
|
||||
goto drop;
|
||||
}
|
||||
/* End of IPv6 ICMP processing. */
|
||||
|
||||
|
||||
|
||||
#if UIP_UDP
|
||||
/* UDP input processing. */
|
||||
|
@ -1474,7 +1475,7 @@ uip_process(uint8_t flag)
|
|||
remove_ext_hdr();
|
||||
|
||||
PRINTF("Receiving UDP packet\n");
|
||||
|
||||
|
||||
/* UDP processing is really just a hack. We don't do anything to the
|
||||
UDP/IP headers, but let the UDP application do all the hard
|
||||
work. If the application sets uip_slen, it has a packet to
|
||||
|
@ -1537,7 +1538,7 @@ uip_process(uint8_t flag)
|
|||
udp_found:
|
||||
PRINTF("In udp_found\n");
|
||||
UIP_STAT(++uip_stat.udp.recv);
|
||||
|
||||
|
||||
uip_conn = NULL;
|
||||
uip_flags = UIP_NEWDATA;
|
||||
uip_sappdata = uip_appdata = &uip_buf[UIP_IPUDPH_LEN + UIP_LLH_LEN];
|
||||
|
@ -1596,7 +1597,7 @@ uip_process(uint8_t flag)
|
|||
UIP_STAT(++uip_stat.tcp.recv);
|
||||
PRINTF("Receiving TCP packet\n");
|
||||
/* Start of TCP input header processing code. */
|
||||
|
||||
|
||||
if(uip_tcpchksum() != 0xffff) { /* Compute and check the TCP
|
||||
checksum. */
|
||||
UIP_STAT(++uip_stat.tcp.drop);
|
||||
|
@ -1631,7 +1632,7 @@ uip_process(uint8_t flag)
|
|||
if((UIP_TCP_BUF->flags & TCP_CTL) != TCP_SYN) {
|
||||
goto reset;
|
||||
}
|
||||
|
||||
|
||||
tmp16 = UIP_TCP_BUF->destport;
|
||||
/* Next, check listening connections. */
|
||||
for(c = 0; c < UIP_LISTENPORTS; ++c) {
|
||||
|
@ -1639,7 +1640,7 @@ uip_process(uint8_t flag)
|
|||
goto found_listen;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* No matching connection found, so we send a RST packet. */
|
||||
UIP_STAT(++uip_stat.tcp.synrst);
|
||||
|
||||
|
@ -1651,7 +1652,7 @@ uip_process(uint8_t flag)
|
|||
}
|
||||
|
||||
UIP_STAT(++uip_stat.tcp.rst);
|
||||
|
||||
|
||||
UIP_TCP_BUF->flags = TCP_RST | TCP_ACK;
|
||||
uip_len = UIP_IPTCPH_LEN;
|
||||
UIP_TCP_BUF->tcpoffset = 5 << 4;
|
||||
|
@ -1660,15 +1661,15 @@ uip_process(uint8_t flag)
|
|||
c = UIP_TCP_BUF->seqno[3];
|
||||
UIP_TCP_BUF->seqno[3] = UIP_TCP_BUF->ackno[3];
|
||||
UIP_TCP_BUF->ackno[3] = c;
|
||||
|
||||
|
||||
c = UIP_TCP_BUF->seqno[2];
|
||||
UIP_TCP_BUF->seqno[2] = UIP_TCP_BUF->ackno[2];
|
||||
UIP_TCP_BUF->ackno[2] = c;
|
||||
|
||||
|
||||
c = UIP_TCP_BUF->seqno[1];
|
||||
UIP_TCP_BUF->seqno[1] = UIP_TCP_BUF->ackno[1];
|
||||
UIP_TCP_BUF->ackno[1] = c;
|
||||
|
||||
|
||||
c = UIP_TCP_BUF->seqno[0];
|
||||
UIP_TCP_BUF->seqno[0] = UIP_TCP_BUF->ackno[0];
|
||||
UIP_TCP_BUF->ackno[0] = c;
|
||||
|
@ -1683,12 +1684,12 @@ uip_process(uint8_t flag)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Swap port numbers. */
|
||||
tmp16 = UIP_TCP_BUF->srcport;
|
||||
UIP_TCP_BUF->srcport = UIP_TCP_BUF->destport;
|
||||
UIP_TCP_BUF->destport = tmp16;
|
||||
|
||||
|
||||
/* Swap IP addresses. */
|
||||
uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, &UIP_IP_BUF->srcipaddr);
|
||||
uip_ds6_select_src(&UIP_IP_BUF->srcipaddr, &UIP_IP_BUF->destipaddr);
|
||||
|
@ -1729,7 +1730,7 @@ uip_process(uint8_t flag)
|
|||
goto drop;
|
||||
}
|
||||
uip_conn = uip_connr;
|
||||
|
||||
|
||||
/* Fill in the necessary fields for the new connection. */
|
||||
uip_connr->rto = uip_connr->timer = UIP_RTO;
|
||||
uip_connr->sa = 0;
|
||||
|
@ -1747,10 +1748,10 @@ uip_process(uint8_t flag)
|
|||
uip_connr->len = 1;
|
||||
|
||||
/* rcv_nxt should be the seqno from the incoming packet + 1. */
|
||||
uip_connr->rcv_nxt[3] = UIP_TCP_BUF->seqno[3];
|
||||
uip_connr->rcv_nxt[2] = UIP_TCP_BUF->seqno[2];
|
||||
uip_connr->rcv_nxt[1] = UIP_TCP_BUF->seqno[1];
|
||||
uip_connr->rcv_nxt[0] = UIP_TCP_BUF->seqno[0];
|
||||
uip_connr->rcv_nxt[1] = UIP_TCP_BUF->seqno[1];
|
||||
uip_connr->rcv_nxt[2] = UIP_TCP_BUF->seqno[2];
|
||||
uip_connr->rcv_nxt[3] = UIP_TCP_BUF->seqno[3];
|
||||
uip_add_rcv_nxt(1);
|
||||
|
||||
/* Parse the TCP MSS option, if present. */
|
||||
|
@ -1770,7 +1771,7 @@ uip_process(uint8_t flag)
|
|||
(uint16_t)uip_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN + 3 + c];
|
||||
uip_connr->initialmss = uip_connr->mss =
|
||||
tmp16 > UIP_TCP_MSS? UIP_TCP_MSS: tmp16;
|
||||
|
||||
|
||||
/* And we are done processing options. */
|
||||
break;
|
||||
} else {
|
||||
|
@ -1785,19 +1786,19 @@ uip_process(uint8_t flag)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Our response will be a SYNACK. */
|
||||
#if UIP_ACTIVE_OPEN
|
||||
tcp_send_synack:
|
||||
UIP_TCP_BUF->flags = TCP_ACK;
|
||||
|
||||
|
||||
tcp_send_syn:
|
||||
UIP_TCP_BUF->flags |= TCP_SYN;
|
||||
#else /* UIP_ACTIVE_OPEN */
|
||||
tcp_send_synack:
|
||||
UIP_TCP_BUF->flags = TCP_SYN | TCP_ACK;
|
||||
#endif /* UIP_ACTIVE_OPEN */
|
||||
|
||||
|
||||
/* We send out the TCP Maximum Segment Size option with our
|
||||
SYNACK. */
|
||||
UIP_TCP_BUF->optdata[0] = TCP_OPT_MSS;
|
||||
|
@ -1838,9 +1839,9 @@ uip_process(uint8_t flag)
|
|||
receive a SYN, in which case we should retransmit our SYNACK
|
||||
(which is done futher down). */
|
||||
if(!((((uip_connr->tcpstateflags & UIP_TS_MASK) == UIP_SYN_SENT) &&
|
||||
((UIP_TCP_BUF->flags & TCP_CTL) == (TCP_SYN | TCP_ACK))) ||
|
||||
((UIP_TCP_BUF->flags & TCP_CTL) == (TCP_SYN | TCP_ACK))) ||
|
||||
(((uip_connr->tcpstateflags & UIP_TS_MASK) == UIP_SYN_RCVD) &&
|
||||
((UIP_TCP_BUF->flags & TCP_CTL) == TCP_SYN)))) {
|
||||
((UIP_TCP_BUF->flags & TCP_CTL) == TCP_SYN)))) {
|
||||
if((uip_len > 0 || ((UIP_TCP_BUF->flags & (TCP_SYN | TCP_FIN)) != 0)) &&
|
||||
(UIP_TCP_BUF->seqno[0] != uip_connr->rcv_nxt[0] ||
|
||||
UIP_TCP_BUF->seqno[1] != uip_connr->rcv_nxt[1] ||
|
||||
|
@ -1874,7 +1875,7 @@ uip_process(uint8_t flag)
|
|||
uip_connr->snd_nxt[1] = uip_acc32[1];
|
||||
uip_connr->snd_nxt[2] = uip_acc32[2];
|
||||
uip_connr->snd_nxt[3] = uip_acc32[3];
|
||||
|
||||
|
||||
/* Do RTT estimation, unless we have done retransmissions. */
|
||||
if(uip_connr->nrtx == 0) {
|
||||
signed char m;
|
||||
|
@ -1898,7 +1899,7 @@ uip_process(uint8_t flag)
|
|||
/* Reset length of outstanding data. */
|
||||
uip_connr->len = 0;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/* Do different things depending on in what state the connection is. */
|
||||
|
@ -1926,7 +1927,7 @@ uip_process(uint8_t flag)
|
|||
}
|
||||
/* We need to retransmit the SYNACK */
|
||||
if((UIP_TCP_BUF->flags & TCP_CTL) == TCP_SYN) {
|
||||
goto tcp_send_synack;
|
||||
goto tcp_send_synack;
|
||||
}
|
||||
goto drop;
|
||||
#if UIP_ACTIVE_OPEN
|
||||
|
@ -1978,7 +1979,7 @@ uip_process(uint8_t flag)
|
|||
uip_add_rcv_nxt(1);
|
||||
uip_flags = UIP_CONNECTED | UIP_NEWDATA;
|
||||
uip_connr->len = 0;
|
||||
uip_len = 0;
|
||||
uip_clear_buf();
|
||||
uip_slen = 0;
|
||||
UIP_APPCALL();
|
||||
goto appsend;
|
||||
|
@ -1990,7 +1991,7 @@ uip_process(uint8_t flag)
|
|||
uip_conn->tcpstateflags = UIP_CLOSED;
|
||||
goto reset;
|
||||
#endif /* UIP_ACTIVE_OPEN */
|
||||
|
||||
|
||||
case UIP_ESTABLISHED:
|
||||
/* In the ESTABLISHED state, we call upon the application to feed
|
||||
data into the uip_buf. If the UIP_ACKDATA flag is set, the
|
||||
|
@ -2092,7 +2093,7 @@ uip_process(uint8_t flag)
|
|||
UIP_APPCALL();
|
||||
|
||||
appsend:
|
||||
|
||||
|
||||
if(uip_flags & UIP_ABORT) {
|
||||
uip_slen = 0;
|
||||
uip_connr->tcpstateflags = UIP_CLOSED;
|
||||
|
@ -2144,7 +2145,7 @@ uip_process(uint8_t flag)
|
|||
uip_connr->nrtx = 0;
|
||||
apprexmit:
|
||||
uip_appdata = uip_sappdata;
|
||||
|
||||
|
||||
/* If the application has data to be sent, or if the incoming
|
||||
packet had new data in it, we must send out a packet. */
|
||||
if(uip_slen > 0 && uip_connr->len > 0) {
|
||||
|
@ -2173,7 +2174,7 @@ uip_process(uint8_t flag)
|
|||
UIP_APPCALL();
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case UIP_FIN_WAIT_1:
|
||||
/* The application has closed the connection, but the remote host
|
||||
hasn't closed its end yet. Thus we do nothing but wait for a
|
||||
|
@ -2202,7 +2203,7 @@ uip_process(uint8_t flag)
|
|||
goto tcp_send_ack;
|
||||
}
|
||||
goto drop;
|
||||
|
||||
|
||||
case UIP_FIN_WAIT_2:
|
||||
if(uip_len > 0) {
|
||||
uip_add_rcv_nxt(uip_len);
|
||||
|
@ -2222,7 +2223,7 @@ uip_process(uint8_t flag)
|
|||
|
||||
case UIP_TIME_WAIT:
|
||||
goto tcp_send_ack;
|
||||
|
||||
|
||||
case UIP_CLOSING:
|
||||
if(uip_flags & UIP_ACKDATA) {
|
||||
uip_connr->tcpstateflags = UIP_TIME_WAIT;
|
||||
|
@ -2230,7 +2231,7 @@ uip_process(uint8_t flag)
|
|||
}
|
||||
}
|
||||
goto drop;
|
||||
|
||||
|
||||
/* We jump here when we are ready to send the packet, and just want
|
||||
to set the appropriate TCP sequence numbers in the TCP header. */
|
||||
tcp_send_ack:
|
||||
|
@ -2248,12 +2249,12 @@ uip_process(uint8_t flag)
|
|||
packet. */
|
||||
tcp_send:
|
||||
PRINTF("In tcp_send\n");
|
||||
|
||||
|
||||
UIP_TCP_BUF->ackno[0] = uip_connr->rcv_nxt[0];
|
||||
UIP_TCP_BUF->ackno[1] = uip_connr->rcv_nxt[1];
|
||||
UIP_TCP_BUF->ackno[2] = uip_connr->rcv_nxt[2];
|
||||
UIP_TCP_BUF->ackno[3] = uip_connr->rcv_nxt[3];
|
||||
|
||||
|
||||
UIP_TCP_BUF->seqno[0] = uip_connr->snd_nxt[0];
|
||||
UIP_TCP_BUF->seqno[1] = uip_connr->snd_nxt[1];
|
||||
UIP_TCP_BUF->seqno[2] = uip_connr->snd_nxt[2];
|
||||
|
@ -2287,7 +2288,7 @@ uip_process(uint8_t flag)
|
|||
UIP_IP_BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff);
|
||||
|
||||
UIP_TCP_BUF->urgp[0] = UIP_TCP_BUF->urgp[1] = 0;
|
||||
|
||||
|
||||
/* Calculate TCP checksum. */
|
||||
UIP_TCP_BUF->tcpchksum = 0;
|
||||
UIP_TCP_BUF->tcpchksum = ~(uip_tcpchksum());
|
||||
|
@ -2303,15 +2304,14 @@ uip_process(uint8_t flag)
|
|||
send:
|
||||
PRINTF("Sending packet with length %d (%d)\n", uip_len,
|
||||
(UIP_IP_BUF->len[0] << 8) | UIP_IP_BUF->len[1]);
|
||||
|
||||
|
||||
UIP_STAT(++uip_stat.ip.sent);
|
||||
/* Return and let the caller do the actual transmission. */
|
||||
uip_flags = 0;
|
||||
return;
|
||||
|
||||
drop:
|
||||
uip_len = 0;
|
||||
uip_ext_len = 0;
|
||||
uip_clear_buf();
|
||||
uip_ext_bitmap = 0;
|
||||
uip_flags = 0;
|
||||
return;
|
||||
|
|
|
@ -55,7 +55,8 @@ anti_replay_set_counter(void)
|
|||
{
|
||||
frame802154_frame_counter_t reordered_counter;
|
||||
|
||||
reordered_counter.u32 = LLSEC802154_HTONL(++counter);
|
||||
++counter;
|
||||
reordered_counter.u32 = LLSEC802154_HTONL(counter);
|
||||
|
||||
packetbuf_set_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_0_1, reordered_counter.u16[0]);
|
||||
packetbuf_set_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_2_3, reordered_counter.u16[1]);
|
||||
|
|
|
@ -1,52 +1,78 @@
|
|||
/*
|
||||
* Copyright (c) 2013, Hasso-Plattner-Institut.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the Institute nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the Contiki operating system.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
* CCM* convenience functions for LLSEC use
|
||||
* \author
|
||||
* Justin King-Lacroix <justin.kinglacroix@gmail.com>
|
||||
* Konrad Krentz <konrad.krentz@gmail.com>
|
||||
*/
|
||||
|
||||
#include "lib/ccm-star.h"
|
||||
#include "llsec/ccm-star-packetbuf.h"
|
||||
#include "net/linkaddr.h"
|
||||
#include "net/packetbuf.h"
|
||||
#include <string.h>
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void ccm_star_mic_packetbuf(const uint8_t *extended_source_address,
|
||||
uint8_t *result,
|
||||
uint8_t mic_len)
|
||||
static const uint8_t *
|
||||
get_extended_address(const linkaddr_t *addr)
|
||||
#if LINKADDR_SIZE == 2
|
||||
{
|
||||
uint8_t *dataptr = packetbuf_dataptr();
|
||||
uint8_t data_len = packetbuf_datalen();
|
||||
uint8_t *headerptr = packetbuf_hdrptr();
|
||||
uint8_t header_len = packetbuf_hdrlen();
|
||||
uint8_t nonce[CCM_STAR_NONCE_LENGTH];
|
||||
/* workaround for short addresses: derive EUI64 as in RFC 6282 */
|
||||
static linkaddr_extended_t template = { { 0x00 , 0x00 , 0x00 ,
|
||||
0xFF , 0xFE , 0x00 , 0x00 , 0x00 } };
|
||||
|
||||
memcpy(nonce, extended_source_address, 8);
|
||||
template.u16[3] = LLSEC802154_HTONS(addr->u16);
|
||||
|
||||
return template.u8;
|
||||
}
|
||||
#else /* LINKADDR_SIZE == 2 */
|
||||
{
|
||||
return addr->u8;
|
||||
}
|
||||
#endif /* LINKADDR_SIZE == 2 */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
ccm_star_packetbuf_set_nonce(uint8_t *nonce, int forward)
|
||||
{
|
||||
const linkaddr_t *source_addr;
|
||||
|
||||
source_addr = forward ? &linkaddr_node_addr : packetbuf_addr(PACKETBUF_ADDR_SENDER);
|
||||
memcpy(nonce, get_extended_address(source_addr), 8);
|
||||
nonce[8] = packetbuf_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_2_3) >> 8;
|
||||
nonce[9] = packetbuf_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_2_3) & 0xff;
|
||||
nonce[10] = packetbuf_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_0_1) >> 8;
|
||||
nonce[11] = packetbuf_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_0_1) & 0xff;
|
||||
nonce[12] = packetbuf_attr(PACKETBUF_ATTR_SECURITY_LEVEL);
|
||||
|
||||
if(packetbuf_attr(PACKETBUF_ATTR_SECURITY_LEVEL) & (1 << 2)) {
|
||||
CCM_STAR.mic(dataptr, data_len, nonce, headerptr, header_len, result, mic_len);
|
||||
} else {
|
||||
CCM_STAR.mic(dataptr, 0, nonce, headerptr, packetbuf_totlen(), result, mic_len);
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void ccm_star_ctr_packetbuf(const uint8_t *extended_source_address)
|
||||
{
|
||||
uint8_t *dataptr = packetbuf_dataptr();
|
||||
uint8_t data_len = packetbuf_datalen();
|
||||
uint8_t nonce[CCM_STAR_NONCE_LENGTH];
|
||||
|
||||
memcpy(nonce, extended_source_address, 8);
|
||||
nonce[8] = packetbuf_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_2_3) >> 8;
|
||||
nonce[9] = packetbuf_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_2_3) & 0xff;
|
||||
nonce[10] = packetbuf_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_0_1) >> 8;
|
||||
nonce[11] = packetbuf_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_0_1) & 0xff;
|
||||
nonce[12] = packetbuf_attr(PACKETBUF_ATTR_SECURITY_LEVEL);
|
||||
|
||||
CCM_STAR.ctr(dataptr, data_len, nonce);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
|
|
@ -1,24 +1,48 @@
|
|||
/*
|
||||
* Copyright (c) 2013, Hasso-Plattner-Institut.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the Institute nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the Contiki operating system.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
* CCM* convenience functions for MAC security
|
||||
* \author
|
||||
* Justin King-Lacroix <justin.kinglacroix@gmail.com>
|
||||
* Konrad Krentz <konrad.krentz@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef CCM_STAR_PACKETBUF_H_
|
||||
#define CCM_STAR_PACKETBUF_H_
|
||||
|
||||
/**
|
||||
* \brief Calls CCM_STAR.mic with parameters appropriate for LLSEC.
|
||||
*/
|
||||
void ccm_star_mic_packetbuf(const uint8_t *extended_source_address,
|
||||
uint8_t *result,
|
||||
uint8_t mic_len);
|
||||
#include "lib/ccm-star.h"
|
||||
|
||||
/**
|
||||
* \brief Calls CCM_STAR.ctr with parameters appropriate for LLSEC.
|
||||
*/
|
||||
void ccm_star_ctr_packetbuf(const uint8_t *extended_source_address);
|
||||
void ccm_star_packetbuf_set_nonce(uint8_t *nonce, int forward);
|
||||
|
||||
#endif /* CCM_STAR_PACKETBUF_H_ */
|
||||
|
||||
|
|
|
@ -48,10 +48,6 @@
|
|||
* for incoming packets. Likewise, all NETSTACK_NETWORK protocols
|
||||
* invoke NETSTACK_LLSEC.send(...) for outgoing packets.
|
||||
*
|
||||
* The bootstrap function of llsec_drivers can be used to defer the start
|
||||
* of upper layers so as to bootstrap pairwise keys. Only contiki-sky-main.c
|
||||
* supports this at the moment.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
@ -60,35 +56,23 @@
|
|||
|
||||
#include "net/mac/mac.h"
|
||||
|
||||
typedef void (* llsec_on_bootstrapped_t)(void);
|
||||
|
||||
/**
|
||||
* The structure of a link layer security driver.
|
||||
*/
|
||||
struct llsec_driver {
|
||||
char *name;
|
||||
|
||||
/** Bootstraps link layer security and thereafter starts upper layers. */
|
||||
void (* bootstrap)(llsec_on_bootstrapped_t on_bootstrapped);
|
||||
/** Inits link layer security. */
|
||||
void (* init)(void);
|
||||
|
||||
/** Secures outgoing frames before passing them to NETSTACK_MAC. */
|
||||
void (* send)(mac_callback_t sent_callback, void *ptr);
|
||||
|
||||
/**
|
||||
* Once the NETSTACK_FRAMER wrote the headers, the LLSEC driver
|
||||
* can generate a MIC over the entire frame.
|
||||
* \return Returns != 0 <-> success
|
||||
*/
|
||||
int (* on_frame_created)(void);
|
||||
|
||||
/**
|
||||
* Decrypts incoming frames;
|
||||
* filters out injected or replayed frames.
|
||||
*/
|
||||
void (* input)(void);
|
||||
|
||||
/** Returns the security-related overhead per frame in bytes */
|
||||
uint8_t (* get_overhead)(void);
|
||||
};
|
||||
|
||||
#endif /* LLSEC_H_ */
|
||||
|
|
|
@ -85,6 +85,12 @@
|
|||
#define LLSEC802154_USES_EXPLICIT_KEYS 0
|
||||
#endif /* LLSEC802154_CONF_USES_EXPLICIT_KEYS */
|
||||
|
||||
#ifdef LLSEC802154_CONF_USES_FRAME_COUNTER
|
||||
#define LLSEC802154_USES_FRAME_COUNTER LLSEC802154_CONF_USES_FRAME_COUNTER
|
||||
#else /* LLSEC802154_CONF_USES_FRAME_COUNTER */
|
||||
#define LLSEC802154_USES_FRAME_COUNTER (LLSEC802154_SECURITY_LEVEL != FRAME802154_SECURITY_LEVEL_NONE)
|
||||
#endif /* LLSEC802154_CONF_USES_FRAME_COUNTER */
|
||||
|
||||
#if UIP_BYTE_ORDER == UIP_LITTLE_ENDIAN
|
||||
#define LLSEC802154_HTONS(n) (n)
|
||||
#define LLSEC802154_HTONL(n) (n)
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
#include "net/llsec/llsec802154.h"
|
||||
#include "net/llsec/ccm-star-packetbuf.h"
|
||||
#include "net/mac/frame802154.h"
|
||||
#include "net/mac/framer-802154.h"
|
||||
#include "net/netstack.h"
|
||||
#include "net/packetbuf.h"
|
||||
#include "net/nbr-table.h"
|
||||
|
@ -80,81 +81,109 @@ static uint8_t key[16] = NONCORESEC_KEY;
|
|||
NBR_TABLE(struct anti_replay_info, anti_replay_table);
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static const uint8_t *
|
||||
get_extended_address(const linkaddr_t *addr)
|
||||
#if LINKADDR_SIZE == 2
|
||||
static int
|
||||
aead(uint8_t hdrlen, int forward)
|
||||
{
|
||||
/* workaround for short addresses: derive EUI64 as in RFC 6282 */
|
||||
static linkaddr_extended_t template = { { 0x00 , 0x00 , 0x00 ,
|
||||
0xFF , 0xFE , 0x00 , 0x00 , 0x00 } };
|
||||
uint8_t totlen;
|
||||
uint8_t nonce[CCM_STAR_NONCE_LENGTH];
|
||||
uint8_t *m;
|
||||
uint8_t m_len;
|
||||
uint8_t *a;
|
||||
uint8_t a_len;
|
||||
uint8_t *result;
|
||||
uint8_t generated_mic[LLSEC802154_MIC_LENGTH];
|
||||
uint8_t *mic;
|
||||
|
||||
template.u16[3] = LLSEC802154_HTONS(addr->u16);
|
||||
ccm_star_packetbuf_set_nonce(nonce, forward);
|
||||
totlen = packetbuf_totlen();
|
||||
a = packetbuf_hdrptr();
|
||||
#if WITH_ENCRYPTION
|
||||
a_len = hdrlen;
|
||||
m = a + a_len;
|
||||
m_len = totlen - hdrlen;
|
||||
#else /* WITH_ENCRYPTION */
|
||||
a_len = totlen;
|
||||
m = NULL;
|
||||
m_len = 0;
|
||||
#endif /* WITH_ENCRYPTION */
|
||||
|
||||
return template.u8;
|
||||
mic = a + totlen;
|
||||
result = forward ? mic : generated_mic;
|
||||
|
||||
CCM_STAR.aead(nonce,
|
||||
m, m_len,
|
||||
a, a_len,
|
||||
result, LLSEC802154_MIC_LENGTH,
|
||||
forward);
|
||||
|
||||
if(forward) {
|
||||
packetbuf_set_datalen(packetbuf_datalen() + LLSEC802154_MIC_LENGTH);
|
||||
return 1;
|
||||
} else {
|
||||
return (memcmp(generated_mic, mic, LLSEC802154_MIC_LENGTH) == 0);
|
||||
}
|
||||
}
|
||||
#else /* LINKADDR_SIZE == 2 */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
add_security_header(void)
|
||||
{
|
||||
return addr->u8;
|
||||
if(!packetbuf_attr(PACKETBUF_ATTR_SECURITY_LEVEL)) {
|
||||
packetbuf_set_attr(PACKETBUF_ATTR_FRAME_TYPE, FRAME802154_DATAFRAME);
|
||||
packetbuf_set_attr(PACKETBUF_ATTR_SECURITY_LEVEL, LLSEC802154_SECURITY_LEVEL);
|
||||
anti_replay_set_counter();
|
||||
}
|
||||
}
|
||||
#endif /* LINKADDR_SIZE == 2 */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
send(mac_callback_t sent, void *ptr)
|
||||
{
|
||||
packetbuf_set_attr(PACKETBUF_ATTR_FRAME_TYPE, FRAME802154_DATAFRAME);
|
||||
packetbuf_set_attr(PACKETBUF_ATTR_SECURITY_LEVEL, LLSEC802154_SECURITY_LEVEL);
|
||||
anti_replay_set_counter();
|
||||
NETSTACK_MAC.send(sent, ptr);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static int
|
||||
on_frame_created(void)
|
||||
create(void)
|
||||
{
|
||||
uint8_t *dataptr = packetbuf_dataptr();
|
||||
uint8_t data_len = packetbuf_datalen();
|
||||
|
||||
ccm_star_mic_packetbuf(get_extended_address(&linkaddr_node_addr), dataptr + data_len, LLSEC802154_MIC_LENGTH);
|
||||
#if WITH_ENCRYPTION
|
||||
ccm_star_ctr_packetbuf(get_extended_address(&linkaddr_node_addr));
|
||||
#endif /* WITH_ENCRYPTION */
|
||||
packetbuf_set_datalen(data_len + LLSEC802154_MIC_LENGTH);
|
||||
int result;
|
||||
|
||||
return 1;
|
||||
add_security_header();
|
||||
result = framer_802154.create();
|
||||
if(result == FRAMER_FAILED) {
|
||||
return result;
|
||||
}
|
||||
|
||||
aead(result, 1);
|
||||
|
||||
return result;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
input(void)
|
||||
static int
|
||||
parse(void)
|
||||
{
|
||||
uint8_t generated_mic[LLSEC802154_MIC_LENGTH];
|
||||
uint8_t *received_mic;
|
||||
int result;
|
||||
const linkaddr_t *sender;
|
||||
struct anti_replay_info* info;
|
||||
uint8_t *dataptr = packetbuf_dataptr();
|
||||
uint8_t data_len = packetbuf_datalen();
|
||||
|
||||
result = framer_802154.parse();
|
||||
if(result == FRAMER_FAILED) {
|
||||
return result;
|
||||
}
|
||||
|
||||
if(packetbuf_attr(PACKETBUF_ATTR_SECURITY_LEVEL) != LLSEC802154_SECURITY_LEVEL) {
|
||||
PRINTF("noncoresec: received frame with wrong security level\n");
|
||||
return;
|
||||
return FRAMER_FAILED;
|
||||
}
|
||||
sender = packetbuf_addr(PACKETBUF_ADDR_SENDER);
|
||||
if(linkaddr_cmp(sender, &linkaddr_node_addr)) {
|
||||
PRINTF("noncoresec: frame from ourselves\n");
|
||||
return;
|
||||
return FRAMER_FAILED;
|
||||
}
|
||||
|
||||
data_len -= LLSEC802154_MIC_LENGTH;
|
||||
packetbuf_set_datalen(data_len);
|
||||
packetbuf_set_datalen(packetbuf_datalen() - LLSEC802154_MIC_LENGTH);
|
||||
|
||||
#if WITH_ENCRYPTION
|
||||
ccm_star_ctr_packetbuf(get_extended_address(sender));
|
||||
#endif /* WITH_ENCRYPTION */
|
||||
ccm_star_mic_packetbuf(get_extended_address(sender), generated_mic, LLSEC802154_MIC_LENGTH);
|
||||
|
||||
received_mic = dataptr + data_len;
|
||||
if(memcmp(generated_mic, received_mic, LLSEC802154_MIC_LENGTH) != 0) {
|
||||
PRINTF("noncoresec: received nonauthentic frame %"PRIu32"\n",
|
||||
if(!aead(result, 0)) {
|
||||
PRINTF("noncoresec: received unauthentic frame %"PRIu32"\n",
|
||||
anti_replay_get_counter());
|
||||
return;
|
||||
return FRAMER_FAILED;
|
||||
}
|
||||
|
||||
info = nbr_table_get_from_lladdr(anti_replay_table, sender);
|
||||
|
@ -162,7 +191,7 @@ input(void)
|
|||
info = nbr_table_add_lladdr(anti_replay_table, sender);
|
||||
if(!info) {
|
||||
PRINTF("noncoresec: could not get nbr_table_item\n");
|
||||
return;
|
||||
return FRAMER_FAILED;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -179,7 +208,7 @@ input(void)
|
|||
if(!nbr_table_lock(anti_replay_table, info)) {
|
||||
nbr_table_remove(anti_replay_table, info);
|
||||
PRINTF("noncoresec: could not lock\n");
|
||||
return;
|
||||
return FRAMER_FAILED;
|
||||
}
|
||||
|
||||
anti_replay_init_info(info);
|
||||
|
@ -187,34 +216,44 @@ input(void)
|
|||
if(anti_replay_was_replayed(info)) {
|
||||
PRINTF("noncoresec: received replayed frame %"PRIu32"\n",
|
||||
anti_replay_get_counter());
|
||||
return;
|
||||
return FRAMER_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
NETSTACK_NETWORK.input();
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static uint8_t
|
||||
get_overhead(void)
|
||||
{
|
||||
return SECURITY_HEADER_LENGTH + LLSEC802154_MIC_LENGTH;
|
||||
return result;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
bootstrap(llsec_on_bootstrapped_t on_bootstrapped)
|
||||
input(void)
|
||||
{
|
||||
NETSTACK_NETWORK.input();
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static int
|
||||
length(void)
|
||||
{
|
||||
add_security_header();
|
||||
return framer_802154.length() + LLSEC802154_MIC_LENGTH;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
init(void)
|
||||
{
|
||||
CCM_STAR.set_key(key);
|
||||
nbr_table_register(anti_replay_table, NULL);
|
||||
on_bootstrapped();
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
const struct llsec_driver noncoresec_driver = {
|
||||
"noncoresec",
|
||||
bootstrap,
|
||||
init,
|
||||
send,
|
||||
on_frame_created,
|
||||
input,
|
||||
get_overhead
|
||||
input
|
||||
};
|
||||
/*---------------------------------------------------------------------------*/
|
||||
const struct framer noncoresec_framer = {
|
||||
length,
|
||||
create,
|
||||
parse
|
||||
};
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
|
|
|
@ -56,6 +56,7 @@
|
|||
#include "net/llsec/llsec.h"
|
||||
|
||||
extern const struct llsec_driver noncoresec_driver;
|
||||
extern const struct framer noncoresec_framer;
|
||||
|
||||
#endif /* NONCORESEC_H_ */
|
||||
|
||||
|
|
|
@ -49,9 +49,9 @@
|
|||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
bootstrap(llsec_on_bootstrapped_t on_bootstrapped)
|
||||
init(void)
|
||||
{
|
||||
on_bootstrapped();
|
||||
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
|
@ -61,31 +61,17 @@ send(mac_callback_t sent, void *ptr)
|
|||
NETSTACK_MAC.send(sent, ptr);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static int
|
||||
on_frame_created(void)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
input(void)
|
||||
{
|
||||
NETSTACK_NETWORK.input();
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static uint8_t
|
||||
get_overhead(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
const struct llsec_driver nullsec_driver = {
|
||||
"nullsec",
|
||||
bootstrap,
|
||||
init,
|
||||
send,
|
||||
on_frame_created,
|
||||
input,
|
||||
get_overhead
|
||||
input
|
||||
};
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
|
|
|
@ -73,6 +73,8 @@ extern const struct framer DECORATED_FRAMER;
|
|||
#define PRINTF(...)
|
||||
#endif
|
||||
|
||||
static void pad(void);
|
||||
|
||||
/* 2-byte header for recovering padded packets.
|
||||
Wireshark will not understand such packets at present. */
|
||||
struct hdr {
|
||||
|
@ -99,7 +101,8 @@ create(void)
|
|||
}
|
||||
chdr = packetbuf_hdrptr();
|
||||
chdr->id = CONTIKIMAC_ID;
|
||||
chdr->len = 0;
|
||||
chdr->len = packetbuf_datalen();
|
||||
pad();
|
||||
|
||||
hdr_len = DECORATED_FRAMER.create();
|
||||
if(hdr_len < 0) {
|
||||
|
@ -107,6 +110,8 @@ create(void)
|
|||
return FRAMER_FAILED;
|
||||
}
|
||||
|
||||
packetbuf_compact();
|
||||
|
||||
return hdr_len + sizeof(struct hdr);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
@ -117,7 +122,7 @@ pad(void)
|
|||
uint8_t *ptr;
|
||||
uint8_t zeroes_count;
|
||||
|
||||
transmit_len = packetbuf_totlen();
|
||||
transmit_len = packetbuf_totlen() + hdr_length();
|
||||
if(transmit_len < SHORTEST_PACKET_SIZE) {
|
||||
/* Padding required */
|
||||
zeroes_count = SHORTEST_PACKET_SIZE - transmit_len;
|
||||
|
@ -128,30 +133,6 @@ pad(void)
|
|||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static int
|
||||
create_and_secure(void)
|
||||
{
|
||||
struct hdr *chdr;
|
||||
int hdr_len;
|
||||
|
||||
hdr_len = create();
|
||||
if(hdr_len < 0) {
|
||||
return FRAMER_FAILED;
|
||||
}
|
||||
|
||||
packetbuf_compact();
|
||||
if(!NETSTACK_LLSEC.on_frame_created()) {
|
||||
PRINTF("contikimac-framer: securing failed\n");
|
||||
return FRAMER_FAILED;
|
||||
}
|
||||
|
||||
chdr = (struct hdr *)(((uint8_t *) packetbuf_dataptr()) - sizeof(struct hdr));
|
||||
chdr->len = packetbuf_datalen();
|
||||
pad();
|
||||
|
||||
return hdr_len;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static int
|
||||
parse(void)
|
||||
{
|
||||
int hdr_len;
|
||||
|
@ -174,7 +155,6 @@ parse(void)
|
|||
}
|
||||
|
||||
packetbuf_set_datalen(chdr->len);
|
||||
chdr->len = 0;
|
||||
|
||||
return hdr_len + sizeof(struct hdr);
|
||||
}
|
||||
|
@ -182,7 +162,6 @@ parse(void)
|
|||
const struct framer contikimac_framer = {
|
||||
hdr_length,
|
||||
create,
|
||||
create_and_secure,
|
||||
parse
|
||||
};
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
|
|
@ -106,7 +106,11 @@ static int we_are_receiving_burst = 0;
|
|||
|
||||
/* INTER_PACKET_DEADLINE is the maximum time a receiver waits for the
|
||||
next packet of a burst when FRAME_PENDING is set. */
|
||||
#ifdef CONTIKIMAC_CONF_INTER_PACKET_DEADLINE
|
||||
#define INTER_PACKET_DEADLINE CONTIKIMAC_CONF_INTER_PACKET_DEADLINE
|
||||
#else
|
||||
#define INTER_PACKET_DEADLINE CLOCK_SECOND / 32
|
||||
#endif
|
||||
|
||||
/* ContikiMAC performs periodic channel checks. Each channel check
|
||||
consists of two or more CCA checks. CCA_COUNT_MAX is the number of
|
||||
|
@ -166,12 +170,21 @@ static int we_are_receiving_burst = 0;
|
|||
/* MAX_SILENCE_PERIODS is the maximum amount of periods (a period is
|
||||
CCA_CHECK_TIME + CCA_SLEEP_TIME) that we allow to be silent before
|
||||
we turn of the radio. */
|
||||
#ifdef CONTIKIMAC_CONF_MAX_SILENCE_PERIODS
|
||||
#define MAX_SILENCE_PERIODS CONTIKIMAC_CONF_MAX_SILENCE_PERIODS
|
||||
#else
|
||||
#define MAX_SILENCE_PERIODS 5
|
||||
#endif
|
||||
|
||||
/* MAX_NONACTIVITY_PERIODS is the maximum number of periods we allow
|
||||
the radio to be turned on without any packet being received, when
|
||||
WITH_FAST_SLEEP is enabled. */
|
||||
#ifdef CONTIKIMAC_CONF_MAX_NONACTIVITY_PERIODS
|
||||
#define MAX_NONACTIVITY_PERIODS CONTIKIMAC_CONF_MAX_NONACTIVITY_PERIODS
|
||||
#else
|
||||
#define MAX_NONACTIVITY_PERIODS 10
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -181,7 +194,11 @@ static int we_are_receiving_burst = 0;
|
|||
|
||||
/* GUARD_TIME is the time before the expected phase of a neighbor that
|
||||
a transmitted should begin transmitting packets. */
|
||||
#ifdef CONTIKIMAC_CONF_GUARD_TIME
|
||||
#define GUARD_TIME CONTIKIMAC_CONF_GUARD_TIME
|
||||
#else
|
||||
#define GUARD_TIME 10 * CHECK_TIME + CHECK_TIME_TX
|
||||
#endif
|
||||
|
||||
/* INTER_PACKET_INTERVAL is the interval between two successive packet transmissions */
|
||||
#ifdef CONTIKIMAC_CONF_INTER_PACKET_INTERVAL
|
||||
|
@ -201,7 +218,11 @@ static int we_are_receiving_burst = 0;
|
|||
|
||||
/* MAX_PHASE_STROBE_TIME is the time that we transmit repeated packets
|
||||
to a neighbor for which we have a phase lock. */
|
||||
#ifdef CONTIKIMAC_CONF_MAX_PHASE_STROBE_TIME
|
||||
#define MAX_PHASE_STROBE_TIME CONTIKIMAC_CONF_MAX_PHASE_STROBE_TIME
|
||||
#else
|
||||
#define MAX_PHASE_STROBE_TIME RTIMER_ARCH_SECOND / 60
|
||||
#endif
|
||||
|
||||
#ifdef CONTIKIMAC_CONF_SEND_SW_ACK
|
||||
#define CONTIKIMAC_SEND_SW_ACK CONTIKIMAC_CONF_SEND_SW_ACK
|
||||
|
@ -269,20 +290,24 @@ off(void)
|
|||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static volatile rtimer_clock_t cycle_start;
|
||||
static void powercycle_wrapper(struct rtimer *t, void *ptr);
|
||||
static char powercycle(struct rtimer *t, void *ptr);
|
||||
static void
|
||||
schedule_powercycle(struct rtimer *t, rtimer_clock_t time)
|
||||
{
|
||||
int r;
|
||||
rtimer_clock_t now;
|
||||
|
||||
if(contikimac_is_on) {
|
||||
|
||||
if(RTIMER_CLOCK_LT(RTIMER_TIME(t) + time, RTIMER_NOW() + 2)) {
|
||||
time = RTIMER_NOW() - RTIMER_TIME(t) + 2;
|
||||
time += RTIMER_TIME(t);
|
||||
now = RTIMER_NOW();
|
||||
if(RTIMER_CLOCK_LT(time, now + RTIMER_GUARD_TIME)) {
|
||||
time = now + RTIMER_GUARD_TIME;
|
||||
}
|
||||
|
||||
r = rtimer_set(t, RTIMER_TIME(t) + time, 1,
|
||||
(void (*)(struct rtimer *, void *))powercycle, NULL);
|
||||
r = rtimer_set(t, time, 1, powercycle_wrapper, NULL);
|
||||
|
||||
if(r != RTIMER_OK) {
|
||||
PRINTF("schedule_powercycle: could not set rtimer\n");
|
||||
}
|
||||
|
@ -293,15 +318,16 @@ static void
|
|||
schedule_powercycle_fixed(struct rtimer *t, rtimer_clock_t fixed_time)
|
||||
{
|
||||
int r;
|
||||
rtimer_clock_t now;
|
||||
|
||||
if(contikimac_is_on) {
|
||||
|
||||
if(RTIMER_CLOCK_LT(fixed_time, RTIMER_NOW() + 1)) {
|
||||
fixed_time = RTIMER_NOW() + 1;
|
||||
now = RTIMER_NOW();
|
||||
if(RTIMER_CLOCK_LT(fixed_time, now + RTIMER_GUARD_TIME)) {
|
||||
fixed_time = now + RTIMER_GUARD_TIME;
|
||||
}
|
||||
|
||||
r = rtimer_set(t, fixed_time, 1,
|
||||
(void (*)(struct rtimer *, void *))powercycle, NULL);
|
||||
r = rtimer_set(t, fixed_time, 1, powercycle_wrapper, NULL);
|
||||
if(r != RTIMER_OK) {
|
||||
PRINTF("schedule_powercycle: could not set rtimer\n");
|
||||
}
|
||||
|
@ -335,6 +361,12 @@ powercycle_turn_radio_on(void)
|
|||
/*---------------------------------------------------------------------------*/
|
||||
volatile uint8_t mcusleepcycle=16;
|
||||
|
||||
static void
|
||||
powercycle_wrapper(struct rtimer *t, void *ptr)
|
||||
{
|
||||
powercycle(t, ptr);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static char
|
||||
powercycle(struct rtimer *t, void *ptr)
|
||||
{
|
||||
|
@ -511,14 +543,16 @@ send_packet(mac_callback_t mac_callback, void *mac_callback_ptr,
|
|||
#endif
|
||||
int strobes;
|
||||
uint8_t got_strobe_ack = 0;
|
||||
int len;
|
||||
uint8_t is_broadcast = 0;
|
||||
uint8_t is_known_receiver = 0;
|
||||
uint8_t collisions;
|
||||
int transmit_len;
|
||||
int ret;
|
||||
uint8_t contikimac_was_on;
|
||||
#if !RDC_CONF_HARDWARE_ACK
|
||||
int len;
|
||||
uint8_t seqno;
|
||||
#endif
|
||||
|
||||
/* Exit if RDC and radio were explicitly turned off */
|
||||
if(!contikimac_is_on && !contikimac_keep_radio_on) {
|
||||
|
@ -562,7 +596,7 @@ send_packet(mac_callback_t mac_callback, void *mac_callback_ptr,
|
|||
|
||||
if(!packetbuf_attr(PACKETBUF_ATTR_IS_CREATED_AND_SECURED)) {
|
||||
packetbuf_set_attr(PACKETBUF_ATTR_MAC_ACK, 1);
|
||||
if(NETSTACK_FRAMER.create_and_secure() < 0) {
|
||||
if(NETSTACK_FRAMER.create() < 0) {
|
||||
PRINTF("contikimac: framer failed\n");
|
||||
return MAC_TX_ERR_FATAL;
|
||||
}
|
||||
|
@ -659,11 +693,11 @@ send_packet(mac_callback_t mac_callback, void *mac_callback_ptr,
|
|||
or rx cycle */
|
||||
on();
|
||||
}
|
||||
seqno = packetbuf_attr(PACKETBUF_ATTR_MAC_SEQNO);
|
||||
#endif
|
||||
|
||||
watchdog_periodic();
|
||||
t0 = RTIMER_NOW();
|
||||
seqno = packetbuf_attr(PACKETBUF_ATTR_MAC_SEQNO);
|
||||
for(strobes = 0, collisions = 0;
|
||||
got_strobe_ack == 0 && collisions == 0 &&
|
||||
RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + STROBE_TIME); strobes++) {
|
||||
|
@ -678,7 +712,9 @@ send_packet(mac_callback_t mac_callback, void *mac_callback_ptr,
|
|||
}
|
||||
#endif /* WITH_PHASE_OPTIMIZATION */
|
||||
|
||||
#if !RDC_CONF_HARDWARE_ACK
|
||||
len = 0;
|
||||
#endif
|
||||
|
||||
{
|
||||
rtimer_clock_t wt;
|
||||
|
@ -807,6 +843,7 @@ qsend_list(mac_callback_t sent, void *ptr, struct rdc_buf_list *buf_list)
|
|||
struct rdc_buf_list *next;
|
||||
int ret;
|
||||
int is_receiver_awake;
|
||||
int pending;
|
||||
|
||||
if(buf_list == NULL) {
|
||||
return;
|
||||
|
@ -831,7 +868,7 @@ qsend_list(mac_callback_t sent, void *ptr, struct rdc_buf_list *buf_list)
|
|||
packetbuf_set_attr(PACKETBUF_ATTR_PENDING, 1);
|
||||
}
|
||||
packetbuf_set_attr(PACKETBUF_ATTR_MAC_ACK, 1);
|
||||
if(NETSTACK_FRAMER.create_and_secure() < 0) {
|
||||
if(NETSTACK_FRAMER.create() < 0) {
|
||||
PRINTF("contikimac: framer failed\n");
|
||||
mac_call_sent_callback(sent, ptr, MAC_TX_ERR_FATAL, 1);
|
||||
return;
|
||||
|
@ -851,7 +888,9 @@ qsend_list(mac_callback_t sent, void *ptr, struct rdc_buf_list *buf_list)
|
|||
|
||||
/* Prepare the packetbuf */
|
||||
queuebuf_to_packetbuf(curr->buf);
|
||||
|
||||
|
||||
pending = packetbuf_attr(PACKETBUF_ATTR_PENDING);
|
||||
|
||||
/* Send the current packet */
|
||||
ret = send_packet(sent, ptr, curr, is_receiver_awake);
|
||||
if(ret != MAC_TX_DEFERRED) {
|
||||
|
@ -868,7 +907,7 @@ qsend_list(mac_callback_t sent, void *ptr, struct rdc_buf_list *buf_list)
|
|||
/* The transmission failed, we stop the burst */
|
||||
next = NULL;
|
||||
}
|
||||
} while((next != NULL) && packetbuf_attr(PACKETBUF_ATTR_PENDING));
|
||||
} while((next != NULL) && pending);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Timer callback triggered when receiving a burst, after having
|
||||
|
@ -917,8 +956,6 @@ input_packet(void)
|
|||
broadcast address. */
|
||||
|
||||
/* If FRAME_PENDING is set, we are receiving a packets in a burst */
|
||||
/* TODO To prevent denial-of-sleep attacks, the transceiver should
|
||||
be disabled upon receipt of an unauthentic frame. */
|
||||
we_are_receiving_burst = packetbuf_attr(PACKETBUF_ATTR_PENDING);
|
||||
if(we_are_receiving_burst) {
|
||||
on();
|
||||
|
@ -995,8 +1032,7 @@ init(void)
|
|||
radio_is_on = 0;
|
||||
PT_INIT(&pt);
|
||||
|
||||
rtimer_set(&rt, RTIMER_NOW() + CYCLE_TIME, 1,
|
||||
(void (*)(struct rtimer *, void *))powercycle, NULL);
|
||||
rtimer_set(&rt, RTIMER_NOW() + CYCLE_TIME, 1, powercycle_wrapper, NULL);
|
||||
|
||||
contikimac_is_on = 1;
|
||||
|
||||
|
@ -1012,8 +1048,7 @@ turn_on(void)
|
|||
if(contikimac_is_on == 0) {
|
||||
contikimac_is_on = 1;
|
||||
contikimac_keep_radio_on = 0;
|
||||
rtimer_set(&rt, RTIMER_NOW() + CYCLE_TIME, 1,
|
||||
(void (*)(struct rtimer *, void *))powercycle, NULL);
|
||||
rtimer_set(&rt, RTIMER_NOW() + CYCLE_TIME, 1, powercycle_wrapper, NULL);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -171,8 +171,10 @@ transmit_packet_list(void *ptr)
|
|||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
free_packet(struct neighbor_queue *n, struct rdc_buf_list *p)
|
||||
free_packet(struct neighbor_queue *n, struct rdc_buf_list *p, int status)
|
||||
{
|
||||
clock_time_t tx_delay;
|
||||
|
||||
if(p != NULL) {
|
||||
/* Remove packet from list and deallocate */
|
||||
list_remove(n->queued_packet_list, p);
|
||||
|
@ -188,8 +190,8 @@ free_packet(struct neighbor_queue *n, struct rdc_buf_list *p)
|
|||
n->collisions = 0;
|
||||
n->deferrals = 0;
|
||||
/* Set a timer for next transmissions */
|
||||
ctimer_set(&n->transmit_timer, default_timebase(),
|
||||
transmit_packet_list, n);
|
||||
tx_delay = (status == MAC_TX_OK) ? 0 : default_timebase();
|
||||
ctimer_set(&n->transmit_timer, tx_delay, transmit_packet_list, n);
|
||||
} else {
|
||||
/* This was the last packet in the queue, we free the neighbor */
|
||||
ctimer_stop(&n->transmit_timer);
|
||||
|
@ -293,7 +295,7 @@ packet_sent(void *ptr, int status, int num_transmissions)
|
|||
} else {
|
||||
PRINTF("csma: drop with status %d after %d transmissions, %d collisions\n",
|
||||
status, n->transmissions, n->collisions);
|
||||
free_packet(n, q);
|
||||
free_packet(n, q, status);
|
||||
mac_call_sent_callback(sent, cptr, status, num_tx);
|
||||
}
|
||||
} else {
|
||||
|
@ -302,7 +304,7 @@ packet_sent(void *ptr, int status, int num_transmissions)
|
|||
} else {
|
||||
PRINTF("csma: rexmit failed %d: %d\n", n->transmissions, status);
|
||||
}
|
||||
free_packet(n, q);
|
||||
free_packet(n, q, status);
|
||||
mac_call_sent_callback(sent, cptr, status, num_tx);
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -44,11 +44,11 @@
|
|||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
*/
|
||||
/*
|
||||
* \brief This file is where the main functions that relate to frame
|
||||
* manipulation will reside.
|
||||
*/
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
|
@ -61,7 +61,7 @@
|
|||
/**
|
||||
* \addtogroup frame802154
|
||||
* @{
|
||||
*/
|
||||
*/
|
||||
|
||||
#include "sys/cc.h"
|
||||
#include "net/mac/frame802154.h"
|
||||
|
@ -69,11 +69,18 @@
|
|||
#include "net/linkaddr.h"
|
||||
#include <string.h>
|
||||
|
||||
/** \brief The 16-bit identifier of the PAN on which the device is
|
||||
* operating. If this value is 0xffff, the device is not
|
||||
* associated.
|
||||
*/
|
||||
static uint16_t mac_pan_id = IEEE802154_PANID;
|
||||
|
||||
/**
|
||||
* \brief Structure that contains the lengths of the various addressing and security fields
|
||||
* in the 802.15.4 header. This structure is used in \ref frame802154_create()
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t seqno_len; /**< Length (in bytes) of sequence number field */
|
||||
uint8_t dest_pid_len; /**< Length (in bytes) of destination PAN ID field */
|
||||
uint8_t dest_addr_len; /**< Length (in bytes) of destination address field */
|
||||
uint8_t src_pid_len; /**< Length (in bytes) of source PAN ID field */
|
||||
|
@ -111,30 +118,199 @@ get_key_id_len(uint8_t key_id_mode)
|
|||
}
|
||||
}
|
||||
#endif /* LLSEC802154_USES_EXPLICIT_KEYS */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Get current PAN ID */
|
||||
uint16_t
|
||||
frame802154_get_pan_id(void)
|
||||
{
|
||||
return mac_pan_id;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Set current PAN ID */
|
||||
void
|
||||
frame802154_set_pan_id(uint16_t pan_id)
|
||||
{
|
||||
mac_pan_id = pan_id;
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Tells whether a given Frame Control Field indicates a frame with
|
||||
* source PANID and/or destination PANID */
|
||||
void
|
||||
frame802154_has_panid(frame802154_fcf_t *fcf, int *has_src_pan_id, int *has_dest_pan_id)
|
||||
{
|
||||
int src_pan_id = 0;
|
||||
int dest_pan_id = 0;
|
||||
|
||||
if(fcf == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(fcf->frame_version == FRAME802154_IEEE802154E_2012) {
|
||||
if(!fcf->panid_compression) {
|
||||
/* Compressed PAN ID == no PAN ID at all */
|
||||
if(fcf->dest_addr_mode == fcf->dest_addr_mode) {
|
||||
/* No address or both addresses: include destination PAN ID */
|
||||
dest_pan_id = 1;
|
||||
} else if(fcf->dest_addr_mode) {
|
||||
/* Only dest address, include dest PAN ID */
|
||||
dest_pan_id = 1;
|
||||
} else if(fcf->src_addr_mode) {
|
||||
/* Only src address, include src PAN ID */
|
||||
src_pan_id = 1;
|
||||
}
|
||||
}
|
||||
if(fcf->dest_addr_mode == 0 && fcf->dest_addr_mode == 1) {
|
||||
/* No address included, include dest PAN ID conditionally */
|
||||
if(!fcf->panid_compression) {
|
||||
dest_pan_id = 1;
|
||||
}
|
||||
}
|
||||
/* Remove the following rule the day rows 2 and 3 from table 2a are fixed: */
|
||||
if(fcf->dest_addr_mode == 0 && fcf->dest_addr_mode == 0) {
|
||||
/* Not meaningful, we include a PAN ID iff the compress flag is set, but
|
||||
* this is what the standard currently stipulates */
|
||||
dest_pan_id = fcf->panid_compression;
|
||||
}
|
||||
} else {
|
||||
/* No PAN ID in ACK */
|
||||
if(fcf->frame_type != FRAME802154_ACKFRAME) {
|
||||
if(!fcf->panid_compression && fcf->src_addr_mode & 3) {
|
||||
/* If compressed, don't inclue source PAN ID */
|
||||
src_pan_id = 1;
|
||||
}
|
||||
if(fcf->dest_addr_mode & 3) {
|
||||
dest_pan_id = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(has_src_pan_id != NULL) {
|
||||
*has_src_pan_id = src_pan_id;
|
||||
}
|
||||
if(has_dest_pan_id != NULL) {
|
||||
*has_dest_pan_id = dest_pan_id;
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Check if the destination PAN ID, if any, matches ours */
|
||||
int
|
||||
frame802154_check_dest_panid(frame802154_t *frame)
|
||||
{
|
||||
int has_dest_panid;
|
||||
|
||||
if(frame == NULL) {
|
||||
return 0;
|
||||
}
|
||||
frame802154_has_panid(&frame->fcf, NULL, &has_dest_panid);
|
||||
if(has_dest_panid
|
||||
&& frame->dest_pid != frame802154_get_pan_id()
|
||||
&& frame->dest_pid != FRAME802154_BROADCASTPANDID) {
|
||||
/* Packet to another PAN */
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Check is the address is a broadcast address, whatever its size */
|
||||
int
|
||||
frame802154_is_broadcast_addr(uint8_t mode, uint8_t *addr)
|
||||
{
|
||||
int i = mode == FRAME802154_SHORTADDRMODE ? 2 : 8;
|
||||
while(i-- > 0) {
|
||||
if(addr[i] != 0xff) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Check and extract source and destination linkaddr from frame */
|
||||
int
|
||||
frame802154_extract_linkaddr(frame802154_t *frame,
|
||||
linkaddr_t *source_address, linkaddr_t *dest_address)
|
||||
{
|
||||
int src_addr_len;
|
||||
int dest_addr_len;
|
||||
|
||||
if(frame == NULL) {
|
||||
return 0;
|
||||
}
|
||||
/* Check and extract source address */
|
||||
src_addr_len = frame->fcf.src_addr_mode ?
|
||||
((frame->fcf.src_addr_mode == FRAME802154_SHORTADDRMODE) ? 2 : 8) : 0;
|
||||
if(src_addr_len == 0 || frame802154_is_broadcast_addr(frame->fcf.src_addr_mode, frame->src_addr)) {
|
||||
/* Broadcast address */
|
||||
if(source_address != NULL) {
|
||||
linkaddr_copy(source_address, &linkaddr_null);
|
||||
}
|
||||
} else {
|
||||
/* Unicast address */
|
||||
if(src_addr_len != LINKADDR_SIZE) {
|
||||
/* Destination address has a size we can not handle */
|
||||
return 0;
|
||||
}
|
||||
if(source_address != NULL) {
|
||||
linkaddr_copy(source_address, (linkaddr_t *)frame->src_addr);
|
||||
}
|
||||
}
|
||||
|
||||
/* Check and extract destination address */
|
||||
dest_addr_len = frame->fcf.dest_addr_mode ?
|
||||
((frame->fcf.dest_addr_mode == FRAME802154_SHORTADDRMODE) ? 2 : 8) : 0;
|
||||
if(dest_addr_len == 0 || frame802154_is_broadcast_addr(frame->fcf.dest_addr_mode, frame->dest_addr)) {
|
||||
/* Broadcast address */
|
||||
if(dest_address != NULL) {
|
||||
linkaddr_copy(dest_address, &linkaddr_null);
|
||||
}
|
||||
} else {
|
||||
/* Unicast address */
|
||||
if(dest_addr_len != LINKADDR_SIZE) {
|
||||
/* Destination address has a size we can not handle */
|
||||
return 0;
|
||||
}
|
||||
if(dest_address != NULL) {
|
||||
linkaddr_copy(dest_address, (linkaddr_t *)frame->dest_addr);
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
static void
|
||||
field_len(frame802154_t *p, field_length_t *flen)
|
||||
{
|
||||
int has_src_panid;
|
||||
int has_dest_panid;
|
||||
|
||||
/* init flen to zeros */
|
||||
memset(flen, 0, sizeof(field_length_t));
|
||||
|
||||
/* Determine lengths of each field based on fcf and other args */
|
||||
if(p->fcf.dest_addr_mode & 3) {
|
||||
flen->dest_pid_len = 2;
|
||||
if((p->fcf.sequence_number_suppression & 1) == 0) {
|
||||
flen->seqno_len = 1;
|
||||
}
|
||||
if(p->fcf.src_addr_mode & 3) {
|
||||
|
||||
/* IEEE802.15.4e changes the meaning of PAN ID Compression (see Table 2a).
|
||||
* In this case, we leave the decision whether to compress PAN ID or not
|
||||
* up to the caller. */
|
||||
if(p->fcf.frame_version < FRAME802154_IEEE802154E_2012) {
|
||||
/* Set PAN ID compression bit if src pan id matches dest pan id. */
|
||||
if(p->fcf.dest_addr_mode & 3 && p->fcf.src_addr_mode & 3 &&
|
||||
p->src_pid == p->dest_pid) {
|
||||
p->fcf.panid_compression = 1;
|
||||
} else {
|
||||
p->fcf.panid_compression = 0;
|
||||
}
|
||||
}
|
||||
|
||||
frame802154_has_panid(&p->fcf, &has_src_panid, &has_dest_panid);
|
||||
|
||||
if(has_src_panid) {
|
||||
flen->src_pid_len = 2;
|
||||
}
|
||||
|
||||
/* Set PAN ID compression bit if src pan id matches dest pan id. */
|
||||
if(p->fcf.dest_addr_mode & 3 && p->fcf.src_addr_mode & 3 &&
|
||||
p->src_pid == p->dest_pid) {
|
||||
p->fcf.panid_compression = 1;
|
||||
|
||||
/* compressed header, only do dest pid */
|
||||
flen->src_pid_len = 0;
|
||||
} else {
|
||||
p->fcf.panid_compression = 0;
|
||||
if(has_dest_panid) {
|
||||
flen->dest_pid_len = 2;
|
||||
}
|
||||
|
||||
/* determine address lengths */
|
||||
|
@ -144,9 +320,16 @@ field_len(frame802154_t *p, field_length_t *flen)
|
|||
#if LLSEC802154_SECURITY_LEVEL
|
||||
/* Aux security header */
|
||||
if(p->fcf.security_enabled & 1) {
|
||||
flen->aux_sec_len = 5
|
||||
flen->aux_sec_len = 1; /* FCF + possibly frame counter and key ID */
|
||||
if(p->aux_hdr.security_control.frame_counter_suppression == 0) {
|
||||
if(p->aux_hdr.security_control.frame_counter_size == 1) {
|
||||
flen->aux_sec_len += 5;
|
||||
} else {
|
||||
flen->aux_sec_len += 4;
|
||||
}
|
||||
}
|
||||
#if LLSEC802154_USES_EXPLICIT_KEYS
|
||||
+ get_key_id_len(p->aux_hdr.security_control.key_id_mode);
|
||||
flen->aux_sec_len += get_key_id_len(p->aux_hdr.security_control.key_id_mode);
|
||||
#endif /* LLSEC802154_USES_EXPLICIT_KEYS */
|
||||
;
|
||||
}
|
||||
|
@ -161,14 +344,14 @@ field_len(frame802154_t *p, field_length_t *flen)
|
|||
* frame to send.
|
||||
*
|
||||
* \return The length of the frame header.
|
||||
*/
|
||||
*/
|
||||
int
|
||||
frame802154_hdrlen(frame802154_t *p)
|
||||
{
|
||||
field_length_t flen;
|
||||
field_len(p, &flen);
|
||||
return 3 + flen.dest_pid_len + flen.dest_addr_len +
|
||||
flen.src_pid_len + flen.src_addr_len + flen.aux_sec_len;
|
||||
return 2 + flen.seqno_len + flen.dest_pid_len + flen.dest_addr_len +
|
||||
flen.src_pid_len + flen.src_addr_len + flen.aux_sec_len;
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/**
|
||||
|
@ -181,7 +364,7 @@ frame802154_hdrlen(frame802154_t *p)
|
|||
* \param buf Pointer to the buffer to use for the frame.
|
||||
*
|
||||
* \return The length of the frame header
|
||||
*/
|
||||
*/
|
||||
int
|
||||
frame802154_create(frame802154_t *p, uint8_t *buf)
|
||||
{
|
||||
|
@ -193,7 +376,7 @@ frame802154_create(frame802154_t *p, uint8_t *buf)
|
|||
#endif /* LLSEC802154_USES_EXPLICIT_KEYS */
|
||||
|
||||
field_len(p, &flen);
|
||||
|
||||
|
||||
/* OK, now we have field lengths. Time to actually construct */
|
||||
/* the outgoing frame, and store it in buf */
|
||||
buf[0] = (p->fcf.frame_type & 7) |
|
||||
|
@ -201,13 +384,18 @@ frame802154_create(frame802154_t *p, uint8_t *buf)
|
|||
((p->fcf.frame_pending & 1) << 4) |
|
||||
((p->fcf.ack_required & 1) << 5) |
|
||||
((p->fcf.panid_compression & 1) << 6);
|
||||
buf[1] = ((p->fcf.dest_addr_mode & 3) << 2) |
|
||||
buf[1] = ((p->fcf.sequence_number_suppression & 1)) |
|
||||
((p->fcf.ie_list_present & 1)) << 1 |
|
||||
((p->fcf.dest_addr_mode & 3) << 2) |
|
||||
((p->fcf.frame_version & 3) << 4) |
|
||||
((p->fcf.src_addr_mode & 3) << 6);
|
||||
|
||||
/* sequence number */
|
||||
buf[2] = p->seq;
|
||||
pos = 3;
|
||||
pos = 2;
|
||||
|
||||
/* Sequence number */
|
||||
if(flen.seqno_len == 1) {
|
||||
buf[pos++] = p->seq;
|
||||
}
|
||||
|
||||
/* Destination PAN ID */
|
||||
if(flen.dest_pid_len == 2) {
|
||||
|
@ -230,17 +418,24 @@ frame802154_create(frame802154_t *p, uint8_t *buf)
|
|||
for(c = flen.src_addr_len; c > 0; c--) {
|
||||
buf[pos++] = p->src_addr[c - 1];
|
||||
}
|
||||
|
||||
#if LLSEC802154_SECURITY_LEVEL
|
||||
/* Aux header */
|
||||
if(flen.aux_sec_len) {
|
||||
buf[pos++] = p->aux_hdr.security_control.security_level
|
||||
#if LLSEC802154_USES_EXPLICIT_KEYS
|
||||
| (p->aux_hdr.security_control.key_id_mode << 3)
|
||||
| (p->aux_hdr.security_control.key_id_mode << 3)
|
||||
#endif /* LLSEC802154_USES_EXPLICIT_KEYS */
|
||||
| (p->aux_hdr.security_control.frame_counter_suppression << 5)
|
||||
| (p->aux_hdr.security_control.frame_counter_size << 6)
|
||||
;
|
||||
memcpy(buf + pos, p->aux_hdr.frame_counter.u8, 4);
|
||||
pos += 4;
|
||||
if(p->aux_hdr.security_control.frame_counter_suppression == 0) {
|
||||
/* We support only 4-byte counters */
|
||||
memcpy(buf + pos, p->aux_hdr.frame_counter.u8, 4);
|
||||
pos += 4;
|
||||
if(p->aux_hdr.security_control.frame_counter_size == 1) {
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
|
||||
#if LLSEC802154_USES_EXPLICIT_KEYS
|
||||
key_id_mode = p->aux_hdr.security_control.key_id_mode;
|
||||
|
@ -272,11 +467,13 @@ frame802154_parse(uint8_t *data, int len, frame802154_t *pf)
|
|||
uint8_t *p;
|
||||
frame802154_fcf_t fcf;
|
||||
int c;
|
||||
int has_src_panid;
|
||||
int has_dest_panid;
|
||||
#if LLSEC802154_USES_EXPLICIT_KEYS
|
||||
uint8_t key_id_mode;
|
||||
#endif /* LLSEC802154_USES_EXPLICIT_KEYS */
|
||||
|
||||
if(len < 3) {
|
||||
if(len < 2) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -289,20 +486,32 @@ frame802154_parse(uint8_t *data, int len, frame802154_t *pf)
|
|||
fcf.ack_required = (p[0] >> 5) & 1;
|
||||
fcf.panid_compression = (p[0] >> 6) & 1;
|
||||
|
||||
fcf.sequence_number_suppression = p[1] & 1;
|
||||
fcf.ie_list_present = (p[1] >> 1) & 1;
|
||||
fcf.dest_addr_mode = (p[1] >> 2) & 3;
|
||||
fcf.frame_version = (p[1] >> 4) & 3;
|
||||
fcf.src_addr_mode = (p[1] >> 6) & 3;
|
||||
|
||||
/* copy fcf and seqNum */
|
||||
memcpy(&pf->fcf, &fcf, sizeof(frame802154_fcf_t));
|
||||
pf->seq = p[2];
|
||||
p += 3; /* Skip first three bytes */
|
||||
p += 2; /* Skip first two bytes */
|
||||
|
||||
if(fcf.sequence_number_suppression == 0) {
|
||||
pf->seq = p[0];
|
||||
p++;
|
||||
}
|
||||
|
||||
frame802154_has_panid(&fcf, &has_src_panid, &has_dest_panid);
|
||||
|
||||
/* Destination address, if any */
|
||||
if(fcf.dest_addr_mode) {
|
||||
/* Destination PAN */
|
||||
pf->dest_pid = p[0] + (p[1] << 8);
|
||||
p += 2;
|
||||
if(has_dest_panid) {
|
||||
/* Destination PAN */
|
||||
pf->dest_pid = p[0] + (p[1] << 8);
|
||||
p += 2;
|
||||
} else {
|
||||
pf->dest_pid = 0;
|
||||
}
|
||||
|
||||
/* Destination address */
|
||||
/* l = addr_len(fcf.dest_addr_mode); */
|
||||
|
@ -329,9 +538,12 @@ frame802154_parse(uint8_t *data, int len, frame802154_t *pf)
|
|||
/* Source address, if any */
|
||||
if(fcf.src_addr_mode) {
|
||||
/* Source PAN */
|
||||
if(!fcf.panid_compression) {
|
||||
if(has_src_panid) {
|
||||
pf->src_pid = p[0] + (p[1] << 8);
|
||||
p += 2;
|
||||
if(!has_dest_panid) {
|
||||
pf->dest_pid = pf->src_pid;
|
||||
}
|
||||
} else {
|
||||
pf->src_pid = pf->dest_pid;
|
||||
}
|
||||
|
@ -357,18 +569,25 @@ frame802154_parse(uint8_t *data, int len, frame802154_t *pf)
|
|||
linkaddr_copy((linkaddr_t *)&(pf->src_addr), &linkaddr_null);
|
||||
pf->src_pid = 0;
|
||||
}
|
||||
|
||||
|
||||
#if LLSEC802154_SECURITY_LEVEL
|
||||
if(fcf.security_enabled) {
|
||||
pf->aux_hdr.security_control.security_level = p[0] & 7;
|
||||
#if LLSEC802154_USES_EXPLICIT_KEYS
|
||||
pf->aux_hdr.security_control.key_id_mode = (p[0] >> 3) & 3;
|
||||
#endif /* LLSEC802154_USES_EXPLICIT_KEYS */
|
||||
pf->aux_hdr.security_control.frame_counter_suppression = p[0] >> 5;
|
||||
pf->aux_hdr.security_control.frame_counter_size = p[0] >> 6;
|
||||
p += 1;
|
||||
|
||||
memcpy(pf->aux_hdr.frame_counter.u8, p, 4);
|
||||
p += 4;
|
||||
|
||||
|
||||
if(pf->aux_hdr.security_control.frame_counter_suppression == 0) {
|
||||
memcpy(pf->aux_hdr.frame_counter.u8, p, 4);
|
||||
p += 4;
|
||||
if(pf->aux_hdr.security_control.frame_counter_size == 1) {
|
||||
p ++;
|
||||
}
|
||||
}
|
||||
|
||||
#if LLSEC802154_USES_EXPLICIT_KEYS
|
||||
key_id_mode = pf->aux_hdr.security_control.key_id_mode;
|
||||
if(key_id_mode) {
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
*/
|
||||
|
||||
/**
|
||||
* \addtogroup net
|
||||
|
@ -59,14 +59,14 @@
|
|||
* This file converts to and from a structure to a packed 802.15.4
|
||||
* frame.
|
||||
*
|
||||
*/
|
||||
|
||||
*/
|
||||
|
||||
/* Includes */
|
||||
#ifndef FRAME_802154_H
|
||||
#define FRAME_802154_H
|
||||
|
||||
#include "contiki-conf.h"
|
||||
#include "net/linkaddr.h"
|
||||
|
||||
#ifdef IEEE802154_CONF_PANID
|
||||
#define IEEE802154_PANID IEEE802154_CONF_PANID
|
||||
|
@ -74,6 +74,18 @@
|
|||
#define IEEE802154_PANID 0xABCD
|
||||
#endif /* IEEE802154_CONF_PANID */
|
||||
|
||||
#ifdef FRAME802154_CONF_VERSION
|
||||
#define FRAME802154_VERSION FRAME802154_CONF_VERSION
|
||||
#else /* FRAME802154_CONF_VERSION */
|
||||
#define FRAME802154_VERSION FRAME802154_IEEE802154_2006
|
||||
#endif /* FRAME802154_CONF_VERSION */
|
||||
|
||||
#ifdef FRAME802154_CONF_SUPPR_SEQNO
|
||||
#define FRAME802154_SUPPR_SEQNO FRAME802154_CONF_SUPPR_SEQNO
|
||||
#else /* FRAME802154_CONF_SUPPR_SEQNO */
|
||||
#define FRAME802154_SUPPR_SEQNO 0
|
||||
#endif /* FRAME802154_CONF_SUPPR_SEQNO */
|
||||
|
||||
/* Macros & Defines */
|
||||
|
||||
/** \brief These are some definitions of values used in the FCF. See the 802.15.4 spec for details.
|
||||
|
@ -97,8 +109,9 @@
|
|||
#define FRAME802154_BROADCASTADDR (0xFFFF)
|
||||
#define FRAME802154_BROADCASTPANDID (0xFFFF)
|
||||
|
||||
#define FRAME802154_IEEE802154_2003 (0x00)
|
||||
#define FRAME802154_IEEE802154_2006 (0x01)
|
||||
#define FRAME802154_IEEE802154_2003 (0x00)
|
||||
#define FRAME802154_IEEE802154_2006 (0x01)
|
||||
#define FRAME802154_IEEE802154E_2012 (0x02)
|
||||
|
||||
#define FRAME802154_SECURITY_LEVEL_NONE (0)
|
||||
#define FRAME802154_SECURITY_LEVEL_MIC_32 (1)
|
||||
|
@ -125,7 +138,7 @@
|
|||
* 3. Addressing fields - 4 - 20 bytes - Variable
|
||||
* 4. Aux security header - 0 - 14 bytes - Variable
|
||||
* 5. CRC - 2 bytes - Fixed
|
||||
*/
|
||||
*/
|
||||
|
||||
/**
|
||||
* \brief Defines the bitfields of the frame control field (FCF).
|
||||
|
@ -136,7 +149,9 @@ typedef struct {
|
|||
uint8_t frame_pending; /**< 1 bit. True if sender has more data to send */
|
||||
uint8_t ack_required; /**< 1 bit. Is an ack frame required? */
|
||||
uint8_t panid_compression; /**< 1 bit. Is this a compressed header? */
|
||||
/* uint8_t reserved; */ /**< 3 bit. Unused bits */
|
||||
/* uint8_t reserved; */ /**< 1 bit. Unused bit */
|
||||
uint8_t sequence_number_suppression; /**< 1 bit. Does the header omit sequence number?, see 802.15.4e */
|
||||
uint8_t ie_list_present; /**< 1 bit. Does the header contain Information Elements?, see 802.15.4e */
|
||||
uint8_t dest_addr_mode; /**< 2 bit. Destination address mode, see 802.15.4 */
|
||||
uint8_t frame_version; /**< 2 bit. 802.15.4 frame version */
|
||||
uint8_t src_addr_mode; /**< 2 bit. Source address mode, see 802.15.4 */
|
||||
|
@ -146,6 +161,8 @@ typedef struct {
|
|||
typedef struct {
|
||||
uint8_t security_level; /**< 3 bit. security level */
|
||||
uint8_t key_id_mode; /**< 2 bit. Key identifier mode */
|
||||
uint8_t frame_counter_suppression; /**< 1 bit. Frame counter suppression */
|
||||
uint8_t frame_counter_size; /**< 1 bit. Frame counter size (0: 4 bytes, 1: 5 bytes) */
|
||||
uint8_t reserved; /**< 3 bit. Reserved bits */
|
||||
} frame802154_scf_t;
|
||||
|
||||
|
@ -193,6 +210,20 @@ int frame802154_hdrlen(frame802154_t *p);
|
|||
int frame802154_create(frame802154_t *p, uint8_t *buf);
|
||||
int frame802154_parse(uint8_t *data, int length, frame802154_t *pf);
|
||||
|
||||
/* Get current PAN ID */
|
||||
uint16_t frame802154_get_pan_id(void);
|
||||
/* Set current PAN ID */
|
||||
void frame802154_set_pan_id(uint16_t pan_id);
|
||||
/* Tells whether a given Frame Control Field indicates a frame with
|
||||
* source PANID and/or destination PANID */
|
||||
void frame802154_has_panid(frame802154_fcf_t *fcf, int *has_src_pan_id, int *has_dest_pan_id);
|
||||
/* Check if the destination PAN ID, if any, matches ours */
|
||||
int frame802154_check_dest_panid(frame802154_t *frame);
|
||||
/* Check is the address is a broadcast address, whatever its size */
|
||||
int frame802154_is_broadcast_addr(uint8_t mode, uint8_t *addr);
|
||||
/* Check and extract source and destination linkaddr from frame */
|
||||
int frame802154_extract_linkaddr(frame802154_t *frame, linkaddr_t *source_address, linkaddr_t *dest_address);
|
||||
|
||||
/** @} */
|
||||
#endif /* FRAME_802154_H */
|
||||
/** @} */
|
||||
|
|
585
core/net/mac/frame802154e-ie.c
Normal file
585
core/net/mac/frame802154e-ie.c
Normal file
|
@ -0,0 +1,585 @@
|
|||
/*
|
||||
* Copyright (c) 2015, SICS Swedish ICT.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the Institute nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the Contiki operating system.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
* IEEE 802.15.4e Information Element (IE) creation and parsing.
|
||||
* \author
|
||||
* Simon Duquennoy <simonduq@sics.se>
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "net/mac/frame802154e-ie.h"
|
||||
|
||||
#define DEBUG DEBUG_NONE
|
||||
#include "net/ip/uip-debug.h"
|
||||
|
||||
/* c.f. IEEE 802.15.4e Table 4b */
|
||||
enum ieee802154e_header_ie_id {
|
||||
HEADER_IE_LE_CSL = 0x1a,
|
||||
HEADER_IE_LE_RIT,
|
||||
HEADER_IE_DSME_PAN_DESCRIPTOR,
|
||||
HEADER_IE_RZ_TIME,
|
||||
HEADER_IE_ACK_NACK_TIME_CORRECTION,
|
||||
HEADER_IE_GACK,
|
||||
HEADER_IE_LOW_LATENCY_NETWORK_INFO,
|
||||
HEADER_IE_LIST_TERMINATION_1 = 0x7e,
|
||||
HEADER_IE_LIST_TERMINATION_2 = 0x7f,
|
||||
};
|
||||
|
||||
/* c.f. IEEE 802.15.4e Table 4c */
|
||||
enum ieee802154e_payload_ie_id {
|
||||
PAYLOAD_IE_ESDU = 0,
|
||||
PAYLOAD_IE_MLME,
|
||||
PAYLOAD_IE_LIST_TERMINATION = 0xf,
|
||||
};
|
||||
|
||||
/* c.f. IEEE 802.15.4e Table 4d */
|
||||
enum ieee802154e_mlme_short_subie_id {
|
||||
MLME_SHORT_IE_TSCH_SYNCHRONIZATION = 0x1a,
|
||||
MLME_SHORT_IE_TSCH_SLOFTRAME_AND_LINK,
|
||||
MLME_SHORT_IE_TSCH_TIMESLOT,
|
||||
MLME_SHORT_IE_TSCH_HOPPING_TIMING,
|
||||
MLME_SHORT_IE_TSCH_EB_FILTER,
|
||||
MLME_SHORT_IE_TSCH_MAC_METRICS_1,
|
||||
MLME_SHORT_IE_TSCH_MAC_METRICS_2,
|
||||
};
|
||||
|
||||
/* c.f. IEEE 802.15.4e Table 4e */
|
||||
enum ieee802154e_mlme_long_subie_id {
|
||||
MLME_LONG_IE_TSCH_CHANNEL_HOPPING_SEQUENCE = 0x9,
|
||||
};
|
||||
|
||||
#define WRITE16(buf, val) \
|
||||
do { ((uint8_t *)(buf))[0] = (val) & 0xff; \
|
||||
((uint8_t *)(buf))[1] = ((val) >> 8) & 0xff; } while(0);
|
||||
|
||||
#define READ16(buf, var) \
|
||||
(var) = ((uint8_t *)(buf))[0] | ((uint8_t *)(buf))[1] << 8
|
||||
|
||||
/* Create a header IE 2-byte descriptor */
|
||||
static void
|
||||
create_header_ie_descriptor(uint8_t *buf, uint8_t element_id, int ie_len)
|
||||
{
|
||||
uint16_t ie_desc;
|
||||
/* Header IE descriptor: b0-6: len, b7-14: element id:, b15: type: 0 */
|
||||
ie_desc = (ie_len & 0x7f) + ((element_id & 0xff) << 7);
|
||||
WRITE16(buf, ie_desc);
|
||||
}
|
||||
|
||||
/* Create a payload IE 2-byte descriptor */
|
||||
static void
|
||||
create_payload_ie_descriptor(uint8_t *buf, uint8_t group_id, int ie_len)
|
||||
{
|
||||
uint16_t ie_desc;
|
||||
/* MLME Long IE descriptor: b0-10: len, b11-14: group id:, b15: type: 1 */
|
||||
ie_desc = (ie_len & 0x07ff) + ((group_id & 0x0f) << 11) + (1 << 15);
|
||||
WRITE16(buf, ie_desc);
|
||||
}
|
||||
|
||||
/* Create a MLME short IE 2-byte descriptor */
|
||||
static void
|
||||
create_mlme_short_ie_descriptor(uint8_t *buf, uint8_t sub_id, int ie_len)
|
||||
{
|
||||
uint16_t ie_desc;
|
||||
/* MLME Short IE descriptor: b0-7: len, b8-14: sub id:, b15: type: 0 */
|
||||
ie_desc = (ie_len & 0xff) + ((sub_id & 0x7f) << 8);
|
||||
WRITE16(buf, ie_desc);
|
||||
}
|
||||
|
||||
/* Create a MLME long IE 2-byte descriptor */
|
||||
static void
|
||||
create_mlme_long_ie_descriptor(uint8_t *buf, uint8_t sub_id, int ie_len)
|
||||
{
|
||||
uint16_t ie_desc;
|
||||
/* MLME Long IE descriptor: b0-10: len, b11-14: sub id:, b15: type: 1 */
|
||||
ie_desc = (ie_len & 0x07ff) + ((sub_id & 0x0f) << 11) + (1 << 15);
|
||||
WRITE16(buf, ie_desc);
|
||||
}
|
||||
|
||||
/* Header IE. ACK/NACK time correction. Used in enhanced ACKs */
|
||||
int
|
||||
frame80215e_create_ie_header_ack_nack_time_correction(uint8_t *buf, int len,
|
||||
struct ieee802154_ies *ies)
|
||||
{
|
||||
int ie_len = 2;
|
||||
if(len >= 2 + ie_len && ies != NULL) {
|
||||
int16_t drift_us;
|
||||
uint16_t time_sync_field;
|
||||
drift_us = ies->ie_time_correction;
|
||||
time_sync_field = drift_us & 0x0fff;
|
||||
if(ies->ie_is_nack) {
|
||||
time_sync_field |= 0x8000;
|
||||
}
|
||||
WRITE16(buf+2, time_sync_field);
|
||||
create_header_ie_descriptor(buf, HEADER_IE_ACK_NACK_TIME_CORRECTION, ie_len);
|
||||
return 2 + ie_len;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Header IE. List termination 1 (Signals the end of the Header IEs when
|
||||
* followed by payload IEs) */
|
||||
int
|
||||
frame80215e_create_ie_header_list_termination_1(uint8_t *buf, int len,
|
||||
struct ieee802154_ies *ies)
|
||||
{
|
||||
int ie_len = 0;
|
||||
if(len >= 2 + ie_len && ies != NULL) {
|
||||
create_header_ie_descriptor(buf, HEADER_IE_LIST_TERMINATION_1, 0);
|
||||
return 2 + ie_len;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Header IE. List termination 2 (Signals the end of the Header IEs when
|
||||
* followed by an unformatted payload) */
|
||||
int
|
||||
frame80215e_create_ie_header_list_termination_2(uint8_t *buf, int len,
|
||||
struct ieee802154_ies *ies)
|
||||
{
|
||||
int ie_len = 0;
|
||||
if(len >= 2 + ie_len && ies != NULL) {
|
||||
create_header_ie_descriptor(buf, HEADER_IE_LIST_TERMINATION_2, 0);
|
||||
return 2 + ie_len;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Payload IE. List termination */
|
||||
int
|
||||
frame80215e_create_ie_payload_list_termination(uint8_t *buf, int len,
|
||||
struct ieee802154_ies *ies)
|
||||
{
|
||||
int ie_len = 0;
|
||||
if(len >= 2 + ie_len && ies != NULL) {
|
||||
create_payload_ie_descriptor(buf, PAYLOAD_IE_LIST_TERMINATION, 0);
|
||||
return 2 + ie_len;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Payload IE. MLME. Used to nest sub-IEs */
|
||||
int
|
||||
frame80215e_create_ie_mlme(uint8_t *buf, int len,
|
||||
struct ieee802154_ies *ies)
|
||||
{
|
||||
int ie_len = 0;
|
||||
if(len >= 2 + ie_len && ies != NULL) {
|
||||
/* The length of the outer MLME IE is the total length of sub-IEs */
|
||||
create_payload_ie_descriptor(buf, PAYLOAD_IE_MLME, ies->ie_mlme_len);
|
||||
return 2 + ie_len;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* MLME sub-IE. TSCH synchronization. Used in EBs: ASN and join priority */
|
||||
int
|
||||
frame80215e_create_ie_tsch_synchronization(uint8_t *buf, int len,
|
||||
struct ieee802154_ies *ies)
|
||||
{
|
||||
int ie_len = 6;
|
||||
if(len >= 2 + ie_len && ies != NULL) {
|
||||
buf[2] = ies->ie_asn.ls4b;
|
||||
buf[3] = ies->ie_asn.ls4b >> 8;
|
||||
buf[4] = ies->ie_asn.ls4b >> 16;
|
||||
buf[5] = ies->ie_asn.ls4b >> 24;
|
||||
buf[6] = ies->ie_asn.ms1b;
|
||||
buf[7] = ies->ie_join_priority;
|
||||
create_mlme_short_ie_descriptor(buf, MLME_SHORT_IE_TSCH_SYNCHRONIZATION, ie_len);
|
||||
return 2 + ie_len;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* MLME sub-IE. TSCH slotframe and link. Used in EBs: initial schedule */
|
||||
int
|
||||
frame80215e_create_ie_tsch_slotframe_and_link(uint8_t *buf, int len,
|
||||
struct ieee802154_ies *ies)
|
||||
{
|
||||
if(ies != NULL) {
|
||||
int i;
|
||||
int num_slotframes = ies->ie_tsch_slotframe_and_link.num_slotframes;
|
||||
int num_links = ies->ie_tsch_slotframe_and_link.num_links;
|
||||
int ie_len = 1 + num_slotframes * (4 + 5 * num_links);
|
||||
if(num_slotframes > 1 || num_links > FRAME802154E_IE_MAX_LINKS
|
||||
|| len < 2 + ie_len) {
|
||||
/* We support only 0 or 1 slotframe in this IE and a predefined maximum number of links */
|
||||
return -1;
|
||||
}
|
||||
/* Insert IE */
|
||||
buf[2] = num_slotframes;
|
||||
/* Insert slotframe */
|
||||
if(num_slotframes == 1) {
|
||||
buf[2 + 1] = ies->ie_tsch_slotframe_and_link.slotframe_handle;
|
||||
WRITE16(buf + 2 + 2, ies->ie_tsch_slotframe_and_link.slotframe_size);
|
||||
buf[2 + 4] = num_links;
|
||||
/* Loop over links */
|
||||
for(i = 0; i < num_links; i++) {
|
||||
/* Insert links */
|
||||
WRITE16(buf + 2 + 5 + i * 5, ies->ie_tsch_slotframe_and_link.links[i].timeslot);
|
||||
WRITE16(buf + 2 + 5 + i * 5 + 2, ies->ie_tsch_slotframe_and_link.links[i].channel_offset);
|
||||
buf[2 + 5 + i * 5 + 4] = ies->ie_tsch_slotframe_and_link.links[i].link_options;
|
||||
}
|
||||
}
|
||||
create_mlme_short_ie_descriptor(buf, MLME_SHORT_IE_TSCH_SLOFTRAME_AND_LINK, ie_len);
|
||||
return 2 + ie_len;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* MLME sub-IE. TSCH timeslot. Used in EBs: timeslot template (timing) */
|
||||
int
|
||||
frame80215e_create_ie_tsch_timeslot(uint8_t *buf, int len,
|
||||
struct ieee802154_ies *ies)
|
||||
{
|
||||
int ie_len;
|
||||
if(ies == NULL) {
|
||||
return -1;
|
||||
}
|
||||
/* Only ID if ID == 0, else full timing description */
|
||||
ie_len = ies->ie_tsch_timeslot_id == 0 ? 1 : 25;
|
||||
if(len >= 2 + ie_len) {
|
||||
buf[2] = ies->ie_tsch_timeslot_id;
|
||||
if(ies->ie_tsch_timeslot_id != 0) {
|
||||
int i;
|
||||
for(i = 0; i < tsch_ts_elements_count; i++) {
|
||||
WRITE16(buf + 3 + 2 * i, ies->ie_tsch_timeslot[i]);
|
||||
}
|
||||
}
|
||||
create_mlme_short_ie_descriptor(buf, MLME_SHORT_IE_TSCH_TIMESLOT, ie_len);
|
||||
return 2 + ie_len;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* MLME sub-IE. TSCH channel hopping sequence. Used in EBs: hopping sequence */
|
||||
int
|
||||
frame80215e_create_ie_tsch_channel_hopping_sequence(uint8_t *buf, int len,
|
||||
struct ieee802154_ies *ies)
|
||||
{
|
||||
int ie_len;
|
||||
if(ies == NULL || ies->ie_hopping_sequence_len > sizeof(ies->ie_hopping_sequence_list)) {
|
||||
return -1;
|
||||
}
|
||||
ie_len = ies->ie_channel_hopping_sequence_id == 0 ? 1 : 12 + ies->ie_hopping_sequence_len;
|
||||
if(len >= 2 + ie_len && ies != NULL) {
|
||||
buf[2] = ies->ie_channel_hopping_sequence_id;
|
||||
buf[3] = 0; /* channel page */
|
||||
WRITE16(buf + 4, 0); /* number of channels */
|
||||
WRITE16(buf + 6, 0); /* phy configuration */
|
||||
WRITE16(buf + 8, 0);
|
||||
/* Extended bitmap. Size: 0 */
|
||||
WRITE16(buf + 10, ies->ie_hopping_sequence_len); /* sequence len */
|
||||
memcpy(buf + 12, ies->ie_hopping_sequence_list, ies->ie_hopping_sequence_len); /* sequence list */
|
||||
WRITE16(buf + 12 + ies->ie_hopping_sequence_len, 0); /* current hop */
|
||||
create_mlme_long_ie_descriptor(buf, MLME_LONG_IE_TSCH_CHANNEL_HOPPING_SEQUENCE, ie_len);
|
||||
return 2 + ie_len;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Parse a header IE */
|
||||
static int
|
||||
frame802154e_parse_header_ie(const uint8_t *buf, int len,
|
||||
uint8_t element_id, struct ieee802154_ies *ies)
|
||||
{
|
||||
switch(element_id) {
|
||||
case HEADER_IE_ACK_NACK_TIME_CORRECTION:
|
||||
if(len == 2) {
|
||||
if(ies != NULL) {
|
||||
/* If the originator was a time source neighbor, the receiver adjust
|
||||
* its own clock by incorporating the received drift correction */
|
||||
uint16_t time_sync_field = 0;
|
||||
int16_t drift_us = 0;
|
||||
/* Extract drift correction from Sync-IE, cast from 12 to 16-bit,
|
||||
* and convert it to RTIMER ticks.
|
||||
* See page 88 in IEEE Std 802.15.4e-2012. */
|
||||
READ16(buf, time_sync_field);
|
||||
/* First extract NACK */
|
||||
ies->ie_is_nack = (time_sync_field & (uint16_t)0x8000) ? 1 : 0;
|
||||
/* Then cast from 12 to 16 bit signed */
|
||||
if(time_sync_field & 0x0800) { /* Negative integer */
|
||||
drift_us = time_sync_field | 0xf000;
|
||||
} else { /* Positive integer */
|
||||
drift_us = time_sync_field & 0x0fff;
|
||||
}
|
||||
/* Convert to RTIMER ticks */
|
||||
ies->ie_time_correction = drift_us;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Parse a MLME short IE */
|
||||
static int
|
||||
frame802154e_parse_mlme_short_ie(const uint8_t *buf, int len,
|
||||
uint8_t sub_id, struct ieee802154_ies *ies)
|
||||
{
|
||||
switch(sub_id) {
|
||||
case MLME_SHORT_IE_TSCH_SLOFTRAME_AND_LINK:
|
||||
if(len >= 1) {
|
||||
int i;
|
||||
int num_slotframes = buf[0];
|
||||
int num_links = buf[4];
|
||||
if(num_slotframes == 0) {
|
||||
return len;
|
||||
}
|
||||
if(num_slotframes <= 1 && num_links <= FRAME802154E_IE_MAX_LINKS
|
||||
&& len == 1 + num_slotframes * (4 + 5 * num_links)) {
|
||||
if(ies != NULL) {
|
||||
/* We support only 0 or 1 slotframe in this IE and a predefined maximum number of links */
|
||||
ies->ie_tsch_slotframe_and_link.num_slotframes = buf[0];
|
||||
ies->ie_tsch_slotframe_and_link.slotframe_handle = buf[1];
|
||||
READ16(buf + 2, ies->ie_tsch_slotframe_and_link.slotframe_size);
|
||||
ies->ie_tsch_slotframe_and_link.num_links = buf[4];
|
||||
for(i = 0; i < num_links; i++) {
|
||||
READ16(buf + 5 + i * 5, ies->ie_tsch_slotframe_and_link.links[i].timeslot);
|
||||
READ16(buf + 5 + i * 5 + 2, ies->ie_tsch_slotframe_and_link.links[i].channel_offset);
|
||||
ies->ie_tsch_slotframe_and_link.links[i].link_options = buf[5 + i * 5 + 4];
|
||||
}
|
||||
}
|
||||
return len;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MLME_SHORT_IE_TSCH_SYNCHRONIZATION:
|
||||
if(len == 6) {
|
||||
if(ies != NULL) {
|
||||
ies->ie_asn.ls4b = (uint32_t)buf[0];
|
||||
ies->ie_asn.ls4b |= (uint32_t)buf[1] << 8;
|
||||
ies->ie_asn.ls4b |= (uint32_t)buf[2] << 16;
|
||||
ies->ie_asn.ls4b |= (uint32_t)buf[3] << 24;
|
||||
ies->ie_asn.ms1b = (uint8_t)buf[4];
|
||||
ies->ie_join_priority = (uint8_t)buf[5];
|
||||
}
|
||||
return len;
|
||||
}
|
||||
break;
|
||||
case MLME_SHORT_IE_TSCH_TIMESLOT:
|
||||
if(len == 1 || len == 25) {
|
||||
if(ies != NULL) {
|
||||
ies->ie_tsch_timeslot_id = buf[0];
|
||||
if(len == 25) {
|
||||
int i;
|
||||
for(i = 0; i < tsch_ts_elements_count; i++) {
|
||||
READ16(buf+1+2*i, ies->ie_tsch_timeslot[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return len;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Parse a MLME long IE */
|
||||
static int
|
||||
frame802154e_parse_mlme_long_ie(const uint8_t *buf, int len,
|
||||
uint8_t sub_id, struct ieee802154_ies *ies)
|
||||
{
|
||||
switch(sub_id) {
|
||||
case MLME_LONG_IE_TSCH_CHANNEL_HOPPING_SEQUENCE:
|
||||
if(len > 0) {
|
||||
if(ies != NULL) {
|
||||
ies->ie_channel_hopping_sequence_id = buf[0];
|
||||
if(len > 1) {
|
||||
READ16(buf+8, ies->ie_hopping_sequence_len); /* sequence len */
|
||||
if(ies->ie_hopping_sequence_len <= sizeof(ies->ie_hopping_sequence_list)
|
||||
&& len == 12 + ies->ie_hopping_sequence_len) {
|
||||
memcpy(ies->ie_hopping_sequence_list, buf+10, ies->ie_hopping_sequence_len); /* sequence list */
|
||||
}
|
||||
}
|
||||
}
|
||||
return len;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Parse all IEEE 802.15.4e Information Elements (IE) from a frame */
|
||||
int
|
||||
frame802154e_parse_information_elements(const uint8_t *buf, uint8_t buf_size,
|
||||
struct ieee802154_ies *ies)
|
||||
{
|
||||
const uint8_t *start = buf;
|
||||
uint16_t ie_desc;
|
||||
uint8_t type;
|
||||
uint8_t id;
|
||||
uint16_t len = 0;
|
||||
int nested_mlme_len = 0;
|
||||
enum {PARSING_HEADER_IE, PARSING_PAYLOAD_IE, PARSING_MLME_SUBIE} parsing_state;
|
||||
|
||||
if(ies == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Always look for a header IE first (at least "list termination 1") */
|
||||
parsing_state = PARSING_HEADER_IE;
|
||||
ies->ie_payload_ie_offset = 0;
|
||||
|
||||
/* Loop over all IEs */
|
||||
while(buf_size > 0) {
|
||||
if(buf_size < 2) { /* Not enough space for IE descriptor */
|
||||
return -1;
|
||||
}
|
||||
READ16(buf, ie_desc);
|
||||
buf_size -= 2;
|
||||
buf += 2;
|
||||
type = ie_desc & 0x8000 ? 1 : 0; /* b15 */
|
||||
PRINTF("frame802154e: ie type %u, current state %u\n", type, parsing_state);
|
||||
|
||||
switch(parsing_state) {
|
||||
case PARSING_HEADER_IE:
|
||||
if(type != 0) {
|
||||
PRINTF("frame802154e: wrong type %04x\n", ie_desc);
|
||||
return -1;
|
||||
}
|
||||
/* Header IE: 2 bytes descriptor, c.f. fig 48n in IEEE 802.15.4e */
|
||||
len = ie_desc & 0x007f; /* b0-b6 */
|
||||
id = (ie_desc & 0x7f80) >> 7; /* b7-b14 */
|
||||
PRINTF("frame802154e: header ie len %u id %x\n", len, id);
|
||||
switch(id) {
|
||||
case HEADER_IE_LIST_TERMINATION_1:
|
||||
if(len == 0) {
|
||||
/* End of payload IE list, now expect payload IEs */
|
||||
parsing_state = PARSING_PAYLOAD_IE;
|
||||
ies->ie_payload_ie_offset = buf - start; /* Save IE header len */
|
||||
PRINTF("frame802154e: list termination 1, look for payload IEs\n");
|
||||
} else {
|
||||
PRINTF("frame802154e: list termination 1, wrong len %u\n", len);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case HEADER_IE_LIST_TERMINATION_2:
|
||||
/* End of IE parsing */
|
||||
if(len == 0) {
|
||||
ies->ie_payload_ie_offset = buf - start; /* Save IE header len */
|
||||
PRINTF("frame802154e: list termination 2\n");
|
||||
return buf + len - start;
|
||||
} else {
|
||||
PRINTF("frame802154e: list termination 2, wrong len %u\n", len);
|
||||
return -1;
|
||||
}
|
||||
default:
|
||||
if(len > buf_size || frame802154e_parse_header_ie(buf, len, id, ies) == -1) {
|
||||
PRINTF("frame802154e: failed to parse\n");
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case PARSING_PAYLOAD_IE:
|
||||
if(type != 1) {
|
||||
PRINTF("frame802154e: wrong type %04x\n", ie_desc);
|
||||
return -1;
|
||||
}
|
||||
/* Payload IE: 2 bytes descriptor, c.f. fig 48o in IEEE 802.15.4e */
|
||||
len = ie_desc & 0x7ff; /* b0-b10 */
|
||||
id = (ie_desc & 0x7800) >> 11; /* b11-b14 */
|
||||
PRINTF("frame802154e: payload ie len %u id %x\n", len, id);
|
||||
switch(id) {
|
||||
case PAYLOAD_IE_MLME:
|
||||
/* Now expect 'len' bytes of MLME sub-IEs */
|
||||
parsing_state = PARSING_MLME_SUBIE;
|
||||
nested_mlme_len = len;
|
||||
len = 0; /* Reset len as we want to read subIEs and not jump over them */
|
||||
PRINTF("frame802154e: entering MLME ie with len %u\n", nested_mlme_len);
|
||||
break;
|
||||
case PAYLOAD_IE_LIST_TERMINATION:
|
||||
PRINTF("frame802154e: payload ie list termination %u\n", len);
|
||||
return (len == 0) ? buf + len - start : -1;
|
||||
default:
|
||||
PRINTF("frame802154e: non-supported payload ie\n");
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case PARSING_MLME_SUBIE:
|
||||
/* MLME sub-IE: 2 bytes descriptor, c.f. fig 48q in IEEE 802.15.4e */
|
||||
/* type == 0 means short sub-IE, type == 1 means long sub-IE */
|
||||
if(type == 0) {
|
||||
/* Short sub-IE, c.f. fig 48r in IEEE 802.15.4e */
|
||||
len = ie_desc & 0x00ff; /* b0-b7 */
|
||||
id = (ie_desc & 0x7f00) >> 8; /* b8-b14 */
|
||||
PRINTF("frame802154e: short mlme ie len %u id %x\n", len, id);
|
||||
if(len > buf_size || frame802154e_parse_mlme_short_ie(buf, len, id, ies) == -1) {
|
||||
PRINTF("frame802154e: failed to parse ie\n");
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
/* Long sub-IE, c.f. fig 48s in IEEE 802.15.4e */
|
||||
len = ie_desc & 0x7ff; /* b0-b10 */
|
||||
id = (ie_desc & 0x7800) >> 11; /* b11-b14 */
|
||||
PRINTF("frame802154e: long mlme ie len %u id %x\n", len, id);
|
||||
if(len > buf_size || frame802154e_parse_mlme_long_ie(buf, len, id, ies) == -1) {
|
||||
PRINTF("frame802154e: failed to parse ie\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
/* Update remaining nested MLME len */
|
||||
nested_mlme_len -= 2 + len;
|
||||
if(nested_mlme_len < 0) {
|
||||
PRINTF("frame802154e: found more sub-IEs than initially advertised\n");
|
||||
/* We found more sub-IEs than initially advertised */
|
||||
return -1;
|
||||
}
|
||||
if(nested_mlme_len == 0) {
|
||||
PRINTF("frame802154e: end of MLME IE parsing\n");
|
||||
/* End of IE parsing, look for another payload IE */
|
||||
parsing_state = PARSING_PAYLOAD_IE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
buf += len;
|
||||
buf_size -= len;
|
||||
}
|
||||
|
||||
if(parsing_state == PARSING_HEADER_IE) {
|
||||
ies->ie_payload_ie_offset = buf - start; /* Save IE header len */
|
||||
}
|
||||
|
||||
return buf - start;
|
||||
}
|
120
core/net/mac/frame802154e-ie.h
Normal file
120
core/net/mac/frame802154e-ie.h
Normal file
|
@ -0,0 +1,120 @@
|
|||
/*
|
||||
* Copyright (c) 2015, SICS Swedish ICT.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the Institute nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the Contiki operating system.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
* IEEE 802.15.4e Information Element (IE) creation and parsing.
|
||||
* \author
|
||||
* Simon Duquennoy <simonduq@sics.se>
|
||||
*/
|
||||
|
||||
#ifndef FRAME_802154E_H
|
||||
#define FRAME_802154E_H
|
||||
|
||||
#include "contiki.h"
|
||||
/* We need definitions from tsch-private.h for TSCH-specific information elements */
|
||||
#include "net/mac/tsch/tsch-private.h"
|
||||
|
||||
#define FRAME802154E_IE_MAX_LINKS 4
|
||||
|
||||
/* Structures used for the Slotframe and Links information element */
|
||||
struct tsch_slotframe_and_links_link {
|
||||
uint16_t timeslot;
|
||||
uint16_t channel_offset;
|
||||
uint8_t link_options;
|
||||
};
|
||||
struct tsch_slotframe_and_links {
|
||||
uint8_t num_slotframes; /* We support only 0 or 1 slotframe in this IE */
|
||||
uint8_t slotframe_handle;
|
||||
uint16_t slotframe_size;
|
||||
uint8_t num_links;
|
||||
struct tsch_slotframe_and_links_link links[FRAME802154E_IE_MAX_LINKS];
|
||||
};
|
||||
|
||||
/* The information elements that we currently support */
|
||||
struct ieee802154_ies {
|
||||
/* Header IEs */
|
||||
int16_t ie_time_correction;
|
||||
uint8_t ie_is_nack;
|
||||
/* Payload MLME */
|
||||
uint8_t ie_payload_ie_offset;
|
||||
uint16_t ie_mlme_len;
|
||||
/* Payload Short MLME IEs */
|
||||
uint8_t ie_tsch_synchronization_offset;
|
||||
struct asn_t ie_asn;
|
||||
uint8_t ie_join_priority;
|
||||
uint8_t ie_tsch_timeslot_id;
|
||||
uint16_t ie_tsch_timeslot[tsch_ts_elements_count];
|
||||
struct tsch_slotframe_and_links ie_tsch_slotframe_and_link;
|
||||
/* Payload Long MLME IEs */
|
||||
uint8_t ie_channel_hopping_sequence_id;
|
||||
/* We include and parse only the sequence len and list and omit unused fields */
|
||||
uint16_t ie_hopping_sequence_len;
|
||||
uint8_t ie_hopping_sequence_list[TSCH_HOPPING_SEQUENCE_MAX_LEN];
|
||||
};
|
||||
|
||||
/** Insert various Information Elements **/
|
||||
/* Header IE. ACK/NACK time correction. Used in enhanced ACKs */
|
||||
int frame80215e_create_ie_header_ack_nack_time_correction(uint8_t *buf, int len,
|
||||
struct ieee802154_ies *ies);
|
||||
/* Header IE. List termination 1 (Signals the end of the Header IEs when
|
||||
* followed by payload IEs) */
|
||||
int frame80215e_create_ie_header_list_termination_1(uint8_t *buf, int len,
|
||||
struct ieee802154_ies *ies);
|
||||
/* Header IE. List termination 2 (Signals the end of the Header IEs when
|
||||
* followed by an unformatted payload) */
|
||||
int frame80215e_create_ie_header_list_termination_2(uint8_t *buf, int len,
|
||||
struct ieee802154_ies *ies);
|
||||
/* Payload IE. List termination */
|
||||
int frame80215e_create_ie_payload_list_termination(uint8_t *buf, int len,
|
||||
struct ieee802154_ies *ies);
|
||||
/* Payload IE. MLME. Used to nest sub-IEs */
|
||||
int frame80215e_create_ie_mlme(uint8_t *buf, int len,
|
||||
struct ieee802154_ies *ies);
|
||||
/* MLME sub-IE. TSCH synchronization. Used in EBs: ASN and join priority */
|
||||
int frame80215e_create_ie_tsch_synchronization(uint8_t *buf, int len,
|
||||
struct ieee802154_ies *ies);
|
||||
/* MLME sub-IE. TSCH slotframe and link. Used in EBs: initial schedule */
|
||||
int frame80215e_create_ie_tsch_slotframe_and_link(uint8_t *buf, int len,
|
||||
struct ieee802154_ies *ies);
|
||||
/* MLME sub-IE. TSCH timeslot. Used in EBs: timeslot template (timing) */
|
||||
int frame80215e_create_ie_tsch_timeslot(uint8_t *buf, int len,
|
||||
struct ieee802154_ies *ies);
|
||||
/* MLME sub-IE. TSCH channel hopping sequence. Used in EBs: hopping sequence */
|
||||
int frame80215e_create_ie_tsch_channel_hopping_sequence(uint8_t *buf, int len,
|
||||
struct ieee802154_ies *ies);
|
||||
|
||||
/* Parse all Information Elements of a frame */
|
||||
int frame802154e_parse_information_elements(const uint8_t *buf, uint8_t buf_size,
|
||||
struct ieee802154_ies *ies);
|
||||
|
||||
#endif /* FRAME_802154E_H */
|
|
@ -62,30 +62,6 @@ static uint8_t mac_dsn;
|
|||
|
||||
static uint8_t initialized = 0;
|
||||
|
||||
/** \brief The 16-bit identifier of the PAN on which the device is
|
||||
* sending to. If this value is 0xffff, the device is not
|
||||
* associated.
|
||||
*/
|
||||
static const uint16_t mac_dst_pan_id = IEEE802154_PANID;
|
||||
|
||||
/** \brief The 16-bit identifier of the PAN on which the device is
|
||||
* operating. If this value is 0xffff, the device is not
|
||||
* associated.
|
||||
*/
|
||||
static const uint16_t mac_src_pan_id = IEEE802154_PANID;
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static int
|
||||
is_broadcast_addr(uint8_t mode, uint8_t *addr)
|
||||
{
|
||||
int i = mode == FRAME802154_SHORTADDRMODE ? 2 : 8;
|
||||
while(i-- > 0) {
|
||||
if(addr[i] != 0xff) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static int
|
||||
create_frame(int type, int do_create)
|
||||
|
@ -93,6 +69,10 @@ create_frame(int type, int do_create)
|
|||
frame802154_t params;
|
||||
int hdr_len;
|
||||
|
||||
if(frame802154_get_pan_id() == 0xffff) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* init to zeros */
|
||||
memset(¶ms, 0, sizeof(params));
|
||||
|
||||
|
@ -109,10 +89,14 @@ create_frame(int type, int do_create)
|
|||
} else {
|
||||
params.fcf.ack_required = packetbuf_attr(PACKETBUF_ATTR_MAC_ACK);
|
||||
}
|
||||
/* We do not compress PAN ID in outgoing frames, i.e. include one PAN ID (dest by default)
|
||||
* There is one exception, seemingly a typo in Table 2a: rows 2 and 3: when there is no
|
||||
* source nor destination address, we have dest PAN ID iff compression is *set*. */
|
||||
params.fcf.panid_compression = 0;
|
||||
params.fcf.sequence_number_suppression = FRAME802154_SUPPR_SEQNO;
|
||||
|
||||
/* Insert IEEE 802.15.4 (2006) version bits. */
|
||||
params.fcf.frame_version = FRAME802154_IEEE802154_2006;
|
||||
/* Insert IEEE 802.15.4 version bits. */
|
||||
params.fcf.frame_version = FRAME802154_VERSION;
|
||||
|
||||
#if LLSEC802154_SECURITY_LEVEL
|
||||
if(packetbuf_attr(PACKETBUF_ATTR_SECURITY_LEVEL)) {
|
||||
|
@ -120,8 +104,13 @@ create_frame(int type, int do_create)
|
|||
}
|
||||
/* Setting security-related attributes */
|
||||
params.aux_hdr.security_control.security_level = packetbuf_attr(PACKETBUF_ATTR_SECURITY_LEVEL);
|
||||
#if LLSEC802154_USES_FRAME_COUNTER
|
||||
params.aux_hdr.frame_counter.u16[0] = packetbuf_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_0_1);
|
||||
params.aux_hdr.frame_counter.u16[1] = packetbuf_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_2_3);
|
||||
#else /* LLSEC802154_USES_FRAME_COUNTER */
|
||||
params.aux_hdr.security_control.frame_counter_suppression = 1;
|
||||
params.aux_hdr.security_control.frame_counter_size = 1;
|
||||
#endif /* LLSEC802154_USES_FRAME_COUNTER */
|
||||
#if LLSEC802154_USES_EXPLICIT_KEYS
|
||||
params.aux_hdr.security_control.key_id_mode = packetbuf_attr(PACKETBUF_ATTR_KEY_ID_MODE);
|
||||
params.aux_hdr.key_index = packetbuf_attr(PACKETBUF_ATTR_KEY_INDEX);
|
||||
|
@ -150,21 +139,20 @@ create_frame(int type, int do_create)
|
|||
/**
|
||||
\todo For phase 1 the addresses are all long. We'll need a mechanism
|
||||
in the rime attributes to tell the mac to use long or short for phase 2.
|
||||
*/
|
||||
*/
|
||||
if(LINKADDR_SIZE == 2) {
|
||||
/* Use short address mode if linkaddr size is short. */
|
||||
params.fcf.src_addr_mode = FRAME802154_SHORTADDRMODE;
|
||||
} else {
|
||||
params.fcf.src_addr_mode = FRAME802154_LONGADDRMODE;
|
||||
}
|
||||
params.dest_pid = mac_dst_pan_id;
|
||||
params.dest_pid = frame802154_get_pan_id();
|
||||
|
||||
if(packetbuf_holds_broadcast()) {
|
||||
/* Broadcast requires short address mode. */
|
||||
params.fcf.dest_addr_mode = FRAME802154_SHORTADDRMODE;
|
||||
params.dest_addr[0] = 0xFF;
|
||||
params.dest_addr[1] = 0xFF;
|
||||
|
||||
} else {
|
||||
linkaddr_copy((linkaddr_t *)¶ms.dest_addr,
|
||||
packetbuf_addr(PACKETBUF_ADDR_RECEIVER));
|
||||
|
@ -177,7 +165,7 @@ create_frame(int type, int do_create)
|
|||
}
|
||||
|
||||
/* Set the source PAN ID to the global variable. */
|
||||
params.src_pid = mac_src_pan_id;
|
||||
params.src_pid = frame802154_get_pan_id();
|
||||
|
||||
/*
|
||||
* Set up the source address using only the long address mode for
|
||||
|
@ -191,7 +179,6 @@ create_frame(int type, int do_create)
|
|||
if(!do_create) {
|
||||
/* Only calculate header length */
|
||||
return hdr_len;
|
||||
|
||||
} else if(packetbuf_hdralloc(hdr_len)) {
|
||||
frame802154_create(¶ms, packetbuf_hdrptr());
|
||||
|
||||
|
@ -223,35 +210,41 @@ parse(void)
|
|||
{
|
||||
frame802154_t frame;
|
||||
int hdr_len;
|
||||
|
||||
|
||||
hdr_len = frame802154_parse(packetbuf_dataptr(), packetbuf_datalen(), &frame);
|
||||
|
||||
|
||||
if(hdr_len && packetbuf_hdrreduce(hdr_len)) {
|
||||
packetbuf_set_attr(PACKETBUF_ATTR_FRAME_TYPE, frame.fcf.frame_type);
|
||||
|
||||
|
||||
if(frame.fcf.dest_addr_mode) {
|
||||
if(frame.dest_pid != mac_src_pan_id &&
|
||||
frame.dest_pid != FRAME802154_BROADCASTPANDID) {
|
||||
if(frame.dest_pid != frame802154_get_pan_id() &&
|
||||
frame.dest_pid != FRAME802154_BROADCASTPANDID) {
|
||||
/* Packet to another PAN */
|
||||
PRINTF("15.4: for another pan %u\n", frame.dest_pid);
|
||||
return FRAMER_FAILED;
|
||||
}
|
||||
if(!is_broadcast_addr(frame.fcf.dest_addr_mode, frame.dest_addr)) {
|
||||
if(!frame802154_is_broadcast_addr(frame.fcf.dest_addr_mode, frame.dest_addr)) {
|
||||
packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, (linkaddr_t *)&frame.dest_addr);
|
||||
}
|
||||
}
|
||||
packetbuf_set_addr(PACKETBUF_ADDR_SENDER, (linkaddr_t *)&frame.src_addr);
|
||||
packetbuf_set_attr(PACKETBUF_ATTR_PENDING, frame.fcf.frame_pending);
|
||||
packetbuf_set_attr(PACKETBUF_ATTR_MAC_SEQNO, frame.seq);
|
||||
if(frame.fcf.sequence_number_suppression == 0) {
|
||||
packetbuf_set_attr(PACKETBUF_ATTR_MAC_SEQNO, frame.seq);
|
||||
} else {
|
||||
packetbuf_set_attr(PACKETBUF_ATTR_MAC_SEQNO, 0xffff);
|
||||
}
|
||||
#if NETSTACK_CONF_WITH_RIME
|
||||
packetbuf_set_attr(PACKETBUF_ATTR_PACKET_ID, frame.seq);
|
||||
#endif
|
||||
|
||||
|
||||
#if LLSEC802154_SECURITY_LEVEL
|
||||
if(frame.fcf.security_enabled) {
|
||||
packetbuf_set_attr(PACKETBUF_ATTR_SECURITY_LEVEL, frame.aux_hdr.security_control.security_level);
|
||||
#if LLSEC802154_USES_FRAME_COUNTER
|
||||
packetbuf_set_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_0_1, frame.aux_hdr.frame_counter.u16[0]);
|
||||
packetbuf_set_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_2_3, frame.aux_hdr.frame_counter.u16[1]);
|
||||
#endif /* LLSEC802154_USES_FRAME_COUNTER */
|
||||
#if LLSEC802154_USES_EXPLICIT_KEYS
|
||||
packetbuf_set_attr(PACKETBUF_ATTR_KEY_ID_MODE, frame.aux_hdr.security_control.key_id_mode);
|
||||
packetbuf_set_attr(PACKETBUF_ATTR_KEY_INDEX, frame.aux_hdr.key_index);
|
||||
|
@ -264,7 +257,7 @@ parse(void)
|
|||
PRINTADDR(packetbuf_addr(PACKETBUF_ADDR_SENDER));
|
||||
PRINTADDR(packetbuf_addr(PACKETBUF_ADDR_RECEIVER));
|
||||
PRINTF("%d %u (%u)\n", hdr_len, packetbuf_datalen(), packetbuf_totlen());
|
||||
|
||||
|
||||
return hdr_len;
|
||||
}
|
||||
return FRAMER_FAILED;
|
||||
|
@ -273,7 +266,6 @@ parse(void)
|
|||
const struct framer framer_802154 = {
|
||||
hdr_length,
|
||||
create,
|
||||
framer_canonical_create_and_secure,
|
||||
parse
|
||||
};
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
|
|
@ -99,6 +99,5 @@ parse(void)
|
|||
const struct framer framer_nullmac = {
|
||||
hdr_length,
|
||||
create,
|
||||
framer_canonical_create_and_secure,
|
||||
parse
|
||||
};
|
||||
|
|
|
@ -47,13 +47,8 @@ struct framer {
|
|||
|
||||
int (* length)(void);
|
||||
int (* create)(void);
|
||||
|
||||
/** Creates the frame and calls LLSEC.on_frame_created() */
|
||||
int (* create_and_secure)(void);
|
||||
int (* parse)(void);
|
||||
|
||||
};
|
||||
|
||||
int framer_canonical_create_and_secure(void);
|
||||
|
||||
#endif /* FRAMER_H_ */
|
||||
|
|
94
core/net/mac/nordc.c
Normal file
94
core/net/mac/nordc.c
Normal file
|
@ -0,0 +1,94 @@
|
|||
/*
|
||||
* Copyright (c) 2014, SICS Swedish ICT.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the Institute nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the Contiki operating system.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
* This RDC layer does nothing. It is meant for use with MAC
|
||||
* layers that do not use a RDC at all, such as TSCH.
|
||||
* \author
|
||||
* Simon Duquennoy <simonduq@sics.se>
|
||||
*
|
||||
*/
|
||||
|
||||
#include "net/mac/rdc.h"
|
||||
#include "net/netstack.h"
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
send_packet(mac_callback_t sent, void *ptr)
|
||||
{
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
send_list(mac_callback_t sent, void *ptr, struct rdc_buf_list *buf_list)
|
||||
{
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
packet_input(void)
|
||||
{
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static int
|
||||
on(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static int
|
||||
off(int keep_radio_on)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static unsigned short
|
||||
channel_check_interval(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
init(void)
|
||||
{
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
const struct rdc_driver nordc_driver = {
|
||||
"nordc",
|
||||
init,
|
||||
send_packet,
|
||||
send_list,
|
||||
packet_input,
|
||||
on,
|
||||
off,
|
||||
channel_check_interval,
|
||||
};
|
||||
/*---------------------------------------------------------------------------*/
|
|
@ -48,6 +48,7 @@
|
|||
|
||||
#if CONTIKI_TARGET_COOJA
|
||||
#include "lib/simEnvChange.h"
|
||||
#include "sys/cooja_mt.h"
|
||||
#endif /* CONTIKI_TARGET_COOJA */
|
||||
|
||||
#define DEBUG 0
|
||||
|
@ -120,7 +121,7 @@ send_one_packet(mac_callback_t sent, void *ptr)
|
|||
packetbuf_set_attr(PACKETBUF_ATTR_MAC_ACK, 1);
|
||||
#endif /* NULLRDC_802154_AUTOACK || NULLRDC_802154_AUTOACK_HW */
|
||||
|
||||
if(NETSTACK_FRAMER.create_and_secure() < 0) {
|
||||
if(NETSTACK_FRAMER.create() < 0) {
|
||||
/* Failed to allocate space for headers */
|
||||
PRINTF("nullrdc: send failed, too large header\n");
|
||||
ret = MAC_TX_ERR_FATAL;
|
||||
|
@ -302,8 +303,7 @@ packet_input(void)
|
|||
}
|
||||
#endif /* RDC_WITH_DUPLICATE_DETECTION */
|
||||
#endif /* NULLRDC_802154_AUTOACK */
|
||||
|
||||
/* TODO We may want to acknowledge only authentic frames */
|
||||
|
||||
#if NULLRDC_SEND_802154_ACK
|
||||
{
|
||||
frame802154_t info154;
|
||||
|
|
|
@ -219,6 +219,11 @@ phase_wait(const linkaddr_t *neighbor, rtimer_clock_t cycle_time,
|
|||
if(buf_list == NULL) {
|
||||
packetbuf_set_attr(PACKETBUF_ATTR_IS_CREATED_AND_SECURED, 1);
|
||||
p->q = queuebuf_new_from_packetbuf();
|
||||
if(p->q == NULL) {
|
||||
/* memory allocation failed */
|
||||
memb_free(&queued_packets_memb, p);
|
||||
return PHASE_UNKNOWN;
|
||||
}
|
||||
}
|
||||
p->mac_callback = mac_callback;
|
||||
p->mac_callback_ptr = mac_callback_ptr;
|
||||
|
|
1
core/net/mac/tsch/Makefile.tsch
Normal file
1
core/net/mac/tsch/Makefile.tsch
Normal file
|
@ -0,0 +1 @@
|
|||
CONTIKI_SOURCEFILES += tsch.c tsch-slot-operation.c tsch-queue.c tsch-packet.c tsch-schedule.c tsch-log.c tsch-rpl.c tsch-adaptive-timesync.c
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue