0001
0002
0003
0004
0005
0006
0007 #include "main.h"
0008
0009 #include <linux/byteorder/generic.h>
0010 #include <linux/container_of.h>
0011 #include <linux/etherdevice.h>
0012 #include <linux/gfp.h>
0013 #include <linux/if_ether.h>
0014 #include <linux/kref.h>
0015 #include <linux/list.h>
0016 #include <linux/lockdep.h>
0017 #include <linux/netdevice.h>
0018 #include <linux/pkt_sched.h>
0019 #include <linux/rculist.h>
0020 #include <linux/rcupdate.h>
0021 #include <linux/skbuff.h>
0022 #include <linux/slab.h>
0023 #include <linux/spinlock.h>
0024 #include <linux/stddef.h>
0025 #include <linux/string.h>
0026 #include <linux/types.h>
0027 #include <uapi/linux/batadv_packet.h>
0028
0029 #include "originator.h"
0030 #include "send.h"
0031 #include "tvlv.h"
0032
0033
0034
0035
0036
0037
0038 static void batadv_tvlv_handler_release(struct kref *ref)
0039 {
0040 struct batadv_tvlv_handler *tvlv_handler;
0041
0042 tvlv_handler = container_of(ref, struct batadv_tvlv_handler, refcount);
0043 kfree_rcu(tvlv_handler, rcu);
0044 }
0045
0046
0047
0048
0049
0050
0051 static void batadv_tvlv_handler_put(struct batadv_tvlv_handler *tvlv_handler)
0052 {
0053 if (!tvlv_handler)
0054 return;
0055
0056 kref_put(&tvlv_handler->refcount, batadv_tvlv_handler_release);
0057 }
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068 static struct batadv_tvlv_handler *
0069 batadv_tvlv_handler_get(struct batadv_priv *bat_priv, u8 type, u8 version)
0070 {
0071 struct batadv_tvlv_handler *tvlv_handler_tmp, *tvlv_handler = NULL;
0072
0073 rcu_read_lock();
0074 hlist_for_each_entry_rcu(tvlv_handler_tmp,
0075 &bat_priv->tvlv.handler_list, list) {
0076 if (tvlv_handler_tmp->type != type)
0077 continue;
0078
0079 if (tvlv_handler_tmp->version != version)
0080 continue;
0081
0082 if (!kref_get_unless_zero(&tvlv_handler_tmp->refcount))
0083 continue;
0084
0085 tvlv_handler = tvlv_handler_tmp;
0086 break;
0087 }
0088 rcu_read_unlock();
0089
0090 return tvlv_handler;
0091 }
0092
0093
0094
0095
0096
0097 static void batadv_tvlv_container_release(struct kref *ref)
0098 {
0099 struct batadv_tvlv_container *tvlv;
0100
0101 tvlv = container_of(ref, struct batadv_tvlv_container, refcount);
0102 kfree(tvlv);
0103 }
0104
0105
0106
0107
0108
0109
0110 static void batadv_tvlv_container_put(struct batadv_tvlv_container *tvlv)
0111 {
0112 if (!tvlv)
0113 return;
0114
0115 kref_put(&tvlv->refcount, batadv_tvlv_container_release);
0116 }
0117
0118
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130 static struct batadv_tvlv_container *
0131 batadv_tvlv_container_get(struct batadv_priv *bat_priv, u8 type, u8 version)
0132 {
0133 struct batadv_tvlv_container *tvlv_tmp, *tvlv = NULL;
0134
0135 lockdep_assert_held(&bat_priv->tvlv.container_list_lock);
0136
0137 hlist_for_each_entry(tvlv_tmp, &bat_priv->tvlv.container_list, list) {
0138 if (tvlv_tmp->tvlv_hdr.type != type)
0139 continue;
0140
0141 if (tvlv_tmp->tvlv_hdr.version != version)
0142 continue;
0143
0144 kref_get(&tvlv_tmp->refcount);
0145 tvlv = tvlv_tmp;
0146 break;
0147 }
0148
0149 return tvlv;
0150 }
0151
0152
0153
0154
0155
0156
0157
0158
0159
0160
0161
0162 static u16 batadv_tvlv_container_list_size(struct batadv_priv *bat_priv)
0163 {
0164 struct batadv_tvlv_container *tvlv;
0165 u16 tvlv_len = 0;
0166
0167 lockdep_assert_held(&bat_priv->tvlv.container_list_lock);
0168
0169 hlist_for_each_entry(tvlv, &bat_priv->tvlv.container_list, list) {
0170 tvlv_len += sizeof(struct batadv_tvlv_hdr);
0171 tvlv_len += ntohs(tvlv->tvlv_hdr.len);
0172 }
0173
0174 return tvlv_len;
0175 }
0176
0177
0178
0179
0180
0181
0182
0183
0184
0185
0186 static void batadv_tvlv_container_remove(struct batadv_priv *bat_priv,
0187 struct batadv_tvlv_container *tvlv)
0188 {
0189 lockdep_assert_held(&bat_priv->tvlv.container_list_lock);
0190
0191 if (!tvlv)
0192 return;
0193
0194 hlist_del(&tvlv->list);
0195
0196
0197 batadv_tvlv_container_put(tvlv);
0198 batadv_tvlv_container_put(tvlv);
0199 }
0200
0201
0202
0203
0204
0205
0206
0207
0208 void batadv_tvlv_container_unregister(struct batadv_priv *bat_priv,
0209 u8 type, u8 version)
0210 {
0211 struct batadv_tvlv_container *tvlv;
0212
0213 spin_lock_bh(&bat_priv->tvlv.container_list_lock);
0214 tvlv = batadv_tvlv_container_get(bat_priv, type, version);
0215 batadv_tvlv_container_remove(bat_priv, tvlv);
0216 spin_unlock_bh(&bat_priv->tvlv.container_list_lock);
0217 }
0218
0219
0220
0221
0222
0223
0224
0225
0226
0227
0228
0229
0230
0231 void batadv_tvlv_container_register(struct batadv_priv *bat_priv,
0232 u8 type, u8 version,
0233 void *tvlv_value, u16 tvlv_value_len)
0234 {
0235 struct batadv_tvlv_container *tvlv_old, *tvlv_new;
0236
0237 if (!tvlv_value)
0238 tvlv_value_len = 0;
0239
0240 tvlv_new = kzalloc(sizeof(*tvlv_new) + tvlv_value_len, GFP_ATOMIC);
0241 if (!tvlv_new)
0242 return;
0243
0244 tvlv_new->tvlv_hdr.version = version;
0245 tvlv_new->tvlv_hdr.type = type;
0246 tvlv_new->tvlv_hdr.len = htons(tvlv_value_len);
0247
0248 memcpy(tvlv_new + 1, tvlv_value, ntohs(tvlv_new->tvlv_hdr.len));
0249 INIT_HLIST_NODE(&tvlv_new->list);
0250 kref_init(&tvlv_new->refcount);
0251
0252 spin_lock_bh(&bat_priv->tvlv.container_list_lock);
0253 tvlv_old = batadv_tvlv_container_get(bat_priv, type, version);
0254 batadv_tvlv_container_remove(bat_priv, tvlv_old);
0255
0256 kref_get(&tvlv_new->refcount);
0257 hlist_add_head(&tvlv_new->list, &bat_priv->tvlv.container_list);
0258 spin_unlock_bh(&bat_priv->tvlv.container_list_lock);
0259
0260
0261 batadv_tvlv_container_put(tvlv_new);
0262 }
0263
0264
0265
0266
0267
0268
0269
0270
0271
0272
0273
0274
0275
0276 static bool batadv_tvlv_realloc_packet_buff(unsigned char **packet_buff,
0277 int *packet_buff_len,
0278 int min_packet_len,
0279 int additional_packet_len)
0280 {
0281 unsigned char *new_buff;
0282
0283 new_buff = kmalloc(min_packet_len + additional_packet_len, GFP_ATOMIC);
0284
0285
0286 if (!new_buff)
0287 return false;
0288
0289 memcpy(new_buff, *packet_buff, min_packet_len);
0290 kfree(*packet_buff);
0291 *packet_buff = new_buff;
0292 *packet_buff_len = min_packet_len + additional_packet_len;
0293
0294 return true;
0295 }
0296
0297
0298
0299
0300
0301
0302
0303
0304
0305
0306
0307
0308
0309
0310
0311 u16 batadv_tvlv_container_ogm_append(struct batadv_priv *bat_priv,
0312 unsigned char **packet_buff,
0313 int *packet_buff_len, int packet_min_len)
0314 {
0315 struct batadv_tvlv_container *tvlv;
0316 struct batadv_tvlv_hdr *tvlv_hdr;
0317 u16 tvlv_value_len;
0318 void *tvlv_value;
0319 bool ret;
0320
0321 spin_lock_bh(&bat_priv->tvlv.container_list_lock);
0322 tvlv_value_len = batadv_tvlv_container_list_size(bat_priv);
0323
0324 ret = batadv_tvlv_realloc_packet_buff(packet_buff, packet_buff_len,
0325 packet_min_len, tvlv_value_len);
0326
0327 if (!ret)
0328 goto end;
0329
0330 if (!tvlv_value_len)
0331 goto end;
0332
0333 tvlv_value = (*packet_buff) + packet_min_len;
0334
0335 hlist_for_each_entry(tvlv, &bat_priv->tvlv.container_list, list) {
0336 tvlv_hdr = tvlv_value;
0337 tvlv_hdr->type = tvlv->tvlv_hdr.type;
0338 tvlv_hdr->version = tvlv->tvlv_hdr.version;
0339 tvlv_hdr->len = tvlv->tvlv_hdr.len;
0340 tvlv_value = tvlv_hdr + 1;
0341 memcpy(tvlv_value, tvlv + 1, ntohs(tvlv->tvlv_hdr.len));
0342 tvlv_value = (u8 *)tvlv_value + ntohs(tvlv->tvlv_hdr.len);
0343 }
0344
0345 end:
0346 spin_unlock_bh(&bat_priv->tvlv.container_list_lock);
0347 return tvlv_value_len;
0348 }
0349
0350
0351
0352
0353
0354
0355
0356
0357
0358
0359
0360
0361
0362
0363
0364
0365 static int batadv_tvlv_call_handler(struct batadv_priv *bat_priv,
0366 struct batadv_tvlv_handler *tvlv_handler,
0367 bool ogm_source,
0368 struct batadv_orig_node *orig_node,
0369 u8 *src, u8 *dst,
0370 void *tvlv_value, u16 tvlv_value_len)
0371 {
0372 if (!tvlv_handler)
0373 return NET_RX_SUCCESS;
0374
0375 if (ogm_source) {
0376 if (!tvlv_handler->ogm_handler)
0377 return NET_RX_SUCCESS;
0378
0379 if (!orig_node)
0380 return NET_RX_SUCCESS;
0381
0382 tvlv_handler->ogm_handler(bat_priv, orig_node,
0383 BATADV_NO_FLAGS,
0384 tvlv_value, tvlv_value_len);
0385 tvlv_handler->flags |= BATADV_TVLV_HANDLER_OGM_CALLED;
0386 } else {
0387 if (!src)
0388 return NET_RX_SUCCESS;
0389
0390 if (!dst)
0391 return NET_RX_SUCCESS;
0392
0393 if (!tvlv_handler->unicast_handler)
0394 return NET_RX_SUCCESS;
0395
0396 return tvlv_handler->unicast_handler(bat_priv, src,
0397 dst, tvlv_value,
0398 tvlv_value_len);
0399 }
0400
0401 return NET_RX_SUCCESS;
0402 }
0403
0404
0405
0406
0407
0408
0409
0410
0411
0412
0413
0414
0415
0416
0417
0418 int batadv_tvlv_containers_process(struct batadv_priv *bat_priv,
0419 bool ogm_source,
0420 struct batadv_orig_node *orig_node,
0421 u8 *src, u8 *dst,
0422 void *tvlv_value, u16 tvlv_value_len)
0423 {
0424 struct batadv_tvlv_handler *tvlv_handler;
0425 struct batadv_tvlv_hdr *tvlv_hdr;
0426 u16 tvlv_value_cont_len;
0427 u8 cifnotfound = BATADV_TVLV_HANDLER_OGM_CIFNOTFND;
0428 int ret = NET_RX_SUCCESS;
0429
0430 while (tvlv_value_len >= sizeof(*tvlv_hdr)) {
0431 tvlv_hdr = tvlv_value;
0432 tvlv_value_cont_len = ntohs(tvlv_hdr->len);
0433 tvlv_value = tvlv_hdr + 1;
0434 tvlv_value_len -= sizeof(*tvlv_hdr);
0435
0436 if (tvlv_value_cont_len > tvlv_value_len)
0437 break;
0438
0439 tvlv_handler = batadv_tvlv_handler_get(bat_priv,
0440 tvlv_hdr->type,
0441 tvlv_hdr->version);
0442
0443 ret |= batadv_tvlv_call_handler(bat_priv, tvlv_handler,
0444 ogm_source, orig_node,
0445 src, dst, tvlv_value,
0446 tvlv_value_cont_len);
0447 batadv_tvlv_handler_put(tvlv_handler);
0448 tvlv_value = (u8 *)tvlv_value + tvlv_value_cont_len;
0449 tvlv_value_len -= tvlv_value_cont_len;
0450 }
0451
0452 if (!ogm_source)
0453 return ret;
0454
0455 rcu_read_lock();
0456 hlist_for_each_entry_rcu(tvlv_handler,
0457 &bat_priv->tvlv.handler_list, list) {
0458 if ((tvlv_handler->flags & BATADV_TVLV_HANDLER_OGM_CIFNOTFND) &&
0459 !(tvlv_handler->flags & BATADV_TVLV_HANDLER_OGM_CALLED))
0460 tvlv_handler->ogm_handler(bat_priv, orig_node,
0461 cifnotfound, NULL, 0);
0462
0463 tvlv_handler->flags &= ~BATADV_TVLV_HANDLER_OGM_CALLED;
0464 }
0465 rcu_read_unlock();
0466
0467 return NET_RX_SUCCESS;
0468 }
0469
0470
0471
0472
0473
0474
0475
0476
0477 void batadv_tvlv_ogm_receive(struct batadv_priv *bat_priv,
0478 struct batadv_ogm_packet *batadv_ogm_packet,
0479 struct batadv_orig_node *orig_node)
0480 {
0481 void *tvlv_value;
0482 u16 tvlv_value_len;
0483
0484 if (!batadv_ogm_packet)
0485 return;
0486
0487 tvlv_value_len = ntohs(batadv_ogm_packet->tvlv_len);
0488 if (!tvlv_value_len)
0489 return;
0490
0491 tvlv_value = batadv_ogm_packet + 1;
0492
0493 batadv_tvlv_containers_process(bat_priv, true, orig_node, NULL, NULL,
0494 tvlv_value, tvlv_value_len);
0495 }
0496
0497
0498
0499
0500
0501
0502
0503
0504
0505
0506
0507
0508
0509
0510
0511 void batadv_tvlv_handler_register(struct batadv_priv *bat_priv,
0512 void (*optr)(struct batadv_priv *bat_priv,
0513 struct batadv_orig_node *orig,
0514 u8 flags,
0515 void *tvlv_value,
0516 u16 tvlv_value_len),
0517 int (*uptr)(struct batadv_priv *bat_priv,
0518 u8 *src, u8 *dst,
0519 void *tvlv_value,
0520 u16 tvlv_value_len),
0521 u8 type, u8 version, u8 flags)
0522 {
0523 struct batadv_tvlv_handler *tvlv_handler;
0524
0525 spin_lock_bh(&bat_priv->tvlv.handler_list_lock);
0526
0527 tvlv_handler = batadv_tvlv_handler_get(bat_priv, type, version);
0528 if (tvlv_handler) {
0529 spin_unlock_bh(&bat_priv->tvlv.handler_list_lock);
0530 batadv_tvlv_handler_put(tvlv_handler);
0531 return;
0532 }
0533
0534 tvlv_handler = kzalloc(sizeof(*tvlv_handler), GFP_ATOMIC);
0535 if (!tvlv_handler) {
0536 spin_unlock_bh(&bat_priv->tvlv.handler_list_lock);
0537 return;
0538 }
0539
0540 tvlv_handler->ogm_handler = optr;
0541 tvlv_handler->unicast_handler = uptr;
0542 tvlv_handler->type = type;
0543 tvlv_handler->version = version;
0544 tvlv_handler->flags = flags;
0545 kref_init(&tvlv_handler->refcount);
0546 INIT_HLIST_NODE(&tvlv_handler->list);
0547
0548 kref_get(&tvlv_handler->refcount);
0549 hlist_add_head_rcu(&tvlv_handler->list, &bat_priv->tvlv.handler_list);
0550 spin_unlock_bh(&bat_priv->tvlv.handler_list_lock);
0551
0552
0553 batadv_tvlv_handler_put(tvlv_handler);
0554 }
0555
0556
0557
0558
0559
0560
0561
0562
0563 void batadv_tvlv_handler_unregister(struct batadv_priv *bat_priv,
0564 u8 type, u8 version)
0565 {
0566 struct batadv_tvlv_handler *tvlv_handler;
0567
0568 tvlv_handler = batadv_tvlv_handler_get(bat_priv, type, version);
0569 if (!tvlv_handler)
0570 return;
0571
0572 batadv_tvlv_handler_put(tvlv_handler);
0573 spin_lock_bh(&bat_priv->tvlv.handler_list_lock);
0574 hlist_del_rcu(&tvlv_handler->list);
0575 spin_unlock_bh(&bat_priv->tvlv.handler_list_lock);
0576 batadv_tvlv_handler_put(tvlv_handler);
0577 }
0578
0579
0580
0581
0582
0583
0584
0585
0586
0587
0588
0589
0590 void batadv_tvlv_unicast_send(struct batadv_priv *bat_priv, const u8 *src,
0591 const u8 *dst, u8 type, u8 version,
0592 void *tvlv_value, u16 tvlv_value_len)
0593 {
0594 struct batadv_unicast_tvlv_packet *unicast_tvlv_packet;
0595 struct batadv_tvlv_hdr *tvlv_hdr;
0596 struct batadv_orig_node *orig_node;
0597 struct sk_buff *skb;
0598 unsigned char *tvlv_buff;
0599 unsigned int tvlv_len;
0600 ssize_t hdr_len = sizeof(*unicast_tvlv_packet);
0601
0602 orig_node = batadv_orig_hash_find(bat_priv, dst);
0603 if (!orig_node)
0604 return;
0605
0606 tvlv_len = sizeof(*tvlv_hdr) + tvlv_value_len;
0607
0608 skb = netdev_alloc_skb_ip_align(NULL, ETH_HLEN + hdr_len + tvlv_len);
0609 if (!skb)
0610 goto out;
0611
0612 skb->priority = TC_PRIO_CONTROL;
0613 skb_reserve(skb, ETH_HLEN);
0614 tvlv_buff = skb_put(skb, sizeof(*unicast_tvlv_packet) + tvlv_len);
0615 unicast_tvlv_packet = (struct batadv_unicast_tvlv_packet *)tvlv_buff;
0616 unicast_tvlv_packet->packet_type = BATADV_UNICAST_TVLV;
0617 unicast_tvlv_packet->version = BATADV_COMPAT_VERSION;
0618 unicast_tvlv_packet->ttl = BATADV_TTL;
0619 unicast_tvlv_packet->reserved = 0;
0620 unicast_tvlv_packet->tvlv_len = htons(tvlv_len);
0621 unicast_tvlv_packet->align = 0;
0622 ether_addr_copy(unicast_tvlv_packet->src, src);
0623 ether_addr_copy(unicast_tvlv_packet->dst, dst);
0624
0625 tvlv_buff = (unsigned char *)(unicast_tvlv_packet + 1);
0626 tvlv_hdr = (struct batadv_tvlv_hdr *)tvlv_buff;
0627 tvlv_hdr->version = version;
0628 tvlv_hdr->type = type;
0629 tvlv_hdr->len = htons(tvlv_value_len);
0630 tvlv_buff += sizeof(*tvlv_hdr);
0631 memcpy(tvlv_buff, tvlv_value, tvlv_value_len);
0632
0633 batadv_send_skb_to_orig(skb, orig_node, NULL);
0634 out:
0635 batadv_orig_node_put(orig_node);
0636 }