LCOV - code coverage report
Current view: top level - network - networkd-lldp-rx.c (source / functions) Hit Total Coverage
Test: systemd_full.info Lines: 6 108 5.6 %
Date: 2019-08-23 13:36:53 Functions: 4 8 50.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 13 122 10.7 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: LGPL-2.1+ */
       2                 :            : 
       3                 :            : #include <net/if.h>
       4                 :            : #include <net/if_arp.h>
       5                 :            : #include <unistd.h>
       6                 :            : 
       7                 :            : #include "fd-util.h"
       8                 :            : #include "fileio.h"
       9                 :            : #include "networkd-link.h"
      10                 :            : #include "networkd-lldp-rx.h"
      11                 :            : #include "networkd-lldp-tx.h"
      12                 :            : #include "networkd-network.h"
      13                 :            : #include "string-table.h"
      14                 :            : #include "string-util.h"
      15                 :            : #include "tmpfile-util.h"
      16                 :            : 
      17   [ -  +  -  +  :         12 : DEFINE_CONFIG_PARSE_ENUM(config_parse_lldp_mode, lldp_mode, LLDPMode, "Failed to parse LLDP= setting.");
          -  +  -  +  -  
                +  #  # ]
      18                 :            : 
      19                 :            : static const char* const lldp_mode_table[_LLDP_MODE_MAX] = {
      20                 :            :         [LLDP_MODE_NO] = "no",
      21                 :            :         [LLDP_MODE_YES] = "yes",
      22                 :            :         [LLDP_MODE_ROUTERS_ONLY] = "routers-only",
      23                 :            : };
      24                 :            : 
      25   [ +  +  +  +  :         52 : DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(lldp_mode, LLDPMode, LLDP_MODE_YES);
                   +  + ]
      26                 :            : 
      27                 :          0 : bool link_lldp_rx_enabled(Link *link) {
      28         [ #  # ]:          0 :         assert(link);
      29                 :            : 
      30         [ #  # ]:          0 :         if (link->flags & IFF_LOOPBACK)
      31                 :          0 :                 return false;
      32                 :            : 
      33         [ #  # ]:          0 :         if (link->iftype != ARPHRD_ETHER)
      34                 :          0 :                 return false;
      35                 :            : 
      36         [ #  # ]:          0 :         if (!link->network)
      37                 :          0 :                 return false;
      38                 :            : 
      39                 :            :         /* LLDP should be handled on bridge slaves as those have a direct
      40                 :            :          * connection to their peers not on the bridge master. Linux doesn't
      41                 :            :          * even (by default) forward lldp packets to the bridge master.*/
      42         [ #  # ]:          0 :         if (streq_ptr("bridge", link->kind))
      43                 :          0 :                 return false;
      44                 :            : 
      45                 :          0 :         return link->network->lldp_mode != LLDP_MODE_NO;
      46                 :            : }
      47                 :            : 
      48                 :          0 : static void lldp_handler(sd_lldp *lldp, sd_lldp_event event, sd_lldp_neighbor *n, void *userdata) {
      49                 :          0 :         Link *link = userdata;
      50                 :            :         int r;
      51                 :            : 
      52         [ #  # ]:          0 :         assert(link);
      53                 :            : 
      54                 :          0 :         (void) link_lldp_save(link);
      55                 :            : 
      56   [ #  #  #  # ]:          0 :         if (link_lldp_emit_enabled(link) && event == SD_LLDP_EVENT_ADDED) {
      57                 :            :                 /* If we received information about a new neighbor, restart the LLDP "fast" logic */
      58                 :            : 
      59   [ #  #  #  # ]:          0 :                 log_link_debug(link, "Received LLDP datagram from previously unknown neighbor, restarting 'fast' LLDP transmission.");
      60                 :            : 
      61                 :          0 :                 r = link_lldp_emit_start(link);
      62         [ #  # ]:          0 :                 if (r < 0)
      63   [ #  #  #  # ]:          0 :                         log_link_warning_errno(link, r, "Failed to restart LLDP transmission: %m");
      64                 :            :         }
      65                 :          0 : }
      66                 :            : 
      67                 :          0 : int link_lldp_rx_configure(Link *link) {
      68                 :            :         int r;
      69                 :            : 
      70                 :          0 :         r = sd_lldp_new(&link->lldp);
      71         [ #  # ]:          0 :         if (r < 0)
      72                 :          0 :                 return r;
      73                 :            : 
      74                 :          0 :         r = sd_lldp_set_ifindex(link->lldp, link->ifindex);
      75         [ #  # ]:          0 :         if (r < 0)
      76                 :          0 :                 return r;
      77                 :            : 
      78                 :          0 :         r = sd_lldp_match_capabilities(link->lldp,
      79         [ #  # ]:          0 :                                        link->network->lldp_mode == LLDP_MODE_ROUTERS_ONLY ?
      80                 :            :                                        SD_LLDP_SYSTEM_CAPABILITIES_ALL_ROUTERS :
      81                 :            :                                        SD_LLDP_SYSTEM_CAPABILITIES_ALL);
      82         [ #  # ]:          0 :         if (r < 0)
      83                 :          0 :                 return r;
      84                 :            : 
      85                 :          0 :         r = sd_lldp_set_filter_address(link->lldp, &link->mac);
      86         [ #  # ]:          0 :         if (r < 0)
      87                 :          0 :                 return r;
      88                 :            : 
      89                 :          0 :         r = sd_lldp_attach_event(link->lldp, NULL, 0);
      90         [ #  # ]:          0 :         if (r < 0)
      91                 :          0 :                 return r;
      92                 :            : 
      93                 :          0 :         r = sd_lldp_set_callback(link->lldp, lldp_handler, link);
      94         [ #  # ]:          0 :         if (r < 0)
      95                 :          0 :                 return r;
      96                 :            : 
      97                 :          0 :         r = link_update_lldp(link);
      98         [ #  # ]:          0 :         if (r < 0)
      99                 :          0 :                 return r;
     100                 :            : 
     101                 :          0 :         return 0;
     102                 :            : }
     103                 :            : 
     104                 :         28 : int link_update_lldp(Link *link) {
     105                 :            :         int r;
     106                 :            : 
     107         [ -  + ]:         28 :         assert(link);
     108                 :            : 
     109         [ +  - ]:         28 :         if (!link->lldp)
     110                 :         28 :                 return 0;
     111                 :            : 
     112         [ #  # ]:          0 :         if (link->flags & IFF_UP) {
     113                 :          0 :                 r = sd_lldp_start(link->lldp);
     114         [ #  # ]:          0 :                 if (r < 0)
     115   [ #  #  #  # ]:          0 :                         return log_link_warning_errno(link, r, "Failed to start LLDP: %m");
     116         [ #  # ]:          0 :                 if (r > 0)
     117   [ #  #  #  # ]:          0 :                         log_link_debug(link, "Started LLDP.");
     118                 :            :         } else {
     119                 :          0 :                 r = sd_lldp_stop(link->lldp);
     120         [ #  # ]:          0 :                 if (r < 0)
     121   [ #  #  #  # ]:          0 :                         return log_link_warning_errno(link, r, "Failed to stop LLDP: %m");
     122         [ #  # ]:          0 :                 if (r > 0)
     123   [ #  #  #  # ]:          0 :                         log_link_debug(link, "Stopped LLDP.");
     124                 :            :         }
     125                 :            : 
     126                 :          0 :         return r;
     127                 :            : }
     128                 :            : 
     129                 :          0 : int link_lldp_save(Link *link) {
     130                 :          0 :         _cleanup_free_ char *temp_path = NULL;
     131                 :          0 :         _cleanup_fclose_ FILE *f = NULL;
     132                 :          0 :         sd_lldp_neighbor **l = NULL;
     133                 :          0 :         int n = 0, r, i;
     134                 :            : 
     135         [ #  # ]:          0 :         assert(link);
     136         [ #  # ]:          0 :         assert(link->lldp_file);
     137                 :            : 
     138         [ #  # ]:          0 :         if (!link->lldp) {
     139                 :          0 :                 (void) unlink(link->lldp_file);
     140                 :          0 :                 return 0;
     141                 :            :         }
     142                 :            : 
     143                 :          0 :         r = sd_lldp_get_neighbors(link->lldp, &l);
     144         [ #  # ]:          0 :         if (r < 0)
     145                 :          0 :                 goto finish;
     146         [ #  # ]:          0 :         if (r == 0) {
     147                 :          0 :                 (void) unlink(link->lldp_file);
     148                 :          0 :                 goto finish;
     149                 :            :         }
     150                 :            : 
     151                 :          0 :         n = r;
     152                 :            : 
     153                 :          0 :         r = fopen_temporary(link->lldp_file, &f, &temp_path);
     154         [ #  # ]:          0 :         if (r < 0)
     155                 :          0 :                 goto finish;
     156                 :            : 
     157                 :          0 :         fchmod(fileno(f), 0644);
     158                 :            : 
     159         [ #  # ]:          0 :         for (i = 0; i < n; i++) {
     160                 :            :                 const void *p;
     161                 :            :                 le64_t u;
     162                 :            :                 size_t sz;
     163                 :            : 
     164                 :          0 :                 r = sd_lldp_neighbor_get_raw(l[i], &p, &sz);
     165         [ #  # ]:          0 :                 if (r < 0)
     166                 :          0 :                         goto finish;
     167                 :            : 
     168                 :          0 :                 u = htole64(sz);
     169                 :          0 :                 (void) fwrite(&u, 1, sizeof(u), f);
     170                 :          0 :                 (void) fwrite(p, 1, sz, f);
     171                 :            :         }
     172                 :            : 
     173                 :          0 :         r = fflush_and_check(f);
     174         [ #  # ]:          0 :         if (r < 0)
     175                 :          0 :                 goto finish;
     176                 :            : 
     177         [ #  # ]:          0 :         if (rename(temp_path, link->lldp_file) < 0) {
     178                 :          0 :                 r = -errno;
     179                 :          0 :                 goto finish;
     180                 :            :         }
     181                 :            : 
     182                 :          0 : finish:
     183         [ #  # ]:          0 :         if (r < 0) {
     184                 :          0 :                 (void) unlink(link->lldp_file);
     185         [ #  # ]:          0 :                 if (temp_path)
     186                 :          0 :                         (void) unlink(temp_path);
     187                 :            : 
     188   [ #  #  #  # ]:          0 :                 log_link_error_errno(link, r, "Failed to save LLDP data to %s: %m", link->lldp_file);
     189                 :            :         }
     190                 :            : 
     191         [ #  # ]:          0 :         if (l) {
     192         [ #  # ]:          0 :                 for (i = 0; i < n; i++)
     193                 :          0 :                         sd_lldp_neighbor_unref(l[i]);
     194                 :          0 :                 free(l);
     195                 :            :         }
     196                 :            : 
     197                 :          0 :         return r;
     198                 :            : }

Generated by: LCOV version 1.14