1/** 2 * @file 3 * 4 * Ethernet output for IPv6. Uses ND tables for link-layer addressing. 5 */ 6 7/* 8 * Copyright (c) 2010 Inico Technologies Ltd. 9 * All rights reserved. 10 * 11 * Redistribution and use in source and binary forms, with or without modification, 12 * are permitted provided that the following conditions are met: 13 * 14 * 1. Redistributions of source code must retain the above copyright notice, 15 * this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright notice, 17 * this list of conditions and the following disclaimer in the documentation 18 * and/or other materials provided with the distribution. 19 * 3. The name of the author may not be used to endorse or promote products 20 * derived from this software without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 23 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 24 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 25 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 26 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 27 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 30 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 31 * OF SUCH DAMAGE. 32 * 33 * This file is part of the lwIP TCP/IP stack. 34 * 35 * Author: Ivan Delamer <delamer@inicotech.com> 36 * 37 * 38 * Please coordinate changes and requests with Ivan Delamer 39 * <delamer@inicotech.com> 40 */ 41 42#include "lwip/opt.h" 43 44#if LWIP_IPV6 && LWIP_ETHERNET 45 46#include "lwip/ethip6.h" 47#include "lwip/nd6.h" 48#include "lwip/pbuf.h" 49#include "lwip/ip6.h" 50#include "lwip/ip6_addr.h" 51#include "lwip/inet_chksum.h" 52#include "lwip/netif.h" 53#include "lwip/icmp6.h" 54#include "lwip/prot/ethernet.h" 55#include "netif/ethernet.h" 56 57#include <string.h> 58 59/** 60 * Resolve and fill-in Ethernet address header for outgoing IPv6 packet. 61 * 62 * For IPv6 multicast, corresponding Ethernet addresses 63 * are selected and the packet is transmitted on the link. 64 * 65 * For unicast addresses, ask the ND6 module what to do. It will either let us 66 * send the the packet right away, or queue the packet for later itself, unless 67 * an error occurs. 68 * 69 * @todo anycast addresses 70 * 71 * @param netif The lwIP network interface which the IP packet will be sent on. 72 * @param q The pbuf(s) containing the IP packet to be sent. 73 * @param ip6addr The IP address of the packet destination. 74 * 75 * @return 76 * - ERR_OK or the return value of @ref nd6_get_next_hop_addr_or_queue. 77 */ 78err_t 79ethip6_output(struct netif *netif, struct pbuf *q, const ip6_addr_t *ip6addr) 80{ 81 struct eth_addr dest; 82 const u8_t *hwaddr; 83 err_t result; 84 85 /* multicast destination IP address? */ 86 if (ip6_addr_ismulticast(ip6addr)) { 87 /* Hash IP multicast address to MAC address.*/ 88 dest.addr[0] = 0x33; 89 dest.addr[1] = 0x33; 90 dest.addr[2] = ((const u8_t *)(&(ip6addr->addr[3])))[0]; 91 dest.addr[3] = ((const u8_t *)(&(ip6addr->addr[3])))[1]; 92 dest.addr[4] = ((const u8_t *)(&(ip6addr->addr[3])))[2]; 93 dest.addr[5] = ((const u8_t *)(&(ip6addr->addr[3])))[3]; 94 95 /* Send out. */ 96 return ethernet_output(netif, q, (const struct eth_addr*)(netif->hwaddr), &dest, ETHTYPE_IPV6); 97 } 98 99 /* We have a unicast destination IP address */ 100 /* @todo anycast? */ 101 102 /* Ask ND6 what to do with the packet. */ 103 result = nd6_get_next_hop_addr_or_queue(netif, q, ip6addr, &hwaddr); 104 if (result != ERR_OK) { 105 return result; 106 } 107 108 /* If no hardware address is returned, nd6 has queued the packet for later. */ 109 if (hwaddr == NULL) { 110 return ERR_OK; 111 } 112 113 /* Send out the packet using the returned hardware address. */ 114 SMEMCPY(dest.addr, hwaddr, 6); 115 return ethernet_output(netif, q, (const struct eth_addr*)(netif->hwaddr), &dest, ETHTYPE_IPV6); 116} 117 118#endif /* LWIP_IPV6 && LWIP_ETHERNET */ 119