1 /******************************************************************************
2  * Copyright (c) 2013 IBM Corporation
3  * All rights reserved.
4  * This program and the accompanying materials
5  * are made available under the terms of the BSD License
6  * which accompanies this distribution, and is available at
7  * http://www.opensource.org/licenses/bsd-license.php
8  *
9  * Contributors:
10  *     IBM Corporation - initial implementation
11  *****************************************************************************/
12 
13 #include <stdlib.h>
14 #include <string.h>
15 #include <stdio.h>
16 #include "ipv6.h"
17 #include "icmpv6.h"
18 #include "ndp.h"
19 
20 /* Neighbor cache */
21 static struct neighbor *first_neighbor;
22 static struct neighbor *last_neighbor;
23 
24 /* Router list */
25 static struct router *first_router;
26 static struct router *last_router;
27 
28 /*
29  * NET: add new router to list
30  * @param  struct router nghb  - new router
31  * @return true or false
32  */
33 int8_t
router_add(struct router * nghb)34 router_add (struct router *nghb )
35 {
36 	if (nghb == NULL)
37 		return -1;
38 
39 	if (first_router == NULL) {
40 		first_router= nghb;
41 		last_router = first_router;
42 		last_router->next = NULL;
43 	} else {
44 		last_router->next = nghb;
45 		last_router = nghb;
46 		last_router->next = NULL;
47 	}
48 	return 1; /* no error */
49 }
50 
51 /*
52  * NET: create a new router
53  * @param  uint8_t *packet - received packet (Ethernet/IPv6/ICMPv6/ND_NghSlct)
54  * @param  struct packeth  - pointers to headers in packet
55  * @return pointer to new router
56  */
57 void *
router_create(uint8_t * mac,ip6_addr_t ip)58 router_create(uint8_t *mac, ip6_addr_t ip)
59 {
60 	struct router *new_router;
61 
62 	new_router = malloc (sizeof(struct router));
63 	if( !new_router) {
64 		return 0;
65 	}
66 	memset (new_router, 0, sizeof(struct router));
67 
68 	/* fill neighbor struct */
69 	memcpy (new_router->mac, mac, 6);
70 	memcpy (&(new_router->ip.addr[0]), ip.addr, IPV6_ADDR_LENGTH);
71 
72 	return new_router;
73 }
74 
75 struct router *
find_router(ip6_addr_t ip)76 find_router(ip6_addr_t ip)
77 {
78 	struct router *n = NULL;
79 
80 	for (n = first_router; n != NULL ; n=n->next)
81 		if (ip6_cmp(n->ip, ip))
82 			return n; /* router is already in list*/
83 
84 	return NULL; /* router is unknown */
85 }
86 
87 /**
88  * Find a router for a given host address
89  * @param  ip - IPv6 address with the prefered prefix
90  * @return pointer to router, or NULL if none is available
91  */
ipv6_get_default_router(ip6_addr_t ip)92 struct router *ipv6_get_default_router(ip6_addr_t ip)
93 {
94 	struct router *n = NULL;
95 
96 	for (n = first_router; n != NULL; n = n->next) {
97 		if (n->ip.part.prefix == ip.part.prefix)
98 			return n;
99 	}
100 
101 	return first_router;
102 }
103 
104 /*
105  * NET: add new neighbor to list
106  * @param  struct neighbor nghb  - new neighbor
107  * @return true or false
108  */
109 int8_t
neighbor_add(struct neighbor * nghb)110 neighbor_add (struct neighbor *nghb)
111 {
112 	if (nghb == NULL)
113 		return -1;
114 
115 	if (first_neighbor == NULL) {
116 		first_neighbor = nghb;
117 		last_neighbor = first_neighbor;
118 		last_neighbor->next = NULL;
119 	} else {
120 		last_neighbor->next = nghb;
121 		last_neighbor = nghb;
122 		last_neighbor->next = NULL;
123 	}
124 
125 	return 1; /* no error */
126 }
127 
128 /*
129  * NET: create a new neighbor
130  * @param  uint8_t *packet - received packet (Ethernet/IPv6/ICMPv6/ND_NghSlct)
131  * @param  struct packeth  - pointers to headers in packet
132  * @return pointer         - pointer to new neighbor
133  *         NULL            - malloc failed
134  */
135 void *
neighbor_create(uint8_t * packet,struct packeth * headers)136 neighbor_create (uint8_t *packet, struct packeth *headers)
137 {
138 	struct neighbor *new_neighbor;
139 
140 	new_neighbor = malloc (sizeof(struct neighbor));
141 	if( !new_neighbor )
142 		return NULL;
143 	memset(new_neighbor, 0, sizeof(struct neighbor));
144 
145 	/* fill neighbor struct */
146 	memcpy (&(new_neighbor->mac),
147 		&(headers->ethh->src_mac[0]), 6);
148 	memcpy (&(new_neighbor->ip.addr), &(headers->ip6h->src), IPV6_ADDR_LENGTH);
149 	new_neighbor->status = NB_INCOMPLETE;
150 
151 	return new_neighbor;
152 }
153 
154 /**
155  * NET: Find neighbor with given IPv6 address in Neighbor Cache
156  *
157  * @param  ip - Pointer to IPv6 address
158  * @return pointer - pointer to client IPv6 address (e.g. ::1)
159  *         NULL    - Neighbor not found
160  */
161 struct neighbor *
find_neighbor(ip6_addr_t ip)162 find_neighbor(ip6_addr_t ip)
163 {
164 	struct neighbor *n = NULL;
165 
166 	for (n = first_neighbor; n != NULL ; n=n->next) {
167 		if (ip6_cmp(n->ip, ip)) {
168 			return n; /* neighbor is already in cache */
169 		}
170 	}
171 
172 	return NULL; /* neighbor is unknown */
173 }
174 
ndp_init(void)175 void ndp_init(void)
176 {
177 	/* Router list */
178 	first_router = NULL;
179 	last_router = first_router;
180 
181 	/* Init Neighbour cache */
182 	first_neighbor = NULL;
183 	last_neighbor  = first_neighbor;
184 }
185