27c4abb25302729ad0c96ec703db78d470cb60a4
[firefly-linux-kernel-4.4.55.git] / drivers / staging / batman-adv / unicast.c
1 /*
2  * Copyright (C) 2010 B.A.T.M.A.N. contributors:
3  *
4  * Andreas Langer
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 "unicast.h"
24 #include "send.h"
25 #include "soft-interface.h"
26 #include "hash.h"
27 #include "translation-table.h"
28 #include "routing.h"
29 #include "hard-interface.h"
30
31 int unicast_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv)
32 {
33         struct ethhdr *ethhdr = (struct ethhdr *)skb->data;
34         struct unicast_packet *unicast_packet;
35         struct orig_node *orig_node;
36         struct batman_if *batman_if;
37         struct neigh_node *router;
38         uint8_t dstaddr[6];
39         unsigned long flags;
40
41         spin_lock_irqsave(&orig_hash_lock, flags);
42
43         /* get routing information */
44         orig_node = ((struct orig_node *)hash_find(orig_hash, ethhdr->h_dest));
45
46         /* check for hna host */
47         if (!orig_node)
48                 orig_node = transtable_search(ethhdr->h_dest);
49
50         router = find_router(orig_node, NULL);
51
52         if (!router)
53                 goto unlock;
54
55         /* don't lock while sending the packets ... we therefore
56                 * copy the required data before sending */
57
58         batman_if = router->if_incoming;
59         memcpy(dstaddr, router->addr, ETH_ALEN);
60
61         spin_unlock_irqrestore(&orig_hash_lock, flags);
62
63         if (batman_if->if_status != IF_ACTIVE)
64                 goto dropped;
65
66         if (my_skb_push(skb, sizeof(struct unicast_packet)) < 0)
67                 goto dropped;
68
69         unicast_packet = (struct unicast_packet *)skb->data;
70
71         unicast_packet->version = COMPAT_VERSION;
72         /* batman packet type: unicast */
73         unicast_packet->packet_type = BAT_UNICAST;
74         /* set unicast ttl */
75         unicast_packet->ttl = TTL;
76         /* copy the destination for faster routing */
77         memcpy(unicast_packet->dest, orig_node->orig, ETH_ALEN);
78
79         send_skb_packet(skb, batman_if, dstaddr);
80         return 0;
81
82 unlock:
83         spin_unlock_irqrestore(&orig_hash_lock, flags);
84 dropped:
85         kfree_skb(skb);
86         return 1;
87 }