LCOV - code coverage report
Current view: top level - network - networkd-fdb.c (source / functions) Hit Total Coverage
Test: systemd test coverage Lines: 0 110 0.0 %
Date: 2015-07-29 18:47:03 Functions: 0 6 0.0 %

          Line data    Source code
       1             : /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
       2             : 
       3             : /***
       4             :   This file is part of systemd.
       5             : 
       6             :   Copyright (C) 2014 Intel Corporation. All rights reserved.
       7             : 
       8             :   systemd is free software; you can redistribute it and/or modify it
       9             :   under the terms of the GNU Lesser General Public License as published by
      10             :   the Free Software Foundation; either version 2.1 of the License, or
      11             :   (at your option) any later version.
      12             : 
      13             :   systemd is distributed in the hope that it will be useful, but
      14             :   WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
      16             :   Lesser General Public License for more details.
      17             : 
      18             :   You should have received a copy of the GNU Lesser General Public License
      19             :   along with systemd; If not, see <http://www.gnu.org/licenses/>.
      20             : ***/
      21             : 
      22             : #include <net/if.h>
      23             : #include <net/ethernet.h>
      24             : 
      25             : #include "networkd.h"
      26             : #include "networkd-link.h"
      27             : #include "conf-parser.h"
      28             : #include "util.h"
      29             : 
      30             : /* create a new FDB entry or get an existing one. */
      31           0 : int fdb_entry_new_static(Network *const network,
      32             :                          const unsigned section,
      33             :                          FdbEntry **ret) {
      34           0 :         _cleanup_fdbentry_free_ FdbEntry *fdb_entry = NULL;
      35           0 :         struct ether_addr *mac_addr = NULL;
      36             : 
      37           0 :         assert(network);
      38             : 
      39             :         /* search entry in hashmap first. */
      40           0 :         if(section) {
      41           0 :                 fdb_entry = hashmap_get(network->fdb_entries_by_section, UINT_TO_PTR(section));
      42           0 :                 if (fdb_entry) {
      43           0 :                         *ret = fdb_entry;
      44           0 :                         fdb_entry = NULL;
      45             : 
      46           0 :                         return 0;
      47             :                 }
      48             :         }
      49             : 
      50             :         /* allocate space for MAC address. */
      51           0 :         mac_addr = new0(struct ether_addr, 1);
      52           0 :         if (!mac_addr)
      53           0 :                 return -ENOMEM;
      54             : 
      55             :         /* allocate space for and FDB entry. */
      56           0 :         fdb_entry = new0(FdbEntry, 1);
      57             : 
      58           0 :         if (!fdb_entry) {
      59             :                 /* free previously allocated space for mac_addr. */
      60           0 :                 free(mac_addr);
      61           0 :                 return -ENOMEM;
      62             :         }
      63             : 
      64             :         /* init FDB structure. */
      65           0 :         fdb_entry->network = network;
      66           0 :         fdb_entry->mac_addr = mac_addr;
      67             : 
      68           0 :         LIST_PREPEND(static_fdb_entries, network->static_fdb_entries, fdb_entry);
      69             : 
      70           0 :         if (section) {
      71           0 :                 fdb_entry->section = section;
      72           0 :                 hashmap_put(network->fdb_entries_by_section,
      73           0 :                             UINT_TO_PTR(fdb_entry->section), fdb_entry);
      74             :         }
      75             : 
      76             :         /* return allocated FDB structure. */
      77           0 :         *ret = fdb_entry;
      78           0 :         fdb_entry = NULL;
      79             : 
      80           0 :         return 0;
      81             : }
      82             : 
      83           0 : static int set_fdb_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
      84           0 :         Link *link = userdata;
      85             :         int r;
      86             : 
      87           0 :         assert(link);
      88             : 
      89           0 :         r = sd_netlink_message_get_errno(m);
      90           0 :         if (r < 0 && r != -EEXIST)
      91           0 :                 log_link_error_errno(link, r, "Could not add FDB entry: %m");
      92             : 
      93           0 :         return 1;
      94             : }
      95             : 
      96             : /* send a request to the kernel to add a FDB entry in its static MAC table. */
      97           0 : int fdb_entry_configure(Link *const link, FdbEntry *const fdb_entry) {
      98           0 :         _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL;
      99             :         sd_netlink *rtnl;
     100             :         int r;
     101             : 
     102           0 :         assert(link);
     103           0 :         assert(link->manager);
     104           0 :         assert(fdb_entry);
     105             : 
     106           0 :         rtnl = link->manager->rtnl;
     107             : 
     108             :         /* create new RTM message */
     109           0 :         r = sd_rtnl_message_new_neigh(rtnl, &req, RTM_NEWNEIGH, link->ifindex, PF_BRIDGE);
     110           0 :         if (r < 0)
     111           0 :                 return rtnl_log_create_error(r);
     112             : 
     113             :         /* only NTF_SELF flag supported. */
     114           0 :         r = sd_rtnl_message_neigh_set_flags(req, NTF_SELF);
     115           0 :         if (r < 0)
     116           0 :                 return rtnl_log_create_error(r);
     117             : 
     118             :         /* only NUD_PERMANENT state supported. */
     119           0 :         r = sd_rtnl_message_neigh_set_state(req, NUD_NOARP | NUD_PERMANENT);
     120           0 :         if (r < 0)
     121           0 :                 return rtnl_log_create_error(r);
     122             : 
     123           0 :         r = sd_netlink_message_append_ether_addr(req, NDA_LLADDR, fdb_entry->mac_addr);
     124           0 :         if (r < 0)
     125           0 :                 return rtnl_log_create_error(r);
     126             : 
     127             :         /* VLAN Id is optional. We'll add VLAN Id only if it's specified. */
     128           0 :         if (0 != fdb_entry->vlan_id) {
     129           0 :                 r = sd_netlink_message_append_u16(req, NDA_VLAN, fdb_entry->vlan_id);
     130           0 :                 if (r < 0)
     131           0 :                         return rtnl_log_create_error(r);
     132             :         }
     133             : 
     134             :         /* send message to the kernel to update its internal static MAC table. */
     135           0 :         r = sd_netlink_call_async(rtnl, req, set_fdb_handler, link, 0, NULL);
     136           0 :         if (r < 0)
     137           0 :                 return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
     138             : 
     139           0 :         return 0;
     140             : }
     141             : 
     142             : /* remove and FDB entry. */
     143           0 : void fdb_entry_free(FdbEntry *fdb_entry) {
     144           0 :         if(!fdb_entry)
     145           0 :                 return;
     146             : 
     147           0 :         if(fdb_entry->network) {
     148           0 :                 LIST_REMOVE(static_fdb_entries, fdb_entry->network->static_fdb_entries,
     149             :                             fdb_entry);
     150             : 
     151           0 :                 if (fdb_entry->section)
     152           0 :                         hashmap_remove(fdb_entry->network->fdb_entries_by_section,
     153           0 :                                        UINT_TO_PTR(fdb_entry->section));
     154             :         }
     155             : 
     156           0 :         free(fdb_entry->mac_addr);
     157             : 
     158           0 :         free(fdb_entry);
     159             : }
     160             : 
     161             : /* parse the HW address from config files. */
     162           0 : int config_parse_fdb_hwaddr(
     163             :                 const char *unit,
     164             :                 const char *filename,
     165             :                 unsigned line,
     166             :                 const char *section,
     167             :                 unsigned section_line,
     168             :                 const char *lvalue,
     169             :                 int ltype,
     170             :                 const char *rvalue,
     171             :                 void *data,
     172             :                 void *userdata) {
     173             : 
     174           0 :         Network *network = userdata;
     175           0 :         _cleanup_fdbentry_free_ FdbEntry *fdb_entry = NULL;
     176             :         int r;
     177             : 
     178           0 :         assert(filename);
     179           0 :         assert(section);
     180           0 :         assert(lvalue);
     181           0 :         assert(rvalue);
     182           0 :         assert(data);
     183             : 
     184           0 :         r = fdb_entry_new_static(network, section_line, &fdb_entry);
     185           0 :         if (r < 0)
     186           0 :                 return log_oom();
     187             : 
     188             :         /* read in the MAC address for the FDB table. */
     189           0 :         r = sscanf(rvalue, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
     190           0 :                    &fdb_entry->mac_addr->ether_addr_octet[0],
     191           0 :                    &fdb_entry->mac_addr->ether_addr_octet[1],
     192           0 :                    &fdb_entry->mac_addr->ether_addr_octet[2],
     193           0 :                    &fdb_entry->mac_addr->ether_addr_octet[3],
     194           0 :                    &fdb_entry->mac_addr->ether_addr_octet[4],
     195           0 :                    &fdb_entry->mac_addr->ether_addr_octet[5]);
     196             : 
     197           0 :         if (ETHER_ADDR_LEN != r) {
     198           0 :                 log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Not a valid MAC address, ignoring assignment: %s", rvalue);
     199           0 :                 return 0;
     200             :         }
     201             : 
     202           0 :         fdb_entry = NULL;
     203             : 
     204           0 :         return 0;
     205             : }
     206             : 
     207             : /* parse the VLAN Id from config files. */
     208           0 : int config_parse_fdb_vlan_id(
     209             :                 const char *unit,
     210             :                 const char *filename,
     211             :                 unsigned line,
     212             :                 const char *section,
     213             :                 unsigned section_line,
     214             :                 const char *lvalue,
     215             :                 int ltype,
     216             :                 const char *rvalue,
     217             :                 void *data,
     218             :                 void *userdata) {
     219             : 
     220           0 :         Network *network = userdata;
     221           0 :         _cleanup_fdbentry_free_ FdbEntry *fdb_entry = NULL;
     222             :         int r;
     223             : 
     224           0 :         assert(filename);
     225           0 :         assert(section);
     226           0 :         assert(lvalue);
     227           0 :         assert(rvalue);
     228           0 :         assert(data);
     229             : 
     230           0 :         r = fdb_entry_new_static(network, section_line, &fdb_entry);
     231           0 :         if (r < 0)
     232           0 :                 return log_oom();
     233             : 
     234           0 :         r = config_parse_unsigned(unit, filename, line, section,
     235             :                                   section_line, lvalue, ltype,
     236           0 :                                   rvalue, &fdb_entry->vlan_id, userdata);
     237           0 :         if (r < 0)
     238           0 :                 return r;
     239             : 
     240           0 :         fdb_entry = NULL;
     241             : 
     242           0 :         return 0;
     243             : }

Generated by: LCOV version 1.11