]> git.ipfire.org Git - people/ms/network.git/blame - src/networkd/port.c
networkd: config: Add functions to handle boolean values
[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
02801f0d
MT
39 // Link
40 nw_link* link;
41
abeab069 42 char name[IF_NAMESIZE];
827435c8 43 nw_port_type_t type;
abeab069
MT
44
45 // Configuration
2361667e 46 nw_config *config;
2e7f4705
MT
47
48 // Common attributes
49 nw_address_t address;
abeab069
MT
50};
51
827435c8
MT
52static const struct nw_port_type_map {
53 nw_port_type_t type;
54 const char* name;
55} nw_port_type_map[] = {
56 { NW_PORT_DUMMY, "dummy" },
57 { NW_PORT_UNKNOWN, NULL },
58};
59
60static nw_port_type_t nw_port_type_from_string(const char* s) {
61 const struct nw_port_type_map* map = NULL;
62
63 for (map = nw_port_type_map; *map->name; map++) {
64 if (strcmp(map->name, s) == 0)
65 return map->type;
66 }
67
68 return NW_PORT_UNKNOWN;
69}
70
2361667e 71static void nw_port_free(nw_port* port) {
02801f0d
MT
72 if (port->link)
73 nw_link_unref(port->link);
abeab069
MT
74 if (port->config)
75 nw_config_unref(port->config);
30d4ab67
MT
76 if (port->daemon)
77 nw_daemon_unref(port->daemon);
abeab069
MT
78
79 free(port);
80}
81
2361667e 82static int nw_port_setup_address(nw_port* port) {
2e7f4705
MT
83 int r;
84
85 // Read ADDRESS from configuration
86 const char* s = nw_config_get(port->config, "ADDRESS");
87 if (!s) {
88 ERROR("Port %s: Address isn't set\n", port->name);
9a93da54 89 goto ERROR;
2e7f4705
MT
90 }
91
92 // Parse the address
93 r = nw_address_from_string(&port->address, s);
94 if (r) {
95 ERROR("Port %s: Could not parse address: %m\n", port->name);
9a93da54 96 goto ERROR;
2e7f4705
MT
97 }
98
d81d9cf5
MT
99 // Check if this address is usable
100 r = nw_address_is_multicast(&port->address);
101 if (r) {
102 DEBUG("Port %s: Multicast bit is set on Ethernet address\n", port->name);
103 goto ERROR;
104 }
2e7f4705 105
9a93da54
MT
106 return 0;
107
108ERROR:
109 // Generate a random Ethernet address
110 r = nw_address_generate(&port->address);
111 if (r) {
112 ERROR("Could not generate a random Ethernet address: %m\n");
113 return r;
114 }
115
2e7f4705
MT
116 return 0;
117}
118
2361667e 119static int nw_port_setup_common(nw_port* port) {
2e7f4705
MT
120 int r;
121
122 // Address
123 r = nw_port_setup_address(port);
124 if (r)
125 return r;
126
127 return 0;
827435c8
MT
128}
129
2361667e 130static nw_port_type_t nw_port_setup_type(nw_port* port) {
827435c8
MT
131 const char* type = nw_config_get(port->config, "TYPE");
132 if (!type)
133 return NW_PORT_UNKNOWN;
134
135 return nw_port_type_from_string(type);
136}
137
2361667e 138static int nw_port_setup(nw_port* port) {
827435c8
MT
139 char path[PATH_MAX];
140 int r;
141
02801f0d
MT
142 // Find the link
143 port->link = nw_daemon_get_link_by_name(port->daemon, port->name);
144 if (port->link) {
145 DEBUG("%s: Found matching link %d\n", port->name, nw_link_ifindex(port->link));
146 } else {
147 DEBUG("%s: Could not find matching link\n", port->name);
148 }
149
827435c8
MT
150 // Compose the path to the main configuration file
151 r = nw_path_join(path, PORT_CONFIG_DIR, port->name);
152 if (r)
153 return r;
154
155 // Initialize the configuration
156 r = nw_config_create(&port->config, path);
157 if (r)
158 return r;
159
160 // Determine type
161 port->type = nw_port_setup_type(port);
162 if (!port->type) {
163 ERROR("Could not determine type of port %s\n", port->name);
164 return 0;
165 }
166
167 // Perform some common initialization
168 r = nw_port_setup_common(port);
169 if (r)
170 return r;
171
172 // Call any custom initialization
173 switch (port->type) {
174 // These do not need any special initialization
175 case NW_PORT_DUMMY:
176 case NW_PORT_UNKNOWN:
177 break;
178 }
179
180 return 0;
181}
182
2361667e 183int nw_port_create(nw_port** port, nw_daemon* daemon, const char* name) {
abeab069
MT
184 int r;
185
186 // Allocate a new object
2361667e 187 nw_port* p = calloc(1, sizeof(*p));
abeab069
MT
188 if (!p)
189 return 1;
190
30d4ab67
MT
191 // Store a reference to the daemon
192 p->daemon = nw_daemon_ref(daemon);
193
abeab069
MT
194 // Initialize reference counter
195 p->nrefs = 1;
196
197 // Store the name
198 r = nw_string_set(p->name, name);
199 if (r)
200 goto ERROR;
201
827435c8
MT
202 // Setup the port
203 r = nw_port_setup(p);
204 if (r)
205 goto ERROR;
206
abeab069
MT
207 *port = p;
208 return 0;
209
210ERROR:
211 nw_port_free(p);
212 return r;
213}
214
2361667e 215nw_port* nw_port_ref(nw_port* port) {
abeab069
MT
216 port->nrefs++;
217
218 return port;
219}
220
2361667e 221nw_port* nw_port_unref(nw_port* port) {
abeab069
MT
222 if (--port->nrefs > 0)
223 return port;
224
225 nw_port_free(port);
226 return NULL;
227}
228
605e975f
MT
229int nw_port_save(nw_port* port) {
230 int r;
231
232 r = nw_config_write(port->config);
233 if (r)
234 return r;
235
236 return 0;
237}
238
2361667e 239const char* nw_port_name(nw_port* port) {
abeab069
MT
240 return port->name;
241}
7297ba7f 242
2361667e 243char* nw_port_bus_path(nw_port* port) {
7297ba7f
MT
244 char* p = NULL;
245 int r;
246
247 // Encode the bus path
248 r = sd_bus_path_encode("/org/ipfire/network1/port", port->name, &p);
249 if (r < 0)
250 return NULL;
251
252 return p;
253}
4a383286 254
2361667e 255static nw_link* nw_port_get_link(nw_port* port) {
02801f0d
MT
256 if (!port->link)
257 return NULL;
258
259 return nw_link_ref(port->link);
30d4ab67
MT
260}
261
2361667e 262const nw_address_t* nw_port_get_address(nw_port* port) {
4a383286
MT
263 return &port->address;
264}
20375a08
MT
265
266int nw_port_has_carrier(nw_port* port) {
02801f0d
MT
267 if (!port->link)
268 return 0;
20375a08 269
02801f0d 270 return nw_link_has_carrier(port->link);
20375a08 271}