📄 ipp.nc
字号:
/*
* Copyright (c) 2007 Matus Harvan
* All rights reserved
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * The name of the author may not be used to endorse or promote
* products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Parts of the 6lowpan implementation design were inspired Andrew
* Christian's port of Adam Dunkel's uIP to TinyOS 1.x. This work is
* distributed under the following copyrights:
*
* Copyright (c) 2001-2003, Adam Dunkels.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote
* products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Copyright (c) 2005, Hewlett-Packard Company
* All rights reserved
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of the Hewlett-Packard Company nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* The actual implementaion of the 6lowpan/IPv6 stack lives in this file.
*/
#include "IP.h"
#include "IP_internal.h"
#include "message.h"
#ifdef ENABLE_PRINTF_DEBUG
#include "printf.h"
#endif /* ENABLE_PRINTF_DEBUG */
module IPP {
provides {
interface SplitControl as IPControl;
interface IP;
interface UDPClient[uint8_t i];
}
uses {
interface Timer<TMilli> as Timer;
interface Pool<lowpan_pkt_t> as SendPktPool;
interface Pool<app_data_t> as AppDataPool;
interface Pool<frag_info_t> as FragInfoPool;
interface SplitControl as MessageControl;
interface Receive;
interface AMSend;
interface Packet;
interface AMPacket;
#ifdef ENABLE_PRINTF_DEBUG
interface PrintfFlush;
interface SplitControl as PrintfControl;
#endif /* ENABLE_PRINTF_DEBUG */
interface Leds;
}
}
implementation {
/* global variables */
enum {
COUNT_UDP_CLIENT = uniqueCount("UDPClient"),
COUNT_UDP_CONNS = COUNT_UDP_CLIENT
};
ip6_addr_t global_addr;
ip6_addr_t linklocal_addr;
uint16_t g_dgram_tag = 0;
uint16_t uip_len, uip_slen;
uint8_t uip_flags; /* The uip_flags variable is used for
communication between the TCP/IP stack
and the application program. */
message_t g_msg; // AM for sending
lowpan_pkt_t rx_pkt; // packet used for receiving
//struct lowpan_pkt send_pkt[SEND_PKTS]; // packets to be sent
lowpan_pkt_t *send_queue; // packets to be sent - queue
frag_buf_t frag_bufs[FRAG_BUFS]; // fragment reassembly buffers
struct udp_conn udp_conns[COUNT_UDP_CONNS];
static uint16_t lastport; /* Keeps track of the last port used for
a new connection. */
static int g_send_pending = 0;
// Pre-declare
// clear all fields, set app_data = NULL
void lowpan_pkt_clear(lowpan_pkt_t *pkt);
int ip6_addr_cmp(const ip6_addr_t *a, const ip6_addr_t *b);
static void dump_serial_packet(const unsigned char *packet, const int len);
/*---------------------------------------------------------------------------*/
/* from http://www.nabble.com/memcpy-assumes-16-bit-alignment--t712619.html */
void *
my_memcpy(void *dst0, const void *src0, size_t len)
{
char *dst = (char *)dst0;
const char *src = (const char *)src0;
void *ret = dst0;
for (; len > 0; len--)
*dst++ = *src++;
return ret;
}
/*
* Use this function for copying/setting/memset() 16-bit values
* on the MSP430 !!!
*
* The mspgcc compiler geenrates broken code when doing memset with 16
* bit values, i.e. things go wrong if they are not aligned at 16-bit
* boundaries. See
* http://www.nabble.com/msp430-gcc-generating-unaligned-access.-t2261862.html
* and page 25 in http://www.eecs.harvard.edu/~konrad/projects/motetrack/mspgcc-manual-20031127.pdf for details.
*/
/* use when DST may be UNALIGNED */
inline void set_16t(void *dst, uint16_t val)
{
*((uint8_t*)dst) = *((uint8_t*)&val);
*(((uint8_t*)dst)+1) = *(((uint8_t*)&val)+1);
//memcpy((uint8_t*)dst, (uint8_t*)&val, sizeof(uint8_t));
//memcpy(((uint8_t*)dst)+1, ((uint8_t*)&val)+1, sizeof(uint8_t));
}
/* use when SRC may be UNALIGNED */
inline uint16_t get_16t(void *val)
{
uint16_t tmp;
*((uint8_t*)&tmp) = *((uint8_t*)val);
*(((uint8_t*)&tmp)+1) = *(((uint8_t*)val)+1);
//memcpy((uint8_t*)&tmp, (uint8_t*)val, sizeof(uint8_t));
//memcpy(((uint8_t*)&tmp)+1, ((uint8_t*)val)+1, sizeof(uint8_t));
return tmp;
}
inline uint16_t htons( uint16_t val )
{
// The MSB is little-endian; network order is big
return ((val & 0xff) << 8) | ((val & 0xff00) >> 8);
}
inline uint16_t ntohs( uint16_t val )
{
// The MSB is little-endian; network order is big
return ((val & 0xff) << 8) | ((val & 0xff00) >> 8);
}
inline void htonl( uint32_t val, uint8_t *dest )
{
dest[0] = (val & 0xff000000) >> 24;
dest[1] = (val & 0x00ff0000) >> 16;
dest[2] = (val & 0x0000ff00) >> 8;
dest[3] = (val & 0x000000ff);
}
inline uint32_t ntohl( uint8_t *src )
{
return (((uint32_t) src[0]) << 24) | (((uint32_t) src[1]) << 16) |
(((uint32_t) src[2]) << 8) | (((uint32_t) src[3]));
}
/*
inline void uip_pack_ipaddr( ip6_addr_t *addr, uint8_t *new_addr)
{
memcpy(addr, new_addr, sizeof(addr));
}
// Unpack the IP address into an array of octet
inline void uip_unpack_ipaddr( uint8_t *in, uint8_t *out )
{
memcpy(out, in, sizeof(ip6_addr_t));
}
*/
/*---------------------------------------------------------------------------*/
/* This should be optimized for aligned and unaligned case */
static uint16_t ip_chksum(const uint8_t *buf, uint16_t len,
uint16_t acc)
{
uint16_t v;
for (; len > 1; len -= 2) {
v = (((uint16_t) buf[1]) << 8) | ((uint16_t) buf[0]);
if ( (acc += v) < v ) acc++;
buf += 2;
}
// add an odd byte (note we pad with 0)
if (len) {
v = (uint16_t) buf[0];
if ( (acc += v) < v ) acc++;
}
return acc;
}
/*
* IPv6 checksum of the pseudo-header (RFC 2460, Sec 8.1)
* src_addr and dst_addr are in nerwork byte order
* len is in host byte order (will internally be converted)
*/
static uint16_t ipv6_chksum(const ip6_addr_t* src_addr,
const ip6_addr_t* dst_addr,
const uint8_t next_header,
const uint16_t upper_layer_len,
uint16_t acc)
{
uint16_t tmp;
/* source address */
acc = ip_chksum((const uint8_t *) src_addr, sizeof(*src_addr), acc);
/* destination address */
acc = ip_chksum((const uint8_t *) dst_addr, sizeof(*dst_addr), acc);
/* upper-layer packet length */
tmp = htons(upper_layer_len);
acc = ip_chksum((const uint8_t *) &tmp, sizeof(tmp), acc);
/* next header */
tmp = htons(next_header);
acc = ip_chksum((const uint8_t *) &tmp, sizeof(tmp), acc);
return acc;
}
/* same as above, but including the uppel-layer buffer */
static uint16_t ipv6_chksum_data(const ip6_addr_t* src_addr,
const ip6_addr_t* dst_addr,
const uint8_t next_header,
const uint8_t *data, uint16_t data_len,
uint16_t acc)
{
/* upper-layer payload */
acc = ip_chksum(data, data_len, acc);
return ipv6_chksum(src_addr, dst_addr, next_header, data_len, acc);
}
/*---------------------------------------------------------------------------*/
bool ipv6_addr_is_zero(const ip6_addr_t *addr)
{
int i;
for (i=0;i<16;i++) {
if (addr->addr[i]) {
return FALSE;
}
}
return TRUE;
}
bool ipv6_addr_is_linklocal_unicast(const ip6_addr_t *addr)
{
if ( addr->addr[0] == 0xFE
&& addr->addr[1] == 0x80
&& addr->addr[2] == 0
&& addr->addr[3] == 0
&& addr->addr[4] == 0
&& addr->addr[5] == 0
&& addr->addr[6] == 0
&& addr->addr[7] == 0
)
return TRUE;
else
return FALSE;
}
//TODO: prepend pan_id once we have a proper 802.15.4 stack
void ipv6_iface_id_from_am_addr(am_addr_t am_addr, uint8_t *host_part)
{
memset(host_part, 0, 6);
host_part[4] = 0xFF;
host_part[5] = 0xFE;
host_part += 6;
set_16t(host_part, htons(am_addr));
}
void ipv6_iface_id_from_hw_addr(hw_addr_t *hw_addr, uint8_t *host_part)
{
if (hw_addr->type == HW_ADDR_SHORT) {
memset(host_part, 0, 6);
host_part[4] = 0xFF;
host_part[5] = 0xFE;
host_part[7] = hw_addr->addr_short[0];
host_part[8] = hw_addr->addr_short[1];
//ipv6_iface_id_from_am_addr(hw_addr->addr_short, host_part);
} else {
//TODO
}
}
bool ipv6_addr_is_linklocal_multicast(const ip6_addr_t *addr)
{
if (addr->addr[0] == 0xFF
&& addr->addr[1] == 0x02)
return TRUE;
else
return FALSE;
}
bool ipv6_addr_is_linklocal(const ip6_addr_t *addr)
{
return (ipv6_addr_is_linklocal_unicast(addr)
|| ipv6_addr_is_linklocal_multicast(addr));
}
bool ipv6_addr_is_linklocal_allnodes(const ip6_addr_t *addr)
{
//TODO: interface-local addr FF01::1
if ( addr->addr[0] == 0xFF
&& addr->addr[1] == 0x02
&& addr->addr[2] == 0
&& addr->addr[3] == 0
&& addr->addr[4] == 0
&& addr->addr[5] == 0
&& addr->addr[6] == 0
&& addr->addr[7] == 0
&& addr->addr[8] == 0
&& addr->addr[9] == 0
&& addr->addr[10] == 0
&& addr->addr[11] == 0
&& addr->addr[12] == 0
&& addr->addr[13] == 0
&& addr->addr[14] == 0
&& addr->addr[15] == 0x01
)
return TRUE;
else
return FALSE;
}
bool ipv6_addr_is_solicited_node_multicast_prefix(const ip6_addr_t *addr)
{
// Solicited-Node Address: FF02:0:0:0:0:1:FFXX:XXXX
// Solicited-Node multicast address are computed as a function of a
// node's unicast and anycast addresses. A Solicited-Node multicast
// address is formed by taking the low-order 24 bits of an address
// (unicast or anycast) and appending those bits to the prefix
// FF02:0:0:0:0:1:FF00::/104 resulting in a multicast address in the
// range
// FF02:0:0:0:0:1:FF00:0000
// to
// FF02:0:0:0:0:1:FFFF:FFFF
if ( addr->addr[0] == 0xFF
&& addr->addr[1] == 0x02
&& addr->addr[2] == 0
&& addr->addr[3] == 0
&& addr->addr[4] == 0
&& addr->addr[5] == 0
&& addr->addr[6] == 0
&& addr->addr[7] == 0
&& addr->addr[8] == 0
&& addr->addr[9] == 0
&& addr->addr[10] == 0
&& addr->addr[11] == 0x01
&& addr->addr[12] == 0xFF
)
return TRUE;
else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -