unicast.c 13.2 KB
Newer Older
1
/* Copyright (C) 2010-2012 B.A.T.M.A.N. contributors:
2 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
 *
 * Andreas Langer
 *
 * 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 "unicast.h"
#include "send.h"
#include "soft-interface.h"
#include "gateway_client.h"
#include "originator.h"
#include "hash.h"
#include "translation-table.h"
#include "routing.h"
#include "hard-interface.h"


32 33
static struct sk_buff *
batadv_frag_merge_packet(struct list_head *head,
34
			 struct batadv_frag_packet_list_entry *tfp,
35
			 struct sk_buff *skb)
36
{
37
	struct batadv_unicast_frag_packet *up;
38
	struct sk_buff *tmp_skb;
39
	struct batadv_unicast_packet *unicast_packet;
40 41
	int hdr_len = sizeof(*unicast_packet);
	int uni_diff = sizeof(*up) - hdr_len;
42
	uint8_t *packet_pos;
43

44
	up = (struct batadv_unicast_frag_packet *)skb->data;
45
	/* set skb to the first part and tmp_skb to the second part */
46
	if (up->flags & BATADV_UNI_FRAG_HEAD) {
47 48 49 50 51 52
		tmp_skb = tfp->skb;
	} else {
		tmp_skb = skb;
		skb = tfp->skb;
	}

53 54 55
	if (skb_linearize(skb) < 0 || skb_linearize(tmp_skb) < 0)
		goto err;

56
	skb_pull(tmp_skb, sizeof(*up));
57 58
	if (pskb_expand_head(skb, 0, tmp_skb->len, GFP_ATOMIC) < 0)
		goto err;
59 60 61 62 63 64 65 66 67 68

	/* move free entry to end */
	tfp->skb = NULL;
	tfp->seqno = 0;
	list_move_tail(&tfp->list, head);

	memcpy(skb_put(skb, tmp_skb->len), tmp_skb->data, tmp_skb->len);
	kfree_skb(tmp_skb);

	memmove(skb->data + uni_diff, skb->data, hdr_len);
69 70
	packet_pos = skb_pull(skb, uni_diff);
	unicast_packet = (struct batadv_unicast_packet *)packet_pos;
71
	unicast_packet->header.packet_type = BATADV_UNICAST;
72 73

	return skb;
74 75 76 77 78

err:
	/* free buffered skb, skb will be freed later */
	kfree_skb(tfp->skb);
	return NULL;
79 80
}

81 82
static void batadv_frag_create_entry(struct list_head *head,
				     struct sk_buff *skb)
83
{
84
	struct batadv_frag_packet_list_entry *tfp;
85 86 87
	struct batadv_unicast_frag_packet *up;

	up = (struct batadv_unicast_frag_packet *)skb->data;
88 89 90 91 92 93 94 95 96 97 98

	/* free and oldest packets stand at the end */
	tfp = list_entry((head)->prev, typeof(*tfp), list);
	kfree_skb(tfp->skb);

	tfp->seqno = ntohs(up->seqno);
	tfp->skb = skb;
	list_move(&tfp->list, head);
	return;
}

99
static int batadv_frag_create_buffer(struct list_head *head)
100 101
{
	int i;
102
	struct batadv_frag_packet_list_entry *tfp;
103

104
	for (i = 0; i < BATADV_FRAG_BUFFER_SIZE; i++) {
105
		tfp = kmalloc(sizeof(*tfp), GFP_ATOMIC);
106
		if (!tfp) {
107
			batadv_frag_list_free(head);
108 109 110 111 112 113 114 115 116 117 118
			return -ENOMEM;
		}
		tfp->skb = NULL;
		tfp->seqno = 0;
		INIT_LIST_HEAD(&tfp->list);
		list_add(&tfp->list, head);
	}

	return 0;
}

119
static struct batadv_frag_packet_list_entry *
120
batadv_frag_search_packet(struct list_head *head,
121
			  const struct batadv_unicast_frag_packet *up)
122
{
123
	struct batadv_frag_packet_list_entry *tfp;
124
	struct batadv_unicast_frag_packet *tmp_up = NULL;
125
	int is_head_tmp, is_head;
126 127
	uint16_t search_seqno;

128
	if (up->flags & BATADV_UNI_FRAG_HEAD)
129 130 131 132
		search_seqno = ntohs(up->seqno)+1;
	else
		search_seqno = ntohs(up->seqno)-1;

133 134
	is_head = !!(up->flags & BATADV_UNI_FRAG_HEAD);

135 136 137 138 139 140 141 142
	list_for_each_entry(tfp, head, list) {

		if (!tfp->skb)
			continue;

		if (tfp->seqno == ntohs(up->seqno))
			goto mov_tail;

143
		tmp_up = (struct batadv_unicast_frag_packet *)tfp->skb->data;
144 145

		if (tfp->seqno == search_seqno) {
146 147
			is_head_tmp = !!(tmp_up->flags & BATADV_UNI_FRAG_HEAD);
			if (is_head_tmp != is_head)
148 149 150 151 152 153 154 155 156 157 158 159
				return tfp;
			else
				goto mov_tail;
		}
	}
	return NULL;

mov_tail:
	list_move_tail(&tfp->list, head);
	return NULL;
}

160
void batadv_frag_list_free(struct list_head *head)
161
{
162
	struct batadv_frag_packet_list_entry *pf, *tmp_pf;
163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180

	if (!list_empty(head)) {

		list_for_each_entry_safe(pf, tmp_pf, head, list) {
			kfree_skb(pf->skb);
			list_del(&pf->list);
			kfree(pf);
		}
	}
	return;
}

/* frag_reassemble_skb():
 * returns NET_RX_DROP if the operation failed - skb is left intact
 * returns NET_RX_SUCCESS if the fragment was buffered (skb_new will be NULL)
 * or the skb could be reassembled (skb_new will point to the new packet and
 * skb was freed)
 */
181 182
int batadv_frag_reassemble_skb(struct sk_buff *skb,
			       struct batadv_priv *bat_priv,
183
			       struct sk_buff **new_skb)
184
{
185 186
	struct batadv_orig_node *orig_node;
	struct batadv_frag_packet_list_entry *tmp_frag_entry;
187
	int ret = NET_RX_DROP;
188
	struct batadv_unicast_frag_packet *unicast_packet;
189

190
	unicast_packet = (struct batadv_unicast_frag_packet *)skb->data;
191 192
	*new_skb = NULL;

193
	orig_node = batadv_orig_hash_find(bat_priv, unicast_packet->orig);
194
	if (!orig_node)
195 196 197 198 199
		goto out;

	orig_node->last_frag_packet = jiffies;

	if (list_empty(&orig_node->frag_list) &&
200
	    batadv_frag_create_buffer(&orig_node->frag_list)) {
201 202 203 204
		pr_debug("couldn't create frag buffer\n");
		goto out;
	}

205 206
	tmp_frag_entry = batadv_frag_search_packet(&orig_node->frag_list,
						   unicast_packet);
207 208

	if (!tmp_frag_entry) {
209
		batadv_frag_create_entry(&orig_node->frag_list, skb);
210 211 212 213
		ret = NET_RX_SUCCESS;
		goto out;
	}

214 215
	*new_skb = batadv_frag_merge_packet(&orig_node->frag_list,
					    tmp_frag_entry, skb);
216 217 218 219
	/* if not, merge failed */
	if (*new_skb)
		ret = NET_RX_SUCCESS;

220 221
out:
	if (orig_node)
222
		batadv_orig_node_free_ref(orig_node);
223 224 225
	return ret;
}

226 227 228
int batadv_frag_send_skb(struct sk_buff *skb, struct batadv_priv *bat_priv,
			 struct batadv_hard_iface *hard_iface,
			 const uint8_t dstaddr[])
229
{
230
	struct batadv_unicast_packet tmp_uc, *unicast_packet;
231
	struct batadv_hard_iface *primary_if;
232
	struct sk_buff *frag_skb;
233
	struct batadv_unicast_frag_packet *frag1, *frag2;
234 235
	int uc_hdr_len = sizeof(*unicast_packet);
	int ucf_hdr_len = sizeof(*frag1);
236
	int data_len = skb->len - uc_hdr_len;
237
	int large_tail = 0, ret = NET_RX_DROP;
238
	uint16_t seqno;
239

240
	primary_if = batadv_primary_if_get_selected(bat_priv);
241
	if (!primary_if)
242 243
		goto dropped;

244 245 246
	frag_skb = dev_alloc_skb(data_len - (data_len / 2) + ucf_hdr_len);
	if (!frag_skb)
		goto dropped;
247
	skb_reserve(frag_skb, ucf_hdr_len);
248

249
	unicast_packet = (struct batadv_unicast_packet *)skb->data;
250
	memcpy(&tmp_uc, unicast_packet, uc_hdr_len);
251
	skb_split(skb, frag_skb, data_len / 2 + uc_hdr_len);
252

253 254
	if (batadv_skb_head_push(skb, ucf_hdr_len - uc_hdr_len) < 0 ||
	    batadv_skb_head_push(frag_skb, ucf_hdr_len) < 0)
255 256
		goto drop_frag;

257 258
	frag1 = (struct batadv_unicast_frag_packet *)skb->data;
	frag2 = (struct batadv_unicast_frag_packet *)frag_skb->data;
259

260
	memcpy(frag1, &tmp_uc, sizeof(tmp_uc));
261

262
	frag1->header.ttl--;
263
	frag1->header.version = BATADV_COMPAT_VERSION;
264
	frag1->header.packet_type = BATADV_UNICAST_FRAG;
265

266
	memcpy(frag1->orig, primary_if->net_dev->dev_addr, ETH_ALEN);
267
	memcpy(frag2, frag1, sizeof(*frag2));
268

269
	if (data_len & 1)
270
		large_tail = BATADV_UNI_FRAG_LARGETAIL;
271

272
	frag1->flags = BATADV_UNI_FRAG_HEAD | large_tail;
273
	frag2->flags = large_tail;
274

275
	seqno = atomic_add_return(2, &hard_iface->frag_seqno);
276 277
	frag1->seqno = htons(seqno - 1);
	frag2->seqno = htons(seqno);
278

279 280
	batadv_send_skb_packet(skb, hard_iface, dstaddr);
	batadv_send_skb_packet(frag_skb, hard_iface, dstaddr);
281 282
	ret = NET_RX_SUCCESS;
	goto out;
283 284 285 286 287

drop_frag:
	kfree_skb(frag_skb);
dropped:
	kfree_skb(skb);
288 289
out:
	if (primary_if)
290
		batadv_hardif_free_ref(primary_if);
291
	return ret;
292 293
}

294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398
/**
 * batadv_unicast_push_and_fill_skb - extends the buffer and initializes the
 * common fields for unicast packets
 * @skb: packet
 * @hdr_size: amount of bytes to push at the beginning of the skb
 * @orig_node: the destination node
 *
 * Returns false if the buffer extension was not possible or true otherwise
 */
static bool batadv_unicast_push_and_fill_skb(struct sk_buff *skb, int hdr_size,
					     struct batadv_orig_node *orig_node)
{
	struct batadv_unicast_packet *unicast_packet;
	uint8_t ttvn = (uint8_t)atomic_read(&orig_node->last_ttvn);

	if (batadv_skb_head_push(skb, hdr_size) < 0)
		return false;

	unicast_packet = (struct batadv_unicast_packet *)skb->data;
	unicast_packet->header.version = BATADV_COMPAT_VERSION;
	/* batman packet type: unicast */
	unicast_packet->header.packet_type = BATADV_UNICAST;
	/* set unicast ttl */
	unicast_packet->header.ttl = BATADV_TTL;
	/* copy the destination for faster routing */
	memcpy(unicast_packet->dest, orig_node->orig, ETH_ALEN);
	/* set the destination tt version number */
	unicast_packet->ttvn = ttvn;

	return true;
}

/**
 * batadv_unicast_prepare_skb - encapsulate an skb with a unicast header
 * @skb: the skb containing the payload to encapsulate
 * @orig_node: the destination node
 *
 * Returns false if the payload could not be encapsulated or true otherwise
 */
static bool batadv_unicast_prepare_skb(struct sk_buff *skb,
				       struct batadv_orig_node *orig_node)
{
	size_t uni_size = sizeof(struct batadv_unicast_packet);
	return batadv_unicast_push_and_fill_skb(skb, uni_size, orig_node);
}

/**
 * batadv_unicast_4addr_prepare_skb - encapsulate an skb with a unicast4addr
 * header
 * @bat_priv: the bat priv with all the soft interface information
 * @skb: the skb containing the payload to encapsulate
 * @orig_node: the destination node
 * @packet_subtype: the batman 4addr packet subtype to use
 *
 * Returns false if the payload could not be encapsulated or true otherwise
 */
static bool batadv_unicast_4addr_prepare_skb(struct batadv_priv *bat_priv,
					     struct sk_buff *skb,
					     struct batadv_orig_node *orig,
					     int packet_subtype)
{
	struct batadv_hard_iface *primary_if;
	struct batadv_unicast_4addr_packet *unicast_4addr_packet;
	bool ret = false;

	primary_if = batadv_primary_if_get_selected(bat_priv);
	if (!primary_if)
		goto out;

	/* pull the header space and fill the unicast_packet substructure.
	 * We can do that because the first member of the unicast_4addr_packet
	 * is of type struct unicast_packet
	 */
	if (!batadv_unicast_push_and_fill_skb(skb,
					      sizeof(*unicast_4addr_packet),
					      orig))
		goto out;

	unicast_4addr_packet = (struct batadv_unicast_4addr_packet *)skb->data;
	unicast_4addr_packet->u.header.packet_type = BATADV_UNICAST_4ADDR;
	memcpy(unicast_4addr_packet->src, primary_if->net_dev->dev_addr,
	       ETH_ALEN);
	unicast_4addr_packet->subtype = packet_subtype;
	unicast_4addr_packet->reserved = 0;

	ret = true;
out:
	if (primary_if)
		batadv_hardif_free_ref(primary_if);
	return ret;
}

/**
 * batadv_unicast_generic_send_skb - send an skb as unicast
 * @bat_priv: the bat priv with all the soft interface information
 * @skb: payload to send
 * @packet_type: the batman unicast packet type to use
 * @packet_subtype: the batman packet subtype. It is ignored if packet_type is
 *		    not BATADV_UNICAT_4ADDR
 *
 * Returns 1 in case of error or 0 otherwise
 */
int batadv_unicast_generic_send_skb(struct batadv_priv *bat_priv,
				    struct sk_buff *skb, int packet_type,
				    int packet_subtype)
399 400
{
	struct ethhdr *ethhdr = (struct ethhdr *)skb->data;
401
	struct batadv_unicast_packet *unicast_packet;
402 403
	struct batadv_orig_node *orig_node;
	struct batadv_neigh_node *neigh_node;
404
	int data_len = skb->len;
405
	int ret = 1;
406
	unsigned int dev_mtu;
407 408

	/* get routing information */
409
	if (is_multicast_ether_addr(ethhdr->h_dest)) {
410
		orig_node = batadv_gw_get_selected_orig(bat_priv);
411
		if (orig_node)
412 413
			goto find_router;
	}
414

415
	/* check for tt host - increases orig_node refcount.
416 417
	 * returns NULL in case of AP isolation
	 */
418 419
	orig_node = batadv_transtable_search(bat_priv, ethhdr->h_source,
					     ethhdr->h_dest);
420

421
find_router:
422
	/* find_router():
423 424 425
	 *  - if orig_node is NULL it returns NULL
	 *  - increases neigh_nodes refcount if found.
	 */
426
	neigh_node = batadv_find_router(bat_priv, orig_node, NULL);
427

428
	if (!neigh_node)
429
		goto out;
430

431 432 433 434 435 436 437 438 439 440 441 442
	switch (packet_type) {
	case BATADV_UNICAST:
		batadv_unicast_prepare_skb(skb, orig_node);
		break;
	case BATADV_UNICAST_4ADDR:
		batadv_unicast_4addr_prepare_skb(bat_priv, skb, orig_node,
						 packet_subtype);
		break;
	default:
		/* this function supports UNICAST and UNICAST_4ADDR only. It
		 * should never be invoked with any other packet type
		 */
443
		goto out;
444
	}
445

446
	unicast_packet = (struct batadv_unicast_packet *)skb->data;
447

448 449 450 451 452
	/* inform the destination node that we are still missing a correct route
	 * for this client. The destination will receive this packet and will
	 * try to reroute it because the ttvn contained in the header is less
	 * than the current one
	 */
453
	if (batadv_tt_global_client_is_roaming(bat_priv, ethhdr->h_dest))
454 455
		unicast_packet->ttvn = unicast_packet->ttvn - 1;

456
	dev_mtu = neigh_node->if_incoming->net_dev->mtu;
457 458 459
	/* fragmentation mechanism only works for UNICAST (now) */
	if (packet_type == BATADV_UNICAST &&
	    atomic_read(&bat_priv->fragmentation) &&
460
	    data_len + sizeof(*unicast_packet) > dev_mtu) {
461
		/* send frag skb decreases ttl */
462
		unicast_packet->header.ttl++;
463 464 465
		ret = batadv_frag_send_skb(skb, bat_priv,
					   neigh_node->if_incoming,
					   neigh_node->addr);
466
		goto out;
467 468
	}

469
	batadv_send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr);
470
	ret = 0;
471

472 473
out:
	if (neigh_node)
474
		batadv_neigh_node_free_ref(neigh_node);
475
	if (orig_node)
476
		batadv_orig_node_free_ref(orig_node);
477 478 479
	if (ret == 1)
		kfree_skb(skb);
	return ret;
480
}