185 lines
4.1 KiB
C
185 lines
4.1 KiB
C
|
/******************************************************************************
|
||
|
* Copyright (c) 2013 IBM Corporation
|
||
|
* All rights reserved.
|
||
|
* This program and the accompanying materials
|
||
|
* are made available under the terms of the BSD License
|
||
|
* which accompanies this distribution, and is available at
|
||
|
* http://www.opensource.org/licenses/bsd-license.php
|
||
|
*
|
||
|
* Contributors:
|
||
|
* IBM Corporation - initial implementation
|
||
|
*****************************************************************************/
|
||
|
|
||
|
#include <stdlib.h>
|
||
|
#include <string.h>
|
||
|
#include <stdio.h>
|
||
|
#include "ipv6.h"
|
||
|
#include "icmpv6.h"
|
||
|
#include "ndp.h"
|
||
|
|
||
|
/* Neighbor cache */
|
||
|
static struct neighbor *first_neighbor;
|
||
|
static struct neighbor *last_neighbor;
|
||
|
|
||
|
/* Router list */
|
||
|
static struct router *first_router;
|
||
|
static struct router *last_router;
|
||
|
|
||
|
/*
|
||
|
* NET: add new router to list
|
||
|
* @param struct router nghb - new router
|
||
|
* @return true or false
|
||
|
*/
|
||
|
int8_t
|
||
|
router_add (struct router *nghb )
|
||
|
{
|
||
|
if (nghb == NULL)
|
||
|
return -1;
|
||
|
|
||
|
if (first_router == NULL) {
|
||
|
first_router= nghb;
|
||
|
last_router = first_router;
|
||
|
last_router->next = NULL;
|
||
|
} else {
|
||
|
last_router->next = nghb;
|
||
|
last_router = nghb;
|
||
|
last_router->next = NULL;
|
||
|
}
|
||
|
return 1; /* no error */
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* NET: create a new router
|
||
|
* @param uint8_t *packet - received packet (Ethernet/IPv6/ICMPv6/ND_NghSlct)
|
||
|
* @param struct packeth - pointers to headers in packet
|
||
|
* @return pointer to new router
|
||
|
*/
|
||
|
void *
|
||
|
router_create(uint8_t *mac, ip6_addr_t ip)
|
||
|
{
|
||
|
struct router *new_router;
|
||
|
|
||
|
new_router = malloc (sizeof(struct router));
|
||
|
if( !new_router) {
|
||
|
return 0;
|
||
|
}
|
||
|
memset (new_router, 0, sizeof(struct router));
|
||
|
|
||
|
/* fill neighbor struct */
|
||
|
memcpy (new_router->mac, mac, 6);
|
||
|
memcpy (&(new_router->ip.addr[0]), ip.addr, IPV6_ADDR_LENGTH);
|
||
|
|
||
|
return new_router;
|
||
|
}
|
||
|
|
||
|
struct router *
|
||
|
find_router(ip6_addr_t ip)
|
||
|
{
|
||
|
struct router *n = NULL;
|
||
|
|
||
|
for (n = first_router; n != NULL ; n=n->next)
|
||
|
if (ip6_cmp(n->ip, ip))
|
||
|
return n; /* router is already in list*/
|
||
|
|
||
|
return NULL; /* router is unknown */
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Find a router for a given host address
|
||
|
* @param ip - IPv6 address with the prefered prefix
|
||
|
* @return pointer to router, or NULL if none is available
|
||
|
*/
|
||
|
struct router *ipv6_get_default_router(ip6_addr_t ip)
|
||
|
{
|
||
|
struct router *n = NULL;
|
||
|
|
||
|
for (n = first_router; n != NULL; n = n->next) {
|
||
|
if (n->ip.part.prefix == ip.part.prefix)
|
||
|
return n;
|
||
|
}
|
||
|
|
||
|
return first_router;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* NET: add new neighbor to list
|
||
|
* @param struct neighbor nghb - new neighbor
|
||
|
* @return true or false
|
||
|
*/
|
||
|
int8_t
|
||
|
neighbor_add (struct neighbor *nghb)
|
||
|
{
|
||
|
if (nghb == NULL)
|
||
|
return -1;
|
||
|
|
||
|
if (first_neighbor == NULL) {
|
||
|
first_neighbor = nghb;
|
||
|
last_neighbor = first_neighbor;
|
||
|
last_neighbor->next = NULL;
|
||
|
} else {
|
||
|
last_neighbor->next = nghb;
|
||
|
last_neighbor = nghb;
|
||
|
last_neighbor->next = NULL;
|
||
|
}
|
||
|
|
||
|
return 1; /* no error */
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* NET: create a new neighbor
|
||
|
* @param uint8_t *packet - received packet (Ethernet/IPv6/ICMPv6/ND_NghSlct)
|
||
|
* @param struct packeth - pointers to headers in packet
|
||
|
* @return pointer - pointer to new neighbor
|
||
|
* NULL - malloc failed
|
||
|
*/
|
||
|
void *
|
||
|
neighbor_create (uint8_t *packet, struct packeth *headers)
|
||
|
{
|
||
|
struct neighbor *new_neighbor;
|
||
|
|
||
|
new_neighbor = malloc (sizeof(struct neighbor));
|
||
|
if( !new_neighbor )
|
||
|
return NULL;
|
||
|
memset(new_neighbor, 0, sizeof(struct neighbor));
|
||
|
|
||
|
/* fill neighbor struct */
|
||
|
memcpy (&(new_neighbor->mac),
|
||
|
&(headers->ethh->src_mac[0]), 6);
|
||
|
memcpy (&(new_neighbor->ip.addr), &(headers->ip6h->src), IPV6_ADDR_LENGTH);
|
||
|
new_neighbor->status = NB_INCOMPLETE;
|
||
|
|
||
|
return new_neighbor;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* NET: Find neighbor with given IPv6 address in Neighbor Cache
|
||
|
*
|
||
|
* @param ip - Pointer to IPv6 address
|
||
|
* @return pointer - pointer to client IPv6 address (e.g. ::1)
|
||
|
* NULL - Neighbor not found
|
||
|
*/
|
||
|
struct neighbor *
|
||
|
find_neighbor(ip6_addr_t ip)
|
||
|
{
|
||
|
struct neighbor *n = NULL;
|
||
|
|
||
|
for (n = first_neighbor; n != NULL ; n=n->next) {
|
||
|
if (ip6_cmp(n->ip, ip)) {
|
||
|
return n; /* neighbor is already in cache */
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return NULL; /* neighbor is unknown */
|
||
|
}
|
||
|
|
||
|
void ndp_init(void)
|
||
|
{
|
||
|
/* Router list */
|
||
|
first_router = NULL;
|
||
|
last_router = first_router;
|
||
|
|
||
|
/* Init Neighbour cache */
|
||
|
first_neighbor = NULL;
|
||
|
last_neighbor = first_neighbor;
|
||
|
}
|