[Tinyos-2-commits] CVS: tinyos-2.x/support/sdk/c/blip/driver Makefile, NONE, 1.1 config.c, NONE, 1.1 config.h, NONE, 1.1 hashtable.c, NONE, 1.1 hashtable.h, NONE, 1.1 hashtable_private.h, NONE, 1.1 logging.c, NONE, 1.1 logging.h, NONE, 1.1 nwstate.c, NONE, 1.1 nwstate.h, NONE, 1.1 radvd-wrapper.c, NONE, 1.1 routing.c, NONE, 1.1 routing.h, NONE, 1.1 serial_tun.c, NONE, 1.1 tun_dev.c, NONE, 1.1 tun_dev.h, NONE, 1.1 tunnel.c, NONE, 1.1
sdhsdh
sdhsdh at users.sourceforge.net
Mon Jan 19 16:28:16 PST 2009
- Previous message: [Tinyos-2-commits] CVS: tinyos-2.x/support/sdk/c/blip Makefile, NONE, 1.1 serial_tun.conf, NONE, 1.1
- Next message: [Tinyos-2-commits] CVS: tinyos-2.x/support/sdk/c/blip/driver/radvd-1.0 CHANGES, NONE, 1.1 COPYRIGHT, NONE, 1.1 INTRO.html, NONE, 1.1 Makefile, NONE, 1.1 Makefile.am, NONE, 1.1 Makefile.in, NONE, 1.1 README, NONE, 1.1 TODO, NONE, 1.1 VERSION, NONE, 1.1 aclocal.m4, NONE, 1.1 config.cache, NONE, 1.1 config.guess, NONE, 1.1 config.h, NONE, 1.1 config.h.in, NONE, 1.1 config.log, NONE, 1.1 config.status, NONE, 1.1 config.sub, NONE, 1.1 configure, NONE, 1.1 configure.in, NONE, 1.1 copyright.blurb, NONE, 1.1 defaults.h, NONE, 1.1 depcomp, NONE, 1.1 device-bsd44.c, NONE, 1.1 device-common.c, NONE, 1.1 device-linux.c, NONE, 1.1 gram.c, NONE, 1.1 gram.h, NONE, 1.1 gram.y, NONE, 1.1 includes.h, NONE, 1.1 install-sh, NONE, 1.1 interface.c, NONE, 1.1 log.c, NONE, 1.1 missing, NONE, 1.1 mkinstalldirs, NONE, 1.1 pathnames.h, NONE, 1.1 process.c, NONE, 1.1 radvd.8.man, NONE, 1.1 radvd.c, NONE, 1.1 radvd.conf.5.man, NONE, 1.1 radvd.conf.example, NONE, 1.1 radvd.h, NONE, 1.1 radvdump.8.man, NONE, 1.1 radvdump.c, NONE, 1.1 recv.c, NONE, 1.1 scanner.c, NONE, 1.1 scanner.l, NONE, 1.1 send.c, NONE, 1.1 socket.c, NONE, 1.1 stamp-h, NONE, 1.1 stamp-h.in, NONE, 1.1 timer.c, NONE, 1.1 util.c, NONE, 1.1
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
Update of /cvsroot/tinyos/tinyos-2.x/support/sdk/c/blip/driver
In directory ddv4jf1.ch3.sourceforge.com:/tmp/cvs-serv6583/support/sdk/c/blip/driver
Added Files:
Makefile config.c config.h hashtable.c hashtable.h
hashtable_private.h logging.c logging.h nwstate.c nwstate.h
radvd-wrapper.c routing.c routing.h serial_tun.c tun_dev.c
tun_dev.h tunnel.c
Log Message:
- initial commit of blip (berkeley low-power ip) stack
--- NEW FILE: Makefile ---
SOURCES=serial_tun.c tun_dev.c hashtable.c routing.c nwstate.c \
logging.c config.c radvd-wrapper.c
COMMON_SRC = radvd/log.c radvd/socket.c radvd/recv.c radvd/util.c radvd/radvd.h \
radvd/defaults.h radvd/pathnames.h \
radvd/includes.h
radvd_SOURCES = $(COMMON_SRC) radvd/timer.c radvd/send.c radvd/process.c radvd/interface.c \
radvd/device.c radvd/device-common.c radvd/gram.h
LIBS=../lib6lowpan.a ${TOSROOT}/support/sdk/c/sf/libmote.a
TARGET=ip-driver
INCLUDE=../include/
ifndef GCC
GCC=gcc
endif
TFLAGS=-Wall -g -DPC
TFLAGS+=-I${TOSROOT}/support/sdk/c/sf -I$(INCLUDE) -Iradvd/
ifneq ($(filter sim-null,$(MAKECMDGOALS)),)
TFLAGS+=-DSIM
endif
# CFLAGS+=-DFULL_PATH_INSTALL
all: $(TARGET)
sim: lib
make $(TARGET) sim-null
sim-null:
echo Built $(TARGET) for TOSSIM
$(TARGET): $(SOURCES) $(LIBS)
$(GCC) $(TFLAGS) $(CFLAGS) -o $(TARGET) $(SOURCES) $(radvd_SOURCES) $(LIBS) -lm
clean:
rm $(TARGET)
--- NEW FILE: config.c ---
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include "ip.h"
#include "config.h"
#include "logging.h"
#define BUF_LEN 200
void rm_comment (char *buf) {
while (*buf != '#' && *buf != '\0')
buf++;
*buf = '\0';
}
void upd_start(char **buf) {
while ((**buf == ' ' || **buf == '\t' || **buf == '\n') && **buf != '\0')
*buf = (*buf) + 1;
}
int config_parse(const char *file, struct config *c) {
char *buf, real_buf[BUF_LEN], arg[BUF_LEN];
FILE *fp = fopen(file, "r");
int gotargs = 0;
if (fp == NULL) return 1;
while (fgets(real_buf, BUF_LEN, fp) != NULL) {
buf = real_buf;
rm_comment(buf);
upd_start(&buf);
if (sscanf(buf, "addr %s\n", arg) > 0) {
inet_pton6(arg, &c->router_addr);
gotargs ++;
} else if (sscanf(buf, "proxy %s\n", c->proxy_dev) > 0) {
gotargs ++;
} else if (sscanf(buf, "channel %i\n", &c->channel) > 0) {
if (c->channel < 11 || c->channel > 26) {
fatal("Invalid channel specified in '%s'\n", file);
exit(1);
}
gotargs ++;
} else if (sscanf(buf, "log %s\n", arg) > 0) {
int i;
for (i = 0; i < 5; i++) {
if (strncmp(log_names[i], arg, strlen(log_names[i])) == 0) {
info("Read log level: %s\n", arg);
log_setlevel(i);
break;
}
}
} else if (*buf != '\0') {
// anything else indicates that there's invalid input.
return 1;
}
}
fclose(fp);
if (gotargs != 3) return 1;
info("Read config from '%s'\n", file);
info("\tProxying neighbor advertisements to %s\n", c->proxy_dev);
info("\tUsing channel %i\n", c->channel);
return 0;
}
int config_print(struct config *c) {
char buf[64];
printf ("configuration:\n");
inet_ntop(AF_INET6, &c->router_addr, buf, 64);
printf (" router address: %s\n", buf);
printf(" proxy dev: %s\n", c->proxy_dev);
printf(" channel: %i\n", c->channel);
return 0;
}
--- NEW FILE: config.h ---
#ifndef _CONFIG_H
#define _CONFIG_H
#include <net/if.h>
struct config {
struct in6_addr router_addr;
char proxy_dev[IFNAMSIZ];
int channel;
};
int config_parse(const char *file, struct config *c);
int config_print(struct config *c);
#endif
--- NEW FILE: hashtable.c ---
/* Copyright (C) 2004 Christopher Clark <firstname.lastname at cl.cam.ac.uk> */
#include "hashtable.h"
#include "hashtable_private.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
/*
Credit for primes table: Aaron Krowne
http://br.endernet.org/~akrowne/
http://planetmath.org/encyclopedia/GoodHashTablePrimes.html
*/
static const unsigned int primes[] = {
53, 97, 193, 389,
769, 1543, 3079, 6151,
12289, 24593, 49157, 98317,
196613, 393241, 786433, 1572869,
3145739, 6291469, 12582917, 25165843,
50331653, 100663319, 201326611, 402653189,
805306457, 1610612741
};
const unsigned int prime_table_length = sizeof(primes)/sizeof(primes[0]);
const float max_load_factor = 0.65;
/*****************************************************************************/
struct hashtable *
create_hashtable(unsigned int minsize,
unsigned int (*hashf) (void*),
int (*eqf) (void*,void*))
{
struct hashtable *h;
unsigned int pindex, size = primes[0];
/* Check requested hashtable isn't too large */
if (minsize > (1u << 30)) return NULL;
/* Enforce size as prime */
for (pindex=0; pindex < prime_table_length; pindex++) {
if (primes[pindex] > minsize) { size = primes[pindex]; break; }
}
h = (struct hashtable *)malloc(sizeof(struct hashtable));
if (NULL == h) return NULL; /*oom*/
h->table = (struct entry **)malloc(sizeof(struct entry*) * size);
if (NULL == h->table) { free(h); return NULL; } /*oom*/
memset(h->table, 0, size * sizeof(struct entry *));
h->tablelength = size;
h->primeindex = pindex;
h->entrycount = 0;
h->hashfn = hashf;
h->eqfn = eqf;
h->loadlimit = (unsigned int) ceil(size * max_load_factor);
return h;
}
/*****************************************************************************/
unsigned int
hash(struct hashtable *h, void *k)
{
/* Aim to protect against poor hash functions by adding logic here
* - logic taken from java 1.4 hashtable source */
unsigned int i = h->hashfn(k);
i += ~(i << 9);
i ^= ((i >> 14) | (i << 18)); /* >>> */
i += (i << 4);
i ^= ((i >> 10) | (i << 22)); /* >>> */
return i;
}
/*****************************************************************************/
static int
hashtable_expand(struct hashtable *h)
{
/* Double the size of the table to accomodate more entries */
struct entry **newtable;
struct entry *e;
struct entry **pE;
unsigned int newsize, i, index;
/* Check we're not hitting max capacity */
if (h->primeindex == (prime_table_length - 1)) return 0;
newsize = primes[++(h->primeindex)];
newtable = (struct entry **)malloc(sizeof(struct entry*) * newsize);
if (NULL != newtable)
{
memset(newtable, 0, newsize * sizeof(struct entry *));
/* This algorithm is not 'stable'. ie. it reverses the list
* when it transfers entries between the tables */
for (i = 0; i < h->tablelength; i++) {
while (NULL != (e = h->table[i])) {
h->table[i] = e->next;
index = indexFor(newsize,e->h);
e->next = newtable[index];
newtable[index] = e;
}
}
free(h->table);
h->table = newtable;
}
/* Plan B: realloc instead */
else
{
newtable = (struct entry **)
realloc(h->table, newsize * sizeof(struct entry *));
if (NULL == newtable) { (h->primeindex)--; return 0; }
h->table = newtable;
memset(newtable[h->tablelength], 0, newsize - h->tablelength);
for (i = 0; i < h->tablelength; i++) {
for (pE = &(newtable[i]), e = *pE; e != NULL; e = *pE) {
index = indexFor(newsize,e->h);
if (index == i)
{
pE = &(e->next);
}
else
{
*pE = e->next;
e->next = newtable[index];
newtable[index] = e;
}
}
}
}
h->tablelength = newsize;
h->loadlimit = (unsigned int) ceil(newsize * max_load_factor);
return -1;
}
/*****************************************************************************/
unsigned int
hashtable_count(struct hashtable *h)
{
return h->entrycount;
}
/*****************************************************************************/
int
hashtable_insert(struct hashtable *h, void *k, void *v)
{
/* This method allows duplicate keys - but they shouldn't be used */
unsigned int index;
struct entry *e;
if (++(h->entrycount) > h->loadlimit)
{
/* Ignore the return value. If expand fails, we should
* still try cramming just this value into the existing table
* -- we may not have memory for a larger table, but one more
* element may be ok. Next time we insert, we'll try expanding again.*/
hashtable_expand(h);
}
e = (struct entry *)malloc(sizeof(struct entry));
if (NULL == e) { --(h->entrycount); return 0; } /*oom*/
e->h = hash(h,k);
index = indexFor(h->tablelength,e->h);
e->k = k;
e->v = v;
e->next = h->table[index];
h->table[index] = e;
return -1;
}
/*****************************************************************************/
void * /* returns value associated with key */
hashtable_search(struct hashtable *h, void *k)
{
struct entry *e;
unsigned int hashvalue, index;
hashvalue = hash(h,k);
index = indexFor(h->tablelength,hashvalue);
e = h->table[index];
while (NULL != e)
{
/* Check hash value to short circuit heavier comparison */
if ((hashvalue == e->h) && (h->eqfn(k, e->k))) return e->v;
e = e->next;
}
return NULL;
}
/*****************************************************************************/
void * /* returns value associated with key */
hashtable_remove(struct hashtable *h, void *k)
{
/* TODO: consider compacting the table when the load factor drops enough,
* or provide a 'compact' method. */
struct entry *e;
struct entry **pE;
void *v;
unsigned int hashvalue, index;
hashvalue = hash(h,k);
index = indexFor(h->tablelength,hash(h,k));
pE = &(h->table[index]);
e = *pE;
while (NULL != e)
{
/* Check hash value to short circuit heavier comparison */
if ((hashvalue == e->h) && (h->eqfn(k, e->k)))
{
*pE = e->next;
h->entrycount--;
v = e->v;
freekey(e->k);
free(e);
return v;
}
pE = &(e->next);
e = e->next;
}
return NULL;
}
/*****************************************************************************/
/* destroy */
void
hashtable_destroy(struct hashtable *h, int free_values)
{
unsigned int i;
struct entry *e, *f;
struct entry **table = h->table;
if (free_values)
{
for (i = 0; i < h->tablelength; i++)
{
e = table[i];
while (NULL != e)
{ f = e; e = e->next; freekey(f->k); free(f->v); free(f); }
}
}
else
{
for (i = 0; i < h->tablelength; i++)
{
e = table[i];
while (NULL != e)
{ f = e; e = e->next; freekey(f->k); free(f); }
}
}
free(h->table);
free(h);
}
/*
* Copyright (c) 2002, Christopher Clark
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * 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.
*
* * Neither the name of the original author; nor the names of any contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER
* 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.
*/
--- NEW FILE: hashtable.h ---
/* Copyright (C) 2002 Christopher Clark <firstname.lastname at cl.cam.ac.uk> */
#ifndef __HASHTABLE_CWC22_H__
#define __HASHTABLE_CWC22_H__
struct hashtable;
/* Example of use:
*
* struct hashtable *h;
* struct some_key *k;
* struct some_value *v;
*
* static unsigned int hash_from_key_fn( void *k );
* static int keys_equal_fn ( void *key1, void *key2 );
*
* h = create_hashtable(16, hash_from_key_fn, keys_equal_fn);
* k = (struct some_key *) malloc(sizeof(struct some_key));
* v = (struct some_value *) malloc(sizeof(struct some_value));
*
* (initialise k and v to suitable values)
*
* if (! hashtable_insert(h,k,v) )
* { exit(-1); }
*
* if (NULL == (found = hashtable_search(h,k) ))
* { printf("not found!"); }
*
* if (NULL == (found = hashtable_remove(h,k) ))
* { printf("Not found\n"); }
*
*/
/* Macros may be used to define type-safe(r) hashtable access functions, with
* methods specialized to take known key and value types as parameters.
*
* Example:
*
* Insert this at the start of your file:
*
* DEFINE_HASHTABLE_INSERT(insert_some, struct some_key, struct some_value);
* DEFINE_HASHTABLE_SEARCH(search_some, struct some_key, struct some_value);
* DEFINE_HASHTABLE_REMOVE(remove_some, struct some_key, struct some_value);
*
* This defines the functions 'insert_some', 'search_some' and 'remove_some'.
* These operate just like hashtable_insert etc., with the same parameters,
* but their function signatures have 'struct some_key *' rather than
* 'void *', and hence can generate compile time errors if your program is
* supplying incorrect data as a key (and similarly for value).
*
* Note that the hash and key equality functions passed to create_hashtable
* still take 'void *' parameters instead of 'some key *'. This shouldn't be
* a difficult issue as they're only defined and passed once, and the other
* functions will ensure that only valid keys are supplied to them.
*
* The cost for this checking is increased code size and runtime overhead
* - if performance is important, it may be worth switching back to the
* unsafe methods once your program has been debugged with the safe methods.
* This just requires switching to some simple alternative defines - eg:
* #define insert_some hashtable_insert
*
*/
/*****************************************************************************
* create_hashtable
* @name create_hashtable
* @param minsize minimum initial size of hashtable
* @param hashfunction function for hashing keys
* @param key_eq_fn function for determining key equality
* @return newly created hashtable or NULL on failure
*/
struct hashtable *
create_hashtable(unsigned int minsize,
unsigned int (*hashfunction) (void*),
int (*key_eq_fn) (void*,void*));
/*****************************************************************************
* hashtable_insert
* @name hashtable_insert
* @param h the hashtable to insert into
* @param k the key - hashtable claims ownership and will free on removal
* @param v the value - does not claim ownership
* @return non-zero for successful insertion
*
* This function will cause the table to expand if the insertion would take
* the ratio of entries to table size over the maximum load factor.
*
* This function does not check for repeated insertions with a duplicate key.
* The value returned when using a duplicate key is undefined -- when
* the hashtable changes size, the order of retrieval of duplicate key
* entries is reversed.
* If in doubt, remove before insert.
*/
int
hashtable_insert(struct hashtable *h, void *k, void *v);
#define DEFINE_HASHTABLE_INSERT(fnname, keytype, valuetype) \
int fnname (struct hashtable *h, keytype *k, valuetype *v) \
{ \
return hashtable_insert(h,k,v); \
}
/*****************************************************************************
* hashtable_search
* @name hashtable_search
* @param h the hashtable to search
* @param k the key to search for - does not claim ownership
* @return the value associated with the key, or NULL if none found
*/
void *
hashtable_search(struct hashtable *h, void *k);
#define DEFINE_HASHTABLE_SEARCH(fnname, keytype, valuetype) \
valuetype * fnname (struct hashtable *h, keytype *k) \
{ \
return (valuetype *) (hashtable_search(h,k)); \
}
/*****************************************************************************
* hashtable_remove
* @name hashtable_remove
* @param h the hashtable to remove the item from
* @param k the key to search for - does not claim ownership
* @return the value associated with the key, or NULL if none found
*/
void * /* returns value */
hashtable_remove(struct hashtable *h, void *k);
#define DEFINE_HASHTABLE_REMOVE(fnname, keytype, valuetype) \
valuetype * fnname (struct hashtable *h, keytype *k) \
{ \
return (valuetype *) (hashtable_remove(h,k)); \
}
/*****************************************************************************
* hashtable_count
* @name hashtable_count
* @param h the hashtable
* @return the number of items stored in the hashtable
*/
unsigned int
hashtable_count(struct hashtable *h);
/*****************************************************************************
* hashtable_destroy
* @name hashtable_destroy
* @param h the hashtable
* @param free_values whether to call 'free' on the remaining values
*/
void
hashtable_destroy(struct hashtable *h, int free_values);
#endif /* __HASHTABLE_CWC22_H__ */
/*
* Copyright (c) 2002, Christopher Clark
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * 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.
*
* * Neither the name of the original author; nor the names of any contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER
* 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.
*/
--- NEW FILE: hashtable_private.h ---
/*
* "Copyright (c) 2008 The Regents of the University of California.
* All rights reserved."
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement is
* hereby granted, provided that the above copyright notice, the following
* two paragraphs and the author appear in all copies of this software.
*
* IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
* CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
*
*/
/* Copyright (C) 2002, 2004 Christopher Clark <firstname.lastname at cl.cam.ac.uk> */
#ifndef __HASHTABLE_PRIVATE_CWC22_H__
#define __HASHTABLE_PRIVATE_CWC22_H__
#include "hashtable.h"
/*****************************************************************************/
struct entry
{
void *k, *v;
unsigned int h;
struct entry *next;
};
struct hashtable {
unsigned int tablelength;
struct entry **table;
unsigned int entrycount;
unsigned int loadlimit;
unsigned int primeindex;
unsigned int (*hashfn) (void *k);
int (*eqfn) (void *k1, void *k2);
};
/*****************************************************************************/
unsigned int
hash(struct hashtable *h, void *k);
/*****************************************************************************/
/* indexFor */
static inline unsigned int
indexFor(unsigned int tablelength, unsigned int hashvalue) {
return (hashvalue % tablelength);
};
/* Only works if tablelength == 2^N */
/*static inline unsigned int
indexFor(unsigned int tablelength, unsigned int hashvalue)
{
return (hashvalue & (tablelength - 1u));
}
*/
/*****************************************************************************/
#define freekey(X) free(X)
/*define freekey(X) ; */
/*****************************************************************************/
#endif /* __HASHTABLE_PRIVATE_CWC22_H__*/
/*
* Copyright (c) 2002, Christopher Clark
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * 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.
*
* * Neither the name of the original author; nor the names of any contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER
* 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.
*/
--- NEW FILE: logging.c ---
/*
* "Copyright (c) 2008 The Regents of the University of California.
* All rights reserved."
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement is
* hereby granted, provided that the above copyright notice, the following
* two paragraphs and the author appear in all copies of this software.
*
* IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
* CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
*
*/
#include <stdio.h>
#include <time.h>
#include <sys/time.h>
#include <stdarg.h>
#include "logging.h"
loglevel_t log_level;
FILE *log_dest;
char *log_names[5] = {"DEBUG",
"INFO",
"WARN",
"ERROR",
"FATAL"};
static void timestamp(){
struct timeval tv;
struct timezone tz;
struct tm *ltime;
gettimeofday(&tv, &tz);
ltime = localtime(&tv.tv_sec);
fprintf(log_dest, "%02d:%02d:%02d.%03d: ",
ltime->tm_hour, ltime->tm_min, ltime->tm_sec, (int)tv.tv_usec);
}
loglevel_t log_setlevel(loglevel_t l) {
loglevel_t old_lvl = log_level;
log_level = l;
return old_lvl;
}
loglevel_t log_getlevel() {
return log_level;
}
void log_init() {
log_level = LOGLVL_INFO;
log_dest = stderr;
}
void log_log (loglevel_t level, const char *fmt, ...) {
if (log_level > level) return;
va_list ap;
va_start(ap, fmt);
timestamp();
fprintf(log_dest, "%s: ", log_names[level]);
vfprintf(log_dest, fmt, ap);
va_end(ap);
}
void log_clear (loglevel_t level, const char *fmt, ...) {
if (log_level > level) return;
va_list ap;
va_start(ap, fmt);
vfprintf(log_dest, fmt, ap);
va_end(ap);
}
/* print char* in hex format */
void log_dump_serial_packet(unsigned char *packet, const int len) {
int i;
if (log_level > LOGLVL_DEBUG) return;
printf("len: %d\n", len);
if (!packet)
return;
for (i = 0; i < len; i++) {
printf("%02x ", packet[i]);
//printf("%02x(%c) ", packet[i], packet[i]);
//printf("%c", packet[i]);
}
putchar('\n');
}
--- NEW FILE: logging.h ---
/*
* "Copyright (c) 2008 The Regents of the University of California.
* All rights reserved."
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement is
* hereby granted, provided that the above copyright notice, the following
* two paragraphs and the author appear in all copies of this software.
*
* IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
* CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
*
*/
#ifndef LOGGING_H_
#define LOGGING_H_
#include <stdio.h>
// SDH : log levels defined here
// also edit the log names in logging.h
typedef enum {
LOGLVL_DEBUG = 0,
LOGLVL_INFO = 1,
LOGLVL_WARN = 2,
LOGLVL_ERROR = 3,
LOGLVL_FATAL = 4,
} loglevel_t;
extern char *log_names[5];
extern loglevel_t log_level;
extern FILE *log_dest;
void log_init();
loglevel_t log_setlevel(loglevel_t l);
loglevel_t log_getlevel();
void log_log (loglevel_t level, const char *fmt, ...);
void log_clear (loglevel_t level, const char *fmt, ...);
#define debug(fmt, args...) \
log_log(LOGLVL_DEBUG, fmt, ## args)
#define info(fmt, args...) \
log_log(LOGLVL_INFO, fmt, ## args)
#define warn(fmt, args...) \
log_log(LOGLVL_WARN, fmt, ## args)
#define error(fmt, args...) \
log_log(LOGLVL_ERROR, fmt, ## args)
#define fatal(fmt, args...) \
log_log(LOGLVL_FATAL, fmt, ## args)
#define log_fprintf(X, FMT, ...) ;
void log_dump_serial_packet(unsigned char *packet, const int len);
#endif
--- NEW FILE: nwstate.c ---
/*
* "Copyright (c) 2008 The Regents of the University of California.
* All rights reserved."
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement is
* hereby granted, provided that the above copyright notice, the following
* two paragraphs and the author appear in all copies of this software.
*
* IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
* CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
*
*/
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <float.h>
#include "nwstate.h"
#include "hashtable.h"
#include "logging.h"
#include "lib6lowpan.h"
#include "routing.h"
struct hashtable *links;
struct hashtable *routers;
router_t *router_list = NULL;
int routes_out_of_date = 1;
extern struct in6_addr __my_address;
void compute_routes(node_id_t v1);
//
// general boilerplate
//
static unsigned int hash_link(void *k) {
link_key_t *l = (link_key_t *)k;
if (l->r1 > l->r2)
return (l->r1 | (l->r2 << 16));
else
return (l->r2 | (l->r1 << 16));
}
static int link_equal(void *k1, void *k2) {
link_key_t *l1 = (link_key_t *)k1;
link_key_t *l2 = (link_key_t *)k2;
return ((l1->r1 == l2->r1 && l1->r2 == l2->r2) ||
(l1->r1 == l2->r2 && l1->r2 == l2->r1));
}
static unsigned int hash_router(void *k) {
return *((router_key_t *)k);
}
static int router_equal(void *k1, void *k2) {
return ((router_t *)k1)->id == ((router_t *)k2)->id;
}
int do_print = 0;
int do_routes = 0;
int printCount = 0;
int nw_print_dotfile(char *filename) {
router_t *r;
link_t *e;
FILE *fp = fopen (filename, "w");
if (fp == NULL) return -1;
info("writing topology to '%s'\n", filename);
printCount ++;
fprintf(fp, "digraph Network {\n");
for (r = router_list; r != NULL; r = r->next) {
for (e = r->links; e != NULL; e = e->next1) {
if (e->pc < printCount) {
fprintf(fp, " \"0x%x\" -> \"0x%x\" [label=\"%f\"]\n", e->n1->id, e->n2->id, e->qual);
e->pc = printCount;
}
}
for (e = r->links; e != NULL; e = e->next2) {
if (e->pc < printCount) {
fprintf(fp, " \"0x%x\" -> \"0x%x\" [label=\"%f\"]\n", e->n1->id, e->n2->id, e->qual);
e->pc = printCount;
}
}
}
fprintf(fp, "}\n");
fclose(fp);
return 0;
}
void nw_print_routes() {
router_t *r,*s;
for (r = router_list; r != NULL; r = r->next) {
log_clear(LOGLVL_INFO, " 0x%x: ", r->id);
for (s = r->sp.prev; s != NULL; s = s->sp.prev) {
log_clear(LOGLVL_INFO, "0x%x ", s->id);
}
log_clear(LOGLVL_INFO, "\n");
}
}
void nw_test_routes() {
node_id_t dest = ntohs(__my_address.s6_addr16[7]);
debug("nwstate: computing new routes (root: 0x%x)\n", ntohs(__my_address.s6_addr16[7]));
compute_routes(dest);
}
void nw_print_links() {
router_t *r;
link_t *l;
for (r = router_list; r != NULL; r = r->next) {
log_clear(LOGLVL_INFO, " 0x%x: dist: %.1f\n", r->id, r->sp.dist);
for (l = r->links; l != NULL; l = (r == l->n1) ? l->next1 : l->next2) {
if (r == l->n1) {
log_clear(LOGLVL_INFO, " --> 0x%x [%.1f]\n", l->n2->id, l->qual);
}
}
log_clear(LOGLVL_INFO, "\n");
}
}
//
// helpers
//
router_t *get_insert_router(node_id_t rid) {
router_key_t *key;
router_t *ret = hashtable_search(routers, &rid);
if (ret == NULL) {
key = (router_key_t *)malloc(sizeof(router_key_t));
ret = (router_t *)malloc(sizeof(router_t));
ret->id = rid;
ret->links = NULL;
ret->next = router_list;
ret->reports = 0;
ret->sp.dist = FLT_MAX;
ret->sp.prev = NULL;
router_list = ret;
*key = rid;
hashtable_insert(routers, key, ret);
routing_add_table_entry(rid);
}
return ret;
}
//
// network state API impl.
//
int nw_init() {
links = create_hashtable(16, hash_link, link_equal);
routers = create_hashtable(16, hash_router, router_equal);
return 0;
}
/*
* Adds an observation of the link (v1, v2) to the database. This
* implicitly adds the reverse edge for now, as well.
*/
int nw_add_incr_edge(node_id_t v1, struct topology_entry *te) {
link_key_t key;
link_t *link_str;
node_id_t v2 = ntoh16(te->hwaddr);
key.r1 = v1;
key.r2 = v2;
link_str = hashtable_search(links, &key);
if (link_str == NULL) {
link_key_t *new_key = (link_key_t *)malloc(sizeof(link_key_t));
router_t *r1 = get_insert_router(v1);
router_t *r2 = get_insert_router(v2);
link_str = (link_t *)malloc(sizeof(link_t));
new_key->r1 = v1;
new_key->r2 = v2;
// point the links at their routers
link_str->n1 = r1;
link_str->n2 = r2;
// add this link to the head of the linked list of edges each router maintains
link_str->next1 = r1->links;
link_str->next2 = r2->links;
link_str->n1_reportcount = 0;
link_str->n2_reportcount = 0;
r1->links = link_str;
r2->links = link_str;
link_str->pc = 0;
hashtable_insert(links, new_key, link_str);
}
link_str->marked = 1;
link_str->qual = ((float)(te->etx)) / 10.0;
link_str->conf = te->conf;
debug("nw_add_incr_edge [%i -> %i]: qual: %f conf: %i\n",
v1, v2, link_str->qual, link_str->conf);
(v1 == link_str->n1->id) ? link_str->n1_reportcount++ :
link_str->n2_reportcount++;
return 0;
}
/*
* Returns a route from v1 to v2 as a linked list.
*
* quadratic-time dijkstra implementation: no priority queue
*/
/*
* relaxes the neighbors of cur
*/
float getMetric(link_t *l) {
return l->qual;
//return ((float)l->qual / 3000.0) + 1.0;
//return (10. / (float)l->nobs);
}
void update_neighbors(router_t *cur) {
link_t *l;
router_t *otherguy;
// clunky iterator
for (l = cur->links; l != NULL; l = (cur == l->n1) ? l->next1 : l->next2) {
otherguy = (cur == l->n1) ? l->n2 : l->n1;
if (cur->sp.dist + getMetric(l) < otherguy->sp.dist) {
otherguy->sp.dist = cur->sp.dist + getMetric(l);
otherguy->sp.prev = cur;
}
}
}
router_t *extract_min(router_t **list) {
router_t *r, *prev = NULL, *min = NULL, *prev_min = NULL;
float min_dist = FLT_MAX;
for (r = *list; r != NULL; r = r->sp.setptr) {
if (r->sp.dist < min_dist) {
min_dist = r->sp.dist;
min = r;
prev_min = prev;
}
prev = r;
}
if (min == NULL) {
// it might be the case that not everyone is reachable. In that
// case, we'll just leave them unconnected.
*list = NULL;
} else if (prev_min == NULL) {
// the first element was the best, set list is pointed at the second element
*list = (*list)->sp.setptr;
} else {
// otherwise just remove the min element from the list
prev_min->sp.setptr = min->sp.setptr;
}
return min;
}
void age_routers() {
router_t *r;
int max_reports = 0;
for (r = router_list; r != NULL; r = r->next) {
if (r->reports > max_reports) {
max_reports = r->reports;
}
// debug("nwstate: node: %i reports: %i\n", r->id, r->reports);
}
if (max_reports == 4) {
debug("age_routers: max: %i\n", max_reports);
for (r = router_list; r != NULL; r = r->next) {
if (r->reports > 0) {
r->reports = 0;
} else {
// debug("nwstate: removing router 0x%x due to age %i\n", r->id, r->reports);
// nw_inval_node(r->id);
r->reports = 0;
}
}
}
}
/*
* compute all destinations shortest path to node v1
*/
void compute_routes(node_id_t v1) {
router_t *r, *cur = NULL, *not_visited = NULL;
routes_out_of_date = 0;
for (r = router_list; r != NULL; r = r->next) {
r->sp.dist = FLT_MAX;
r->sp.prev = NULL;
if (r->id == v1) {
cur = r;
} else {
r->sp.setptr = not_visited;
not_visited = r;
}
}
if (cur == NULL) return;
cur->sp.dist = 0;
while (not_visited != NULL) {
update_neighbors(cur);
cur = extract_min (¬_visited);
}
// all the prev and distance pointers are now valid.
}
path_t *nw_get_route(node_id_t v1, node_id_t v2) {
router_t *r, *from, *to;
path_t *ret = NULL, *new;
from = hashtable_search(routers, &v1);
to = hashtable_search(routers, &v2);
if (from == NULL || to == NULL) return NULL;
if (to->sp.prev == NULL || from->sp.prev != NULL || routes_out_of_date) {
// the current set of shortest paths do not end at node v2, if we
// haven't computed any paths yet, we will do that when the next
// test fails.
debug("nw_get_route: computing new routes\n");
compute_routes(v1);
}
// now the routes should be valid;
for (r = to; r != NULL; r = r->sp.prev) {
// this both constructs the return value and reverses the path,
// since the prev pointers will give you the reverse path.
// in the future routes will probably be cached.
if (r != from) {
new = (path_t *)malloc(sizeof(path_t));
new->node = r->id;
new->next = ret;
new->length = (ret == NULL) ? 1 : ret->length + 1;
ret = new;
}
}
return ret;
}
void nw_free_path(path_t *r) {
path_t *next;
while (r != NULL) {
next = r->next;
free(r);
r = next;
}
}
// remove link from the linked list of links owned by router.
void remove_link(router_t *r, link_t *link) {
link_t *l;
link_t **prev = &r->links;
for (l = r->links; l != NULL; l = (r== l->n1) ? l->next1 : l->next2) {
if (l == link) {
*prev = (r == l->n1) ? l->next1 : l->next2;
return;
}
prev = (r == l->n1) ? &l->next1 : &l->next2;
}
warn("link_remove: link not removed (inconsistent state)?\n");
}
void nw_inval_node(node_id_t v) {
router_t *cur;
link_t *l, *next;
router_t *otherguy;
link_key_t key;
routes_out_of_date = 1;
cur = hashtable_search(routers, &v);
if (cur == NULL) return;
// remove the links from the linked lists of the other guys,
// and delete them from the hashtable
for (l = cur->links; l != NULL; l = (cur == l->n1) ? l->next1 : l->next2) {
otherguy = (cur == l->n1) ? l->n2 : l->n1;
key.r1 = v;
key.r2 = otherguy->id;
remove_link(otherguy, l);
hashtable_remove(links, &key);
}
// free the link structures
l = cur->links;
while (l != NULL) {
next = (cur == l->n1) ? l->next1 : l->next2;
free(l);
l = next;
}
cur->links = NULL;
// force a route recomputation when this node is used.
cur->sp.dist = FLT_MAX;
cur->sp.prev = NULL;
}
/*
* called before adding the topology from a node
* unsets the marked bit * in the link structures to show that they
* have not been reported
*/
void nw_unmark_links(node_id_t v) {
router_t *cur;
link_t *l;
routes_out_of_date = 1;
cur = hashtable_search(routers, &v);
if (cur == NULL) return;
for (l = cur->links; l != NULL; l = (cur == l->n1) ? l->next1 : l->next2) {
l->marked = 0;
}
}
void nw_report_node(node_id_t v) {
router_t *cur;
cur = hashtable_search(routers, &v);
if (cur == NULL) return;
cur->reports++;
}
/*
* called after processing a topology report
*
* removes links which were not contained by this topology report, and
* which were not reported by the router on the other end.
*
*/
void nw_clear_unmarked(node_id_t v) {
router_t *cur;
link_key_t key;
link_t *l, *next;
key.r1 = v;
cur = hashtable_search(routers, &v);
if (cur == NULL) return;
for (l = cur->links; l != NULL; l = (cur == l->n1) ? l->next1 : l->next2) {
if (l->marked == 0) {
// it's not marked, so it wasn't contained in the topology report
if (((cur == l->n1) ? l->n2_reportcount : l->n1_reportcount) == 0) {
// it has never been reported by the router on the other end, so we
// remove the link from the topology data
router_t *otherguy = (cur == l->n1) ? l->n2 : l->n1;
key.r2 = otherguy->id;
remove_link(otherguy, l);
hashtable_remove(links, &key);
//info("removing unmarked link, 0x%x -> 0x%x\n", cur->id, otherguy->id);
// remove it from our own linked list
} else {
// it has been reported by the other size, so we just set its
// observation count to zero.
if (cur == l->n1) l->n1_reportcount = 0 ;
else l->n2_reportcount = 0;
l->marked = 1;
// router_t *otherguy = (cur == l->n1) ? l->n2 : l->n1;
//debug("unseting obs count on 0x%x -> 0x%x\n", cur->id, otherguy->id);
}
}
}
// free the links no longer in use
l = cur->links;
while (l != NULL) {
next = (cur == l->n1) ? l->next1 : l->next2;
// if its still umarked, we mean to remove it from the graph
if (l->marked == 0) {
remove_link(cur, l);
free(l);
}
l = next;
}
age_routers();
}
--- NEW FILE: nwstate.h ---
/*
* "Copyright (c) 2008 The Regents of the University of California.
* All rights reserved."
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement is
* hereby granted, provided that the above copyright notice, the following
* two paragraphs and the author appear in all copies of this software.
*
* IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
* CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
*
*/
#ifndef NWSTATE_H
#define NWSTATE_H
#include <6lowpan.h>
/*
* Defines a programatic representation of the link state of the network.
* Also tracks observable statistics about the links present.
*
*/
typedef uint16_t node_id_t;
struct route_path {
uint16_t len;
hw_addr_t path[0];
};
typedef struct {
node_id_t r1;
node_id_t r2;
} link_key_t;
struct router;
struct link;
typedef struct link {
struct router *n1;
struct router *n2;
struct link *next1;
struct link *next2;
int n1_reportcount;
int n2_reportcount;
int marked;
float qual;
int conf;
int pc;
} link_t;
typedef node_id_t router_key_t;
typedef enum bool {
FALSE,
TRUE,
} bool_t;
typedef struct router {
node_id_t id;
link_t *links;
struct router *next;
int reports;
// fields for shortest path
// computation
struct {
// the current estimate of the
// distance to the source
float dist;
// the current prev pointer
struct router *prev;
// used for maintaining a list of
// vertices we have not yet visited
struct router *setptr;
} sp;
} router_t;
typedef struct path {
node_id_t node;
int length;
struct path *next;
} path_t;
int nw_init();
int nw_add_incr_edge(node_id_t v1, struct topology_entry *v2);
void nw_report_node(node_id_t v);
path_t *nw_get_route(node_id_t v1, node_id_t v2);
void nw_free_path(path_t *path);
void nw_inval_node(node_id_t v);
void nw_unmark_links(node_id_t v);
void nw_clear_unmarked(node_id_t v);
int nw_print_dotfile(char *filename);
void nw_print_routes();
void nw_print_links();
void nw_test_routes();
#endif
--- NEW FILE: radvd-wrapper.c ---
/*
* radvd-wrapper.c
* author: Stephen Dawson-Haggerty <stevedh at eecs.berkeley.edu>
*
* Alternate set of call points for the IPv6 router advertisement
* daemon. Using this interface the daemon may be integrated into
* another program (like ip-driver). radvd is distributed under a
* BSD-like license.
*
* radvd_init() must be called to set up state for the specified
* interface. If successful, it will return a file descriptor;
* radvd_process() must be called whenever there is pending data on
* this descriptor (ie, from a select() loop.)
*
* radvd has its own logging infrastructure; by default radvd_init()
* sends that log to stderr and makes no attempt to integrate it with
* whatever logging facilities may be availabile. See radvd/log.c for
* more.
*
* NB: radvd uses SIGALRM for its internal timer. Thus, once
* radvd_init() has been called, SIGALRM must not be used elsewhere in
* the application.
*
*/
#include <includes.h>
#include <radvd.h>
#include <pathnames.h>
#include "logging.h"
#include "config.h"
struct Interface *iface;
int sock;
void radvd_timer_handler(void *data) {
struct Interface *iface = (struct Interface *) data;
double next;
dlog(LOG_DEBUG, 4, "timer_handler called for %s", iface->Name);
send_ra(sock, iface, NULL);
next = rand_between(iface->MinRtrAdvInterval, iface->MaxRtrAdvInterval);
if (iface->init_racount < MAX_INITIAL_RTR_ADVERTISEMENTS) {
iface->init_racount++;
next = min(MAX_INITIAL_RTR_ADVERT_INTERVAL, next);
}
set_timer(&iface->tm, next);
}
void radvd_kickoff_adverts(void) {
init_timer(&iface->tm, radvd_timer_handler, (void *) iface);
if (iface->AdvSendAdvert) {
/* send an initial advertisement */
send_ra(sock, iface, NULL);
iface->init_racount++;
set_timer(&iface->tm,
min(MAX_INITIAL_RTR_ADVERT_INTERVAL,
iface->MaxRtrAdvInterval));
}
}
void radvd_process() {
unsigned char msg[MSG_SIZE];
int len, hoplimit;
struct sockaddr_in6 rcv_addr;
struct in6_pktinfo *pkt_info = NULL;
len = recv_rs_ra(sock, msg, &rcv_addr, &pkt_info, &hoplimit);
if (len > 0)
process(sock, iface, msg, len,
&rcv_addr, pkt_info, hoplimit);
}
/* Set up all the radvd internal stuff from our own configuration */
int radvd_init(char *ifname, struct config *c) {
struct AdvPrefix *prefix;
sigset_t oset, nset;
if (log_open(L_STDERR, "radvd", NULL, -1) < 0) {
error("log_open\n");
return -1;
}
srand((unsigned int)time(NULL));
info("starting radvd on device %s\n", ifname);
sock = open_icmpv6_socket();
if (sock < 0) {
error("open_icmpv6_socket\n");
return -1;
}
sigemptyset(&nset);
sigaddset(&nset, SIGALRM);
sigprocmask(SIG_UNBLOCK, &nset, &oset);
if (sigismember(&oset, SIGALRM))
flog(LOG_WARNING, "SIGALRM has been unblocked. Your startup environment might be wrong.");
/* setup the radvd struct Interface to know about all our defaults */
iface = malloc(sizeof(struct Interface));
if (iface == NULL)
return -1;
iface_init_defaults(iface);
strncpy(iface->Name, ifname, IFNAMSIZ-1);
iface->Name[IFNAMSIZ-1] = '\0';
iface->next = NULL;
iface->AdvSendAdvert = 1;
/* check the interface exists... this probably shouldn't fail */
if (check_device(sock, iface) < 0) {
error("check_device!\n");
return -1;
}
if (setup_deviceinfo(sock, iface) < 0) {
error("setup_deviceinfo\n");
return -1;
}
if (check_iface(iface) < 0) {
error("check_iface\n");
return -1;
}
if (setup_linklocal_addr(sock, iface) < 0) {
error("setup_linklocal_addr\n");
return -1;
}
if (setup_allrouters_membership(sock, iface) < 0) {
error("setup_allrouters_membership\n");
return -1;
}
/* set up the prefix we're advertising from the config struct we get passed in. */
prefix = malloc(sizeof(struct AdvPrefix));
if (prefix == NULL)
return -1;
prefix_init_defaults(prefix);
prefix->PrefixLen = 64;
memcpy(&prefix->Prefix, c->router_addr.s6_addr, sizeof(struct in6_addr));
prefix->next = NULL;
iface->AdvPrefixList = prefix;
// config_interface();
radvd_kickoff_adverts();
return sock;
}
--- NEW FILE: routing.c ---
/*
* "Copyright (c) 2008 The Regents of the University of California.
* All rights reserved."
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement is
* hereby granted, provided that the above copyright notice, the following
* two paragraphs and the author appear in all copies of this software.
*
* IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
* CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
*
*/
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <net/if.h>
#include <6lowpan.h>
#include <lib6lowpan.h>
#include "routing.h"
#include "nwstate.h"
#include "logging.h"
#include "config.h"
static hw_addr_t my_short_addr;
extern struct in6_addr __my_address;
char proxy_dev[IFNAMSIZ], tun_dev[IFNAMSIZ];
/*
* Call to setup routing tables.
*
*/
uint8_t routing_init(struct config *c, char *tun_name) {
nw_init();
my_short_addr = ntohs(__my_address.s6_addr16[7]);
strncpy(proxy_dev, c->proxy_dev, IFNAMSIZ);
strncpy(tun_dev, tun_name, IFNAMSIZ);
/* nl_fd = socket(AF_NETLINK, SOCK_RAW, protocol); */
/* if (nl_fd < 0) */
/* return -1; */
return 0;
}
/*
* @returns: truth value indicating if the destination of the packet
* is a single hop, and requires no source route.
*/
uint8_t routing_is_onehop(struct split_ip_msg *msg) {
path_t *path;
uint8_t ret = ROUTE_NO_ROUTE;
if (cmpPfx(msg->hdr.ip6_dst.s6_addr, multicast_prefix))
return ROUTE_ONEHOP;
if (msg->hdr.nxt_hdr == NXTHDR_SOURCE) {
debug("routing_is_onehop: Source header\n");
return ROUTE_SOURCE;
}
path = nw_get_route(my_short_addr, ntohs(msg->hdr.ip6_dst.s6_addr16[7]));
if (path != NULL) {
if (path->length == 1)
ret = ROUTE_ONEHOP;
else
ret = ROUTE_MHOP;
}
debug("routing_is_onehop: 0x%x\n", ret);
nw_free_path(path);
return ret;
}
/*
* Identical to routing_insert_route, except allows for a detour route
*/
/*uint8_t routing_insert_route_indirect(struct split_ip_msg *orig, ip6_addr_t detour) {
int offset = 0;
path_t *path = nw_get_route(my_short_addr, l2fromIP(detour));
path_t *path_second = nw_get_route(l2fromIP(detour), l2fromIP(orig->hdr.dst_addr));
path_t *i;
struct generic_header *g_hdr = (struct generic_header *)malloc(sizeof(struct generic_header));
struct source_header *sh;
debug("routing_insert_route_indirect len1: 0x%x, len2: 0x%x\n", path->length, path_second->length);
if (ntoh16(orig->hdr.plen) + sizeof(struct source_header) + ((path->length + path_second->length) * sizeof(uint16_t)) + sizeof(struct ip6_hdr) > INET_MTU) {
warn("packet plus source header too long\n");
return 1;
}
sh = (struct source_header *)malloc(sizeof(struct source_header) + (path->length + path_second->length)*sizeof(uint16_t));
if (sh == NULL || g_hdr == NULL) return 1;
sh->nxt_hdr = orig->hdr.nxt_hdr;
sh->len = sizeof(struct source_header) + ((path->length + path_second->length) * sizeof(uint16_t));
sh->dispatch = IP_EXT_SOURCE_DISPATCH;
sh->current = 0;
orig->hdr.nxt_hdr = NXTHDR_SOURCE;
fprintf(stderr, "to 0x%x [%i]: ", noths(orig->hdr.ip6_dst.s6_addr16[7]), path->length + path_second->length);
for (i = path; i != NULL; i = i->next) {
fprintf(stderr, "0x%x ", i->node);
sh->hops[offset++] = hton16(i->node);
}
for (i = path_second; i != NULL; i = i->next) {
fprintf(stderr, "0x%x ", i->node);
sh->hops[offset++] = hton16(i->node);
}
fprintf(stderr, "\n");
orig->hdr.plen = hton16(ntoh16(orig->hdr.plen) + sh->len);
g_hdr->payload_malloced = 1;
g_hdr->len = sh->len;
g_hdr->hdr.sh = sh;
g_hdr->next = orig->headers;
orig->headers = g_hdr;
nw_free_path(path);
nw_free_path(path_second);
return 0;
}
*/
/*
* Copys the IP message at orig to the empty one at ret, inserting
* necessary routing information.
*/
uint8_t routing_insert_route(struct split_ip_msg *orig) {
int offset = 0;
path_t *path = nw_get_route(my_short_addr, ntohs(orig->hdr.ip6_dst.s6_addr16[7]));
path_t *i;
struct generic_header *g_hdr = (struct generic_header *)malloc(sizeof(struct generic_header));
struct source_header *sh;
if (g_hdr == NULL || path == NULL) {
if (g_hdr) free(g_hdr);
if (path) nw_free_path(path);
return 1;
}
if (path->length == 1) {
free(g_hdr);
nw_free_path(path);
return 1;
}
debug("routing_insert_route len: 0x%x\n", path->length);
// if the packet with the source route is longer then the buffer
// we're putting it into, drop it.
if (ntoh16(orig->hdr.plen) + sizeof(struct source_header) +
(path->length * sizeof(uint16_t)) + sizeof(struct ip6_hdr) > INET_MTU) {
warn("packet plus source header too long\n");
free(g_hdr);
nw_free_path(path);
return 1;
}
sh = (struct source_header *)malloc(sizeof(struct source_header) + path->length * sizeof(uint16_t));
if (sh == NULL) {
free (g_hdr);
nw_free_path(path);
return 1;
}
sh->nxt_hdr = orig->hdr.nxt_hdr;
sh->len = sizeof(struct source_header) + (path->length * sizeof(uint16_t));
sh->dispatch = IP_EXT_SOURCE_DISPATCH | IP_EXT_SOURCE_CONTROLLER;
sh->current = 0;
orig->hdr.nxt_hdr = NXTHDR_SOURCE;
log_clear(LOGLVL_DEBUG, "to 0x%x [%i]: ", ntohs(orig->hdr.ip6_dst.s6_addr16[7]), path->length);
for (i = path; i != NULL; i = i->next) {
log_clear(LOGLVL_DEBUG, "0x%x ", i->node);
sh->hops[offset++] = hton16(i->node);
}
log_clear(LOGLVL_DEBUG, "\n");
orig->hdr.plen = hton16(ntoh16(orig->hdr.plen) + sh->len);
g_hdr->payload_malloced = 1;
g_hdr->len = sh->len;
g_hdr->hdr.sh = sh;
g_hdr->next = orig->headers;
orig->headers = g_hdr;
nw_free_path(path);
return 0;
}
/*
* Returns the address of the next router this packet should be send to.
*/
hw_addr_t routing_get_nexthop(struct split_ip_msg *msg) {
hw_addr_t ret = 0xffff;;
path_t * path;
if (cmpPfx(msg->hdr.ip6_dst.s6_addr, multicast_prefix))
return ret;
// If it's source routed, just grab the next hop out of the header
if (msg->hdr.nxt_hdr == NXTHDR_SOURCE) {
debug("routing_get_nexthop: src header\n");
return ntoh16((msg->headers->hdr.sh->hops[msg->headers->hdr.sh->current]));
}
path = nw_get_route(my_short_addr, ntohs(msg->hdr.ip6_dst.s6_addr16[7]));
if (path != NULL)
ret = path->node;
nw_free_path(path);
return ret;
}
void routing_proc_msg(struct split_ip_msg *msg) {
struct generic_header *g_hdr, **prev_hdr;
uint8_t *prev_next, nxt_hdr = msg->hdr.nxt_hdr;
int i;
node_id_t reporter = ntohs(msg->hdr.ip6_src.s6_addr16[7]);
prev_next = &msg->hdr.nxt_hdr;
prev_hdr = &msg->headers;
nw_report_node(reporter);
for (g_hdr = msg->headers; g_hdr != NULL; g_hdr = g_hdr->next) {
if (nxt_hdr == NXTHDR_TOPO) {
// add the topology reports to the database
nw_unmark_links(reporter);
for (i = 0; i < (g_hdr->len - sizeof(struct topology_header))/sizeof(struct topology_entry); i++) {
//debug("topo neigh: 0x%x hop: %i qual: 0x%x\n", g_hdr->hdr.th->topo[i].hwaddr,
// g_hdr->hdr.th->topo[i].hops, g_hdr->hdr.th->topo[i].link);
nw_add_incr_edge(reporter, &g_hdr->hdr.th->topo[i]);
}
nw_clear_unmarked(reporter);
// remove the topology header
*prev_next = g_hdr->hdr.ext->nxt_hdr;
*prev_hdr = g_hdr->next;
if (g_hdr->payload_malloced) free(g_hdr->hdr.data);
msg->hdr.plen = hton16(ntoh16(msg->hdr.plen) - g_hdr->len);
free(g_hdr);
return;
} else {
nxt_hdr = g_hdr->hdr.ext->nxt_hdr;
prev_next = &g_hdr->hdr.ext->nxt_hdr;
prev_hdr = &g_hdr->next;
}
}
}
void routing_add_table_entry(node_id_t id) {
/* static const char* route_add_fmt = "ip -6 route add %x%02x:%x%02x:%x%02x:%x%02x:%x%02x:%x%02x:%x%02x:%x%02x/128 dev %s"; */
/* static const char* route_proxy_fmt = "ip -6 neigh add proxy %x%02x:%x%02x:%x%02x:%x%02x:%x%02x:%x%02x:%x%02x:%x%02x dev %s"; */
}
--- NEW FILE: routing.h ---
/*
* "Copyright (c) 2008 The Regents of the University of California.
* All rights reserved."
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement is
* hereby granted, provided that the above copyright notice, the following
* two paragraphs and the author appear in all copies of this software.
*
* IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
* CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
*
*/
#ifndef __ROUTING_H_
#define __ROUTING_H_
#include <ip.h>
#include <string.h>
#include "nwstate.h"
#include "config.h"
enum {
ROUTE_NO_ROUTE,
ROUTE_ONEHOP,
ROUTE_MHOP,
ROUTE_SOURCE,
};
uint8_t routing_init(struct config *c, char *tun_dev);
/*
* @returns: truth value indicating if the destination of the packet
* is a single hop, and requires no source route.
*/
uint8_t routing_is_onehop(struct split_ip_msg *msg);
/*
* Copys the IP message at orig to the empty one at ret, inserting
* necessary routing information.
*/
uint8_t routing_insert_route(struct split_ip_msg *orig);
/*
* Returns the address of the next router this packet should be send to.
*/
hw_addr_t routing_get_nexthop(struct split_ip_msg *msg);
/*
* Called for all reconstructed packets off serial.
* allows the router to inpect and remove any extra headers in the message.
*/
void routing_proc_msg(struct split_ip_msg *msg);
/*
* Update kernel routing state to reflect a new node
*/
void routing_add_table_entry(node_id_t id);
#endif
--- NEW FILE: serial_tun.c ---
/*
* "Copyright (c) 2008 The Regents of the University of California.
* All rights reserved."
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement is
* hereby granted, provided that the above copyright notice, the following
* two paragraphs and the author appear in all copies of this software.
*
* IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
* CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
[...1069 lines suppressed...]
exit(1);
}
#endif
info("Press 'h' for help\n");
routing_init(&driver_config, dev);
#ifndef SIM
configure_reboot();
#endif
/* start tunneling */
serial_tunnel(tun_fd);
/* clean up */
// close_serial_source(ser_src);
// close(ser_fd);
tun_close(tun_fd, dev);
return 0;
}
--- NEW FILE: tun_dev.c ---
/*
* "Copyright (c) 2008 The Regents of the University of California.
* All rights reserved."
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement is
* hereby granted, provided that the above copyright notice, the following
* two paragraphs and the author appear in all copies of this software.
*
* IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
* CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
*
*/
/*
* Copyright (c) 2007 Matus Harvan
* All rights reserved
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * 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.
* * The name of the author may not be used to endorse or promote
* products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT
* OWNER 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.
*/
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <syslog.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <linux/if.h>
#include <linux/if_ether.h>
#include <netinet/in.h>
#include "lib6lowpan.h"
#include "tun_dev.h"
/*
* This is in linux/include/net/ipv6.h.
* Thanks, net-tools!
*/
struct in6_ifreq {
struct in6_addr ifr6_addr;
__u32 ifr6_prefixlen;
unsigned int ifr6_ifindex;
};
int tun_open(char *dev)
{
struct ifreq ifr;
int fd;
if ((fd = open("/dev/net/tun", O_RDWR | O_NONBLOCK)) < 0)
return -1;
memset(&ifr, 0, sizeof(ifr));
/* By default packets are tagged as IPv4. To tag them as IPv6,
* they need to be prefixed by struct tun_pi.
*/
//ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
ifr.ifr_flags = IFF_TUN;
if (*dev)
strncpy(ifr.ifr_name, dev, IFNAMSIZ);
if (ioctl(fd, TUNSETIFF, (void *) &ifr) < 0)
goto failed;
strcpy(dev, ifr.ifr_name);
return fd;
failed:
perror("tun_open");
close(fd);
return -1;
}
int tun_setup(char *dev, struct in6_addr *addr) {
struct in6_ifreq ifr6;
struct ifreq ifr;
int fd;
if ((fd = socket(PF_INET6, SOCK_DGRAM, 0)) < 0)
return -1;
memset(&ifr, 0, sizeof(struct ifreq));
strncpy(ifr.ifr_name, dev, IFNAMSIZ);
/* set the interface up */
if (ioctl(fd, SIOCGIFFLAGS, &ifr) < 0) {
perror("SIOCGIFFLAGS");
return -1;
}
ifr.ifr_flags |= IFF_UP;
if (ioctl(fd, SIOCSIFFLAGS, &ifr) < 0) {
perror("SIOCSIFFLAGS");
return -1;
}
/* MTU */
ifr.ifr_mtu = 1280;
if (ioctl(fd, SIOCSIFMTU, &ifr) < 0) {
perror("SIOCSIFMTU");
return -1;
}
/* Global address */
memset(&ifr6, 0, sizeof(struct in6_ifreq));
memcpy(&ifr6.ifr6_addr, addr, 16);
if (ioctl(fd, SIOGIFINDEX, &ifr) < 0) {
perror("SIOGIFINDEX");
return -1;
}
ifr6.ifr6_ifindex = ifr.ifr_ifindex;
ifr6.ifr6_prefixlen = 64;
if (ioctl(fd, SIOCSIFADDR, &ifr6) < 0) {
perror("SIOCSIFADDR (global)");
return -1;
}
memset(&ifr6.ifr6_addr.s6_addr[0], 0, 16);
ifr6.ifr6_addr.s6_addr16[0] = htons(0xfe80);
ifr6.ifr6_addr.s6_addr16[7] = addr->s6_addr16[7];
if (ioctl(fd, SIOCSIFADDR, &ifr6) < 0) {
perror("SIOCSIFADDR (local)");
return -1;
}
close(fd);
return 0;
}
int tun_close(int fd, char *dev)
{
return close(fd);
}
/* Read/write frames from TUN device */
int tun_write(int fd, struct split_ip_msg *msg)
{
uint8_t buf[INET_MTU + sizeof(struct tun_pi)], *packet;
struct tun_pi *pi = (struct tun_pi *)buf;
struct generic_header *cur;
packet = (uint8_t *)(pi + 1);
if (ntohs(msg->hdr.plen) + sizeof(struct ip6_hdr) >= INET_MTU)
return 1;
pi->flags = 0;
pi->proto = htons(ETH_P_IPV6);
memcpy(packet, &msg->hdr, sizeof(struct ip6_hdr));
packet += sizeof(struct ip6_hdr);
cur = msg->headers;
while (cur != NULL) {
memcpy(packet, cur->hdr.data, cur->len);
packet += cur->len;
cur = cur->next;
}
memcpy(packet, msg->data, msg->data_len);
return write(fd, buf, sizeof(struct tun_pi) + sizeof(struct ip6_hdr) + ntohs(msg->hdr.plen));
}
int tun_read(int fd, char *buf, int len)
{
int out;
out = read(fd, buf, sizeof(struct tun_pi) + len);
return out - sizeof(struct tun_pi);
}
--- NEW FILE: tun_dev.h ---
/*
* "Copyright (c) 2008 The Regents of the University of California.
* All rights reserved."
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement is
* hereby granted, provided that the above copyright notice, the following
* two paragraphs and the author appear in all copies of this software.
*
* IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
* CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
*
*/
/*
* Copyright (c) 2007 Matus Harvan
* All rights reserved
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * 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.
* * The name of the author may not be used to endorse or promote
* products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT
* OWNER 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.
*/
#ifndef _TUN_DEV_H
#define _TUN_DEV_H
#include <ip.h>
int tun_open(char *dev);
int tun_close(int fd, char *dev);
int tun_setup(char *dev, struct in6_addr *addr);
int tun_write(int fd, struct split_ip_msg *msg);
int tun_read(int fd, char *buf, int len);
#endif
--- NEW FILE: tunnel.c ---
/*
* "Copyright (c) 2008 The Regents of the University of California.
* All rights reserved."
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement is
* hereby granted, provided that the above copyright notice, the following
* two paragraphs and the author appear in all copies of this software.
*
* IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
* CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
*
*/
/*
* Implementation of user-mode driver and IP gateway using a node
* running IPBaseStation as 802.15.4 hardware. Uses kernel tun
* interface to route addresses.
*
*/
#include <stdio.h>
#include <stdint.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
uint16_t shortAddr;
int tun_fd;
char *tun_dev = "/dev/net/tun";
void usage(char **args) {
fprintf(stderr, "\n\t%s <my-short-addr>\n\n", args[0]);
}
int create_tunnel() {
struct ifreq ifr;
if ((tun_fd = open(tun_dev, O_RDWR)) < 0) {
fprintf(stderr, "Failed to open '%s' : ", tun_dev);
perror("");
return 1;
}
ifr.irf_flags = IFF_TAP | IFF_NO_PI;
str
return 0;
}
int main(int argc, char **argv) {
if (argc != 2) {
usage(argv);
return 1;
}
shortAddr = atoi(argv[1]);
if (create_tunnel())
return 1;
sleep(20);
return 0;
}
- Previous message: [Tinyos-2-commits] CVS: tinyos-2.x/support/sdk/c/blip Makefile, NONE, 1.1 serial_tun.conf, NONE, 1.1
- Next message: [Tinyos-2-commits] CVS: tinyos-2.x/support/sdk/c/blip/driver/radvd-1.0 CHANGES, NONE, 1.1 COPYRIGHT, NONE, 1.1 INTRO.html, NONE, 1.1 Makefile, NONE, 1.1 Makefile.am, NONE, 1.1 Makefile.in, NONE, 1.1 README, NONE, 1.1 TODO, NONE, 1.1 VERSION, NONE, 1.1 aclocal.m4, NONE, 1.1 config.cache, NONE, 1.1 config.guess, NONE, 1.1 config.h, NONE, 1.1 config.h.in, NONE, 1.1 config.log, NONE, 1.1 config.status, NONE, 1.1 config.sub, NONE, 1.1 configure, NONE, 1.1 configure.in, NONE, 1.1 copyright.blurb, NONE, 1.1 defaults.h, NONE, 1.1 depcomp, NONE, 1.1 device-bsd44.c, NONE, 1.1 device-common.c, NONE, 1.1 device-linux.c, NONE, 1.1 gram.c, NONE, 1.1 gram.h, NONE, 1.1 gram.y, NONE, 1.1 includes.h, NONE, 1.1 install-sh, NONE, 1.1 interface.c, NONE, 1.1 log.c, NONE, 1.1 missing, NONE, 1.1 mkinstalldirs, NONE, 1.1 pathnames.h, NONE, 1.1 process.c, NONE, 1.1 radvd.8.man, NONE, 1.1 radvd.c, NONE, 1.1 radvd.conf.5.man, NONE, 1.1 radvd.conf.example, NONE, 1.1 radvd.h, NONE, 1.1 radvdump.8.man, NONE, 1.1 radvdump.c, NONE, 1.1 recv.c, NONE, 1.1 scanner.c, NONE, 1.1 scanner.l, NONE, 1.1 send.c, NONE, 1.1 socket.c, NONE, 1.1 stamp-h, NONE, 1.1 stamp-h.in, NONE, 1.1 timer.c, NONE, 1.1 util.c, NONE, 1.1
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
More information about the Tinyos-2-commits
mailing list