1 /*
2  * Copyright (C) 2010-2012 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(*unicast_packet);
43 	int uni_diff = sizeof(*up) - 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(*up));
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->header.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(*tfp), GFP_ATOMIC);
103 		if (!tfp) {
104 			frag_list_free(head);
105 			return -ENOMEM;
106 		}
107 		tfp->skb = NULL;
108 		tfp->seqno = 0;
109 		INIT_LIST_HEAD(&tfp->list);
110 		list_add(&tfp->list, head);
111 	}
112 
113 	return 0;
114 }
115 
frag_search_packet(struct list_head * head,const struct unicast_frag_packet * up)116 static struct frag_packet_list_entry *frag_search_packet(struct list_head *head,
117 					   const struct unicast_frag_packet *up)
118 {
119 	struct frag_packet_list_entry *tfp;
120 	struct unicast_frag_packet *tmp_up = NULL;
121 	uint16_t search_seqno;
122 
123 	if (up->flags & UNI_FRAG_HEAD)
124 		search_seqno = ntohs(up->seqno)+1;
125 	else
126 		search_seqno = ntohs(up->seqno)-1;
127 
128 	list_for_each_entry(tfp, head, list) {
129 
130 		if (!tfp->skb)
131 			continue;
132 
133 		if (tfp->seqno == ntohs(up->seqno))
134 			goto mov_tail;
135 
136 		tmp_up = (struct unicast_frag_packet *)tfp->skb->data;
137 
138 		if (tfp->seqno == search_seqno) {
139 
140 			if ((tmp_up->flags & UNI_FRAG_HEAD) !=
141 			    (up->flags & UNI_FRAG_HEAD))
142 				return tfp;
143 			else
144 				goto mov_tail;
145 		}
146 	}
147 	return NULL;
148 
149 mov_tail:
150 	list_move_tail(&tfp->list, head);
151 	return NULL;
152 }
153 
frag_list_free(struct list_head * head)154 void frag_list_free(struct list_head *head)
155 {
156 	struct frag_packet_list_entry *pf, *tmp_pf;
157 
158 	if (!list_empty(head)) {
159 
160 		list_for_each_entry_safe(pf, tmp_pf, head, list) {
161 			kfree_skb(pf->skb);
162 			list_del(&pf->list);
163 			kfree(pf);
164 		}
165 	}
166 	return;
167 }
168 
169 /* frag_reassemble_skb():
170  * returns NET_RX_DROP if the operation failed - skb is left intact
171  * returns NET_RX_SUCCESS if the fragment was buffered (skb_new will be NULL)
172  * or the skb could be reassembled (skb_new will point to the new packet and
173  * skb was freed)
174  */
frag_reassemble_skb(struct sk_buff * skb,struct bat_priv * bat_priv,struct sk_buff ** new_skb)175 int frag_reassemble_skb(struct sk_buff *skb, struct bat_priv *bat_priv,
176 			struct sk_buff **new_skb)
177 {
178 	struct orig_node *orig_node;
179 	struct frag_packet_list_entry *tmp_frag_entry;
180 	int ret = NET_RX_DROP;
181 	struct unicast_frag_packet *unicast_packet =
182 		(struct unicast_frag_packet *)skb->data;
183 
184 	*new_skb = NULL;
185 
186 	orig_node = orig_hash_find(bat_priv, unicast_packet->orig);
187 	if (!orig_node)
188 		goto out;
189 
190 	orig_node->last_frag_packet = jiffies;
191 
192 	if (list_empty(&orig_node->frag_list) &&
193 	    frag_create_buffer(&orig_node->frag_list)) {
194 		pr_debug("couldn't create frag buffer\n");
195 		goto out;
196 	}
197 
198 	tmp_frag_entry = frag_search_packet(&orig_node->frag_list,
199 					    unicast_packet);
200 
201 	if (!tmp_frag_entry) {
202 		frag_create_entry(&orig_node->frag_list, skb);
203 		ret = NET_RX_SUCCESS;
204 		goto out;
205 	}
206 
207 	*new_skb = frag_merge_packet(&orig_node->frag_list, tmp_frag_entry,
208 				     skb);
209 	/* if not, merge failed */
210 	if (*new_skb)
211 		ret = NET_RX_SUCCESS;
212 
213 out:
214 	if (orig_node)
215 		orig_node_free_ref(orig_node);
216 	return ret;
217 }
218 
frag_send_skb(struct sk_buff * skb,struct bat_priv * bat_priv,struct hard_iface * hard_iface,const uint8_t dstaddr[])219 int frag_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv,
220 		  struct hard_iface *hard_iface, const uint8_t dstaddr[])
221 {
222 	struct unicast_packet tmp_uc, *unicast_packet;
223 	struct hard_iface *primary_if;
224 	struct sk_buff *frag_skb;
225 	struct unicast_frag_packet *frag1, *frag2;
226 	int uc_hdr_len = sizeof(*unicast_packet);
227 	int ucf_hdr_len = sizeof(*frag1);
228 	int data_len = skb->len - uc_hdr_len;
229 	int large_tail = 0, ret = NET_RX_DROP;
230 	uint16_t seqno;
231 
232 	primary_if = primary_if_get_selected(bat_priv);
233 	if (!primary_if)
234 		goto dropped;
235 
236 	frag_skb = dev_alloc_skb(data_len - (data_len / 2) + ucf_hdr_len);
237 	if (!frag_skb)
238 		goto dropped;
239 	skb_reserve(frag_skb, ucf_hdr_len);
240 
241 	unicast_packet = (struct unicast_packet *)skb->data;
242 	memcpy(&tmp_uc, unicast_packet, uc_hdr_len);
243 	skb_split(skb, frag_skb, data_len / 2 + uc_hdr_len);
244 
245 	if (my_skb_head_push(skb, ucf_hdr_len - uc_hdr_len) < 0 ||
246 	    my_skb_head_push(frag_skb, ucf_hdr_len) < 0)
247 		goto drop_frag;
248 
249 	frag1 = (struct unicast_frag_packet *)skb->data;
250 	frag2 = (struct unicast_frag_packet *)frag_skb->data;
251 
252 	memcpy(frag1, &tmp_uc, sizeof(tmp_uc));
253 
254 	frag1->header.ttl--;
255 	frag1->header.version = COMPAT_VERSION;
256 	frag1->header.packet_type = BAT_UNICAST_FRAG;
257 
258 	memcpy(frag1->orig, primary_if->net_dev->dev_addr, ETH_ALEN);
259 	memcpy(frag2, frag1, sizeof(*frag2));
260 
261 	if (data_len & 1)
262 		large_tail = UNI_FRAG_LARGETAIL;
263 
264 	frag1->flags = UNI_FRAG_HEAD | large_tail;
265 	frag2->flags = large_tail;
266 
267 	seqno = atomic_add_return(2, &hard_iface->frag_seqno);
268 	frag1->seqno = htons(seqno - 1);
269 	frag2->seqno = htons(seqno);
270 
271 	send_skb_packet(skb, hard_iface, dstaddr);
272 	send_skb_packet(frag_skb, hard_iface, dstaddr);
273 	ret = NET_RX_SUCCESS;
274 	goto out;
275 
276 drop_frag:
277 	kfree_skb(frag_skb);
278 dropped:
279 	kfree_skb(skb);
280 out:
281 	if (primary_if)
282 		hardif_free_ref(primary_if);
283 	return ret;
284 }
285 
unicast_send_skb(struct sk_buff * skb,struct bat_priv * bat_priv)286 int unicast_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv)
287 {
288 	struct ethhdr *ethhdr = (struct ethhdr *)skb->data;
289 	struct unicast_packet *unicast_packet;
290 	struct orig_node *orig_node;
291 	struct neigh_node *neigh_node;
292 	int data_len = skb->len;
293 	int ret = 1;
294 
295 	/* get routing information */
296 	if (is_multicast_ether_addr(ethhdr->h_dest)) {
297 		orig_node = gw_get_selected_orig(bat_priv);
298 		if (orig_node)
299 			goto find_router;
300 	}
301 
302 	/* check for tt host - increases orig_node refcount.
303 	 * returns NULL in case of AP isolation */
304 	orig_node = transtable_search(bat_priv, ethhdr->h_source,
305 				      ethhdr->h_dest);
306 
307 find_router:
308 	/**
309 	 * find_router():
310 	 *  - if orig_node is NULL it returns NULL
311 	 *  - increases neigh_nodes refcount if found.
312 	 */
313 	neigh_node = find_router(bat_priv, orig_node, NULL);
314 
315 	if (!neigh_node)
316 		goto out;
317 
318 	if (my_skb_head_push(skb, sizeof(*unicast_packet)) < 0)
319 		goto out;
320 
321 	unicast_packet = (struct unicast_packet *)skb->data;
322 
323 	unicast_packet->header.version = COMPAT_VERSION;
324 	/* batman packet type: unicast */
325 	unicast_packet->header.packet_type = BAT_UNICAST;
326 	/* set unicast ttl */
327 	unicast_packet->header.ttl = TTL;
328 	/* copy the destination for faster routing */
329 	memcpy(unicast_packet->dest, orig_node->orig, ETH_ALEN);
330 	/* set the destination tt version number */
331 	unicast_packet->ttvn =
332 		(uint8_t)atomic_read(&orig_node->last_ttvn);
333 
334 	if (atomic_read(&bat_priv->fragmentation) &&
335 	    data_len + sizeof(*unicast_packet) >
336 				neigh_node->if_incoming->net_dev->mtu) {
337 		/* send frag skb decreases ttl */
338 		unicast_packet->header.ttl++;
339 		ret = frag_send_skb(skb, bat_priv,
340 				    neigh_node->if_incoming, neigh_node->addr);
341 		goto out;
342 	}
343 
344 	send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr);
345 	ret = 0;
346 	goto out;
347 
348 out:
349 	if (neigh_node)
350 		neigh_node_free_ref(neigh_node);
351 	if (orig_node)
352 		orig_node_free_ref(orig_node);
353 	if (ret == 1)
354 		kfree_skb(skb);
355 	return ret;
356 }
357