LCOV - code coverage report
Current view: top level - network - networkd-lldp-rx.c (source / functions) Hit Total Coverage
Test: main_coverage.info Lines: 6 108 5.6 %
Date: 2019-08-22 15:41:25 Functions: 4 8 50.0 %

          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           3 : 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          13 : 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           6 : int link_update_lldp(Link *link) {
     105             :         int r;
     106             : 
     107           6 :         assert(link);
     108             : 
     109           6 :         if (!link->lldp)
     110           6 :                 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