1 /* 2 * Copyright (C) 2007-2012 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, write to the Free Software 17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 18 * 02110-1301, USA 19 * 20 */ 21 22 #include "main.h" 23 #include "bat_sysfs.h" 24 #include "bat_debugfs.h" 25 #include "routing.h" 26 #include "send.h" 27 #include "originator.h" 28 #include "soft-interface.h" 29 #include "icmp_socket.h" 30 #include "translation-table.h" 31 #include "hard-interface.h" 32 #include "gateway_client.h" 33 #include "bridge_loop_avoidance.h" 34 #include "vis.h" 35 #include "hash.h" 36 #include "bat_algo.h" 37 38 39 /* List manipulations on hardif_list have to be rtnl_lock()'ed, 40 * list traversals just rcu-locked */ 41 struct list_head hardif_list; 42 char bat_routing_algo[20] = "BATMAN IV"; 43 static struct hlist_head bat_algo_list; 44 45 unsigned char broadcast_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; 46 47 struct workqueue_struct *bat_event_workqueue; 48 49 static int __init batman_init(void) 50 { 51 INIT_LIST_HEAD(&hardif_list); 52 INIT_HLIST_HEAD(&bat_algo_list); 53 54 bat_iv_init(); 55 56 /* the name should not be longer than 10 chars - see 57 * http://lwn.net/Articles/23634/ */ 58 bat_event_workqueue = create_singlethread_workqueue("bat_events"); 59 60 if (!bat_event_workqueue) 61 return -ENOMEM; 62 63 bat_socket_init(); 64 debugfs_init(); 65 66 register_netdevice_notifier(&hard_if_notifier); 67 68 pr_info("B.A.T.M.A.N. advanced %s (compatibility version %i) loaded\n", 69 SOURCE_VERSION, COMPAT_VERSION); 70 71 return 0; 72 } 73 74 static void __exit batman_exit(void) 75 { 76 debugfs_destroy(); 77 unregister_netdevice_notifier(&hard_if_notifier); 78 hardif_remove_interfaces(); 79 80 flush_workqueue(bat_event_workqueue); 81 destroy_workqueue(bat_event_workqueue); 82 bat_event_workqueue = NULL; 83 84 rcu_barrier(); 85 } 86 87 int mesh_init(struct net_device *soft_iface) 88 { 89 struct bat_priv *bat_priv = netdev_priv(soft_iface); 90 91 spin_lock_init(&bat_priv->forw_bat_list_lock); 92 spin_lock_init(&bat_priv->forw_bcast_list_lock); 93 spin_lock_init(&bat_priv->tt_changes_list_lock); 94 spin_lock_init(&bat_priv->tt_req_list_lock); 95 spin_lock_init(&bat_priv->tt_roam_list_lock); 96 spin_lock_init(&bat_priv->tt_buff_lock); 97 spin_lock_init(&bat_priv->gw_list_lock); 98 spin_lock_init(&bat_priv->vis_hash_lock); 99 spin_lock_init(&bat_priv->vis_list_lock); 100 101 INIT_HLIST_HEAD(&bat_priv->forw_bat_list); 102 INIT_HLIST_HEAD(&bat_priv->forw_bcast_list); 103 INIT_HLIST_HEAD(&bat_priv->gw_list); 104 INIT_LIST_HEAD(&bat_priv->tt_changes_list); 105 INIT_LIST_HEAD(&bat_priv->tt_req_list); 106 INIT_LIST_HEAD(&bat_priv->tt_roam_list); 107 108 if (originator_init(bat_priv) < 1) 109 goto err; 110 111 if (tt_init(bat_priv) < 1) 112 goto err; 113 114 tt_local_add(soft_iface, soft_iface->dev_addr, NULL_IFINDEX); 115 116 if (vis_init(bat_priv) < 1) 117 goto err; 118 119 if (bla_init(bat_priv) < 1) 120 goto err; 121 122 atomic_set(&bat_priv->gw_reselect, 0); 123 atomic_set(&bat_priv->mesh_state, MESH_ACTIVE); 124 goto end; 125 126 err: 127 mesh_free(soft_iface); 128 return -1; 129 130 end: 131 return 0; 132 } 133 134 void mesh_free(struct net_device *soft_iface) 135 { 136 struct bat_priv *bat_priv = netdev_priv(soft_iface); 137 138 atomic_set(&bat_priv->mesh_state, MESH_DEACTIVATING); 139 140 purge_outstanding_packets(bat_priv, NULL); 141 142 vis_quit(bat_priv); 143 144 gw_node_purge(bat_priv); 145 originator_free(bat_priv); 146 147 tt_free(bat_priv); 148 149 bla_free(bat_priv); 150 151 atomic_set(&bat_priv->mesh_state, MESH_INACTIVE); 152 } 153 154 void inc_module_count(void) 155 { 156 try_module_get(THIS_MODULE); 157 } 158 159 void dec_module_count(void) 160 { 161 module_put(THIS_MODULE); 162 } 163 164 int is_my_mac(const uint8_t *addr) 165 { 166 const struct hard_iface *hard_iface; 167 168 rcu_read_lock(); 169 list_for_each_entry_rcu(hard_iface, &hardif_list, list) { 170 if (hard_iface->if_status != IF_ACTIVE) 171 continue; 172 173 if (compare_eth(hard_iface->net_dev->dev_addr, addr)) { 174 rcu_read_unlock(); 175 return 1; 176 } 177 } 178 rcu_read_unlock(); 179 return 0; 180 } 181 182 static struct bat_algo_ops *bat_algo_get(char *name) 183 { 184 struct bat_algo_ops *bat_algo_ops = NULL, *bat_algo_ops_tmp; 185 struct hlist_node *node; 186 187 hlist_for_each_entry(bat_algo_ops_tmp, node, &bat_algo_list, list) { 188 if (strcmp(bat_algo_ops_tmp->name, name) != 0) 189 continue; 190 191 bat_algo_ops = bat_algo_ops_tmp; 192 break; 193 } 194 195 return bat_algo_ops; 196 } 197 198 int bat_algo_register(struct bat_algo_ops *bat_algo_ops) 199 { 200 struct bat_algo_ops *bat_algo_ops_tmp; 201 int ret = -1; 202 203 bat_algo_ops_tmp = bat_algo_get(bat_algo_ops->name); 204 if (bat_algo_ops_tmp) { 205 pr_info("Trying to register already registered routing algorithm: %s\n", 206 bat_algo_ops->name); 207 goto out; 208 } 209 210 /* all algorithms must implement all ops (for now) */ 211 if (!bat_algo_ops->bat_iface_enable || 212 !bat_algo_ops->bat_iface_disable || 213 !bat_algo_ops->bat_primary_iface_set || 214 !bat_algo_ops->bat_ogm_update_mac || 215 !bat_algo_ops->bat_ogm_schedule || 216 !bat_algo_ops->bat_ogm_emit || 217 !bat_algo_ops->bat_ogm_receive) { 218 pr_info("Routing algo '%s' does not implement required ops\n", 219 bat_algo_ops->name); 220 goto out; 221 } 222 223 INIT_HLIST_NODE(&bat_algo_ops->list); 224 hlist_add_head(&bat_algo_ops->list, &bat_algo_list); 225 ret = 0; 226 227 out: 228 return ret; 229 } 230 231 int bat_algo_select(struct bat_priv *bat_priv, char *name) 232 { 233 struct bat_algo_ops *bat_algo_ops; 234 int ret = -1; 235 236 bat_algo_ops = bat_algo_get(name); 237 if (!bat_algo_ops) 238 goto out; 239 240 bat_priv->bat_algo_ops = bat_algo_ops; 241 ret = 0; 242 243 out: 244 return ret; 245 } 246 247 int bat_algo_seq_print_text(struct seq_file *seq, void *offset) 248 { 249 struct bat_algo_ops *bat_algo_ops; 250 struct hlist_node *node; 251 252 seq_printf(seq, "Available routing algorithms:\n"); 253 254 hlist_for_each_entry(bat_algo_ops, node, &bat_algo_list, list) { 255 seq_printf(seq, "%s\n", bat_algo_ops->name); 256 } 257 258 return 0; 259 } 260 261 static int param_set_ra(const char *val, const struct kernel_param *kp) 262 { 263 struct bat_algo_ops *bat_algo_ops; 264 265 bat_algo_ops = bat_algo_get((char *)val); 266 if (!bat_algo_ops) { 267 pr_err("Routing algorithm '%s' is not supported\n", val); 268 return -EINVAL; 269 } 270 271 return param_set_copystring(val, kp); 272 } 273 274 static const struct kernel_param_ops param_ops_ra = { 275 .set = param_set_ra, 276 .get = param_get_string, 277 }; 278 279 static struct kparam_string __param_string_ra = { 280 .maxlen = sizeof(bat_routing_algo), 281 .string = bat_routing_algo, 282 }; 283 284 module_param_cb(routing_algo, ¶m_ops_ra, &__param_string_ra, 0644); 285 module_init(batman_init); 286 module_exit(batman_exit); 287 288 MODULE_LICENSE("GPL"); 289 290 MODULE_AUTHOR(DRIVER_AUTHOR); 291 MODULE_DESCRIPTION(DRIVER_DESC); 292 MODULE_SUPPORTED_DEVICE(DRIVER_DEVICE); 293 MODULE_VERSION(SOURCE_VERSION); 294