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