4848#define TRACE_GROUP "icmp"
4949
5050static buffer_t * icmpv6_echo_request_handler (struct buffer * buf );
51- static buffer_t * icmpv6_na_handler (struct buffer * buf );
5251
5352/* Check to see if a message is recognisable ICMPv6, and if so, fill in code/type */
5453/* This used ONLY for the e.1 + e.2 tests in RFC 4443, to try to avoid ICMPv6 error loops */
@@ -486,7 +485,6 @@ static buffer_t *icmpv6_ns_handler(buffer_t *buf)
486485 * interface, which we should only do in the whiteboard case.
487486 */
488487 if (addr_interface_address_compare (cur , target ) != 0 ) {
489- int8_t mesh_id = -1 ;
490488 //tr_debug("Received NS for proxy %s", trace_ipv6(target));
491489
492490 proxy = true;
@@ -495,7 +493,7 @@ static buffer_t *icmpv6_ns_handler(buffer_t *buf)
495493 goto drop ;
496494 }
497495
498- if (!nd_proxy_enabled_for_downstream (cur -> id ) || !nd_proxy_target_address_validation (cur -> id , target , & mesh_id )) {
496+ if (!nd_proxy_enabled_for_downstream (cur -> id ) || !nd_proxy_target_address_validation (cur -> id , target )) {
499497 goto drop ;
500498 }
501499 }
@@ -922,6 +920,80 @@ static buffer_t *icmpv6_redirect_handler(buffer_t *buf, protocol_interface_info_
922920 tr_warn ("Redirect drop" );
923921 return buffer_free (buf );
924922}
923+
924+ static buffer_t * icmpv6_na_handler (buffer_t * buf )
925+ {
926+ protocol_interface_info_entry_t * cur ;
927+ uint8_t * dptr = buffer_data_pointer (buf );
928+ uint8_t flags ;
929+ const uint8_t * target ;
930+ const uint8_t * tllao ;
931+ if_address_entry_t * addr_entry ;
932+ ipv6_neighbour_t * neighbour_entry ;
933+
934+ //"Parse NA at IPv6\n");
935+
936+ if (buf -> options .code != 0 || buf -> options .hop_limit != 255 ) {
937+ goto drop ;
938+ }
939+
940+ if (!icmpv6_options_well_formed_in_buffer (buf , 20 )) {
941+ goto drop ;
942+ }
943+
944+ // Skip the 4 reserved bytes
945+ flags = * dptr ;
946+ dptr += 4 ;
947+
948+ // Note the target IPv6 address
949+ target = dptr ;
950+
951+ if (addr_is_ipv6_multicast (target )) {
952+ goto drop ;
953+ }
954+
955+ /* Solicited flag must be clear if sent to a multicast address */
956+ if (addr_is_ipv6_multicast (buf -> dst_sa .address ) && (flags & NA_S )) {
957+ goto drop ;
958+ }
959+
960+ cur = buf -> interface ;
961+
962+ /* RFC 4862 5.4.4 DAD checks */
963+ addr_entry = addr_get_entry (cur , target );
964+ if (addr_entry ) {
965+ if (addr_entry -> tentative ) {
966+ tr_debug ("Received NA for our tentative address" );
967+ addr_duplicate_detected (cur , target );
968+ } else {
969+ tr_debug ("NA received for our own address: %s" , trace_ipv6 (target ));
970+ }
971+ goto drop ;
972+ }
973+
974+ if (cur -> ipv6_neighbour_cache .recv_na_aro ) {
975+ const uint8_t * aro = icmpv6_find_option_in_buffer (buf , 20 , ICMPV6_OPT_ADDR_REGISTRATION , 2 );
976+ if (aro ) {
977+ icmpv6_na_aro_handler (cur , aro , buf -> dst_sa .address );
978+ }
979+ }
980+
981+ /* No need to create a neighbour cache entry if one doesn't already exist */
982+ neighbour_entry = ipv6_neighbour_lookup (& cur -> ipv6_neighbour_cache , target );
983+ if (!neighbour_entry ) {
984+ goto drop ;
985+ }
986+
987+ tllao = icmpv6_find_option_in_buffer (buf , 20 , ICMPV6_OPT_TGT_LL_ADDR , 0 );
988+ if (!tllao || !cur -> if_llao_parse (cur , tllao , & buf -> dst_sa )) {
989+ buf -> dst_sa .addr_type = ADDR_NONE ;
990+ }
991+
992+ ipv6_neighbour_update_from_na (& cur -> ipv6_neighbour_cache , neighbour_entry , flags , buf -> dst_sa .addr_type , buf -> dst_sa .address );
993+
994+ drop :
995+ return buffer_free (buf );
996+ }
925997#endif // HAVE_IPV6_ND
926998
927999buffer_t * icmpv6_up (buffer_t * buf )
@@ -994,7 +1066,7 @@ buffer_t *icmpv6_up(buffer_t *buf)
9941066
9951067 case ICMPV6_TYPE_INFO_ECHO_REPLY :
9961068 ipv6_neighbour_reachability_confirmation (buf -> src_sa .address , buf -> interface -> id );
997- /* no break */
1069+ /* fall through */
9981070
9991071 case ICMPV6_TYPE_ERROR_DESTINATION_UNREACH :
10001072#ifdef HAVE_RPL_ROOT
@@ -1499,79 +1571,6 @@ buffer_t *icmpv6_build_na(protocol_interface_info_entry_t *cur, bool solicited,
14991571 return (buf );
15001572}
15011573
1502- static buffer_t * icmpv6_na_handler (buffer_t * buf )
1503- {
1504- protocol_interface_info_entry_t * cur ;
1505- uint8_t * dptr = buffer_data_pointer (buf );
1506- uint8_t flags ;
1507- const uint8_t * target ;
1508- const uint8_t * tllao ;
1509- if_address_entry_t * addr_entry ;
1510- ipv6_neighbour_t * neighbour_entry ;
1511-
1512- //"Parse NA at IPv6\n");
1513-
1514- if (buf -> options .code != 0 || buf -> options .hop_limit != 255 ) {
1515- goto drop ;
1516- }
1517-
1518- if (!icmpv6_options_well_formed_in_buffer (buf , 20 )) {
1519- goto drop ;
1520- }
1521-
1522- // Skip the 4 reserved bytes
1523- flags = * dptr ;
1524- dptr += 4 ;
1525-
1526- // Note the target IPv6 address
1527- target = dptr ;
1528-
1529- if (addr_is_ipv6_multicast (target )) {
1530- goto drop ;
1531- }
1532-
1533- /* Solicited flag must be clear if sent to a multicast address */
1534- if (addr_is_ipv6_multicast (buf -> dst_sa .address ) && (flags & NA_S )) {
1535- goto drop ;
1536- }
1537-
1538- cur = buf -> interface ;
1539-
1540- /* RFC 4862 5.4.4 DAD checks */
1541- addr_entry = addr_get_entry (cur , target );
1542- if (addr_entry ) {
1543- if (addr_entry -> tentative ) {
1544- tr_debug ("Received NA for our tentative address" );
1545- addr_duplicate_detected (cur , target );
1546- } else {
1547- tr_debug ("NA received for our own address: %s" , trace_ipv6 (target ));
1548- }
1549- goto drop ;
1550- }
1551-
1552- if (cur -> ipv6_neighbour_cache .recv_na_aro ) {
1553- const uint8_t * aro = icmpv6_find_option_in_buffer (buf , 20 , ICMPV6_OPT_ADDR_REGISTRATION , 2 );
1554- if (aro ) {
1555- icmpv6_na_aro_handler (cur , aro , buf -> dst_sa .address );
1556- }
1557- }
1558-
1559- /* No need to create a neighbour cache entry if one doesn't already exist */
1560- neighbour_entry = ipv6_neighbour_lookup (& cur -> ipv6_neighbour_cache , target );
1561- if (!neighbour_entry ) {
1562- goto drop ;
1563- }
1564-
1565- tllao = icmpv6_find_option_in_buffer (buf , 20 , ICMPV6_OPT_TGT_LL_ADDR , 0 );
1566- if (!tllao || !cur -> if_llao_parse (cur , tllao , & buf -> dst_sa )) {
1567- buf -> dst_sa .addr_type = ADDR_NONE ;
1568- }
1569-
1570- ipv6_neighbour_update_from_na (& cur -> ipv6_neighbour_cache , neighbour_entry , flags , buf -> dst_sa .addr_type , buf -> dst_sa .address );
1571-
1572- drop :
1573- return buffer_free (buf );
1574- }
15751574#endif // HAVE_IPV6_ND
15761575
15771576#ifdef HAVE_IPV6_ND
0 commit comments