1 /*
2  * Copyright (C) 2010-2011 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 "gateway_client.h"
27 #include "originator.h"
28 #include "hash.h"
29 #include "translation-table.h"
30 #include "routing.h"
31 #include "hard-interface.h"
32 
33 
frag_merge_packet(struct list_head * head,struct frag_packet_list_entry * tfp,struct sk_buff * skb)34 static struct sk_buff *frag_merge_packet(struct list_head *head,
35 					 struct frag_packet_list_entry *tfp,
36 					 struct sk_buff *skb)
37 {
38 	struct unicast_frag_packet *up =
39 		(struct unicast_frag_packet *)skb->data;
40 	struct sk_buff *tmp_skb;
41 	struct unicast_packet *unicast_packet;
42 	int hdr_len = sizeof(struct unicast_packet);
43 	int uni_diff = sizeof(struct unicast_frag_packet) - hdr_len;
44 
45 	/* set skb to the first part and tmp_skb to the second part */
46 	if (up->flags & UNI_FRAG_HEAD) {
47 		tmp_skb = tfp->skb;
48 	} else {
49 		tmp_skb = skb;
50 		skb = tfp->skb;
51 	}
52 
53 	if (skb_linearize(skb) < 0 || skb_linearize(tmp_skb) < 0)
54 		goto err;
55 
56 	skb_pull(tmp_skb, sizeof(struct unicast_frag_packet));
57 	if (pskb_expand_head(skb, 0, tmp_skb->len, GFP_ATOMIC) < 0)
58 		goto err;
59 
60 	/* move free entry to end */
61 	tfp->skb = NULL;
62 	tfp->seqno = 0;
63 	list_move_tail(&tfp->list, head);
64 
65 	memcpy(skb_put(skb, tmp_skb->len), tmp_skb->data, tmp_skb->len);
66 	kfree_skb(tmp_skb);
67 
68 	memmove(skb->data + uni_diff, skb->data, hdr_len);
69 	unicast_packet = (struct unicast_packet *) skb_pull(skb, uni_diff);
70 	unicast_packet->packet_type = BAT_UNICAST;
71 
72 	return skb;
73 
74 err:
75 	/* free buffered skb, skb will be freed later */
76 	kfree_skb(tfp->skb);
77 	return NULL;
78 }
79 
frag_create_entry(struct list_head * head,struct sk_buff * skb)80 static void frag_create_entry(struct list_head *head, struct sk_buff *skb)
81 {
82 	struct frag_packet_list_entry *tfp;
83 	struct unicast_frag_packet *up =
84 		(struct unicast_frag_packet *)skb->data;
85 
86 	/* free and oldest packets stand at the end */
87 	tfp = list_entry((head)->prev, typeof(*tfp), list);
88 	kfree_skb(tfp->skb);
89 
90 	tfp->seqno = ntohs(up->seqno);
91 	tfp->skb = skb;
92 	list_move(&tfp->list, head);
93 	return;
94 }
95 
frag_create_buffer(struct list_head * head)96 static int frag_create_buffer(struct list_head *head)
97 {
98 	int i;
99 	struct frag_packet_list_entry *tfp;
100 
101 	for (i = 0; i < FRAG_BUFFER_SIZE; i++) {
102 		tfp = kmalloc(sizeof(struct frag_packet_list_entry),
103 			GFP_ATOMIC);
104 		if (!tfp) {
105 			frag_list_free(head);
106 			return -ENOMEM;
107 		}
108 		tfp->skb = NULL;
109 		tfp->seqno = 0;
110 		INIT_LIST_HEAD(&tfp->list);
111 		list_add(&tfp->list, head);
112 	}
113 
114 	return 0;
115 }
116 
frag_search_packet(struct list_head * head,struct unicast_frag_packet * up)117 static struct frag_packet_list_entry *frag_search_packet(struct list_head *head,
118 						 struct unicast_frag_packet *up)
119 {
120 	struct frag_packet_list_entry *tfp;
121 	struct unicast_frag_packet *tmp_up = NULL;
122 	uint16_t search_seqno;
123 
124 	if (up->flags & UNI_FRAG_HEAD)
125 		search_seqno = ntohs(up->seqno)+1;
126 	else
127 		search_seqno = ntohs(up->seqno)-1;
128 
129 	list_for_each_entry(tfp, head, list) {
130 
131 		if (!tfp->skb)
132 			continue;
133 
134 		if (tfp->seqno == ntohs(up->seqno))
135 			goto mov_tail;
136 
137 		tmp_up = (struct unicast_frag_packet *)tfp->skb->data;
138 
139 		if (tfp->seqno == search_seqno) {
140 
141 			if ((tmp_up->flags & UNI_FRAG_HEAD) !=
142 			    (up->flags & UNI_FRAG_HEAD))
143 				return tfp;
144 			else
145 				goto mov_tail;
146 		}
147 	}
148 	return NULL;
149 
150 mov_tail:
151 	list_move_tail(&tfp->list, head);
152 	return NULL;
153 }
154 
frag_list_free(struct list_head * head)155 void frag_list_free(struct list_head *head)
156 {
157 	struct frag_packet_list_entry *pf, *tmp_pf;
158 
159 	if (!list_empty(head)) {
160 
161 		list_for_each_entry_safe(pf, tmp_pf, head, list) {
162 			kfree_skb(pf->skb);
163 			list_del(&pf->list);
164 			kfree(pf);
165 		}
166 	}
167 	return;
168 }
169 
170 /* frag_reassemble_skb():
171  * returns NET_RX_DROP if the operation failed - skb is left intact
172  * returns NET_RX_SUCCESS if the fragment was buffered (skb_new will be NULL)
173  * or the skb could be reassembled (skb_new will point to the new packet and
174  * skb was freed)
175  */
frag_reassemble_skb(struct sk_buff * skb,struct bat_priv * bat_priv,struct sk_buff ** new_skb)176 int frag_reassemble_skb(struct sk_buff *skb, struct bat_priv *bat_priv,
177 			struct sk_buff **new_skb)
178 {
179 	struct orig_node *orig_node;
180 	struct frag_packet_list_entry *tmp_frag_entry;
181 	int ret = NET_RX_DROP;
182 	struct unicast_frag_packet *unicast_packet =
183 		(struct unicast_frag_packet *)skb->data;
184 
185 	*new_skb = NULL;
186 
187 	orig_node = orig_hash_find(bat_priv, unicast_packet->orig);
188 	if (!orig_node)
189 		goto out;
190 
191 	orig_node->last_frag_packet = jiffies;
192 
193 	if (list_empty(&orig_node->frag_list) &&
194 	    frag_create_buffer(&orig_node->frag_list)) {
195 		pr_debug("couldn't create frag buffer\n");
196 		goto out;
197 	}
198 
199 	tmp_frag_entry = frag_search_packet(&orig_node->frag_list,
200 					    unicast_packet);
201 
202 	if (!tmp_frag_entry) {
203 		frag_create_entry(&orig_node->frag_list, skb);
204 		ret = NET_RX_SUCCESS;
205 		goto out;
206 	}
207 
208 	*new_skb = frag_merge_packet(&orig_node->frag_list, tmp_frag_entry,
209 				     skb);
210 	/* if not, merge failed */
211 	if (*new_skb)
212 		ret = NET_RX_SUCCESS;
213 
214 out:
215 	if (orig_node)
216 		orig_node_free_ref(orig_node);
217 	return ret;
218 }
219 
frag_send_skb(struct sk_buff * skb,struct bat_priv * bat_priv,struct hard_iface * hard_iface,uint8_t dstaddr[])220 int frag_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv,
221 		  struct hard_iface *hard_iface, uint8_t dstaddr[])
222 {
223 	struct unicast_packet tmp_uc, *unicast_packet;
224 	struct sk_buff *frag_skb;
225 	struct unicast_frag_packet *frag1, *frag2;
226 	int uc_hdr_len = sizeof(struct unicast_packet);
227 	int ucf_hdr_len = sizeof(struct unicast_frag_packet);
228 	int data_len = skb->len - uc_hdr_len;
229 	int large_tail = 0;
230 	uint16_t seqno;
231 
232 	if (!bat_priv->primary_if)
233 		goto dropped;
234 
235 	frag_skb = dev_alloc_skb(data_len - (data_len / 2) + ucf_hdr_len);
236 	if (!frag_skb)
237 		goto dropped;
238 	skb_reserve(frag_skb, ucf_hdr_len);
239 
240 	unicast_packet = (struct unicast_packet *) skb->data;
241 	memcpy(&tmp_uc, unicast_packet, uc_hdr_len);
242 	skb_split(skb, frag_skb, data_len / 2 + uc_hdr_len);
243 
244 	if (my_skb_head_push(skb, ucf_hdr_len - uc_hdr_len) < 0 ||
245 	    my_skb_head_push(frag_skb, ucf_hdr_len) < 0)
246 		goto drop_frag;
247 
248 	frag1 = (struct unicast_frag_packet *)skb->data;
249 	frag2 = (struct unicast_frag_packet *)frag_skb->data;
250 
251 	memcpy(frag1, &tmp_uc, sizeof(struct unicast_packet));
252 
253 	frag1->ttl--;
254 	frag1->version = COMPAT_VERSION;
255 	frag1->packet_type = BAT_UNICAST_FRAG;
256 
257 	memcpy(frag1->orig, bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN);
258 	memcpy(frag2, frag1, sizeof(struct unicast_frag_packet));
259 
260 	if (data_len & 1)
261 		large_tail = UNI_FRAG_LARGETAIL;
262 
263 	frag1->flags = UNI_FRAG_HEAD | large_tail;
264 	frag2->flags = large_tail;
265 
266 	seqno = atomic_add_return(2, &hard_iface->frag_seqno);
267 	frag1->seqno = htons(seqno - 1);
268 	frag2->seqno = htons(seqno);
269 
270 	send_skb_packet(skb, hard_iface, dstaddr);
271 	send_skb_packet(frag_skb, hard_iface, dstaddr);
272 	return NET_RX_SUCCESS;
273 
274 drop_frag:
275 	kfree_skb(frag_skb);
276 dropped:
277 	kfree_skb(skb);
278 	return NET_RX_DROP;
279 }
280 
unicast_send_skb(struct sk_buff * skb,struct bat_priv * bat_priv)281 int unicast_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv)
282 {
283 	struct ethhdr *ethhdr = (struct ethhdr *)skb->data;
284 	struct unicast_packet *unicast_packet;
285 	struct orig_node *orig_node;
286 	struct neigh_node *neigh_node;
287 	int data_len = skb->len;
288 	int ret = 1;
289 
290 	/* get routing information */
291 	if (is_multicast_ether_addr(ethhdr->h_dest)) {
292 		orig_node = (struct orig_node *)gw_get_selected(bat_priv);
293 		if (orig_node)
294 			goto find_router;
295 	}
296 
297 	/* check for hna host - increases orig_node refcount */
298 	orig_node = transtable_search(bat_priv, ethhdr->h_dest);
299 
300 find_router:
301 	/**
302 	 * find_router():
303 	 *  - if orig_node is NULL it returns NULL
304 	 *  - increases neigh_nodes refcount if found.
305 	 */
306 	neigh_node = find_router(bat_priv, orig_node, NULL);
307 
308 	if (!neigh_node)
309 		goto out;
310 
311 	if (neigh_node->if_incoming->if_status != IF_ACTIVE)
312 		goto out;
313 
314 	if (my_skb_head_push(skb, sizeof(struct unicast_packet)) < 0)
315 		goto out;
316 
317 	unicast_packet = (struct unicast_packet *)skb->data;
318 
319 	unicast_packet->version = COMPAT_VERSION;
320 	/* batman packet type: unicast */
321 	unicast_packet->packet_type = BAT_UNICAST;
322 	/* set unicast ttl */
323 	unicast_packet->ttl = TTL;
324 	/* copy the destination for faster routing */
325 	memcpy(unicast_packet->dest, orig_node->orig, ETH_ALEN);
326 
327 	if (atomic_read(&bat_priv->fragmentation) &&
328 	    data_len + sizeof(struct unicast_packet) >
329 				neigh_node->if_incoming->net_dev->mtu) {
330 		/* send frag skb decreases ttl */
331 		unicast_packet->ttl++;
332 		ret = frag_send_skb(skb, bat_priv,
333 				    neigh_node->if_incoming, neigh_node->addr);
334 		goto out;
335 	}
336 
337 	send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr);
338 	ret = 0;
339 	goto out;
340 
341 out:
342 	if (neigh_node)
343 		neigh_node_free_ref(neigh_node);
344 	if (orig_node)
345 		orig_node_free_ref(orig_node);
346 	if (ret == 1)
347 		kfree_skb(skb);
348 	return ret;
349 }
350