]> git.ipfire.org Git - people/ms/network.git/blame - src/networkd/port.c
networkd: Fix finding links by name
[people/ms/network.git] / src / networkd / port.c
CommitLineData
abeab069
MT
1/*#############################################################################
2# #
3# IPFire.org - A linux based firewall #
4# Copyright (C) 2023 IPFire Network Development Team #
5# #
6# This program is free software: you can redistribute it and/or modify #
7# it under the terms of the GNU General Public License as published by #
8# the Free Software Foundation, either version 3 of the License, or #
9# (at your option) any later version. #
10# #
11# This program is distributed in the hope that it will be useful, #
12# but WITHOUT ANY WARRANTY; without even the implied warranty of #
13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
14# GNU General Public License for more details. #
15# #
16# You should have received a copy of the GNU General Public License #
17# along with this program. If not, see <http://www.gnu.org/licenses/>. #
18# #
19#############################################################################*/
20
827435c8 21#include <limits.h>
abeab069 22#include <net/if.h>
2e7f4705 23#include <stdint.h>
abeab069
MT
24#include <stdlib.h>
25
7297ba7f
MT
26#include <systemd/sd-bus.h>
27
2e7f4705 28#include "address.h"
abeab069 29#include "config.h"
30d4ab67 30#include "link.h"
827435c8 31#include "logging.h"
abeab069
MT
32#include "string.h"
33#include "port.h"
34
35struct nw_port {
2361667e 36 nw_daemon* daemon;
abeab069
MT
37 int nrefs;
38
39 char name[IF_NAMESIZE];
827435c8 40 nw_port_type_t type;
abeab069
MT
41
42 // Configuration
2361667e 43 nw_config *config;
2e7f4705
MT
44
45 // Common attributes
46 nw_address_t address;
abeab069
MT
47};
48
827435c8
MT
49static const struct nw_port_type_map {
50 nw_port_type_t type;
51 const char* name;
52} nw_port_type_map[] = {
53 { NW_PORT_DUMMY, "dummy" },
54 { NW_PORT_UNKNOWN, NULL },
55};
56
57static nw_port_type_t nw_port_type_from_string(const char* s) {
58 const struct nw_port_type_map* map = NULL;
59
60 for (map = nw_port_type_map; *map->name; map++) {
61 if (strcmp(map->name, s) == 0)
62 return map->type;
63 }
64
65 return NW_PORT_UNKNOWN;
66}
67
2361667e 68static void nw_port_free(nw_port* port) {
abeab069
MT
69 if (port->config)
70 nw_config_unref(port->config);
30d4ab67
MT
71 if (port->daemon)
72 nw_daemon_unref(port->daemon);
abeab069
MT
73
74 free(port);
75}
76
2361667e 77static int nw_port_setup_address(nw_port* port) {
2e7f4705
MT
78 int r;
79
80 // Read ADDRESS from configuration
81 const char* s = nw_config_get(port->config, "ADDRESS");
82 if (!s) {
83 ERROR("Port %s: Address isn't set\n", port->name);
9a93da54 84 goto ERROR;
2e7f4705
MT
85 }
86
87 // Parse the address
88 r = nw_address_from_string(&port->address, s);
89 if (r) {
90 ERROR("Port %s: Could not parse address: %m\n", port->name);
9a93da54 91 goto ERROR;
2e7f4705
MT
92 }
93
d81d9cf5
MT
94 // Check if this address is usable
95 r = nw_address_is_multicast(&port->address);
96 if (r) {
97 DEBUG("Port %s: Multicast bit is set on Ethernet address\n", port->name);
98 goto ERROR;
99 }
2e7f4705 100
9a93da54
MT
101 return 0;
102
103ERROR:
104 // Generate a random Ethernet address
105 r = nw_address_generate(&port->address);
106 if (r) {
107 ERROR("Could not generate a random Ethernet address: %m\n");
108 return r;
109 }
110
2e7f4705
MT
111 return 0;
112}
113
2361667e 114static int nw_port_setup_common(nw_port* port) {
2e7f4705
MT
115 int r;
116
117 // Address
118 r = nw_port_setup_address(port);
119 if (r)
120 return r;
121
122 return 0;
827435c8
MT
123}
124
2361667e 125static nw_port_type_t nw_port_setup_type(nw_port* port) {
827435c8
MT
126 const char* type = nw_config_get(port->config, "TYPE");
127 if (!type)
128 return NW_PORT_UNKNOWN;
129
130 return nw_port_type_from_string(type);
131}
132
2361667e 133static int nw_port_setup(nw_port* port) {
827435c8
MT
134 char path[PATH_MAX];
135 int r;
136
137 // Compose the path to the main configuration file
138 r = nw_path_join(path, PORT_CONFIG_DIR, port->name);
139 if (r)
140 return r;
141
142 // Initialize the configuration
143 r = nw_config_create(&port->config, path);
144 if (r)
145 return r;
146
147 // Determine type
148 port->type = nw_port_setup_type(port);
149 if (!port->type) {
150 ERROR("Could not determine type of port %s\n", port->name);
151 return 0;
152 }
153
154 // Perform some common initialization
155 r = nw_port_setup_common(port);
156 if (r)
157 return r;
158
159 // Call any custom initialization
160 switch (port->type) {
161 // These do not need any special initialization
162 case NW_PORT_DUMMY:
163 case NW_PORT_UNKNOWN:
164 break;
165 }
166
167 return 0;
168}
169
2361667e 170int nw_port_create(nw_port** port, nw_daemon* daemon, const char* name) {
abeab069
MT
171 int r;
172
173 // Allocate a new object
2361667e 174 nw_port* p = calloc(1, sizeof(*p));
abeab069
MT
175 if (!p)
176 return 1;
177
30d4ab67
MT
178 // Store a reference to the daemon
179 p->daemon = nw_daemon_ref(daemon);
180
abeab069
MT
181 // Initialize reference counter
182 p->nrefs = 1;
183
184 // Store the name
185 r = nw_string_set(p->name, name);
186 if (r)
187 goto ERROR;
188
827435c8
MT
189 // Setup the port
190 r = nw_port_setup(p);
191 if (r)
192 goto ERROR;
193
abeab069
MT
194 *port = p;
195 return 0;
196
197ERROR:
198 nw_port_free(p);
199 return r;
200}
201
2361667e 202nw_port* nw_port_ref(nw_port* port) {
abeab069
MT
203 port->nrefs++;
204
205 return port;
206}
207
2361667e 208nw_port* nw_port_unref(nw_port* port) {
abeab069
MT
209 if (--port->nrefs > 0)
210 return port;
211
212 nw_port_free(port);
213 return NULL;
214}
215
605e975f
MT
216int nw_port_save(nw_port* port) {
217 int r;
218
219 r = nw_config_write(port->config);
220 if (r)
221 return r;
222
223 return 0;
224}
225
2361667e 226const char* nw_port_name(nw_port* port) {
abeab069
MT
227 return port->name;
228}
7297ba7f 229
2361667e 230char* nw_port_bus_path(nw_port* port) {
7297ba7f
MT
231 char* p = NULL;
232 int r;
233
234 // Encode the bus path
235 r = sd_bus_path_encode("/org/ipfire/network1/port", port->name, &p);
236 if (r < 0)
237 return NULL;
238
239 return p;
240}
4a383286 241
2361667e 242static nw_link* nw_port_get_link(nw_port* port) {
30d4ab67
MT
243 return nw_daemon_get_link_by_name(port->daemon, port->name);
244}
245
2361667e 246const nw_address_t* nw_port_get_address(nw_port* port) {
4a383286
MT
247 return &port->address;
248}
20375a08
MT
249
250int nw_port_has_carrier(nw_port* port) {
251 int has_carrier = 0;
252
253 // Fetch link
254 nw_link* link = nw_port_get_link(port);
255 if (link) {
256 has_carrier = nw_link_has_carrier(link);
257 nw_link_unref(link);
258 }
259
260 return has_carrier;
261}