LCOV - code coverage report
Current view: top level - waltz/neigh - fd_neigh4_netlink.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 0 100 0.0 %
Date: 2025-03-20 12:08:36 Functions: 0 2 0.0 %

          Line data    Source code
       1             : #include "fd_neigh4_netlink.h"
       2             : 
       3             : #include <errno.h>
       4             : #include <sys/socket.h> /* AF_INET */
       5             : #include <linux/netlink.h> /* struct nlmsghdr */
       6             : #include <linux/rtnetlink.h> /* RTM_NEWNEIGH */
       7             : #include <linux/neighbour.h> /* struct ndmsg */
       8             : #include "../ip/fd_netlink1.h"
       9             : #include "fd_neigh4_map.h"
      10             : 
      11             : int
      12             : fd_neigh4_netlink_request_dump( fd_netlink_t * netlink,
      13           0 :                                 uint           if_idx ) {
      14             : 
      15           0 :   uint seq = netlink->seq++;
      16             : 
      17           0 :   struct {
      18           0 :     struct nlmsghdr nlh;
      19           0 :     struct ndmsg    ndm;
      20           0 :   } request;
      21           0 :   request.nlh = (struct nlmsghdr) {
      22           0 :     .nlmsg_type  = RTM_GETNEIGH,
      23           0 :     .nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP,
      24           0 :     .nlmsg_len   = sizeof(request),
      25           0 :     .nlmsg_seq   = seq
      26           0 :   };
      27           0 :   request.ndm = (struct ndmsg) {
      28           0 :     .ndm_family  = AF_INET,
      29           0 :     .ndm_ifindex = (int)if_idx
      30           0 :   };
      31             : 
      32           0 :   long send_res = send( netlink->fd, &request, sizeof(request), 0 );
      33           0 :   if( FD_UNLIKELY( send_res<0 ) ) {
      34           0 :     FD_LOG_WARNING(( "netlink send(RTM_GETNEIGH,NLM_F_REQUEST|NLM_F_DUMP) failed (%d-%s)", errno, fd_io_strerror( errno ) ));
      35           0 :     return errno;
      36           0 :   }
      37           0 :   if( FD_UNLIKELY( send_res!=sizeof(request ) ) ) {
      38           0 :     FD_LOG_WARNING(( "netlink send(RTM_GETNEIGH,NLM_F_REQUEST|NLM_F_DUMP) failed (short write)" ));
      39           0 :     return EPIPE;
      40           0 :   }
      41             : 
      42           0 :   return 0;
      43           0 : }
      44             : 
      45             : void
      46             : fd_neigh4_netlink_ingest_message( fd_neigh4_hmap_t *      map,
      47             :                                   struct nlmsghdr const * msg_hdr,
      48           0 :                                   uint                    if_idx ) {
      49           0 :   if( FD_UNLIKELY( msg_hdr->nlmsg_type!=RTM_NEWNEIGH && msg_hdr->nlmsg_type!=RTM_DELNEIGH ) ) {
      50           0 :     FD_LOG_WARNING(( "unexpected nlmsg_type %u", msg_hdr->nlmsg_type ));
      51           0 :     return;
      52           0 :   }
      53             : 
      54           0 :   struct ndmsg const *  ndm    = NLMSG_DATA( msg_hdr );
      55           0 :   struct rtattr const * rat    = RTM_RTA( ndm );
      56           0 :   long                  rat_sz = (long)(int)RTM_PAYLOAD( msg_hdr );
      57             : 
      58           0 :   if( FD_UNLIKELY( ndm->ndm_family!=AF_INET       ) ) return;
      59           0 :   if( FD_UNLIKELY( (uint)ndm->ndm_ifindex!=if_idx ) ) return;
      60             : 
      61           0 :   uint ip4_dst = 0U;
      62           0 :   union {
      63           0 :     uchar u6[6];
      64           0 :     ulong ul;
      65           0 :   } mac_addr = {0};
      66             : 
      67           0 :   for( ; RTA_OK( rat, rat_sz ); rat=RTA_NEXT( rat, rat_sz ) ) {
      68             : 
      69           0 :     void * rta    = RTA_DATA( rat );
      70           0 :     ulong  rta_sz = RTA_PAYLOAD( rat );
      71             : 
      72           0 :     switch( rat->rta_type ) {
      73             : 
      74           0 :     case NDA_DST:
      75           0 :       if( FD_UNLIKELY( rta_sz!=4UL ) ) {
      76           0 :         FD_LOG_WARNING(( "unexpected NDA_DST size %lu", rta_sz ));
      77           0 :         return;
      78           0 :       }
      79           0 :       ip4_dst = FD_LOAD( uint, rta ); /* big endian */
      80           0 :       break;
      81             : 
      82           0 :     case NDA_LLADDR:
      83           0 :       if( FD_UNLIKELY( rta_sz!=6UL ) ) {
      84           0 :         FD_LOG_WARNING(( "unexpected NDA_LLADDR size %lu (is this an Ethernet interface?)", rta_sz ));
      85           0 :         return;
      86           0 :       }
      87           0 :       memcpy( mac_addr.u6, rta, 6 );
      88           0 :       break;
      89             : 
      90           0 :     default:
      91           0 :       break; /* ignore */
      92           0 :     }
      93             : 
      94           0 :   }
      95             : 
      96           0 :   if( FD_UNLIKELY( !mac_addr.ul || !ip4_dst ) ) {
      97           0 :     FD_LOG_DEBUG(( "Ignoring neighbor table update with missing or invalid L2 or L3 address" ));
      98           0 :     return;
      99           0 :   }
     100             : 
     101             :   /* Determine if we should remove or insert/update entry */
     102             : 
     103           0 :   int remove = 0;
     104           0 :   switch( ndm->ndm_state ) {
     105           0 :   case NUD_REACHABLE:
     106           0 :   case NUD_STALE:
     107           0 :   case NUD_DELAY:
     108           0 :   case NUD_PROBE:
     109           0 :   case NUD_PERMANENT:
     110           0 :     remove = 0;
     111           0 :     break;
     112           0 :   default:
     113           0 :     remove = 1;
     114           0 :     break;
     115           0 :   }
     116           0 :   if( msg_hdr->nlmsg_type==RTM_DELNEIGH ) {
     117           0 :     remove = 1;
     118           0 :   }
     119             : 
     120             :   /* Perform update */
     121             : 
     122           0 :   if( remove ) {
     123             : 
     124           0 :     fd_neigh4_hmap_remove( map, &ip4_dst, NULL, FD_MAP_FLAG_BLOCKING );
     125             : 
     126           0 :   } else {
     127             : 
     128           0 :     fd_neigh4_hmap_query_t query[1];
     129           0 :     int prepare_res = fd_neigh4_hmap_prepare( map, &ip4_dst, NULL, query, FD_MAP_FLAG_BLOCKING );
     130           0 :     if( FD_UNLIKELY( prepare_res!=FD_MAP_SUCCESS ) ) {
     131           0 :       FD_LOG_WARNING(( "Failed to update neighbor table" ));
     132           0 :       return;
     133           0 :     }
     134             : 
     135           0 :     fd_neigh4_entry_t * ele = fd_neigh4_hmap_query_ele( query );
     136             : 
     137           0 :     ele->state    = FD_NEIGH4_STATE_ACTIVE;
     138           0 :     ele->ip4_addr = ip4_dst;
     139           0 :     memcpy( ele->mac_addr, mac_addr.u6, 6 );
     140             : 
     141           0 :     fd_neigh4_hmap_publish( query );
     142             : 
     143           0 :   }
     144             : 
     145           0 : }

Generated by: LCOV version 1.14