From 00acab920bacbf49dfbe5a68e939926053e54f60 Mon Sep 17 00:00:00 2001 From: Martin Lenders Date: Thu, 13 Feb 2014 13:57:59 +0100 Subject: [PATCH] Let IPv6 and ICMP use new 6LoWPAN layer (+fixes) --- Makefile.dep | 10 +- sys/net/include/sixlowpan/icmp.h | 4 +- sys/net/include/sixlowpan/ip.h | 211 ++++-- sys/net/include/sixlowpan/ndp.h | 126 +++- sys/net/include/sixlowpan/types.h | 21 +- .../network_layer/sixlowpan/border/border.h | 2 +- .../sixlowpan/border/bordermultiplex.c | 8 +- sys/net/network_layer/sixlowpan/icmp.c | 606 +++++++++++++----- sys/net/network_layer/sixlowpan/icmp.h | 5 +- sys/net/network_layer/sixlowpan/ip.c | 544 ++++++++-------- sys/net/network_layer/sixlowpan/ip.h | 45 +- sys/net/network_layer/sixlowpan/lowpan.h | 6 +- sys/net/routing/rpl/rpl.c | 16 +- sys/net/routing/rpl/rpl.h | 2 +- sys/net/routing/rpl/rpl_dodag.c | 4 +- sys/net/transport_layer/destiny/socket.c | 32 +- sys/shell/commands/sc_net_if.c | 67 +- 17 files changed, 1140 insertions(+), 569 deletions(-) diff --git a/Makefile.dep b/Makefile.dep index eff649d8a4..f7b80ef62b 100644 --- a/Makefile.dep +++ b/Makefile.dep @@ -92,13 +92,13 @@ ifneq (,$(filter sixlowpan,$(USEMODULE))) ifeq (,$(filter net_help,$(USEMODULE))) USEMODULE += net_help endif - ifeq (,$(filter semaphore,$(USEMODULE))) + ifeq (,$(filter net_if,$(USEMODULE))) + USEMODULE += net_if + endif + ifeq (,$(filter semaphore, $(USEMODULE))) USEMODULE += semaphore endif - ifeq (,$(filter transceiver,$(USEMODULE))) - USEMODULE += transceiver - endif - ifeq (,$(filter vtimer,$(USEMODULE))) + ifeq (,$(filter vtimer, $(USEMODULE))) USEMODULE += vtimer endif endif diff --git a/sys/net/include/sixlowpan/icmp.h b/sys/net/include/sixlowpan/icmp.h index 6aa417c66c..97b08791aa 100644 --- a/sys/net/include/sixlowpan/icmp.h +++ b/sys/net/include/sixlowpan/icmp.h @@ -150,7 +150,7 @@ void icmpv6_send_parameter_prob(ipv6_addr_t *src, ipv6_addr_t *dest, * @param[in] data_len Length of data payload. */ void icmpv6_send_echo_request(ipv6_addr_t *destaddr, uint16_t id, - uint16_t seq, char *data, + uint16_t seq, uint8_t *data, size_t data_len); /** @@ -163,7 +163,7 @@ void icmpv6_send_echo_request(ipv6_addr_t *destaddr, uint16_t id, * @param[in] data_len Length of data payload. */ void icmpv6_send_echo_reply(ipv6_addr_t *destaddr, uint16_t id, - uint16_t seq, char *data, size_t data_len); + uint16_t seq, uint8_t *data, size_t data_len); /** * @brief Send ICMPv6 router solicitation. diff --git a/sys/net/include/sixlowpan/ip.h b/sys/net/include/sixlowpan/ip.h index d365a65c33..aaf41c44ac 100644 --- a/sys/net/include/sixlowpan/ip.h +++ b/sys/net/include/sixlowpan/ip.h @@ -24,6 +24,9 @@ #include +#include "inet_ntop.h" +#include "net_help.h" +#include "net_if.h" #include "sixlowpan/types.h" /** @@ -32,7 +35,17 @@ #define IPV6_MTU (256) /** - * @brief Maximum length of a IPv6 address represented as string. + * @brief Length of an IPv6 address in byte. + */ +#define IPV6_ADDR_LEN (16) + +/** + * @brief Length of an IPv6 address in bit. + */ +#define IPV6_ADDR_BIT_LEN (128) + +/** + * @brief Maximum length of an IPv6 address represented as string. */ #define IPV6_MAX_ADDR_STR_LEN (40) @@ -160,7 +173,11 @@ void ipv6_register_rpl_handler(int pid); * * @param[in,out] ipv6_addr The address to set. */ -void ipv6_addr_set_link_local_prefix(ipv6_addr_t *ipv6_addr); +static inline void ipv6_addr_set_link_local_prefix(ipv6_addr_t *ipv6_addr) +{ + ipv6_addr->uint32[0] = HTONL(0xfe800000); + ipv6_addr->uint32[1] = 0; +} /** * @brief Sets IPv6 address *out* according to the remaining @@ -181,16 +198,20 @@ void ipv6_addr_init(ipv6_addr_t *out, uint16_t addr0, uint16_t addr1, uint16_t addr5, uint16_t addr6, uint16_t addr7); /** - * @brief Sets IPv6 address *out* using the given *prefix* and this - * nodes EUI-64 (i. e. interface must be initialized). + * @brief Sets IPv6 address *out* using the given *prefix* and an interface's + * EUI-64. + * * * @param[out] out Address to be set. + * @param[in] if_id The interface to take the EUI-64 from. * @param[in] prefix 64-bit network prefix to be used for *out* * (only the first 64 bit of the ipv6_addr_t type * are copied to *out*) + * + * @return The Address to be set on success, NULL on error. */ -void ipv6_addr_set_by_eui64(ipv6_addr_t *out, - const ipv6_addr_t *prefix); +ipv6_addr_t *ipv6_addr_set_by_eui64(ipv6_addr_t *out, int if_id, + const ipv6_addr_t *prefix); /** * @brief Sets IPv6 address *out* with the first *bits* bit taken @@ -213,7 +234,13 @@ void ipv6_addr_init_prefix(ipv6_addr_t *out, const ipv6_addr_t *prefix, * * @param[out] ipv6_addr Is set to the loopback address. */ -void ipv6_addr_set_loopback_addr(ipv6_addr_t *ipv6_addr); +static inline void ipv6_addr_set_loopback_addr(ipv6_addr_t *ipv6_addr) +{ + ipv6_addr->uint32[0] = 0; + ipv6_addr->uint32[1] = 0; + ipv6_addr->uint32[2] = 0; + ipv6_addr->uint32[3] = HTONL(1); +} /** * @brief Set *ipv6_addr* to a link-local all routers multicast @@ -226,7 +253,13 @@ void ipv6_addr_set_loopback_addr(ipv6_addr_t *ipv6_addr); * @param[out] ipv6_addr Is set to a link-local all routers multicast * address. */ -void ipv6_addr_set_all_routers_addr(ipv6_addr_t *ipv6_addr); +static inline void ipv6_addr_set_all_routers_addr(ipv6_addr_t *ipv6_addr) +{ + ipv6_addr->uint32[0] = HTONL(0xff020000); + ipv6_addr->uint32[1] = 0; + ipv6_addr->uint32[2] = 0; + ipv6_addr->uint32[3] = HTONL(2); +} /** * @brief Set *ipv6_addr* to a link-local all nodes multicast address @@ -239,7 +272,13 @@ void ipv6_addr_set_all_routers_addr(ipv6_addr_t *ipv6_addr); * @param[out] ipv6_addr Is set to a link-local all nodes multicast * address. */ -void ipv6_addr_set_all_nodes_addr(ipv6_addr_t *ipv6_addr); +static inline void ipv6_addr_set_all_nodes_addr(ipv6_addr_t *ipv6_addr) +{ + ipv6_addr->uint32[0] = HTONL(0xff020000); + ipv6_addr->uint32[1] = 0; + ipv6_addr->uint32[2] = 0; + ipv6_addr->uint32[3] = HTONL(1); +} /** * @brief Set *ipv6_addr_out* to the solicited-node multicast address @@ -254,22 +293,34 @@ void ipv6_addr_set_all_nodes_addr(ipv6_addr_t *ipv6_addr); * @param[in] ipv6_addr_in The IPv6 address the solicited-node * address. */ -void ipv6_addr_set_solicited_node_addr(ipv6_addr_t *ipv6_addr_out, - const ipv6_addr_t *ipv6_addr_in); +static inline void ipv6_addr_set_solicited_node_addr(ipv6_addr_t *ipv6_addr_out, + const ipv6_addr_t *ipv6_addr_in) +{ + /* copy only the last 24-bit of the ip-address that is beeing resolved */ + ipv6_addr_out->uint32[0] = HTONL(0xff020000); + ipv6_addr_out->uint32[1] = 0; + ipv6_addr_out->uint32[2] = HTONS(1); + ipv6_addr_out->uint8[12] = 0xff; + ipv6_addr_out->uint8[13] = ipv6_addr_in->uint8[13]; + ipv6_addr_out->uint16[7] = ipv6_addr_in->uint16[7]; +} /** - * @brief Converts IPv6 address into string (unabbrivated notation). - * Note that addr_str must allocate at least - * IPV6_MAX_ADDR_STR_LEN byte (40 byte). + * @brief Converts IPv6 address into string. * * @param[out] addr_str The IPv6 address as string. Must allocate * at least IPV6_MAX_ADDR_STR_LEN byte (40 * byte). + * @param[in] str_len The maximum length available to *addr_str*. * @param[in] ipv6_addr IPv6 address to be converted. * * @return Pointer to addr_str. */ -char *ipv6_addr_to_str(char *addr_str, const ipv6_addr_t *ipv6_addr); +static inline const char *ipv6_addr_to_str(char *addr_str, uint8_t str_len, + const ipv6_addr_t *ipv6_addr) +{ + return inet_ntop(AF_INET6, ipv6_addr, addr_str, (size_t)str_len); +} /** * @brief Checks if two IPv6 addresses are equal. @@ -279,7 +330,13 @@ char *ipv6_addr_to_str(char *addr_str, const ipv6_addr_t *ipv6_addr); * * @return 1 if *a* and *b* are equal, 0 otherwise. */ -int ipv6_addr_is_equal(const ipv6_addr_t *a, const ipv6_addr_t *b); +static inline int ipv6_addr_is_equal(const ipv6_addr_t *a, const ipv6_addr_t *b) +{ + return (a->uint32[0] == b->uint32[0]) && + (a->uint32[1] == b->uint32[1]) && + (a->uint32[2] == b->uint32[2]) && + (a->uint32[3] == b->uint32[3]); +} /** * @brief Checks if *ipv6_addr* is unspecified (all zero). @@ -292,7 +349,48 @@ int ipv6_addr_is_equal(const ipv6_addr_t *a, const ipv6_addr_t *b); * * @return 1 if *ipv6_addr* is unspecified address, 0 otherwise. */ -int ipv6_addr_is_unspecified(const ipv6_addr_t *ipv6_addr); +static inline int ipv6_addr_is_unspecified(const ipv6_addr_t *ipv6_addr) +{ + return (ipv6_addr->uint32[0] == 0) && + (ipv6_addr->uint32[1] == 0) && + (ipv6_addr->uint32[2] == 0) && + (ipv6_addr->uint32[3] == 0); +} + +/** + * @brief Check if *ipv6_addr* is a multicast address. + * + * @see + * RFC 4291 + * + * + * @param[in] ipv6_addr An IPv6 address. + * + * @return 1 if *ipv6_addr* is multicast address, 0 otherwise. + */ +static inline int ipv6_addr_is_multicast(const ipv6_addr_t *ipv6_addr) +{ + return (ipv6_addr->uint8[0] == 0xff); +} + +/** + * @brief Checks if *ipv6_addr* is a loopback address. + * + * @see + * RFC 4291 + * + * + * @param[in] ipv6_addr An IPv6 address. + * + * @return 1 if *ipv6_addr* is loopback address, 0 otherwise. + */ +static inline int ipv6_addr_is_loopback(const ipv6_addr_t *ipv6_addr) +{ + return ipv6_addr->uint32[0] == 0 && + ipv6_addr->uint32[1] == 0 && + ipv6_addr->uint32[2] == 0 && + NTOHL(ipv6_addr->uint32[3]) == 1; +} /** * @brief Check if *ipv6_addr* is a link-local address. @@ -305,7 +403,13 @@ int ipv6_addr_is_unspecified(const ipv6_addr_t *ipv6_addr); * * @return 1 if *ipv6_addr* is link-local address, 0 otherwise. */ -int ipv6_addr_is_link_local(const ipv6_addr_t *ipv6_addr); +static inline int ipv6_addr_is_link_local(const ipv6_addr_t *ipv6_addr) +{ + return ((ipv6_addr->uint32[0] == HTONL(0xfe800000)) && + (ipv6_addr->uint32[1] == 0)) || + (ipv6_addr_is_multicast(ipv6_addr) && + (ipv6_addr->uint8[1] & 0x0f) == 2); +} /** * @brief Check if *ipv6_addr* is unique local unicast address. @@ -319,20 +423,10 @@ int ipv6_addr_is_link_local(const ipv6_addr_t *ipv6_addr); * @return 1 if *ipv6_addr* is unique local unicast address, * 0 otherwise. */ -int ipv6_addr_is_unique_local_unicast(const ipv6_addr_t *addr); - -/** - * @brief Check if *ipv6_addr* is a multicast address. - * - * @see - * RFC 4291 - * - * - * @param[in] ipv6_addr An IPv6 address. - * - * @return 1 if *ipv6_addr* is multicast address, 0 otherwise. - */ -int ipv6_addr_is_multicast(const ipv6_addr_t *ipv6_addr); +static inline int ipv6_addr_is_unique_local_unicast(const ipv6_addr_t *ipv6_addr) +{ + return ((ipv6_addr->uint8[0] == 0xfc) || (ipv6_addr->uint8[0] == 0xfd)); +} /** * @brief Check if *ipv6_addr* is solicited-node multicast address. @@ -346,7 +440,28 @@ int ipv6_addr_is_multicast(const ipv6_addr_t *ipv6_addr); * @return 1 if *ipv6_addr* is solicited-node multicast address, * 0 otherwise. */ -int ipv6_addr_is_solicited_node(const ipv6_addr_t *ipv6_addr); +static inline int ipv6_addr_is_solicited_node(const ipv6_addr_t *ipv6_addr) +{ + return (ipv6_addr->uint32[0] == HTONL(0xff020000)) && + (ipv6_addr->uint32[1] == 0) && + (ipv6_addr->uint32[2] == HTONL(1)) && + (ipv6_addr->uint8[12] == 0xff); +} + +/** + * @brief Get pointer to potential EUI-64 bit of the IPv6 address. + * + * @param[in] ipv6_addr An IPv6 address of this node. + * @param[in] prefix_len Length of the prefix. Only multiples of 8 are + * possible. + * + * @return The IID (as EUI-64) of this node. + */ +static inline net_if_eui64_t *ipv6_addr_get_iid(const ipv6_addr_t *ipv6_addr, + uint8_t prefix_len) +{ + return ((net_if_eui64_t *) &ipv6_addr->uint8[prefix_len / 8]); +} /* * TODO to wrap sixlowpan initialisations @@ -354,26 +469,35 @@ int ipv6_addr_is_solicited_node(const ipv6_addr_t *ipv6_addr); */ /** - * @brief Add an IPv6 address to this nodes interface. + * @brief Add an IPv6 address to one of this nodes interfaces. * * @see * RFC 4862 * * + * @param[in] if_id The interface's ID. * @param[in] addr Address to be added to the interface. * @param[in] type Type of this address. * @param[in] state Initial state of the address. - * @param[in] val_ltime Valid lifetime of this address in seconds. + * @param[in] val_ltime Valid lifetime of this address in seconds. Set 0 + * for unspecified. * @param[in] pref_ltime Preferred lifetime of this address in - * seconds. + * seconds. Set 0 for unspecified. + * @param[in] is_anycast Determines if an address is anycast. Anycast + * addresses are syntactically undistinguishable + * from unicast addresses and can only be identified + * with this flag. If *addr* is no unicast address + * and *is_anycast* is set, this function will fail. + * + * @return 1 on success, 0 on failure. */ -void ipv6_iface_add_addr(const ipv6_addr_t *addr, ipv6_addr_type_t type, +int ipv6_net_if_add_addr(int if_id, const ipv6_addr_t *addr, ndp_addr_state_t state, uint32_t val_ltime, - uint32_t pref_ltime); + uint32_t pref_ltime, uint8_t is_anycast); /** * @brief Tries to determine best suitable source address attached to - * the interface of this node based on the given destination + * an interface of this node based on the given destination * address. The use-case for this function is to find a * suitable address for the source address field of an IPv6 * address upon sending. *src* may be empty (all zero) if there @@ -381,16 +505,11 @@ void ipv6_iface_add_addr(const ipv6_addr_t *addr, ipv6_addr_type_t type, * * @param[out] src The best source address for this node (may be * all zero if ther is none). + * @param[in] if_id The interface's ID. * @param[in] dest The destination address for a packet we search * the source address for. */ -void ipv6_iface_get_best_src_addr(ipv6_addr_t *src, - const ipv6_addr_t *dest); - -/** - * @brief Print all addresses attached to the interface to stdout. - */ -void ipv6_iface_print_addrs(void); +void ipv6_net_if_get_best_src_addr(ipv6_addr_t *src, const ipv6_addr_t *dest); /** * @brief Registers a function that decides how to route incomming diff --git a/sys/net/include/sixlowpan/ndp.h b/sys/net/include/sixlowpan/ndp.h index 939844fa53..9bf7b69561 100644 --- a/sys/net/include/sixlowpan/ndp.h +++ b/sys/net/include/sixlowpan/ndp.h @@ -24,6 +24,7 @@ #include +#include "net_if.h" #include "timex.h" #include "sixlowpan/types.h" @@ -32,6 +33,7 @@ #define NDP_OPT_SLLAO_TYPE (1) #define NDP_OPT_TLLAO_TYPE (2) #define NDP_OPT_PI_VLIFETIME_INFINITE (0xffffffff) +#define NDP_OPT_PI_PLIFETIME_INFINITE (0xffffffff) #define NDP_OPT_ARO_STATE_SUCCESS (0) #define NDP_OPT_ARO_STATE_DUP_ADDR (1) #define NDP_OPT_ARO_STATE_NBR_CACHE_FULL (2) @@ -64,18 +66,37 @@ typedef enum __attribute__((packed)) { /** * @brief Prefix list type to store information spread by prefix - * information option. + * information option on the interface. + * + * @see net_if_addr_t */ -typedef struct __attribute__((packed)) { - uint8_t inuse; ///< Prefix is in in use. - uint8_t adv; - ipv6_addr_t addr; ///< The Prefix. - uint8_t length; ///< Length of the prefix. - uint8_t l_a_reserved1; ///< L and A flag of prefix information option - uint32_t val_ltime; ///< valid lifetime - uint32_t pref_ltime; ///< preferred lifetime - uint8_t infinite; ///< flag to set to infinite lifetime -} ndp_prefix_list_t; +typedef struct __attribute__((packed)) ndp_prefix_info_t { + /** + * @brief The next on the interface. Intialise with NULL + */ + struct ndp_prefix_info_t *addr_next; + /** + * @brief The prev address on the interface. Initialise with NULL + */ + struct ndp_prefix_info_t *addr_prev; + /** + * @brief Flags to define upper layer protocols this address applies to. + * For this layer NET_IF_L3P_IPV6_PREFIX must be set. + */ + net_if_l3p_t prefix_protocol; + ipv6_addr_t *prefix_data; ///< The Prefix. + uint8_t prefix_len; ///< Length of the prefix. + uint8_t inuse; ///< Prefix is in in use. + /** + * Use this information in Prefix Information Options of Router + * Advertisements. + */ + uint8_t advertisable; + uint8_t flags; ///< flags of the prefix information option + uint32_t valid_lifetime; ///< valid lifetime + uint32_t preferred_lifetime; ///< preferred lifetime + uint8_t infinite; ///< flag to set to infinite lifetime +} ndp_prefix_info_t; /** * @brief Default router list to store information spread by @@ -84,7 +105,7 @@ typedef struct __attribute__((packed)) { typedef struct __attribute__((packed)) { ipv6_addr_t addr; ///< Address of router. timex_t inval_time; ///< remaining time until this entry is - ///< invalid. + ///< invalid. } ndp_default_router_list_t; /** @@ -94,14 +115,16 @@ typedef struct __attribute__((packed)) { * . */ typedef struct __attribute__((packed)) { + int if_id; ///< Interface the IPv6 address is reachable + ///< over ndp_nce_type_t type; ///< Type of neighbor cache entry. ndp_nce_state_t state; ///< State of neighbor cache entry. uint8_t isrouter; ///< Flag to signify that this neighbor - ///< is a router. + ///< is a router. ipv6_addr_t addr; ///< IPv6 address of the neighbor. - ieee_802154_long_t laddr; ///< EUI-64 of neighbor - ieee_802154_short_t saddr; ///< IEEE 802.15.4 16-bit short address - ///< of neighbor. + uint8_t lladdr[8]; ///< Link-layer address of the neighbor + uint8_t lladdr_len; ///< Length of link-layer address of the + ///< neighbor timex_t ltime; ///< lifetime of entry. } ndp_neighbor_cache_t; @@ -118,9 +141,76 @@ typedef struct __attribute__((packed)) { } ndp_a6br_cache_t; ndp_default_router_list_t *ndp_default_router_list_search(ipv6_addr_t *ipaddr); +uint8_t ndp_neighbor_cache_add(int if_id, const ipv6_addr_t *ipaddr, + const void *lladdr, uint8_t lladdr_len, + uint8_t isrouter, ndp_nce_state_t state, + ndp_nce_type_t type, uint16_t ltime); ndp_neighbor_cache_t *ndp_neighbor_cache_search(ipv6_addr_t *ipaddr); -/*TODO: to implement*/ -uint8_t ndp_prefix_list_search(ipv6_addr_t *addr); +ndp_neighbor_cache_t *ndp_get_ll_address(ipv6_addr_t *ipaddr); +int ndp_addr_is_on_link(ipv6_addr_t *dest_addr); + +/** + * @brief Adds a prefix information to an interface. If it already exists, + * the values *valid_lifetime*, *preferred_lifetime*, *advertisable*, + * and flags will be updated accordingly and the prefix will be marked + * as *in_use*. + * + * @see + * RFC 4861, section 4.6.2 + * . + * + * @param[in] if_id The interface's ID. + * @param[in] prefix The prefix. + * @param[in] prefix_len The length of the prefix in bit. + * @param[in] valid_lifetime The time in seconds this prefix is valid + * for on-link determination. + * NDP_OPT_PI_VLIFETIME_INFINITE for infinite + * lifetime. + * @param[in] preferred_lifetime The time in seconds addresses generated with + * this prefix remain preferred. + * NDP_OPT_PI_PLIFETIME_INFINITE for infinite + * lifetime. + * @param[in] advertisable Set this to a value != 0 to advertise this + * prefix information with the Prefix + * Information Option, set it to 0 if not. + * @param[in] flags Flags for the Prefix Information Option. + * Valid values are + * ICMPV6_NDP_OPT_PI_FLAG_ON_LINK and + * ICMPV6_NDP_OPT_PI_FLAG_AUTONOM + */ +int ndp_add_prefix_info(int if_id, const ipv6_addr_t *prefix, + uint8_t prefix_len, uint32_t valid_lifetime, + uint32_t preferred_lifetime, uint8_t advertisable, + uint8_t flags); + +/** + * @brief Searches the information for the longest prefix up to *up_to* bits + * on an interface fitting to an address *addr*. + * + * @param[in] if_id The interface's ID. + * @param[in] addr The address to search the prefix for. + * @param[in] up_to The number of bits up to which point the search should + * go. Set to IPV6_ADDR_BIT_LEN for the whole address. + * Values greater then IPV6_ADDR_BIT_LEN are set to + * IPV6_ADDR_BIT_LEN. + * + * @return The found prefix information, NULL when none is found. + */ +ndp_prefix_info_t *ndp_prefix_info_search(int if_id, const ipv6_addr_t *addr, + uint8_t up_to); + +/** + * @brief Searches the information for the prefix that matches *prefix* with + * length *prefix_len*. + * + * @param[in] if_id The interface's ID. + * @param[in] prefix The prefix to search for. + * @param[in] prefix_len The length of the prefix in bit. + * + * @return The found prefix information, NULL when none is found. + */ +ndp_prefix_info_t *ndp_prefix_info_match(int if_id, const ipv6_addr_t *prefix, + uint8_t prefix_len); ndp_a6br_cache_t *ndp_a6br_cache_get_most_current(void); ndp_a6br_cache_t *ndp_a6br_cache_get_oldest(void); diff --git a/sys/net/include/sixlowpan/types.h b/sys/net/include/sixlowpan/types.h index 879d8e5d1d..d8ebc0334e 100644 --- a/sys/net/include/sixlowpan/types.h +++ b/sys/net/include/sixlowpan/types.h @@ -49,25 +49,6 @@ typedef union __attribute__((packed)) { uint32_t uint32[4]; ///< devided by 4 32-bit words. } ipv6_addr_t; -/** - * @brief Data type to represent IPv6 address types. - * - * @see - * RFC 4291 - * - */ -typedef enum __attribute__((packed)) { - IPV6_ADDR_TYPE_NONE, ///< address has no type/is invalid. - IPV6_ADDR_TYPE_UNICAST, ///< address is an unicast address. - IPV6_ADDR_TYPE_MULTICAST, ///< address is a multicast address. - IPV6_ADDR_TYPE_ANYCAST, ///< address is an anycast address. - IPV6_ADDR_TYPE_SOLICITED_NODE, ///< address is a solicitated node - ///< multicast address. - IPV6_ADDR_TYPE_LOOPBACK, ///< address is a loopback address. - IPV6_ADDR_TYPE_LINK_LOCAL, ///< address is a link-local address. - IPV6_ADDR_TYPE_GLOBAL ///< address is a global address. -} ipv6_addr_type_t; - /** * @brief Data type to represent an IPv6 packet header * @@ -78,7 +59,7 @@ typedef enum __attribute__((packed)) { typedef struct __attribute__((packed)) { uint8_t version_trafficclass; ///< Version field + first 4 bit of Traffic Class. uint8_t trafficclass_flowlabel; ///< last 4 bit of Traffic Class - ///< and first 4 bit of Flow Label. + ///< and first 4 bit of Flow Label. uint16_t flowlabel; ///< last 16 bit of Flow Label. uint16_t length; ///< payload length of this packet. uint8_t nextheader; ///< type of next header in this packet. diff --git a/sys/net/network_layer/sixlowpan/border/border.h b/sys/net/network_layer/sixlowpan/border/border.h index f9a7d0c9a5..fbdfe95be5 100644 --- a/sys/net/network_layer/sixlowpan/border/border.h +++ b/sys/net/network_layer/sixlowpan/border/border.h @@ -29,7 +29,7 @@ #include "ip.h" #include "semaphore.h" -extern ipv6_addr_t abr_addr; +extern ipv6_addr_t *abr_addr; uint16_t border_get_serial_reader(void); diff --git a/sys/net/network_layer/sixlowpan/border/bordermultiplex.c b/sys/net/network_layer/sixlowpan/border/bordermultiplex.c index 3cd0ed2b38..1d113872ee 100644 --- a/sys/net/network_layer/sixlowpan/border/bordermultiplex.c +++ b/sys/net/network_layer/sixlowpan/border/bordermultiplex.c @@ -77,7 +77,7 @@ void demultiplex(border_packet_t *packet) context->context.lifetime ); mutex_unlock(&lowpan_context_mutex); - abr_add_context(context->context.version, &abr_addr, context->context.cid); + abr_add_context(context->context.version, abr_addr, context->context.cid); /* Send router advertisement */ break; } @@ -141,7 +141,7 @@ int readpacket(uint8_t *packet_buf, size_t size) break; } - if ((size_t) (line_buf_ptr - packet_buf) >= size - 1) { + if ((size_t)(line_buf_ptr - packet_buf) >= size - 1) { return -SIXLOWERROR_ARRAYFULL; } @@ -179,8 +179,8 @@ int writepacket(uint8_t *packet_buf, size_t size) { uint8_t *byte_ptr = packet_buf; - while ((size_t) (byte_ptr - packet_buf) < size) { - if ((size_t) (byte_ptr - packet_buf) > BORDER_BUFFER_SIZE) { + while ((size_t)(byte_ptr - packet_buf) < size) { + if ((size_t)(byte_ptr - packet_buf) > BORDER_BUFFER_SIZE) { return -1; } diff --git a/sys/net/network_layer/sixlowpan/icmp.c b/sys/net/network_layer/sixlowpan/icmp.c index 69005329fe..31952db2c8 100644 --- a/sys/net/network_layer/sixlowpan/icmp.c +++ b/sys/net/network_layer/sixlowpan/icmp.c @@ -94,6 +94,8 @@ /* default router list size */ #define DEF_RTR_LST_SIZE (3) /* geeigneten wert finden */ +#define PREFIX_BUF_LEN (NET_IF_MAX * OPT_PI_LIST_LEN) + /* extern variables */ uint8_t ipv6_ext_hdr_len = 0; @@ -102,17 +104,18 @@ uint8_t abr_count = 0; uint8_t nbr_count = 0; uint8_t def_rtr_count = 0; uint8_t rtr_sol_count = 0; -uint8_t prefix_count = 0; +uint8_t prefix_info_count = 0; +uint8_t prefix_buf_count = 0; /* datastructures */ ndp_a6br_cache_t abr_cache[ABR_CACHE_SIZE]; ndp_neighbor_cache_t nbr_cache[NBR_CACHE_SIZE]; ndp_default_router_list_t def_rtr_lst[DEF_RTR_LST_SIZE]; -ndp_prefix_list_t plist[OPT_PI_LIST_LEN]; +ndp_prefix_info_t prefix_info_buf[PREFIX_BUF_LEN]; +uint8_t prefix_buf[sizeof(ipv6_addr_t) * PREFIX_BUF_LEN]; /* pointer */ static uint8_t *llao; -addr_list_t *addr_list_ptr; static ipv6_hdr_t *ipv6_buf; static icmpv6_hdr_t *icmp_buf; @@ -137,15 +140,11 @@ ndp_default_router_list_t *def_rtr_entry; uint8_t recvd_cids[NDP_6LOWPAN_CONTEXT_MAX]; uint8_t icmpv6_opt_hdr_len = 0; uint8_t recvd_cids_len = 0; -ndp_prefix_list_t *recvd_prefixes[OPT_PI_LIST_LEN]; +ndp_prefix_info_t *recvd_prefixes[PREFIX_BUF_LEN]; uint8_t recvd_pref_len = 0; void def_rtr_lst_add(ipv6_addr_t *ipaddr, uint32_t rtr_ltime); void def_rtr_lst_rem(ndp_default_router_list_t *entry); -uint8_t nbr_cache_add(ipv6_addr_t *ipaddr, ieee_802154_long_t *laddr, - uint8_t isrouter, ndp_nce_state_t state, - ndp_nce_type_t type, uint16_t ltime, - ieee_802154_short_t *saddr); void nbr_cache_rem(ipv6_addr_t *addr); /** @@ -153,11 +152,12 @@ void nbr_cache_rem(ipv6_addr_t *addr); * configuration. * * @param[out] sllao The SLLAO to set. + * @param[in] if_id The interface to get the link-layer address from. * @param[in] type The value for the type field of the SLLAO. * @param[in] length The value for the length field of the SLLAO */ -void icmpv6_ndp_set_sllao(icmpv6_ndp_opt_stllao_t *sllao, uint8_t type, - uint8_t length); +void icmpv6_ndp_set_sllao(icmpv6_ndp_opt_stllao_t *sllao, int if_id, + uint8_t type, uint8_t length); int min(int a, int b) { @@ -239,14 +239,14 @@ static icmpv6_ndp_opt_aro_t *get_opt_aro_buf(uint8_t ext_len, uint8_t opt_len) return ((icmpv6_ndp_opt_aro_t *) &buffer[LLHDR_ICMPV6HDR_LEN + ext_len + opt_len]); } -void icmpv6_send_echo_request(ipv6_addr_t *destaddr, uint16_t id, uint16_t seq, char *data, size_t data_len) +void icmpv6_send_echo_request(ipv6_addr_t *destaddr, uint16_t id, uint16_t seq, uint8_t *data, size_t data_len) { uint16_t packet_length; ipv6_buf = ipv6_get_buf(); icmp_buf = get_icmpv6_buf(ipv6_ext_hdr_len); icmpv6_echo_request_hdr_t *echo_buf = get_echo_req_buf(ipv6_ext_hdr_len); - char *echo_data_buf = ((char *)echo_buf) + sizeof(icmpv6_echo_request_hdr_t); + uint8_t *echo_data_buf = ((uint8_t *)echo_buf) + sizeof(icmpv6_echo_request_hdr_t); icmp_buf->type = ICMPV6_TYPE_ECHO_REQUEST; icmp_buf->code = 0; @@ -257,35 +257,36 @@ void icmpv6_send_echo_request(ipv6_addr_t *destaddr, uint16_t id, uint16_t seq, ipv6_buf->hoplimit = ipv6_get_default_hop_limit(); memcpy(&ipv6_buf->destaddr, destaddr, sizeof(ipv6_addr_t)); - ipv6_iface_get_best_src_addr(&ipv6_buf->srcaddr, &ipv6_buf->destaddr); - echo_buf->id = id; - echo_buf->seq = seq; + ipv6_net_if_get_best_src_addr(&ipv6_buf->srcaddr, &ipv6_buf->destaddr); + echo_buf->id = HTONS(id); + echo_buf->seq = HTONS(seq); memcpy(echo_data_buf, data, data_len); packet_length = IPV6_HDR_LEN + ICMPV6_HDR_LEN + ipv6_ext_hdr_len + ECHO_REQ_LEN + data_len; - ipv6_buf->length = packet_length - IPV6_HDR_LEN; + ipv6_buf->length = HTONS(packet_length - IPV6_HDR_LEN); icmp_buf->checksum = 0; icmp_buf->checksum = ~icmpv6_csum(IPV6_PROTO_NUM_ICMPV6); #ifdef DEBUG_ENABLED char addr_str[IPV6_MAX_ADDR_STR_LEN]; - printf("INFO: send echo request to: %s\n", - ipv6_addr_to_str(addr_str, &ipv6_buf->destaddr)); + printf("INFO: send echo request (id = %04x, seq = %d, data_len = %d) to: %s\n", + id, seq, data_len, ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, + &ipv6_buf->destaddr)); #endif ipv6_send_packet(ipv6_buf); } -void icmpv6_send_echo_reply(ipv6_addr_t *destaddr, uint16_t id, uint16_t seq, char *data, size_t data_len) +void icmpv6_send_echo_reply(ipv6_addr_t *destaddr, uint16_t id, uint16_t seq, uint8_t *data, size_t data_len) { uint16_t packet_length; ipv6_buf = ipv6_get_buf(); icmp_buf = get_icmpv6_buf(ipv6_ext_hdr_len); icmpv6_echo_reply_hdr_t *echo_buf = get_echo_repl_buf(ipv6_ext_hdr_len); - char *echo_data_buf = ((char *)echo_buf) + sizeof(icmpv6_echo_reply_hdr_t); + uint8_t *echo_data_buf = ((uint8_t *)echo_buf) + sizeof(icmpv6_echo_reply_hdr_t); icmp_buf->type = ICMPV6_TYPE_ECHO_REPLY; icmp_buf->code = 0; @@ -296,23 +297,24 @@ void icmpv6_send_echo_reply(ipv6_addr_t *destaddr, uint16_t id, uint16_t seq, ch ipv6_buf->hoplimit = ipv6_get_default_hop_limit(); memcpy(&ipv6_buf->destaddr, destaddr, sizeof(ipv6_addr_t)); - ipv6_iface_get_best_src_addr(&ipv6_buf->srcaddr, &ipv6_buf->destaddr); - echo_buf->id = id; - echo_buf->seq = seq; + ipv6_net_if_get_best_src_addr(&ipv6_buf->srcaddr, &ipv6_buf->destaddr); + echo_buf->id = HTONS(id); + echo_buf->seq = HTONS(seq); memcpy(echo_data_buf, data, data_len); packet_length = IPV6_HDR_LEN + ICMPV6_HDR_LEN + ipv6_ext_hdr_len + ECHO_REPL_LEN + data_len; - ipv6_buf->length = packet_length - IPV6_HDR_LEN; + ipv6_buf->length = HTONS(packet_length - IPV6_HDR_LEN); icmp_buf->checksum = 0; icmp_buf->checksum = ~icmpv6_csum(IPV6_PROTO_NUM_ICMPV6); #ifdef DEBUG_ENABLED char addr_str[IPV6_MAX_ADDR_STR_LEN]; - printf("INFO: send echo request to: %s\n", - ipv6_addr_to_str(addr_str, &ipv6_buf->destaddr)); + printf("INFO: send echo reply (id = %04x, seq = %d, data_len = %d) to: %s\n", + id, seq, data_len, ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, + &ipv6_buf->destaddr)); #endif ipv6_send_packet(ipv6_buf); } @@ -321,6 +323,7 @@ void icmpv6_send_echo_reply(ipv6_addr_t *destaddr, uint16_t id, uint16_t seq, ch void icmpv6_send_router_sol(uint8_t sllao) { uint16_t packet_length; + int if_id = 0; // TODO get this somehow ipv6_buf = ipv6_get_buf(); icmp_buf = get_icmpv6_buf(ipv6_ext_hdr_len); @@ -337,29 +340,39 @@ void icmpv6_send_router_sol(uint8_t sllao) //iface_find_src_ipaddr(&ipv6_buf->srcaddr, NDP_ADDR_STATE_PREFERRED, /* IPV6_ADDR_TYPE_MULTICAST); */ - ipv6_iface_get_best_src_addr(&(ipv6_buf->srcaddr), &(ipv6_buf->destaddr)); + ipv6_net_if_get_best_src_addr(&(ipv6_buf->srcaddr), &(ipv6_buf->destaddr)); icmpv6_opt_hdr_len = RTR_SOL_LEN; - ipv6_buf->length = HTONS(ICMPV6_HDR_LEN + RTR_SOL_LEN + OPT_STLLAO_MAX_LEN); if (sllao == OPT_SLLAO) { opt_stllao_buf = get_opt_stllao_buf(ipv6_ext_hdr_len, icmpv6_opt_hdr_len); - icmpv6_ndp_set_sllao(opt_stllao_buf, NDP_OPT_SLLAO_TYPE, 2); - packet_length = IPV6_HDR_LEN + ICMPV6_HDR_LEN + ipv6_ext_hdr_len + - RTR_SOL_LEN + OPT_STLLAO_MAX_LEN; + + if (net_if_get_src_address_mode(if_id) == NET_IF_TRANS_ADDR_M_LONG) { + icmpv6_ndp_set_sllao(opt_stllao_buf, if_id, NDP_OPT_SLLAO_TYPE, 2); + packet_length = IPV6_HDR_LEN + ICMPV6_HDR_LEN + ipv6_ext_hdr_len + + RTR_SOL_LEN + OPT_STLLAO_MAX_LEN; + } + else { + icmpv6_ndp_set_sllao(opt_stllao_buf, if_id, NDP_OPT_SLLAO_TYPE, 1); + packet_length = IPV6_HDR_LEN + ICMPV6_HDR_LEN + ipv6_ext_hdr_len + + RTR_SOL_LEN + OPT_STLLAO_MIN_LEN; + } } else { packet_length = IPV6_HDR_LEN + ICMPV6_HDR_LEN + ipv6_ext_hdr_len + RTR_SOL_LEN; } + ipv6_buf->length = HTONS(packet_length - IPV6_HDR_LEN); + icmp_buf->checksum = 0; icmp_buf->checksum = ~icmpv6_csum(IPV6_PROTO_NUM_ICMPV6); #ifdef DEBUG_ENABLED char addr_str[IPV6_MAX_ADDR_STR_LEN]; printf("INFO: send router solicitation to: %s\n", - ipv6_addr_to_str(addr_str, &ipv6_buf->destaddr)); + ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, + &ipv6_buf->destaddr)); #endif ipv6_send_packet(ipv6_buf); } @@ -368,15 +381,17 @@ void recv_echo_req(void) { ipv6_buf = ipv6_get_buf(); icmpv6_echo_request_hdr_t *echo_buf = get_echo_req_buf(ipv6_ext_hdr_len); - char *echo_data_buf = ((char *)echo_buf) + sizeof(icmpv6_echo_reply_hdr_t); - size_t data_len = ipv6_buf->length - (IPV6_HDR_LEN + ICMPV6_HDR_LEN + - ipv6_ext_hdr_len + ECHO_REQ_LEN); + uint8_t *echo_data_buf = ((uint8_t *)echo_buf) + sizeof(icmpv6_echo_reply_hdr_t); + size_t data_len = NTOHS(ipv6_buf->length) - ICMPV6_HDR_LEN - ECHO_REQ_LEN; + #ifdef DEBUG_ENABLED char addr_str[IPV6_MAX_ADDR_STR_LEN]; printf("INFO: received echo request from: %s\n", - ipv6_addr_to_str(addr_str, &ipv6_buf->srcaddr)); + ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, + &ipv6_buf->srcaddr)); printf("\n"); - printf("id = 0x%04x, seq = %d\n", echo_buf->id, echo_buf->seq); + printf("id = 0x%04x, seq = %d, data_len = %d\n", NTOHS(echo_buf->id), + NTOHS(echo_buf->seq), data_len); for (size_t i = 0; i < data_len; i++) { printf("%02x ", echo_data_buf[i]); @@ -387,8 +402,8 @@ void recv_echo_req(void) } #endif - icmpv6_send_echo_reply(&ipv6_buf->srcaddr, echo_buf->id, echo_buf->seq, - echo_data_buf, data_len); + icmpv6_send_echo_reply(&ipv6_buf->srcaddr, NTOHS(echo_buf->id), + NTOHS(echo_buf->seq), echo_data_buf, data_len); } void recv_echo_repl(void) @@ -396,14 +411,16 @@ void recv_echo_repl(void) #ifdef DEBUG_ENABLED ipv6_buf = ipv6_get_buf(); icmpv6_echo_reply_hdr_t *echo_buf = get_echo_repl_buf(ipv6_ext_hdr_len); - char *echo_data_buf = ((char *)echo_buf) + sizeof(icmpv6_echo_reply_hdr_t); - size_t data_len = ipv6_buf->length - ICMPV6_HDR_LEN - ECHO_REPL_LEN; + uint8_t *echo_data_buf = ((uint8_t *)echo_buf) + sizeof(icmpv6_echo_reply_hdr_t); + size_t data_len = NTOHS(ipv6_buf->length) - ICMPV6_HDR_LEN - ECHO_REPL_LEN; char addr_str[IPV6_MAX_ADDR_STR_LEN]; printf("INFO: received echo reply from: %s\n", - ipv6_addr_to_str(addr_str, &ipv6_buf->srcaddr)); + ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, + &ipv6_buf->srcaddr)); printf("\n"); - printf("id = 0x%04x, seq = %d\n", echo_buf->id, echo_buf->seq); + printf("id = 0x%04x, seq = %d, data_len = %d\n", NTOHS(echo_buf->id), + NTOHS(echo_buf->seq), data_len); for (size_t i = 0; i < data_len; i++) { printf("%02x ", echo_data_buf[i]); @@ -420,6 +437,7 @@ void recv_echo_repl(void) void recv_rtr_sol(void) { + int if_id = 0; // TODO, get this somehow icmpv6_opt_hdr_len = RTR_SOL_LEN; ipv6_buf = ipv6_get_buf(); @@ -431,25 +449,39 @@ void recv_rtr_sol(void) } if (llao != NULL) { + uint8_t lladdr_len; nbr_entry = ndp_neighbor_cache_search(&ipv6_buf->srcaddr); + if (opt_stllao_buf->length == 2) { + lladdr_len = 8; + } + else if (opt_stllao_buf->length == 1) { + lladdr_len = 2; + } + else { + DEBUG("Unknown length for S/TLLAO: %d * 8 Bytes.\n", opt_stllao_buf->length); + return; + } + if (nbr_entry != NULL) { - /* found neighbor in cache, update values and check long addr */ - if (memcmp(&llao[2], &nbr_entry->laddr, 8) == 0) { + /* found neighbor in cache, update values and check addr */ + if (memcmp(&llao[2], &nbr_entry->lladdr, lladdr_len) == 0) { + nbr_entry->if_id = if_id; nbr_entry->isrouter = 0; } else { - /* new long addr found, update */ - memcpy(&nbr_entry->laddr, &llao[2], 8); + /* new addr found, update */ + nbr_entry->if_id = if_id; + memcpy(&nbr_entry->lladdr, &llao[2], lladdr_len); nbr_entry->state = NDP_NCE_STATUS_STALE; nbr_entry->isrouter = 0; } } else { /* nothing found, add neigbor into cache*/ - nbr_cache_add(&ipv6_buf->srcaddr, (ieee_802154_long_t *)&llao[2], - 0, NDP_NCE_STATUS_STALE, NDP_NCE_TYPE_TENTATIVE, - NBR_CACHE_LTIME_TEN, NULL); + ndp_neighbor_cache_add(if_id, &ipv6_buf->srcaddr, &llao[2], lladdr_len, + 0, NDP_NCE_STATUS_STALE, NDP_NCE_TYPE_TENTATIVE, + NBR_CACHE_LTIME_TEN); } } @@ -460,12 +492,6 @@ void recv_rtr_sol(void) else { icmpv6_send_router_adv(&ipv6_buf->srcaddr, 0, 0, OPT_PI, 0, 0); } - -#ifdef DEBUG_ENABLED - char addr_str[IPV6_MAX_ADDR_STR_LEN]; - printf("INFO: send router advertisment to: %s\n", - ipv6_addr_to_str(addr_str, &ipv6_buf->destaddr)); -#endif } uint8_t set_opt_6co_flags(uint8_t compression_flag, uint8_t cid) @@ -495,6 +521,7 @@ lowpan_context_t *abr_get_context(ndp_a6br_cache_t *abr, uint8_t cid); void icmpv6_send_router_adv(ipv6_addr_t *addr, uint8_t sllao, uint8_t mtu, uint8_t pi, uint8_t sixco, uint8_t abro) { + int if_id = 0; // TODO: get this somehow uint16_t packet_length; lowpan_context_t *contexts = NULL; @@ -516,7 +543,7 @@ void icmpv6_send_router_adv(ipv6_addr_t *addr, uint8_t sllao, uint8_t mtu, uint8 memcpy(&ipv6_buf->destaddr, addr, 16); } - ipv6_iface_get_best_src_addr(&(ipv6_buf->srcaddr), &(ipv6_buf->destaddr)); + ipv6_net_if_get_best_src_addr(&(ipv6_buf->srcaddr), &(ipv6_buf->destaddr)); icmp_buf->type = ICMPV6_TYPE_ROUTER_ADV; icmp_buf->code = 0; @@ -537,9 +564,17 @@ void icmpv6_send_router_adv(ipv6_addr_t *addr, uint8_t sllao, uint8_t mtu, uint8 if (sllao == OPT_SLLAO) { /* set link layer address option */ opt_stllao_buf = get_opt_stllao_buf(ipv6_ext_hdr_len, icmpv6_opt_hdr_len); - icmpv6_ndp_set_sllao(opt_stllao_buf, NDP_OPT_SLLAO_TYPE, 2); - icmpv6_opt_hdr_len += OPT_STLLAO_MAX_LEN; - packet_length += OPT_STLLAO_MAX_LEN; + + if (net_if_get_src_address_mode(if_id) == NET_IF_TRANS_ADDR_M_LONG) { + icmpv6_ndp_set_sllao(opt_stllao_buf, if_id, NDP_OPT_SLLAO_TYPE, 2); + icmpv6_opt_hdr_len += OPT_STLLAO_MAX_LEN; + packet_length += OPT_STLLAO_MAX_LEN; + } + else { + icmpv6_ndp_set_sllao(opt_stllao_buf, if_id, NDP_OPT_SLLAO_TYPE, 1); + icmpv6_opt_hdr_len += OPT_STLLAO_MIN_LEN; + packet_length += OPT_STLLAO_MIN_LEN; + } } if (mtu == OPT_MTU) { @@ -638,17 +673,21 @@ void icmpv6_send_router_adv(ipv6_addr_t *addr, uint8_t sllao, uint8_t mtu, uint8 } if (pi == OPT_PI) { + ndp_prefix_info_t *prefix = NULL; + /* set prefix option */ - for (int i = 0; i < OPT_PI_LIST_LEN; i++) { - if (plist[i].inuse && plist[i].adv) { + while (net_if_iter_addresses(if_id, (net_if_addr_t **) &prefix)) { + if (prefix->prefix_protocol & NET_IF_L3P_IPV6_PREFIX && + prefix->inuse && prefix->advertisable) { opt_pi_buf = get_opt_pi_buf(ipv6_ext_hdr_len, icmpv6_opt_hdr_len); - memcpy(&(opt_pi_buf->addr.uint8[0]), &(plist[i].addr.uint8[0]), 16); + memset(&opt_pi_buf->addr, 0, sizeof(ipv6_addr_t)); + memcpy(&opt_pi_buf->addr, &prefix->prefix_data, prefix->prefix_len); opt_pi_buf->type = OPT_PI_TYPE; opt_pi_buf->length = OPT_PI_LEN; - opt_pi_buf->prefix_length = plist[i].length; - opt_pi_buf->l_a_reserved1 = plist[i].l_a_reserved1; - opt_pi_buf->val_ltime = HTONL(plist[i].val_ltime); - opt_pi_buf->pref_ltime = HTONL(plist[i].pref_ltime); + opt_pi_buf->prefix_length = prefix->prefix_len; + opt_pi_buf->l_a_reserved1 = prefix->flags; + opt_pi_buf->val_ltime = HTONL(prefix->valid_lifetime); + opt_pi_buf->pref_ltime = HTONL(prefix->preferred_lifetime); opt_pi_buf->reserved2 = 0; packet_length += OPT_PI_HDR_LEN; icmpv6_opt_hdr_len += OPT_PI_HDR_LEN; @@ -661,10 +700,19 @@ void icmpv6_send_router_adv(ipv6_addr_t *addr, uint8_t sllao, uint8_t mtu, uint8 /* calculate checksum */ icmp_buf->checksum = 0; icmp_buf->checksum = ~icmpv6_csum(IPV6_PROTO_NUM_ICMPV6); + +#ifdef DEBUG_ENABLED + char addr_str[IPV6_MAX_ADDR_STR_LEN]; + printf("INFO: send router advertisement to: %s\n", + ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, + &ipv6_buf->destaddr)); +#endif + ipv6_send_packet(ipv6_buf); } void recv_rtr_adv(void) { + int if_id = 0; // TODO: get this somehow int8_t trigger_ns = -1; int8_t abro_found = 0; int16_t abro_version = 0; /* later replaced, just to supress warnings */ @@ -680,11 +728,19 @@ void recv_rtr_adv(void) /* update interface reachable time and retrans timer */ if (rtr_adv_buf->reachable_time != 0) { - iface.adv_reachable_time = HTONL(rtr_adv_buf->reachable_time); + ipv6_net_if_ext_t *iface; + + if ((iface = ipv6_net_if_get_ext(if_id)) == NULL) { + iface->adv_reachable_time = NTOHL(rtr_adv_buf->reachable_time); + } } if (rtr_adv_buf->retrans_timer != 0) { - iface.adv_retrans_timer = HTONL(rtr_adv_buf->retrans_timer); + ipv6_net_if_ext_t *iface; + + if ((iface = ipv6_net_if_get_ext(if_id)) == NULL) { + iface->adv_retrans_timer = NTOHL(rtr_adv_buf->retrans_timer); + } } def_rtr_entry = ndp_default_router_list_search(&ipv6_buf->srcaddr); @@ -737,46 +793,51 @@ void recv_rtr_adv(void) } if (opt_pi_buf->l_a_reserved1 & ICMPV6_NDP_OPT_PI_FLAG_AUTONOM) { - addr_list_ptr = ipv6_iface_addr_prefix_eq(&opt_pi_buf->addr); + ipv6_net_if_hit_t addr_hit; - if (addr_list_ptr == NULL) { + if (!ipv6_net_if_addr_prefix_eq(&addr_hit, &opt_pi_buf->addr)) { /* 5.5.3d */ if (opt_pi_buf->val_ltime != 0) { /* iid will also be added here */ - ipv6_addr_set_by_eui64(&newaddr, + ipv6_addr_set_by_eui64(&newaddr, if_id, &opt_pi_buf->addr); /* add into address list * TODO: duplicate address detection is not * implementet yet, so all new addresse will * be added with state PREFFERED */ - ipv6_iface_add_addr(&newaddr, - IPV6_ADDR_TYPE_UNICAST, - NDP_ADDR_STATE_PREFERRED, - opt_pi_buf->val_ltime, - opt_pi_buf->pref_ltime); + ipv6_net_if_add_addr(if_id, &newaddr, + NDP_ADDR_STATE_PREFERRED, + opt_pi_buf->val_ltime, + opt_pi_buf->pref_ltime, 0); DEBUG("INFO: added address to interface\n"); trigger_ns = 1; } } else { /* 5.5.3e */ - set_remaining_time(&(addr_list_ptr->pref_ltime), opt_pi_buf->pref_ltime); + set_remaining_time(&addr_hit.addr->preferred_lifetime, + opt_pi_buf->pref_ltime); /* 7200 = 2hours in seconds */ if (HTONL(opt_pi_buf->val_ltime) > 7200 || HTONL(opt_pi_buf->val_ltime) > - get_remaining_time(&(addr_list_ptr->val_ltime))) { - set_remaining_time(&(addr_list_ptr->val_ltime), HTONL(opt_pi_buf->val_ltime)); + get_remaining_time(&addr_hit.addr->valid_lifetime)) { + set_remaining_time(&addr_hit.addr->valid_lifetime, + HTONL(opt_pi_buf->val_ltime)); } else { /* reset valid lifetime to 2 hours */ - set_remaining_time(&(addr_list_ptr->val_ltime), 7200); + set_remaining_time(&addr_hit.addr->valid_lifetime, + 7200); } } } } - /* TODO: save found prefixes */ + ndp_add_prefix_info(if_id, &opt_pi_buf->addr, opt_pi_buf->length, + opt_pi_buf->val_ltime, opt_pi_buf->pref_ltime, + 0, opt_pi_buf->l_a_reserved1); + break; } @@ -843,11 +904,6 @@ void recv_rtr_adv(void) * * if new address was configured, set src to newaddr(gp16) */ icmpv6_send_neighbor_sol(&newaddr, &(ipv6_buf->srcaddr), &(ipv6_buf->srcaddr), OPT_SLLAO, OPT_ARO); -#ifdef DEBUG_ENABLED - char addr_str[IPV6_MAX_ADDR_STR_LEN]; - printf("INFO: send neighbor solicitation to: %s\n", - ipv6_addr_to_str(addr_str, &(ipv6_buf->destaddr))); -#endif } } @@ -856,6 +912,7 @@ void icmpv6_send_neighbor_sol(ipv6_addr_t *src, ipv6_addr_t *dest, ipv6_addr_t * { uint16_t packet_length; int if_id = 0; // TODO: get this somehow + ipv6_net_if_hit_t hit; ipv6_buf = ipv6_get_buf(); ipv6_buf->version_trafficclass = IPV6_VER; @@ -883,9 +940,9 @@ void icmpv6_send_neighbor_sol(ipv6_addr_t *src, ipv6_addr_t *dest, ipv6_addr_t * packet_length = IPV6_HDR_LEN + ICMPV6_HDR_LEN + NBR_SOL_LEN; - if (ipv6_iface_addr_match(targ) == NULL) { + if (!ipv6_net_if_addr_match(&hit, targ)) { if (src == NULL) { - ipv6_iface_get_best_src_addr(&(ipv6_buf->srcaddr), &(ipv6_buf->destaddr)); + ipv6_net_if_get_best_src_addr(&(ipv6_buf->srcaddr), &(ipv6_buf->destaddr)); } else { memcpy(&(ipv6_buf->srcaddr), src, 16); @@ -894,10 +951,17 @@ void icmpv6_send_neighbor_sol(ipv6_addr_t *src, ipv6_addr_t *dest, ipv6_addr_t * if (sllao == OPT_SLLAO) { /* set sllao option */ opt_stllao_buf = get_opt_stllao_buf(ipv6_ext_hdr_len, icmpv6_opt_hdr_len); - icmpv6_ndp_set_sllao(opt_stllao_buf, NDP_OPT_SLLAO_TYPE, 1); - icmpv6_opt_hdr_len += OPT_STLLAO_MIN_LEN; - packet_length += OPT_STLLAO_MIN_LEN; + if (net_if_get_src_address_mode(if_id) == NET_IF_TRANS_ADDR_M_LONG) { + icmpv6_ndp_set_sllao(opt_stllao_buf, if_id, NDP_OPT_SLLAO_TYPE, 2); + icmpv6_opt_hdr_len += OPT_STLLAO_MAX_LEN; + packet_length += OPT_STLLAO_MAX_LEN; + } + else { + icmpv6_ndp_set_sllao(opt_stllao_buf, if_id, NDP_OPT_SLLAO_TYPE, 1); + icmpv6_opt_hdr_len += OPT_STLLAO_MIN_LEN; + packet_length += OPT_STLLAO_MIN_LEN; + } } } @@ -926,17 +990,25 @@ void icmpv6_send_neighbor_sol(ipv6_addr_t *src, ipv6_addr_t *dest, ipv6_addr_t * icmp_buf->checksum = 0; icmp_buf->checksum = ~icmpv6_csum(IPV6_PROTO_NUM_ICMPV6); + +#ifdef DEBUG_ENABLED + char addr_str[IPV6_MAX_ADDR_STR_LEN]; + printf("INFO: send neighbor solicitation to: %s\n", + ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, + &ipv6_buf->destaddr)); +#endif + ipv6_send_packet(ipv6_buf); } void recv_nbr_sol(void) { + int if_id = 0; // TODO, get this somehow ipv6_buf = ipv6_get_buf(); llao = NULL; icmpv6_opt_hdr_len = NBR_SOL_LEN; uint8_t send_na = 0; uint8_t sllao_set = 0; - uint8_t aro_state = NDP_OPT_ARO_STATE_SUCCESS; uint16_t packet_length = IPV6_HDR_LEN + NTOHS(ipv6_buf->length); /* check whick options are set, we need that because an aro @@ -971,11 +1043,13 @@ void recv_nbr_sol(void) if (nbr_entry != NULL) { switch (opt_stllao_buf->length) { case (1): { - if (memcmp(&llao[2], &(nbr_entry->saddr), 2) == 0) { + if (memcmp(&llao[2], &(nbr_entry->lladdr), 2) == 0) { + nbr_entry->if_id = if_id; nbr_entry->isrouter = 0; } else { - memcpy(&nbr_entry->saddr, &llao[2], 2); + nbr_entry->if_id = if_id; + memcpy(&nbr_entry->lladdr, &llao[2], 2); nbr_entry->state = NDP_NCE_STATUS_STALE; nbr_entry->isrouter = 0; } @@ -984,11 +1058,13 @@ void recv_nbr_sol(void) } case (2): { - if (memcmp(&llao[2], &(nbr_entry->laddr), 8) == 0) { + if (memcmp(&llao[2], &(nbr_entry->lladdr), 8) == 0) { + nbr_entry->if_id = if_id; nbr_entry->isrouter = 0; } else { - memcpy(&nbr_entry->laddr, &llao[2], 8); + nbr_entry->if_id = if_id; + memcpy(&nbr_entry->lladdr, &llao[2], 8); nbr_entry->state = NDP_NCE_STATUS_STALE; nbr_entry->isrouter = 0; } @@ -1003,21 +1079,21 @@ void recv_nbr_sol(void) else { switch (opt_stllao_buf->length) { case (1): { - nbr_cache_add(&ipv6_buf->srcaddr, - NULL , 0, NDP_NCE_STATUS_STALE, - NDP_NCE_TYPE_TENTATIVE, - NBR_CACHE_LTIME_TEN, - (ieee_802154_short_t *)&llao[2]); + ndp_neighbor_cache_add(if_id, &ipv6_buf->srcaddr, + &llao[2], 2, 0, + NDP_NCE_STATUS_STALE, + NDP_NCE_TYPE_TENTATIVE, + NBR_CACHE_LTIME_TEN); break; } case (2): { - nbr_cache_add(&ipv6_buf->srcaddr, - (ieee_802154_long_t *)&llao[2], 0, - NDP_NCE_STATUS_STALE, - NDP_NCE_TYPE_TENTATIVE, - NBR_CACHE_LTIME_TEN, NULL); + ndp_neighbor_cache_add(if_id, &ipv6_buf->srcaddr, + &llao[2], 8, 0, + NDP_NCE_STATUS_STALE, + NDP_NCE_TYPE_TENTATIVE, + NBR_CACHE_LTIME_TEN); break; } @@ -1035,6 +1111,7 @@ void recv_nbr_sol(void) * isn't unspecified - draft-ietf-6lowpan-nd-15#section-6.5 */ if (!(ipv6_addr_is_unspecified(&ipv6_buf->srcaddr)) && sllao_set == 1) { + uint8_t aro_state = NDP_OPT_ARO_STATE_SUCCESS; opt_aro_buf = get_opt_aro_buf(ipv6_ext_hdr_len, icmpv6_opt_hdr_len); @@ -1045,10 +1122,10 @@ void recv_nbr_sol(void) if (nbr_entry == NULL) { /* create neighbor cache */ - aro_state = nbr_cache_add(&ipv6_buf->srcaddr, - &(opt_aro_buf->eui64), 0, - NDP_NCE_STATUS_STALE, NDP_NCE_TYPE_TENTATIVE, - opt_aro_buf->reg_ltime, NULL); + aro_state = ndp_neighbor_cache_add(if_id, &ipv6_buf->srcaddr, + &(opt_aro_buf->eui64), 8, 0, + NDP_NCE_STATUS_STALE, NDP_NCE_TYPE_TENTATIVE, + opt_aro_buf->reg_ltime); } else { if (memcmp(&(nbr_entry->addr.uint16[4]), @@ -1086,20 +1163,19 @@ void recv_nbr_sol(void) icmpv6_opt_hdr_len += (opt_buf->length * 8); } - addr_list_t *alist_targ, *alist_dest; + ipv6_net_if_hit_t alist_targ, alist_dest; nbr_sol_buf = get_nbr_sol_buf(ipv6_ext_hdr_len); - alist_targ = ipv6_iface_addr_match(&(nbr_sol_buf->target_addr)); - if (alist_targ != NULL) { - alist_dest = ipv6_iface_addr_match(&(ipv6_buf->destaddr)); + if (ipv6_net_if_addr_match(&alist_targ, &nbr_sol_buf->target_addr) != NULL) { + ipv6_net_if_addr_match(&alist_dest, &ipv6_buf->destaddr); - if ((memcmp(&(alist_targ->addr), &(alist_dest->addr), 16) == 0) || + if ((memcmp(alist_targ.addr->addr_data, alist_dest.addr->addr_data, 16) == 0) || ipv6_addr_is_solicited_node(&ipv6_buf->destaddr)) { memcpy(&(ipv6_buf->destaddr.uint8[0]), - &(ipv6_buf->srcaddr.uint8[0]), 16); + &(ipv6_buf->srcaddr.uint8[0]), sizeof(ipv6_addr_t)); memcpy(&(ipv6_buf->srcaddr.uint8[0]), - &(nbr_sol_buf->target_addr.uint8[0]), 16); + &(nbr_sol_buf->target_addr.uint8[0]), sizeof(ipv6_addr_t)); send_na = 1; } } @@ -1108,12 +1184,7 @@ void recv_nbr_sol(void) /* solicited na */ uint8_t flags = (ICMPV6_NEIGHBOR_ADV_FLAG_OVERRIDE | ICMPV6_NEIGHBOR_ADV_FLAG_SOLICITED); icmpv6_send_neighbor_adv(&(ipv6_buf->srcaddr), &(ipv6_buf->destaddr), - &(alist_targ->addr), flags, 0, OPT_ARO); -#ifdef DEBUG_ENABLED - char addr_str[IPV6_MAX_ADDR_STR_LEN]; - printf("INFO: send neighbor advertisment to: %s\n", - ipv6_addr_to_str(addr_str, &ipv6_buf->destaddr)); -#endif + alist_targ.addr->addr_data, flags, 0, OPT_ARO); } } @@ -1135,8 +1206,13 @@ void icmpv6_send_neighbor_adv(ipv6_addr_t *src, ipv6_addr_t *dst, ipv6_addr_t *t icmp_buf->type = ICMPV6_TYPE_NEIGHBOR_ADV; icmp_buf->code = 0; - memcpy(&(ipv6_buf->destaddr.uint8[0]), &(dst->uint8[0]), 16); - memcpy(&(ipv6_buf->srcaddr.uint8[0]), &(src->uint8[0]), 16); + if (&ipv6_buf->destaddr != dst) { + memcpy(&(ipv6_buf->destaddr.uint8[0]), &(dst->uint8[0]), 16); + } + + if (&ipv6_buf->srcaddr != src) { + memcpy(&(ipv6_buf->srcaddr.uint8[0]), &(src->uint8[0]), 16); + } nbr_adv_buf = get_nbr_adv_buf(ipv6_ext_hdr_len); nbr_adv_buf->rso = rso; @@ -1149,10 +1225,17 @@ void icmpv6_send_neighbor_adv(ipv6_addr_t *src, ipv6_addr_t *dst, ipv6_addr_t *t if (sllao == OPT_SLLAO) { /* set sllao option */ opt_stllao_buf = get_opt_stllao_buf(ipv6_ext_hdr_len, icmpv6_opt_hdr_len); - icmpv6_ndp_set_sllao(opt_stllao_buf, NDP_OPT_SLLAO_TYPE, 1); - icmpv6_opt_hdr_len += OPT_STLLAO_MIN_LEN; - packet_length += OPT_STLLAO_MIN_LEN; + if (net_if_get_src_address_mode(if_id) == NET_IF_TRANS_ADDR_M_LONG) { + icmpv6_ndp_set_sllao(opt_stllao_buf, if_id, NDP_OPT_SLLAO_TYPE, 2); + icmpv6_opt_hdr_len += OPT_STLLAO_MAX_LEN; + packet_length += OPT_STLLAO_MAX_LEN; + } + else { + icmpv6_ndp_set_sllao(opt_stllao_buf, if_id, NDP_OPT_SLLAO_TYPE, 1); + icmpv6_opt_hdr_len += OPT_STLLAO_MIN_LEN; + packet_length += OPT_STLLAO_MIN_LEN; + } } if (aro == OPT_ARO) { @@ -1180,12 +1263,21 @@ void icmpv6_send_neighbor_adv(ipv6_addr_t *src, ipv6_addr_t *dst, ipv6_addr_t *t icmp_buf->checksum = 0; icmp_buf->checksum = ~icmpv6_csum(IPV6_PROTO_NUM_ICMPV6); + +#ifdef DEBUG_ENABLED + char addr_str[IPV6_MAX_ADDR_STR_LEN]; + printf("INFO: send neighbor advertisement to: %s\n", + ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, + &ipv6_buf->destaddr)); +#endif + ipv6_send_packet(ipv6_buf); } void recv_nbr_adv(void) { + int if_id = 0; // TODO, get this somehow ipv6_buf = ipv6_get_buf(); - uint16_t packet_length = IPV6_HDR_LEN + ipv6_buf->length; + uint16_t packet_length = IPV6_HDR_LEN + NTOHS(ipv6_buf->length); icmpv6_opt_hdr_len = NBR_ADV_LEN; llao = NULL; nbr_entry = NULL; @@ -1211,16 +1303,16 @@ void recv_nbr_adv(void) icmpv6_opt_hdr_len += (opt_buf->length * 8); } - addr_list_t *addr; - addr = ipv6_iface_addr_match(&nbr_adv_buf->target_addr); + ipv6_net_if_hit_t hit; - if (addr == NULL) { + if (ipv6_net_if_addr_match(&hit, &nbr_adv_buf->target_addr) == NULL) { nbr_entry = ndp_neighbor_cache_search(&nbr_adv_buf->target_addr); if (nbr_entry != NULL) { if (llao != 0) { - /* TODO: untersheiden zwischen short und long stllao option */ - new_ll = memcmp(&llao[2], &(nbr_entry->laddr), 8); + new_ll = memcmp(&llao[2], &(nbr_entry->lladdr), + nbr_entry->lladdr_len); + ((icmpv6_ndp_opt_stllao_t *)llao)->length = nbr_entry->lladdr_len / 8 + 1; } if (nbr_entry->state == NDP_NCE_STATUS_INCOMPLETE) { @@ -1228,8 +1320,19 @@ void recv_nbr_adv(void) return; } - /* TODO: untersheiden zwischen short und long stllao option */ - memcpy(&nbr_entry->laddr, &llao[2], 8); + if (((icmpv6_ndp_opt_stllao_t *)llao)->length == 2) { + nbr_entry->if_id = if_id; + nbr_entry->lladdr_len = 8; + memcpy(&nbr_entry->lladdr, &llao[2], nbr_entry->lladdr_len); + } + else if (((icmpv6_ndp_opt_stllao_t *)llao)->length == 1) { + nbr_entry->if_id = if_id; + nbr_entry->lladdr_len = 2; + memcpy(&nbr_entry->lladdr, &llao[2], nbr_entry->lladdr_len); + } + else { + return; + } if (nbr_adv_buf->rso & ICMPV6_NEIGHBOR_ADV_FLAG_SOLICITED) { nbr_entry->state = NDP_NCE_STATUS_REACHABLE; @@ -1254,7 +1357,19 @@ void recv_nbr_adv(void) (!(nbr_adv_buf->rso & ICMPV6_NEIGHBOR_ADV_FLAG_OVERRIDE) && llao != 0 && !new_ll)) { if (llao != 0) { - memcpy(&nbr_entry->laddr, &llao[2], 8); + if (((icmpv6_ndp_opt_stllao_t *)llao)->length == 2) { + nbr_entry->if_id = if_id; + nbr_entry->lladdr_len = 8; + } + else if (((icmpv6_ndp_opt_stllao_t *)llao)->length == 1) { + nbr_entry->if_id = if_id; + nbr_entry->lladdr_len = 2; + } + else { + return; + } + + memcpy(&nbr_entry->lladdr, &llao[2], nbr_entry->lladdr_len); } if (nbr_adv_buf->rso & ICMPV6_NEIGHBOR_ADV_FLAG_SOLICITED) { @@ -1274,7 +1389,8 @@ void recv_nbr_adv(void) } /* link-layer address option - RFC4861 section 4.6.1/ RFC4944 8. */ -void icmpv6_ndp_set_sllao(icmpv6_ndp_opt_stllao_t *sllao, uint8_t type, uint8_t length) +void icmpv6_ndp_set_sllao(icmpv6_ndp_opt_stllao_t *sllao, int if_id, + uint8_t type, uint8_t length) { sllao->type = type; sllao->length = length; @@ -1284,17 +1400,34 @@ void icmpv6_ndp_set_sllao(icmpv6_ndp_opt_stllao_t *sllao, uint8_t type, uint8_t /* get link layer address */ switch (length) { case (1): { - memcpy(&llao[2], &(iface.saddr), 2); - memset(&llao[4], 0, 4); - break; + uint16_t addr = net_if_get_hardware_address(if_id); + + if (addr != 0) { + addr = HTONS(addr); + memcpy(&llao[2], &addr, 2); + memset(&llao[4], 0, 4); + break; + } + else { + goto SET_SLLAO_DEFAULT; + } } case (2): { - memcpy(&llao[2], &(iface.laddr), 8); - memset(&llao[10], 0, 6); - break; + net_if_eui64_t addr; + + if (net_if_get_eui64(&addr, if_id, 0)) { + memcpy(&llao[2], &addr, 8); + memset(&llao[10], 0, 6); + break; + } + else { + goto SET_SLLAO_DEFAULT; + } } + SET_SLLAO_DEFAULT: + default: { printf("ERROR: llao not set\n"); break; @@ -1350,6 +1483,14 @@ void icmpv6_send_parameter_prob(ipv6_addr_t *src, ipv6_addr_t *dest, icmp_buf->checksum = 0; icmp_buf->checksum = ~icmpv6_csum(IPV6_PROTO_NUM_ICMPV6); + +#ifdef DEBUG_ENABLED + char addr_str[IPV6_MAX_ADDR_STR_LEN]; + printf("INFO: send parameter problem to: %s\n", + ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, + &ipv6_buf->destaddr)); +#endif + ipv6_send_packet(ipv6_buf); } //------------------------------------------------------------------------------ @@ -1368,21 +1509,64 @@ ndp_neighbor_cache_t *ndp_neighbor_cache_search(ipv6_addr_t *ipaddr) return NULL; } -uint8_t nbr_cache_add(ipv6_addr_t *ipaddr, ieee_802154_long_t *laddr, - uint8_t isrouter, ndp_nce_state_t state, - ndp_nce_type_t type, uint16_t ltime, - ieee_802154_short_t *saddr) +ndp_neighbor_cache_t *ndp_get_ll_address(ipv6_addr_t *ipaddr) +{ + ndp_neighbor_cache_t *nce = ndp_neighbor_cache_search(ipaddr); + + if (nce == NULL || nce->type == NDP_NCE_TYPE_GC || + nce->state == NDP_NCE_STATUS_INCOMPLETE) { + // TODO: send neighbor solicitation, wait, and recheck cache + return NULL; + } + + return nce; +} + +int ndp_addr_is_on_link(ipv6_addr_t *dest_addr) +{ + ndp_prefix_info_t *pi; + ndp_neighbor_cache_t *nce; + int if_id = -1; + + if (ipv6_addr_is_link_local(dest_addr)) { + return 1; + } + + if ((nce = ndp_neighbor_cache_search(dest_addr))) { + return 1; + } + + while ((if_id = net_if_iter_interfaces(if_id)) >= 0) { + if ((pi = ndp_prefix_info_search(if_id, dest_addr, 128))) { + return (pi->flags & ICMPV6_NDP_OPT_PI_FLAG_ON_LINK) != 0; + } + } + + /* TODO Other cases (http://tools.ietf.org/html/rfc4861#page-6): + * * neighboring router specifies address as target of + * redircect message + * * neighbor discovery message is received from address. + */ + + return 0; +} + +uint8_t ndp_neighbor_cache_add(int if_id, const ipv6_addr_t *ipaddr, + const void *lladdr, uint8_t lladdr_len, + uint8_t isrouter, ndp_nce_state_t state, + ndp_nce_type_t type, uint16_t ltime) { (void) ltime; - (void) saddr; if (nbr_count == NBR_CACHE_SIZE) { printf("ERROR: neighbor cache full\n"); return NDP_OPT_ARO_STATE_NBR_CACHE_FULL; } + nbr_cache[nbr_count].if_id = if_id; memcpy(&(nbr_cache[nbr_count].addr), ipaddr, 16); - memcpy(&(nbr_cache[nbr_count].laddr), laddr, 8); + memcpy(&(nbr_cache[nbr_count].lladdr), lladdr, lladdr_len); + nbr_cache[nbr_count].lladdr_len = lladdr_len; nbr_cache[nbr_count].isrouter = isrouter; nbr_cache[nbr_count].state = state; nbr_cache[nbr_count].type = type; @@ -1572,23 +1756,115 @@ void def_rtr_lst_rem(ndp_default_router_list_t *entry) } //------------------------------------------------------------------------------ -/* prefix list functions */ +/* prefix information functions */ -int plist_add(ipv6_addr_t *addr, uint8_t size, uint32_t val_ltime, - uint32_t pref_ltime, uint8_t adv_opt, uint8_t l_a_reserved1) +int ndp_add_prefix_info(int if_id, const ipv6_addr_t *prefix, + uint8_t prefix_len, uint32_t valid_lifetime, + uint32_t preferred_lifetime, uint8_t advertisable, + uint8_t flags) { - if (prefix_count == OPT_PI_LIST_LEN) { - return SIXLOWERROR_ARRAYFULL; - } - else { - plist[prefix_count].inuse = 1; - plist[prefix_count].length = size; - plist[prefix_count].adv = adv_opt; - plist[prefix_count].l_a_reserved1 = l_a_reserved1; - plist[prefix_count].val_ltime = HTONL(val_ltime); - plist[prefix_count].pref_ltime = HTONL(pref_ltime); - memcpy(&(plist[prefix_count].addr.uint8[0]), &(addr->uint8[0]), 16); + ndp_prefix_info_t *prefix_info = ndp_prefix_info_match(if_id, prefix, + prefix_len); + + if (prefix_info) { + prefix_info->inuse = 1; + prefix_info->advertisable = advertisable; + prefix_info->flags = 0xc0 & flags; + prefix_info->valid_lifetime = HTONL(valid_lifetime); + prefix_info->preferred_lifetime = HTONL(preferred_lifetime); return SIXLOWERROR_SUCCESS; } + + if ((prefix_info_count >= PREFIX_BUF_LEN) || + (prefix_buf_count >= sizeof(prefix_buf))) { + return SIXLOWERROR_ARRAYFULL; + } + + if (prefix_len > 128) { + prefix_len = 128; + } + + prefix_info = &prefix_info_buf[prefix_info_count]; + + if (prefix_len > 0) { + memcpy(&prefix_buf[prefix_buf_count], prefix, (prefix_len / 8) + 1); + } + + prefix_info->prefix_data = (ipv6_addr_t *) &prefix_buf[prefix_buf_count]; + prefix_buf_count += prefix_len; + + prefix_info->prefix_len = prefix_len; + prefix_info->prefix_protocol = NET_IF_L3P_IPV6_PREFIX; + prefix_info->inuse = 1; + prefix_info->advertisable = advertisable; + prefix_info->flags = 0xc0 & flags; + prefix_info->valid_lifetime = HTONL(valid_lifetime); + prefix_info->preferred_lifetime = HTONL(preferred_lifetime); + + if (!net_if_add_address(if_id, (net_if_addr_t *) prefix_info)) { + return SIXLOWERROR_VALUE; + } + + prefix_info_count++; + + return SIXLOWERROR_SUCCESS; +} + +ndp_prefix_info_t *ndp_prefix_info_search(int if_id, const ipv6_addr_t *addr, + uint8_t up_to) +{ + uint8_t best_match = 0; + ndp_prefix_info_t *prefix = NULL, *tmp = NULL; + + if (up_to > 128) { + up_to = 128; + } + + while (net_if_iter_addresses(if_id, (net_if_addr_t **) &prefix)) { + if (prefix->prefix_protocol & NET_IF_L3P_IPV6_PREFIX) { + uint8_t match = 0, len = min(up_to, prefix->prefix_len); + uint8_t byte_len = (len / 8); + + for (int i = 0; i < byte_len; i++) { + if (addr->uint8[i] != prefix->prefix_data->uint8[i]) { + break; + } + + match += 8; + } + + if (byte_len < 16) { + for (int i = len % 8; i > 0; i--) { + if (addr->uint8[byte_len] >> i != + prefix->prefix_data->uint8[byte_len] >> i) { + break; + } + + match += 1; + } + } + + if (prefix->prefix_len == 0 && match > best_match) { + tmp = prefix; + best_match = match; + } + } + } + + return tmp; +} + +ndp_prefix_info_t *ndp_prefix_info_match(int if_id, const ipv6_addr_t *prefix, + uint8_t prefix_len) +{ + ndp_prefix_info_t *res = ndp_prefix_info_search(if_id, prefix, + prefix_len); + + if (res != NULL && res->prefix_len == prefix_len) { + return res; + } + else { + return NULL; + } } diff --git a/sys/net/network_layer/sixlowpan/icmp.h b/sys/net/network_layer/sixlowpan/icmp.h index 6cb502d3fe..a8fcf12f15 100644 --- a/sys/net/network_layer/sixlowpan/icmp.h +++ b/sys/net/network_layer/sixlowpan/icmp.h @@ -42,7 +42,7 @@ enum option_types_t { OPT_DAC, }; -extern unsigned int nd_nbr_cache_rem_pid; +extern int nd_nbr_cache_rem_pid; void recv_echo_req(void); @@ -53,9 +53,6 @@ void recv_nbr_adv(void); void recv_nbr_sol(void); void nbr_cache_auto_rem(void); -int plist_add(ipv6_addr_t *addr, uint8_t size, uint32_t val_ltime, - uint32_t pref_ltime, uint8_t adv_opt, uint8_t l_a_reserved1); - ndp_a6br_cache_t *abr_add_context(uint16_t version, ipv6_addr_t *abr_addr, uint8_t cid); void abr_remove_context(uint8_t cid); diff --git a/sys/net/network_layer/sixlowpan/ip.c b/sys/net/network_layer/sixlowpan/ip.c index 5b2e453836..bf7f31ddbc 100644 --- a/sys/net/network_layer/sixlowpan/ip.c +++ b/sys/net/network_layer/sixlowpan/ip.c @@ -25,6 +25,7 @@ #include "vtimer.h" #include "mutex.h" #include "msg.h" +#include "net_help.h" #include "net_if.h" #include "sixlowpan/mac.h" @@ -32,17 +33,18 @@ #include "icmp.h" #include "lowpan.h" -#include "destiny/socket.h" #include "net_help.h" #define ENABLE_DEBUG (0) #if ENABLE_DEBUG +#define DEBUG_ENABLED char addr_str[IPV6_MAX_ADDR_STR_LEN]; #endif #include "debug.h" #define IP_PKT_RECV_BUF_SIZE (64) #define LLHDR_IPV6HDR_LEN (LL_HDR_LEN + IPV6_HDR_LEN) +#define IPV6_NET_IF_ADDR_BUFFER_LEN (NET_IF_MAX * IPV6_NET_IF_ADDR_LIST_LEN) uint8_t ip_send_buffer[BUFFER_SIZE]; uint8_t buffer[BUFFER_SIZE]; @@ -51,34 +53,79 @@ ipv6_hdr_t *ipv6_buf; icmpv6_hdr_t *icmp_buf; uint8_t *nextheader; -uint8_t iface_addr_list_count = 0; int udp_packet_handler_pid = 0; int tcp_packet_handler_pid = 0; int rpl_process_pid = 0; ipv6_addr_t *(*ip_get_next_hop)(ipv6_addr_t *) = 0; +static ipv6_net_if_ext_t ipv6_net_if_ext[NET_IF_MAX]; +static ipv6_net_if_addr_t ipv6_net_if_addr_buffer[IPV6_NET_IF_ADDR_BUFFER_LEN]; +static ipv6_addr_t ipv6_addr_buffer[IPV6_NET_IF_ADDR_BUFFER_LEN]; +static uint8_t ipv6_net_if_addr_buffer_count = 0; + static uint8_t default_hop_limit = MULTIHOP_HOPLIMIT; /* registered upper layer threads */ int sixlowip_reg[SIXLOWIP_MAX_REGISTERED]; -int ipv6_send_packet(ipv6_hdr_t *bytes) +int ipv6_send_packet(ipv6_hdr_t *packet) { - int if_id = 0; - uint16_t offset = IPV6_HDR_LEN + HTONS(bytes->length); + uint16_t length = IPV6_HDR_LEN + NTOHS(packet->length); + ndp_neighbor_cache_t *nce; - bytes->flowlabel = HTONS(bytes->flowlabel); - bytes->length = HTONS(bytes->length); + ipv6_net_if_get_best_src_addr(&packet->srcaddr, &packet->destaddr); - memset(bytes, 0, BUFFER_SIZE); - memcpy(bytes + LL_HDR_LEN, bytes, offset); + if (!ipv6_addr_is_multicast(&packet->destaddr) && + ndp_addr_is_on_link(&packet->destaddr)) { + nce = ndp_get_ll_address(&packet->destaddr); - if (sixlowpan_lowpan_sendto(nce->if_id, &nce->lladdr, nce->lladdr_len, - (uint8_t *)packet, length) < 0) { - return -1; + + if (nce == NULL || sixlowpan_lowpan_sendto(nce->if_id, &nce->lladdr, + nce->lladdr_len, + (uint8_t *)packet, + length) < 0) { + /* XXX: this is wrong, but until ND does not work correctly, + * this is the only way (aka the old way)*/ + uint16_t raddr = NTOHS(packet->destaddr.uint16[7]); + sixlowpan_lowpan_sendto(0, &raddr, 2, (uint8_t *)packet, length); + /* return -1; */ + } + + return length; } + else { + /* see if dest should be routed to a different next hop */ + if (ipv6_addr_is_multicast(&packet->destaddr)) { + /* if_id will be ignored */ + uint16_t addr = 0xffff; + return sixlowpan_lowpan_sendto(0, &addr, 2, (uint8_t *)packet, + length); + } - return length; + if (ip_get_next_hop == NULL) { + return -1; + } + + ipv6_addr_t *dest = ip_get_next_hop(&packet->destaddr); + + if (dest == NULL) { + return -1; + } + + nce = ndp_get_ll_address(&packet->destaddr); + + if (nce == NULL || sixlowpan_lowpan_sendto(nce->if_id, &nce->lladdr, + nce->lladdr_len, + (uint8_t *)packet, length) < 0) { + /* XXX: this is wrong, but until ND does not work correctly, + * this is the only way (aka the old way)*/ + uint16_t raddr = NTOHS(packet->destaddr.uint16[7]); + sixlowpan_lowpan_sendto(0, &raddr, 2, (uint8_t *)packet, length); + /* return -1; */ + } + + return length; + } } ipv6_hdr_t *ipv6_get_buf_send(void) @@ -110,7 +157,6 @@ int ipv6_sendto(const ipv6_addr_t *dest, uint8_t next_header, const uint8_t *payload, uint16_t payload_length) { uint8_t *p_ptr; - uint16_t packet_length; if (next_header == IPV6_PROTO_NUM_TCP) { p_ptr = get_payload_buf_send(ipv6_ext_hdr_len); @@ -125,32 +171,14 @@ int ipv6_sendto(const ipv6_addr_t *dest, uint8_t next_header, ipv6_buf->trafficclass_flowlabel = 0; ipv6_buf->flowlabel = 0; ipv6_buf->nextheader = next_header; - ipv6_buf->hoplimit = default_hop_limit; - ipv6_buf->length = payload_length; + ipv6_buf->hoplimit = MULTIHOP_HOPLIMIT; + ipv6_buf->length = HTONS(payload_length); memcpy(&(ipv6_buf->destaddr), dest, 16); - ipv6_iface_get_best_src_addr(&(ipv6_buf->srcaddr), &(ipv6_buf->destaddr)); memcpy(p_ptr, payload, payload_length); - packet_length = IPV6_HDR_LEN + payload_length; - - /* see if dest should be routed to a different next hop */ - if (ip_get_next_hop == NULL || ipv6_addr_is_multicast(&ipv6_buf->destaddr)) { - dest = &ipv6_buf->destaddr; - } - else { - dest = ip_get_next_hop(&ipv6_buf->destaddr); - } - - if (dest == NULL) { - return -1; - } - - sixlowpan_lowpan_sendto(0, &dest->uint16[4], 8, - (uint8_t *)ipv6_buf, packet_length); - - return payload_length; + return ipv6_send_packet(ipv6_buf); } void ipv6_set_default_hop_limit(uint8_t hop_limit) @@ -278,19 +306,40 @@ uint8_t ipv6_get_addr_match(const ipv6_addr_t *src, return val; } +int is_our_address(ipv6_addr_t *addr) +{ + ipv6_net_if_ext_t *net_if_ext; + ipv6_net_if_addr_t *myaddr; + uint8_t prefix, suffix; + int if_id = -1; + + while ((if_id = net_if_iter_interfaces(if_id)) >= 0) { + net_if_ext = ipv6_net_if_get_ext(if_id); + myaddr = NULL; + prefix = net_if_ext->prefix / 8; + suffix = IPV6_ADDR_LEN - prefix; + + while ((myaddr = (ipv6_net_if_addr_t *)net_if_iter_addresses(if_id, + (net_if_addr_t **) &myaddr)) != NULL) { + if ((ipv6_get_addr_match(myaddr->addr_data, addr) >= net_if_ext->prefix) && + (memcmp(&addr->uint8[prefix], &myaddr->addr_data->uint8[prefix], suffix) == 0)) { + return 1; + } + } + } + + return 0; +} + void ipv6_process(void) { msg_t m_recv_lowpan, m_send_lowpan; msg_t m_recv, m_send; - ipv6_addr_t myaddr; uint8_t i; uint16_t packet_length; msg_init_queue(ip_msg_queue, IP_PKT_RECV_BUF_SIZE); - ipv6_addr_init(&myaddr, 0xabcd, 0x0, 0x0, 0x0, 0x3612, 0x00ff, 0xfe00, - sixlowpan_mac_get_radio_address()); - while (1) { msg_receive(&m_recv_lowpan); @@ -308,40 +357,16 @@ void ipv6_process(void) } } - /* destination is foreign address */ - if ((ipv6_get_addr_match(&myaddr, &ipv6_buf->destaddr) >= 112) && - (ipv6_buf->destaddr.uint8[15] != myaddr.uint8[15])) { - packet_length = IPV6_HDR_LEN + ipv6_buf->length; - - ipv6_addr_t *dest; - - if (ip_get_next_hop == NULL) { - dest = &ipv6_buf->destaddr; - } - else { - dest = ip_get_next_hop(&ipv6_buf->destaddr); - } - - if (dest == NULL || --ipv6_buf->hoplimit == 0) { - continue; - } - - /* copy received packet to send buffer */ - memcpy(ipv6_get_buf_send(), ipv6_get_buf(), packet_length); - /* send packet to node ID derived from dest IP */ - sixlowpan_lowpan_sendto((ieee_802154_long_t *) &dest->uint16[4], - (uint8_t *)ipv6_get_buf_send(), - packet_length); - } /* destination is our address */ - else { + if (is_our_address(&ipv6_buf->destaddr)) { switch (*nextheader) { case (IPV6_PROTO_NUM_ICMPV6): { icmp_buf = get_icmpv6_buf(ipv6_ext_hdr_len); /* checksum test*/ - if (ipv6_csum(ipv6_buf, (uint8_t *) icmp_buf, ipv6_buf->length, IPV6_PROTO_NUM_ICMPV6) != 0xffff) { - printf("ERROR: wrong checksum\n"); + if (ipv6_csum(ipv6_buf, (uint8_t *) icmp_buf, NTOHS(ipv6_buf->length), + IPV6_PROTO_NUM_ICMPV6) != 0xffff) { + DEBUG("ERROR: wrong checksum\n"); } icmpv6_demultiplex(icmp_buf); @@ -354,7 +379,7 @@ void ipv6_process(void) msg_send_receive(&m_send, &m_recv, tcp_packet_handler_pid); } else { - printf("INFO: No TCP handler registered.\n"); + DEBUG("INFO: No TCP handler registered.\n"); } break; @@ -366,14 +391,14 @@ void ipv6_process(void) msg_send_receive(&m_send, &m_recv, udp_packet_handler_pid); } else { - printf("INFO: No UDP handler registered.\n"); + DEBUG("INFO: No UDP handler registered.\n"); } break; } case (IPV6_PROTO_NUM_NONE): { - printf("INFO: Packet with no Header following the IPv6 Header received.\n"); + DEBUG("INFO: Packet with no Header following the IPv6 Header received.\n"); break; } @@ -381,97 +406,205 @@ void ipv6_process(void) break; } } + /* destination is foreign address */ + else { + packet_length = IPV6_HDR_LEN + NTOHS(ipv6_buf->length); + ndp_neighbor_cache_t *nce; + + ipv6_addr_t *dest; + + if (ip_get_next_hop == NULL) { + dest = &ipv6_buf->destaddr; + } + else { + dest = ip_get_next_hop(&ipv6_buf->destaddr); + } + + if ((dest == NULL) || ((--ipv6_buf->hoplimit) == 0)) { + continue; + } + + nce = ndp_get_ll_address(dest); + + /* copy received packet to send buffer */ + memcpy(ipv6_get_buf_send(), ipv6_get_buf(), packet_length); + + /* send packet to node ID derived from dest IP */ + if (nce != NULL) { + sixlowpan_lowpan_sendto(nce->if_id, &nce->lladdr, + nce->lladdr_len, + (uint8_t *)ipv6_get_buf_send(), + packet_length); + } + } msg_reply(&m_recv_lowpan, &m_send_lowpan); } } -void ipv6_iface_add_addr(const ipv6_addr_t *addr, ipv6_addr_type_t type, - ndp_addr_state_t state, uint32_t val_ltime, - uint32_t pref_ltime) +ipv6_net_if_ext_t *ipv6_net_if_get_ext(int if_id) { + if (net_if_get_interface(if_id)) { + return &ipv6_net_if_ext[if_id]; + } + else { + return NULL; + } +} + +int ipv6_net_if_add_addr(int if_id, const ipv6_addr_t *addr, + ndp_addr_state_t state, uint32_t val_ltime, + uint32_t pref_ltime, uint8_t is_anycast) +{ + ipv6_net_if_addr_t *addr_entry; + ipv6_net_if_hit_t hit; + if (ipv6_addr_is_unspecified(addr) == 128) { - printf("ERROR: unspecified address (::) can't be assigned to interface.\n"); - return; + DEBUG("ERROR: unspecified address (::) can't be assigned to interface.\n"); + return 0; } - if (ipv6_iface_addr_match(addr) != 0) { - return; + if (ipv6_addr_is_multicast(addr) && is_anycast) { + DEBUG("ERROR: anycast addresses must not be multicast addresses " + "(i.e. start with ff::/2)\n"); + return 0; } - if (iface_addr_list_count < IFACE_ADDR_LIST_LEN) { - memcpy(&(iface.addr_list[iface_addr_list_count].addr.uint8[0]), - &(addr->uint8[0]), 16); - iface.addr_list[iface_addr_list_count].state = state; + if (ipv6_net_if_addr_match(&hit, addr)) { + return 1; + } + + if (ipv6_net_if_addr_buffer_count < IPV6_NET_IF_ADDR_BUFFER_LEN) { timex_t valtime = {val_ltime, 0}; timex_t preftime = {pref_ltime, 0}; timex_t now; + vtimer_now(&now); - iface.addr_list[iface_addr_list_count].val_ltime = timex_add(now, valtime); - iface.addr_list[iface_addr_list_count].pref_ltime = timex_add(now, preftime); - iface.addr_list[iface_addr_list_count].type = type; - iface_addr_list_count++; + + ipv6_addr_t *addr_data = &ipv6_addr_buffer[ipv6_net_if_addr_buffer_count]; + memcpy(addr_data, addr, sizeof(ipv6_addr_t)); + + addr_entry = &ipv6_net_if_addr_buffer[ipv6_net_if_addr_buffer_count]; + addr_entry->addr_data = addr_data; + addr_entry->addr_len = 128; + + if (is_anycast) { + addr_entry->addr_protocol = NET_IF_L3P_IPV6_ANYCAST; + } + else if (ipv6_addr_is_multicast(addr_data)) { + addr_entry->addr_protocol = NET_IF_L3P_IPV6_MULTICAST; + } + else { + addr_entry->addr_protocol = NET_IF_L3P_IPV6_UNICAST; + } + + addr_entry->ndp_state = state; + addr_entry->valid_lifetime = timex_add(now, valtime); + addr_entry->preferred_lifetime = timex_add(now, preftime); + addr_entry->is_anycast = is_anycast; + + ipv6_net_if_addr_buffer_count++; + + net_if_add_address(if_id, (net_if_addr_t *)addr_entry); /* Register to Solicited-Node multicast address according to RFC 4291 */ - if (type == IPV6_ADDR_TYPE_ANYCAST || type == IPV6_ADDR_TYPE_LINK_LOCAL || - type == IPV6_ADDR_TYPE_GLOBAL || type == IPV6_ADDR_TYPE_UNICAST) { + if (is_anycast || !ipv6_addr_is_multicast(addr)) { ipv6_addr_t sol_node_mcast_addr; ipv6_addr_set_solicited_node_addr(&sol_node_mcast_addr, addr); - if (ipv6_iface_addr_match(&sol_node_mcast_addr) == NULL) { - ipv6_iface_add_addr(&sol_node_mcast_addr, - IPV6_ADDR_TYPE_SOLICITED_NODE, - state, val_ltime, pref_ltime); + if (ipv6_net_if_addr_match(&hit, &sol_node_mcast_addr) == NULL) { + ipv6_net_if_add_addr(if_id, &sol_node_mcast_addr, state, + val_ltime, pref_ltime, 0); + } + } + + return 1; + } + + return 0; +} + +ipv6_net_if_hit_t *ipv6_net_if_addr_match(ipv6_net_if_hit_t *hit, + const ipv6_addr_t *addr) +{ + int if_id = -1; + ipv6_net_if_addr_t *addr_entry = NULL; + + while ((if_id = net_if_iter_interfaces(if_id)) >= 0) { + while (net_if_iter_addresses(if_id, (net_if_addr_t **) &addr_entry) != NULL) { + if (addr_entry->addr_protocol & NET_IF_L3P_IPV6) { + uint8_t byte_al = addr_entry->addr_len / 8; + uint8_t mask[] = {0x00, 0x80, 0xc0, 0xe0, + 0xf0, 0xf8, 0xfc, 0xfe + }; + + if (memcmp(addr_entry->addr_data, addr, byte_al) == 0 && + (addr_entry->addr_len % 8 == 0 || + ((addr_entry->addr_data->uint8[byte_al] - addr->uint8[byte_al]) & mask[addr_entry->addr_len - (byte_al * 8)]))) { + hit->if_id = if_id; + hit->addr = addr_entry; + return hit; + } } } } + + return NULL; } -addr_list_t *ipv6_iface_addr_match(const ipv6_addr_t *addr) +ipv6_net_if_hit_t *ipv6_net_if_addr_prefix_eq(ipv6_net_if_hit_t *hit, + ipv6_addr_t *addr) { - int i; + int if_id = -1; + ipv6_net_if_addr_t *addr_entry = NULL; - for (i = 0; i < iface_addr_list_count; i++) { - if (memcmp(&(iface.addr_list[i].addr.uint8[0]), - &(addr->uint8[0]), 16) == 0) { - return &(iface.addr_list[i]); + while ((if_id = net_if_iter_interfaces(if_id)) >= 0) { + while (net_if_iter_addresses(if_id, (net_if_addr_t **) &addr_entry) != NULL) { + if (addr_entry->addr_protocol & NET_IF_L3P_IPV6) { + if (memcmp(addr_entry->addr_data, &addr, 8) == 0) { + hit->if_id = if_id; + hit->addr = addr_entry; + return hit; + } + } } } return NULL; } -addr_list_t *ipv6_iface_addr_prefix_eq(ipv6_addr_t *addr) -{ - int i; - - for (i = 0; i < iface_addr_list_count; i++) { - if (memcmp(&(iface.addr_list[i].addr.uint8[0]), - &(addr->uint8[0]), 8) == 0) { - return &(iface.addr_list[i]); - } - } - - return NULL; -} - -void ipv6_iface_print_addrs(void) -{ - for (int i = 0; i < iface_addr_list_count; i++) { - char addr_str[IPV6_MAX_ADDR_STR_LEN]; - printf("%s\n", ipv6_addr_to_str(addr_str, - &(iface.addr_list[i].addr))); - } -} - -void ipv6_addr_set_by_eui64(ipv6_addr_t *out, const ipv6_addr_t *prefix) +/* TODO ipv6_net_if_hit_t returning function similar wrapping + * ipv6_net_if_get_best_src_addr() to search on all interfaces */ + +ipv6_addr_t *ipv6_addr_set_by_eui64(ipv6_addr_t *out, int if_id, + const ipv6_addr_t *prefix) { + uint8_t force_generation = 0; out->uint16[0] = prefix->uint16[0]; out->uint16[1] = prefix->uint16[1]; out->uint16[2] = prefix->uint16[2]; out->uint16[3] = prefix->uint16[3]; - memcpy(&(out->uint8[8]), &(iface.laddr.uint8[0]), 8); + if (net_if_get_src_address_mode(if_id) == NET_IF_TRANS_ADDR_M_SHORT) { + force_generation = 1; + } + + if (net_if_get_eui64((net_if_eui64_t *) &out->uint8[8], if_id, + force_generation)) { +#ifdef MODULE_SIXLOWPAN + + if (!sixlowpan_lowpan_eui64_to_short_addr((net_if_eui64_t *)&out->uint8[8])) { + out->uint8[8] ^= 0x02; + } + +#else + out->uint8[8] ^= 0x02; +#endif + return out; + } + else { + return NULL; + } } void ipv6_addr_init_prefix(ipv6_addr_t *out, const ipv6_addr_t *prefix, @@ -496,96 +629,51 @@ void ipv6_addr_init_prefix(ipv6_addr_t *out, const ipv6_addr_t *prefix, out->uint8[bytes] = prefix->uint8[bytes] & mask; } -void ipv6_addr_set_all_routers_addr(ipv6_addr_t *ipv6_addr) -{ - ipv6_addr->uint16[0] = HTONS(0xff02); - ipv6_addr->uint16[1] = 0; - ipv6_addr->uint16[2] = 0; - ipv6_addr->uint16[3] = 0; - ipv6_addr->uint16[4] = 0; - ipv6_addr->uint16[5] = 0; - ipv6_addr->uint16[6] = 0; - ipv6_addr->uint16[7] = HTONS(0x0002); -} - -void ipv6_addr_set_all_nodes_addr(ipv6_addr_t *ipv6_addr) -{ - ipv6_addr->uint16[0] = HTONS(0xff02); - ipv6_addr->uint16[1] = 0; - ipv6_addr->uint16[2] = 0; - ipv6_addr->uint16[3] = 0; - ipv6_addr->uint16[4] = 0; - ipv6_addr->uint16[5] = 0; - ipv6_addr->uint16[6] = 0; - ipv6_addr->uint16[7] = HTONS(0x0001); -} - -void ipv6_addr_set_loopback_addr(ipv6_addr_t *ipv6_addr) -{ - ipv6_addr->uint16[0] = 0; - ipv6_addr->uint16[1] = 0; - ipv6_addr->uint16[2] = 0; - ipv6_addr->uint16[3] = 0; - ipv6_addr->uint16[4] = 0; - ipv6_addr->uint16[5] = 0; - ipv6_addr->uint16[6] = 0; - ipv6_addr->uint16[7] = HTONS(0x0001); -} - -void ipv6_iface_get_best_src_addr(ipv6_addr_t *src, const ipv6_addr_t *dest) +void ipv6_net_if_get_best_src_addr(ipv6_addr_t *src, const ipv6_addr_t *dest) { /* try to find best match if dest is not mcast or link local */ - int8_t itmp = -1; + int if_id = 0; // TODO: get this somehow uint8_t tmp = 0; uint8_t bmatch = 0; + ipv6_net_if_addr_t *addr = NULL; + ipv6_net_if_addr_t *tmp_addr = NULL; if (!(ipv6_addr_is_link_local(dest)) && !(ipv6_addr_is_multicast(dest))) { - for (int i = 0; i < IFACE_ADDR_LIST_LEN; i++) { - if (iface.addr_list[i].state == NDP_ADDR_STATE_PREFERRED) { - if (!ipv6_addr_is_link_local(&(iface.addr_list[i].addr)) && - !ipv6_addr_is_multicast(&(iface.addr_list[i].addr)) && - !ipv6_addr_is_unique_local_unicast(&(iface.addr_list[i].addr))) { - tmp = ipv6_get_addr_match(dest, &(iface.addr_list[i].addr)); + while ((addr = (ipv6_net_if_addr_t *)net_if_iter_addresses(if_id, + (net_if_addr_t **)&addr))) { + if (addr->ndp_state == NDP_ADDR_STATE_PREFERRED) { + if (!ipv6_addr_is_link_local(addr->addr_data) && + !ipv6_addr_is_multicast(addr->addr_data) && + !ipv6_addr_is_unique_local_unicast(addr->addr_data)) { + tmp = ipv6_get_addr_match(dest, addr->addr_data); if (tmp >= bmatch) { bmatch = tmp; - itmp = i; + tmp_addr = addr; } } } } } else { - for (int j = 0; j < IFACE_ADDR_LIST_LEN; j++) { - if ((iface.addr_list[j].state == NDP_ADDR_STATE_PREFERRED) && - ipv6_addr_is_link_local(&(iface.addr_list[j].addr)) && - !ipv6_addr_is_multicast(&(iface.addr_list[j].addr))) { - itmp = j; + while ((addr = (ipv6_net_if_addr_t *)net_if_iter_addresses(if_id, + (net_if_addr_t **)&addr))) { + if (addr->ndp_state == NDP_ADDR_STATE_PREFERRED && + ipv6_addr_is_link_local(addr->addr_data) && + !ipv6_addr_is_multicast(addr->addr_data)) { + tmp_addr = addr; } } } - if (itmp == -1) { + if (tmp_addr == NULL) { memset(src, 0, 16); } else { - memcpy(src, &(iface.addr_list[itmp].addr), 16); + memcpy(src, tmp_addr->addr_data, 16); } } -int ipv6_addr_is_equal(const ipv6_addr_t *a, const ipv6_addr_t *b) -{ - return (ipv6_get_addr_match(a, b) == 128); -} - -void ipv6_addr_set_link_local_prefix(ipv6_addr_t *ipv6_addr) -{ - ipv6_addr->uint16[0] = HTONS(0xfe80); - ipv6_addr->uint16[1] = 0; - ipv6_addr->uint16[2] = 0; - ipv6_addr->uint16[3] = 0; -} - void ipv6_addr_init(ipv6_addr_t *out, uint16_t addr0, uint16_t addr1, uint16_t addr2, uint16_t addr3, uint16_t addr4, uint16_t addr5, uint16_t addr6, uint16_t addr7) @@ -600,66 +688,6 @@ void ipv6_addr_init(ipv6_addr_t *out, uint16_t addr0, uint16_t addr1, out->uint16[7] = HTONS(addr7); } -int ipv6_addr_is_link_local(const ipv6_addr_t *addr) -{ - return (addr->uint16[0] == HTONS(0xfe80)); -} - -int ipv6_addr_is_unique_local_unicast(const ipv6_addr_t *addr) -{ - return (addr->uint8[0] == 0xfc || addr->uint8[0] == 0xfd); -} - -int ipv6_addr_is_multicast(const ipv6_addr_t *addr) -{ - return (addr->uint8[0] == 0xff); -} - -int ipv6_addr_is_unspecified(const ipv6_addr_t *ipv6_addr) -{ - return (ipv6_addr->uint32[0] == 0) && (ipv6_addr->uint32[1] == 0) && - (ipv6_addr->uint32[2] == 0) && (ipv6_addr->uint32[3] == 0); -} - -int ipv6_addr_is_solicited_node(const ipv6_addr_t *ipv6_addr) -{ - return (ipv6_addr->uint8[0] == 0xFF) && - (ipv6_addr->uint8[1] == 0x02) && - (ipv6_addr->uint16[1] == 0x00) && - (ipv6_addr->uint16[2] == 0x00) && - (ipv6_addr->uint16[3] == 0x00) && - (ipv6_addr->uint16[4] == 0x00) && - (ipv6_addr->uint8[10] == 0x00) && - (ipv6_addr->uint8[11] == 0x01) && - (ipv6_addr->uint8[12] == 0xFF); -} - -void ipv6_addr_set_solicited_node_addr(ipv6_addr_t *ipv6_addr_out, - const ipv6_addr_t *ipv6_addr_in) -{ - /* copy only the last 24-bit of the ip-address that is beeing resolved */ - ipv6_addr_out->uint16[0] = HTONS(0xff02); - ipv6_addr_out->uint16[1] = 0; - ipv6_addr_out->uint16[2] = 0; - ipv6_addr_out->uint16[3] = 0; - ipv6_addr_out->uint16[4] = 0; - ipv6_addr_out->uint16[5] = HTONS(0x0001); - ipv6_addr_out->uint8[12] = 0xff; - ipv6_addr_out->uint8[13] = ipv6_addr_in->uint8[13]; - ipv6_addr_out->uint16[7] = ipv6_addr_in->uint16[7]; -} - -char *ipv6_addr_to_str(char *addr_str, const ipv6_addr_t *ipv6_addr) -{ - sprintf(addr_str, - "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x", - NTOHS(ipv6_addr->uint16[0]), NTOHS(ipv6_addr->uint16[1]), - NTOHS(ipv6_addr->uint16[2]), NTOHS(ipv6_addr->uint16[3]), - NTOHS(ipv6_addr->uint16[4]), NTOHS(ipv6_addr->uint16[5]), - NTOHS(ipv6_addr->uint16[6]), NTOHS(ipv6_addr->uint16[7])); - return addr_str; -} - uint32_t get_remaining_time(timex_t *t) { timex_t now; @@ -677,22 +705,32 @@ void set_remaining_time(timex_t *t, uint32_t time) *t = timex_add(now, tmp); } -void ipv6_init_iface_as_router(void) +int ipv6_init_as_router(void) { ipv6_addr_t addr; + int if_id = -1; ipv6_addr_set_all_routers_addr(&addr); - ipv6_iface_add_addr(&addr, NDP_ADDR_STATE_PREFERRED, 0, 0, IPV6_ADDR_TYPE_MULTICAST); + + while ((if_id = net_if_iter_interfaces(if_id)) >= 0) { + if (!ipv6_net_if_add_addr(if_id, &addr, NDP_ADDR_STATE_PREFERRED, 0, 0, + 0)) { + return 0; + } + } + + return 1; } uint8_t ipv6_is_router(void) { ipv6_addr_t addr; + ipv6_net_if_hit_t hit; ipv6_addr_set_all_routers_addr(&addr); - if (ipv6_iface_addr_match(&addr) != NULL) { + if (ipv6_net_if_addr_match(&hit, &addr) != NULL) { return 1; } @@ -741,8 +779,10 @@ uint16_t ipv6_csum(ipv6_hdr_t *ipv6_header, uint8_t *buf, uint16_t len, uint8_t { uint16_t sum = 0; DEBUG("Calculate checksum over src: %s, dst: %s, len: %04X, buf: %p, proto: %u\n", - ipv6_addr_to_str(addr_str, &ipv6_header->srcaddr), - ipv6_addr_to_str(addr_str, &ipv6_header->destaddr), + ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, + &ipv6_header->srcaddr), + ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, + &ipv6_header->destaddr), len, buf, proto); sum = len + proto; sum = csum(sum, (uint8_t *)&ipv6_header->srcaddr, 2 * sizeof(ipv6_addr_t)); diff --git a/sys/net/network_layer/sixlowpan/ip.h b/sys/net/network_layer/sixlowpan/ip.h index ec5ecf8291..740ef77b22 100644 --- a/sys/net/network_layer/sixlowpan/ip.h +++ b/sys/net/network_layer/sixlowpan/ip.h @@ -25,8 +25,10 @@ #include +#include "kernel.h" #include "timex.h" #include "mutex.h" +#include "net_if.h" #include "sixlowpan/ip.h" #include "sixlowpan/types.h" @@ -39,52 +41,61 @@ #define MULTIHOP_HOPLIMIT (64) #define SIXLOWIP_MAX_REGISTERED (4) +#define IP_PROCESS_STACKSIZE (KERNEL_CONF_STACKSIZE_MAIN) /* extern variables */ extern uint8_t ipv6_ext_hdr_len; +extern int ip_process_pid; /* base header lengths */ #define LL_HDR_LEN (0x4) #define ICMPV6_HDR_LEN (0x4) #define IPV6_HDR_LEN (0x28) -#define IFACE_ADDR_LIST_LEN (10) // maybe to much +#define IPV6_NET_IF_ADDR_LIST_LEN (10) // maybe to much /* buffer */ extern uint8_t buffer[BUFFER_SIZE]; +extern char ip_process_buf[IP_PROCESS_STACKSIZE]; extern int sixlowip_reg[SIXLOWIP_MAX_REGISTERED]; typedef struct __attribute__((packed)) { - ipv6_addr_t addr; - ipv6_addr_type_t type; - ndp_addr_state_t state; - timex_t val_ltime; - timex_t pref_ltime; -} addr_list_t; + struct net_if_addr_t *addr_next; + struct net_if_addr_t *addr_prev; + net_if_l3p_t addr_protocol; + ipv6_addr_t *addr_data; + uint8_t addr_len; + ndp_addr_state_t ndp_state; + timex_t valid_lifetime; + timex_t preferred_lifetime; + uint8_t is_anycast; +} ipv6_net_if_addr_t; typedef struct __attribute__((packed)) { - ieee_802154_short_t saddr; - ieee_802154_long_t laddr; - addr_list_t addr_list[IFACE_ADDR_LIST_LEN]; + ipv6_net_if_addr_t *addr; + int if_id; +} ipv6_net_if_hit_t; + +typedef struct __attribute__((packed)) { + uint8_t prefix; ///< prefix length of the sub-net uint8_t adv_cur_hop_limit; uint32_t adv_reachable_time; uint32_t adv_retrans_timer; -} iface_t; - -extern iface_t iface; +} ipv6_net_if_ext_t; /* function prototypes */ -void ipv6_send_bytes(ipv6_hdr_t *bytes); +ipv6_net_if_ext_t *ipv6_net_if_get_ext(int if_id); + icmpv6_hdr_t *get_icmpv6_buf(uint8_t ext_len); uint8_t *get_payload_buf(uint8_t ext_len); uint8_t *get_payload_buf_send(uint8_t ext_len); int icmpv6_demultiplex(const icmpv6_hdr_t *hdr); -void ipv6_init_iface_as_router(void); +int ipv6_init_as_router(void); void ipv6_process(void); -addr_list_t *ipv6_iface_addr_prefix_eq(ipv6_addr_t *addr); -addr_list_t *ipv6_iface_addr_match(const ipv6_addr_t *addr); +ipv6_net_if_hit_t *ipv6_net_if_addr_prefix_eq(ipv6_net_if_hit_t *hit, ipv6_addr_t *addr); +ipv6_net_if_hit_t *ipv6_net_if_addr_match(ipv6_net_if_hit_t *hit, const ipv6_addr_t *addr); uint32_t get_remaining_time(timex_t *t); void set_remaining_time(timex_t *t, uint32_t time); diff --git a/sys/net/network_layer/sixlowpan/lowpan.h b/sys/net/network_layer/sixlowpan/lowpan.h index 38830ae9b4..e1c1af1a00 100644 --- a/sys/net/network_layer/sixlowpan/lowpan.h +++ b/sys/net/network_layer/sixlowpan/lowpan.h @@ -25,6 +25,7 @@ #define _SIXLOWPAN_LOWPAN_H #include "mutex.h" +#include "net_if.h" #include "vtimer.h" #include "sixlowpan/lowpan.h" @@ -42,9 +43,8 @@ typedef struct { extern uint16_t local_address; extern mutex_t lowpan_context_mutex; -void lowpan_read(uint8_t *data, uint8_t length, - ieee_802154_long_t *s_laddr, - ieee_802154_long_t *d_laddr); +void lowpan_read(uint8_t *data, uint8_t length, net_if_eui64_t *s_addr, + net_if_eui64_t *d_addr); uint8_t lowpan_context_len(void); lowpan_context_t *lowpan_context_update(uint8_t num, const ipv6_addr_t *prefix, diff --git a/sys/net/routing/rpl/rpl.c b/sys/net/routing/rpl/rpl.c index a9a7d6fa3c..eb1535ec8f 100644 --- a/sys/net/routing/rpl/rpl.c +++ b/sys/net/routing/rpl/rpl.c @@ -191,15 +191,11 @@ rpl_of_t *rpl_get_of_for_ocp(uint16_t ocp) return NULL; } -uint8_t rpl_init(transceiver_type_t trans, uint16_t rpl_address) +uint8_t rpl_init(int if_id) { mutex_init(&rpl_send_mutex); mutex_init(&rpl_recv_mutex); - if (rpl_address == 0) { - return SIXLOWERROR_ADDRESS; - } - rpl_instances_init(); /* initialize routing table */ @@ -213,11 +209,15 @@ uint8_t rpl_init(transceiver_type_t trans, uint16_t rpl_address) objective_functions[0] = rpl_get_of0(); /* objective_functions[1] = rpl_get_of_ETX() */ - sixlowpan_lowpan_init(trans, rpl_address, 0); + if (!sixlowpan_lowpan_init()) { + return 0; + } + + sixlowpan_lowpan_init_interface(if_id); /* need link local prefix to query _our_ corresponding address */ ipv6_addr_t ll_address; ipv6_addr_set_link_local_prefix(&ll_address); - ipv6_iface_get_best_src_addr(&my_address, &ll_address); + ipv6_net_if_get_best_src_addr(&my_address, &ll_address); ipv6_register_rpl_handler(rpl_process_pid); /* initialize ETX-calculation if needed */ @@ -932,7 +932,7 @@ void rpl_send(ipv6_addr_t *destination, uint8_t *payload, uint16_t p_len, uint8_ ipv6_send_buf->length = HTONS(p_len); memcpy(&(ipv6_send_buf->destaddr), destination, 16); - ipv6_iface_get_best_src_addr(&(ipv6_send_buf->srcaddr), &(ipv6_send_buf->destaddr)); + ipv6_net_if_get_best_src_addr(&(ipv6_send_buf->srcaddr), &(ipv6_send_buf->destaddr)); icmp_send_buf = get_rpl_send_icmpv6_buf(ipv6_ext_hdr_len); icmp_send_buf->checksum = 0; diff --git a/sys/net/routing/rpl/rpl.h b/sys/net/routing/rpl/rpl.h index 31497afc7d..7ab6ef1a9d 100644 --- a/sys/net/routing/rpl/rpl.h +++ b/sys/net/routing/rpl/rpl.h @@ -35,7 +35,7 @@ #define RPL_PKT_RECV_BUF_SIZE 16 #define RPL_PROCESS_STACKSIZE KERNEL_CONF_STACKSIZE_DEFAULT -uint8_t rpl_init(transceiver_type_t trans, uint16_t rpl_address); +uint8_t rpl_init(int if_id); void rpl_init_root(void); rpl_of_t *rpl_get_of_for_ocp(uint16_t ocp); diff --git a/sys/net/routing/rpl/rpl_dodag.c b/sys/net/routing/rpl/rpl_dodag.c index 5c356f7d3c..7689237307 100644 --- a/sys/net/routing/rpl/rpl_dodag.c +++ b/sys/net/routing/rpl/rpl_dodag.c @@ -357,7 +357,9 @@ void rpl_join_dodag(rpl_dodag_t *dodag, ipv6_addr_t *parent, uint16_t parent_ran DEBUG("\tminhoprankincrease :\t%04X\n", my_dodag->minhoprankincrease); DEBUG("\tdefault_lifetime:\t%02X\n", my_dodag->default_lifetime); DEBUG("\tgrounded:\t%02X\n", my_dodag->grounded); - DEBUG("\tmy_preferred_parent:\t%s\n", ipv6_addr_to_str(addr_str, &my_dodag->my_preferred_parent->addr)); + DEBUG("\tmy_preferred_parent:\t%s\n", + ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, + &my_dodag->my_preferred_parent->addr)); DEBUG("\tmy_preferred_parent rank\t%02X\n", my_dodag->my_preferred_parent->rank); DEBUG("\tmy_preferred_parent lifetime\t%04X\n", my_dodag->my_preferred_parent->lifetime); diff --git a/sys/net/transport_layer/destiny/socket.c b/sys/net/transport_layer/destiny/socket.c index 2d267aaad3..627e0462ac 100644 --- a/sys/net/transport_layer/destiny/socket.c +++ b/sys/net/transport_layer/destiny/socket.c @@ -121,9 +121,11 @@ void print_tcp_status(int in_or_out, ipv6_hdr_t *ipv6_header, printf("--- %s TCP packet: ---\n", (in_or_out == INC_PACKET ? "Incoming" : "Outgoing")); printf("IPv6 Source: %s\n", - ipv6_addr_to_str(addr_str, &ipv6_header->srcaddr)); + ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, + &ipv6_header->srcaddr)); printf("IPv6 Dest: %s\n", - ipv6_addr_to_str(addr_str, &ipv6_header->destaddr)); + ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, + &ipv6_header->destaddr)); printf("TCP Length: %x\n", ipv6_header->length - TCP_HDR_LEN); printf("Source Port: %x, Dest. Port: %x\n", NTOHS(tcp_header->src_port), NTOHS(tcp_header->dst_port)); @@ -148,10 +150,10 @@ void print_socket(socket_t *current_socket) current_socket->type, current_socket->protocol); printf("Local address: %s\n", - ipv6_addr_to_str(addr_str, + ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, ¤t_socket->local_address.sin6_addr)); printf("Foreign address: %s\n", - ipv6_addr_to_str(addr_str, + ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, ¤t_socket->foreign_address.sin6_addr)); printf("Local Port: %u, Foreign Port: %u\n", NTOHS(current_socket->local_address.sin6_port), @@ -494,13 +496,13 @@ int send_tcp(socket_internal_t *current_socket, tcp_hdr_t *current_tcp_packet, } return ipv6_sendto(¤t_tcp_socket->foreign_address.sin6_addr, - IPPROTO_TCP, (uint8_t *)(current_tcp_packet), - compressed_size); + IPPROTO_TCP, (uint8_t *)(current_tcp_packet), + compressed_size); #else switch_tcp_packet_byte_order(current_tcp_packet); return ipv6_sendto(¤t_tcp_socket->foreign_address.sin6_addr, - IPPROTO_TCP, (uint8_t *)(current_tcp_packet), - header_length * 4 + payload_length); + IPPROTO_TCP, (uint8_t *)(current_tcp_packet), + header_length * 4 + payload_length); #endif } @@ -539,7 +541,7 @@ int destiny_socket_connect(int socket, sockaddr6_t *addr, uint32_t addrlen) current_int_tcp_socket->recv_pid = thread_getpid(); /* Local address information */ - ipv6_iface_get_best_src_addr(&src_addr, &addr->sin6_addr); + ipv6_net_if_get_best_src_addr(&src_addr, &addr->sin6_addr); set_socket_address(¤t_tcp_socket->local_address, PF_INET6, HTONS(get_free_source_port(IPPROTO_TCP)), 0, &src_addr); @@ -1011,7 +1013,7 @@ int32_t destiny_socket_sendto(int s, const void *buf, uint32_t len, int flags, uint8_t *payload = &send_buffer[IPV6_HDR_LEN + UDP_HDR_LEN]; memcpy(&(temp_ipv6_header->destaddr), &to->sin6_addr, 16); - ipv6_iface_get_best_src_addr(&(temp_ipv6_header->srcaddr), &(temp_ipv6_header->destaddr)); + ipv6_net_if_get_best_src_addr(&(temp_ipv6_header->srcaddr), &(temp_ipv6_header->destaddr)); current_udp_packet->src_port = get_free_source_port(IPPROTO_UDP); current_udp_packet->dst_port = to->sin6_port; @@ -1022,13 +1024,13 @@ int32_t destiny_socket_sendto(int s, const void *buf, uint32_t len, int flags, temp_ipv6_header->length = UDP_HDR_LEN + len; current_udp_packet->checksum = ~ipv6_csum(temp_ipv6_header, - (uint8_t*) current_udp_packet, - UDP_HDR_LEN + len, - IPPROTO_UDP); + (uint8_t *) current_udp_packet, + UDP_HDR_LEN + len, + IPPROTO_UDP); return ipv6_sendto(&to->sin6_addr, IPPROTO_UDP, - (uint8_t *)(current_udp_packet), - NTOHS(current_udp_packet->length)); + (uint8_t *)(current_udp_packet), + NTOHS(current_udp_packet->length)); } else { return -1; diff --git a/sys/shell/commands/sc_net_if.c b/sys/shell/commands/sc_net_if.c index 790173abe2..efd54e1dd2 100644 --- a/sys/shell/commands/sc_net_if.c +++ b/sys/shell/commands/sc_net_if.c @@ -23,18 +23,21 @@ #include #include -#include "destiny/socket.h" /* for AF_INET6 */ #include "inet_pton.h" #include "inet_ntop.h" #include "net_help.h" #include "net_if.h" #include "transceiver.h" +#ifndef MODULE_SIXLOWPAN #define ADDR_REGISTERED_MAX (6) #define ADDRS_LEN_MAX (16) static uint8_t addr_registered = 0; static uint8_t addrs[ADDR_REGISTERED_MAX][ADDRS_LEN_MAX]; +#else +#include "ipv6.h" +#endif void _net_if_ifconfig_add(int if_id, int argc, char **argv); void _net_if_ifconfig_add_ipv6(int if_id, int argc, char **argv); @@ -45,8 +48,9 @@ void _net_if_ifconfig_set_hwaddr(int if_id, char *addr); void _net_if_ifconfig_set_pan_id(int if_id, char *pan_id); void _net_if_ifconfig_set_channel(int if_id, char *channel); void _net_if_ifconfig_create(char *transceivers_str); -int _net_if_ifconfig_ipv6_addr_convert(net_if_addr_t *addr, char *type, - char *addr_data_str, char *addr_data_len); +int _net_if_ifconfig_ipv6_addr_convert(net_if_addr_t *addr, void *addr_data, + char *type, char *addr_data_str, + char *addr_data_len); void _net_if_ifconfig_list(int if_id); int isnumber(char *str) @@ -335,20 +339,60 @@ void _net_if_ifconfig_add_ipv6(int if_id, int argc, char **argv) type = NULL; } +#ifdef MODULE_SIXLOWPAN + ipv6_addr_t ipv6_addr; + void *addr_data = &ipv6_addr; +#else + void *addr_data = (void *)&addrs[addr_registered][0]; +#endif + addr_data_str = strtok(addr_str, "/"); addr_data_len = strtok(NULL, "/"); - if (!_net_if_ifconfig_ipv6_addr_convert(&addr, type, addr_data_str, addr_data_len)) { + if (!_net_if_ifconfig_ipv6_addr_convert(&addr, addr_data, type, + addr_data_str, addr_data_len)) { add_usage(); return; } +#ifdef MODULE_SIXLOWPAN + + if (addr.addr_protocol & NET_IF_L3P_IPV6_PREFIX) { + if (ndp_add_prefix_info(if_id, &ipv6_addr, addr.addr_len, + NDP_OPT_PI_VLIFETIME_INFINITE, + NDP_OPT_PI_PLIFETIME_INFINITE, 1, + ICMPV6_NDP_OPT_PI_FLAG_AUTONOM) != SIXLOWERROR_SUCCESS) { + add_usage(); + return; + } + } + else if (addr.addr_protocol & NET_IF_L3P_IPV6_ADDR) { + uint8_t is_anycast = 0; + + if (addr.addr_protocol & NET_IF_L3P_IPV6_ANYCAST) { + is_anycast = 1; + } + + if (!ipv6_net_if_add_addr(if_id, &ipv6_addr, NDP_ADDR_STATE_PREFERRED, + 0, 0, is_anycast)) { + add_usage(); + return; + } + } + else { + add_usage(); + return; + } + +#else + if (net_if_add_address(if_id, &addr) < 0) { add_usage(); return; } addr_registered++; +#endif } void _net_if_ifconfig_add(int if_id, int argc, char **argv) @@ -413,13 +457,21 @@ void _net_if_ifconfig_create(char *transceivers_str) static inline int _is_multicast(uint8_t *addr) { +#ifdef MODULE_SIXLOWPAN + return ipv6_addr_is_multicast((ipv6_addr_t *) addr); +#else return *addr == 0xff; +#endif } static inline int _is_link_local(uint8_t *addr) { +#ifdef MODULE_SIXLOWPAN + return ipv6_addr_is_link_local((ipv6_addr_t *) addr); +#else return (addr[0] == 0xfe && addr[1] == 0x80) || (_is_multicast(addr) && (addr[1] & 0x0f) == 2); +#endif } int _set_protocol_from_type(char *type, net_if_addr_t *addr) @@ -448,14 +500,15 @@ int _set_protocol_from_type(char *type, net_if_addr_t *addr) } } -int _net_if_ifconfig_ipv6_addr_convert(net_if_addr_t *addr, char *type, - char *addr_data_str, char *addr_data_len) +int _net_if_ifconfig_ipv6_addr_convert(net_if_addr_t *addr, void *addr_data, + char *type, char *addr_data_str, + char *addr_data_len) { if (addr_data_len && !isnumber(addr_data_len)) { return 0; } - addr->addr_data = (void *)&addrs[addr_registered][0]; + addr->addr_data = addr_data; if (!inet_pton(AF_INET6, addr_data_str, addr->addr_data)) { return 0;