/*
* Copyright (c) 2011, Broadcom Corporation
* Copyright (c) 2014, QLogic Corporation
*
* Written by: Eddie Wai (eddie.wai@broadcom.com)
* Based on Kevin Tran's iSCSI boot code
*
* 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. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Adam Dunkels.
* 4. 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.
*
* ipv6.h - This file contains macro definitions pertaining to IPv6.
*
* RFC 2460 : IPv6 Specification.
* RFC 2373 : IPv6 Addressing Architecture.
* RFC 2462 : IPv6 Stateless Address Autoconfiguration.
* RFC 2464 : Transmission of IPv6 Packets over Ethernet Networks.
*
*/
#ifndef __IPV6_H__
#define __IPV6_H__
#include "ipv6_ndpc.h"
#define FALSE 0
#define TRUE 1
#define LINK_LOCAL_PREFIX_LENGTH 2
#define LAYER2_HEADER_LENGTH 14
#define LAYER2_VLAN_HEADER_LENGTH 16
#define LAYER2_TYPE_IPV6 0x86dd
struct ipv6_addr {
union {
u8_t addr8[16];
u16_t addr16[8];
u32_t addr[4];
};
};
struct udp_hdr {
u16_t src_port;
u16_t dest_port;
u16_t length;
u16_t chksum;
};
struct mac_address {
union {
u8_t addr[6];
struct {
u16_t first_2_bytes;
u32_t last_4_bytes;
} __attribute__ ((packed));
};
};
#define HOST_TO_NET16(a) htons(a)
#define HOST_TO_NET32(a) htonl(a)
#define NET_TO_HOST16(a) ntohs(a)
/*
* Local definition for masks
*/
#define IPV6_MASK0 { { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } } }
#define IPV6_MASK32 { { { 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, \
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }
#define IPV6_MASK64 { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }
#define IPV6_MASK96 { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 } } }
#define IPV6_MASK128 { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } } }
#ifdef BIG_ENDIAN
#define IPV6_ADDR_INT32_ONE 1
#define IPV6_ADDR_INT32_TWO 2
#define IPV6_ADDR_INT32_MNL 0xff010000
#define IPV6_ADDR_INT32_MLL 0xff020000
#define IPV6_ADDR_INT32_SMP 0x0000ffff
#define IPV6_ADDR_INT16_ULL 0xfe80
#define IPV6_ADDR_INT16_USL 0xfec0
#define IPV6_ADDR_INT16_MLL 0xff02
#else /* LITTE ENDIAN */
#define IPV6_ADDR_INT32_ONE 0x01000000
#define IPV6_ADDR_INT32_TWO 0x02000000
#define IPV6_ADDR_INT32_MNL 0x000001ff
#define IPV6_ADDR_INT32_MLL 0x000002ff
#define IPV6_ADDR_INT32_SMP 0xffff0000
#define IPV6_ADDR_INT16_ULL 0x80fe
#define IPV6_ADDR_INT16_USL 0xc0fe
#define IPV6_ADDR_INT16_MLL 0x02ff
#endif
/*
* Definition of some useful macros to handle IP6 addresses
*/
#define IPV6_ADDR_ANY_INIT \
{ { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }
#define IPV6_ADDR_LOOPBACK_INIT \
{ { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } } }
#define IPV6_ADDR_NODELOCAL_ALLNODES_INIT \
{ { { 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } } }
#define IPV6_ADDR_INTFACELOCAL_ALLNODES_INIT \
{ { { 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } } }
#define IPV6_ADDR_LINKLOCAL_ALLNODES_INIT \
{ { { 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } } }
#define IPV6_ADDR_LINKLOCAL_ALLROUTERS_INIT \
{ { { 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 } } }
#define IPV6_ARE_ADDR_EQUAL(a, b) \
(memcmp((char *)a, (char *)b, sizeof(struct ipv6_addr)) == 0)
/* Unspecified IPv6 address */
#define IPV6_IS_ADDR_UNSPECIFIED(a) \
((((a)->addr[0]) == 0) && \
(((a)->addr[1]) == 0) && \
(((a)->addr[2]) == 0) && \
(((a)->addr[3]) == 0))
/* IPv6 Scope Values */
#define IPV6_ADDR_SCOPE_INTFACELOCAL 0x01 /* Node-local scope */
#define IPV6_ADDR_SCOPE_LINKLOCAL 0x02 /* Link-local scope */
#define IPV6_ADDR_SCOPE_SITELOCAL 0x05 /* Site-local scope */
#define IPV6_ADDR_SCOPE_ORGLOCAL 0x08 /* Organization-local scope */
#define IPV6_ADDR_SCOPE_GLOBAL 0x0e /* Global scope */
/* Link-local Unicast : 10-bits much be 1111111010b --> 0xfe80. */
#define IPV6_IS_ADDR_LINKLOCAL(a) \
(((a)->addr8[0] == 0xfe) && (((a)->addr8[1] & 0xc0) == 0x80))
/* Site-local Unicast : 10-bits much be 1111111011b --> 0xfec0. */
#define IPV6_IS_ADDR_SITELOCAL(a) \
(((a)->addr8[0] == 0xfe) && (((a)->addr8[1] & 0xc0) == 0xc0))
/* Multicast : 10bits much be 11111111b. Next 4 bits is flags | 4-bit scope */
#define IPV6_IS_ADDR_MULTICAST(a) ((a)->addr8[0] == 0xff)
#define IPV6_ADDR_MC_SCOPE(a) ((a)->addr8[1] & 0x0f)
/* Multicast Scope */
struct eth_hdr {
struct mac_address dest_mac;
struct mac_address src_mac;
u16_t len_type;
};
struct ipv6_hdr {
union {
struct {
u32_t ipv6_flow; /* Version (4-bit) |
Traffic Class (8-bit) |
Flow ID (20-bit) */
u16_t ipv6_plen; /* Payload length */
u8_t ipv6_nxt_hdr; /* Next Header */
u8_t ipv6_hop_limit; /* hop limit */
} ipv6_dw1;
u8_t ipv6_version_fc; /* 4 bits version, top 4 bits class */
} ipv6_ctrl;
struct ipv6_addr ipv6_src; /* Source address */
struct ipv6_addr ipv6_dst; /* Destination address */
};
#define ipv6_version_fc ipv6_ctrl.ipv6_version_fc
#define ipv6_flow ipv6_ctrl.ipv6_dw1.ipv6_flow
#define ipv6_plen ipv6_ctrl.ipv6_dw1.ipv6_plen
#define ipv6_nxt_hdr ipv6_ctrl.ipv6_dw1.ipv6_nxt_hdr
#define ipv6_hop_limit ipv6_ctrl.ipv6_dw1.ipv6_hop_limit
#define IPV6_VERSION 0x60
#define IPV6_VERSION_MASK 0xf0
#define IPV6_HOP_LIMIT 64
/* Length of the IP header with no next header */
#define IPV6_HEADER_LEN sizeof(struct ipv6_hdr)
#ifdef BIG_ENDIAN
#define IPV6_FLOWINFO_MASK 0x0fffffff /* flow info (28 bits) */
#define IPV6_FLOWLABEL_MASK 0x000fffff /* flow label (20 bits) */
#else /* LITTLE_ENDIAN */
#define IPV6_FLOWINFO_MASK 0xffffff0f /* flow info (28 bits) */
#define IPV6_FLOWLABEL_MASK 0xffff0f00 /* flow label (20 bits) */
#endif
struct packet_ipv6 {
struct mac_address dest_mac;
struct mac_address src_mac;
u16_t len_type;
struct ipv6_hdr ipv6;
union {
struct udp_hdr udp;
} layer4_prot;
};
struct packet_ipv6_vlan {
struct mac_address dest_mac;
struct mac_address src_mac;
u16_t len_type;
u16_t vlan_id;
struct ipv6_hdr ipv6;
union {
struct udp_hdr udp;
} layer4_prot;
};
struct ipv6_arp_entry {
struct ipv6_addr ip_addr;
struct mac_address mac_addr;
u8_t time;
};
#define IPV6_NUM_OF_ADDRESS_ENTRY 4
struct ipv6_prefix_entry {
struct ipv6_prefix_entry *next;
struct ipv6_addr ip_addr;
u8_t prefix_len;
};
struct ipv6_addr_entry {
struct ipv6_addr ip_addr;
u8_t prefix_len;
};
struct ipv6_context {
u16_t flags;
#define IPV6_FLAGS_MANAGED_ADDR_CONFIG (1 << 0)
#define IPV6_FLAGS_OTHER_STATEFUL_CONFIG (1 << 1)
#define IPV6_FLAGS_ROUTER_ADV_RECEIVED (1 << 2)
#define IPV6_FLAGS_DISABLE_DHCPV6 (1 << 3)
struct mac_address mac_addr;
struct ipv6_addr link_local_addr;
struct ipv6_addr link_local_multi;
struct ipv6_addr multi; /* For Static IPv6 only */
struct ipv6_addr multi_dest; /* For Static IPv6 only */
struct ipv6_addr default_router;
struct ipv6_prefix_entry *addr_list;
u8_t hop_limit;
#define UIP_ARPTAB_SIZE 16
struct uip_stack *ustack;
#define MAX_MCADDR_TABLE 5
struct mac_address mc_addr[MAX_MCADDR_TABLE];
u8_t arptime;
struct ipv6_arp_entry ipv6_arp_table[UIP_ARPTAB_SIZE];
struct ipv6_prefix_entry ipv6_prefix_table[IPV6_NUM_OF_ADDRESS_ENTRY];
/* VLAN support */
void *dhcpv6_context;
};
#define ISCSI_FLAGS_DHCP_TCPIP_CONFIG (1<<0)
#define ISCSI_FLAGS_DHCP_ISCSI_CONFIG (1<<1)
#define IPV6_MAX_ROUTER_SOL_DELAY 4
#define IPV6_MAX_ROUTER_SOL_RETRY 3
#define DHCPV6_CLIENT_PORT 546
#define DHCPV6_SERVER_PORT 547
/* Function prototype */
void ipv6_init(struct ndpc_state *ndp, int cfg);
int ipv6_autoconfig(struct ipv6_context *context);
int ipv6_discover_address(struct ipv6_context *context);
struct ipv6_addr *ipv6_our_address(struct ipv6_context *context);
int ipv6_ip_in_arp_table(struct ipv6_context *context,
struct ipv6_addr *ipv6_addr,
struct mac_address *mac_addr);
void ipv6_arp_timer(struct ipv6_context *context);
void ipv6_arp_out(struct ipv6_context *context, int *uip_len);
int ipv6_add_prefix_entry(struct ipv6_context *context,
struct ipv6_addr *ip_addr, u8_t prefix_len);
void ipv6_set_ip_params(struct ipv6_context *context,
struct ipv6_addr *src_ip, u8_t prefix_len,
struct ipv6_addr *default_gateway,
struct ipv6_addr *linklocal);
void ipv6_set_host_addr(struct ipv6_context *context, struct ipv6_addr *src_ip);
int ipv6_get_default_router_ip_addrs(struct ipv6_context *context,
struct ipv6_addr *ip_addr);
struct mac_address *ipv6_get_link_addr(struct ipv6_context *context);
u16_t ipv6_do_stateful_dhcpv6(struct ipv6_context *context, u32_t flags);
void ipv6_add_solit_node_address(struct ipv6_context *context,
struct ipv6_addr *ip_addr);
int ipv6_get_source_ip_addrs(struct ipv6_context *context,
struct ipv6_addr_entry *addr_list);
void ipv6_cfg_link_local_addr(struct ipv6_context *context,
struct ipv6_addr *ip_addr);
void ipv6_disable_dhcpv6(struct ipv6_context *context);
int ipv6_send_nd_solicited_packet(struct ipv6_context *context,
struct eth_hdr *eth, struct ipv6_hdr *ipv6);
int ipv6_is_it_our_link_local_address(struct ipv6_context *context,
struct ipv6_addr *ip_addr);
void ipv6_mc_init_dest_mac(struct eth_hdr *eth, struct ipv6_hdr *ipv6);
struct ipv6_addr *ipv6_find_longest_match(struct ipv6_context *context,
struct ipv6_addr *ip_addr);
#endif /* __IPV6_H__ */