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