1195972f6Sopenharmony_ci/** 2195972f6Sopenharmony_ci * @file 3195972f6Sopenharmony_ci * 6LowPAN over BLE output for IPv6 (RFC7668). 4195972f6Sopenharmony_ci*/ 5195972f6Sopenharmony_ci 6195972f6Sopenharmony_ci/* 7195972f6Sopenharmony_ci * Copyright (c) 2017 Benjamin Aigner 8195972f6Sopenharmony_ci * Copyright (c) 2015 Inico Technologies Ltd. , Author: Ivan Delamer <delamer@inicotech.com> 9195972f6Sopenharmony_ci * 10195972f6Sopenharmony_ci * All rights reserved. 11195972f6Sopenharmony_ci * 12195972f6Sopenharmony_ci * Redistribution and use in source and binary forms, with or without modification, 13195972f6Sopenharmony_ci * are permitted provided that the following conditions are met: 14195972f6Sopenharmony_ci * 15195972f6Sopenharmony_ci * 1. Redistributions of source code must retain the above copyright notice, 16195972f6Sopenharmony_ci * this list of conditions and the following disclaimer. 17195972f6Sopenharmony_ci * 2. Redistributions in binary form must reproduce the above copyright notice, 18195972f6Sopenharmony_ci * this list of conditions and the following disclaimer in the documentation 19195972f6Sopenharmony_ci * and/or other materials provided with the distribution. 20195972f6Sopenharmony_ci * 3. The name of the author may not be used to endorse or promote products 21195972f6Sopenharmony_ci * derived from this software without specific prior written permission. 22195972f6Sopenharmony_ci * 23195972f6Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 24195972f6Sopenharmony_ci * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 25195972f6Sopenharmony_ci * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 26195972f6Sopenharmony_ci * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 27195972f6Sopenharmony_ci * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 28195972f6Sopenharmony_ci * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 29195972f6Sopenharmony_ci * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 30195972f6Sopenharmony_ci * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 31195972f6Sopenharmony_ci * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 32195972f6Sopenharmony_ci * OF SUCH DAMAGE. 33195972f6Sopenharmony_ci * 34195972f6Sopenharmony_ci * Author: Benjamin Aigner <aignerb@technikum-wien.at> 35195972f6Sopenharmony_ci * 36195972f6Sopenharmony_ci * Based on the original 6lowpan implementation of lwIP ( @see 6lowpan.c) 37195972f6Sopenharmony_ci */ 38195972f6Sopenharmony_ci 39195972f6Sopenharmony_ci 40195972f6Sopenharmony_ci/** 41195972f6Sopenharmony_ci * @defgroup rfc7668if 6LoWPAN over BLE (RFC7668) 42195972f6Sopenharmony_ci * @ingroup netifs 43195972f6Sopenharmony_ci * This file implements a RFC7668 implementation for 6LoWPAN over 44195972f6Sopenharmony_ci * Bluetooth Low Energy. The specification is very similar to 6LoWPAN, 45195972f6Sopenharmony_ci * so most of the code is re-used. 46195972f6Sopenharmony_ci * Compared to 6LoWPAN, much functionality is already implemented in 47195972f6Sopenharmony_ci * lower BLE layers (fragmenting, session management,...). 48195972f6Sopenharmony_ci * 49195972f6Sopenharmony_ci * Usage: 50195972f6Sopenharmony_ci * - add this netif 51195972f6Sopenharmony_ci * - don't add IPv4 addresses (no IPv4 support in RFC7668), pass 'NULL','NULL','NULL' 52195972f6Sopenharmony_ci * - use the BLE to EUI64 conversation util to create an IPv6 link-local address from the BLE MAC (@ref ble_addr_to_eui64) 53195972f6Sopenharmony_ci * - input function: @ref rfc7668_input 54195972f6Sopenharmony_ci * - set the link output function, which transmits output data to an established L2CAP channel 55195972f6Sopenharmony_ci * - If data arrives (HCI event "L2CAP_DATA_PACKET"): 56195972f6Sopenharmony_ci * - allocate a @ref PBUF_RAW buffer 57195972f6Sopenharmony_ci * - let the pbuf struct point to the incoming data or copy it to the buffer 58195972f6Sopenharmony_ci * - call netif->input 59195972f6Sopenharmony_ci * 60195972f6Sopenharmony_ci * @todo: 61195972f6Sopenharmony_ci * - further testing 62195972f6Sopenharmony_ci * - support compression contexts 63195972f6Sopenharmony_ci * - support multiple addresses 64195972f6Sopenharmony_ci * - support multicast 65195972f6Sopenharmony_ci * - support neighbor discovery 66195972f6Sopenharmony_ci */ 67195972f6Sopenharmony_ci 68195972f6Sopenharmony_ci 69195972f6Sopenharmony_ci#include "netif/lowpan6_ble.h" 70195972f6Sopenharmony_ci 71195972f6Sopenharmony_ci#if LWIP_IPV6 72195972f6Sopenharmony_ci 73195972f6Sopenharmony_ci#include "lwip/ip.h" 74195972f6Sopenharmony_ci#include "lwip/pbuf.h" 75195972f6Sopenharmony_ci#include "lwip/ip_addr.h" 76195972f6Sopenharmony_ci#include "lwip/netif.h" 77195972f6Sopenharmony_ci#include "lwip/nd6.h" 78195972f6Sopenharmony_ci#include "lwip/mem.h" 79195972f6Sopenharmony_ci#include "lwip/udp.h" 80195972f6Sopenharmony_ci#include "lwip/tcpip.h" 81195972f6Sopenharmony_ci#include "lwip/snmp.h" 82195972f6Sopenharmony_ci 83195972f6Sopenharmony_ci#include <string.h> 84195972f6Sopenharmony_ci 85195972f6Sopenharmony_ci#if LWIP_6LOWPAN_NUM_CONTEXTS > 0 86195972f6Sopenharmony_ci/** context memory, containing IPv6 addresses */ 87195972f6Sopenharmony_cistatic ip6_addr_t rfc7668_context[LWIP_6LOWPAN_NUM_CONTEXTS]; 88195972f6Sopenharmony_ci#else 89195972f6Sopenharmony_ci#define rfc7668_context NULL 90195972f6Sopenharmony_ci#endif 91195972f6Sopenharmony_ci 92195972f6Sopenharmony_cistatic struct lowpan6_link_addr rfc7668_local_addr; 93195972f6Sopenharmony_cistatic struct lowpan6_link_addr rfc7668_peer_addr; 94195972f6Sopenharmony_ci 95195972f6Sopenharmony_ci/** 96195972f6Sopenharmony_ci * @ingroup rfc7668if 97195972f6Sopenharmony_ci * convert BT address to EUI64 addr 98195972f6Sopenharmony_ci * 99195972f6Sopenharmony_ci * This method converts a Bluetooth MAC address to an EUI64 address, 100195972f6Sopenharmony_ci * which is used within IPv6 communication 101195972f6Sopenharmony_ci * 102195972f6Sopenharmony_ci * @param dst IPv6 destination space 103195972f6Sopenharmony_ci * @param src BLE MAC address source 104195972f6Sopenharmony_ci * @param public_addr If the LWIP_RFC7668_LINUX_WORKAROUND_PUBLIC_ADDRESS 105195972f6Sopenharmony_ci * option is set, bit 0x02 will be set if param=0 (no public addr); cleared otherwise 106195972f6Sopenharmony_ci * 107195972f6Sopenharmony_ci * @see LWIP_RFC7668_LINUX_WORKAROUND_PUBLIC_ADDRESS 108195972f6Sopenharmony_ci */ 109195972f6Sopenharmony_civoid 110195972f6Sopenharmony_cible_addr_to_eui64(uint8_t *dst, const uint8_t *src, int public_addr) 111195972f6Sopenharmony_ci{ 112195972f6Sopenharmony_ci /* according to RFC7668 ch 3.2.2. */ 113195972f6Sopenharmony_ci memcpy(dst, src, 3); 114195972f6Sopenharmony_ci dst[3] = 0xFF; 115195972f6Sopenharmony_ci dst[4] = 0xFE; 116195972f6Sopenharmony_ci memcpy(&dst[5], &src[3], 3); 117195972f6Sopenharmony_ci#if LWIP_RFC7668_LINUX_WORKAROUND_PUBLIC_ADDRESS 118195972f6Sopenharmony_ci if(public_addr) { 119195972f6Sopenharmony_ci dst[0] &= ~0x02; 120195972f6Sopenharmony_ci } else { 121195972f6Sopenharmony_ci dst[0] |= 0x02; 122195972f6Sopenharmony_ci } 123195972f6Sopenharmony_ci#else 124195972f6Sopenharmony_ci LWIP_UNUSED_ARG(public_addr); 125195972f6Sopenharmony_ci#endif 126195972f6Sopenharmony_ci} 127195972f6Sopenharmony_ci 128195972f6Sopenharmony_ci/** 129195972f6Sopenharmony_ci * @ingroup rfc7668if 130195972f6Sopenharmony_ci * convert EUI64 address to Bluetooth MAC addr 131195972f6Sopenharmony_ci * 132195972f6Sopenharmony_ci * This method converts an EUI64 address to a Bluetooth MAC address, 133195972f6Sopenharmony_ci * 134195972f6Sopenharmony_ci * @param dst BLE MAC address destination 135195972f6Sopenharmony_ci * @param src IPv6 source 136195972f6Sopenharmony_ci * 137195972f6Sopenharmony_ci */ 138195972f6Sopenharmony_civoid 139195972f6Sopenharmony_cieui64_to_ble_addr(uint8_t *dst, const uint8_t *src) 140195972f6Sopenharmony_ci{ 141195972f6Sopenharmony_ci /* according to RFC7668 ch 3.2.2. */ 142195972f6Sopenharmony_ci memcpy(dst,src,3); 143195972f6Sopenharmony_ci memcpy(&dst[3],&src[5],3); 144195972f6Sopenharmony_ci} 145195972f6Sopenharmony_ci 146195972f6Sopenharmony_ci/** Set an address used for stateful compression. 147195972f6Sopenharmony_ci * This expects an address of 6 or 8 bytes. 148195972f6Sopenharmony_ci */ 149195972f6Sopenharmony_cistatic err_t 150195972f6Sopenharmony_cirfc7668_set_addr(struct lowpan6_link_addr *addr, const u8_t *in_addr, size_t in_addr_len, int is_mac_48, int is_public_addr) 151195972f6Sopenharmony_ci{ 152195972f6Sopenharmony_ci if ((in_addr == NULL) || (addr == NULL)) { 153195972f6Sopenharmony_ci return ERR_VAL; 154195972f6Sopenharmony_ci } 155195972f6Sopenharmony_ci if (is_mac_48) { 156195972f6Sopenharmony_ci if (in_addr_len != 6) { 157195972f6Sopenharmony_ci return ERR_VAL; 158195972f6Sopenharmony_ci } 159195972f6Sopenharmony_ci addr->addr_len = 8; 160195972f6Sopenharmony_ci ble_addr_to_eui64(addr->addr, in_addr, is_public_addr); 161195972f6Sopenharmony_ci } else { 162195972f6Sopenharmony_ci if (in_addr_len != 8) { 163195972f6Sopenharmony_ci return ERR_VAL; 164195972f6Sopenharmony_ci } 165195972f6Sopenharmony_ci addr->addr_len = 8; 166195972f6Sopenharmony_ci memcpy(addr->addr, in_addr, 8); 167195972f6Sopenharmony_ci } 168195972f6Sopenharmony_ci return ERR_OK; 169195972f6Sopenharmony_ci} 170195972f6Sopenharmony_ci 171195972f6Sopenharmony_ci 172195972f6Sopenharmony_ci/** Set the local address used for stateful compression. 173195972f6Sopenharmony_ci * This expects an address of 8 bytes. 174195972f6Sopenharmony_ci */ 175195972f6Sopenharmony_cierr_t 176195972f6Sopenharmony_cirfc7668_set_local_addr_eui64(struct netif *netif, const u8_t *local_addr, size_t local_addr_len) 177195972f6Sopenharmony_ci{ 178195972f6Sopenharmony_ci /* netif not used for now, the address is stored globally... */ 179195972f6Sopenharmony_ci LWIP_UNUSED_ARG(netif); 180195972f6Sopenharmony_ci return rfc7668_set_addr(&rfc7668_local_addr, local_addr, local_addr_len, 0, 0); 181195972f6Sopenharmony_ci} 182195972f6Sopenharmony_ci 183195972f6Sopenharmony_ci/** Set the local address used for stateful compression. 184195972f6Sopenharmony_ci * This expects an address of 6 bytes. 185195972f6Sopenharmony_ci */ 186195972f6Sopenharmony_cierr_t 187195972f6Sopenharmony_cirfc7668_set_local_addr_mac48(struct netif *netif, const u8_t *local_addr, size_t local_addr_len, int is_public_addr) 188195972f6Sopenharmony_ci{ 189195972f6Sopenharmony_ci /* netif not used for now, the address is stored globally... */ 190195972f6Sopenharmony_ci LWIP_UNUSED_ARG(netif); 191195972f6Sopenharmony_ci return rfc7668_set_addr(&rfc7668_local_addr, local_addr, local_addr_len, 1, is_public_addr); 192195972f6Sopenharmony_ci} 193195972f6Sopenharmony_ci 194195972f6Sopenharmony_ci/** Set the peer address used for stateful compression. 195195972f6Sopenharmony_ci * This expects an address of 8 bytes. 196195972f6Sopenharmony_ci */ 197195972f6Sopenharmony_cierr_t 198195972f6Sopenharmony_cirfc7668_set_peer_addr_eui64(struct netif *netif, const u8_t *peer_addr, size_t peer_addr_len) 199195972f6Sopenharmony_ci{ 200195972f6Sopenharmony_ci /* netif not used for now, the address is stored globally... */ 201195972f6Sopenharmony_ci LWIP_UNUSED_ARG(netif); 202195972f6Sopenharmony_ci return rfc7668_set_addr(&rfc7668_peer_addr, peer_addr, peer_addr_len, 0, 0); 203195972f6Sopenharmony_ci} 204195972f6Sopenharmony_ci 205195972f6Sopenharmony_ci/** Set the peer address used for stateful compression. 206195972f6Sopenharmony_ci * This expects an address of 6 bytes. 207195972f6Sopenharmony_ci */ 208195972f6Sopenharmony_cierr_t 209195972f6Sopenharmony_cirfc7668_set_peer_addr_mac48(struct netif *netif, const u8_t *peer_addr, size_t peer_addr_len, int is_public_addr) 210195972f6Sopenharmony_ci{ 211195972f6Sopenharmony_ci /* netif not used for now, the address is stored globally... */ 212195972f6Sopenharmony_ci LWIP_UNUSED_ARG(netif); 213195972f6Sopenharmony_ci return rfc7668_set_addr(&rfc7668_peer_addr, peer_addr, peer_addr_len, 1, is_public_addr); 214195972f6Sopenharmony_ci} 215195972f6Sopenharmony_ci 216195972f6Sopenharmony_ci/** Encapsulate IPv6 frames for BLE transmission 217195972f6Sopenharmony_ci * 218195972f6Sopenharmony_ci * This method implements the IPv6 header compression: 219195972f6Sopenharmony_ci * *) According to RFC6282 220195972f6Sopenharmony_ci * *) See Figure 2, contains base format of bit positions 221195972f6Sopenharmony_ci * *) Fragmentation not necessary (done at L2CAP layer of BLE) 222195972f6Sopenharmony_ci * @note Currently the pbuf allocation uses 256 bytes. If longer packets are used (possible due to MTU=1480Bytes), increase it here! 223195972f6Sopenharmony_ci * 224195972f6Sopenharmony_ci * @param p Pbuf struct, containing the payload data 225195972f6Sopenharmony_ci * @param netif Output network interface. Should be of RFC7668 type 226195972f6Sopenharmony_ci * 227195972f6Sopenharmony_ci * @return Same as netif->output. 228195972f6Sopenharmony_ci */ 229195972f6Sopenharmony_cistatic err_t 230195972f6Sopenharmony_cirfc7668_compress(struct netif *netif, struct pbuf *p) 231195972f6Sopenharmony_ci{ 232195972f6Sopenharmony_ci struct pbuf *p_frag; 233195972f6Sopenharmony_ci u16_t remaining_len; 234195972f6Sopenharmony_ci u8_t *buffer; 235195972f6Sopenharmony_ci u8_t lowpan6_header_len; 236195972f6Sopenharmony_ci u8_t hidden_header_len; 237195972f6Sopenharmony_ci err_t err; 238195972f6Sopenharmony_ci 239195972f6Sopenharmony_ci LWIP_ASSERT("lowpan6_frag: netif->linkoutput not set", netif->linkoutput != NULL); 240195972f6Sopenharmony_ci 241195972f6Sopenharmony_ci#if LWIP_6LOWPAN_IPHC 242195972f6Sopenharmony_ci 243195972f6Sopenharmony_ci /* We'll use a dedicated pbuf for building BLE fragments. 244195972f6Sopenharmony_ci * We'll over-allocate it by the bytes saved for header compression. 245195972f6Sopenharmony_ci */ 246195972f6Sopenharmony_ci p_frag = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM); 247195972f6Sopenharmony_ci if (p_frag == NULL) { 248195972f6Sopenharmony_ci MIB2_STATS_NETIF_INC(netif, ifoutdiscards); 249195972f6Sopenharmony_ci return ERR_MEM; 250195972f6Sopenharmony_ci } 251195972f6Sopenharmony_ci LWIP_ASSERT("this needs a pbuf in one piece", p_frag->len == p_frag->tot_len); 252195972f6Sopenharmony_ci 253195972f6Sopenharmony_ci /* Write IP6 header (with IPHC). */ 254195972f6Sopenharmony_ci buffer = (u8_t*)p_frag->payload; 255195972f6Sopenharmony_ci 256195972f6Sopenharmony_ci err = lowpan6_compress_headers(netif, (u8_t *)p->payload, p->len, buffer, p_frag->len, 257195972f6Sopenharmony_ci &lowpan6_header_len, &hidden_header_len, rfc7668_context, &rfc7668_local_addr, &rfc7668_peer_addr); 258195972f6Sopenharmony_ci if (err != ERR_OK) { 259195972f6Sopenharmony_ci MIB2_STATS_NETIF_INC(netif, ifoutdiscards); 260195972f6Sopenharmony_ci pbuf_free(p_frag); 261195972f6Sopenharmony_ci return err; 262195972f6Sopenharmony_ci } 263195972f6Sopenharmony_ci pbuf_remove_header(p, hidden_header_len); 264195972f6Sopenharmony_ci 265195972f6Sopenharmony_ci /* Calculate remaining packet length */ 266195972f6Sopenharmony_ci remaining_len = p->tot_len; 267195972f6Sopenharmony_ci 268195972f6Sopenharmony_ci /* Copy IPv6 packet */ 269195972f6Sopenharmony_ci pbuf_copy_partial(p, buffer + lowpan6_header_len, remaining_len, 0); 270195972f6Sopenharmony_ci 271195972f6Sopenharmony_ci /* Calculate frame length */ 272195972f6Sopenharmony_ci p_frag->len = p_frag->tot_len = remaining_len + lowpan6_header_len; 273195972f6Sopenharmony_ci 274195972f6Sopenharmony_ci /* send the packet */ 275195972f6Sopenharmony_ci MIB2_STATS_NETIF_ADD(netif, ifoutoctets, p_frag->tot_len); 276195972f6Sopenharmony_ci LWIP_DEBUGF(LWIP_LOWPAN6_DEBUG|LWIP_DBG_TRACE, ("rfc7668_output: sending packet %p\n", (void *)p)); 277195972f6Sopenharmony_ci err = netif->linkoutput(netif, p_frag); 278195972f6Sopenharmony_ci 279195972f6Sopenharmony_ci pbuf_free(p_frag); 280195972f6Sopenharmony_ci 281195972f6Sopenharmony_ci return err; 282195972f6Sopenharmony_ci#else /* LWIP_6LOWPAN_IPHC */ 283195972f6Sopenharmony_ci /* 6LoWPAN over BLE requires IPHC! */ 284195972f6Sopenharmony_ci return ERR_IF; 285195972f6Sopenharmony_ci#endif/* LWIP_6LOWPAN_IPHC */ 286195972f6Sopenharmony_ci} 287195972f6Sopenharmony_ci 288195972f6Sopenharmony_ci/** 289195972f6Sopenharmony_ci * @ingroup rfc7668if 290195972f6Sopenharmony_ci * Set context id IPv6 address 291195972f6Sopenharmony_ci * 292195972f6Sopenharmony_ci * Store one IPv6 address to a given context id. 293195972f6Sopenharmony_ci * 294195972f6Sopenharmony_ci * @param idx Context id 295195972f6Sopenharmony_ci * @param context IPv6 addr for this context 296195972f6Sopenharmony_ci * 297195972f6Sopenharmony_ci * @return ERR_OK (if everything is fine), ERR_ARG (if the context id is out of range), ERR_VAL (if contexts disabled) 298195972f6Sopenharmony_ci */ 299195972f6Sopenharmony_cierr_t 300195972f6Sopenharmony_cirfc7668_set_context(u8_t idx, const ip6_addr_t *context) 301195972f6Sopenharmony_ci{ 302195972f6Sopenharmony_ci#if LWIP_6LOWPAN_NUM_CONTEXTS > 0 303195972f6Sopenharmony_ci /* check if the ID is possible */ 304195972f6Sopenharmony_ci if (idx >= LWIP_6LOWPAN_NUM_CONTEXTS) { 305195972f6Sopenharmony_ci return ERR_ARG; 306195972f6Sopenharmony_ci } 307195972f6Sopenharmony_ci /* copy IPv6 address to context storage */ 308195972f6Sopenharmony_ci ip6_addr_set(&rfc7668_context[idx], context); 309195972f6Sopenharmony_ci return ERR_OK; 310195972f6Sopenharmony_ci#else 311195972f6Sopenharmony_ci LWIP_UNUSED_ARG(idx); 312195972f6Sopenharmony_ci LWIP_UNUSED_ARG(context); 313195972f6Sopenharmony_ci return ERR_VAL; 314195972f6Sopenharmony_ci#endif 315195972f6Sopenharmony_ci} 316195972f6Sopenharmony_ci 317195972f6Sopenharmony_ci/** 318195972f6Sopenharmony_ci * @ingroup rfc7668if 319195972f6Sopenharmony_ci * Compress outgoing IPv6 packet and pass it on to netif->linkoutput 320195972f6Sopenharmony_ci * 321195972f6Sopenharmony_ci * @param netif The lwIP network interface which the IP packet will be sent on. 322195972f6Sopenharmony_ci * @param q The pbuf(s) containing the IP packet to be sent. 323195972f6Sopenharmony_ci * @param ip6addr The IP address of the packet destination. 324195972f6Sopenharmony_ci * 325195972f6Sopenharmony_ci * @return See rfc7668_compress 326195972f6Sopenharmony_ci */ 327195972f6Sopenharmony_cierr_t 328195972f6Sopenharmony_cirfc7668_output(struct netif *netif, struct pbuf *q, const ip6_addr_t *ip6addr) 329195972f6Sopenharmony_ci{ 330195972f6Sopenharmony_ci /* dst ip6addr is not used here, we only have one peer */ 331195972f6Sopenharmony_ci LWIP_UNUSED_ARG(ip6addr); 332195972f6Sopenharmony_ci 333195972f6Sopenharmony_ci return rfc7668_compress(netif, q); 334195972f6Sopenharmony_ci} 335195972f6Sopenharmony_ci 336195972f6Sopenharmony_ci/** 337195972f6Sopenharmony_ci * @ingroup rfc7668if 338195972f6Sopenharmony_ci * Process a received raw payload from an L2CAP channel 339195972f6Sopenharmony_ci * 340195972f6Sopenharmony_ci * @param p the received packet, p->payload pointing to the 341195972f6Sopenharmony_ci * IPv6 header (maybe compressed) 342195972f6Sopenharmony_ci * @param netif the network interface on which the packet was received 343195972f6Sopenharmony_ci * 344195972f6Sopenharmony_ci * @return ERR_OK if everything was fine 345195972f6Sopenharmony_ci */ 346195972f6Sopenharmony_cierr_t 347195972f6Sopenharmony_cirfc7668_input(struct pbuf * p, struct netif *netif) 348195972f6Sopenharmony_ci{ 349195972f6Sopenharmony_ci u8_t * puc; 350195972f6Sopenharmony_ci 351195972f6Sopenharmony_ci MIB2_STATS_NETIF_ADD(netif, ifinoctets, p->tot_len); 352195972f6Sopenharmony_ci 353195972f6Sopenharmony_ci /* Load first header byte */ 354195972f6Sopenharmony_ci puc = (u8_t*)p->payload; 355195972f6Sopenharmony_ci 356195972f6Sopenharmony_ci /* no IP header compression */ 357195972f6Sopenharmony_ci if (*puc == 0x41) { 358195972f6Sopenharmony_ci LWIP_DEBUGF(LWIP_LOWPAN6_DECOMPRESSION_DEBUG, ("Completed packet, removing dispatch: 0x%2x \n", *puc)); 359195972f6Sopenharmony_ci /* This is a complete IPv6 packet, just skip header byte. */ 360195972f6Sopenharmony_ci pbuf_remove_header(p, 1); 361195972f6Sopenharmony_ci /* IPHC header compression */ 362195972f6Sopenharmony_ci } else if ((*puc & 0xe0 )== 0x60) { 363195972f6Sopenharmony_ci LWIP_DEBUGF(LWIP_LOWPAN6_DECOMPRESSION_DEBUG, ("Completed packet, decompress dispatch: 0x%2x \n", *puc)); 364195972f6Sopenharmony_ci /* IPv6 headers are compressed using IPHC. */ 365195972f6Sopenharmony_ci p = lowpan6_decompress(p, 0, rfc7668_context, &rfc7668_peer_addr, &rfc7668_local_addr); 366195972f6Sopenharmony_ci /* if no pbuf is returned, handle as discarded packet */ 367195972f6Sopenharmony_ci if (p == NULL) { 368195972f6Sopenharmony_ci MIB2_STATS_NETIF_INC(netif, ifindiscards); 369195972f6Sopenharmony_ci return ERR_OK; 370195972f6Sopenharmony_ci } 371195972f6Sopenharmony_ci /* invalid header byte, discard */ 372195972f6Sopenharmony_ci } else { 373195972f6Sopenharmony_ci LWIP_DEBUGF(LWIP_LOWPAN6_DECOMPRESSION_DEBUG, ("Completed packet, discarding: 0x%2x \n", *puc)); 374195972f6Sopenharmony_ci MIB2_STATS_NETIF_INC(netif, ifindiscards); 375195972f6Sopenharmony_ci pbuf_free(p); 376195972f6Sopenharmony_ci return ERR_OK; 377195972f6Sopenharmony_ci } 378195972f6Sopenharmony_ci /* @todo: distinguish unicast/multicast */ 379195972f6Sopenharmony_ci MIB2_STATS_NETIF_INC(netif, ifinucastpkts); 380195972f6Sopenharmony_ci 381195972f6Sopenharmony_ci#if LWIP_RFC7668_IP_UNCOMPRESSED_DEBUG 382195972f6Sopenharmony_ci { 383195972f6Sopenharmony_ci u16_t i; 384195972f6Sopenharmony_ci LWIP_DEBUGF(LWIP_RFC7668_IP_UNCOMPRESSED_DEBUG, ("IPv6 payload:\n")); 385195972f6Sopenharmony_ci for (i = 0; i < p->len; i++) { 386195972f6Sopenharmony_ci if ((i%4)==0) { 387195972f6Sopenharmony_ci LWIP_DEBUGF(LWIP_RFC7668_IP_UNCOMPRESSED_DEBUG, ("\n")); 388195972f6Sopenharmony_ci } 389195972f6Sopenharmony_ci LWIP_DEBUGF(LWIP_RFC7668_IP_UNCOMPRESSED_DEBUG, ("%2X ", *((uint8_t *)p->payload+i))); 390195972f6Sopenharmony_ci } 391195972f6Sopenharmony_ci LWIP_DEBUGF(LWIP_RFC7668_IP_UNCOMPRESSED_DEBUG, ("\np->len: %d\n", p->len)); 392195972f6Sopenharmony_ci } 393195972f6Sopenharmony_ci#endif 394195972f6Sopenharmony_ci /* pass data to ip6_input */ 395195972f6Sopenharmony_ci return ip6_input(p, netif); 396195972f6Sopenharmony_ci} 397195972f6Sopenharmony_ci 398195972f6Sopenharmony_ci/** 399195972f6Sopenharmony_ci * @ingroup rfc7668if 400195972f6Sopenharmony_ci * Initialize the netif 401195972f6Sopenharmony_ci * 402195972f6Sopenharmony_ci * No flags are used (broadcast not possible, not ethernet, ...) 403195972f6Sopenharmony_ci * The shortname for this netif is "BT" 404195972f6Sopenharmony_ci * 405195972f6Sopenharmony_ci * @param netif the network interface to be initialized as RFC7668 netif 406195972f6Sopenharmony_ci * 407195972f6Sopenharmony_ci * @return ERR_OK if everything went fine 408195972f6Sopenharmony_ci */ 409195972f6Sopenharmony_cierr_t 410195972f6Sopenharmony_cirfc7668_if_init(struct netif *netif) 411195972f6Sopenharmony_ci{ 412195972f6Sopenharmony_ci netif->name[0] = 'b'; 413195972f6Sopenharmony_ci netif->name[1] = 't'; 414195972f6Sopenharmony_ci /* local function as IPv6 output */ 415195972f6Sopenharmony_ci netif->output_ip6 = rfc7668_output; 416195972f6Sopenharmony_ci 417195972f6Sopenharmony_ci MIB2_INIT_NETIF(netif, snmp_ifType_other, 0); 418195972f6Sopenharmony_ci 419195972f6Sopenharmony_ci /* maximum transfer unit, set according to RFC7668 ch2.4 */ 420195972f6Sopenharmony_ci netif->mtu = IP6_MIN_MTU_LENGTH; 421195972f6Sopenharmony_ci 422195972f6Sopenharmony_ci /* no flags set (no broadcast, ethernet,...)*/ 423195972f6Sopenharmony_ci netif->flags = 0; 424195972f6Sopenharmony_ci 425195972f6Sopenharmony_ci /* everything fine */ 426195972f6Sopenharmony_ci return ERR_OK; 427195972f6Sopenharmony_ci} 428195972f6Sopenharmony_ci 429195972f6Sopenharmony_ci#if !NO_SYS 430195972f6Sopenharmony_ci/** 431195972f6Sopenharmony_ci * Pass a received packet to tcpip_thread for input processing 432195972f6Sopenharmony_ci * 433195972f6Sopenharmony_ci * @param p the received packet, p->payload pointing to the 434195972f6Sopenharmony_ci * IEEE 802.15.4 header. 435195972f6Sopenharmony_ci * @param inp the network interface on which the packet was received 436195972f6Sopenharmony_ci * 437195972f6Sopenharmony_ci * @return see @ref tcpip_inpkt, same return values 438195972f6Sopenharmony_ci */ 439195972f6Sopenharmony_cierr_t 440195972f6Sopenharmony_citcpip_rfc7668_input(struct pbuf *p, struct netif *inp) 441195972f6Sopenharmony_ci{ 442195972f6Sopenharmony_ci /* send data to upper layer, return the result */ 443195972f6Sopenharmony_ci return tcpip_inpkt(p, inp, rfc7668_input); 444195972f6Sopenharmony_ci} 445195972f6Sopenharmony_ci#endif /* !NO_SYS */ 446195972f6Sopenharmony_ci 447195972f6Sopenharmony_ci#endif /* LWIP_IPV6 */ 448