1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2
3 #include <inttypes.h>
4 #include <netinet/in.h>
5 #include <linux/genetlink.h>
6 #include <linux/if_arp.h>
7
8 #include "batadv.h"
9 #include "fileio.h"
10 #include "netlink-util.h"
11 #include "network-internal.h"
12 #include "networkd-manager.h"
13 #include "parse-util.h"
14 #include "stdio-util.h"
15 #include "string-table.h"
16 #include "string-util.h"
17
batadv_init(NetDev * n)18 static void batadv_init(NetDev *n) {
19 BatmanAdvanced *b;
20
21 b = BATADV(n);
22
23 /* Set defaults */
24 b->aggregation = true;
25 b->gateway_bandwidth_down = 10000;
26 b->gateway_bandwidth_up = 2000;
27 b->bridge_loop_avoidance = true;
28 b->distributed_arp_table = true;
29 b->fragmentation = true;
30 b->hop_penalty = 15;
31 b->originator_interval = 1000;
32 b->routing_algorithm = BATADV_ROUTING_ALGORITHM_BATMAN_V;
33 }
34
35 static const char* const batadv_gateway_mode_table[_BATADV_GATEWAY_MODE_MAX] = {
36 [BATADV_GATEWAY_MODE_OFF] = "off",
37 [BATADV_GATEWAY_MODE_CLIENT] = "client",
38 [BATADV_GATEWAY_MODE_SERVER] = "server",
39 };
40
41 static const char* const batadv_routing_algorithm_table[_BATADV_ROUTING_ALGORITHM_MAX] = {
42 [BATADV_ROUTING_ALGORITHM_BATMAN_V] = "batman-v",
43 [BATADV_ROUTING_ALGORITHM_BATMAN_IV] = "batman-iv",
44 };
45
46 static const char* const batadv_routing_algorithm_kernel_table[_BATADV_ROUTING_ALGORITHM_MAX] = {
47 [BATADV_ROUTING_ALGORITHM_BATMAN_V] = "BATMAN_V",
48 [BATADV_ROUTING_ALGORITHM_BATMAN_IV] = "BATMAN_IV",
49 };
50
51 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(batadv_gateway_mode, BatadvGatewayModes);
52 DEFINE_CONFIG_PARSE_ENUM(config_parse_batadv_gateway_mode, batadv_gateway_mode, BatadvGatewayModes,
53 "Failed to parse GatewayMode=");
54
55 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(batadv_routing_algorithm, BatadvRoutingAlgorithm);
56 DEFINE_CONFIG_PARSE_ENUM(config_parse_batadv_routing_algorithm, batadv_routing_algorithm, BatadvRoutingAlgorithm,
57 "Failed to parse RoutingAlgorithm=");
58
59 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(batadv_routing_algorithm_kernel, BatadvRoutingAlgorithm);
60
config_parse_badadv_bandwidth(const char * unit,const char * filename,unsigned line,const char * section,unsigned section_line,const char * lvalue,int ltype,const char * rvalue,void * data,void * userdata)61 int config_parse_badadv_bandwidth (
62 const char *unit,
63 const char *filename,
64 unsigned line,
65 const char *section,
66 unsigned section_line,
67 const char *lvalue,
68 int ltype,
69 const char *rvalue,
70 void *data,
71 void *userdata) {
72
73 uint64_t k;
74 uint32_t *bandwidth = data;
75 int r;
76
77 assert(filename);
78 assert(lvalue);
79 assert(rvalue);
80
81 r = parse_size(rvalue, 1000, &k);
82 if (r < 0) {
83 log_syntax(unit, LOG_WARNING, filename, line, r,
84 "Failed to parse '%s=', ignoring assignment: %s",
85 lvalue, rvalue);
86 return 0;
87 }
88
89 if (k/1000/100 > UINT32_MAX)
90 log_syntax(unit, LOG_WARNING, filename, line, 0,
91 "The value of '%s=', is outside of 0...429496729500000 range: %s",
92 lvalue, rvalue);
93
94 *bandwidth = k/1000/100;
95
96 return 0;
97 }
98
99 /* callback for batman netdev's parameter set */
netdev_batman_set_handler(sd_netlink * rtnl,sd_netlink_message * m,NetDev * netdev)100 static int netdev_batman_set_handler(sd_netlink *rtnl, sd_netlink_message *m, NetDev *netdev) {
101 int r;
102
103 assert(netdev);
104 assert(m);
105
106 r = sd_netlink_message_get_errno(m);
107 if (r < 0) {
108 log_netdev_warning_errno(netdev, r, "BATADV parameters could not be set: %m");
109 return 1;
110 }
111
112 log_netdev_debug(netdev, "BATADV parameters set success");
113
114 return 1;
115 }
116
netdev_batadv_post_create_message(NetDev * netdev,sd_netlink_message * message)117 static int netdev_batadv_post_create_message(NetDev *netdev, sd_netlink_message *message) {
118 BatmanAdvanced *b;
119 int r;
120
121 assert_se(b = BATADV(netdev));
122
123 r = sd_netlink_message_append_u32(message, BATADV_ATTR_MESH_IFINDEX, netdev->ifindex);
124 if (r < 0)
125 return r;
126
127 r = sd_netlink_message_append_u8(message, BATADV_ATTR_GW_MODE, b->gateway_mode);
128 if (r < 0)
129 return r;
130
131 r = sd_netlink_message_append_u8(message, BATADV_ATTR_AGGREGATED_OGMS_ENABLED, b->aggregation);
132 if (r < 0)
133 return r;
134
135 r = sd_netlink_message_append_u8(message, BATADV_ATTR_BRIDGE_LOOP_AVOIDANCE_ENABLED, b->bridge_loop_avoidance);
136 if (r < 0)
137 return r;
138
139 r = sd_netlink_message_append_u8(message, BATADV_ATTR_DISTRIBUTED_ARP_TABLE_ENABLED, b->distributed_arp_table);
140 if (r < 0)
141 return r;
142
143 r = sd_netlink_message_append_u8(message, BATADV_ATTR_FRAGMENTATION_ENABLED, b->fragmentation);
144 if (r < 0)
145 return r;
146
147 r = sd_netlink_message_append_u8(message, BATADV_ATTR_HOP_PENALTY, b->hop_penalty);
148 if (r < 0)
149 return r;
150
151 r = sd_netlink_message_append_u32(message, BATADV_ATTR_ORIG_INTERVAL, DIV_ROUND_UP(b->originator_interval, USEC_PER_MSEC));
152 if (r < 0)
153 return r;
154
155 r = sd_netlink_message_append_u32(message, BATADV_ATTR_GW_BANDWIDTH_DOWN, b->gateway_bandwidth_down);
156 if (r < 0)
157 return r;
158
159 r = sd_netlink_message_append_u32(message, BATADV_ATTR_GW_BANDWIDTH_UP, b->gateway_bandwidth_up);
160 if (r < 0)
161 return r;
162
163 return 0;
164 }
165
netdev_batadv_post_create(NetDev * netdev,Link * link)166 static int netdev_batadv_post_create(NetDev *netdev, Link *link) {
167 _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *message = NULL;
168 int r;
169
170 assert(netdev);
171
172 r = sd_genl_message_new(netdev->manager->genl, BATADV_NL_NAME, BATADV_CMD_SET_MESH, &message);
173 if (r < 0)
174 return log_netdev_error_errno(netdev, r, "Could not allocate netlink message: %m");
175
176 r = netdev_batadv_post_create_message(netdev, message);
177 if (r < 0)
178 return log_netdev_error_errno(netdev, r, "Could not create netlink message: %m");
179
180 r = netlink_call_async(netdev->manager->genl, NULL, message, netdev_batman_set_handler,
181 netdev_destroy_callback, netdev);
182 if (r < 0)
183 return log_netdev_error_errno(netdev, r, "Could not send netlink message: %m");
184
185 netdev_ref(netdev);
186
187 return r;
188 }
189
netdev_batadv_fill_message_create(NetDev * netdev,Link * link,sd_netlink_message * m)190 static int netdev_batadv_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) {
191 BatmanAdvanced *b;
192 int r;
193
194 assert(netdev);
195 assert(m);
196
197 b = BATADV(netdev);
198 assert(b);
199
200 r = sd_netlink_message_append_string(m, IFLA_BATADV_ALGO_NAME, batadv_routing_algorithm_kernel_to_string(b->routing_algorithm));
201 if (r < 0)
202 return r;
203
204 return 0;
205 }
206
207 const NetDevVTable batadv_vtable = {
208 .object_size = sizeof(BatmanAdvanced),
209 .init = batadv_init,
210 .sections = NETDEV_COMMON_SECTIONS "BatmanAdvanced\0",
211 .fill_message_create = netdev_batadv_fill_message_create,
212 .post_create = netdev_batadv_post_create,
213 .create_type = NETDEV_CREATE_INDEPENDENT,
214 .iftype = ARPHRD_ETHER,
215 .generate_mac = true,
216 };
217