1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* Copyright (C) B.A.T.M.A.N. contributors: |
3 | * |
4 | * Antonio Quartulli |
5 | */ |
6 | |
7 | #include "distributed-arp-table.h" |
8 | #include "main.h" |
9 | |
10 | #include <asm/unaligned.h> |
11 | #include <linux/atomic.h> |
12 | #include <linux/bitops.h> |
13 | #include <linux/byteorder/generic.h> |
14 | #include <linux/container_of.h> |
15 | #include <linux/errno.h> |
16 | #include <linux/etherdevice.h> |
17 | #include <linux/gfp.h> |
18 | #include <linux/if_arp.h> |
19 | #include <linux/if_ether.h> |
20 | #include <linux/if_vlan.h> |
21 | #include <linux/in.h> |
22 | #include <linux/ip.h> |
23 | #include <linux/jiffies.h> |
24 | #include <linux/kref.h> |
25 | #include <linux/list.h> |
26 | #include <linux/netlink.h> |
27 | #include <linux/rculist.h> |
28 | #include <linux/rcupdate.h> |
29 | #include <linux/skbuff.h> |
30 | #include <linux/slab.h> |
31 | #include <linux/spinlock.h> |
32 | #include <linux/stddef.h> |
33 | #include <linux/string.h> |
34 | #include <linux/udp.h> |
35 | #include <linux/workqueue.h> |
36 | #include <net/arp.h> |
37 | #include <net/genetlink.h> |
38 | #include <net/netlink.h> |
39 | #include <net/sock.h> |
40 | #include <uapi/linux/batman_adv.h> |
41 | |
42 | #include "bridge_loop_avoidance.h" |
43 | #include "hard-interface.h" |
44 | #include "hash.h" |
45 | #include "log.h" |
46 | #include "netlink.h" |
47 | #include "originator.h" |
48 | #include "send.h" |
49 | #include "soft-interface.h" |
50 | #include "translation-table.h" |
51 | #include "tvlv.h" |
52 | |
53 | enum batadv_bootpop { |
54 | BATADV_BOOTREPLY = 2, |
55 | }; |
56 | |
57 | enum batadv_boothtype { |
58 | BATADV_HTYPE_ETHERNET = 1, |
59 | }; |
60 | |
61 | enum batadv_dhcpoptioncode { |
62 | BATADV_DHCP_OPT_PAD = 0, |
63 | BATADV_DHCP_OPT_MSG_TYPE = 53, |
64 | BATADV_DHCP_OPT_END = 255, |
65 | }; |
66 | |
67 | enum batadv_dhcptype { |
68 | BATADV_DHCPACK = 5, |
69 | }; |
70 | |
71 | /* { 99, 130, 83, 99 } */ |
72 | #define BATADV_DHCP_MAGIC 1669485411 |
73 | |
74 | struct batadv_dhcp_packet { |
75 | __u8 op; |
76 | __u8 htype; |
77 | __u8 hlen; |
78 | __u8 hops; |
79 | __be32 xid; |
80 | __be16 secs; |
81 | __be16 flags; |
82 | __be32 ciaddr; |
83 | __be32 yiaddr; |
84 | __be32 siaddr; |
85 | __be32 giaddr; |
86 | __u8 chaddr[16]; |
87 | __u8 sname[64]; |
88 | __u8 file[128]; |
89 | __be32 magic; |
90 | /* __u8 options[]; */ |
91 | }; |
92 | |
93 | #define BATADV_DHCP_YIADDR_LEN sizeof(((struct batadv_dhcp_packet *)0)->yiaddr) |
94 | #define BATADV_DHCP_CHADDR_LEN sizeof(((struct batadv_dhcp_packet *)0)->chaddr) |
95 | |
96 | static void batadv_dat_purge(struct work_struct *work); |
97 | |
98 | /** |
99 | * batadv_dat_start_timer() - initialise the DAT periodic worker |
100 | * @bat_priv: the bat priv with all the soft interface information |
101 | */ |
102 | static void batadv_dat_start_timer(struct batadv_priv *bat_priv) |
103 | { |
104 | queue_delayed_work(wq: batadv_event_workqueue, dwork: &bat_priv->dat.work, |
105 | delay: msecs_to_jiffies(m: 10000)); |
106 | } |
107 | |
108 | /** |
109 | * batadv_dat_entry_release() - release dat_entry from lists and queue for free |
110 | * after rcu grace period |
111 | * @ref: kref pointer of the dat_entry |
112 | */ |
113 | static void batadv_dat_entry_release(struct kref *ref) |
114 | { |
115 | struct batadv_dat_entry *dat_entry; |
116 | |
117 | dat_entry = container_of(ref, struct batadv_dat_entry, refcount); |
118 | |
119 | kfree_rcu(dat_entry, rcu); |
120 | } |
121 | |
122 | /** |
123 | * batadv_dat_entry_put() - decrement the dat_entry refcounter and possibly |
124 | * release it |
125 | * @dat_entry: dat_entry to be free'd |
126 | */ |
127 | static void batadv_dat_entry_put(struct batadv_dat_entry *dat_entry) |
128 | { |
129 | if (!dat_entry) |
130 | return; |
131 | |
132 | kref_put(kref: &dat_entry->refcount, release: batadv_dat_entry_release); |
133 | } |
134 | |
135 | /** |
136 | * batadv_dat_to_purge() - check whether a dat_entry has to be purged or not |
137 | * @dat_entry: the entry to check |
138 | * |
139 | * Return: true if the entry has to be purged now, false otherwise. |
140 | */ |
141 | static bool batadv_dat_to_purge(struct batadv_dat_entry *dat_entry) |
142 | { |
143 | return batadv_has_timed_out(timestamp: dat_entry->last_update, |
144 | BATADV_DAT_ENTRY_TIMEOUT); |
145 | } |
146 | |
147 | /** |
148 | * __batadv_dat_purge() - delete entries from the DAT local storage |
149 | * @bat_priv: the bat priv with all the soft interface information |
150 | * @to_purge: function in charge to decide whether an entry has to be purged or |
151 | * not. This function takes the dat_entry as argument and has to |
152 | * returns a boolean value: true is the entry has to be deleted, |
153 | * false otherwise |
154 | * |
155 | * Loops over each entry in the DAT local storage and deletes it if and only if |
156 | * the to_purge function passed as argument returns true. |
157 | */ |
158 | static void __batadv_dat_purge(struct batadv_priv *bat_priv, |
159 | bool (*to_purge)(struct batadv_dat_entry *)) |
160 | { |
161 | spinlock_t *list_lock; /* protects write access to the hash lists */ |
162 | struct batadv_dat_entry *dat_entry; |
163 | struct hlist_node *node_tmp; |
164 | struct hlist_head *head; |
165 | u32 i; |
166 | |
167 | if (!bat_priv->dat.hash) |
168 | return; |
169 | |
170 | for (i = 0; i < bat_priv->dat.hash->size; i++) { |
171 | head = &bat_priv->dat.hash->table[i]; |
172 | list_lock = &bat_priv->dat.hash->list_locks[i]; |
173 | |
174 | spin_lock_bh(lock: list_lock); |
175 | hlist_for_each_entry_safe(dat_entry, node_tmp, head, |
176 | hash_entry) { |
177 | /* if a helper function has been passed as parameter, |
178 | * ask it if the entry has to be purged or not |
179 | */ |
180 | if (to_purge && !to_purge(dat_entry)) |
181 | continue; |
182 | |
183 | hlist_del_rcu(n: &dat_entry->hash_entry); |
184 | batadv_dat_entry_put(dat_entry); |
185 | } |
186 | spin_unlock_bh(lock: list_lock); |
187 | } |
188 | } |
189 | |
190 | /** |
191 | * batadv_dat_purge() - periodic task that deletes old entries from the local |
192 | * DAT hash table |
193 | * @work: kernel work struct |
194 | */ |
195 | static void batadv_dat_purge(struct work_struct *work) |
196 | { |
197 | struct delayed_work *delayed_work; |
198 | struct batadv_priv_dat *priv_dat; |
199 | struct batadv_priv *bat_priv; |
200 | |
201 | delayed_work = to_delayed_work(work); |
202 | priv_dat = container_of(delayed_work, struct batadv_priv_dat, work); |
203 | bat_priv = container_of(priv_dat, struct batadv_priv, dat); |
204 | |
205 | __batadv_dat_purge(bat_priv, to_purge: batadv_dat_to_purge); |
206 | batadv_dat_start_timer(bat_priv); |
207 | } |
208 | |
209 | /** |
210 | * batadv_compare_dat() - comparing function used in the local DAT hash table |
211 | * @node: node in the local table |
212 | * @data2: second object to compare the node to |
213 | * |
214 | * Return: true if the two entries are the same, false otherwise. |
215 | */ |
216 | static bool batadv_compare_dat(const struct hlist_node *node, const void *data2) |
217 | { |
218 | const void *data1 = container_of(node, struct batadv_dat_entry, |
219 | hash_entry); |
220 | |
221 | return memcmp(p: data1, q: data2, size: sizeof(__be32)) == 0; |
222 | } |
223 | |
224 | /** |
225 | * batadv_arp_hw_src() - extract the hw_src field from an ARP packet |
226 | * @skb: ARP packet |
227 | * @hdr_size: size of the possible header before the ARP packet |
228 | * |
229 | * Return: the value of the hw_src field in the ARP packet. |
230 | */ |
231 | static u8 *batadv_arp_hw_src(struct sk_buff *skb, int hdr_size) |
232 | { |
233 | u8 *addr; |
234 | |
235 | addr = (u8 *)(skb->data + hdr_size); |
236 | addr += ETH_HLEN + sizeof(struct arphdr); |
237 | |
238 | return addr; |
239 | } |
240 | |
241 | /** |
242 | * batadv_arp_ip_src() - extract the ip_src field from an ARP packet |
243 | * @skb: ARP packet |
244 | * @hdr_size: size of the possible header before the ARP packet |
245 | * |
246 | * Return: the value of the ip_src field in the ARP packet. |
247 | */ |
248 | static __be32 batadv_arp_ip_src(struct sk_buff *skb, int hdr_size) |
249 | { |
250 | return *(__force __be32 *)(batadv_arp_hw_src(skb, hdr_size) + ETH_ALEN); |
251 | } |
252 | |
253 | /** |
254 | * batadv_arp_hw_dst() - extract the hw_dst field from an ARP packet |
255 | * @skb: ARP packet |
256 | * @hdr_size: size of the possible header before the ARP packet |
257 | * |
258 | * Return: the value of the hw_dst field in the ARP packet. |
259 | */ |
260 | static u8 *batadv_arp_hw_dst(struct sk_buff *skb, int hdr_size) |
261 | { |
262 | return batadv_arp_hw_src(skb, hdr_size) + ETH_ALEN + 4; |
263 | } |
264 | |
265 | /** |
266 | * batadv_arp_ip_dst() - extract the ip_dst field from an ARP packet |
267 | * @skb: ARP packet |
268 | * @hdr_size: size of the possible header before the ARP packet |
269 | * |
270 | * Return: the value of the ip_dst field in the ARP packet. |
271 | */ |
272 | static __be32 batadv_arp_ip_dst(struct sk_buff *skb, int hdr_size) |
273 | { |
274 | u8 *dst = batadv_arp_hw_src(skb, hdr_size) + ETH_ALEN * 2 + 4; |
275 | |
276 | return *(__force __be32 *)dst; |
277 | } |
278 | |
279 | /** |
280 | * batadv_hash_dat() - compute the hash value for an IP address |
281 | * @data: data to hash |
282 | * @size: size of the hash table |
283 | * |
284 | * Return: the selected index in the hash table for the given data. |
285 | */ |
286 | static u32 batadv_hash_dat(const void *data, u32 size) |
287 | { |
288 | u32 hash = 0; |
289 | const struct batadv_dat_entry *dat = data; |
290 | const unsigned char *key; |
291 | __be16 vid; |
292 | u32 i; |
293 | |
294 | key = (__force const unsigned char *)&dat->ip; |
295 | for (i = 0; i < sizeof(dat->ip); i++) { |
296 | hash += key[i]; |
297 | hash += (hash << 10); |
298 | hash ^= (hash >> 6); |
299 | } |
300 | |
301 | vid = htons(dat->vid); |
302 | key = (__force const unsigned char *)&vid; |
303 | for (i = 0; i < sizeof(dat->vid); i++) { |
304 | hash += key[i]; |
305 | hash += (hash << 10); |
306 | hash ^= (hash >> 6); |
307 | } |
308 | |
309 | hash += (hash << 3); |
310 | hash ^= (hash >> 11); |
311 | hash += (hash << 15); |
312 | |
313 | return hash % size; |
314 | } |
315 | |
316 | /** |
317 | * batadv_dat_entry_hash_find() - look for a given dat_entry in the local hash |
318 | * table |
319 | * @bat_priv: the bat priv with all the soft interface information |
320 | * @ip: search key |
321 | * @vid: VLAN identifier |
322 | * |
323 | * Return: the dat_entry if found, NULL otherwise. |
324 | */ |
325 | static struct batadv_dat_entry * |
326 | batadv_dat_entry_hash_find(struct batadv_priv *bat_priv, __be32 ip, |
327 | unsigned short vid) |
328 | { |
329 | struct hlist_head *head; |
330 | struct batadv_dat_entry to_find, *dat_entry, *dat_entry_tmp = NULL; |
331 | struct batadv_hashtable *hash = bat_priv->dat.hash; |
332 | u32 index; |
333 | |
334 | if (!hash) |
335 | return NULL; |
336 | |
337 | to_find.ip = ip; |
338 | to_find.vid = vid; |
339 | |
340 | index = batadv_hash_dat(data: &to_find, size: hash->size); |
341 | head = &hash->table[index]; |
342 | |
343 | rcu_read_lock(); |
344 | hlist_for_each_entry_rcu(dat_entry, head, hash_entry) { |
345 | if (dat_entry->ip != ip) |
346 | continue; |
347 | |
348 | if (!kref_get_unless_zero(kref: &dat_entry->refcount)) |
349 | continue; |
350 | |
351 | dat_entry_tmp = dat_entry; |
352 | break; |
353 | } |
354 | rcu_read_unlock(); |
355 | |
356 | return dat_entry_tmp; |
357 | } |
358 | |
359 | /** |
360 | * batadv_dat_entry_add() - add a new dat entry or update it if already exists |
361 | * @bat_priv: the bat priv with all the soft interface information |
362 | * @ip: ipv4 to add/edit |
363 | * @mac_addr: mac address to assign to the given ipv4 |
364 | * @vid: VLAN identifier |
365 | */ |
366 | static void batadv_dat_entry_add(struct batadv_priv *bat_priv, __be32 ip, |
367 | u8 *mac_addr, unsigned short vid) |
368 | { |
369 | struct batadv_dat_entry *dat_entry; |
370 | int hash_added; |
371 | |
372 | dat_entry = batadv_dat_entry_hash_find(bat_priv, ip, vid); |
373 | /* if this entry is already known, just update it */ |
374 | if (dat_entry) { |
375 | if (!batadv_compare_eth(data1: dat_entry->mac_addr, data2: mac_addr)) |
376 | ether_addr_copy(dst: dat_entry->mac_addr, src: mac_addr); |
377 | dat_entry->last_update = jiffies; |
378 | batadv_dbg(BATADV_DBG_DAT, bat_priv, |
379 | "Entry updated: %pI4 %pM (vid: %d)\n" , |
380 | &dat_entry->ip, dat_entry->mac_addr, |
381 | batadv_print_vid(vid)); |
382 | goto out; |
383 | } |
384 | |
385 | dat_entry = kmalloc(size: sizeof(*dat_entry), GFP_ATOMIC); |
386 | if (!dat_entry) |
387 | goto out; |
388 | |
389 | dat_entry->ip = ip; |
390 | dat_entry->vid = vid; |
391 | ether_addr_copy(dst: dat_entry->mac_addr, src: mac_addr); |
392 | dat_entry->last_update = jiffies; |
393 | kref_init(kref: &dat_entry->refcount); |
394 | |
395 | kref_get(kref: &dat_entry->refcount); |
396 | hash_added = batadv_hash_add(hash: bat_priv->dat.hash, compare: batadv_compare_dat, |
397 | choose: batadv_hash_dat, data: dat_entry, |
398 | data_node: &dat_entry->hash_entry); |
399 | |
400 | if (unlikely(hash_added != 0)) { |
401 | /* remove the reference for the hash */ |
402 | batadv_dat_entry_put(dat_entry); |
403 | goto out; |
404 | } |
405 | |
406 | batadv_dbg(BATADV_DBG_DAT, bat_priv, "New entry added: %pI4 %pM (vid: %d)\n" , |
407 | &dat_entry->ip, dat_entry->mac_addr, batadv_print_vid(vid)); |
408 | |
409 | out: |
410 | batadv_dat_entry_put(dat_entry); |
411 | } |
412 | |
413 | #ifdef CONFIG_BATMAN_ADV_DEBUG |
414 | |
415 | /** |
416 | * batadv_dbg_arp() - print a debug message containing all the ARP packet |
417 | * details |
418 | * @bat_priv: the bat priv with all the soft interface information |
419 | * @skb: ARP packet |
420 | * @hdr_size: size of the possible header before the ARP packet |
421 | * @msg: message to print together with the debugging information |
422 | */ |
423 | static void batadv_dbg_arp(struct batadv_priv *bat_priv, struct sk_buff *skb, |
424 | int hdr_size, char *msg) |
425 | { |
426 | struct batadv_unicast_4addr_packet *unicast_4addr_packet; |
427 | struct batadv_bcast_packet *bcast_pkt; |
428 | u8 *orig_addr; |
429 | __be32 ip_src, ip_dst; |
430 | |
431 | if (msg) |
432 | batadv_dbg(BATADV_DBG_DAT, bat_priv, "%s\n" , msg); |
433 | |
434 | ip_src = batadv_arp_ip_src(skb, hdr_size); |
435 | ip_dst = batadv_arp_ip_dst(skb, hdr_size); |
436 | batadv_dbg(BATADV_DBG_DAT, bat_priv, |
437 | "ARP MSG = [src: %pM-%pI4 dst: %pM-%pI4]\n" , |
438 | batadv_arp_hw_src(skb, hdr_size), &ip_src, |
439 | batadv_arp_hw_dst(skb, hdr_size), &ip_dst); |
440 | |
441 | if (hdr_size < sizeof(struct batadv_unicast_packet)) |
442 | return; |
443 | |
444 | unicast_4addr_packet = (struct batadv_unicast_4addr_packet *)skb->data; |
445 | |
446 | switch (unicast_4addr_packet->u.packet_type) { |
447 | case BATADV_UNICAST: |
448 | batadv_dbg(BATADV_DBG_DAT, bat_priv, |
449 | "* encapsulated within a UNICAST packet\n" ); |
450 | break; |
451 | case BATADV_UNICAST_4ADDR: |
452 | batadv_dbg(BATADV_DBG_DAT, bat_priv, |
453 | "* encapsulated within a UNICAST_4ADDR packet (src: %pM)\n" , |
454 | unicast_4addr_packet->src); |
455 | switch (unicast_4addr_packet->subtype) { |
456 | case BATADV_P_DAT_DHT_PUT: |
457 | batadv_dbg(BATADV_DBG_DAT, bat_priv, "* type: DAT_DHT_PUT\n" ); |
458 | break; |
459 | case BATADV_P_DAT_DHT_GET: |
460 | batadv_dbg(BATADV_DBG_DAT, bat_priv, "* type: DAT_DHT_GET\n" ); |
461 | break; |
462 | case BATADV_P_DAT_CACHE_REPLY: |
463 | batadv_dbg(BATADV_DBG_DAT, bat_priv, |
464 | "* type: DAT_CACHE_REPLY\n" ); |
465 | break; |
466 | case BATADV_P_DATA: |
467 | batadv_dbg(BATADV_DBG_DAT, bat_priv, "* type: DATA\n" ); |
468 | break; |
469 | default: |
470 | batadv_dbg(BATADV_DBG_DAT, bat_priv, "* type: Unknown (%u)!\n" , |
471 | unicast_4addr_packet->u.packet_type); |
472 | } |
473 | break; |
474 | case BATADV_BCAST: |
475 | bcast_pkt = (struct batadv_bcast_packet *)unicast_4addr_packet; |
476 | orig_addr = bcast_pkt->orig; |
477 | batadv_dbg(BATADV_DBG_DAT, bat_priv, |
478 | "* encapsulated within a BCAST packet (src: %pM)\n" , |
479 | orig_addr); |
480 | break; |
481 | default: |
482 | batadv_dbg(BATADV_DBG_DAT, bat_priv, |
483 | "* encapsulated within an unknown packet type (0x%x)\n" , |
484 | unicast_4addr_packet->u.packet_type); |
485 | } |
486 | } |
487 | |
488 | #else |
489 | |
490 | static void batadv_dbg_arp(struct batadv_priv *bat_priv, struct sk_buff *skb, |
491 | int hdr_size, char *msg) |
492 | { |
493 | } |
494 | |
495 | #endif /* CONFIG_BATMAN_ADV_DEBUG */ |
496 | |
497 | /** |
498 | * batadv_is_orig_node_eligible() - check whether a node can be a DHT candidate |
499 | * @res: the array with the already selected candidates |
500 | * @select: number of already selected candidates |
501 | * @tmp_max: address of the currently evaluated node |
502 | * @max: current round max address |
503 | * @last_max: address of the last selected candidate |
504 | * @candidate: orig_node under evaluation |
505 | * @max_orig_node: last selected candidate |
506 | * |
507 | * Return: true if the node has been elected as next candidate or false |
508 | * otherwise. |
509 | */ |
510 | static bool batadv_is_orig_node_eligible(struct batadv_dat_candidate *res, |
511 | int select, batadv_dat_addr_t tmp_max, |
512 | batadv_dat_addr_t max, |
513 | batadv_dat_addr_t last_max, |
514 | struct batadv_orig_node *candidate, |
515 | struct batadv_orig_node *max_orig_node) |
516 | { |
517 | bool ret = false; |
518 | int j; |
519 | |
520 | /* check if orig node candidate is running DAT */ |
521 | if (!test_bit(BATADV_ORIG_CAPA_HAS_DAT, &candidate->capabilities)) |
522 | goto out; |
523 | |
524 | /* Check if this node has already been selected... */ |
525 | for (j = 0; j < select; j++) |
526 | if (res[j].orig_node == candidate) |
527 | break; |
528 | /* ..and possibly skip it */ |
529 | if (j < select) |
530 | goto out; |
531 | /* sanity check: has it already been selected? This should not happen */ |
532 | if (tmp_max > last_max) |
533 | goto out; |
534 | /* check if during this iteration an originator with a closer dht |
535 | * address has already been found |
536 | */ |
537 | if (tmp_max < max) |
538 | goto out; |
539 | /* this is an hash collision with the temporary selected node. Choose |
540 | * the one with the lowest address |
541 | */ |
542 | if (tmp_max == max && max_orig_node && |
543 | batadv_compare_eth(data1: candidate->orig, data2: max_orig_node->orig)) |
544 | goto out; |
545 | |
546 | ret = true; |
547 | out: |
548 | return ret; |
549 | } |
550 | |
551 | /** |
552 | * batadv_choose_next_candidate() - select the next DHT candidate |
553 | * @bat_priv: the bat priv with all the soft interface information |
554 | * @cands: candidates array |
555 | * @select: number of candidates already present in the array |
556 | * @ip_key: key to look up in the DHT |
557 | * @last_max: pointer where the address of the selected candidate will be saved |
558 | */ |
559 | static void batadv_choose_next_candidate(struct batadv_priv *bat_priv, |
560 | struct batadv_dat_candidate *cands, |
561 | int select, batadv_dat_addr_t ip_key, |
562 | batadv_dat_addr_t *last_max) |
563 | { |
564 | batadv_dat_addr_t max = 0; |
565 | batadv_dat_addr_t tmp_max = 0; |
566 | struct batadv_orig_node *orig_node, *max_orig_node = NULL; |
567 | struct batadv_hashtable *hash = bat_priv->orig_hash; |
568 | struct hlist_head *head; |
569 | int i; |
570 | |
571 | /* if no node is eligible as candidate, leave the candidate type as |
572 | * NOT_FOUND |
573 | */ |
574 | cands[select].type = BATADV_DAT_CANDIDATE_NOT_FOUND; |
575 | |
576 | /* iterate over the originator list and find the node with the closest |
577 | * dat_address which has not been selected yet |
578 | */ |
579 | for (i = 0; i < hash->size; i++) { |
580 | head = &hash->table[i]; |
581 | |
582 | rcu_read_lock(); |
583 | hlist_for_each_entry_rcu(orig_node, head, hash_entry) { |
584 | /* the dht space is a ring using unsigned addresses */ |
585 | tmp_max = BATADV_DAT_ADDR_MAX - orig_node->dat_addr + |
586 | ip_key; |
587 | |
588 | if (!batadv_is_orig_node_eligible(res: cands, select, |
589 | tmp_max, max, |
590 | last_max: *last_max, candidate: orig_node, |
591 | max_orig_node)) |
592 | continue; |
593 | |
594 | if (!kref_get_unless_zero(kref: &orig_node->refcount)) |
595 | continue; |
596 | |
597 | max = tmp_max; |
598 | batadv_orig_node_put(orig_node: max_orig_node); |
599 | max_orig_node = orig_node; |
600 | } |
601 | rcu_read_unlock(); |
602 | } |
603 | if (max_orig_node) { |
604 | cands[select].type = BATADV_DAT_CANDIDATE_ORIG; |
605 | cands[select].orig_node = max_orig_node; |
606 | batadv_dbg(BATADV_DBG_DAT, bat_priv, |
607 | "dat_select_candidates() %d: selected %pM addr=%u dist=%u\n" , |
608 | select, max_orig_node->orig, max_orig_node->dat_addr, |
609 | max); |
610 | } |
611 | *last_max = max; |
612 | } |
613 | |
614 | /** |
615 | * batadv_dat_select_candidates() - select the nodes which the DHT message has |
616 | * to be sent to |
617 | * @bat_priv: the bat priv with all the soft interface information |
618 | * @ip_dst: ipv4 to look up in the DHT |
619 | * @vid: VLAN identifier |
620 | * |
621 | * An originator O is selected if and only if its DHT_ID value is one of three |
622 | * closest values (from the LEFT, with wrap around if needed) then the hash |
623 | * value of the key. ip_dst is the key. |
624 | * |
625 | * Return: the candidate array of size BATADV_DAT_CANDIDATE_NUM. |
626 | */ |
627 | static struct batadv_dat_candidate * |
628 | batadv_dat_select_candidates(struct batadv_priv *bat_priv, __be32 ip_dst, |
629 | unsigned short vid) |
630 | { |
631 | int select; |
632 | batadv_dat_addr_t last_max = BATADV_DAT_ADDR_MAX, ip_key; |
633 | struct batadv_dat_candidate *res; |
634 | struct batadv_dat_entry dat; |
635 | |
636 | if (!bat_priv->orig_hash) |
637 | return NULL; |
638 | |
639 | res = kmalloc_array(BATADV_DAT_CANDIDATES_NUM, size: sizeof(*res), |
640 | GFP_ATOMIC); |
641 | if (!res) |
642 | return NULL; |
643 | |
644 | dat.ip = ip_dst; |
645 | dat.vid = vid; |
646 | ip_key = (batadv_dat_addr_t)batadv_hash_dat(data: &dat, |
647 | BATADV_DAT_ADDR_MAX); |
648 | |
649 | batadv_dbg(BATADV_DBG_DAT, bat_priv, |
650 | "%s(): IP=%pI4 hash(IP)=%u\n" , __func__, &ip_dst, |
651 | ip_key); |
652 | |
653 | for (select = 0; select < BATADV_DAT_CANDIDATES_NUM; select++) |
654 | batadv_choose_next_candidate(bat_priv, cands: res, select, ip_key, |
655 | last_max: &last_max); |
656 | |
657 | return res; |
658 | } |
659 | |
660 | /** |
661 | * batadv_dat_forward_data() - copy and send payload to the selected candidates |
662 | * @bat_priv: the bat priv with all the soft interface information |
663 | * @skb: payload to send |
664 | * @ip: the DHT key |
665 | * @vid: VLAN identifier |
666 | * @packet_subtype: unicast4addr packet subtype to use |
667 | * |
668 | * This function copies the skb with pskb_copy() and is sent as a unicast packet |
669 | * to each of the selected candidates. |
670 | * |
671 | * Return: true if the packet is sent to at least one candidate, false |
672 | * otherwise. |
673 | */ |
674 | static bool batadv_dat_forward_data(struct batadv_priv *bat_priv, |
675 | struct sk_buff *skb, __be32 ip, |
676 | unsigned short vid, int packet_subtype) |
677 | { |
678 | int i; |
679 | bool ret = false; |
680 | int send_status; |
681 | struct batadv_neigh_node *neigh_node = NULL; |
682 | struct sk_buff *tmp_skb; |
683 | struct batadv_dat_candidate *cand; |
684 | |
685 | cand = batadv_dat_select_candidates(bat_priv, ip_dst: ip, vid); |
686 | if (!cand) |
687 | goto out; |
688 | |
689 | batadv_dbg(BATADV_DBG_DAT, bat_priv, "DHT_SEND for %pI4\n" , &ip); |
690 | |
691 | for (i = 0; i < BATADV_DAT_CANDIDATES_NUM; i++) { |
692 | if (cand[i].type == BATADV_DAT_CANDIDATE_NOT_FOUND) |
693 | continue; |
694 | |
695 | neigh_node = batadv_orig_router_get(orig_node: cand[i].orig_node, |
696 | BATADV_IF_DEFAULT); |
697 | if (!neigh_node) |
698 | goto free_orig; |
699 | |
700 | tmp_skb = pskb_copy_for_clone(skb, GFP_ATOMIC); |
701 | if (!batadv_send_skb_prepare_unicast_4addr(bat_priv, skb: tmp_skb, |
702 | orig_node: cand[i].orig_node, |
703 | packet_subtype)) { |
704 | kfree_skb(skb: tmp_skb); |
705 | goto free_neigh; |
706 | } |
707 | |
708 | send_status = batadv_send_unicast_skb(skb: tmp_skb, neigh_node); |
709 | if (send_status == NET_XMIT_SUCCESS) { |
710 | /* count the sent packet */ |
711 | switch (packet_subtype) { |
712 | case BATADV_P_DAT_DHT_GET: |
713 | batadv_inc_counter(bat_priv, |
714 | BATADV_CNT_DAT_GET_TX); |
715 | break; |
716 | case BATADV_P_DAT_DHT_PUT: |
717 | batadv_inc_counter(bat_priv, |
718 | BATADV_CNT_DAT_PUT_TX); |
719 | break; |
720 | } |
721 | |
722 | /* packet sent to a candidate: return true */ |
723 | ret = true; |
724 | } |
725 | free_neigh: |
726 | batadv_neigh_node_put(neigh_node); |
727 | free_orig: |
728 | batadv_orig_node_put(orig_node: cand[i].orig_node); |
729 | } |
730 | |
731 | out: |
732 | kfree(objp: cand); |
733 | return ret; |
734 | } |
735 | |
736 | /** |
737 | * batadv_dat_tvlv_container_update() - update the dat tvlv container after dat |
738 | * setting change |
739 | * @bat_priv: the bat priv with all the soft interface information |
740 | */ |
741 | static void batadv_dat_tvlv_container_update(struct batadv_priv *bat_priv) |
742 | { |
743 | char dat_mode; |
744 | |
745 | dat_mode = atomic_read(v: &bat_priv->distributed_arp_table); |
746 | |
747 | switch (dat_mode) { |
748 | case 0: |
749 | batadv_tvlv_container_unregister(bat_priv, type: BATADV_TVLV_DAT, version: 1); |
750 | break; |
751 | case 1: |
752 | batadv_tvlv_container_register(bat_priv, type: BATADV_TVLV_DAT, version: 1, |
753 | NULL, tvlv_value_len: 0); |
754 | break; |
755 | } |
756 | } |
757 | |
758 | /** |
759 | * batadv_dat_status_update() - update the dat tvlv container after dat |
760 | * setting change |
761 | * @net_dev: the soft interface net device |
762 | */ |
763 | void batadv_dat_status_update(struct net_device *net_dev) |
764 | { |
765 | struct batadv_priv *bat_priv = netdev_priv(dev: net_dev); |
766 | |
767 | batadv_dat_tvlv_container_update(bat_priv); |
768 | } |
769 | |
770 | /** |
771 | * batadv_dat_tvlv_ogm_handler_v1() - process incoming dat tvlv container |
772 | * @bat_priv: the bat priv with all the soft interface information |
773 | * @orig: the orig_node of the ogm |
774 | * @flags: flags indicating the tvlv state (see batadv_tvlv_handler_flags) |
775 | * @tvlv_value: tvlv buffer containing the gateway data |
776 | * @tvlv_value_len: tvlv buffer length |
777 | */ |
778 | static void batadv_dat_tvlv_ogm_handler_v1(struct batadv_priv *bat_priv, |
779 | struct batadv_orig_node *orig, |
780 | u8 flags, |
781 | void *tvlv_value, u16 tvlv_value_len) |
782 | { |
783 | if (flags & BATADV_TVLV_HANDLER_OGM_CIFNOTFND) |
784 | clear_bit(nr: BATADV_ORIG_CAPA_HAS_DAT, addr: &orig->capabilities); |
785 | else |
786 | set_bit(nr: BATADV_ORIG_CAPA_HAS_DAT, addr: &orig->capabilities); |
787 | } |
788 | |
789 | /** |
790 | * batadv_dat_hash_free() - free the local DAT hash table |
791 | * @bat_priv: the bat priv with all the soft interface information |
792 | */ |
793 | static void batadv_dat_hash_free(struct batadv_priv *bat_priv) |
794 | { |
795 | if (!bat_priv->dat.hash) |
796 | return; |
797 | |
798 | __batadv_dat_purge(bat_priv, NULL); |
799 | |
800 | batadv_hash_destroy(hash: bat_priv->dat.hash); |
801 | |
802 | bat_priv->dat.hash = NULL; |
803 | } |
804 | |
805 | /** |
806 | * batadv_dat_init() - initialise the DAT internals |
807 | * @bat_priv: the bat priv with all the soft interface information |
808 | * |
809 | * Return: 0 in case of success, a negative error code otherwise |
810 | */ |
811 | int batadv_dat_init(struct batadv_priv *bat_priv) |
812 | { |
813 | if (bat_priv->dat.hash) |
814 | return 0; |
815 | |
816 | bat_priv->dat.hash = batadv_hash_new(size: 1024); |
817 | |
818 | if (!bat_priv->dat.hash) |
819 | return -ENOMEM; |
820 | |
821 | INIT_DELAYED_WORK(&bat_priv->dat.work, batadv_dat_purge); |
822 | batadv_dat_start_timer(bat_priv); |
823 | |
824 | batadv_tvlv_handler_register(bat_priv, optr: batadv_dat_tvlv_ogm_handler_v1, |
825 | NULL, NULL, type: BATADV_TVLV_DAT, version: 1, |
826 | flags: BATADV_TVLV_HANDLER_OGM_CIFNOTFND); |
827 | batadv_dat_tvlv_container_update(bat_priv); |
828 | return 0; |
829 | } |
830 | |
831 | /** |
832 | * batadv_dat_free() - free the DAT internals |
833 | * @bat_priv: the bat priv with all the soft interface information |
834 | */ |
835 | void batadv_dat_free(struct batadv_priv *bat_priv) |
836 | { |
837 | batadv_tvlv_container_unregister(bat_priv, type: BATADV_TVLV_DAT, version: 1); |
838 | batadv_tvlv_handler_unregister(bat_priv, type: BATADV_TVLV_DAT, version: 1); |
839 | |
840 | cancel_delayed_work_sync(dwork: &bat_priv->dat.work); |
841 | |
842 | batadv_dat_hash_free(bat_priv); |
843 | } |
844 | |
845 | /** |
846 | * batadv_dat_cache_dump_entry() - dump one entry of the DAT cache table to a |
847 | * netlink socket |
848 | * @msg: buffer for the message |
849 | * @portid: netlink port |
850 | * @cb: Control block containing additional options |
851 | * @dat_entry: entry to dump |
852 | * |
853 | * Return: 0 or error code. |
854 | */ |
855 | static int |
856 | batadv_dat_cache_dump_entry(struct sk_buff *msg, u32 portid, |
857 | struct netlink_callback *cb, |
858 | struct batadv_dat_entry *dat_entry) |
859 | { |
860 | int msecs; |
861 | void *hdr; |
862 | |
863 | hdr = genlmsg_put(skb: msg, portid, seq: cb->nlh->nlmsg_seq, |
864 | family: &batadv_netlink_family, NLM_F_MULTI, |
865 | cmd: BATADV_CMD_GET_DAT_CACHE); |
866 | if (!hdr) |
867 | return -ENOBUFS; |
868 | |
869 | genl_dump_check_consistent(cb, user_hdr: hdr); |
870 | |
871 | msecs = jiffies_to_msecs(j: jiffies - dat_entry->last_update); |
872 | |
873 | if (nla_put_in_addr(skb: msg, attrtype: BATADV_ATTR_DAT_CACHE_IP4ADDRESS, |
874 | addr: dat_entry->ip) || |
875 | nla_put(skb: msg, attrtype: BATADV_ATTR_DAT_CACHE_HWADDRESS, ETH_ALEN, |
876 | data: dat_entry->mac_addr) || |
877 | nla_put_u16(skb: msg, attrtype: BATADV_ATTR_DAT_CACHE_VID, value: dat_entry->vid) || |
878 | nla_put_u32(skb: msg, attrtype: BATADV_ATTR_LAST_SEEN_MSECS, value: msecs)) { |
879 | genlmsg_cancel(skb: msg, hdr); |
880 | return -EMSGSIZE; |
881 | } |
882 | |
883 | genlmsg_end(skb: msg, hdr); |
884 | return 0; |
885 | } |
886 | |
887 | /** |
888 | * batadv_dat_cache_dump_bucket() - dump one bucket of the DAT cache table to |
889 | * a netlink socket |
890 | * @msg: buffer for the message |
891 | * @portid: netlink port |
892 | * @cb: Control block containing additional options |
893 | * @hash: hash to dump |
894 | * @bucket: bucket index to dump |
895 | * @idx_skip: How many entries to skip |
896 | * |
897 | * Return: 0 or error code. |
898 | */ |
899 | static int |
900 | batadv_dat_cache_dump_bucket(struct sk_buff *msg, u32 portid, |
901 | struct netlink_callback *cb, |
902 | struct batadv_hashtable *hash, unsigned int bucket, |
903 | int *idx_skip) |
904 | { |
905 | struct batadv_dat_entry *dat_entry; |
906 | int idx = 0; |
907 | |
908 | spin_lock_bh(lock: &hash->list_locks[bucket]); |
909 | cb->seq = atomic_read(v: &hash->generation) << 1 | 1; |
910 | |
911 | hlist_for_each_entry(dat_entry, &hash->table[bucket], hash_entry) { |
912 | if (idx < *idx_skip) |
913 | goto skip; |
914 | |
915 | if (batadv_dat_cache_dump_entry(msg, portid, cb, dat_entry)) { |
916 | spin_unlock_bh(lock: &hash->list_locks[bucket]); |
917 | *idx_skip = idx; |
918 | |
919 | return -EMSGSIZE; |
920 | } |
921 | |
922 | skip: |
923 | idx++; |
924 | } |
925 | spin_unlock_bh(lock: &hash->list_locks[bucket]); |
926 | |
927 | return 0; |
928 | } |
929 | |
930 | /** |
931 | * batadv_dat_cache_dump() - dump DAT cache table to a netlink socket |
932 | * @msg: buffer for the message |
933 | * @cb: callback structure containing arguments |
934 | * |
935 | * Return: message length. |
936 | */ |
937 | int batadv_dat_cache_dump(struct sk_buff *msg, struct netlink_callback *cb) |
938 | { |
939 | struct batadv_hard_iface *primary_if = NULL; |
940 | int portid = NETLINK_CB(cb->skb).portid; |
941 | struct net *net = sock_net(sk: cb->skb->sk); |
942 | struct net_device *soft_iface; |
943 | struct batadv_hashtable *hash; |
944 | struct batadv_priv *bat_priv; |
945 | int bucket = cb->args[0]; |
946 | int idx = cb->args[1]; |
947 | int ifindex; |
948 | int ret = 0; |
949 | |
950 | ifindex = batadv_netlink_get_ifindex(nlh: cb->nlh, |
951 | attrtype: BATADV_ATTR_MESH_IFINDEX); |
952 | if (!ifindex) |
953 | return -EINVAL; |
954 | |
955 | soft_iface = dev_get_by_index(net, ifindex); |
956 | if (!soft_iface || !batadv_softif_is_valid(net_dev: soft_iface)) { |
957 | ret = -ENODEV; |
958 | goto out; |
959 | } |
960 | |
961 | bat_priv = netdev_priv(dev: soft_iface); |
962 | hash = bat_priv->dat.hash; |
963 | |
964 | primary_if = batadv_primary_if_get_selected(bat_priv); |
965 | if (!primary_if || primary_if->if_status != BATADV_IF_ACTIVE) { |
966 | ret = -ENOENT; |
967 | goto out; |
968 | } |
969 | |
970 | while (bucket < hash->size) { |
971 | if (batadv_dat_cache_dump_bucket(msg, portid, cb, hash, bucket, |
972 | idx_skip: &idx)) |
973 | break; |
974 | |
975 | bucket++; |
976 | idx = 0; |
977 | } |
978 | |
979 | cb->args[0] = bucket; |
980 | cb->args[1] = idx; |
981 | |
982 | ret = msg->len; |
983 | |
984 | out: |
985 | batadv_hardif_put(hard_iface: primary_if); |
986 | |
987 | dev_put(dev: soft_iface); |
988 | |
989 | return ret; |
990 | } |
991 | |
992 | /** |
993 | * batadv_arp_get_type() - parse an ARP packet and gets the type |
994 | * @bat_priv: the bat priv with all the soft interface information |
995 | * @skb: packet to analyse |
996 | * @hdr_size: size of the possible header before the ARP packet in the skb |
997 | * |
998 | * Return: the ARP type if the skb contains a valid ARP packet, 0 otherwise. |
999 | */ |
1000 | static u16 batadv_arp_get_type(struct batadv_priv *bat_priv, |
1001 | struct sk_buff *skb, int hdr_size) |
1002 | { |
1003 | struct arphdr *arphdr; |
1004 | struct ethhdr *ethhdr; |
1005 | __be32 ip_src, ip_dst; |
1006 | u8 *hw_src, *hw_dst; |
1007 | u16 type = 0; |
1008 | |
1009 | /* pull the ethernet header */ |
1010 | if (unlikely(!pskb_may_pull(skb, hdr_size + ETH_HLEN))) |
1011 | goto out; |
1012 | |
1013 | ethhdr = (struct ethhdr *)(skb->data + hdr_size); |
1014 | |
1015 | if (ethhdr->h_proto != htons(ETH_P_ARP)) |
1016 | goto out; |
1017 | |
1018 | /* pull the ARP payload */ |
1019 | if (unlikely(!pskb_may_pull(skb, hdr_size + ETH_HLEN + |
1020 | arp_hdr_len(skb->dev)))) |
1021 | goto out; |
1022 | |
1023 | arphdr = (struct arphdr *)(skb->data + hdr_size + ETH_HLEN); |
1024 | |
1025 | /* check whether the ARP packet carries a valid IP information */ |
1026 | if (arphdr->ar_hrd != htons(ARPHRD_ETHER)) |
1027 | goto out; |
1028 | |
1029 | if (arphdr->ar_pro != htons(ETH_P_IP)) |
1030 | goto out; |
1031 | |
1032 | if (arphdr->ar_hln != ETH_ALEN) |
1033 | goto out; |
1034 | |
1035 | if (arphdr->ar_pln != 4) |
1036 | goto out; |
1037 | |
1038 | /* Check for bad reply/request. If the ARP message is not sane, DAT |
1039 | * will simply ignore it |
1040 | */ |
1041 | ip_src = batadv_arp_ip_src(skb, hdr_size); |
1042 | ip_dst = batadv_arp_ip_dst(skb, hdr_size); |
1043 | if (ipv4_is_loopback(addr: ip_src) || ipv4_is_multicast(addr: ip_src) || |
1044 | ipv4_is_loopback(addr: ip_dst) || ipv4_is_multicast(addr: ip_dst) || |
1045 | ipv4_is_zeronet(addr: ip_src) || ipv4_is_lbcast(addr: ip_src) || |
1046 | ipv4_is_zeronet(addr: ip_dst) || ipv4_is_lbcast(addr: ip_dst)) |
1047 | goto out; |
1048 | |
1049 | hw_src = batadv_arp_hw_src(skb, hdr_size); |
1050 | if (is_zero_ether_addr(addr: hw_src) || is_multicast_ether_addr(addr: hw_src)) |
1051 | goto out; |
1052 | |
1053 | /* don't care about the destination MAC address in ARP requests */ |
1054 | if (arphdr->ar_op != htons(ARPOP_REQUEST)) { |
1055 | hw_dst = batadv_arp_hw_dst(skb, hdr_size); |
1056 | if (is_zero_ether_addr(addr: hw_dst) || |
1057 | is_multicast_ether_addr(addr: hw_dst)) |
1058 | goto out; |
1059 | } |
1060 | |
1061 | type = ntohs(arphdr->ar_op); |
1062 | out: |
1063 | return type; |
1064 | } |
1065 | |
1066 | /** |
1067 | * batadv_dat_get_vid() - extract the VLAN identifier from skb if any |
1068 | * @skb: the buffer containing the packet to extract the VID from |
1069 | * @hdr_size: the size of the batman-adv header encapsulating the packet |
1070 | * |
1071 | * Return: If the packet embedded in the skb is vlan tagged this function |
1072 | * returns the VID with the BATADV_VLAN_HAS_TAG flag. Otherwise BATADV_NO_FLAGS |
1073 | * is returned. |
1074 | */ |
1075 | static unsigned short batadv_dat_get_vid(struct sk_buff *skb, int *hdr_size) |
1076 | { |
1077 | unsigned short vid; |
1078 | |
1079 | vid = batadv_get_vid(skb, header_len: *hdr_size); |
1080 | |
1081 | /* ARP parsing functions jump forward of hdr_size + ETH_HLEN. |
1082 | * If the header contained in the packet is a VLAN one (which is longer) |
1083 | * hdr_size is updated so that the functions will still skip the |
1084 | * correct amount of bytes. |
1085 | */ |
1086 | if (vid & BATADV_VLAN_HAS_TAG) |
1087 | *hdr_size += VLAN_HLEN; |
1088 | |
1089 | return vid; |
1090 | } |
1091 | |
1092 | /** |
1093 | * batadv_dat_arp_create_reply() - create an ARP Reply |
1094 | * @bat_priv: the bat priv with all the soft interface information |
1095 | * @ip_src: ARP sender IP |
1096 | * @ip_dst: ARP target IP |
1097 | * @hw_src: Ethernet source and ARP sender MAC |
1098 | * @hw_dst: Ethernet destination and ARP target MAC |
1099 | * @vid: VLAN identifier (optional, set to zero otherwise) |
1100 | * |
1101 | * Creates an ARP Reply from the given values, optionally encapsulated in a |
1102 | * VLAN header. |
1103 | * |
1104 | * Return: An skb containing an ARP Reply. |
1105 | */ |
1106 | static struct sk_buff * |
1107 | batadv_dat_arp_create_reply(struct batadv_priv *bat_priv, __be32 ip_src, |
1108 | __be32 ip_dst, u8 *hw_src, u8 *hw_dst, |
1109 | unsigned short vid) |
1110 | { |
1111 | struct sk_buff *skb; |
1112 | |
1113 | skb = arp_create(ARPOP_REPLY, ETH_P_ARP, dest_ip: ip_dst, dev: bat_priv->soft_iface, |
1114 | src_ip: ip_src, dest_hw: hw_dst, src_hw: hw_src, target_hw: hw_dst); |
1115 | if (!skb) |
1116 | return NULL; |
1117 | |
1118 | skb_reset_mac_header(skb); |
1119 | |
1120 | if (vid & BATADV_VLAN_HAS_TAG) |
1121 | skb = vlan_insert_tag(skb, htons(ETH_P_8021Q), |
1122 | vlan_tci: vid & VLAN_VID_MASK); |
1123 | |
1124 | return skb; |
1125 | } |
1126 | |
1127 | /** |
1128 | * batadv_dat_snoop_outgoing_arp_request() - snoop the ARP request and try to |
1129 | * answer using DAT |
1130 | * @bat_priv: the bat priv with all the soft interface information |
1131 | * @skb: packet to check |
1132 | * |
1133 | * Return: true if the message has been sent to the dht candidates, false |
1134 | * otherwise. In case of a positive return value the message has to be enqueued |
1135 | * to permit the fallback. |
1136 | */ |
1137 | bool batadv_dat_snoop_outgoing_arp_request(struct batadv_priv *bat_priv, |
1138 | struct sk_buff *skb) |
1139 | { |
1140 | u16 type = 0; |
1141 | __be32 ip_dst, ip_src; |
1142 | u8 *hw_src; |
1143 | bool ret = false; |
1144 | struct batadv_dat_entry *dat_entry = NULL; |
1145 | struct sk_buff *skb_new; |
1146 | struct net_device *soft_iface = bat_priv->soft_iface; |
1147 | int hdr_size = 0; |
1148 | unsigned short vid; |
1149 | |
1150 | if (!atomic_read(v: &bat_priv->distributed_arp_table)) |
1151 | goto out; |
1152 | |
1153 | vid = batadv_dat_get_vid(skb, hdr_size: &hdr_size); |
1154 | |
1155 | type = batadv_arp_get_type(bat_priv, skb, hdr_size); |
1156 | /* If the node gets an ARP_REQUEST it has to send a DHT_GET unicast |
1157 | * message to the selected DHT candidates |
1158 | */ |
1159 | if (type != ARPOP_REQUEST) |
1160 | goto out; |
1161 | |
1162 | batadv_dbg_arp(bat_priv, skb, hdr_size, msg: "Parsing outgoing ARP REQUEST" ); |
1163 | |
1164 | ip_src = batadv_arp_ip_src(skb, hdr_size); |
1165 | hw_src = batadv_arp_hw_src(skb, hdr_size); |
1166 | ip_dst = batadv_arp_ip_dst(skb, hdr_size); |
1167 | |
1168 | batadv_dat_entry_add(bat_priv, ip: ip_src, mac_addr: hw_src, vid); |
1169 | |
1170 | dat_entry = batadv_dat_entry_hash_find(bat_priv, ip: ip_dst, vid); |
1171 | if (dat_entry) { |
1172 | /* If the ARP request is destined for a local client the local |
1173 | * client will answer itself. DAT would only generate a |
1174 | * duplicate packet. |
1175 | * |
1176 | * Moreover, if the soft-interface is enslaved into a bridge, an |
1177 | * additional DAT answer may trigger kernel warnings about |
1178 | * a packet coming from the wrong port. |
1179 | */ |
1180 | if (batadv_is_my_client(bat_priv, addr: dat_entry->mac_addr, vid)) { |
1181 | ret = true; |
1182 | goto out; |
1183 | } |
1184 | |
1185 | /* If BLA is enabled, only send ARP replies if we have claimed |
1186 | * the destination for the ARP request or if no one else of |
1187 | * the backbone gws belonging to our backbone has claimed the |
1188 | * destination. |
1189 | */ |
1190 | if (!batadv_bla_check_claim(bat_priv, |
1191 | addr: dat_entry->mac_addr, vid)) { |
1192 | batadv_dbg(BATADV_DBG_DAT, bat_priv, |
1193 | "Device %pM claimed by another backbone gw. Don't send ARP reply!" , |
1194 | dat_entry->mac_addr); |
1195 | ret = true; |
1196 | goto out; |
1197 | } |
1198 | |
1199 | skb_new = batadv_dat_arp_create_reply(bat_priv, ip_src: ip_dst, ip_dst: ip_src, |
1200 | hw_src: dat_entry->mac_addr, |
1201 | hw_dst: hw_src, vid); |
1202 | if (!skb_new) |
1203 | goto out; |
1204 | |
1205 | skb_new->protocol = eth_type_trans(skb: skb_new, dev: soft_iface); |
1206 | |
1207 | batadv_inc_counter(bat_priv, BATADV_CNT_RX); |
1208 | batadv_add_counter(bat_priv, idx: BATADV_CNT_RX_BYTES, |
1209 | count: skb->len + ETH_HLEN + hdr_size); |
1210 | |
1211 | netif_rx(skb: skb_new); |
1212 | batadv_dbg(BATADV_DBG_DAT, bat_priv, "ARP request replied locally\n" ); |
1213 | ret = true; |
1214 | } else { |
1215 | /* Send the request to the DHT */ |
1216 | ret = batadv_dat_forward_data(bat_priv, skb, ip: ip_dst, vid, |
1217 | packet_subtype: BATADV_P_DAT_DHT_GET); |
1218 | } |
1219 | out: |
1220 | batadv_dat_entry_put(dat_entry); |
1221 | return ret; |
1222 | } |
1223 | |
1224 | /** |
1225 | * batadv_dat_snoop_incoming_arp_request() - snoop the ARP request and try to |
1226 | * answer using the local DAT storage |
1227 | * @bat_priv: the bat priv with all the soft interface information |
1228 | * @skb: packet to check |
1229 | * @hdr_size: size of the encapsulation header |
1230 | * |
1231 | * Return: true if the request has been answered, false otherwise. |
1232 | */ |
1233 | bool batadv_dat_snoop_incoming_arp_request(struct batadv_priv *bat_priv, |
1234 | struct sk_buff *skb, int hdr_size) |
1235 | { |
1236 | u16 type; |
1237 | __be32 ip_src, ip_dst; |
1238 | u8 *hw_src; |
1239 | struct sk_buff *skb_new; |
1240 | struct batadv_dat_entry *dat_entry = NULL; |
1241 | bool ret = false; |
1242 | unsigned short vid; |
1243 | int err; |
1244 | |
1245 | if (!atomic_read(v: &bat_priv->distributed_arp_table)) |
1246 | goto out; |
1247 | |
1248 | vid = batadv_dat_get_vid(skb, hdr_size: &hdr_size); |
1249 | |
1250 | type = batadv_arp_get_type(bat_priv, skb, hdr_size); |
1251 | if (type != ARPOP_REQUEST) |
1252 | goto out; |
1253 | |
1254 | hw_src = batadv_arp_hw_src(skb, hdr_size); |
1255 | ip_src = batadv_arp_ip_src(skb, hdr_size); |
1256 | ip_dst = batadv_arp_ip_dst(skb, hdr_size); |
1257 | |
1258 | batadv_dbg_arp(bat_priv, skb, hdr_size, msg: "Parsing incoming ARP REQUEST" ); |
1259 | |
1260 | batadv_dat_entry_add(bat_priv, ip: ip_src, mac_addr: hw_src, vid); |
1261 | |
1262 | dat_entry = batadv_dat_entry_hash_find(bat_priv, ip: ip_dst, vid); |
1263 | if (!dat_entry) |
1264 | goto out; |
1265 | |
1266 | skb_new = batadv_dat_arp_create_reply(bat_priv, ip_src: ip_dst, ip_dst: ip_src, |
1267 | hw_src: dat_entry->mac_addr, hw_dst: hw_src, vid); |
1268 | if (!skb_new) |
1269 | goto out; |
1270 | |
1271 | /* To preserve backwards compatibility, the node has choose the outgoing |
1272 | * format based on the incoming request packet type. The assumption is |
1273 | * that a node not using the 4addr packet format doesn't support it. |
1274 | */ |
1275 | if (hdr_size == sizeof(struct batadv_unicast_4addr_packet)) |
1276 | err = batadv_send_skb_via_tt_4addr(bat_priv, skb: skb_new, |
1277 | packet_subtype: BATADV_P_DAT_CACHE_REPLY, |
1278 | NULL, vid); |
1279 | else |
1280 | err = batadv_send_skb_via_tt(bat_priv, skb: skb_new, NULL, vid); |
1281 | |
1282 | if (err != NET_XMIT_DROP) { |
1283 | batadv_inc_counter(bat_priv, BATADV_CNT_DAT_CACHED_REPLY_TX); |
1284 | ret = true; |
1285 | } |
1286 | out: |
1287 | batadv_dat_entry_put(dat_entry); |
1288 | if (ret) |
1289 | kfree_skb(skb); |
1290 | return ret; |
1291 | } |
1292 | |
1293 | /** |
1294 | * batadv_dat_snoop_outgoing_arp_reply() - snoop the ARP reply and fill the DHT |
1295 | * @bat_priv: the bat priv with all the soft interface information |
1296 | * @skb: packet to check |
1297 | */ |
1298 | void batadv_dat_snoop_outgoing_arp_reply(struct batadv_priv *bat_priv, |
1299 | struct sk_buff *skb) |
1300 | { |
1301 | u16 type; |
1302 | __be32 ip_src, ip_dst; |
1303 | u8 *hw_src, *hw_dst; |
1304 | int hdr_size = 0; |
1305 | unsigned short vid; |
1306 | |
1307 | if (!atomic_read(v: &bat_priv->distributed_arp_table)) |
1308 | return; |
1309 | |
1310 | vid = batadv_dat_get_vid(skb, hdr_size: &hdr_size); |
1311 | |
1312 | type = batadv_arp_get_type(bat_priv, skb, hdr_size); |
1313 | if (type != ARPOP_REPLY) |
1314 | return; |
1315 | |
1316 | batadv_dbg_arp(bat_priv, skb, hdr_size, msg: "Parsing outgoing ARP REPLY" ); |
1317 | |
1318 | hw_src = batadv_arp_hw_src(skb, hdr_size); |
1319 | ip_src = batadv_arp_ip_src(skb, hdr_size); |
1320 | hw_dst = batadv_arp_hw_dst(skb, hdr_size); |
1321 | ip_dst = batadv_arp_ip_dst(skb, hdr_size); |
1322 | |
1323 | batadv_dat_entry_add(bat_priv, ip: ip_src, mac_addr: hw_src, vid); |
1324 | batadv_dat_entry_add(bat_priv, ip: ip_dst, mac_addr: hw_dst, vid); |
1325 | |
1326 | /* Send the ARP reply to the candidates for both the IP addresses that |
1327 | * the node obtained from the ARP reply |
1328 | */ |
1329 | batadv_dat_forward_data(bat_priv, skb, ip: ip_src, vid, |
1330 | packet_subtype: BATADV_P_DAT_DHT_PUT); |
1331 | batadv_dat_forward_data(bat_priv, skb, ip: ip_dst, vid, |
1332 | packet_subtype: BATADV_P_DAT_DHT_PUT); |
1333 | } |
1334 | |
1335 | /** |
1336 | * batadv_dat_snoop_incoming_arp_reply() - snoop the ARP reply and fill the |
1337 | * local DAT storage only |
1338 | * @bat_priv: the bat priv with all the soft interface information |
1339 | * @skb: packet to check |
1340 | * @hdr_size: size of the encapsulation header |
1341 | * |
1342 | * Return: true if the packet was snooped and consumed by DAT. False if the |
1343 | * packet has to be delivered to the interface |
1344 | */ |
1345 | bool batadv_dat_snoop_incoming_arp_reply(struct batadv_priv *bat_priv, |
1346 | struct sk_buff *skb, int hdr_size) |
1347 | { |
1348 | struct batadv_dat_entry *dat_entry = NULL; |
1349 | u16 type; |
1350 | __be32 ip_src, ip_dst; |
1351 | u8 *hw_src, *hw_dst; |
1352 | bool dropped = false; |
1353 | unsigned short vid; |
1354 | |
1355 | if (!atomic_read(v: &bat_priv->distributed_arp_table)) |
1356 | goto out; |
1357 | |
1358 | vid = batadv_dat_get_vid(skb, hdr_size: &hdr_size); |
1359 | |
1360 | type = batadv_arp_get_type(bat_priv, skb, hdr_size); |
1361 | if (type != ARPOP_REPLY) |
1362 | goto out; |
1363 | |
1364 | batadv_dbg_arp(bat_priv, skb, hdr_size, msg: "Parsing incoming ARP REPLY" ); |
1365 | |
1366 | hw_src = batadv_arp_hw_src(skb, hdr_size); |
1367 | ip_src = batadv_arp_ip_src(skb, hdr_size); |
1368 | hw_dst = batadv_arp_hw_dst(skb, hdr_size); |
1369 | ip_dst = batadv_arp_ip_dst(skb, hdr_size); |
1370 | |
1371 | /* If ip_dst is already in cache and has the right mac address, |
1372 | * drop this frame if this ARP reply is destined for us because it's |
1373 | * most probably an ARP reply generated by another node of the DHT. |
1374 | * We have most probably received already a reply earlier. Delivering |
1375 | * this frame would lead to doubled receive of an ARP reply. |
1376 | */ |
1377 | dat_entry = batadv_dat_entry_hash_find(bat_priv, ip: ip_src, vid); |
1378 | if (dat_entry && batadv_compare_eth(data1: hw_src, data2: dat_entry->mac_addr)) { |
1379 | batadv_dbg(BATADV_DBG_DAT, bat_priv, "Doubled ARP reply removed: ARP MSG = [src: %pM-%pI4 dst: %pM-%pI4]; dat_entry: %pM-%pI4\n" , |
1380 | hw_src, &ip_src, hw_dst, &ip_dst, |
1381 | dat_entry->mac_addr, &dat_entry->ip); |
1382 | dropped = true; |
1383 | } |
1384 | |
1385 | /* Update our internal cache with both the IP addresses the node got |
1386 | * within the ARP reply |
1387 | */ |
1388 | batadv_dat_entry_add(bat_priv, ip: ip_src, mac_addr: hw_src, vid); |
1389 | batadv_dat_entry_add(bat_priv, ip: ip_dst, mac_addr: hw_dst, vid); |
1390 | |
1391 | if (dropped) |
1392 | goto out; |
1393 | |
1394 | /* If BLA is enabled, only forward ARP replies if we have claimed the |
1395 | * source of the ARP reply or if no one else of the same backbone has |
1396 | * already claimed that client. This prevents that different gateways |
1397 | * to the same backbone all forward the ARP reply leading to multiple |
1398 | * replies in the backbone. |
1399 | */ |
1400 | if (!batadv_bla_check_claim(bat_priv, addr: hw_src, vid)) { |
1401 | batadv_dbg(BATADV_DBG_DAT, bat_priv, |
1402 | "Device %pM claimed by another backbone gw. Drop ARP reply.\n" , |
1403 | hw_src); |
1404 | dropped = true; |
1405 | goto out; |
1406 | } |
1407 | |
1408 | /* if this REPLY is directed to a client of mine, let's deliver the |
1409 | * packet to the interface |
1410 | */ |
1411 | dropped = !batadv_is_my_client(bat_priv, addr: hw_dst, vid); |
1412 | |
1413 | /* if this REPLY is sent on behalf of a client of mine, let's drop the |
1414 | * packet because the client will reply by itself |
1415 | */ |
1416 | dropped |= batadv_is_my_client(bat_priv, addr: hw_src, vid); |
1417 | out: |
1418 | if (dropped) |
1419 | kfree_skb(skb); |
1420 | batadv_dat_entry_put(dat_entry); |
1421 | /* if dropped == false -> deliver to the interface */ |
1422 | return dropped; |
1423 | } |
1424 | |
1425 | /** |
1426 | * batadv_dat_check_dhcp_ipudp() - check skb for IP+UDP headers valid for DHCP |
1427 | * @skb: the packet to check |
1428 | * @ip_src: a buffer to store the IPv4 source address in |
1429 | * |
1430 | * Checks whether the given skb has an IP and UDP header valid for a DHCP |
1431 | * message from a DHCP server. And if so, stores the IPv4 source address in |
1432 | * the provided buffer. |
1433 | * |
1434 | * Return: True if valid, false otherwise. |
1435 | */ |
1436 | static bool |
1437 | batadv_dat_check_dhcp_ipudp(struct sk_buff *skb, __be32 *ip_src) |
1438 | { |
1439 | unsigned int offset = skb_network_offset(skb); |
1440 | struct udphdr *udphdr, _udphdr; |
1441 | struct iphdr *iphdr, _iphdr; |
1442 | |
1443 | iphdr = skb_header_pointer(skb, offset, len: sizeof(_iphdr), buffer: &_iphdr); |
1444 | if (!iphdr || iphdr->version != 4 || iphdr->ihl * 4 < sizeof(_iphdr)) |
1445 | return false; |
1446 | |
1447 | if (iphdr->protocol != IPPROTO_UDP) |
1448 | return false; |
1449 | |
1450 | offset += iphdr->ihl * 4; |
1451 | skb_set_transport_header(skb, offset); |
1452 | |
1453 | udphdr = skb_header_pointer(skb, offset, len: sizeof(_udphdr), buffer: &_udphdr); |
1454 | if (!udphdr || udphdr->source != htons(67)) |
1455 | return false; |
1456 | |
1457 | *ip_src = get_unaligned(&iphdr->saddr); |
1458 | |
1459 | return true; |
1460 | } |
1461 | |
1462 | /** |
1463 | * batadv_dat_check_dhcp() - examine packet for valid DHCP message |
1464 | * @skb: the packet to check |
1465 | * @proto: ethernet protocol hint (behind a potential vlan) |
1466 | * @ip_src: a buffer to store the IPv4 source address in |
1467 | * |
1468 | * Checks whether the given skb is a valid DHCP packet. And if so, stores the |
1469 | * IPv4 source address in the provided buffer. |
1470 | * |
1471 | * Caller needs to ensure that the skb network header is set correctly. |
1472 | * |
1473 | * Return: If skb is a valid DHCP packet, then returns its op code |
1474 | * (e.g. BOOTREPLY vs. BOOTREQUEST). Otherwise returns -EINVAL. |
1475 | */ |
1476 | static int |
1477 | batadv_dat_check_dhcp(struct sk_buff *skb, __be16 proto, __be32 *ip_src) |
1478 | { |
1479 | __be32 *magic, _magic; |
1480 | unsigned int offset; |
1481 | struct { |
1482 | __u8 op; |
1483 | __u8 htype; |
1484 | __u8 hlen; |
1485 | __u8 hops; |
1486 | } *dhcp_h, _dhcp_h; |
1487 | |
1488 | if (proto != htons(ETH_P_IP)) |
1489 | return -EINVAL; |
1490 | |
1491 | if (!batadv_dat_check_dhcp_ipudp(skb, ip_src)) |
1492 | return -EINVAL; |
1493 | |
1494 | offset = skb_transport_offset(skb) + sizeof(struct udphdr); |
1495 | if (skb->len < offset + sizeof(struct batadv_dhcp_packet)) |
1496 | return -EINVAL; |
1497 | |
1498 | dhcp_h = skb_header_pointer(skb, offset, len: sizeof(_dhcp_h), buffer: &_dhcp_h); |
1499 | if (!dhcp_h || dhcp_h->htype != BATADV_HTYPE_ETHERNET || |
1500 | dhcp_h->hlen != ETH_ALEN) |
1501 | return -EINVAL; |
1502 | |
1503 | offset += offsetof(struct batadv_dhcp_packet, magic); |
1504 | |
1505 | magic = skb_header_pointer(skb, offset, len: sizeof(_magic), buffer: &_magic); |
1506 | if (!magic || get_unaligned(magic) != htonl(BATADV_DHCP_MAGIC)) |
1507 | return -EINVAL; |
1508 | |
1509 | return dhcp_h->op; |
1510 | } |
1511 | |
1512 | /** |
1513 | * batadv_dat_get_dhcp_message_type() - get message type of a DHCP packet |
1514 | * @skb: the DHCP packet to parse |
1515 | * |
1516 | * Iterates over the DHCP options of the given DHCP packet to find a |
1517 | * DHCP Message Type option and parse it. |
1518 | * |
1519 | * Caller needs to ensure that the given skb is a valid DHCP packet and |
1520 | * that the skb transport header is set correctly. |
1521 | * |
1522 | * Return: The found DHCP message type value, if found. -EINVAL otherwise. |
1523 | */ |
1524 | static int batadv_dat_get_dhcp_message_type(struct sk_buff *skb) |
1525 | { |
1526 | unsigned int offset = skb_transport_offset(skb) + sizeof(struct udphdr); |
1527 | u8 *type, _type; |
1528 | struct { |
1529 | u8 type; |
1530 | u8 len; |
1531 | } *tl, _tl; |
1532 | |
1533 | offset += sizeof(struct batadv_dhcp_packet); |
1534 | |
1535 | while ((tl = skb_header_pointer(skb, offset, len: sizeof(_tl), buffer: &_tl))) { |
1536 | if (tl->type == BATADV_DHCP_OPT_MSG_TYPE) |
1537 | break; |
1538 | |
1539 | if (tl->type == BATADV_DHCP_OPT_END) |
1540 | break; |
1541 | |
1542 | if (tl->type == BATADV_DHCP_OPT_PAD) |
1543 | offset++; |
1544 | else |
1545 | offset += tl->len + sizeof(_tl); |
1546 | } |
1547 | |
1548 | /* Option Overload Code not supported */ |
1549 | if (!tl || tl->type != BATADV_DHCP_OPT_MSG_TYPE || |
1550 | tl->len != sizeof(_type)) |
1551 | return -EINVAL; |
1552 | |
1553 | offset += sizeof(_tl); |
1554 | |
1555 | type = skb_header_pointer(skb, offset, len: sizeof(_type), buffer: &_type); |
1556 | if (!type) |
1557 | return -EINVAL; |
1558 | |
1559 | return *type; |
1560 | } |
1561 | |
1562 | /** |
1563 | * batadv_dat_dhcp_get_yiaddr() - get yiaddr from a DHCP packet |
1564 | * @skb: the DHCP packet to parse |
1565 | * @buf: a buffer to store the yiaddr in |
1566 | * |
1567 | * Caller needs to ensure that the given skb is a valid DHCP packet and |
1568 | * that the skb transport header is set correctly. |
1569 | * |
1570 | * Return: True on success, false otherwise. |
1571 | */ |
1572 | static bool batadv_dat_dhcp_get_yiaddr(struct sk_buff *skb, __be32 *buf) |
1573 | { |
1574 | unsigned int offset = skb_transport_offset(skb) + sizeof(struct udphdr); |
1575 | __be32 *yiaddr; |
1576 | |
1577 | offset += offsetof(struct batadv_dhcp_packet, yiaddr); |
1578 | yiaddr = skb_header_pointer(skb, offset, BATADV_DHCP_YIADDR_LEN, buffer: buf); |
1579 | |
1580 | if (!yiaddr) |
1581 | return false; |
1582 | |
1583 | if (yiaddr != buf) |
1584 | *buf = get_unaligned(yiaddr); |
1585 | |
1586 | return true; |
1587 | } |
1588 | |
1589 | /** |
1590 | * batadv_dat_get_dhcp_chaddr() - get chaddr from a DHCP packet |
1591 | * @skb: the DHCP packet to parse |
1592 | * @buf: a buffer to store the chaddr in |
1593 | * |
1594 | * Caller needs to ensure that the given skb is a valid DHCP packet and |
1595 | * that the skb transport header is set correctly. |
1596 | * |
1597 | * Return: True on success, false otherwise |
1598 | */ |
1599 | static bool batadv_dat_get_dhcp_chaddr(struct sk_buff *skb, u8 *buf) |
1600 | { |
1601 | unsigned int offset = skb_transport_offset(skb) + sizeof(struct udphdr); |
1602 | u8 *chaddr; |
1603 | |
1604 | offset += offsetof(struct batadv_dhcp_packet, chaddr); |
1605 | chaddr = skb_header_pointer(skb, offset, BATADV_DHCP_CHADDR_LEN, buffer: buf); |
1606 | |
1607 | if (!chaddr) |
1608 | return false; |
1609 | |
1610 | if (chaddr != buf) |
1611 | memcpy(buf, chaddr, BATADV_DHCP_CHADDR_LEN); |
1612 | |
1613 | return true; |
1614 | } |
1615 | |
1616 | /** |
1617 | * batadv_dat_put_dhcp() - puts addresses from a DHCP packet into the DHT and |
1618 | * DAT cache |
1619 | * @bat_priv: the bat priv with all the soft interface information |
1620 | * @chaddr: the DHCP client MAC address |
1621 | * @yiaddr: the DHCP client IP address |
1622 | * @hw_dst: the DHCP server MAC address |
1623 | * @ip_dst: the DHCP server IP address |
1624 | * @vid: VLAN identifier |
1625 | * |
1626 | * Adds given MAC/IP pairs to the local DAT cache and propagates them further |
1627 | * into the DHT. |
1628 | * |
1629 | * For the DHT propagation, client MAC + IP will appear as the ARP Reply |
1630 | * transmitter (and hw_dst/ip_dst as the target). |
1631 | */ |
1632 | static void batadv_dat_put_dhcp(struct batadv_priv *bat_priv, u8 *chaddr, |
1633 | __be32 yiaddr, u8 *hw_dst, __be32 ip_dst, |
1634 | unsigned short vid) |
1635 | { |
1636 | struct sk_buff *skb; |
1637 | |
1638 | skb = batadv_dat_arp_create_reply(bat_priv, ip_src: yiaddr, ip_dst, hw_src: chaddr, |
1639 | hw_dst, vid); |
1640 | if (!skb) |
1641 | return; |
1642 | |
1643 | skb_set_network_header(skb, ETH_HLEN); |
1644 | |
1645 | batadv_dat_entry_add(bat_priv, ip: yiaddr, mac_addr: chaddr, vid); |
1646 | batadv_dat_entry_add(bat_priv, ip: ip_dst, mac_addr: hw_dst, vid); |
1647 | |
1648 | batadv_dat_forward_data(bat_priv, skb, ip: yiaddr, vid, |
1649 | packet_subtype: BATADV_P_DAT_DHT_PUT); |
1650 | batadv_dat_forward_data(bat_priv, skb, ip: ip_dst, vid, |
1651 | packet_subtype: BATADV_P_DAT_DHT_PUT); |
1652 | |
1653 | consume_skb(skb); |
1654 | |
1655 | batadv_dbg(BATADV_DBG_DAT, bat_priv, |
1656 | "Snooped from outgoing DHCPACK (server address): %pI4, %pM (vid: %i)\n" , |
1657 | &ip_dst, hw_dst, batadv_print_vid(vid)); |
1658 | batadv_dbg(BATADV_DBG_DAT, bat_priv, |
1659 | "Snooped from outgoing DHCPACK (client address): %pI4, %pM (vid: %i)\n" , |
1660 | &yiaddr, chaddr, batadv_print_vid(vid)); |
1661 | } |
1662 | |
1663 | /** |
1664 | * batadv_dat_check_dhcp_ack() - examine packet for valid DHCP message |
1665 | * @skb: the packet to check |
1666 | * @proto: ethernet protocol hint (behind a potential vlan) |
1667 | * @ip_src: a buffer to store the IPv4 source address in |
1668 | * @chaddr: a buffer to store the DHCP Client Hardware Address in |
1669 | * @yiaddr: a buffer to store the DHCP Your IP Address in |
1670 | * |
1671 | * Checks whether the given skb is a valid DHCPACK. And if so, stores the |
1672 | * IPv4 server source address (ip_src), client MAC address (chaddr) and client |
1673 | * IPv4 address (yiaddr) in the provided buffers. |
1674 | * |
1675 | * Caller needs to ensure that the skb network header is set correctly. |
1676 | * |
1677 | * Return: True if the skb is a valid DHCPACK. False otherwise. |
1678 | */ |
1679 | static bool |
1680 | batadv_dat_check_dhcp_ack(struct sk_buff *skb, __be16 proto, __be32 *ip_src, |
1681 | u8 *chaddr, __be32 *yiaddr) |
1682 | { |
1683 | int type; |
1684 | |
1685 | type = batadv_dat_check_dhcp(skb, proto, ip_src); |
1686 | if (type != BATADV_BOOTREPLY) |
1687 | return false; |
1688 | |
1689 | type = batadv_dat_get_dhcp_message_type(skb); |
1690 | if (type != BATADV_DHCPACK) |
1691 | return false; |
1692 | |
1693 | if (!batadv_dat_dhcp_get_yiaddr(skb, buf: yiaddr)) |
1694 | return false; |
1695 | |
1696 | if (!batadv_dat_get_dhcp_chaddr(skb, buf: chaddr)) |
1697 | return false; |
1698 | |
1699 | return true; |
1700 | } |
1701 | |
1702 | /** |
1703 | * batadv_dat_snoop_outgoing_dhcp_ack() - snoop DHCPACK and fill DAT with it |
1704 | * @bat_priv: the bat priv with all the soft interface information |
1705 | * @skb: the packet to snoop |
1706 | * @proto: ethernet protocol hint (behind a potential vlan) |
1707 | * @vid: VLAN identifier |
1708 | * |
1709 | * This function first checks whether the given skb is a valid DHCPACK. If |
1710 | * so then its source MAC and IP as well as its DHCP Client Hardware Address |
1711 | * field and DHCP Your IP Address field are added to the local DAT cache and |
1712 | * propagated into the DHT. |
1713 | * |
1714 | * Caller needs to ensure that the skb mac and network headers are set |
1715 | * correctly. |
1716 | */ |
1717 | void batadv_dat_snoop_outgoing_dhcp_ack(struct batadv_priv *bat_priv, |
1718 | struct sk_buff *skb, |
1719 | __be16 proto, |
1720 | unsigned short vid) |
1721 | { |
1722 | u8 chaddr[BATADV_DHCP_CHADDR_LEN]; |
1723 | __be32 ip_src, yiaddr; |
1724 | |
1725 | if (!atomic_read(v: &bat_priv->distributed_arp_table)) |
1726 | return; |
1727 | |
1728 | if (!batadv_dat_check_dhcp_ack(skb, proto, ip_src: &ip_src, chaddr, yiaddr: &yiaddr)) |
1729 | return; |
1730 | |
1731 | batadv_dat_put_dhcp(bat_priv, chaddr, yiaddr, hw_dst: eth_hdr(skb)->h_source, |
1732 | ip_dst: ip_src, vid); |
1733 | } |
1734 | |
1735 | /** |
1736 | * batadv_dat_snoop_incoming_dhcp_ack() - snoop DHCPACK and fill DAT cache |
1737 | * @bat_priv: the bat priv with all the soft interface information |
1738 | * @skb: the packet to snoop |
1739 | * @hdr_size: header size, up to the tail of the batman-adv header |
1740 | * |
1741 | * This function first checks whether the given skb is a valid DHCPACK. If |
1742 | * so then its source MAC and IP as well as its DHCP Client Hardware Address |
1743 | * field and DHCP Your IP Address field are added to the local DAT cache. |
1744 | */ |
1745 | void batadv_dat_snoop_incoming_dhcp_ack(struct batadv_priv *bat_priv, |
1746 | struct sk_buff *skb, int hdr_size) |
1747 | { |
1748 | u8 chaddr[BATADV_DHCP_CHADDR_LEN]; |
1749 | struct ethhdr *ethhdr; |
1750 | __be32 ip_src, yiaddr; |
1751 | unsigned short vid; |
1752 | __be16 proto; |
1753 | u8 *hw_src; |
1754 | |
1755 | if (!atomic_read(v: &bat_priv->distributed_arp_table)) |
1756 | return; |
1757 | |
1758 | if (unlikely(!pskb_may_pull(skb, hdr_size + ETH_HLEN))) |
1759 | return; |
1760 | |
1761 | ethhdr = (struct ethhdr *)(skb->data + hdr_size); |
1762 | skb_set_network_header(skb, offset: hdr_size + ETH_HLEN); |
1763 | proto = ethhdr->h_proto; |
1764 | |
1765 | if (!batadv_dat_check_dhcp_ack(skb, proto, ip_src: &ip_src, chaddr, yiaddr: &yiaddr)) |
1766 | return; |
1767 | |
1768 | hw_src = ethhdr->h_source; |
1769 | vid = batadv_dat_get_vid(skb, hdr_size: &hdr_size); |
1770 | |
1771 | batadv_dat_entry_add(bat_priv, ip: yiaddr, mac_addr: chaddr, vid); |
1772 | batadv_dat_entry_add(bat_priv, ip: ip_src, mac_addr: hw_src, vid); |
1773 | |
1774 | batadv_dbg(BATADV_DBG_DAT, bat_priv, |
1775 | "Snooped from incoming DHCPACK (server address): %pI4, %pM (vid: %i)\n" , |
1776 | &ip_src, hw_src, batadv_print_vid(vid)); |
1777 | batadv_dbg(BATADV_DBG_DAT, bat_priv, |
1778 | "Snooped from incoming DHCPACK (client address): %pI4, %pM (vid: %i)\n" , |
1779 | &yiaddr, chaddr, batadv_print_vid(vid)); |
1780 | } |
1781 | |
1782 | /** |
1783 | * batadv_dat_drop_broadcast_packet() - check if an ARP request has to be |
1784 | * dropped (because the node has already obtained the reply via DAT) or not |
1785 | * @bat_priv: the bat priv with all the soft interface information |
1786 | * @forw_packet: the broadcast packet |
1787 | * |
1788 | * Return: true if the node can drop the packet, false otherwise. |
1789 | */ |
1790 | bool batadv_dat_drop_broadcast_packet(struct batadv_priv *bat_priv, |
1791 | struct batadv_forw_packet *forw_packet) |
1792 | { |
1793 | u16 type; |
1794 | __be32 ip_dst; |
1795 | struct batadv_dat_entry *dat_entry = NULL; |
1796 | bool ret = false; |
1797 | int hdr_size = sizeof(struct batadv_bcast_packet); |
1798 | unsigned short vid; |
1799 | |
1800 | if (!atomic_read(v: &bat_priv->distributed_arp_table)) |
1801 | goto out; |
1802 | |
1803 | /* If this packet is an ARP_REQUEST and the node already has the |
1804 | * information that it is going to ask, then the packet can be dropped |
1805 | */ |
1806 | if (batadv_forw_packet_is_rebroadcast(forw_packet)) |
1807 | goto out; |
1808 | |
1809 | vid = batadv_dat_get_vid(skb: forw_packet->skb, hdr_size: &hdr_size); |
1810 | |
1811 | type = batadv_arp_get_type(bat_priv, skb: forw_packet->skb, hdr_size); |
1812 | if (type != ARPOP_REQUEST) |
1813 | goto out; |
1814 | |
1815 | ip_dst = batadv_arp_ip_dst(skb: forw_packet->skb, hdr_size); |
1816 | dat_entry = batadv_dat_entry_hash_find(bat_priv, ip: ip_dst, vid); |
1817 | /* check if the node already got this entry */ |
1818 | if (!dat_entry) { |
1819 | batadv_dbg(BATADV_DBG_DAT, bat_priv, |
1820 | "ARP Request for %pI4: fallback\n" , &ip_dst); |
1821 | goto out; |
1822 | } |
1823 | |
1824 | batadv_dbg(BATADV_DBG_DAT, bat_priv, |
1825 | "ARP Request for %pI4: fallback prevented\n" , &ip_dst); |
1826 | ret = true; |
1827 | |
1828 | out: |
1829 | batadv_dat_entry_put(dat_entry); |
1830 | return ret; |
1831 | } |
1832 | |