1 // SPDX-License-Identifier: GPL-2.0 2 /* Copyright (C) 2007-2019 B.A.T.M.A.N. contributors: 3 * 4 * Marek Lindner, Simon Wunderlich 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of version 2 of the GNU General Public 8 * License as published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope that it will be useful, but 11 * WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 * General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program; if not, see <http://www.gnu.org/licenses/>. 17 */ 18 19 #include "main.h" 20 21 #include <linux/errno.h> 22 #include <linux/list.h> 23 #include <linux/moduleparam.h> 24 #include <linux/netlink.h> 25 #include <linux/printk.h> 26 #include <linux/seq_file.h> 27 #include <linux/skbuff.h> 28 #include <linux/stddef.h> 29 #include <linux/string.h> 30 #include <net/genetlink.h> 31 #include <net/netlink.h> 32 #include <uapi/linux/batman_adv.h> 33 34 #include "bat_algo.h" 35 #include "netlink.h" 36 37 char batadv_routing_algo[20] = "BATMAN_IV"; 38 static struct hlist_head batadv_algo_list; 39 40 /** 41 * batadv_algo_init() - Initialize batman-adv algorithm management data 42 * structures 43 */ 44 void batadv_algo_init(void) 45 { 46 INIT_HLIST_HEAD(&batadv_algo_list); 47 } 48 49 static struct batadv_algo_ops *batadv_algo_get(char *name) 50 { 51 struct batadv_algo_ops *bat_algo_ops = NULL, *bat_algo_ops_tmp; 52 53 hlist_for_each_entry(bat_algo_ops_tmp, &batadv_algo_list, list) { 54 if (strcmp(bat_algo_ops_tmp->name, name) != 0) 55 continue; 56 57 bat_algo_ops = bat_algo_ops_tmp; 58 break; 59 } 60 61 return bat_algo_ops; 62 } 63 64 /** 65 * batadv_algo_register() - Register callbacks for a mesh algorithm 66 * @bat_algo_ops: mesh algorithm callbacks to add 67 * 68 * Return: 0 on success or negative error number in case of failure 69 */ 70 int batadv_algo_register(struct batadv_algo_ops *bat_algo_ops) 71 { 72 struct batadv_algo_ops *bat_algo_ops_tmp; 73 74 bat_algo_ops_tmp = batadv_algo_get(bat_algo_ops->name); 75 if (bat_algo_ops_tmp) { 76 pr_info("Trying to register already registered routing algorithm: %s\n", 77 bat_algo_ops->name); 78 return -EEXIST; 79 } 80 81 /* all algorithms must implement all ops (for now) */ 82 if (!bat_algo_ops->iface.enable || 83 !bat_algo_ops->iface.disable || 84 !bat_algo_ops->iface.update_mac || 85 !bat_algo_ops->iface.primary_set || 86 !bat_algo_ops->neigh.cmp || 87 !bat_algo_ops->neigh.is_similar_or_better) { 88 pr_info("Routing algo '%s' does not implement required ops\n", 89 bat_algo_ops->name); 90 return -EINVAL; 91 } 92 93 INIT_HLIST_NODE(&bat_algo_ops->list); 94 hlist_add_head(&bat_algo_ops->list, &batadv_algo_list); 95 96 return 0; 97 } 98 99 /** 100 * batadv_algo_select() - Select algorithm of soft interface 101 * @bat_priv: the bat priv with all the soft interface information 102 * @name: name of the algorithm to select 103 * 104 * The algorithm callbacks for the soft interface will be set when the algorithm 105 * with the correct name was found. Any previous selected algorithm will not be 106 * deinitialized and the new selected algorithm will also not be initialized. 107 * It is therefore not allowed to call batadv_algo_select outside the creation 108 * function of the soft interface. 109 * 110 * Return: 0 on success or negative error number in case of failure 111 */ 112 int batadv_algo_select(struct batadv_priv *bat_priv, char *name) 113 { 114 struct batadv_algo_ops *bat_algo_ops; 115 116 bat_algo_ops = batadv_algo_get(name); 117 if (!bat_algo_ops) 118 return -EINVAL; 119 120 bat_priv->algo_ops = bat_algo_ops; 121 122 return 0; 123 } 124 125 #ifdef CONFIG_BATMAN_ADV_DEBUGFS 126 127 /** 128 * batadv_algo_seq_print_text() - Print the supported algorithms in a seq file 129 * @seq: seq file to print on 130 * @offset: not used 131 * 132 * Return: always 0 133 */ 134 int batadv_algo_seq_print_text(struct seq_file *seq, void *offset) 135 { 136 struct batadv_algo_ops *bat_algo_ops; 137 138 seq_puts(seq, "Available routing algorithms:\n"); 139 140 hlist_for_each_entry(bat_algo_ops, &batadv_algo_list, list) { 141 seq_printf(seq, " * %s\n", bat_algo_ops->name); 142 } 143 144 return 0; 145 } 146 #endif 147 148 static int batadv_param_set_ra(const char *val, const struct kernel_param *kp) 149 { 150 struct batadv_algo_ops *bat_algo_ops; 151 char *algo_name = (char *)val; 152 size_t name_len = strlen(algo_name); 153 154 if (name_len > 0 && algo_name[name_len - 1] == '\n') 155 algo_name[name_len - 1] = '\0'; 156 157 bat_algo_ops = batadv_algo_get(algo_name); 158 if (!bat_algo_ops) { 159 pr_err("Routing algorithm '%s' is not supported\n", algo_name); 160 return -EINVAL; 161 } 162 163 return param_set_copystring(algo_name, kp); 164 } 165 166 static const struct kernel_param_ops batadv_param_ops_ra = { 167 .set = batadv_param_set_ra, 168 .get = param_get_string, 169 }; 170 171 static struct kparam_string batadv_param_string_ra = { 172 .maxlen = sizeof(batadv_routing_algo), 173 .string = batadv_routing_algo, 174 }; 175 176 module_param_cb(routing_algo, &batadv_param_ops_ra, &batadv_param_string_ra, 177 0644); 178 179 /** 180 * batadv_algo_dump_entry() - fill in information about one supported routing 181 * algorithm 182 * @msg: netlink message to be sent back 183 * @portid: Port to reply to 184 * @seq: Sequence number of message 185 * @bat_algo_ops: Algorithm to be dumped 186 * 187 * Return: Error number, or 0 on success 188 */ 189 static int batadv_algo_dump_entry(struct sk_buff *msg, u32 portid, u32 seq, 190 struct batadv_algo_ops *bat_algo_ops) 191 { 192 void *hdr; 193 194 hdr = genlmsg_put(msg, portid, seq, &batadv_netlink_family, 195 NLM_F_MULTI, BATADV_CMD_GET_ROUTING_ALGOS); 196 if (!hdr) 197 return -EMSGSIZE; 198 199 if (nla_put_string(msg, BATADV_ATTR_ALGO_NAME, bat_algo_ops->name)) 200 goto nla_put_failure; 201 202 genlmsg_end(msg, hdr); 203 return 0; 204 205 nla_put_failure: 206 genlmsg_cancel(msg, hdr); 207 return -EMSGSIZE; 208 } 209 210 /** 211 * batadv_algo_dump() - fill in information about supported routing 212 * algorithms 213 * @msg: netlink message to be sent back 214 * @cb: Parameters to the netlink request 215 * 216 * Return: Length of reply message. 217 */ 218 int batadv_algo_dump(struct sk_buff *msg, struct netlink_callback *cb) 219 { 220 int portid = NETLINK_CB(cb->skb).portid; 221 struct batadv_algo_ops *bat_algo_ops; 222 int skip = cb->args[0]; 223 int i = 0; 224 225 hlist_for_each_entry(bat_algo_ops, &batadv_algo_list, list) { 226 if (i++ < skip) 227 continue; 228 229 if (batadv_algo_dump_entry(msg, portid, cb->nlh->nlmsg_seq, 230 bat_algo_ops)) { 231 i--; 232 break; 233 } 234 } 235 236 cb->args[0] = i; 237 238 return msg->len; 239 } 240