main.c 4.3 KB
Newer Older
1
/*
2
 * Copyright (C) 2007-2011 B.A.T.M.A.N. contributors:
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
 *
 * Marek Lindner, Simon Wunderlich
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of version 2 of the GNU General Public
 * License as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301, USA
 *
 */

#include "main.h"
#include "bat_sysfs.h"
#include "bat_debugfs.h"
#include "routing.h"
#include "send.h"
#include "originator.h"
#include "soft-interface.h"
#include "icmp_socket.h"
#include "translation-table.h"
#include "hard-interface.h"
#include "gateway_client.h"
#include "vis.h"
#include "hash.h"

36 37 38

/* List manipulations on hardif_list have to be rtnl_lock()'ed,
 * list traversals just rcu-locked */
39
struct list_head hardif_list;
40 41 42 43 44 45 46

unsigned char broadcast_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};

struct workqueue_struct *bat_event_workqueue;

static int __init batman_init(void)
{
47
	INIT_LIST_HEAD(&hardif_list);
48 49 50 51 52 53 54 55 56 57 58 59 60

	/* the name should not be longer than 10 chars - see
	 * http://lwn.net/Articles/23634/ */
	bat_event_workqueue = create_singlethread_workqueue("bat_events");

	if (!bat_event_workqueue)
		return -ENOMEM;

	bat_socket_init();
	debugfs_init();

	register_netdevice_notifier(&hard_if_notifier);

61 62
	pr_info("B.A.T.M.A.N. advanced %s (compatibility version %i) "
		"loaded\n", SOURCE_VERSION, COMPAT_VERSION);
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85

	return 0;
}

static void __exit batman_exit(void)
{
	debugfs_destroy();
	unregister_netdevice_notifier(&hard_if_notifier);
	hardif_remove_interfaces();

	flush_workqueue(bat_event_workqueue);
	destroy_workqueue(bat_event_workqueue);
	bat_event_workqueue = NULL;

	rcu_barrier();
}

int mesh_init(struct net_device *soft_iface)
{
	struct bat_priv *bat_priv = netdev_priv(soft_iface);

	spin_lock_init(&bat_priv->forw_bat_list_lock);
	spin_lock_init(&bat_priv->forw_bcast_list_lock);
86 87
	spin_lock_init(&bat_priv->tt_changes_list_lock);
	spin_lock_init(&bat_priv->tt_req_list_lock);
88
	spin_lock_init(&bat_priv->tt_roam_list_lock);
89
	spin_lock_init(&bat_priv->tt_buff_lock);
90 91 92 93
	spin_lock_init(&bat_priv->gw_list_lock);
	spin_lock_init(&bat_priv->vis_hash_lock);
	spin_lock_init(&bat_priv->vis_list_lock);
	spin_lock_init(&bat_priv->softif_neigh_lock);
94
	spin_lock_init(&bat_priv->softif_neigh_vid_lock);
95 96 97 98

	INIT_HLIST_HEAD(&bat_priv->forw_bat_list);
	INIT_HLIST_HEAD(&bat_priv->forw_bcast_list);
	INIT_HLIST_HEAD(&bat_priv->gw_list);
99
	INIT_HLIST_HEAD(&bat_priv->softif_neigh_vids);
100 101
	INIT_LIST_HEAD(&bat_priv->tt_changes_list);
	INIT_LIST_HEAD(&bat_priv->tt_req_list);
102
	INIT_LIST_HEAD(&bat_priv->tt_roam_list);
103 104 105 106

	if (originator_init(bat_priv) < 1)
		goto err;

107
	if (tt_init(bat_priv) < 1)
108 109
		goto err;

110
	tt_local_add(soft_iface, soft_iface->dev_addr, NULL_IFINDEX);
111 112 113 114

	if (vis_init(bat_priv) < 1)
		goto err;

115
	atomic_set(&bat_priv->gw_reselect, 0);
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
	atomic_set(&bat_priv->mesh_state, MESH_ACTIVE);
	goto end;

err:
	mesh_free(soft_iface);
	return -1;

end:
	return 0;
}

void mesh_free(struct net_device *soft_iface)
{
	struct bat_priv *bat_priv = netdev_priv(soft_iface);

	atomic_set(&bat_priv->mesh_state, MESH_DEACTIVATING);

	purge_outstanding_packets(bat_priv, NULL);

	vis_quit(bat_priv);

	gw_node_purge(bat_priv);
	originator_free(bat_priv);

140
	tt_free(bat_priv);
141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156

	softif_neigh_purge(bat_priv);

	atomic_set(&bat_priv->mesh_state, MESH_INACTIVE);
}

void inc_module_count(void)
{
	try_module_get(THIS_MODULE);
}

void dec_module_count(void)
{
	module_put(THIS_MODULE);
}

157
int is_my_mac(const uint8_t *addr)
158
{
159
	const struct hard_iface *hard_iface;
160 161

	rcu_read_lock();
162 163
	list_for_each_entry_rcu(hard_iface, &hardif_list, list) {
		if (hard_iface->if_status != IF_ACTIVE)
164 165
			continue;

166
		if (compare_eth(hard_iface->net_dev->dev_addr, addr)) {
167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183
			rcu_read_unlock();
			return 1;
		}
	}
	rcu_read_unlock();
	return 0;
}

module_init(batman_init);
module_exit(batman_exit);

MODULE_LICENSE("GPL");

MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_SUPPORTED_DEVICE(DRIVER_DEVICE);
MODULE_VERSION(SOURCE_VERSION);