Blame iscsiuio/src/uip/uip-neighbor.c

Packit eace71
/*
Packit eace71
 * Copyright (c) 2006, Swedish Institute of Computer Science.
Packit eace71
 * All rights reserved.
Packit eace71
 *
Packit eace71
 * Redistribution and use in source and binary forms, with or without
Packit eace71
 * modification, are permitted provided that the following conditions
Packit eace71
 * are met:
Packit eace71
 * 1. Redistributions of source code must retain the above copyright
Packit eace71
 *    notice, this list of conditions and the following disclaimer.
Packit eace71
 * 2. Redistributions in binary form must reproduce the above copyright
Packit eace71
 *    notice, this list of conditions and the following disclaimer in the
Packit eace71
 *    documentation and/or other materials provided with the distribution.
Packit eace71
 * 3. Neither the name of the Institute nor the names of its contributors
Packit eace71
 *    may be used to endorse or promote products derived from this software
Packit eace71
 *    without specific prior written permission.
Packit eace71
 *
Packit eace71
 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
Packit eace71
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
Packit eace71
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
Packit eace71
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
Packit eace71
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
Packit eace71
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
Packit eace71
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
Packit eace71
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
Packit eace71
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
Packit eace71
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
Packit eace71
 * SUCH DAMAGE.
Packit eace71
 *
Packit eace71
 * This file is part of the uIP TCP/IP stack
Packit eace71
 *
Packit eace71
 */
Packit eace71
Packit eace71
/**
Packit eace71
 * \file
Packit eace71
 *         Database of link-local neighbors, used by IPv6 code and
Packit eace71
 *         to be used by a future ARP code rewrite.
Packit eace71
 * \author
Packit eace71
 *         Adam Dunkels <adam@sics.se>
Packit eace71
 */
Packit eace71
Packit eace71
#include "logger.h"
Packit eace71
#include "uip.h"
Packit eace71
#include "uip-neighbor.h"
Packit eace71
Packit eace71
#include <errno.h>
Packit eace71
#include <string.h>
Packit eace71
#include <arpa/inet.h>
Packit eace71
Packit eace71
/*******************************************************************************
Packit eace71
 * Constants
Packit eace71
 ******************************************************************************/
Packit eace71
#define PFX "uip-neigh "
Packit eace71
Packit eace71
#define MAX_TIME 128
Packit eace71
Packit eace71
/*---------------------------------------------------------------------------*/
Packit eace71
void uip_neighbor_init(struct uip_stack *ustack)
Packit eace71
{
Packit eace71
	int i;
Packit eace71
Packit eace71
	pthread_mutex_lock(&ustack->lock);
Packit eace71
	for (i = 0; i < UIP_NEIGHBOR_ENTRIES; ++i) {
Packit eace71
		memset(&(ustack->neighbor_entries[i].ipaddr), 0,
Packit eace71
		       sizeof(ustack->neighbor_entries[i].ipaddr));
Packit eace71
		memset(&(ustack->neighbor_entries[i].mac_addr), 0,
Packit eace71
		       sizeof(ustack->neighbor_entries[i].mac_addr));
Packit eace71
		ustack->neighbor_entries[i].time = MAX_TIME;
Packit eace71
	}
Packit eace71
	pthread_mutex_unlock(&ustack->lock);
Packit eace71
}
Packit eace71
Packit eace71
void uip_neighbor_add(struct uip_stack *ustack,
Packit eace71
		      struct in6_addr *addr6, struct uip_eth_addr *addr)
Packit eace71
{
Packit eace71
	int i, oldest;
Packit eace71
	u8_t oldest_time;
Packit eace71
	char buf[INET6_ADDRSTRLEN];
Packit eace71
Packit eace71
	inet_ntop(AF_INET6, addr6, buf, sizeof(buf));
Packit eace71
Packit eace71
	pthread_mutex_lock(&ustack->lock);
Packit eace71
Packit eace71
	/* Find the first unused entry or the oldest used entry. */
Packit eace71
	oldest_time = 0;
Packit eace71
	oldest = 0;
Packit eace71
	for (i = 0; i < UIP_NEIGHBOR_ENTRIES; ++i) {
Packit eace71
		if (ustack->neighbor_entries[i].time == MAX_TIME) {
Packit eace71
			oldest = i;
Packit eace71
			break;
Packit eace71
		}
Packit eace71
		if (uip_ip6addr_cmp
Packit eace71
		    (ustack->neighbor_entries[i].ipaddr.s6_addr, addr6)) {
Packit eace71
			oldest = i;
Packit eace71
			break;
Packit eace71
		}
Packit eace71
		if (ustack->neighbor_entries[i].time > oldest_time) {
Packit eace71
			oldest = i;
Packit eace71
			oldest_time = ustack->neighbor_entries[i].time;
Packit eace71
		}
Packit eace71
	}
Packit eace71
Packit eace71
	/* Use the oldest or first free entry (either pointed to by the
Packit eace71
	   "oldest" variable). */
Packit eace71
	ustack->neighbor_entries[oldest].time = 0;
Packit eace71
	uip_ip6addr_copy(ustack->neighbor_entries[oldest].ipaddr.s6_addr,
Packit eace71
			 addr6);
Packit eace71
	memcpy(&ustack->neighbor_entries[oldest].mac_addr, addr,
Packit eace71
	       sizeof(struct uip_eth_addr));
Packit eace71
Packit eace71
	LOG_DEBUG("Adding neighbor %s with "
Packit eace71
		  "mac address %02x:%02x:%02x:%02x:%02x:%02x at %d",
Packit eace71
		  buf, addr->addr[0], addr->addr[1], addr->addr[2],
Packit eace71
		  addr->addr[3], addr->addr[4], addr->addr[5], oldest);
Packit eace71
Packit eace71
	pthread_mutex_unlock(&ustack->lock);
Packit eace71
}
Packit eace71
Packit eace71
/*---------------------------------------------------------------------------*/
Packit eace71
static struct neighbor_entry *find_entry(struct uip_stack *ustack,
Packit eace71
					 struct in6_addr *addr6)
Packit eace71
{
Packit eace71
	int i;
Packit eace71
Packit eace71
	for (i = 0; i < UIP_NEIGHBOR_ENTRIES; ++i) {
Packit eace71
		if (uip_ip6addr_cmp
Packit eace71
		    (ustack->neighbor_entries[i].ipaddr.s6_addr,
Packit eace71
		     addr6->s6_addr)) {
Packit eace71
			return &ustack->neighbor_entries[i];
Packit eace71
		}
Packit eace71
	}
Packit eace71
Packit eace71
	return NULL;
Packit eace71
}
Packit eace71
Packit eace71
/*---------------------------------------------------------------------------*/
Packit eace71
void uip_neighbor_update(struct uip_stack *ustack, struct in6_addr *addr6)
Packit eace71
{
Packit eace71
	struct neighbor_entry *e;
Packit eace71
Packit eace71
	pthread_mutex_lock(&ustack->lock);
Packit eace71
Packit eace71
	e = find_entry(ustack, addr6);
Packit eace71
	if (e != NULL)
Packit eace71
		e->time = 0;
Packit eace71
Packit eace71
	pthread_mutex_unlock(&ustack->lock);
Packit eace71
}
Packit eace71
Packit eace71
/*---------------------------------------------------------------------------*/
Packit eace71
int uip_neighbor_lookup(struct uip_stack *ustack,
Packit eace71
			struct in6_addr *addr6, uint8_t *mac_addr)
Packit eace71
{
Packit eace71
	struct neighbor_entry *e;
Packit eace71
Packit eace71
	pthread_mutex_lock(&ustack->lock);
Packit eace71
	e = find_entry(ustack, addr6);
Packit eace71
	if (e != NULL) {
Packit eace71
		char addr6_str[INET6_ADDRSTRLEN];
Packit eace71
		uint8_t *entry_mac_addr;
Packit eace71
Packit eace71
		addr6_str[0] = '\0';
Packit eace71
		inet_ntop(AF_INET6, addr6->s6_addr, addr6_str,
Packit eace71
			  sizeof(addr6_str));
Packit eace71
		entry_mac_addr = (uint8_t *)&e->mac_addr.addr;
Packit eace71
Packit eace71
		LOG_DEBUG(PFX
Packit eace71
			  "Found %s at %02x:%02x:%02x:%02x:%02x:%02x",
Packit eace71
			  addr6_str,
Packit eace71
			  entry_mac_addr[0], entry_mac_addr[1],
Packit eace71
			  entry_mac_addr[2], entry_mac_addr[3],
Packit eace71
			  entry_mac_addr[4], entry_mac_addr[5]);
Packit eace71
Packit eace71
		memcpy(mac_addr, entry_mac_addr, sizeof(e->mac_addr));
Packit eace71
		pthread_mutex_unlock(&ustack->lock);
Packit eace71
		return 0;
Packit eace71
	}
Packit eace71
Packit eace71
	pthread_mutex_unlock(&ustack->lock);
Packit eace71
	return -ENOENT;
Packit eace71
}
Packit eace71
Packit eace71
void uip_neighbor_out(struct uip_stack *ustack)
Packit eace71
{
Packit eace71
	struct neighbor_entry *e;
Packit eace71
	struct uip_eth_hdr *eth_hdr =
Packit eace71
	    (struct uip_eth_hdr *)ustack->data_link_layer;
Packit eace71
	struct uip_ipv6_hdr *ipv6_hdr =
Packit eace71
	    (struct uip_ipv6_hdr *)ustack->network_layer;
Packit eace71
Packit eace71
	pthread_mutex_lock(&ustack->lock);
Packit eace71
Packit eace71
	/* Find the destination IP address in the neighbor table and construct
Packit eace71
	   the Ethernet header. If the destination IP addres isn't on the
Packit eace71
	   local network, we use the default router's IP address instead.
Packit eace71
Packit eace71
	   If not ARP table entry is found, we overwrite the original IP
Packit eace71
	   packet with an ARP request for the IP address. */
Packit eace71
	e = find_entry(ustack, (struct in6_addr *)ipv6_hdr->destipaddr);
Packit eace71
	if (e == NULL) {
Packit eace71
		struct uip_eth_addr eth_addr_tmp;
Packit eace71
Packit eace71
		memcpy(&eth_addr_tmp, eth_hdr->src.addr, sizeof(eth_addr_tmp));
Packit eace71
		memcpy(eth_hdr->src.addr, ustack->uip_ethaddr.addr,
Packit eace71
		       sizeof(eth_hdr->src.addr));
Packit eace71
		memcpy(eth_hdr->dest.addr, &eth_addr_tmp,
Packit eace71
		       sizeof(eth_hdr->dest.addr));
Packit eace71
Packit eace71
		pthread_mutex_unlock(&ustack->lock);
Packit eace71
		return;
Packit eace71
	}
Packit eace71
Packit eace71
	memcpy(eth_hdr->dest.addr, &e->mac_addr, sizeof(eth_hdr->dest.addr));
Packit eace71
	memcpy(eth_hdr->src.addr, ustack->uip_ethaddr.addr,
Packit eace71
	       sizeof(eth_hdr->src.addr));
Packit eace71
Packit eace71
	pthread_mutex_unlock(&ustack->lock);
Packit eace71
}
Packit eace71
Packit eace71
/*---------------------------------------------------------------------------*/