networkd-bridge.c revision bf1bc6701574f5e935fafc3163659372abdcde63
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering/***
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering This file is part of systemd.
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering Copyright 2013 Tom Gundersen <teg@jklm.no>
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering systemd is free software; you can redistribute it and/or modify it
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering under the terms of the GNU Lesser General Public License as published by
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering (at your option) any later version.
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering systemd is distributed in the hope that it will be useful, but
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering Lesser General Public License for more details.
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering You should have received a copy of the GNU Lesser General Public License
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering***/
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering#include "networkd.h"
96aad8d15a324d0e956a4e5653a11a67b209b41aLennart Poettering#include "net-util.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "path-util.h"
4ad7f2761da661853dcc29d542efb4727abb1101Nick Owens#include "conf-files.h"
39d8db043b599a7382f94bfc904d5e108af438bdLennart Poettering#include "conf-parser.h"
51323288fc628a5cac50914df915545d685b793eLennart Poettering#include "list.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
ad867662936a4c7ab2c7116d804c272338801231Lennart Poetteringvoid bridge_free(Bridge *bridge) {
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering bridge_join_callback *callback;
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (!bridge)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return;
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering while ((callback = bridge->callbacks)) {
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering LIST_REMOVE(callbacks, bridge->callbacks, callback);
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering free(callback);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering if (bridge->name)
703e4f5e39c019da8c002ba10bd450ce378c0e91Lennart Poettering hashmap_remove(bridge->manager->bridges, bridge->name);
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering free(bridge->filename);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering free(bridge->description);
309e9d86f0e7f9c5f0a2a09227bdfdb3174d4436Lennart Poettering free(bridge->name);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering free(bridge);
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering}
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poetteringint bridge_get(Manager *manager, const char *name, Bridge **ret) {
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering Bridge *bridge;
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering
818f766b12e025683cf4fed12b3da2a025bb0b31Lennart Poettering assert(manager);
818f766b12e025683cf4fed12b3da2a025bb0b31Lennart Poettering assert(name);
818f766b12e025683cf4fed12b3da2a025bb0b31Lennart Poettering assert(ret);
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering if (manager_should_reload(manager))
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering manager_load_config(manager);
818f766b12e025683cf4fed12b3da2a025bb0b31Lennart Poettering
818f766b12e025683cf4fed12b3da2a025bb0b31Lennart Poettering bridge = hashmap_get(manager->bridges, name);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (!bridge) {
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering *ret = NULL;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return -ENOENT;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering *ret = bridge;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return 0;
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering}
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poetteringstatic int bridge_enter_failed(Bridge *bridge) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering bridge->state = BRIDGE_STATE_FAILED;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return 0;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
63c372cb9df3bee01e3bf8cd7f96f336bddda846Lennart Poetteringstatic int bridge_join_ready(Bridge *bridge, Link* link, sd_rtnl_message_handler_t callback) {
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *req = NULL;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering int r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering assert(bridge);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(bridge->state == BRIDGE_STATE_READY);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(link);
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering assert(callback);
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering r = sd_rtnl_message_link_new(RTM_SETLINK, link->ifindex, &req);
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering if (r < 0) {
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering log_error("Could not allocate RTM_SETLINK message: %s",
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering strerror(-r));
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering r = sd_rtnl_message_append_u32(req, IFLA_MASTER, bridge->link->ifindex);
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering if (r < 0) {
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering log_error("Could not append IFLA_MASTER attribute: %s",
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering strerror(-r));
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering return r;
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering }
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering r = sd_rtnl_call_async(bridge->manager->rtnl, req, callback, link, 0, NULL);
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering if (r < 0) {
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering log_error("Could not send rtnetlink message: %s", strerror(-r));
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering return r;
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering }
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering return 0;
0dd25fb9f005d8ab7ac4bc10a609d00569f8c56aLennart Poettering}
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poetteringstatic int bridge_enter_ready(Bridge *bridge) {
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering bridge_join_callback *callback;
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering bridge->state = BRIDGE_STATE_READY;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
0dd25fb9f005d8ab7ac4bc10a609d00569f8c56aLennart Poettering log_info("Bridge '%s' ready", bridge->name);
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering LIST_FOREACH(callbacks, callback, bridge->callbacks) {
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering /* join the links that were attempted to be joined befor the
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering * link was ready */
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering bridge_join_ready(bridge, callback->link, callback->callback);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering }
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering return 0;
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering}
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poetteringstatic int bridge_create_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering Bridge *bridge = userdata;
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering int r;
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering assert(bridge->state == BRIDGE_STATE_CREATING);
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering r = sd_rtnl_message_get_errno(m);
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering if (r < 0) {
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering log_warning("Bridge '%s' failed: %s", bridge->name, strerror(-r));
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering bridge_enter_failed(bridge);
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering
51323288fc628a5cac50914df915545d685b793eLennart Poettering return 1;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (bridge->link)
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering bridge_enter_ready(bridge);
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering bridge->state = BRIDGE_STATE_CREATED;
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return 1;
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering}
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering
703e4f5e39c019da8c002ba10bd450ce378c0e91Lennart Poetteringstatic int bridge_create(Bridge *bridge) {
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *req = NULL;
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering int r;
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering assert(bridge);
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering assert(bridge->state == _BRIDGE_STATE_INVALID);
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering assert(bridge->name);
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering assert(bridge->manager);
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering assert(bridge->manager->rtnl);
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering r = sd_rtnl_message_link_new(RTM_NEWLINK, 0, &req);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0) {
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering log_error("Could not allocate RTM_NEWLINK message: %s",
51323288fc628a5cac50914df915545d685b793eLennart Poettering strerror(-r));
51323288fc628a5cac50914df915545d685b793eLennart Poettering return r;
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering }
3339cb71d44c5198f9546f113674f06dc7b01a6fLennart Poettering
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering r = sd_rtnl_message_append_string(req, IFLA_IFNAME, bridge->name);
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering if (r < 0) {
3339cb71d44c5198f9546f113674f06dc7b01a6fLennart Poettering log_error("Could not append IFLA_IFNAME attribute: %s",
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering strerror(-r));
801ad6a6a9cd8fbd58b9f9c27f20dbb3c87d47ddLennart Poettering return r;
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering }
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering r = sd_rtnl_message_open_container(req, IFLA_LINKINFO);
3339cb71d44c5198f9546f113674f06dc7b01a6fLennart Poettering if (r < 0) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_error("Colud not open IFLA_LINKINFO container: %s",
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering strerror(-r));
3339cb71d44c5198f9546f113674f06dc7b01a6fLennart Poettering return r;
3339cb71d44c5198f9546f113674f06dc7b01a6fLennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
3339cb71d44c5198f9546f113674f06dc7b01a6fLennart Poettering r = sd_rtnl_message_append_string(req, IFLA_INFO_KIND, "bridge");
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering if (r < 0) {
309e9d86f0e7f9c5f0a2a09227bdfdb3174d4436Lennart Poettering log_error("Could not append IFLA_INFO_KIND attribute: %s",
3339cb71d44c5198f9546f113674f06dc7b01a6fLennart Poettering strerror(-r));
3339cb71d44c5198f9546f113674f06dc7b01a6fLennart Poettering return r;
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering r = sd_rtnl_message_close_container(req);
703e4f5e39c019da8c002ba10bd450ce378c0e91Lennart Poettering if (r < 0) {
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering log_error("Could not close IFLA_LINKINFO container %s",
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering strerror(-r));
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering }
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering r = sd_rtnl_call_async(bridge->manager->rtnl, req, &bridge_create_handler, bridge, 0, NULL);
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering if (r < 0) {
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering log_error("Could not send rtnetlink message: %s", strerror(-r));
309e9d86f0e7f9c5f0a2a09227bdfdb3174d4436Lennart Poettering return r;
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering }
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering log_info("Creating bridge '%s'", bridge->name);
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering
309e9d86f0e7f9c5f0a2a09227bdfdb3174d4436Lennart Poettering bridge->state = BRIDGE_STATE_CREATING;
309e9d86f0e7f9c5f0a2a09227bdfdb3174d4436Lennart Poettering
309e9d86f0e7f9c5f0a2a09227bdfdb3174d4436Lennart Poettering return 0;
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering}
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringint bridge_join(Bridge *bridge, Link *link, sd_rtnl_message_handler_t callback) {
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering if (bridge->state == BRIDGE_STATE_READY) {
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt bridge_join_ready(bridge, link, callback);
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering } else {
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering /* the bridge is not yet read, save this request for when it is*/
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering bridge_join_callback *cb;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering cb = new0(bridge_join_callback, 1);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (!cb)
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering return log_oom();
51323288fc628a5cac50914df915545d685b793eLennart Poettering
51323288fc628a5cac50914df915545d685b793eLennart Poettering cb->callback = callback;
51323288fc628a5cac50914df915545d685b793eLennart Poettering cb->link = link;
51323288fc628a5cac50914df915545d685b793eLennart Poettering
51323288fc628a5cac50914df915545d685b793eLennart Poettering LIST_PREPEND(callbacks, bridge->callbacks, cb);
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering }
51323288fc628a5cac50914df915545d685b793eLennart Poettering
51323288fc628a5cac50914df915545d685b793eLennart Poettering return 0;
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering}
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering
51323288fc628a5cac50914df915545d685b793eLennart Poetteringint bridge_set_link(Manager *m, Link *link) {
51323288fc628a5cac50914df915545d685b793eLennart Poettering Bridge *bridge;
51323288fc628a5cac50914df915545d685b793eLennart Poettering
51323288fc628a5cac50914df915545d685b793eLennart Poettering bridge = hashmap_get(m->bridges, link->ifname);
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering if (!bridge)
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering return -ENOENT;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (bridge->link && bridge->link != link)
51323288fc628a5cac50914df915545d685b793eLennart Poettering return -EEXIST;
51323288fc628a5cac50914df915545d685b793eLennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering bridge->link = link;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (bridge->state == BRIDGE_STATE_CREATED)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering bridge_enter_ready(bridge);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return 0;
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering}
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering
51323288fc628a5cac50914df915545d685b793eLennart Poetteringstatic int bridge_load_one(Manager *manager, const char *filename) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering _cleanup_bridge_free_ Bridge *bridge = NULL;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering _cleanup_fclose_ FILE *file = NULL;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering int r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
0dd25fb9f005d8ab7ac4bc10a609d00569f8c56aLennart Poettering assert(manager);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(filename);
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering
7b9f7afcc04e80b77a2567b0750aa2cd03c1a1cdLennart Poettering file = fopen(filename, "re");
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering if (!file) {
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering if (errno == ENOENT)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return 0;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering else
801ad6a6a9cd8fbd58b9f9c27f20dbb3c87d47ddLennart Poettering return errno;
51323288fc628a5cac50914df915545d685b793eLennart Poettering }
51323288fc628a5cac50914df915545d685b793eLennart Poettering
51323288fc628a5cac50914df915545d685b793eLennart Poettering bridge = new0(Bridge, 1);
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering if (!bridge)
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering return log_oom();
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering bridge->manager = manager;
51323288fc628a5cac50914df915545d685b793eLennart Poettering bridge->state = _BRIDGE_STATE_INVALID;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = config_parse(NULL, filename, file, "Bridge\0", config_item_perf_lookup,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering (void*) network_gperf_lookup, false, false, bridge);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_warning("Could not parse config file %s: %s", filename, strerror(-r));
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering } else
966c66e34940001a40806142ecebaae61b478444Lennart Poettering log_debug("Parsed configuration file %s", filename);
82bd6dddc4a363a9c3c6f41eb46eb171a80dca27Lennart Poettering
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering if (!bridge->name) {
82bd6dddc4a363a9c3c6f41eb46eb171a80dca27Lennart Poettering log_warning("Bridge without Name configured in %s. Ignoring", filename);
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering return 0;
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering }
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering bridge->filename = strdup(filename);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (!bridge->filename)
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering return log_oom();
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering r = hashmap_put(bridge->manager->bridges, bridge->name, bridge);
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering LIST_HEAD_INIT(bridge->callbacks);
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering r = bridge_create(bridge);
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering if (r < 0)
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering bridge = NULL;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering return 0;
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering}
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering
ad867662936a4c7ab2c7116d804c272338801231Lennart Poetteringint bridge_load(Manager *manager) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering Bridge *bridge;
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering char **files, **f;
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering int r;
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering assert(manager);
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering while ((bridge = hashmap_first(manager->bridges)))
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering bridge_free(bridge);
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering r = conf_files_list_strv(&files, ".netdev", NULL, (const char **)manager->network_dirs);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0) {
3339cb71d44c5198f9546f113674f06dc7b01a6fLennart Poettering log_error("Failed to enumerate netdev files: %s", strerror(-r));
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering return r;
801ad6a6a9cd8fbd58b9f9c27f20dbb3c87d47ddLennart Poettering }
3339cb71d44c5198f9546f113674f06dc7b01a6fLennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering STRV_FOREACH_BACKWARDS(f, files) {
3339cb71d44c5198f9546f113674f06dc7b01a6fLennart Poettering r = bridge_load_one(manager, *f);
3339cb71d44c5198f9546f113674f06dc7b01a6fLennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering }
3339cb71d44c5198f9546f113674f06dc7b01a6fLennart Poettering
3339cb71d44c5198f9546f113674f06dc7b01a6fLennart Poettering strv_free(files);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
3339cb71d44c5198f9546f113674f06dc7b01a6fLennart Poettering return 0;
3339cb71d44c5198f9546f113674f06dc7b01a6fLennart Poettering}
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering