1 /********************************************************************************
2 NDPMon - Neighbor Discovery Protocol Monitor
3 Copyright (C) 2006 MADYNES Project, LORIA - INRIA Lorraine (France)
4 
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9 
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 Lesser General Public License for more details.
14 
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
18 
19 Author Info:
20   Name: Thibault Cholez
21   Mail: thibault.cholez@esial.uhp-nancy.fr
22 
23 Maintainer:
24   Name: Frederic Beck
25   Mail: frederic.beck@loria.fr
26 
27 MADYNES Project, LORIA-INRIA Lorraine, hereby disclaims all copyright interest in
28 the tool 'NDPMon' (Neighbor Discovery Protocol Monitor) written by Thibault Cholez.
29 
30 Olivier Festor, Scientific Leader of the MADYNEs Project, 20 August 2006
31 ***********************************************************************************/
32 
33 #include "membounds.h"
34 #ifdef _COUNTERMEASURES_
35 #include "./plugins/countermeasures/countermeasures.h"
36 #endif
37 #include "monitoring_ra.h"
38 
39 #if 0
40 
41 /*Test if the RA comes from a router with IP6 address specified in the
42  *configuration file.
43  *@return: 0=ok, not 0=pb
44  */
45 int watch_ra_ip(char* buffer, struct ether_header* eptr, struct ip6_hdr* ipptr)
46 {
47 	router_list_t *tmp = routers;
48 	char ip_address[IP6_STR_SIZE];
49 
50 	while(tmp != NULL)
51 	{
52 		/* RA supposed to come from a LLA */
53 		if(IN6_ARE_ADDR_EQUAL(&ipptr->ip6_src,&(tmp->lla)))
54 			return 0;
55 
56         /* REM
57 		ipv6_ntoa(ip_address, ipptr->ip6_src);
58 		snprintf (buffer, NOTIFY_BUFFER_SIZE, "wrong router ip %s %s", ether_ntoa((struct ether_addr*) (eptr->ether_shost)), ip_address);
59 		notify(2, buffer, "wrong router ip", (struct ether_addr*) (eptr->ether_shost), ip_address, NULL);
60 		return 2;
61 		END REM*/
62 
63 		tmp = tmp->next;
64 	}
65 
66 	/* if no such router is found*/
67 
68     ipv6_ntoa(ip_address, ipptr->ip6_src);
69     snprintf (buffer, NOTIFY_BUFFER_SIZE, "wrong router ip %s %s", ether_ntoa((struct ether_addr*) (eptr->ether_shost)), ip_address);
70     notify(2, buffer, "wrong router ip", (struct ether_addr*) (eptr->ether_shost), ip_address, NULL);
71     return 2;
72 
73 }
74 
75 
76 /*Test if the RA comes from a router with MAC address specified in the
77  *configuration file.
78  *@return: 0=ok, not 0=pb
79  */
80 int watch_ra_mac(char* buffer, struct ether_header* eptr, struct ip6_hdr* ipptr)
81 {
82 	router_list_t *tmp = routers;
83 	char ip_address[IP6_STR_SIZE];
84 	char* mac_address;
85 
86 	mac_address= (char*)ether_ntoa((struct ether_addr*) (eptr->ether_shost));
87 
88 	while(tmp != NULL)
89 	{
90 		/* RA supposed to come from a LLA */
91 		if(!MEMCMP(eptr->ether_shost,&(tmp->mac),sizeof(struct ether_addr)))
92 			return 0;
93 
94         /*REM
95 		ipv6_ntoa(ip_address, ipptr->ip6_src);
96 		snprintf (buffer, NOTIFY_BUFFER_SIZE, "wrong router mac %s %s", mac_address, ip_address);
97 		notify(2, buffer, "wrong router mac", (struct ether_addr*) (eptr->ether_shost), ip_address, NULL);
98 		return 2;
99 		END REM*/
100 
101 		tmp = tmp->next;
102 	}
103 
104 	/* if no such router is found */
105 
106 	ipv6_ntoa(ip_address, ipptr->ip6_src);
107 	snprintf (buffer, NOTIFY_BUFFER_SIZE, "wrong router mac %s %s", mac_address, ip_address);
108 	notify(2, buffer, "wrong router mac", (struct ether_addr*) (eptr->ether_shost), ip_address, NULL);
109 	return 2;
110 }
111 
112 
113 /*Test if the prefix specified in RA is right according to the configuration
114  *file
115  */
116 int watch_ra_prefix(char* buffer,  const u_char* packet, struct ether_header* eptr, struct ip6_hdr* ipptr, int packet_len)
117 {
118 	router_list_t *tmp = routers;
119 	char prefix[IP6_STR_SIZE];
120 	const u_char* pos;
121 	struct nd_opt_hdr* optptr;  /*netinet/icmp6.h*/
122 	struct nd_opt_prefix_info* preptr = NULL;
123 	int find=0;
124 
125 	/*We have to search the prefix option among the others NA options*/
126 	pos = packet + ETHERNET_SIZE + IPV6_SIZE + sizeof(struct nd_router_advert);
127 	optptr = (struct nd_opt_hdr*) ( pos );
128 
129 	while((optptr->nd_opt_type!=0)&&((u_char*)optptr < (packet+packet_len)))
130 	{
131 		if(optptr->nd_opt_type ==  ND_OPT_PREFIX_INFORMATION)
132 		{
133 
134 			preptr = (struct nd_opt_prefix_info*) optptr;
135 			ipv6pre_ntoa(prefix, preptr->nd_opt_pi_prefix);
136 
137 			while(tmp != NULL)
138 			{
139 				if(router_has_prefix(routers, tmp->lla, tmp->mac, preptr->nd_opt_pi_prefix, preptr->nd_opt_pi_prefix_len))
140 					find = 1;
141 
142 				tmp = tmp->next;
143 			}
144 
145 			if(!find)
146 			{
147 				char ip_address[IP6_STR_SIZE];
148 				ipv6_ntoa(ip_address, ipptr->ip6_src);
149 				snprintf (buffer, NOTIFY_BUFFER_SIZE, "wrong prefix %s %s %s", prefix,(char*)ether_ntoa((struct ether_addr*) (eptr->ether_shost)), ip_address);
150 				notify(2, buffer, "wrong prefix", (struct ether_addr*) (eptr->ether_shost), ip_address, NULL);
151 				return 2;
152 			}
153 		}
154 
155 		/*Next option field*/
156 		pos += (optptr->nd_opt_len)*8;
157 		optptr = (struct nd_opt_hdr*) ( pos );
158 
159 	}
160 
161 	return 0;
162 }
163 
164 #endif
165 
watch_ra(char * buffer,const u_char * packet,struct ether_header * eptr,struct ip6_hdr * ipptr,int packet_len)166 int watch_ra(char* buffer,  const u_char* packet, struct ether_header* eptr, struct ip6_hdr* ipptr, int packet_len)
167 {
168 	router_list_t* router=NULL;
169 	int ret = 0;
170 	struct ether_addr *src_eth;
171 	char  eth[ETH_ADDRSTRLEN], ip_address[IP6_STR_SIZE];
172 
173 	src_eth = (struct ether_addr *) eptr->ether_shost;
174 	ipv6_ntoa(ip_address, ipptr->ip6_src);
175 	strncpy(eth,ether_ntoa(src_eth), ETH_ADDRSTRLEN);
176 	router = router_get(routers, ipptr->ip6_src, *src_eth);
177 
178 	/* Learning phase, just populate the routers list */
179 	if(learning)
180 	{
181 		const u_char* pos;
182 		struct nd_opt_hdr* optptr;  /*netinet/icmp6.h*/
183 		struct nd_opt_prefix_info* option_prefix = NULL;
184 		struct nd_opt_mtu* option_mtu = NULL;
185 		char prefix[INET6_ADDRSTRLEN];
186 
187 		prefix_t* router_prefix=NULL;
188 		/* Retrieve the Router Advertisement to get the RA params. */
189 		struct nd_router_advert *router_advert = (struct nd_router_advert*) (packet+ETHERNET_SIZE+sizeof(struct ip6_hdr));
190 
191 		/* We have to search the prefix and mtu option among the others RA options: */
192 		pos = packet + ETHERNET_SIZE + IPV6_SIZE + sizeof(struct nd_router_advert);
193 		optptr = (struct nd_opt_hdr*) ( pos );
194 		while((optptr->nd_opt_type!=0)&&((u_char*)optptr < (packet+packet_len)))
195 		{
196 			switch (optptr->nd_opt_type) {
197 				case ND_OPT_PREFIX_INFORMATION:
198 					option_prefix = (struct nd_opt_prefix_info*) optptr;
199 					ipv6pre_ntoa(prefix, option_prefix->nd_opt_pi_prefix);
200 					break;
201 				case ND_OPT_MTU:
202 					option_mtu = (struct nd_opt_mtu*) optptr;
203 					break;
204 				default:
205 					break;
206 			}
207 			/* If all supported options were found skip remaining options: */
208 			if (option_prefix!=NULL && option_mtu!=NULL) {
209 				break;
210 			}
211 			/* Next option field*/
212 			pos += (optptr->nd_opt_len)*8;
213 			optptr = (struct nd_opt_hdr*) ( pos );
214 		}
215 
216 		if (!option_prefix) /*if there is no prefix information:*/
217 		    return 1;
218 
219 		if(router==NULL) /* router not seen before */
220 		{
221 			router_add(
222 				&routers, src_eth, &ipptr->ip6_src,
223 				router_advert->nd_ra_curhoplimit,
224 				router_advert->nd_ra_flags_reserved,
225 				ntohs(router_advert->nd_ra_router_lifetime),
226 				ntohl(router_advert->nd_ra_reachable),
227 				ntohl(router_advert->nd_ra_retransmit),
228 				option_mtu==NULL?0:ntohl(option_mtu->nd_opt_mtu_mtu),
229 				1 /* params are by default volatile (they may change).  */
230 			);
231 			router_add_prefix(
232 				routers, ipptr->ip6_src, *src_eth,
233 				option_prefix->nd_opt_pi_prefix,
234 				option_prefix->nd_opt_pi_prefix_len,
235 				option_prefix->nd_opt_pi_flags_reserved,
236 				ntohl(option_prefix->nd_opt_pi_valid_time),
237 				ntohl(option_prefix->nd_opt_pi_preferred_time)
238 			);
239 		}
240 		else /* router already learned */
241 		{
242 			/* Update router values: */
243 			router->param_curhoplimit     = router_advert->nd_ra_curhoplimit;
244 			router->param_flags_reserved  = router_advert->nd_ra_flags_reserved;
245 			router->param_router_lifetime = ntohs(router_advert->nd_ra_router_lifetime);
246 			router->param_reachable_timer = ntohl(router_advert->nd_ra_reachable);
247 			router->param_retrans_timer   = ntohl(router_advert->nd_ra_retransmit);
248 			if (option_mtu!=NULL) {
249 				router->param_mtu = ntohl(option_mtu->nd_opt_mtu_mtu);
250 			}
251 			router_prefix = router_get_prefix(routers, ipptr->ip6_src, *src_eth, option_prefix->nd_opt_pi_prefix, option_prefix->nd_opt_pi_prefix_len);
252 			if( router_prefix == NULL ) {
253 	                        /* If there is a new prefix advertised add it to the list of prefixes.*/
254 				router_add_prefix(
255 					routers, ipptr->ip6_src, *src_eth,
256 					option_prefix->nd_opt_pi_prefix,
257 					option_prefix->nd_opt_pi_prefix_len,
258 					option_prefix->nd_opt_pi_flags_reserved,
259 					ntohl(option_prefix->nd_opt_pi_valid_time),
260 					ntohl(option_prefix->nd_opt_pi_preferred_time)
261 				);
262 			} else {
263 				/* If the prefix is already in the list update values: */
264 				router_prefix->param_valid_time     = ntohl(option_prefix->nd_opt_pi_valid_time);
265 				router_prefix->param_preferred_time = ntohl(option_prefix->nd_opt_pi_preferred_time);
266 			}
267 		}
268 
269 		return 0;
270 	}
271 
272 	/* if the router is not known */
273 	if(router==NULL)
274 	{
275 		int found_mac = is_router_mac_in(routers, *src_eth);
276 		int found_lla = is_router_lla_in(routers, ipptr->ip6_src);
277 
278 		if( found_mac && found_lla)
279 		{
280 			/* valid MAC and IP, but not together */
281 			snprintf (buffer, NOTIFY_BUFFER_SIZE, "wrong couple IP/MAC %s %s in RA", (char*)ether_ntoa(src_eth), ip_address);
282 			notify(2, buffer, "wrong couple IP/MAC", src_eth, ip_address, NULL);
283 			ret = 2;
284 		}
285 		else if( found_mac && !found_lla)
286 		{
287 			/* wrong IP */
288 			snprintf (buffer, NOTIFY_BUFFER_SIZE, "wrong router ip %s %s", (char*)ether_ntoa(src_eth), ip_address);
289 			notify(2, buffer, "wrong router ip", src_eth, ip_address, NULL);
290 			ret = 2;
291 		}
292 		else if( !found_mac && found_lla)
293 		{
294 			/* wrong MAC */
295 			snprintf (buffer, NOTIFY_BUFFER_SIZE, "wrong router mac %s %s", (char*)ether_ntoa(src_eth), ip_address);
296 			notify(2, buffer, "wrong router mac", src_eth, ip_address, NULL);
297 			ret = 2;
298 		}
299 		else
300 		{
301 			/* wrong ipv6 router: both mac and lla are fantasist */
302 			snprintf (buffer, NOTIFY_BUFFER_SIZE, "wrong ipv6 router %s %s", (char*)ether_ntoa(src_eth), ip_address);
303 			notify(2, buffer, "wrong ipv6 router", src_eth, ip_address, NULL);
304 			ret = 2;
305 #ifdef _COUNTERMEASURES_
306                         cm_kill_illegitimate_router(src_eth, &ipptr->ip6_src);
307 #endif
308 		}
309 	}
310 	/* The router is valid, check options */
311 	else
312 	{
313 		const u_char* pos;
314 		struct nd_router_advert *ra;
315 		struct nd_opt_hdr* optptr;  /*netinet/icmp6.h*/
316 		unsigned int managed_flag, other_flag;
317 		char prefix[INET6_ADDRSTRLEN];
318 /* ADDED param spoofing detection */
319                 uint8_t curhoplimit, flags_reserved;
320 		uint16_t router_lifetime;
321 		uint32_t reachable_timer, retrans_timer;
322 		char param_mismatched_list[RA_PARAM_MISMATCHED_LIST_SIZE], param_mismatched[RA_PARAM_MISMATCHED_SIZE];
323 		int param_mismatch = 0;
324 /* END ADDED */
325 #ifdef _COUNTERMEASURES_
326 		int param_spoofing_detected = 0;
327 #endif
328 		/* Check RA parameters */
329 		pos = packet + ETHERNET_SIZE + IPV6_SIZE;
330 		ra = (struct nd_router_advert *)pos;
331 		managed_flag = (ra->nd_ra_flags_reserved)&ND_RA_FLAG_MANAGED;
332 		other_flag = (ra->nd_ra_flags_reserved)&ND_RA_FLAG_OTHER;
333 
334 		/* expecting
335 		 * M ==1 and O == 1
336 		 * M == 0 and O == 1
337 		 * M == 0 and 0 == 0
338 		 * if M == 1 and O == 0 there is a problem
339 		 * */
340 		if( managed_flag && !other_flag)
341 		{
342 			char ip_address[IP6_STR_SIZE];
343 			ipv6_ntoa(ip_address, ipptr->ip6_src);
344 			snprintf (buffer, NOTIFY_BUFFER_SIZE, "wrong RA flags: M=1 and O=0");
345 			notify(2, buffer, "wrong RA flags", (struct ether_addr*) (eptr->ether_shost), ip_address, NULL);
346 			ret = 2;
347 		}
348 
349 /* ADDED : param spoofing detection */
350 		/* Only perform checks if params are configured not to change: */
351 		if (router->params_volatile==0) {
352 			/* fetch RA params from RA */
353 			curhoplimit     = ra->nd_ra_curhoplimit;
354 			flags_reserved  = ra->nd_ra_flags_reserved;
355 			router_lifetime = ntohs(ra->nd_ra_router_lifetime);
356 			reachable_timer = ntohl(ra->nd_ra_reachable);
357 			retrans_timer   = ntohl(ra->nd_ra_retransmit);
358 			/* compare params to those stored in the router list
359 			   optional parameters are only checked if neither the learned nor the advertised value
360 			   is zero, because zero means unspecified. flags are always checked.
361 			*/
362 			memset(param_mismatched_list, 0, RA_PARAM_MISMATCHED_LIST_SIZE);
363 			if (curhoplimit!=0 && router->param_curhoplimit!=0 && curhoplimit != router->param_curhoplimit) {
364 				memset(param_mismatched, 0, RA_PARAM_MISMATCHED_SIZE);
365 				snprintf(param_mismatched, RA_PARAM_MISMATCHED_SIZE, "curhoplimit=%u;", curhoplimit);
366 				strncat(param_mismatched_list,param_mismatched,RA_PARAM_MISMATCHED_SIZE);
367 				param_mismatch++;
368 			}
369 			if (flags_reserved != router->param_flags_reserved) {
370 				memset(param_mismatched, 0, RA_PARAM_MISMATCHED_SIZE);
371 				snprintf(param_mismatched, RA_PARAM_MISMATCHED_SIZE, "flags=%u;", flags_reserved);
372 				strncat(param_mismatched_list,param_mismatched,RA_PARAM_MISMATCHED_SIZE);
373 				param_mismatch++;
374 			}
375 			if (router_lifetime!=0 && router->param_router_lifetime!=0 && router_lifetime != router->param_router_lifetime) {
376 				memset(param_mismatched, 0, RA_PARAM_MISMATCHED_SIZE);
377 				snprintf (param_mismatched, RA_PARAM_MISMATCHED_SIZE, "router_lifetime=%u;", router_lifetime);
378 				strncat(param_mismatched_list,param_mismatched,RA_PARAM_MISMATCHED_SIZE);
379 				param_mismatch++;
380 			}
381 			if (reachable_timer!=0 && router->param_reachable_timer!=0 && reachable_timer != router->param_reachable_timer) {
382 				memset(param_mismatched, 0, RA_PARAM_MISMATCHED_SIZE);
383 				snprintf (param_mismatched, RA_PARAM_MISMATCHED_SIZE, "reachable_timer=%u;", reachable_timer);
384 				strncat(param_mismatched_list,param_mismatched,RA_PARAM_MISMATCHED_SIZE);
385 				param_mismatch++;
386 			}
387 			if (retrans_timer!=0 && router->param_retrans_timer!=0 && retrans_timer != router->param_retrans_timer) {
388 				memset(param_mismatched, 0, RA_PARAM_MISMATCHED_SIZE);
389 				snprintf (param_mismatched, RA_PARAM_MISMATCHED_SIZE, "retrans_timer=%u;", retrans_timer);
390 				strncat(param_mismatched_list,param_mismatched,RA_PARAM_MISMATCHED_SIZE);
391 				param_mismatch++;
392 			}
393 			if (param_mismatch>0) { /* we might tune the level of reaction here */
394 				snprintf (buffer, NOTIFY_BUFFER_SIZE, "wrong RA params: %s", param_mismatched_list);
395 				notify(2, buffer, "wrong RA params", (struct ether_addr*) (eptr->ether_shost), ip_address, NULL);
396 #ifdef _COUNTERMEASURES_
397 				param_spoofing_detected = 1;
398 #endif
399 			}
400 		}
401 /* END ADDED */
402 
403 		/* Check RA options */
404 		/*We have to search the prefix and other options among the others RA options*/
405 		pos = packet + ETHERNET_SIZE + IPV6_SIZE + sizeof(struct nd_router_advert);
406 		optptr = (struct nd_opt_hdr*) ( pos );
407 		while((optptr->nd_opt_type!=0)&&((u_char*)optptr < (packet+packet_len))) {
408 			if(optptr->nd_opt_type ==  ND_OPT_PREFIX_INFORMATION) {
409 				struct nd_opt_prefix_info* option_prefix = (struct nd_opt_prefix_info*) optptr;
410 				uint8_t prefix_flags_reserved;
411 				uint32_t prefix_valid_time, prefix_preferred_time;
412 /* ADDED param spoofing detection: */
413 				prefix_t* router_prefix=NULL;
414 /* END ADDED */
415 
416 				prefix_flags_reserved = option_prefix->nd_opt_pi_flags_reserved;
417 				prefix_valid_time     = ntohl(option_prefix->nd_opt_pi_valid_time);
418 				prefix_preferred_time = ntohl(option_prefix->nd_opt_pi_preferred_time);
419 				ipv6pre_ntoa(prefix, option_prefix->nd_opt_pi_prefix);
420 				/* Check prefix */
421 				router_prefix = router_get_prefix(routers, ipptr->ip6_src, *src_eth, option_prefix->nd_opt_pi_prefix, option_prefix->nd_opt_pi_prefix_len);
422 				if (router_prefix==NULL) /* prefix not found*/
423 				{
424 					char ip_address[IP6_STR_SIZE];
425 					ipv6_ntoa(ip_address, ipptr->ip6_src);
426 					snprintf (buffer, NOTIFY_BUFFER_SIZE, "wrong prefix %s %s %s", prefix,(char*)ether_ntoa((struct ether_addr*) (eptr->ether_shost)), ip_address);
427 					notify(2, buffer, "wrong prefix", (struct ether_addr*) (eptr->ether_shost), ip_address, NULL);
428 					ret = 2;
429 #ifdef _COUNTERMEASURES_
430 					cm_kill_wrong_prefix(router, &ipptr->ip6_src, &option_prefix->nd_opt_pi_prefix, option_prefix->nd_opt_pi_prefix_len);
431 #endif
432 				}
433 				/* check the lifetimes  - RFC2462 */
434 				/* valid should always be > to preferred - RFC2462 */
435 				if (prefix_preferred_time > prefix_valid_time)
436 				{
437 					char ip_address[IP6_STR_SIZE];
438 					ipv6_ntoa(ip_address, ipptr->ip6_src);
439 					snprintf (buffer, NOTIFY_BUFFER_SIZE, "RA preferred lifetime %d longer than valid lifetime %d",prefix_valid_time, prefix_preferred_time );
440 					notify(2, buffer, "wrong RA prefix option lifetimes", (struct ether_addr*) (eptr->ether_shost), ip_address, NULL);
441 					ret = 2;
442 				}
443 				/* valid lifetime should always be more than 2 hours - RFC2462 */
444 				if (prefix_valid_time < 7200)
445 				{
446 					char ip_address[IP6_STR_SIZE];
447 					ipv6_ntoa(ip_address, ipptr->ip6_src);
448 					snprintf (buffer, NOTIFY_BUFFER_SIZE, "RA prefix option valid lifetime %d < 2 hours", prefix_valid_time );
449 					notify(2, buffer, "RA prefix option valid lifetime too short", (struct ether_addr*) (eptr->ether_shost), ip_address, NULL);
450 					ret = 2;
451 				}
452 /* ADDED : param spoofing detection */
453 				if (router_prefix != NULL && router->params_volatile==0) {
454 					/* Checking value against those learned. prefix params cannot be zero. all are checked. */
455 					memset(param_mismatched_list, 0, RA_PARAM_MISMATCHED_LIST_SIZE);
456 					if (prefix_flags_reserved != router_prefix->param_flags_reserved) {
457 						memset(param_mismatched, 0, RA_PARAM_MISMATCHED_SIZE);
458 						snprintf(param_mismatched, RA_PARAM_MISMATCHED_SIZE, "flags=%u;", prefix_flags_reserved);
459 						strncat(param_mismatched_list,param_mismatched,RA_PARAM_MISMATCHED_SIZE);
460 						param_mismatch++;
461 					}
462 					if (prefix_valid_time != router_prefix->param_valid_time) {
463 						memset(param_mismatched, 0, RA_PARAM_MISMATCHED_SIZE);
464 						snprintf (param_mismatched, RA_PARAM_MISMATCHED_SIZE, "valid_time=%u;", prefix_valid_time);
465 						strncat(param_mismatched_list,param_mismatched,RA_PARAM_MISMATCHED_SIZE);
466 						param_mismatch++;
467 					}
468 					if (prefix_preferred_time != router_prefix->param_preferred_time) {
469 						memset(param_mismatched, 0, RA_PARAM_MISMATCHED_SIZE);
470 						snprintf (param_mismatched, RA_PARAM_MISMATCHED_SIZE, "preferred_time=%u;", prefix_preferred_time);
471 						strncat(param_mismatched_list,param_mismatched,RA_PARAM_MISMATCHED_SIZE);
472 						param_mismatch++;
473 					}
474 					if (param_mismatch>0) {
475 						snprintf (buffer, NOTIFY_BUFFER_SIZE, "wrong RA prefix option params: %s", param_mismatched_list);
476 						notify(2, buffer, "wrong RA prefix option params", (struct ether_addr*) (eptr->ether_shost), ip_address, NULL);
477 #ifdef _COUNTERMEASURES_
478 						param_spoofing_detected = 1;
479 #endif
480 					}
481 				}
482 /* END ADDED */
483 			}
484 			/* Verify that the Source Link Option matches the Ethernet source addr of the packet */
485 			else if(optptr->nd_opt_type ==  ND_OPT_SOURCE_LINKADDR)
486 			{
487 				uint8_t *mac;
488 				mac = (uint8_t *)(pos+2);
489 
490 				if( (mac[0]!=eptr->ether_shost[0]) || (mac[1]!=eptr->ether_shost[1]) || (mac[2]!=eptr->ether_shost[2]) || (mac[3]!=eptr->ether_shost[3]) || (mac[4]!=eptr->ether_shost[4]) || (mac[5]!=eptr->ether_shost[5]) )
491 				{
492 					char  eth_opt[ETH_ADDRSTRLEN];
493 					struct ether_addr * adv_eth = NULL;
494 
495 					adv_eth = (struct ether_addr *) mac;
496 					strncpy(eth_opt,ether_ntoa(adv_eth), ETH_ADDRSTRLEN);
497 					snprintf (buffer, NOTIFY_BUFFER_SIZE, "source link address %s different from ethernet source %s", eth_opt, eth );
498 					notify(2, buffer, "wrong source link address option", (struct ether_addr*) (eptr->ether_shost), ip_address, NULL);
499 					ret = 2;
500 				}
501 			}
502 /* ADDED : param spoofing detection */
503 			/* Checking MTU option against the value learned. A value learned = 0 means option not learned. */
504 			else if(optptr->nd_opt_type ==  ND_OPT_MTU) {
505 				uint32_t mtu;
506 				struct nd_opt_mtu *option_mtu = (struct nd_opt_mtu*) optptr;
507 				mtu = ntohl(option_mtu->nd_opt_mtu_mtu);
508 				if (router != NULL && router->params_volatile==0 && router->param_mtu!=0 && mtu != router->param_mtu) {
509 					snprintf (buffer, NOTIFY_BUFFER_SIZE, "wrong RA mtu option: mtu=%u", mtu);
510 					notify(2, buffer, "wrong RA mtu option", (struct ether_addr*) (eptr->ether_shost), ip_address, NULL);
511 #ifdef _COUNTERMEASURES_
512 					param_spoofing_detected=1;
513 #endif
514 				}
515 /* END ADDED*/
516 			}
517 			/*Next option field*/
518 			pos += (optptr->nd_opt_len)*8;
519 			optptr = (struct nd_opt_hdr*) ( pos );
520 		} /* end options */
521 #ifdef _COUNTERMEASURES_
522 	if (param_spoofing_detected!=0) {
523 		/* Try to restore params in the network. */
524 		cm_propagate_router_params(router, &ipptr->ip6_src);
525 	}
526 #endif
527 	} /* end valid router*/
528 	return ret;
529 }
530