mirror of
https://github.com/lwip-tcpip/lwip.git
synced 2025-01-30 03:32:50 +00:00
Added new files for IPv6
This commit is contained in:
parent
4bfbe7ebeb
commit
90a03a77ad
50
src/core/ipv6/dhcp6.c
Normal file
50
src/core/ipv6/dhcp6.c
Normal file
@ -0,0 +1,50 @@
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* DHCPv6.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2010 Inico Technologies Ltd.
|
||||
* 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.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Ivan Delamer <delamer@inicotech.com>
|
||||
*
|
||||
*
|
||||
* Please coordinate changes and requests with Ivan Delamer
|
||||
* <delamer@inicotech.com>
|
||||
*/
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#if LWIP_IPV6_DHCP6 /* don't build if not configured for use in lwipopts.h */
|
||||
|
||||
#include "lwip/ip6_addr.h"
|
||||
#include "lwip/def.h"
|
||||
|
||||
|
||||
#endif /* LWIP_IPV6_DHCP6 */
|
197
src/core/ipv6/ethip6.c
Normal file
197
src/core/ipv6/ethip6.c
Normal file
@ -0,0 +1,197 @@
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* Ethernet output for IPv6. Uses ND tables for link-layer addressing.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2010 Inico Technologies Ltd.
|
||||
* 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.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Ivan Delamer <delamer@inicotech.com>
|
||||
*
|
||||
*
|
||||
* Please coordinate changes and requests with Ivan Delamer
|
||||
* <delamer@inicotech.com>
|
||||
*/
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#if LWIP_IPV6 && LWIP_ETHERNET
|
||||
|
||||
#include "lwip/ethip6.h"
|
||||
#include "lwip/nd6.h"
|
||||
#include "lwip/pbuf.h"
|
||||
#include "lwip/ip6.h"
|
||||
#include "lwip/ip6_addr.h"
|
||||
#include "lwip/ip6_chksum.h"
|
||||
#include "lwip/netif.h"
|
||||
#include "lwip/icmp6.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#define ETHTYPE_IPV6 0x86dd
|
||||
|
||||
/** The ethernet address */
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/bpstruct.h"
|
||||
#endif
|
||||
PACK_STRUCT_BEGIN
|
||||
struct eth_addr {
|
||||
PACK_STRUCT_FIELD(u8_t addr[6]);
|
||||
} PACK_STRUCT_STRUCT;
|
||||
PACK_STRUCT_END
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/epstruct.h"
|
||||
#endif
|
||||
|
||||
/** Ethernet header */
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/bpstruct.h"
|
||||
#endif
|
||||
PACK_STRUCT_BEGIN
|
||||
struct eth_hdr {
|
||||
#if ETH_PAD_SIZE
|
||||
PACK_STRUCT_FIELD(u8_t padding[ETH_PAD_SIZE]);
|
||||
#endif
|
||||
PACK_STRUCT_FIELD(struct eth_addr dest);
|
||||
PACK_STRUCT_FIELD(struct eth_addr src);
|
||||
PACK_STRUCT_FIELD(u16_t type);
|
||||
} PACK_STRUCT_STRUCT;
|
||||
PACK_STRUCT_END
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/epstruct.h"
|
||||
#endif
|
||||
|
||||
#define SIZEOF_ETH_HDR (14 + ETH_PAD_SIZE)
|
||||
|
||||
static err_t ethip6_send(struct netif *netif, struct pbuf *p, struct eth_addr *src, struct eth_addr *dst);
|
||||
|
||||
/**
|
||||
* Resolve and fill-in Ethernet address header for outgoing IPv6 packet.
|
||||
*
|
||||
* For IPv6 multicast, corresponding Ethernet addresses
|
||||
* are selected and the packet is transmitted on the link.
|
||||
*
|
||||
* For unicast addresses, ...
|
||||
*
|
||||
* @TODO anycast addresses
|
||||
*
|
||||
* @param netif The lwIP network interface which the IP packet will be sent on.
|
||||
* @param q The pbuf(s) containing the IP packet to be sent.
|
||||
* @param ip6addr The IP address of the packet destination.
|
||||
*
|
||||
* @return
|
||||
* - ERR_RTE No route to destination (no gateway to external networks),
|
||||
* or the return type of either etharp_query() or etharp_send_ip().
|
||||
*/
|
||||
err_t
|
||||
ethip6_output(struct netif *netif, struct pbuf *q, ip6_addr_t *ip6addr)
|
||||
{
|
||||
struct eth_addr dest;
|
||||
s8_t i;
|
||||
|
||||
/* make room for Ethernet header - should not fail */
|
||||
if (pbuf_header(q, sizeof(struct eth_hdr)) != 0) {
|
||||
/* bail out */
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS,
|
||||
("etharp_output: could not allocate room for header.\n"));
|
||||
return ERR_BUF;
|
||||
}
|
||||
|
||||
/* multicast destination IP address? */
|
||||
if (ip6_addr_ismulticast(ip6addr)) {
|
||||
/* Hash IP multicast address to MAC address.*/
|
||||
dest.addr[0] = 0x33;
|
||||
dest.addr[1] = 0x33;
|
||||
dest.addr[2] = ((u8_t *)(&(ip6addr->addr[3])))[0];
|
||||
dest.addr[3] = ((u8_t *)(&(ip6addr->addr[3])))[1];
|
||||
dest.addr[4] = ((u8_t *)(&(ip6addr->addr[3])))[2];
|
||||
dest.addr[5] = ((u8_t *)(&(ip6addr->addr[3])))[3];
|
||||
|
||||
/* Send out. */
|
||||
return ethip6_send(netif, q, (struct eth_addr*)(netif->hwaddr), &dest);
|
||||
}
|
||||
|
||||
/* We have a unicast destination IP address */
|
||||
/* TODO anycast? */
|
||||
/* Get next hop record. */
|
||||
i = nd6_get_next_hop_entry(ip6addr, netif);
|
||||
if (i < 0) {
|
||||
/* failed to get a next hop neighbor record. */
|
||||
return ERR_MEM;
|
||||
}
|
||||
|
||||
/* Now that we have a destination record, send or queue the packet. */
|
||||
if (neighbor_cache[i].state == ND6_STALE) {
|
||||
/* Switch to delay state. */
|
||||
neighbor_cache[i].state = ND6_DELAY;
|
||||
neighbor_cache[i].counter.delay_time = LWIP_ND6_DELAY_FIRST_PROBE_TIME;
|
||||
}
|
||||
/* TODO should we send or queue if PROBE? send for now, to let unicast NS pass. */
|
||||
if ((neighbor_cache[i].state == ND6_REACHABLE) ||
|
||||
(neighbor_cache[i].state == ND6_DELAY) ||
|
||||
(neighbor_cache[i].state == ND6_PROBE)) {
|
||||
|
||||
/* Send out. */
|
||||
SMEMCPY(dest.addr, neighbor_cache[i].lladdr, 6);
|
||||
return ethip6_send(netif, q, (struct eth_addr*)(netif->hwaddr), &dest);
|
||||
}
|
||||
|
||||
/* We should queue packet on this interface. */
|
||||
pbuf_header(q, -(s16_t)SIZEOF_ETH_HDR);
|
||||
nd6_queue_packet(i, q);
|
||||
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send an IPv6 packet on the network using netif->linkoutput
|
||||
* The ethernet header is filled in before sending.
|
||||
*
|
||||
* @params netif the lwIP network interface on which to send the packet
|
||||
* @params p the packet to send, p->payload pointing to the (uninitialized) ethernet header
|
||||
* @params src the source MAC address to be copied into the ethernet header
|
||||
* @params dst the destination MAC address to be copied into the ethernet header
|
||||
* @return ERR_OK if the packet was sent, any other err_t on failure
|
||||
*/
|
||||
static err_t
|
||||
ethip6_send(struct netif *netif, struct pbuf *p, struct eth_addr *src, struct eth_addr *dst)
|
||||
{
|
||||
struct eth_hdr *ethhdr = (struct eth_hdr *)p->payload;
|
||||
|
||||
LWIP_ASSERT("netif->hwaddr_len must be 6 for ethip6!",
|
||||
(netif->hwaddr_len == 6));
|
||||
SMEMCPY(ðhdr->dest, dst, 6);
|
||||
SMEMCPY(ðhdr->src, src, 6);
|
||||
ethhdr->type = PP_HTONS(ETHTYPE_IPV6);
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("ethip6_send: sending packet %p\n", (void *)p));
|
||||
/* send the packet */
|
||||
return netif->linkoutput(netif, p);
|
||||
}
|
||||
|
||||
#endif /* LWIP_IPV6 && LWIP_ETHERNET */
|
176
src/core/ipv6/ip6_chksum.c
Normal file
176
src/core/ipv6/ip6_chksum.c
Normal file
@ -0,0 +1,176 @@
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* IPv6 Checksum helper functions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2010 Inico Technologies Ltd.
|
||||
* 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.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Ivan Delamer <delamer@inicotech.com>
|
||||
*
|
||||
*
|
||||
* Please coordinate changes and requests with Ivan Delamer
|
||||
* <delamer@inicotech.com>
|
||||
*/
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#if LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */
|
||||
|
||||
#include "lwip/ip6_addr.h"
|
||||
#include "lwip/ip6_chksum.h"
|
||||
#include "lwip/inet_chksum.h"
|
||||
#include "lwip/def.h"
|
||||
|
||||
#ifndef LWIP_CHKSUM
|
||||
# define LWIP_CHKSUM lwip_standard_chksum
|
||||
extern u16_t lwip_standard_chksum(void *dataptr, u16_t len);
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* Calculates the checksum with IPv6 pseudo header used by TCP and UDP for a pbuf chain.
|
||||
* IPv6 addresses are expected to be in network byte order.
|
||||
*
|
||||
* @param p chain of pbufs over that a checksum should be calculated (ip data part)
|
||||
* @param src source ipv6 address (used for checksum of pseudo header)
|
||||
* @param dst destination ipv6 address (used for checksum of pseudo header)
|
||||
* @param proto ipv6 protocol/next header (used for checksum of pseudo header)
|
||||
* @param proto_len length of the ipv6 payload (used for checksum of pseudo header)
|
||||
* @return checksum (as u16_t) to be saved directly in the protocol header
|
||||
*/
|
||||
u16_t
|
||||
ip6_chksum_pseudo(struct pbuf *p,
|
||||
ip6_addr_t *src, ip6_addr_t *dest,
|
||||
u8_t proto, u16_t proto_len)
|
||||
{
|
||||
u32_t acc;
|
||||
u32_t addr;
|
||||
struct pbuf *q;
|
||||
u8_t swapped;
|
||||
|
||||
acc = 0;
|
||||
swapped = 0;
|
||||
/* iterate through all pbuf in chain */
|
||||
for(q = p; q != NULL; q = q->next) {
|
||||
acc += LWIP_CHKSUM(q->payload, q->len);
|
||||
/* fold the upper bit down */
|
||||
acc = FOLD_U32T(acc);
|
||||
if (q->len % 2 != 0) {
|
||||
swapped = 1 - swapped;
|
||||
acc = SWAP_BYTES_IN_WORD(acc);
|
||||
}
|
||||
}
|
||||
if (swapped) {
|
||||
acc = SWAP_BYTES_IN_WORD(acc);
|
||||
}
|
||||
|
||||
for (swapped = 0; swapped < 4; swapped++) {
|
||||
addr = src->addr[swapped];
|
||||
acc += (addr & 0xffffUL);
|
||||
acc += ((addr >> 16) & 0xffffUL);
|
||||
addr = dest->addr[swapped];
|
||||
acc += (addr & 0xffffUL);
|
||||
acc += ((addr >> 16) & 0xffffUL);
|
||||
}
|
||||
acc += (u32_t)htons((u16_t)proto);
|
||||
acc += (u32_t)htons(proto_len);
|
||||
|
||||
/* Fold 32-bit sum to 16 bits
|
||||
calling this twice is propably faster than if statements... */
|
||||
acc = FOLD_U32T(acc);
|
||||
acc = FOLD_U32T(acc);
|
||||
LWIP_DEBUGF(INET_DEBUG, ("ip6_chksum_pseudo(): pbuf chain lwip_chksum()=%"X32_F"\n", acc));
|
||||
return (u16_t)~(acc & 0xffffUL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the checksum with IPv6 pseudo header used by TCP and UDP for a pbuf chain.
|
||||
* IPv6 addresses are expected to be in network byte order. Will only compute for a
|
||||
* portion of the payload.
|
||||
*
|
||||
* @param p chain of pbufs over that a checksum should be calculated (ip data part)
|
||||
* @param src source ipv6 address (used for checksum of pseudo header)
|
||||
* @param dst destination ipv6 address (used for checksum of pseudo header)
|
||||
* @param proto ipv6 protocol/next header (used for checksum of pseudo header)
|
||||
* @param proto_len length of the ipv6 payload (used for checksum of pseudo header)
|
||||
* @param chksum_len number of payload bytes used to compute chksum
|
||||
* @return checksum (as u16_t) to be saved directly in the protocol header
|
||||
*/
|
||||
u16_t
|
||||
ip6_chksum_pseudo_partial(struct pbuf *p,
|
||||
ip6_addr_t *src, ip6_addr_t *dest,
|
||||
u8_t proto, u16_t proto_len, u16_t chksum_len)
|
||||
{
|
||||
u32_t acc;
|
||||
u32_t addr;
|
||||
struct pbuf *q;
|
||||
u8_t swapped;
|
||||
u16_t chklen;
|
||||
|
||||
acc = 0;
|
||||
swapped = 0;
|
||||
/* iterate through all pbuf in chain */
|
||||
for(q = p; (q != NULL) && (chksum_len > 0); q = q->next) {
|
||||
chklen = q->len;
|
||||
if (chklen > chksum_len) {
|
||||
chklen = chksum_len;
|
||||
}
|
||||
acc += LWIP_CHKSUM(q->payload, chklen);
|
||||
chksum_len -= chklen;
|
||||
acc = FOLD_U32T(acc);
|
||||
if (q->len % 2 != 0) {
|
||||
swapped = 1 - swapped;
|
||||
acc = SWAP_BYTES_IN_WORD(acc);
|
||||
}
|
||||
}
|
||||
if (swapped) {
|
||||
acc = SWAP_BYTES_IN_WORD(acc);
|
||||
}
|
||||
|
||||
for (swapped = 0; swapped < 4; swapped++) {
|
||||
addr = src->addr[swapped];
|
||||
acc += (addr & 0xffffUL);
|
||||
acc += ((addr >> 16) & 0xffffUL);
|
||||
addr = dest->addr[swapped];
|
||||
acc += (addr & 0xffffUL);
|
||||
acc += ((addr >> 16) & 0xffffUL);
|
||||
}
|
||||
acc += (u32_t)htons((u16_t)proto);
|
||||
acc += (u32_t)htons(proto_len);
|
||||
|
||||
/* Fold 32-bit sum to 16 bits
|
||||
calling this twice is propably faster than if statements... */
|
||||
acc = FOLD_U32T(acc);
|
||||
acc = FOLD_U32T(acc);
|
||||
LWIP_DEBUGF(INET_DEBUG, ("ip6_chksum_pseudo_partial(): pbuf chain lwip_chksum()=%"X32_F"\n", acc));
|
||||
return (u16_t)~(acc & 0xffffUL);
|
||||
}
|
||||
|
||||
#endif /* LWIP_IPV6 */
|
689
src/core/ipv6/ip6_frag.c
Normal file
689
src/core/ipv6/ip6_frag.c
Normal file
@ -0,0 +1,689 @@
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* IPv6 fragmentation and reassembly.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2010 Inico Technologies Ltd.
|
||||
* 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.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Ivan Delamer <delamer@inicotech.com>
|
||||
*
|
||||
*
|
||||
* Please coordinate changes and requests with Ivan Delamer
|
||||
* <delamer@inicotech.com>
|
||||
*/
|
||||
|
||||
#include "lwip/opt.h"
|
||||
#include "lwip/ip6_frag.h"
|
||||
#include "lwip/ip6.h"
|
||||
#include "lwip/icmp6.h"
|
||||
#include "lwip/nd6.h"
|
||||
|
||||
#include "lwip/pbuf.h"
|
||||
#include "lwip/memp.h"
|
||||
#include "lwip/stats.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#if LWIP_IPV6_REASS /* don't build if not configured for use in lwipopts.h */
|
||||
|
||||
|
||||
/** Setting this to 0, you can turn off checking the fragments for overlapping
|
||||
* regions. The code gets a little smaller. Only use this if you know that
|
||||
* overlapping won't occur on your network! */
|
||||
#ifndef IP_REASS_CHECK_OVERLAP
|
||||
#define IP_REASS_CHECK_OVERLAP 1
|
||||
#endif /* IP_REASS_CHECK_OVERLAP */
|
||||
|
||||
/** Set to 0 to prevent freeing the oldest datagram when the reassembly buffer is
|
||||
* full (IP_REASS_MAX_PBUFS pbufs are enqueued). The code gets a little smaller.
|
||||
* Datagrams will be freed by timeout only. Especially useful when MEMP_NUM_REASSDATA
|
||||
* is set to 1, so one datagram can be reassembled at a time, only. */
|
||||
#ifndef IP_REASS_FREE_OLDEST
|
||||
#define IP_REASS_FREE_OLDEST 1
|
||||
#endif /* IP_REASS_FREE_OLDEST */
|
||||
|
||||
#define IP_REASS_FLAG_LASTFRAG 0x01
|
||||
|
||||
/** This is a helper struct which holds the starting
|
||||
* offset and the ending offset of this fragment to
|
||||
* easily chain the fragments.
|
||||
* It has the same packing requirements as the IPv6 header, since it replaces
|
||||
* the Fragment Header in memory in incoming fragments to keep
|
||||
* track of the various fragments.
|
||||
*/
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/bpstruct.h"
|
||||
#endif
|
||||
PACK_STRUCT_BEGIN
|
||||
struct ip6_reass_helper {
|
||||
PACK_STRUCT_FIELD(struct pbuf *next_pbuf);
|
||||
PACK_STRUCT_FIELD(u16_t start);
|
||||
PACK_STRUCT_FIELD(u16_t end);
|
||||
} PACK_STRUCT_STRUCT;
|
||||
PACK_STRUCT_END
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/epstruct.h"
|
||||
#endif
|
||||
|
||||
/* static variables */
|
||||
static struct ip6_reassdata *reassdatagrams;
|
||||
static u16_t ip6_reass_pbufcount;
|
||||
|
||||
/* Forward declarations. */
|
||||
static void ip6_reass_free_complete_datagram(struct ip6_reassdata *ipr);
|
||||
#if IP_REASS_FREE_OLDEST
|
||||
static void ip6_reass_remove_oldest_datagram(struct ip6_reassdata *ipr, int pbufs_needed);
|
||||
#endif /* IP_REASS_FREE_OLDEST */
|
||||
|
||||
void
|
||||
ip6_reass_tmr(void)
|
||||
{
|
||||
struct ip6_reassdata *r, *tmp;
|
||||
|
||||
r = reassdatagrams;
|
||||
while (r != NULL) {
|
||||
/* Decrement the timer. Once it reaches 0,
|
||||
* clean up the incomplete fragment assembly */
|
||||
if (r->timer > 0) {
|
||||
r->timer--;
|
||||
r = r->next;
|
||||
} else {
|
||||
/* reassembly timed out */
|
||||
tmp = r;
|
||||
/* get the next pointer before freeing */
|
||||
r = r->next;
|
||||
/* free the helper struct and all enqueued pbufs */
|
||||
ip6_reass_free_complete_datagram(tmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Free a datagram (struct ip6_reassdata) and all its pbufs.
|
||||
* Updates the total count of enqueued pbufs (ip6_reass_pbufcount),
|
||||
* sends an ICMP time exceeded packet.
|
||||
*
|
||||
* @param ipr datagram to free
|
||||
*/
|
||||
static void
|
||||
ip6_reass_free_complete_datagram(struct ip6_reassdata *ipr)
|
||||
{
|
||||
struct ip6_reassdata *prev;
|
||||
u16_t pbufs_freed = 0;
|
||||
u8_t clen;
|
||||
struct pbuf *p;
|
||||
struct ip6_reass_helper *iprh;
|
||||
|
||||
#if LWIP_ICMP6
|
||||
iprh = (struct ip6_reass_helper *)ipr->p->payload;
|
||||
if (iprh->start == 0) {
|
||||
/* The first fragment was received, send ICMP time exceeded. */
|
||||
/* First, de-queue the first pbuf from r->p. */
|
||||
p = ipr->p;
|
||||
ipr->p = iprh->next_pbuf;
|
||||
/* Then, move back to the original header (we are now pointing to Fragment header). */
|
||||
pbuf_header(p, (u8_t*)p->payload - (u8_t*)ipr->iphdr);
|
||||
icmp6_time_exceeded(p, ICMP6_TE_FRAG);
|
||||
clen = pbuf_clen(p);
|
||||
LWIP_ASSERT("pbufs_freed + clen <= 0xffff", pbufs_freed + clen <= 0xffff);
|
||||
pbufs_freed += clen;
|
||||
pbuf_free(p);
|
||||
}
|
||||
#endif /* LWIP_ICMP6 */
|
||||
|
||||
/* First, free all received pbufs. The individual pbufs need to be released
|
||||
separately as they have not yet been chained */
|
||||
p = ipr->p;
|
||||
while (p != NULL) {
|
||||
struct pbuf *pcur;
|
||||
iprh = (struct ip6_reass_helper *)p->payload;
|
||||
pcur = p;
|
||||
/* get the next pointer before freeing */
|
||||
p = iprh->next_pbuf;
|
||||
clen = pbuf_clen(pcur);
|
||||
LWIP_ASSERT("pbufs_freed + clen <= 0xffff", pbufs_freed + clen <= 0xffff);
|
||||
pbufs_freed += clen;
|
||||
pbuf_free(pcur);
|
||||
}
|
||||
|
||||
/* Then, unchain the struct ip6_reassdata from the list and free it. */
|
||||
if (ipr == reassdatagrams) {
|
||||
reassdatagrams = ipr->next;
|
||||
} else {
|
||||
prev = reassdatagrams;
|
||||
while (prev != NULL) {
|
||||
if (prev->next == ipr) {
|
||||
break;
|
||||
}
|
||||
prev = prev->next;
|
||||
}
|
||||
if (prev != NULL) {
|
||||
prev->next = ipr->next;
|
||||
}
|
||||
}
|
||||
memp_free(MEMP_IP6_REASSDATA, ipr);
|
||||
|
||||
/* Finally, update number of pbufs in reassembly queue */
|
||||
LWIP_ASSERT("ip_reass_pbufcount >= clen", ip6_reass_pbufcount >= pbufs_freed);
|
||||
ip6_reass_pbufcount -= pbufs_freed;
|
||||
}
|
||||
|
||||
#if IP_REASS_FREE_OLDEST
|
||||
/**
|
||||
* Free the oldest datagram to make room for enqueueing new fragments.
|
||||
* The datagram ipr is not freed!
|
||||
*
|
||||
* @param ipr ip6_reassdata for the current fragment
|
||||
* @param pbufs_needed number of pbufs needed to enqueue
|
||||
* (used for freeing other datagrams if not enough space)
|
||||
*/
|
||||
static void
|
||||
ip6_reass_remove_oldest_datagram(struct ip6_reassdata *ipr, int pbufs_needed)
|
||||
{
|
||||
struct ip6_reassdata *r, *oldest;
|
||||
|
||||
/* Free datagrams until being allowed to enqueue 'pbufs_needed' pbufs,
|
||||
* but don't free the current datagram! */
|
||||
do {
|
||||
r = oldest = reassdatagrams;
|
||||
while (r != NULL) {
|
||||
if (r != ipr) {
|
||||
if (r->timer <= oldest->timer) {
|
||||
/* older than the previous oldest */
|
||||
oldest = r;
|
||||
}
|
||||
}
|
||||
r = r->next;
|
||||
}
|
||||
if (oldest != NULL) {
|
||||
ip6_reass_free_complete_datagram(oldest);
|
||||
}
|
||||
} while (((ip6_reass_pbufcount + pbufs_needed) > IP_REASS_MAX_PBUFS) && (reassdatagrams != NULL));
|
||||
}
|
||||
#endif /* IP_REASS_FREE_OLDEST */
|
||||
|
||||
/**
|
||||
* Reassembles incoming IPv6 fragments into an IPv6 datagram.
|
||||
*
|
||||
* @param p points to the IPv6 Fragment Header
|
||||
* @param len the length of the payload (after Fragment Header)
|
||||
* @return NULL if reassembly is incomplete, pbuf pointing to
|
||||
* IPv6 Header if reassembly is complete
|
||||
*/
|
||||
struct pbuf *
|
||||
ip6_reass(struct pbuf *p)
|
||||
{
|
||||
struct ip6_reassdata *ipr, *ipr_prev;
|
||||
struct ip6_reass_helper *iprh, *iprh_tmp, *iprh_prev=NULL;
|
||||
struct ip6_frag_hdr * frag_hdr;
|
||||
u16_t offset, len;
|
||||
u8_t clen, valid = 1;
|
||||
struct pbuf *q;
|
||||
|
||||
IP6_FRAG_STATS_INC(ip6_frag.recv);
|
||||
|
||||
frag_hdr = (struct ip6_frag_hdr *) p->payload;
|
||||
|
||||
clen = pbuf_clen(p);
|
||||
|
||||
offset = ntohs(frag_hdr->_fragment_offset);
|
||||
|
||||
/* Calculate fragment length from IPv6 payload length.
|
||||
* Adjust for headers before Fragment Header.
|
||||
* And finally adjust by Fragment Header length. */
|
||||
len = ntohs(ip6_current_header()->_plen);
|
||||
len -= ((u8_t*)p->payload - (u8_t*)ip6_current_header()) - IP6_HLEN;
|
||||
len -= IP6_FRAG_HLEN;
|
||||
|
||||
/* Look for the datagram the fragment belongs to in the current datagram queue,
|
||||
* remembering the previous in the queue for later dequeueing. */
|
||||
for (ipr = reassdatagrams, ipr_prev = NULL; ipr != NULL; ipr = ipr->next) {
|
||||
/* Check if the incoming fragment matches the one currently present
|
||||
in the reassembly buffer. If so, we proceed with copying the
|
||||
fragment into the buffer. */
|
||||
if ((frag_hdr->_identification == ipr->identification) &&
|
||||
ip6_addr_cmp(ip6_current_src_addr(), &(ipr->iphdr->src)) &&
|
||||
ip6_addr_cmp(ip6_current_dest_addr(), &(ipr->iphdr->dest))) {
|
||||
IP6_FRAG_STATS_INC(ip6_frag.cachehit);
|
||||
break;
|
||||
}
|
||||
ipr_prev = ipr;
|
||||
}
|
||||
|
||||
if (ipr == NULL) {
|
||||
/* Enqueue a new datagram into the datagram queue */
|
||||
ipr = (struct ip6_reassdata *)memp_malloc(MEMP_IP6_REASSDATA);
|
||||
if (ipr == NULL) {
|
||||
#if IP_REASS_FREE_OLDEST
|
||||
/* Make room and try again. */
|
||||
ip6_reass_remove_oldest_datagram(ipr, clen);
|
||||
ipr = (struct ip6_reassdata *)memp_malloc(MEMP_IP6_REASSDATA);
|
||||
if (ipr == NULL)
|
||||
#endif /* IP_REASS_FREE_OLDEST */
|
||||
{
|
||||
IP6_FRAG_STATS_INC(ip6_frag.memerr);
|
||||
IP6_FRAG_STATS_INC(ip6_frag.drop);
|
||||
goto nullreturn;
|
||||
}
|
||||
}
|
||||
|
||||
memset(ipr, 0, sizeof(struct ip6_reassdata));
|
||||
ipr->timer = IP_REASS_MAXAGE;
|
||||
|
||||
/* enqueue the new structure to the front of the list */
|
||||
ipr->next = reassdatagrams;
|
||||
reassdatagrams = ipr;
|
||||
|
||||
/* Use the current IPv6 header for src/dest address reference.
|
||||
* Eventually, we will replace it when we get the first fragment
|
||||
* (it might be this one, in any case, it is done later). */
|
||||
ipr->iphdr = (struct ip6_hdr *)ip6_current_header();
|
||||
|
||||
/* copy the fragmented packet id. */
|
||||
ipr->identification = frag_hdr->_identification;
|
||||
|
||||
/* copy the nexth field */
|
||||
ipr->nexth = frag_hdr->_nexth;
|
||||
}
|
||||
|
||||
/* Check if we are allowed to enqueue more datagrams. */
|
||||
if ((ip6_reass_pbufcount + clen) > IP_REASS_MAX_PBUFS) {
|
||||
#if IP_REASS_FREE_OLDEST
|
||||
ip6_reass_remove_oldest_datagram(ipr, clen);
|
||||
if ((ip6_reass_pbufcount + clen) > IP_REASS_MAX_PBUFS)
|
||||
#endif /* IP_REASS_FREE_OLDEST */
|
||||
{
|
||||
/* @todo: send ICMPv6 time exceeded here? */
|
||||
/* drop this pbuf */
|
||||
IP6_FRAG_STATS_INC(ip6_frag.memerr);
|
||||
IP6_FRAG_STATS_INC(ip6_frag.drop);
|
||||
goto nullreturn;
|
||||
}
|
||||
}
|
||||
|
||||
/* Overwrite Fragment Header with our own helper struct. */
|
||||
iprh = (struct ip6_reass_helper *)p->payload;
|
||||
iprh->next_pbuf = NULL;
|
||||
iprh->start = (offset & IP6_FRAG_OFFSET_MASK);
|
||||
iprh->end = (offset & IP6_FRAG_OFFSET_MASK) + len;
|
||||
|
||||
/* find the right place to insert this pbuf */
|
||||
/* Iterate through until we either get to the end of the list (append),
|
||||
* or we find on with a larger offset (insert). */
|
||||
for (q = ipr->p; q != NULL;) {
|
||||
iprh_tmp = (struct ip6_reass_helper*)q->payload;
|
||||
if (iprh->start < iprh_tmp->start) {
|
||||
#if IP_REASS_CHECK_OVERLAP
|
||||
if (iprh->end > iprh_tmp->start) {
|
||||
/* fragment overlaps with following, throw away */
|
||||
IP6_FRAG_STATS_INC(ip6_frag.proterr);
|
||||
IP6_FRAG_STATS_INC(ip6_frag.drop);
|
||||
goto nullreturn;
|
||||
}
|
||||
if (iprh_prev != NULL) {
|
||||
if (iprh->start < iprh_prev->end) {
|
||||
/* fragment overlaps with previous, throw away */
|
||||
IP6_FRAG_STATS_INC(ip6_frag.proterr);
|
||||
IP6_FRAG_STATS_INC(ip6_frag.drop);
|
||||
goto nullreturn;
|
||||
}
|
||||
}
|
||||
#endif /* IP_REASS_CHECK_OVERLAP */
|
||||
/* the new pbuf should be inserted before this */
|
||||
iprh->next_pbuf = q;
|
||||
if (iprh_prev != NULL) {
|
||||
/* not the fragment with the lowest offset */
|
||||
iprh_prev->next_pbuf = p;
|
||||
} else {
|
||||
/* fragment with the lowest offset */
|
||||
ipr->p = p;
|
||||
}
|
||||
break;
|
||||
} else if(iprh->start == iprh_tmp->start) {
|
||||
/* received the same datagram twice: no need to keep the datagram */
|
||||
IP6_FRAG_STATS_INC(ip6_frag.drop);
|
||||
goto nullreturn;
|
||||
#if IP_REASS_CHECK_OVERLAP
|
||||
} else if(iprh->start < iprh_tmp->end) {
|
||||
/* overlap: no need to keep the new datagram */
|
||||
IP6_FRAG_STATS_INC(ip6_frag.proterr);
|
||||
IP6_FRAG_STATS_INC(ip6_frag.drop);
|
||||
goto nullreturn;
|
||||
#endif /* IP_REASS_CHECK_OVERLAP */
|
||||
} else {
|
||||
/* Check if the fragments received so far have no gaps. */
|
||||
if (iprh_prev != NULL) {
|
||||
if (iprh_prev->end != iprh_tmp->start) {
|
||||
/* There is a fragment missing between the current
|
||||
* and the previous fragment */
|
||||
valid = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
q = iprh_tmp->next_pbuf;
|
||||
iprh_prev = iprh_tmp;
|
||||
}
|
||||
|
||||
/* If q is NULL, then we made it to the end of the list. Determine what to do now */
|
||||
if (q == NULL) {
|
||||
if (iprh_prev != NULL) {
|
||||
/* this is (for now), the fragment with the highest offset:
|
||||
* chain it to the last fragment */
|
||||
#if IP_REASS_CHECK_OVERLAP
|
||||
LWIP_ASSERT("check fragments don't overlap", iprh_prev->end <= iprh->start);
|
||||
#endif /* IP_REASS_CHECK_OVERLAP */
|
||||
iprh_prev->next_pbuf = p;
|
||||
if (iprh_prev->end != iprh->start) {
|
||||
valid = 0;
|
||||
}
|
||||
} else {
|
||||
#if IP_REASS_CHECK_OVERLAP
|
||||
LWIP_ASSERT("no previous fragment, this must be the first fragment!",
|
||||
ipr->p == NULL);
|
||||
#endif /* IP_REASS_CHECK_OVERLAP */
|
||||
/* this is the first fragment we ever received for this ip datagram */
|
||||
ipr->p = p;
|
||||
}
|
||||
}
|
||||
|
||||
/* Track the current number of pbufs current 'in-flight', in order to limit
|
||||
the number of fragments that may be enqueued at any one time */
|
||||
ip6_reass_pbufcount += clen;
|
||||
|
||||
/* Remember IPv6 header if this is the first fragment. */
|
||||
if (iprh->start == 0) {
|
||||
ipr->iphdr = (struct ip6_hdr *)ip6_current_header();
|
||||
}
|
||||
|
||||
/* If this is the last fragment, calculate total packet length. */
|
||||
if ((offset & IP6_FRAG_MORE_FLAG) == 0) {
|
||||
ipr->datagram_len = iprh->end;
|
||||
}
|
||||
|
||||
/* Additional validity tests: we have received first and last fragment. */
|
||||
iprh_tmp = (struct ip6_reass_helper*)ipr->p->payload;
|
||||
if (iprh_tmp->start != 0) {
|
||||
valid = 0;
|
||||
}
|
||||
if (ipr->datagram_len == 0) {
|
||||
valid = 0;
|
||||
}
|
||||
|
||||
/* Final validity test: no gaps between current and last fragment. */
|
||||
iprh_prev = iprh;
|
||||
q = iprh->next_pbuf;
|
||||
while (q != NULL) {
|
||||
iprh = (struct ip6_reass_helper*)q->payload;
|
||||
if (iprh_prev->end != iprh->start) {
|
||||
valid = 0;
|
||||
break;
|
||||
}
|
||||
iprh_prev = iprh;
|
||||
q = iprh->next_pbuf;
|
||||
}
|
||||
|
||||
if (valid) {
|
||||
/* All fragments have been received */
|
||||
|
||||
/* chain together the pbufs contained within the ip6_reassdata list. */
|
||||
iprh = (struct ip6_reass_helper*) ipr->p->payload;
|
||||
while(iprh != NULL) {
|
||||
|
||||
if (iprh->next_pbuf != NULL) {
|
||||
/* Save next helper struct (will be hidden in next step). */
|
||||
iprh_tmp = (struct ip6_reass_helper*) iprh->next_pbuf->payload;
|
||||
|
||||
/* hide the fragment header for every succeding fragment */
|
||||
pbuf_header(iprh->next_pbuf, -IP6_FRAG_HLEN);
|
||||
pbuf_cat(ipr->p, iprh->next_pbuf);
|
||||
}
|
||||
else {
|
||||
iprh_tmp = NULL;
|
||||
}
|
||||
|
||||
iprh = iprh_tmp;
|
||||
}
|
||||
|
||||
/* Adjust datagram length by adding header lengths. */
|
||||
ipr->datagram_len += ((u8_t*)ipr->p->payload - (u8_t*)ipr->iphdr)
|
||||
+ IP6_FRAG_HLEN
|
||||
- IP6_HLEN ;
|
||||
|
||||
/* Set payload length in ip header. */
|
||||
ipr->iphdr->_plen = htons(ipr->datagram_len);
|
||||
|
||||
/* Get the furst pbuf. */
|
||||
p = ipr->p;
|
||||
|
||||
/* Restore Fragment Header in first pbuf. Mark as "single fragment"
|
||||
* packet. Restore nexth. */
|
||||
frag_hdr = (struct ip6_frag_hdr *) p->payload;
|
||||
frag_hdr->_nexth = ipr->nexth;
|
||||
frag_hdr->reserved = 0;
|
||||
frag_hdr->_fragment_offset = 0;
|
||||
frag_hdr->_identification = 0;
|
||||
|
||||
/* Move pbuf back to IPv6 header. */
|
||||
pbuf_header(p, (u8_t*)p->payload - (u8_t*)ipr->iphdr);
|
||||
|
||||
/* release the sources allocate for the fragment queue entry */
|
||||
if (reassdatagrams == ipr) {
|
||||
/* it was the first in the list */
|
||||
reassdatagrams = ipr->next;
|
||||
} else {
|
||||
/* it wasn't the first, so it must have a valid 'prev' */
|
||||
LWIP_ASSERT("sanity check linked list", ipr_prev != NULL);
|
||||
ipr_prev->next = ipr->next;
|
||||
}
|
||||
memp_free(MEMP_IP6_REASSDATA, ipr);
|
||||
|
||||
/* and adjust the number of pbufs currently queued for reassembly. */
|
||||
ip6_reass_pbufcount -= pbuf_clen(p);
|
||||
|
||||
/* Return the pbuf chain */
|
||||
return p;
|
||||
}
|
||||
/* the datagram is not (yet?) reassembled completely */
|
||||
return NULL;
|
||||
|
||||
nullreturn:
|
||||
pbuf_free(p);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif /* LWIP_IPV6_REASS */
|
||||
|
||||
#if LWIP_IPV6_FRAG
|
||||
|
||||
/** Allocate a new struct pbuf_custom_ref */
|
||||
static struct pbuf_custom_ref*
|
||||
ip6_frag_alloc_pbuf_custom_ref(void)
|
||||
{
|
||||
return (struct pbuf_custom_ref*)memp_malloc(MEMP_FRAG_PBUF);
|
||||
}
|
||||
|
||||
/** Free a struct pbuf_custom_ref */
|
||||
static void
|
||||
ip6_frag_free_pbuf_custom_ref(struct pbuf_custom_ref* p)
|
||||
{
|
||||
LWIP_ASSERT("p != NULL", p != NULL);
|
||||
memp_free(MEMP_FRAG_PBUF, p);
|
||||
}
|
||||
|
||||
/** Free-callback function to free a 'struct pbuf_custom_ref', called by
|
||||
* pbuf_free. */
|
||||
static void
|
||||
ip6_frag_free_pbuf_custom(struct pbuf *p)
|
||||
{
|
||||
struct pbuf_custom_ref *pcr = (struct pbuf_custom_ref*)p;
|
||||
LWIP_ASSERT("pcr != NULL", pcr != NULL);
|
||||
LWIP_ASSERT("pcr == p", (void*)pcr == (void*)p);
|
||||
if (pcr->original != NULL) {
|
||||
pbuf_free(pcr->original);
|
||||
}
|
||||
ip6_frag_free_pbuf_custom_ref(pcr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fragment an IPv6 datagram if too large for the netif or path MTU.
|
||||
*
|
||||
* Chop the datagram in MTU sized chunks and send them in order
|
||||
* by pointing PBUF_REFs into p
|
||||
*
|
||||
* @param p ipv6 packet to send
|
||||
* @param netif the netif on which to send
|
||||
* @param dest destination ipv6 address to which to send
|
||||
*
|
||||
* @return ERR_OK if sent successfully, err_t otherwise
|
||||
*/
|
||||
err_t
|
||||
ip6_frag(struct pbuf *p, struct netif *netif, ip6_addr_t *dest)
|
||||
{
|
||||
struct ip6_hdr *original_ip6hdr;
|
||||
struct ip6_hdr *ip6hdr;
|
||||
struct ip6_frag_hdr * frag_hdr;
|
||||
struct pbuf *rambuf;
|
||||
struct pbuf *newpbuf;
|
||||
static u32_t identification;
|
||||
u16_t nfb;
|
||||
u16_t left, cop;
|
||||
u16_t mtu;
|
||||
u16_t fragment_offset = 0;
|
||||
u16_t last;
|
||||
u16_t poff = IP6_HLEN;
|
||||
u16_t newpbuflen = 0;
|
||||
u16_t left_to_copy;
|
||||
|
||||
identification++;
|
||||
|
||||
original_ip6hdr = (struct ip6_hdr *)p->payload;
|
||||
|
||||
mtu = nd6_get_destination_mtu(dest, netif);
|
||||
|
||||
/* TODO we assume there are no options in the unfragmentable part (IPv6 header). */
|
||||
left = p->tot_len - IP6_HLEN;
|
||||
|
||||
nfb = (mtu - (IP6_HLEN + IP6_FRAG_HLEN)) & IP6_FRAG_OFFSET_MASK;
|
||||
|
||||
while (left) {
|
||||
last = (left <= nfb);
|
||||
|
||||
/* Fill this fragment */
|
||||
cop = last ? left : nfb;
|
||||
|
||||
/* When not using a static buffer, create a chain of pbufs.
|
||||
* The first will be a PBUF_RAM holding the link, IPv6, and Fragment header.
|
||||
* The rest will be PBUF_REFs mirroring the pbuf chain to be fragged,
|
||||
* but limited to the size of an mtu.
|
||||
*/
|
||||
rambuf = pbuf_alloc(PBUF_LINK, IP6_HLEN + IP6_FRAG_HLEN, PBUF_RAM);
|
||||
if (rambuf == NULL) {
|
||||
IP6_FRAG_STATS_INC(ip6_frag.memerr);
|
||||
return ERR_MEM;
|
||||
}
|
||||
LWIP_ASSERT("this needs a pbuf in one piece!",
|
||||
(p->len >= (IP6_HLEN + IP6_FRAG_HLEN)));
|
||||
SMEMCPY(rambuf->payload, original_ip6hdr, IP6_HLEN);
|
||||
ip6hdr = (struct ip6_hdr *)rambuf->payload;
|
||||
frag_hdr = (struct ip6_frag_hdr *)((u8_t*)rambuf->payload + IP6_HLEN);
|
||||
|
||||
/* Can just adjust p directly for needed offset. */
|
||||
p->payload = (u8_t *)p->payload + poff;
|
||||
p->len -= poff;
|
||||
p->tot_len -= poff;
|
||||
|
||||
left_to_copy = cop;
|
||||
while (left_to_copy) {
|
||||
struct pbuf_custom_ref *pcr;
|
||||
newpbuflen = (left_to_copy < p->len) ? left_to_copy : p->len;
|
||||
/* Is this pbuf already empty? */
|
||||
if (!newpbuflen) {
|
||||
p = p->next;
|
||||
continue;
|
||||
}
|
||||
pcr = ip6_frag_alloc_pbuf_custom_ref();
|
||||
if (pcr == NULL) {
|
||||
pbuf_free(rambuf);
|
||||
IP6_FRAG_STATS_INC(ip6_frag.memerr);
|
||||
return ERR_MEM;
|
||||
}
|
||||
/* Mirror this pbuf, although we might not need all of it. */
|
||||
newpbuf = pbuf_alloced_custom(PBUF_RAW, newpbuflen, PBUF_REF, &pcr->pc, p->payload, newpbuflen);
|
||||
if (newpbuf == NULL) {
|
||||
ip6_frag_free_pbuf_custom_ref(pcr);
|
||||
pbuf_free(rambuf);
|
||||
IP6_FRAG_STATS_INC(ip6_frag.memerr);
|
||||
return ERR_MEM;
|
||||
}
|
||||
pbuf_ref(p);
|
||||
pcr->original = p;
|
||||
pcr->pc.custom_free_function = ip6_frag_free_pbuf_custom;
|
||||
|
||||
/* Add it to end of rambuf's chain, but using pbuf_cat, not pbuf_chain
|
||||
* so that it is removed when pbuf_dechain is later called on rambuf.
|
||||
*/
|
||||
pbuf_cat(rambuf, newpbuf);
|
||||
left_to_copy -= newpbuflen;
|
||||
if (left_to_copy) {
|
||||
p = p->next;
|
||||
}
|
||||
}
|
||||
poff = newpbuflen;
|
||||
|
||||
/* Set headers */
|
||||
frag_hdr->_nexth = original_ip6hdr->_nexth;
|
||||
frag_hdr->reserved = 0;
|
||||
frag_hdr->_fragment_offset = htons((fragment_offset & IP6_FRAG_OFFSET_MASK) | (last ? 0 : IP6_FRAG_MORE_FLAG));
|
||||
frag_hdr->_identification = htonl(identification);
|
||||
|
||||
IP6H_NEXTH_SET(ip6hdr, IP6_NEXTH_FRAGMENT);
|
||||
IP6H_PLEN_SET(ip6hdr, cop + IP6_FRAG_HLEN);
|
||||
|
||||
/* No need for separate header pbuf - we allowed room for it in rambuf
|
||||
* when allocated.
|
||||
*/
|
||||
IP6_FRAG_STATS_INC(ip6_frag.xmit);
|
||||
netif->output_ip6(netif, rambuf, dest);
|
||||
|
||||
/* Unfortunately we can't reuse rambuf - the hardware may still be
|
||||
* using the buffer. Instead we free it (and the ensuing chain) and
|
||||
* recreate it next time round the loop. If we're lucky the hardware
|
||||
* will have already sent the packet, the free will really free, and
|
||||
* there will be zero memory penalty.
|
||||
*/
|
||||
|
||||
pbuf_free(rambuf);
|
||||
left -= cop;
|
||||
fragment_offset += cop;
|
||||
}
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
#endif /* LWIP_IPV6_FRAG */
|
578
src/core/ipv6/mld6.c
Normal file
578
src/core/ipv6/mld6.c
Normal file
@ -0,0 +1,578 @@
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* Multicast listener discovery for IPv6. Aims to be compliant with RFC 2710.
|
||||
* No support for MLDv2.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2010 Inico Technologies Ltd.
|
||||
* 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.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Ivan Delamer <delamer@inicotech.com>
|
||||
*
|
||||
*
|
||||
* Please coordinate changes and requests with Ivan Delamer
|
||||
* <delamer@inicotech.com>
|
||||
*/
|
||||
|
||||
/* Based on igmp.c implementation of igmp v2 protocol */
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#if LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */
|
||||
|
||||
#include "lwip/mld6.h"
|
||||
#include "lwip/icmp6.h"
|
||||
#include "lwip/ip6.h"
|
||||
#include "lwip/ip6_addr.h"
|
||||
#include "lwip/ip6_chksum.h"
|
||||
#include "lwip/pbuf.h"
|
||||
#include "lwip/netif.h"
|
||||
#include "lwip/memp.h"
|
||||
#include "lwip/stats.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
|
||||
/*
|
||||
* MLD constants
|
||||
*/
|
||||
#define MLD6_HL 1
|
||||
#define MLD6_JOIN_DELAYING_MEMBER_TMR_MS (500)
|
||||
|
||||
#define MLD6_GROUP_NON_MEMBER 0
|
||||
#define MLD6_GROUP_DELAYING_MEMBER 1
|
||||
#define MLD6_GROUP_IDLE_MEMBER 2
|
||||
|
||||
|
||||
/* The list of joined groups. */
|
||||
static struct mld_group* mld_group_list;
|
||||
|
||||
|
||||
/* Forward declarations. */
|
||||
static struct mld_group * mld6_new_group(struct netif *ifp, ip6_addr_t *addr);
|
||||
static err_t mld6_free_group(struct mld_group *group);
|
||||
static void mld6_delayed_report(struct mld_group *group, u16_t maxresp);
|
||||
static void mld6_send(struct mld_group *group, u8_t type);
|
||||
|
||||
|
||||
/**
|
||||
* Stop MLD processing on interface
|
||||
*
|
||||
* @param netif network interface on which stop MLD processing
|
||||
*/
|
||||
err_t
|
||||
mld6_stop(struct netif *netif)
|
||||
{
|
||||
struct mld_group *group = mld_group_list;
|
||||
struct mld_group *prev = NULL;
|
||||
struct mld_group *next;
|
||||
|
||||
/* look for groups joined on this interface further down the list */
|
||||
while (group != NULL) {
|
||||
next = group->next;
|
||||
/* is it a group joined on this interface? */
|
||||
if (group->netif == netif) {
|
||||
/* is it the first group of the list? */
|
||||
if (group == mld_group_list) {
|
||||
mld_group_list = next;
|
||||
}
|
||||
/* is there a "previous" group defined? */
|
||||
if (prev != NULL) {
|
||||
prev->next = next;
|
||||
}
|
||||
/* disable the group at the MAC level */
|
||||
if (netif->mld_mac_filter != NULL) {
|
||||
netif->mld_mac_filter(netif, &(group->group_address), MLD6_DEL_MAC_FILTER);
|
||||
}
|
||||
/* free group */
|
||||
memp_free(MEMP_MLD6_GROUP, group);
|
||||
} else {
|
||||
/* change the "previous" */
|
||||
prev = group;
|
||||
}
|
||||
/* move to "next" */
|
||||
group = next;
|
||||
}
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Report MLD memberships for this interface
|
||||
*
|
||||
* @param netif network interface on which report MLD memberships
|
||||
*/
|
||||
void
|
||||
mld6_report_groups(struct netif *netif)
|
||||
{
|
||||
struct mld_group *group = mld_group_list;
|
||||
|
||||
while (group != NULL) {
|
||||
if (group->netif == netif) {
|
||||
mld6_delayed_report(group, MLD6_JOIN_DELAYING_MEMBER_TMR_MS);
|
||||
}
|
||||
group = group->next;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Search for a group that is joined on a netif
|
||||
*
|
||||
* @param ifp the network interface for which to look
|
||||
* @param addr the group ipv6 address to search for
|
||||
* @return a struct mld_group* if the group has been found,
|
||||
* NULL if the group wasn't found.
|
||||
*/
|
||||
struct mld_group *
|
||||
mld6_lookfor_group(struct netif *ifp, ip6_addr_t *addr)
|
||||
{
|
||||
struct mld_group *group = mld_group_list;
|
||||
|
||||
while (group != NULL) {
|
||||
if ((group->netif == ifp) && (ip6_addr_cmp(&(group->group_address), addr))) {
|
||||
return group;
|
||||
}
|
||||
group = group->next;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* create a new group
|
||||
*
|
||||
* @param ifp the network interface for which to create
|
||||
* @param addr the new group ipv6
|
||||
* @return a struct mld_group*,
|
||||
* NULL on memory error.
|
||||
*/
|
||||
static struct mld_group *
|
||||
mld6_new_group(struct netif *ifp, ip6_addr_t *addr)
|
||||
{
|
||||
struct mld_group *group;
|
||||
|
||||
group = (struct mld_group *)memp_malloc(MEMP_MLD6_GROUP);
|
||||
if (group != NULL) {
|
||||
group->netif = ifp;
|
||||
ip6_addr_set(&(group->group_address), addr);
|
||||
group->timer = 0; /* Not running */
|
||||
group->group_state = MLD6_GROUP_IDLE_MEMBER;
|
||||
group->last_reporter_flag = 0;
|
||||
group->use = 0;
|
||||
group->next = mld_group_list;
|
||||
|
||||
mld_group_list = group;
|
||||
}
|
||||
|
||||
return group;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a group in the mld_group_list and free
|
||||
*
|
||||
* @param group the group to remove
|
||||
* @return ERR_OK if group was removed from the list, an err_t otherwise
|
||||
*/
|
||||
static err_t
|
||||
mld6_free_group(struct mld_group *group)
|
||||
{
|
||||
err_t err = ERR_OK;
|
||||
|
||||
/* Is it the first group? */
|
||||
if (mld_group_list == group) {
|
||||
mld_group_list = group->next;
|
||||
} else {
|
||||
/* look for group further down the list */
|
||||
struct mld_group *tmpGroup;
|
||||
for (tmpGroup = mld_group_list; tmpGroup != NULL; tmpGroup = tmpGroup->next) {
|
||||
if (tmpGroup->next == group) {
|
||||
tmpGroup->next = group->next;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* Group not find group */
|
||||
if (tmpGroup == NULL)
|
||||
err = ERR_ARG;
|
||||
}
|
||||
/* free group */
|
||||
memp_free(MEMP_MLD6_GROUP, group);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Process an input MLD message. Called by icmp6_input.
|
||||
*
|
||||
* @param p the mld packet, p->payload pointing to the icmpv6 header
|
||||
* @param inp the netif on which this packet was received
|
||||
*/
|
||||
void
|
||||
mld6_input(struct pbuf *p, struct netif *inp)
|
||||
{
|
||||
struct mld_header * mld_hdr;
|
||||
struct mld_group* group;
|
||||
|
||||
MLD6_STATS_INC(mld6.recv);
|
||||
|
||||
/* Check that mld header fits in packet. */
|
||||
if (p->len < sizeof(struct mld_header)) {
|
||||
/* TODO debug message */
|
||||
pbuf_free(p);
|
||||
MLD6_STATS_INC(mld6.lenerr);
|
||||
MLD6_STATS_INC(mld6.drop);
|
||||
return;
|
||||
}
|
||||
|
||||
mld_hdr = (struct mld_header *)p->payload;
|
||||
|
||||
switch (mld_hdr->type) {
|
||||
case ICMP6_TYPE_MLQ: /* Multicast listener query. */
|
||||
{
|
||||
/* Is it a general query? */
|
||||
if (ip6_addr_isallnodes_linklocal(ip6_current_dest_addr()) &&
|
||||
ip6_addr_isany(&(mld_hdr->multicast_address))) {
|
||||
MLD6_STATS_INC(mld6.rx_general);
|
||||
/* Report all groups, except all nodes group, and if-local groups. */
|
||||
group = mld_group_list;
|
||||
while (group != NULL) {
|
||||
if ((group->netif == inp) &&
|
||||
(!(ip6_addr_ismulticast_iflocal(&(group->group_address)))) &&
|
||||
(!(ip6_addr_isallnodes_linklocal(&(group->group_address))))) {
|
||||
mld6_delayed_report(group, mld_hdr->max_resp_delay);
|
||||
}
|
||||
group = group->next;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Have we joined this group?
|
||||
* We use IP6 destination address to have a memory aligned copy.
|
||||
* mld_hdr->multicast_address should be the same. */
|
||||
MLD6_STATS_INC(mld6.rx_group);
|
||||
group = mld6_lookfor_group(inp, ip6_current_dest_addr());
|
||||
if (group != NULL) {
|
||||
/* Schedule a report. */
|
||||
mld6_delayed_report(group, mld_hdr->max_resp_delay);
|
||||
}
|
||||
}
|
||||
break; /* ICMP6_TYPE_MLQ */
|
||||
}
|
||||
case ICMP6_TYPE_MLR: /* Multicast listener report. */
|
||||
{
|
||||
/* Have we joined this group?
|
||||
* We use IP6 destination address to have a memory aligned copy.
|
||||
* mld_hdr->multicast_address should be the same. */
|
||||
MLD6_STATS_INC(mld6.rx_report);
|
||||
group = mld6_lookfor_group(inp, ip6_current_dest_addr());
|
||||
if (group != NULL) {
|
||||
/* If we are waiting to report, cancel it. */
|
||||
if (group->group_state == MLD6_GROUP_DELAYING_MEMBER) {
|
||||
group->timer = 0; /* stopped */
|
||||
group->group_state = MLD6_GROUP_IDLE_MEMBER;
|
||||
group->last_reporter_flag = 0;
|
||||
}
|
||||
}
|
||||
break; /* ICMP6_TYPE_MLR */
|
||||
}
|
||||
case ICMP6_TYPE_MLD: /* Multicast listener done. */
|
||||
{
|
||||
/* Do nothing, router will query us. */
|
||||
break; /* ICMP6_TYPE_MLD */
|
||||
}
|
||||
default:
|
||||
MLD6_STATS_INC(mld6.proterr);
|
||||
MLD6_STATS_INC(mld6.drop);
|
||||
break;
|
||||
}
|
||||
|
||||
pbuf_free(p);
|
||||
}
|
||||
|
||||
/**
|
||||
* Join a group on a network interface.
|
||||
*
|
||||
* @param srcaddr ipv6 address of the network interface which should
|
||||
* join a new group. If IP6_ADDR_ANY, join on all netifs
|
||||
* @param groupaddr the ipv6 address of the group to join
|
||||
* @return ERR_OK if group was joined on the netif(s), an err_t otherwise
|
||||
*/
|
||||
err_t
|
||||
mld6_joingroup(ip6_addr_t *srcaddr, ip6_addr_t *groupaddr)
|
||||
{
|
||||
err_t err = ERR_VAL; /* no matching interface */
|
||||
struct mld_group *group;
|
||||
struct netif *netif;
|
||||
u8_t match;
|
||||
u8_t i;
|
||||
|
||||
/* loop through netif's */
|
||||
netif = netif_list;
|
||||
while (netif != NULL) {
|
||||
/* Should we join this interface ? */
|
||||
match = 0;
|
||||
if (ip6_addr_isany(srcaddr)) {
|
||||
match = 1;
|
||||
}
|
||||
else {
|
||||
for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
|
||||
if (ip6_addr_cmp(srcaddr, netif_ip6_addr(netif, i))) {
|
||||
match = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (match) {
|
||||
/* find group or create a new one if not found */
|
||||
group = mld6_lookfor_group(netif, groupaddr);
|
||||
|
||||
if (group == NULL) {
|
||||
/* Joining a new group. Create a new group entry. */
|
||||
group = mld6_new_group(netif, groupaddr);
|
||||
if (group == NULL) {
|
||||
return ERR_MEM;
|
||||
}
|
||||
|
||||
/* Activate this address on the MAC layer. */
|
||||
if (netif->mld_mac_filter != NULL) {
|
||||
netif->mld_mac_filter(netif, groupaddr, MLD6_ADD_MAC_FILTER);
|
||||
}
|
||||
|
||||
/* Report our membership. */
|
||||
MLD6_STATS_INC(mld6.tx_report);
|
||||
mld6_send(group, ICMP6_TYPE_MLR);
|
||||
mld6_delayed_report(group, MLD6_JOIN_DELAYING_MEMBER_TMR_MS);
|
||||
}
|
||||
|
||||
/* Increment group use */
|
||||
group->use++;
|
||||
err = ERR_OK;
|
||||
}
|
||||
|
||||
/* proceed to next network interface */
|
||||
netif = netif->next;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* Leave a group on a network interface.
|
||||
*
|
||||
* @param srcaddr ipv6 address of the network interface which should
|
||||
* leave the group. If IP6_ISANY, leave on all netifs
|
||||
* @param groupaddr the ipv6 address of the group to leave
|
||||
* @return ERR_OK if group was left on the netif(s), an err_t otherwise
|
||||
*/
|
||||
err_t
|
||||
mld6_leavegroup(ip6_addr_t *srcaddr, ip6_addr_t *groupaddr)
|
||||
{
|
||||
err_t err = ERR_VAL; /* no matching interface */
|
||||
struct mld_group *group;
|
||||
struct netif *netif;
|
||||
u8_t match;
|
||||
u8_t i;
|
||||
|
||||
/* loop through netif's */
|
||||
netif = netif_list;
|
||||
while (netif != NULL) {
|
||||
/* Should we leave this interface ? */
|
||||
match = 0;
|
||||
if (ip6_addr_isany(srcaddr)) {
|
||||
match = 1;
|
||||
}
|
||||
else {
|
||||
for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
|
||||
if (ip6_addr_cmp(srcaddr, netif_ip6_addr(netif, i))) {
|
||||
match = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (match) {
|
||||
/* find group */
|
||||
group = mld6_lookfor_group(netif, groupaddr);
|
||||
|
||||
if (group != NULL) {
|
||||
/* Leave if there is no other use of the group */
|
||||
if (group->use <= 1) {
|
||||
/* If we are the last reporter for this group */
|
||||
if (group->last_reporter_flag) {
|
||||
MLD6_STATS_INC(mld6.tx_leave);
|
||||
mld6_send(group, ICMP6_TYPE_MLD);
|
||||
}
|
||||
|
||||
/* Disable the group at the MAC level */
|
||||
if (netif->mld_mac_filter != NULL) {
|
||||
netif->mld_mac_filter(netif, groupaddr, MLD6_DEL_MAC_FILTER);
|
||||
}
|
||||
|
||||
/* Free the group */
|
||||
mld6_free_group(group);
|
||||
} else {
|
||||
/* Decrement group use */
|
||||
group->use--;
|
||||
}
|
||||
/* Leave on this interface */
|
||||
err = ERR_OK;
|
||||
}
|
||||
}
|
||||
/* proceed to next network interface */
|
||||
netif = netif->next;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Periodic timer for mld processing. Must be called every
|
||||
* MLD6_TMR_INTERVAL milliseconds (100).
|
||||
*
|
||||
* When a delaying member expires, a membership report is sent.
|
||||
*/
|
||||
void
|
||||
mld6_tmr(void)
|
||||
{
|
||||
struct mld_group *group = mld_group_list;
|
||||
|
||||
while (group != NULL) {
|
||||
if (group->timer > 0) {
|
||||
group->timer--;
|
||||
if (group->timer == 0) {
|
||||
/* If the state is MLD6_GROUP_DELAYING_MEMBER then we send a report for this group */
|
||||
if (group->group_state == MLD6_GROUP_DELAYING_MEMBER) {
|
||||
MLD6_STATS_INC(mld6.tx_report);
|
||||
mld6_send(group, ICMP6_TYPE_MLR);
|
||||
group->group_state = MLD6_GROUP_IDLE_MEMBER;
|
||||
}
|
||||
}
|
||||
}
|
||||
group = group->next;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedule a delayed membership report for a group
|
||||
*
|
||||
* @param group the mld_group for which "delaying" membership report
|
||||
* should be sent
|
||||
* @param maxresp the max resp delay provided in the query
|
||||
*/
|
||||
static void
|
||||
mld6_delayed_report(struct mld_group *group, u16_t maxresp)
|
||||
{
|
||||
/* Convert maxresp from milliseconds to tmr ticks */
|
||||
maxresp = maxresp / MLD6_TMR_INTERVAL;
|
||||
if (maxresp == 0) {
|
||||
maxresp = 1;
|
||||
}
|
||||
|
||||
/* Randomize maxresp. */
|
||||
maxresp = (LWIP_RAND() % (maxresp - 1)) + 1;
|
||||
|
||||
/* Apply timer value if no report has been scheduled already. */
|
||||
if ((group->group_state == MLD6_GROUP_IDLE_MEMBER) ||
|
||||
((group->group_state == MLD6_GROUP_DELAYING_MEMBER) &&
|
||||
((group->timer == 0) || (maxresp < group->timer)))) {
|
||||
group->timer = maxresp;
|
||||
group->group_state = MLD6_GROUP_DELAYING_MEMBER;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a MLD message (report or done).
|
||||
*
|
||||
* An IPv6 hop-by-hop options header with a router alert option
|
||||
* is prepended.
|
||||
*
|
||||
* @param group the group to report or quit
|
||||
* @param type ICMP6_TYPE_MLR (report) or ICMP6_TYPE_MLD (done)
|
||||
*/
|
||||
static void
|
||||
mld6_send(struct mld_group *group, u8_t type)
|
||||
{
|
||||
struct mld_header * mld_hdr;
|
||||
struct pbuf * p;
|
||||
ip6_addr_t * src_addr;
|
||||
|
||||
/* Allocate a packet. Size is MLD header + IPv6 Hop-by-hop options header. */
|
||||
p = pbuf_alloc(PBUF_IP, sizeof(struct mld_header) + sizeof(struct ip6_hbh_hdr), PBUF_RAM);
|
||||
if ((p == NULL) || (p->len < (sizeof(struct mld_header) + sizeof(struct ip6_hbh_hdr)))) {
|
||||
/* We couldn't allocate a suitable pbuf. drop it. */
|
||||
if (p != NULL) {
|
||||
pbuf_free(p);
|
||||
}
|
||||
MLD6_STATS_INC(mld6.memerr);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Move to make room for Hop-by-hop options header. */
|
||||
if (pbuf_header(p, -IP6_HBH_HLEN)) {
|
||||
pbuf_free(p);
|
||||
MLD6_STATS_INC(mld6.lenerr);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Select our source address. */
|
||||
if (!ip6_addr_isvalid(netif_ip6_addr_state(group->netif, 0))) {
|
||||
/* This is a special case, when we are performing duplicate address detection.
|
||||
* We must join the multicast group, but we don't have a valid address yet. */
|
||||
src_addr = IP6_ADDR_ANY;
|
||||
} else {
|
||||
/* Use link-local address as source address. */
|
||||
src_addr = netif_ip6_addr(group->netif, 0);
|
||||
}
|
||||
|
||||
/* MLD message header pointer. */
|
||||
mld_hdr = (struct mld_header *)p->payload;
|
||||
|
||||
/* Set fields. */
|
||||
mld_hdr->type = type;
|
||||
mld_hdr->code = 0;
|
||||
mld_hdr->chksum = 0;
|
||||
mld_hdr->max_resp_delay = 0;
|
||||
mld_hdr->reserved = 0;
|
||||
ip6_addr_set(&(mld_hdr->multicast_address), &(group->group_address));
|
||||
|
||||
mld_hdr->chksum = ip6_chksum_pseudo(p, src_addr, &(group->group_address),
|
||||
IP6_NEXTH_ICMP6, p->len);
|
||||
|
||||
/* Add hop-by-hop headers options: router alert with MLD value. */
|
||||
ip6_options_add_hbh_ra(p, IP6_NEXTH_ICMP6, IP6_ROUTER_ALERT_VALUE_MLD);
|
||||
|
||||
/* Send the packet out. */
|
||||
MLD6_STATS_INC(mld6.xmit);
|
||||
ip6_output_if(p, (ip6_addr_isany(src_addr)) ? NULL : src_addr, &(group->group_address),
|
||||
MLD6_HL, 0, IP6_NEXTH_HOPBYHOP, group->netif);
|
||||
pbuf_free(p);
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif /* LWIP_IPV6 */
|
1728
src/core/ipv6/nd6.c
Normal file
1728
src/core/ipv6/nd6.c
Normal file
File diff suppressed because it is too large
Load Diff
58
src/include/ipv6/lwip/dhcp6.h
Normal file
58
src/include/ipv6/lwip/dhcp6.h
Normal file
@ -0,0 +1,58 @@
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* IPv6 address autoconfiguration as per RFC 4862.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2010 Inico Technologies Ltd.
|
||||
* 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.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Ivan Delamer <delamer@inicotech.com>
|
||||
*
|
||||
* IPv6 address autoconfiguration as per RFC 4862.
|
||||
*
|
||||
* Please coordinate changes and requests with Ivan Delamer
|
||||
* <delamer@inicotech.com>
|
||||
*/
|
||||
|
||||
#ifndef __LWIP_IP6_DHCP6_H__
|
||||
#define __LWIP_IP6_DHCP6_H__
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#if LWIP_IPV6_DHCP6 /* don't build if not configured for use in lwipopts.h */
|
||||
|
||||
|
||||
struct dhcp6
|
||||
{
|
||||
TODO: implement DHCP6
|
||||
};
|
||||
|
||||
#endif /* LWIP_IPV6_DHCP6 */
|
||||
|
||||
#endif /* __LWIP_IP6_DHCP6_H__ */
|
68
src/include/ipv6/lwip/ethip6.h
Normal file
68
src/include/ipv6/lwip/ethip6.h
Normal file
@ -0,0 +1,68 @@
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* Ethernet output for IPv6. Uses ND tables for link-layer addressing.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2010 Inico Technologies Ltd.
|
||||
* 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.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Ivan Delamer <delamer@inicotech.com>
|
||||
*
|
||||
*
|
||||
* Please coordinate changes and requests with Ivan Delamer
|
||||
* <delamer@inicotech.com>
|
||||
*/
|
||||
|
||||
#ifndef __LWIP_ETHIP6_H__
|
||||
#define __LWIP_ETHIP6_H__
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#if LWIP_IPV6 && LWIP_ETHERNET /* don't build if not configured for use in lwipopts.h */
|
||||
|
||||
#include "lwip/pbuf.h"
|
||||
#include "lwip/ip6.h"
|
||||
#include "lwip/ip6_addr.h"
|
||||
#include "lwip/netif.h"
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
err_t ethip6_output(struct netif *netif, struct pbuf *q, ip6_addr_t *ip6addr);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* LWIP_IPV6 && LWIP_ETHERNET */
|
||||
|
||||
#endif /* __LWIP_ETHIP6_H__ */
|
152
src/include/ipv6/lwip/icmp6.h
Normal file
152
src/include/ipv6/lwip/icmp6.h
Normal file
@ -0,0 +1,152 @@
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* IPv6 version of ICMP, as per RFC 4443.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2010 Inico Technologies Ltd.
|
||||
* 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.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Ivan Delamer <delamer@inicotech.com>
|
||||
*
|
||||
*
|
||||
* Please coordinate changes and requests with Ivan Delamer
|
||||
* <delamer@inicotech.com>
|
||||
*/
|
||||
#ifndef __LWIP_ICMP6_H__
|
||||
#define __LWIP_ICMP6_H__
|
||||
|
||||
#include "lwip/opt.h"
|
||||
#include "lwip/pbuf.h"
|
||||
#include "lwip/ip6_addr.h"
|
||||
#include "lwip/netif.h"
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
enum icmp6_type {
|
||||
ICMP6_TYPE_DUR = 1, /* Destination unreachable */
|
||||
ICMP6_TYPE_PTB = 2, /* Packet too big */
|
||||
ICMP6_TYPE_TE = 3, /* Time exceeded */
|
||||
ICMP6_TYPE_PP = 4, /* Parameter problem */
|
||||
ICMP6_TYPE_PE1 = 100, /* Private experimentation */
|
||||
ICMP6_TYPE_PE2 = 101, /* Private experimentation */
|
||||
ICMP6_TYPE_RSV_ERR = 127, /* Reserved for expansion of error messages */
|
||||
|
||||
ICMP6_TYPE_EREQ = 128, /* Echo request */
|
||||
ICMP6_TYPE_EREP = 129, /* Echo reply */
|
||||
ICMP6_TYPE_MLQ = 130, /* Multicast listener query */
|
||||
ICMP6_TYPE_MLR = 131, /* Multicast listener report */
|
||||
ICMP6_TYPE_MLD = 132, /* Multicast listener done */
|
||||
ICMP6_TYPE_RS = 133, /* Router solicitation */
|
||||
ICMP6_TYPE_RA = 134, /* Router advertisement */
|
||||
ICMP6_TYPE_NS = 135, /* Neighbor solicitation */
|
||||
ICMP6_TYPE_NA = 136, /* Neighbor advertisement */
|
||||
ICMP6_TYPE_RD = 137, /* Redirect */
|
||||
ICMP6_TYPE_MRA = 151, /* Multicast router advertisement */
|
||||
ICMP6_TYPE_MRS = 152, /* Multicast router solicitation */
|
||||
ICMP6_TYPE_MRT = 153, /* Multicast router termination */
|
||||
ICMP6_TYPE_PE3 = 200, /* Private experimentation */
|
||||
ICMP6_TYPE_PE4 = 201, /* Private experimentation */
|
||||
ICMP6_TYPE_RSV_INF = 255 /* Reserved for expansion of informational messages */
|
||||
};
|
||||
|
||||
enum icmp6_dur_code {
|
||||
ICMP6_DUR_NO_ROUTE = 0, /* No route to destination */
|
||||
ICMP6_DUR_PROHIBITED = 1, /* Communication with destination administratively prohibited */
|
||||
ICMP6_DUR_SCOPE = 2, /* Beyond scope of source address */
|
||||
ICMP6_DUR_ADDRESS = 3, /* Address unreachable */
|
||||
ICMP6_DUR_PORT = 4, /* Port unreachable */
|
||||
ICMP6_DUR_POLICY = 5, /* Source address failed ingress/egress policy */
|
||||
ICMP6_DUR_REJECT_ROUTE = 6 /* Reject route to destination */
|
||||
};
|
||||
|
||||
enum icmp6_te_code {
|
||||
ICMP6_TE_HL = 0, /* Hop limit exceeded in transit */
|
||||
ICMP6_TE_FRAG = 1 /* Fragment reassembly time exceeded */
|
||||
};
|
||||
|
||||
enum icmp6_pp_code {
|
||||
ICMP6_PP_FIELD = 0, /* Erroneous header field encountered */
|
||||
ICMP6_PP_HEADER = 1, /* Unrecognized next header type encountered */
|
||||
ICMP6_PP_OPTION = 2, /* Unrecognized IPv6 option encountered */
|
||||
};
|
||||
|
||||
/** This is the standard ICMP6 header. */
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/bpstruct.h"
|
||||
#endif
|
||||
PACK_STRUCT_BEGIN
|
||||
struct icmp6_hdr {
|
||||
PACK_STRUCT_FIELD(u8_t type);
|
||||
PACK_STRUCT_FIELD(u8_t code);
|
||||
PACK_STRUCT_FIELD(u16_t chksum);
|
||||
PACK_STRUCT_FIELD(u32_t data);
|
||||
} PACK_STRUCT_STRUCT;
|
||||
PACK_STRUCT_END
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/epstruct.h"
|
||||
#endif
|
||||
|
||||
/** This is the ICMP6 header adapted for echo req/resp. */
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/bpstruct.h"
|
||||
#endif
|
||||
PACK_STRUCT_BEGIN
|
||||
struct icmp6_echo_hdr {
|
||||
PACK_STRUCT_FIELD(u8_t type);
|
||||
PACK_STRUCT_FIELD(u8_t code);
|
||||
PACK_STRUCT_FIELD(u16_t chksum);
|
||||
PACK_STRUCT_FIELD(u16_t id);
|
||||
PACK_STRUCT_FIELD(u16_t seqno);
|
||||
} PACK_STRUCT_STRUCT;
|
||||
PACK_STRUCT_END
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/epstruct.h"
|
||||
#endif
|
||||
|
||||
|
||||
#if LWIP_ICMP6 && LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */
|
||||
|
||||
void icmp6_input(struct pbuf *p, struct netif *inp);
|
||||
void icmp6_dest_unreach(struct pbuf *p, enum icmp6_dur_code c);
|
||||
void icmp6_packet_too_big(struct pbuf *p, u32_t mtu);
|
||||
void icmp6_time_exceeded(struct pbuf *p, enum icmp6_te_code c);
|
||||
void icmp6_param_problem(struct pbuf *p, enum icmp6_pp_code c, u32_t pointer);
|
||||
|
||||
#endif /* LWIP_ICMP6 && LWIP_IPV6 */
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* __LWIP_ICMP6_H__ */
|
89
src/include/ipv6/lwip/inet6.h
Normal file
89
src/include/ipv6/lwip/inet6.h
Normal file
@ -0,0 +1,89 @@
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* INET v6 addresses.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2010 Inico Technologies Ltd.
|
||||
* 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.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Ivan Delamer <delamer@inicotech.com>
|
||||
*
|
||||
*
|
||||
* Please coordinate changes and requests with Ivan Delamer
|
||||
* <delamer@inicotech.com>
|
||||
*/
|
||||
#ifndef __LWIP_INET6_H__
|
||||
#define __LWIP_INET6_H__
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#if LWIP_IPV6 && LWIP_SOCKET /* don't build if not configured for use in lwipopts.h */
|
||||
|
||||
#include "lwip/ip6_addr.h"
|
||||
#include "lwip/def.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** For compatibility with BSD code */
|
||||
struct in6_addr {
|
||||
u32_t s_addr[4];
|
||||
};
|
||||
|
||||
#define IN6ADDR_ANY_INIT {0,0,0,0}
|
||||
#define IN6ADDR_LOOPBACK_INIT {0,0,0,PP_HTONL(1)}
|
||||
|
||||
|
||||
|
||||
#define inet6_addr_from_ip6addr(target_in6addr, source_ip6addr) {(target_in6addr)->s_addr[0] = (source_ip6addr)->addr[0]; \
|
||||
(target_in6addr)->s_addr[1] = (source_ip6addr)->addr[1]; \
|
||||
(target_in6addr)->s_addr[2] = (source_ip6addr)->addr[2]; \
|
||||
(target_in6addr)->s_addr[3] = (source_ip6addr)->addr[3];}
|
||||
#define inet6_addr_to_ip6addr(target_ip6addr, source_in6addr) {(target_ip6addr)->addr[0] = (source_in6addr)->s_addr[0]; \
|
||||
(target_ip6addr)->addr[0] = (source_in6addr)->s_addr[0]; \
|
||||
(target_ip6addr)->addr[0] = (source_in6addr)->s_addr[0]; \
|
||||
(target_ip6addr)->addr[0] = (source_in6addr)->s_addr[0];}
|
||||
/* ATTENTION: the next define only works because both in6_addr and ip6_addr_t are an u32_t[4] effectively! */
|
||||
#define inet6_addr_to_ip6addr_p(target_ip6addr_p, source_in6addr) ((target_ip6addr_p) = (ip6_addr_t*)(source_in6addr))
|
||||
|
||||
/* directly map this to the lwip internal functions */
|
||||
#define inet6_aton(cp, addr) ip6addr_aton(cp, (ip6_addr_t*)addr)
|
||||
#define inet6_ntoa(addr) ip6addr_ntoa((ip6_addr_t*)&(addr))
|
||||
#define inet6_ntoa_r(addr, buf, buflen) ip6addr_ntoa_r((ip6_addr_t*)&(addr), buf, buflen)
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* LWIP_IPV6 */
|
||||
|
||||
#endif /* __LWIP_INET6_H__ */
|
||||
|
225
src/include/ipv6/lwip/ip6.h
Normal file
225
src/include/ipv6/lwip/ip6.h
Normal file
@ -0,0 +1,225 @@
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* IPv6 layer.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2010 Inico Technologies Ltd.
|
||||
* 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.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Ivan Delamer <delamer@inicotech.com>
|
||||
*
|
||||
*
|
||||
* Please coordinate changes and requests with Ivan Delamer
|
||||
* <delamer@inicotech.com>
|
||||
*/
|
||||
#ifndef __LWIP_IP6_H__
|
||||
#define __LWIP_IP6_H__
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#if LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */
|
||||
|
||||
#include "lwip/ip.h"
|
||||
#include "lwip/ip6_addr.h"
|
||||
#include "lwip/def.h"
|
||||
#include "lwip/pbuf.h"
|
||||
#include "lwip/netif.h"
|
||||
|
||||
#include "lwip/err.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define IP6_HLEN 40
|
||||
|
||||
#define IP6_NEXTH_HOPBYHOP 0
|
||||
#define IP6_NEXTH_TCP 6
|
||||
#define IP6_NEXTH_UDP 17
|
||||
#define IP6_NEXTH_ENCAPS 41
|
||||
#define IP6_NEXTH_ROUTING 43
|
||||
#define IP6_NEXTH_FRAGMENT 44
|
||||
#define IP6_NEXTH_ICMP6 58
|
||||
#define IP6_NEXTH_NONE 59
|
||||
#define IP6_NEXTH_DESTOPTS 60
|
||||
#define IP6_NEXTH_UDPLITE 136
|
||||
|
||||
|
||||
/* This is passed as the destination address to ip6_output_if (not
|
||||
to ip6_output), meaning that an IP header already is constructed
|
||||
in the pbuf. This is used when TCP retransmits. */
|
||||
#ifdef IP6_HDRINCL
|
||||
#undef IP6_HDRINCL
|
||||
#endif /* IP6_HDRINCL */
|
||||
#define IP6_HDRINCL NULL
|
||||
|
||||
|
||||
/* The IPv6 header. */
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/bpstruct.h"
|
||||
#endif
|
||||
PACK_STRUCT_BEGIN
|
||||
struct ip6_hdr {
|
||||
/* version / traffic class / flow label */
|
||||
PACK_STRUCT_FIELD(u32_t _v_tc_fl);
|
||||
/* payload length */
|
||||
PACK_STRUCT_FIELD(u16_t _plen);
|
||||
/* next header */
|
||||
PACK_STRUCT_FIELD(u8_t _nexth);
|
||||
/* hop limit */
|
||||
PACK_STRUCT_FIELD(u8_t _hoplim);
|
||||
/* source and destination IP addresses */
|
||||
PACK_STRUCT_FIELD(ip6_addr_p_t src);
|
||||
PACK_STRUCT_FIELD(ip6_addr_p_t dest);
|
||||
} PACK_STRUCT_STRUCT;
|
||||
PACK_STRUCT_END
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/epstruct.h"
|
||||
#endif
|
||||
|
||||
/* Hop-by-hop router alert option. */
|
||||
#define IP6_HBH_HLEN 8
|
||||
#define IP6_PAD1_OPTION 0
|
||||
#define IP6_PADN_ALERT_OPTION 1
|
||||
#define IP6_ROUTER_ALERT_OPTION 5
|
||||
#define IP6_ROUTER_ALERT_VALUE_MLD 0
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/bpstruct.h"
|
||||
#endif
|
||||
PACK_STRUCT_BEGIN
|
||||
struct ip6_hbh_hdr {
|
||||
/* next header */
|
||||
PACK_STRUCT_FIELD(u8_t _nexth);
|
||||
/* header length */
|
||||
PACK_STRUCT_FIELD(u8_t _hlen);
|
||||
/* router alert option type */
|
||||
PACK_STRUCT_FIELD(u8_t _ra_opt_type);
|
||||
/* router alert option data len */
|
||||
PACK_STRUCT_FIELD(u8_t _ra_opt_dlen);
|
||||
/* router alert option data */
|
||||
PACK_STRUCT_FIELD(u16_t _ra_opt_data);
|
||||
/* PadN option type */
|
||||
PACK_STRUCT_FIELD(u8_t _padn_opt_type);
|
||||
/* PadN option data len */
|
||||
PACK_STRUCT_FIELD(u8_t _padn_opt_dlen);
|
||||
} PACK_STRUCT_STRUCT;
|
||||
PACK_STRUCT_END
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/epstruct.h"
|
||||
#endif
|
||||
|
||||
/* Fragment header. */
|
||||
#define IP6_FRAG_HLEN 8
|
||||
#define IP6_FRAG_OFFSET_MASK 0xfff8
|
||||
#define IP6_FRAG_MORE_FLAG 0x0001
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/bpstruct.h"
|
||||
#endif
|
||||
PACK_STRUCT_BEGIN
|
||||
struct ip6_frag_hdr {
|
||||
/* next header */
|
||||
PACK_STRUCT_FIELD(u8_t _nexth);
|
||||
/* reserved */
|
||||
PACK_STRUCT_FIELD(u8_t reserved);
|
||||
/* fragment offset */
|
||||
PACK_STRUCT_FIELD(u16_t _fragment_offset);
|
||||
/* fragmented packet identification */
|
||||
PACK_STRUCT_FIELD(u32_t _identification);
|
||||
} PACK_STRUCT_STRUCT;
|
||||
PACK_STRUCT_END
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/epstruct.h"
|
||||
#endif
|
||||
|
||||
#define IP6H_V(hdr) ((ntohl((hdr)->_v_tc_fl) >> 28) & 0x0f)
|
||||
#define IP6H_TC(hdr) ((ntohl((hdr)->_v_tc_fl) >> 20) & 0xff)
|
||||
#define IP6H_FL(hdr) (ntohl((hdr)->_v_tc_fl) & 0x000fffff)
|
||||
#define IP6H_PLEN(hdr) (ntohs((hdr)->_plen))
|
||||
#define IP6H_NEXTH(hdr) ((hdr)->_nexth)
|
||||
#define IP6H_NEXTH_P(hdr) ((u8_t *)(hdr) + 6)
|
||||
#define IP6H_HOPLIM(hdr) ((hdr)->_hoplim)
|
||||
|
||||
#define IP6H_VTCFL_SET(hdr, v, tc, fl) (hdr)->_v_tc_fl = (htonl(((v) << 28) | ((tc) << 20) | (fl)))
|
||||
#define IP6H_PLEN_SET(hdr, plen) (hdr)->_plen = htons(plen)
|
||||
#define IP6H_NEXTH_SET(hdr, nexth) (hdr)->_nexth = (nexth)
|
||||
#define IP6H_HOPLIM_SET(hdr, hl) (hdr)->_hoplim = (u8_t)(hl)
|
||||
|
||||
|
||||
|
||||
/** Header of the input IPv6 packet currently being processed. */
|
||||
extern const struct ip6_hdr *current_ip6_header;
|
||||
/** Total header length of current_ip6_header (i.e. after this, the UDP/TCP header starts) */
|
||||
extern u16_t current_ip6_header_tot_len;
|
||||
/** Source IPv6 address of current_header */
|
||||
extern ip6_addr_t current_ip6hdr_src;
|
||||
/** Destination IPv6 address of current_header */
|
||||
extern ip6_addr_t current_ip6hdr_dest;
|
||||
|
||||
#define ip6_init() /* TODO should we init current addresses and header pointer? */
|
||||
struct netif *ip6_route(struct ip6_addr *src, struct ip6_addr *dest);
|
||||
ip6_addr_t *ip6_select_source_address(struct netif *netif, ip6_addr_t * dest);
|
||||
err_t ip6_input(struct pbuf *p, struct netif *inp);
|
||||
err_t ip6_output(struct pbuf *p, struct ip6_addr *src, struct ip6_addr *dest,
|
||||
u8_t hl, u8_t tc, u8_t nexth);
|
||||
err_t ip6_output_if(struct pbuf *p, struct ip6_addr *src, struct ip6_addr *dest,
|
||||
u8_t hl, u8_t tc, u8_t nexth, struct netif *netif);
|
||||
#if LWIP_NETIF_HWADDRHINT
|
||||
err_t ip6_output_hinted(struct pbuf *p, ip6_addr_t *src, ip6_addr_t *dest,
|
||||
u8_t hl, u8_t tc, u8_t nexth, u8_t *addr_hint);
|
||||
#endif /* LWIP_NETIF_HWADDRHINT */
|
||||
#if LWIP_IPV6_MLD
|
||||
err_t ip6_options_add_hbh_ra(struct pbuf * p, u8_t nexth, u8_t value);
|
||||
#endif /* LWIP_IPV6_MLD */
|
||||
|
||||
|
||||
/** Get the IPv6 header of the current packet.
|
||||
* This function must only be called from a receive callback (udp_recv,
|
||||
* raw_recv, tcp_accept). It will return NULL otherwise. */
|
||||
#define ip6_current_header() (current_ip6_header)
|
||||
/** Total header length of current_ip6_header (i.e. after this, the UDP/TCP header starts) */
|
||||
#define ip6_current_header_tot_len() (current_ip6_header_tot_len)
|
||||
/** Source IPv6 address of current_header */
|
||||
#define ip6_current_src_addr() (¤t_ip6hdr_src)
|
||||
/** Destination IPv6 address of current_header */
|
||||
#define ip6_current_dest_addr() (¤t_ip6hdr_dest)
|
||||
|
||||
#if IP6_DEBUG
|
||||
void ip6_debug_print(struct pbuf *p);
|
||||
#else
|
||||
#define ip6_debug_print(p)
|
||||
#endif /* IP6_DEBUG */
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* LWIP_IPV6 */
|
||||
|
||||
#endif /* __LWIP_IP6_H__ */
|
282
src/include/ipv6/lwip/ip6_addr.h
Normal file
282
src/include/ipv6/lwip/ip6_addr.h
Normal file
@ -0,0 +1,282 @@
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* IPv6 addresses.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2010 Inico Technologies Ltd.
|
||||
* 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.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Ivan Delamer <delamer@inicotech.com>
|
||||
*
|
||||
* Structs and macros for handling IPv6 addresses.
|
||||
*
|
||||
* Please coordinate changes and requests with Ivan Delamer
|
||||
* <delamer@inicotech.com>
|
||||
*/
|
||||
#ifndef __LWIP_IP6_ADDR_H__
|
||||
#define __LWIP_IP6_ADDR_H__
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#if LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/* This is the aligned version of ip6_addr_t,
|
||||
used as local variable, on the stack, etc. */
|
||||
struct ip6_addr {
|
||||
u32_t addr[4];
|
||||
};
|
||||
|
||||
/* This is the packed version of ip6_addr_t,
|
||||
used in network headers that are itself packed */
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/bpstruct.h"
|
||||
#endif
|
||||
PACK_STRUCT_BEGIN
|
||||
struct ip6_addr_packed {
|
||||
PACK_STRUCT_FIELD(u32_t addr[4]);
|
||||
} PACK_STRUCT_STRUCT;
|
||||
PACK_STRUCT_END
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/epstruct.h"
|
||||
#endif
|
||||
|
||||
/** ip6_addr_t uses a struct for convenience only, so that the same defines can
|
||||
* operate both on ip6_addr_t as well as on ip6_addr_p_t. */
|
||||
typedef struct ip6_addr ip6_addr_t;
|
||||
typedef struct ip6_addr_packed ip6_addr_p_t;
|
||||
|
||||
|
||||
/** IP6_ADDR_ANY can be used as a fixed IPv6 address
|
||||
* for the wildcard
|
||||
*/
|
||||
extern const ip6_addr_t ip6_addr_any;
|
||||
#define IP6_ADDR_ANY ((ip6_addr_t *)&ip6_addr_any)
|
||||
|
||||
|
||||
|
||||
|
||||
#if BYTE_ORDER == BIG_ENDIAN
|
||||
/** Set an IPv6 partial address given by byte-parts. */
|
||||
#define IP6_ADDR(ip6addr, index, a,b,c,d) \
|
||||
(ip6addr)->addr[index] = ((u32_t)((a) & 0xff) << 24) | \
|
||||
((u32_t)((b) & 0xff) << 16) | \
|
||||
((u32_t)((c) & 0xff) << 8) | \
|
||||
(u32_t)((d) & 0xff)
|
||||
#else
|
||||
/** Set an IPv6 partial address given by byte-parts.
|
||||
Little-endian version, stored in network order (no htonl). */
|
||||
#define IP6_ADDR(ip6addr, index, a,b,c,d) \
|
||||
(ip6addr)->addr[index] = ((u32_t)((d) & 0xff) << 24) | \
|
||||
((u32_t)((c) & 0xff) << 16) | \
|
||||
((u32_t)((b) & 0xff) << 8) | \
|
||||
(u32_t)((a) & 0xff)
|
||||
#endif
|
||||
|
||||
/** Access address in 16-bit block */
|
||||
#define IP6_ADDR_BLOCK1(ip6addr) ((htonl((ip6addr)->addr[0]) >> 16) & 0xffff)
|
||||
#define IP6_ADDR_BLOCK2(ip6addr) ((htonl((ip6addr)->addr[0])) & 0xffff)
|
||||
#define IP6_ADDR_BLOCK3(ip6addr) ((htonl((ip6addr)->addr[1]) >> 16) & 0xffff)
|
||||
#define IP6_ADDR_BLOCK4(ip6addr) ((htonl((ip6addr)->addr[1])) & 0xffff)
|
||||
#define IP6_ADDR_BLOCK5(ip6addr) ((htonl((ip6addr)->addr[2]) >> 16) & 0xffff)
|
||||
#define IP6_ADDR_BLOCK6(ip6addr) ((htonl((ip6addr)->addr[2])) & 0xffff)
|
||||
#define IP6_ADDR_BLOCK7(ip6addr) ((htonl((ip6addr)->addr[3]) >> 16) & 0xffff)
|
||||
#define IP6_ADDR_BLOCK8(ip6addr) ((htonl((ip6addr)->addr[3])) & 0xffff)
|
||||
|
||||
/** Copy IPv6 address - faster than ip6_addr_set: no NULL check */
|
||||
#define ip6_addr_copy(dest, src) {(dest).addr[0] = (src).addr[0]; \
|
||||
(dest).addr[1] = (src).addr[1]; \
|
||||
(dest).addr[2] = (src).addr[2]; \
|
||||
(dest).addr[3] = (src).addr[3];}
|
||||
/** Safely copy one IPv6 address to another (src may be NULL) */
|
||||
#define ip6_addr_set(dest, src) {(dest)->addr[0] = (src) == NULL ? 0 : (src)->addr[0]; \
|
||||
(dest)->addr[1] = (src) == NULL ? 0 : (src)->addr[1]; \
|
||||
(dest)->addr[2] = (src) == NULL ? 0 : (src)->addr[2]; \
|
||||
(dest)->addr[3] = (src) == NULL ? 0 : (src)->addr[3];}
|
||||
|
||||
/** Set complete address to zero */
|
||||
#define ip6_addr_set_zero(ip6addr) {(ip6addr)->addr[0] = 0; \
|
||||
(ip6addr)->addr[1] = 0; \
|
||||
(ip6addr)->addr[2] = 0; \
|
||||
(ip6addr)->addr[3] = 0;}
|
||||
|
||||
/** Set address to ipv6 'any' (no need for htonl()) */
|
||||
#define ip6_addr_set_any(ip6addr) ip6_addr_set_zero(ip6addr)
|
||||
/** Set address to ipv6 loopback address */
|
||||
#define ip6_addr_set_loopback(ip6addr) {(ip6addr)->addr[0] = 0; \
|
||||
(ip6addr)->addr[1] = 0; \
|
||||
(ip6addr)->addr[2] = 0; \
|
||||
(ip6addr)->addr[3] = PP_HTONL(0x00000001UL);}
|
||||
/** Safely copy one IPv6 address to another and change byte order
|
||||
* from host- to network-order. */
|
||||
#define ip6_addr_set_hton(dest, src) {(dest)->addr[0] = (src) == NULL ? 0 : htonl((src)->addr[0]); \
|
||||
(dest)->addr[1] = (src) == NULL ? 0 : htonl((src)->addr[1]); \
|
||||
(dest)->addr[2] = (src) == NULL ? 0 : htonl((src)->addr[2]); \
|
||||
(dest)->addr[3] = (src) == NULL ? 0 : htonl((src)->addr[3]);}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Determine if two IPv6 address are on the same network.
|
||||
*
|
||||
* @arg addr1 IPv6 address 1
|
||||
* @arg addr2 IPv6 address 2
|
||||
* @return !0 if the network identifiers of both address match
|
||||
*/
|
||||
#define ip6_addr_netcmp(addr1, addr2) (((addr1)->addr[0] == (addr2)->addr[0]) && \
|
||||
((addr1)->addr[1] == (addr2)->addr[1]))
|
||||
|
||||
#define ip6_addr_cmp(addr1, addr2) (((addr1)->addr[0] == (addr2)->addr[0]) && \
|
||||
((addr1)->addr[1] == (addr2)->addr[1]) && \
|
||||
((addr1)->addr[2] == (addr2)->addr[2]) && \
|
||||
((addr1)->addr[3] == (addr2)->addr[3]))
|
||||
|
||||
#define ip6_get_subnet_id(ip6addr) (htonl((ip6addr)->addr[2]) & 0x0000ffffUL)
|
||||
|
||||
#define ip6_addr_isany(ip6addr) (((ip6addr) == NULL) || \
|
||||
(((ip6addr)->addr[0] == 0) && \
|
||||
((ip6addr)->addr[1] == 0) && \
|
||||
((ip6addr)->addr[2] == 0) && \
|
||||
((ip6addr)->addr[3] == 0)))
|
||||
|
||||
|
||||
#define ip6_addr_isglobal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xe0000000UL)) == PP_HTONL(0x20000000UL))
|
||||
|
||||
#define ip6_addr_islinklocal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xffc00000UL)) == PP_HTONL(0xfe800000UL))
|
||||
|
||||
#define ip6_addr_issitelocal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xffc00000UL)) == PP_HTONL(0xfec00000UL))
|
||||
|
||||
#define ip6_addr_isuniquelocal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xfe000000UL)) == PP_HTONL(0xfc000000UL))
|
||||
|
||||
#define ip6_addr_ismulticast(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xff000000UL)) == PP_HTONL(0xff000000UL))
|
||||
#define ip6_addr_multicast_transient_flag(ip6addr) ((ip6addr)->addr[0] & PP_HTONL(0x00100000UL))
|
||||
#define ip6_addr_multicast_prefix_flag(ip6addr) ((ip6addr)->addr[0] & PP_HTONL(0x00200000UL))
|
||||
#define ip6_addr_multicast_rendezvous_flag(ip6addr) ((ip6addr)->addr[0] & PP_HTONL(0x00400000UL))
|
||||
#define ip6_addr_multicast_scope(ip6addr) ((htonl((ip6addr)->addr[0]) >> 16) & 0xf)
|
||||
#define IP6_MULTICAST_SCOPE_RESERVED 0x0
|
||||
#define IP6_MULTICAST_SCOPE_RESERVED0 0x0
|
||||
#define IP6_MULTICAST_SCOPE_INTERFACE_LOCAL 0x1
|
||||
#define IP6_MULTICAST_SCOPE_LINK_LOCAL 0x2
|
||||
#define IP6_MULTICAST_SCOPE_RESERVED3 0x3
|
||||
#define IP6_MULTICAST_SCOPE_ADMIN_LOCAL 0x4
|
||||
#define IP6_MULTICAST_SCOPE_SITE_LOCAL 0x5
|
||||
#define IP6_MULTICAST_SCOPE_ORGANIZATION_LOCAL 0x8
|
||||
#define IP6_MULTICAST_SCOPE_GLOBAL 0xe
|
||||
#define IP6_MULTICAST_SCOPE_RESERVEDF 0xf
|
||||
#define ip6_addr_ismulticast_iflocal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xffff0000UL)) == PP_HTONL(0xff010000UL))
|
||||
#define ip6_addr_ismulticast_linklocal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xffff0000UL)) == PP_HTONL(0xff020000UL))
|
||||
#define ip6_addr_ismulticast_adminlocal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xffff0000UL)) == PP_HTONL(0xff040000UL))
|
||||
#define ip6_addr_ismulticast_sitelocal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xffff0000UL)) == PP_HTONL(0xff050000UL))
|
||||
#define ip6_addr_ismulticast_orglocal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xffff0000UL)) == PP_HTONL(0xff080000UL))
|
||||
#define ip6_addr_ismulticast_global(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xffff0000UL)) == PP_HTONL(0xff0e0000UL))
|
||||
|
||||
/* TODO define get/set for well-know multicast addresses, e.g. ff02::1 */
|
||||
#define ip6_addr_isallnodes_iflocal(ip6addr) (((ip6addr)->addr[0] == PP_HTONL(0xff010000UL)) && \
|
||||
((ip6addr)->addr[1] == 0UL) && \
|
||||
((ip6addr)->addr[2] == 0UL) && \
|
||||
((ip6addr)->addr[3] == PP_HTONL(0x00000001UL)))
|
||||
|
||||
#define ip6_addr_isallnodes_linklocal(ip6addr) (((ip6addr)->addr[0] == PP_HTONL(0xff020000UL)) && \
|
||||
((ip6addr)->addr[1] == 0UL) && \
|
||||
((ip6addr)->addr[2] == 0UL) && \
|
||||
((ip6addr)->addr[3] == PP_HTONL(0x00000001UL)))
|
||||
#define ip6_addr_set_allnodes_linklocal(ip6addr) {(ip6addr)->addr[0] = PP_HTONL(0xff020000UL); \
|
||||
(ip6addr)->addr[1] = 0; \
|
||||
(ip6addr)->addr[2] = 0; \
|
||||
(ip6addr)->addr[3] = PP_HTONL(0x00000001UL);}
|
||||
|
||||
#define ip6_addr_isallrouters_linklocal(ip6addr) (((ip6addr)->addr[0] == PP_HTONL(0xff020000UL)) && \
|
||||
((ip6addr)->addr[1] == 0UL) && \
|
||||
((ip6addr)->addr[2] == 0UL) && \
|
||||
((ip6addr)->addr[3] == PP_HTONL(0x00000002UL)))
|
||||
#define ip6_addr_set_allrouters_linklocal(ip6addr) {(ip6addr)->addr[0] = PP_HTONL(0xff020000UL); \
|
||||
(ip6addr)->addr[1] = 0; \
|
||||
(ip6addr)->addr[2] = 0; \
|
||||
(ip6addr)->addr[3] = PP_HTONL(0x00000002UL);}
|
||||
|
||||
#define ip6_addr_issolicitednode(ip6addr) ( ((ip6addr)->addr[0] == PP_HTONL(0xff020000UL)) && \
|
||||
((ip6addr)->addr[2] == PP_HTONL(0x00000001UL)) && \
|
||||
(((ip6addr)->addr[3] & PP_HTONL(0xff000000UL)) == PP_HTONL(0xff000000UL)) )
|
||||
|
||||
#define ip6_addr_set_solicitednode(ip6addr, if_id) {(ip6addr)->addr[0] = PP_HTONL(0xff020000UL); \
|
||||
(ip6addr)->addr[1] = 0; \
|
||||
(ip6addr)->addr[2] = PP_HTONL(0x00000001UL); \
|
||||
(ip6addr)->addr[3] = htonl(0xff000000UL | (htonl(if_id) & 0x00ffffffUL));}
|
||||
|
||||
|
||||
/* IPv6 address states. */
|
||||
#define IP6_ADDR_INVALID 0x00
|
||||
#define IP6_ADDR_TENTATIVE 0x08
|
||||
#define IP6_ADDR_TENTATIVE_1 0x09 /* 1 probe sent */
|
||||
#define IP6_ADDR_TENTATIVE_2 0x0a /* 2 probes sent */
|
||||
#define IP6_ADDR_TENTATIVE_3 0x0b /* 3 probes sent */
|
||||
#define IP6_ADDR_TENTATIVE_4 0x0c /* 4 probes sent */
|
||||
#define IP6_ADDR_TENTATIVE_5 0x0d /* 5 probes sent */
|
||||
#define IP6_ADDR_TENTATIVE_6 0x0e /* 6 probes sent */
|
||||
#define IP6_ADDR_TENTATIVE_7 0x0f /* 7 probes sent */
|
||||
#define IP6_ADDR_VALID 0x10
|
||||
#define IP6_ADDR_PREFERRED 0x30
|
||||
#define IP6_ADDR_DEPRECATED 0x50
|
||||
|
||||
#define ip6_addr_isinvalid(addr_state) (addr_state == IP6_ADDR_INVALID)
|
||||
#define ip6_addr_istentative(addr_state) (addr_state & IP6_ADDR_TENTATIVE)
|
||||
#define ip6_addr_isvalid(addr_state) (addr_state & IP6_ADDR_VALID) /* Include valid, preferred, and deprecated. */
|
||||
#define ip6_addr_ispreferred(addr_state) (addr_state == IP6_ADDR_PREFERRED)
|
||||
#define ip6_addr_isdeprecated(addr_state) (addr_state == IP6_ADDR_DEPRECATED)
|
||||
|
||||
#define ip6_addr_debug_print(debug, ipaddr) \
|
||||
LWIP_DEBUGF(debug, ("%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F, \
|
||||
ipaddr != NULL ? IP6_ADDR_BLOCK1(ipaddr) : 0, \
|
||||
ipaddr != NULL ? IP6_ADDR_BLOCK2(ipaddr) : 0, \
|
||||
ipaddr != NULL ? IP6_ADDR_BLOCK3(ipaddr) : 0, \
|
||||
ipaddr != NULL ? IP6_ADDR_BLOCK4(ipaddr) : 0, \
|
||||
ipaddr != NULL ? IP6_ADDR_BLOCK5(ipaddr) : 0, \
|
||||
ipaddr != NULL ? IP6_ADDR_BLOCK6(ipaddr) : 0, \
|
||||
ipaddr != NULL ? IP6_ADDR_BLOCK7(ipaddr) : 0, \
|
||||
ipaddr != NULL ? IP6_ADDR_BLOCK8(ipaddr) : 0))
|
||||
|
||||
int ip6addr_aton(const char *cp, ip6_addr_t *addr);
|
||||
/** returns ptr to static buffer; not reentrant! */
|
||||
char *ip6addr_ntoa(const ip6_addr_t *addr);
|
||||
char *ip6addr_ntoa_r(const ip6_addr_t *addr, char *buf, int buflen);
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* LWIP_IPV6 */
|
||||
|
||||
#endif /* __LWIP_IP6_ADDR_H__ */
|
70
src/include/ipv6/lwip/ip6_chksum.h
Normal file
70
src/include/ipv6/lwip/ip6_chksum.h
Normal file
@ -0,0 +1,70 @@
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* IPv6 Checksum helper functions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2010 Inico Technologies Ltd.
|
||||
* 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.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Ivan Delamer <delamer@inicotech.com>
|
||||
*
|
||||
*
|
||||
* Please coordinate changes and requests with Ivan Delamer
|
||||
* <delamer@inicotech.com>
|
||||
*/
|
||||
#ifndef __LWIP_IP6_CHKSUM_H__
|
||||
#define __LWIP_IP6_CHKSUM_H__
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#if LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */
|
||||
|
||||
#include "lwip/ip6_addr.h"
|
||||
#include "lwip/inet_chksum.h"
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
u16_t ip6_chksum_pseudo(struct pbuf *p,
|
||||
ip6_addr_t *src, ip6_addr_t *dest,
|
||||
u8_t proto, u16_t proto_len);
|
||||
u16_t ip6_chksum_pseudo_partial(struct pbuf *p,
|
||||
ip6_addr_t *src, ip6_addr_t *dest,
|
||||
u8_t proto, u16_t proto_len, u16_t chksum_len);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* LWIP_IPV6 */
|
||||
|
||||
#endif /* __LWIP_IP6_CHKSUM_H__ */
|
102
src/include/ipv6/lwip/ip6_frag.h
Normal file
102
src/include/ipv6/lwip/ip6_frag.h
Normal file
@ -0,0 +1,102 @@
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* IPv6 fragmentation and reassembly.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2010 Inico Technologies Ltd.
|
||||
* 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.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Ivan Delamer <delamer@inicotech.com>
|
||||
*
|
||||
*
|
||||
* Please coordinate changes and requests with Ivan Delamer
|
||||
* <delamer@inicotech.com>
|
||||
*/
|
||||
#ifndef __LWIP_IP6_FRAG_H__
|
||||
#define __LWIP_IP6_FRAG_H__
|
||||
|
||||
#include "lwip/opt.h"
|
||||
#include "lwip/pbuf.h"
|
||||
#include "lwip/ip6_addr.h"
|
||||
#include "lwip/netif.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#if LWIP_IPV6_REASS /* don't build if not configured for use in lwipopts.h */
|
||||
|
||||
/* The IPv6 reassembly timer interval in milliseconds. */
|
||||
#define IP6_REASS_TMR_INTERVAL 1000
|
||||
|
||||
/* IPv6 reassembly helper struct.
|
||||
* This is exported because memp needs to know the size.
|
||||
*/
|
||||
struct ip6_reassdata {
|
||||
struct ip6_reassdata *next;
|
||||
struct pbuf *p;
|
||||
struct ip6_hdr * iphdr;
|
||||
u32_t identification;
|
||||
u16_t datagram_len;
|
||||
u8_t nexth;
|
||||
u8_t timer;
|
||||
};
|
||||
|
||||
#define ip6_reass_init() /* Compatibility define */
|
||||
void ip6_reass_tmr(void);
|
||||
struct pbuf * ip6_reass(struct pbuf *p);
|
||||
|
||||
#endif /* LWIP_IPV6_REASS */
|
||||
|
||||
#if LWIP_IPV6_FRAG /* don't build if not configured for use in lwipopts.h */
|
||||
|
||||
/** A custom pbuf that holds a reference to another pbuf, which is freed
|
||||
* when this custom pbuf is freed. This is used to create a custom PBUF_REF
|
||||
* that points into the original pbuf. */
|
||||
#ifndef __LWIP_PBUF_CUSTOM_REF__
|
||||
#define __LWIP_PBUF_CUSTOM_REF__
|
||||
struct pbuf_custom_ref {
|
||||
/** 'base class' */
|
||||
struct pbuf_custom pc;
|
||||
/** pointer to the original pbuf that is referenced */
|
||||
struct pbuf *original;
|
||||
};
|
||||
#endif /* __LWIP_PBUF_CUSTOM_REF__ */
|
||||
|
||||
err_t ip6_frag(struct pbuf *p, struct netif *netif, ip6_addr_t *dest);
|
||||
|
||||
#endif /* LWIP_IPV6_FRAG */
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __LWIP_IP6_FRAG_H__ */
|
118
src/include/ipv6/lwip/mld6.h
Normal file
118
src/include/ipv6/lwip/mld6.h
Normal file
@ -0,0 +1,118 @@
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* Multicast listener discovery for IPv6. Aims to be compliant with RFC 2710.
|
||||
* No support for MLDv2.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2010 Inico Technologies Ltd.
|
||||
* 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.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Ivan Delamer <delamer@inicotech.com>
|
||||
*
|
||||
*
|
||||
* Please coordinate changes and requests with Ivan Delamer
|
||||
* <delamer@inicotech.com>
|
||||
*/
|
||||
|
||||
#ifndef __LWIP_MLD6_H__
|
||||
#define __LWIP_MLD6_H__
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#if LWIP_IPV6_MLD && LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */
|
||||
|
||||
#include "lwip/pbuf.h"
|
||||
#include "lwip/netif.h"
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct mld_group {
|
||||
/** next link */
|
||||
struct mld_group *next;
|
||||
/** interface on which the group is active */
|
||||
struct netif *netif;
|
||||
/** multicast address */
|
||||
ip6_addr_t group_address;
|
||||
/** signifies we were the last person to report */
|
||||
u8_t last_reporter_flag;
|
||||
/** current state of the group */
|
||||
u8_t group_state;
|
||||
/** timer for reporting */
|
||||
u16_t timer;
|
||||
/** counter of simultaneous uses */
|
||||
u8_t use;
|
||||
};
|
||||
|
||||
/** Multicast listener report/query/done message header. */
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/bpstruct.h"
|
||||
#endif
|
||||
PACK_STRUCT_BEGIN
|
||||
struct mld_header {
|
||||
PACK_STRUCT_FIELD(u8_t type);
|
||||
PACK_STRUCT_FIELD(u8_t code);
|
||||
PACK_STRUCT_FIELD(u16_t chksum);
|
||||
PACK_STRUCT_FIELD(u16_t max_resp_delay);
|
||||
PACK_STRUCT_FIELD(u16_t reserved);
|
||||
PACK_STRUCT_FIELD(ip6_addr_p_t multicast_address);
|
||||
/* Options follow. */
|
||||
} PACK_STRUCT_STRUCT;
|
||||
PACK_STRUCT_END
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/epstruct.h"
|
||||
#endif
|
||||
|
||||
#define MLD6_TMR_INTERVAL 100 /* Milliseconds */
|
||||
|
||||
/* MAC Filter Actions, these are passed to a netif's
|
||||
* mld_mac_filter callback function. */
|
||||
#define MLD6_DEL_MAC_FILTER 0
|
||||
#define MLD6_ADD_MAC_FILTER 1
|
||||
|
||||
|
||||
#define mld6_init() /* TODO should we init tables? */
|
||||
err_t mld6_stop(struct netif *netif);
|
||||
void mld6_report_groups(struct netif *netif);
|
||||
void mld6_tmr(void);
|
||||
struct mld_group *mld6_lookfor_group(struct netif *ifp, ip6_addr_t *addr);
|
||||
void mld6_input(struct pbuf *p, struct netif *inp);
|
||||
err_t mld6_joingroup(ip6_addr_t *srcaddr, ip6_addr_t *groupaddr);
|
||||
err_t mld6_leavegroup(ip6_addr_t *srcaddr, ip6_addr_t *groupaddr);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* LWIP_IPV6_MLD && LWIP_IPV6 */
|
||||
|
||||
#endif /* __LWIP_MLD6_H__ */
|
368
src/include/ipv6/lwip/nd6.h
Normal file
368
src/include/ipv6/lwip/nd6.h
Normal file
@ -0,0 +1,368 @@
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* Neighbor discovery and stateless address autoconfiguration for IPv6.
|
||||
* Aims to be compliant with RFC 4861 (Neighbor discovery) and RFC 4862
|
||||
* (Address autoconfiguration).
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2010 Inico Technologies Ltd.
|
||||
* 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.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Ivan Delamer <delamer@inicotech.com>
|
||||
*
|
||||
*
|
||||
* Please coordinate changes and requests with Ivan Delamer
|
||||
* <delamer@inicotech.com>
|
||||
*/
|
||||
|
||||
#ifndef __LWIP_ND6_H__
|
||||
#define __LWIP_ND6_H__
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#if LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */
|
||||
|
||||
#include "lwip/pbuf.h"
|
||||
#include "lwip/ip6.h"
|
||||
#include "lwip/ip6_addr.h"
|
||||
#include "lwip/netif.h"
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Struct for tables. */
|
||||
struct nd6_neighbor_cache_entry {
|
||||
ip6_addr_t next_hop_address;
|
||||
struct netif * netif;
|
||||
u8_t lladdr[NETIF_MAX_HWADDR_LEN];
|
||||
/*u32_t pmtu;*/
|
||||
#if LWIP_ND6_QUEUEING
|
||||
/** Pointer to queue of pending outgoing packets on this entry. */
|
||||
struct nd6_q_entry *q;
|
||||
#endif /* LWIP_ND6_QUEUEING */
|
||||
u8_t state;
|
||||
u8_t isrouter;
|
||||
union {
|
||||
u32_t reachable_time;
|
||||
u32_t delay_time;
|
||||
u32_t probes_sent;
|
||||
u32_t stale_time;
|
||||
} counter;
|
||||
};
|
||||
|
||||
struct nd6_destination_cache_entry {
|
||||
ip6_addr_t destination_addr;
|
||||
ip6_addr_t next_hop_addr;
|
||||
u32_t pmtu;
|
||||
u32_t age;
|
||||
};
|
||||
|
||||
struct nd6_prefix_list_entry {
|
||||
ip6_addr_t prefix;
|
||||
struct netif * netif;
|
||||
u32_t invalidation_timer;
|
||||
#if LWIP_IPV6_AUTOCONFIG
|
||||
u8_t flags;
|
||||
#define ND6_PREFIX_AUTOCONFIG_AUTONOMOUS 0x01
|
||||
#define ND6_PREFIX_AUTOCONFIG_ADDRESS_GENERATED 0x02
|
||||
#define ND6_PREFIX_AUTOCONFIG_ADDRESS_DUPLICATE 0x04
|
||||
#endif /* LWIP_IPV6_AUTOCONFIG */
|
||||
};
|
||||
|
||||
struct nd6_router_list_entry {
|
||||
struct nd6_neighbor_cache_entry * neighbor_entry;
|
||||
u32_t invalidation_timer;
|
||||
u8_t flags;
|
||||
};
|
||||
|
||||
|
||||
enum nd6_neighbor_cache_entry_state {
|
||||
ND6_NO_ENTRY = 0,
|
||||
ND6_INCOMPLETE,
|
||||
ND6_REACHABLE,
|
||||
ND6_STALE,
|
||||
ND6_DELAY,
|
||||
ND6_PROBE
|
||||
};
|
||||
|
||||
#if LWIP_ND6_QUEUEING
|
||||
/** struct for queueing outgoing packets for unknown address
|
||||
* defined here to be accessed by memp.h
|
||||
*/
|
||||
struct nd6_q_entry {
|
||||
struct nd6_q_entry *next;
|
||||
struct pbuf *p;
|
||||
};
|
||||
#endif /* LWIP_ND6_QUEUEING */
|
||||
|
||||
/** Neighbor solicitation message header. */
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/bpstruct.h"
|
||||
#endif
|
||||
PACK_STRUCT_BEGIN
|
||||
struct ns_header {
|
||||
PACK_STRUCT_FIELD(u8_t type);
|
||||
PACK_STRUCT_FIELD(u8_t code);
|
||||
PACK_STRUCT_FIELD(u16_t chksum);
|
||||
PACK_STRUCT_FIELD(u32_t reserved);
|
||||
PACK_STRUCT_FIELD(ip6_addr_p_t target_address);
|
||||
/* Options follow. */
|
||||
} PACK_STRUCT_STRUCT;
|
||||
PACK_STRUCT_END
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/epstruct.h"
|
||||
#endif
|
||||
|
||||
/** Neighbor advertisement message header. */
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/bpstruct.h"
|
||||
#endif
|
||||
PACK_STRUCT_BEGIN
|
||||
struct na_header {
|
||||
PACK_STRUCT_FIELD(u8_t type);
|
||||
PACK_STRUCT_FIELD(u8_t code);
|
||||
PACK_STRUCT_FIELD(u16_t chksum);
|
||||
PACK_STRUCT_FIELD(u8_t flags);
|
||||
PACK_STRUCT_FIELD(u8_t reserved[3]);
|
||||
PACK_STRUCT_FIELD(ip6_addr_p_t target_address);
|
||||
/* Options follow. */
|
||||
} PACK_STRUCT_STRUCT;
|
||||
PACK_STRUCT_END
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/epstruct.h"
|
||||
#endif
|
||||
#define ND6_FLAG_ROUTER (0x80)
|
||||
#define ND6_FLAG_SOLICITED (0x40)
|
||||
#define ND6_FLAG_OVERRIDE (0x20)
|
||||
|
||||
/** Router solicitation message header. */
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/bpstruct.h"
|
||||
#endif
|
||||
PACK_STRUCT_BEGIN
|
||||
struct rs_header {
|
||||
PACK_STRUCT_FIELD(u8_t type);
|
||||
PACK_STRUCT_FIELD(u8_t code);
|
||||
PACK_STRUCT_FIELD(u16_t chksum);
|
||||
PACK_STRUCT_FIELD(u32_t reserved);
|
||||
/* Options follow. */
|
||||
} PACK_STRUCT_STRUCT;
|
||||
PACK_STRUCT_END
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/epstruct.h"
|
||||
#endif
|
||||
|
||||
/** Router advertisement message header. */
|
||||
#define ND6_RA_FLAG_MANAGED_ADDR_CONFIG (0x80)
|
||||
#define ND6_RA_FLAG_OTHER_STATEFUL_CONFIG (0x40)
|
||||
#define ND6_RA_FLAG_HOME_AGENT (0x20)
|
||||
#define ND6_RA_PREFERENCE_MASK (0x18)
|
||||
#define ND6_RA_PREFERENCE_HIGH (0x08)
|
||||
#define ND6_RA_PREFERENCE_MEDIUM (0x00)
|
||||
#define ND6_RA_PREFERENCE_LOW (0x18)
|
||||
#define ND6_RA_PREFERENCE_DISABLED (0x10)
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/bpstruct.h"
|
||||
#endif
|
||||
PACK_STRUCT_BEGIN
|
||||
struct ra_header {
|
||||
PACK_STRUCT_FIELD(u8_t type);
|
||||
PACK_STRUCT_FIELD(u8_t code);
|
||||
PACK_STRUCT_FIELD(u16_t chksum);
|
||||
PACK_STRUCT_FIELD(u8_t current_hop_limit);
|
||||
PACK_STRUCT_FIELD(u8_t flags);
|
||||
PACK_STRUCT_FIELD(u16_t router_lifetime);
|
||||
PACK_STRUCT_FIELD(u32_t reachable_time);
|
||||
PACK_STRUCT_FIELD(u32_t retrans_timer);
|
||||
/* Options follow. */
|
||||
} PACK_STRUCT_STRUCT;
|
||||
PACK_STRUCT_END
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/epstruct.h"
|
||||
#endif
|
||||
|
||||
/** Redirect message header. */
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/bpstruct.h"
|
||||
#endif
|
||||
PACK_STRUCT_BEGIN
|
||||
struct redirect_header {
|
||||
PACK_STRUCT_FIELD(u8_t type);
|
||||
PACK_STRUCT_FIELD(u8_t code);
|
||||
PACK_STRUCT_FIELD(u16_t chksum);
|
||||
PACK_STRUCT_FIELD(u32_t reserved);
|
||||
PACK_STRUCT_FIELD(ip6_addr_p_t target_address);
|
||||
PACK_STRUCT_FIELD(ip6_addr_p_t destination_address);
|
||||
/* Options follow. */
|
||||
} PACK_STRUCT_STRUCT;
|
||||
PACK_STRUCT_END
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/epstruct.h"
|
||||
#endif
|
||||
|
||||
/** Link-layer address option. */
|
||||
#define ND6_OPTION_TYPE_SOURCE_LLADDR (0x01)
|
||||
#define ND6_OPTION_TYPE_TARGET_LLADDR (0x02)
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/bpstruct.h"
|
||||
#endif
|
||||
PACK_STRUCT_BEGIN
|
||||
struct lladdr_option {
|
||||
PACK_STRUCT_FIELD(u8_t type);
|
||||
PACK_STRUCT_FIELD(u8_t length);
|
||||
PACK_STRUCT_FIELD(u8_t addr[NETIF_MAX_HWADDR_LEN]);
|
||||
} PACK_STRUCT_STRUCT;
|
||||
PACK_STRUCT_END
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/epstruct.h"
|
||||
#endif
|
||||
|
||||
/** Prefix information option. */
|
||||
#define ND6_OPTION_TYPE_PREFIX_INFO (0x03)
|
||||
#define ND6_PREFIX_FLAG_ON_LINK (0x80)
|
||||
#define ND6_PREFIX_FLAG_AUTONOMOUS (0x40)
|
||||
#define ND6_PREFIX_FLAG_ROUTER_ADDRESS (0x20)
|
||||
#define ND6_PREFIX_FLAG_SITE_PREFIX (0x10)
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/bpstruct.h"
|
||||
#endif
|
||||
PACK_STRUCT_BEGIN
|
||||
struct prefix_option {
|
||||
PACK_STRUCT_FIELD(u8_t type);
|
||||
PACK_STRUCT_FIELD(u8_t length);
|
||||
PACK_STRUCT_FIELD(u8_t prefix_length);
|
||||
PACK_STRUCT_FIELD(u8_t flags);
|
||||
PACK_STRUCT_FIELD(u32_t valid_lifetime);
|
||||
PACK_STRUCT_FIELD(u32_t preferred_lifetime);
|
||||
PACK_STRUCT_FIELD(u8_t reserved2[3]);
|
||||
PACK_STRUCT_FIELD(u8_t site_prefix_length);
|
||||
PACK_STRUCT_FIELD(ip6_addr_p_t prefix);
|
||||
} PACK_STRUCT_STRUCT;
|
||||
PACK_STRUCT_END
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/epstruct.h"
|
||||
#endif
|
||||
|
||||
/** Redirected header option. */
|
||||
#define ND6_OPTION_TYPE_REDIR_HDR (0x04)
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/bpstruct.h"
|
||||
#endif
|
||||
PACK_STRUCT_BEGIN
|
||||
struct redirected_header_option {
|
||||
PACK_STRUCT_FIELD(u8_t type);
|
||||
PACK_STRUCT_FIELD(u8_t length);
|
||||
PACK_STRUCT_FIELD(u8_t reserved[6]);
|
||||
/* Portion of redirected packet follows. */
|
||||
/* PACK_STRUCT_FIELD(u8_t redirected[8]); */
|
||||
} PACK_STRUCT_STRUCT;
|
||||
PACK_STRUCT_END
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/epstruct.h"
|
||||
#endif
|
||||
|
||||
/** MTU option. */
|
||||
#define ND6_OPTION_TYPE_MTU (0x05)
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/bpstruct.h"
|
||||
#endif
|
||||
PACK_STRUCT_BEGIN
|
||||
struct mtu_option {
|
||||
PACK_STRUCT_FIELD(u8_t type);
|
||||
PACK_STRUCT_FIELD(u8_t length);
|
||||
PACK_STRUCT_FIELD(u16_t reserved);
|
||||
PACK_STRUCT_FIELD(u32_t mtu);
|
||||
} PACK_STRUCT_STRUCT;
|
||||
PACK_STRUCT_END
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/epstruct.h"
|
||||
#endif
|
||||
|
||||
/** Route information option. */
|
||||
#define ND6_OPTION_TYPE_ROUTE_INFO (24)
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/bpstruct.h"
|
||||
#endif
|
||||
PACK_STRUCT_BEGIN
|
||||
struct route_option {
|
||||
PACK_STRUCT_FIELD(u8_t type);
|
||||
PACK_STRUCT_FIELD(u8_t length);
|
||||
PACK_STRUCT_FIELD(u8_t prefix_length);
|
||||
PACK_STRUCT_FIELD(u8_t preference);
|
||||
PACK_STRUCT_FIELD(u32_t route_lifetime);
|
||||
PACK_STRUCT_FIELD(ip6_addr_p_t prefix);
|
||||
} PACK_STRUCT_STRUCT;
|
||||
PACK_STRUCT_END
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/epstruct.h"
|
||||
#endif
|
||||
|
||||
/* the possible states of an IP address */
|
||||
#define IP6_ADDRESS_STATE_INVALID (0)
|
||||
#define IP6_ADDRESS_STATE_VALID (0x4)
|
||||
#define IP6_ADDRESS_STATE_PREFERRED (0x5) /* includes valid */
|
||||
#define IP6_ADDRESS_STATE_DEPRECATED (0x6) /* includes valid */
|
||||
#define IP6_ADDRESS_STATE_TENTATIV (0x8)
|
||||
|
||||
/** 1 second period */
|
||||
#define ND6_TMR_INTERVAL 1000
|
||||
|
||||
/* Router tables. */
|
||||
/* TODO make these static? and entries accessible through API? */
|
||||
extern struct nd6_neighbor_cache_entry neighbor_cache[];
|
||||
extern struct nd6_destination_cache_entry destination_cache[];
|
||||
extern struct nd6_prefix_list_entry prefix_list[];
|
||||
extern struct nd6_router_list_entry default_router_list[];
|
||||
|
||||
/* Default values, can be updated by a RA message. */
|
||||
extern u32_t reachable_time;
|
||||
extern u32_t retrans_timer;
|
||||
|
||||
#define nd6_init() /* TODO should we init tables? */
|
||||
void nd6_tmr(void);
|
||||
void nd6_input(struct pbuf *p, struct netif *inp);
|
||||
s8_t nd6_get_next_hop_entry(ip6_addr_t * ip6addr, struct netif * netif);
|
||||
s8_t nd6_select_router(ip6_addr_t * ip6addr, struct netif * netif);
|
||||
u16_t nd6_get_destination_mtu(ip6_addr_t * ip6addr, struct netif * netif);
|
||||
#if LWIP_ND6_QUEUEING
|
||||
err_t nd6_queue_packet(s8_t neighbor_index, struct pbuf * p);
|
||||
#endif /* LWIP_ND6_QUEUEING */
|
||||
#if LWIP_ND6_TCP_REACHABILITY_HINTS
|
||||
void nd6_reachability_hint(ip6_addr_t * ip6addr);
|
||||
#endif /* LWIP_ND6_TCP_REACHABILITY_HINTS */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* LWIP_IPV6 */
|
||||
|
||||
#endif /* __LWIP_ND6_H__ */
|
Loading…
x
Reference in New Issue
Block a user