// SPDX-License-Identifier: GPL-2.01/* Copyright (C) B.A.T.M.A.N. contributors:2*3* Linus Lüssing4*/56#include "multicast.h"7#include "main.h"89#include <linux/bug.h>10#include <linux/build_bug.h>11#include <linux/byteorder/generic.h>12#include <linux/compiler.h>13#include <linux/errno.h>14#include <linux/etherdevice.h>15#include <linux/gfp.h>16#include <linux/if_ether.h>17#include <linux/if_vlan.h>18#include <linux/ipv6.h>19#include <linux/limits.h>20#include <linux/netdevice.h>21#include <linux/rculist.h>22#include <linux/rcupdate.h>23#include <linux/skbuff.h>24#include <linux/stddef.h>25#include <linux/string.h>26#include <linux/types.h>27#include <uapi/linux/batadv_packet.h>2829#include "bridge_loop_avoidance.h"30#include "originator.h"31#include "send.h"32#include "translation-table.h"3334#define batadv_mcast_forw_tracker_for_each_dest(dest, num_dests) \35for (; num_dests; num_dests--, (dest) += ETH_ALEN)3637#define batadv_mcast_forw_tracker_for_each_dest2(dest1, dest2, num_dests) \38for (; num_dests; num_dests--, (dest1) += ETH_ALEN, (dest2) += ETH_ALEN)3940/**41* batadv_mcast_forw_skb_push() - skb_push and memorize amount of pushed bytes42* @skb: the skb to push onto43* @size: the amount of bytes to push44* @len: stores the total amount of bytes pushed45*46* Performs an skb_push() onto the given skb and adds the amount of pushed bytes47* to the given len pointer.48*49* Return: the return value of the skb_push() call.50*/51static void *batadv_mcast_forw_skb_push(struct sk_buff *skb, size_t size,52unsigned short *len)53{54*len += size;55return skb_push(skb, size);56}5758/**59* batadv_mcast_forw_push_padding() - push 2 padding bytes to skb's front60* @skb: the skb to push onto61* @tvlv_len: stores the amount of currently pushed TVLV bytes62*63* Pushes two padding bytes to the front of the given skb.64*65* Return: On success a pointer to the first byte of the two pushed padding66* bytes within the skb. NULL otherwise.67*/68static char *69batadv_mcast_forw_push_padding(struct sk_buff *skb, unsigned short *tvlv_len)70{71const int pad_len = 2;72char *padding;7374if (skb_headroom(skb) < pad_len)75return NULL;7677padding = batadv_mcast_forw_skb_push(skb, pad_len, tvlv_len);78memset(padding, 0, pad_len);7980return padding;81}8283/**84* batadv_mcast_forw_push_est_padding() - push padding bytes if necessary85* @skb: the skb to potentially push the padding onto86* @count: the (estimated) number of originators the multicast packet needs to87* be sent to88* @tvlv_len: stores the amount of currently pushed TVLV bytes89*90* If the number of destination entries is even then this adds two91* padding bytes to the end of the tracker TVLV.92*93* Return: true on success or if no padding is needed, false otherwise.94*/95static bool96batadv_mcast_forw_push_est_padding(struct sk_buff *skb, int count,97unsigned short *tvlv_len)98{99if (!(count % 2) && !batadv_mcast_forw_push_padding(skb, tvlv_len))100return false;101102return true;103}104105/**106* batadv_mcast_forw_orig_entry() - get orig_node from an hlist node107* @node: the hlist node to get the orig_node from108* @entry_offset: the offset of the hlist node within the orig_node struct109*110* Return: The orig_node containing the hlist node on success, NULL on error.111*/112static struct batadv_orig_node *113batadv_mcast_forw_orig_entry(struct hlist_node *node,114size_t entry_offset)115{116/* sanity check */117switch (entry_offset) {118case offsetof(struct batadv_orig_node, mcast_want_all_ipv4_node):119case offsetof(struct batadv_orig_node, mcast_want_all_ipv6_node):120case offsetof(struct batadv_orig_node, mcast_want_all_rtr4_node):121case offsetof(struct batadv_orig_node, mcast_want_all_rtr6_node):122break;123default:124WARN_ON(1);125return NULL;126}127128return (struct batadv_orig_node *)((void *)node - entry_offset);129}130131/**132* batadv_mcast_forw_push_dest() - push an originator MAC address onto an skb133* @bat_priv: the bat priv with all the mesh interface information134* @skb: the skb to push the destination address onto135* @vid: the vlan identifier136* @orig_node: the originator node to get the MAC address from137* @num_dests: a pointer to store the number of pushed addresses in138* @tvlv_len: stores the amount of currently pushed TVLV bytes139*140* If the orig_node is a BLA backbone gateway, if there is not enough skb141* headroom available or if num_dests is already at its maximum (65535) then142* neither the skb nor num_dests is changed. Otherwise the originator's MAC143* address is pushed onto the given skb and num_dests incremented by one.144*145* Return: true if the orig_node is a backbone gateway or if an orig address146* was pushed successfully, false otherwise.147*/148static bool batadv_mcast_forw_push_dest(struct batadv_priv *bat_priv,149struct sk_buff *skb, unsigned short vid,150struct batadv_orig_node *orig_node,151unsigned short *num_dests,152unsigned short *tvlv_len)153{154BUILD_BUG_ON(sizeof_field(struct batadv_tvlv_mcast_tracker, num_dests)155!= sizeof(__be16));156157/* Avoid sending to other BLA gateways - they already got the frame from158* the LAN side we share with them.159* TODO: Refactor to take BLA into account earlier in mode check.160*/161if (batadv_bla_is_backbone_gw_orig(bat_priv, orig_node->orig, vid))162return true;163164if (skb_headroom(skb) < ETH_ALEN || *num_dests == U16_MAX)165return false;166167batadv_mcast_forw_skb_push(skb, ETH_ALEN, tvlv_len);168ether_addr_copy(skb->data, orig_node->orig);169(*num_dests)++;170171return true;172}173174/**175* batadv_mcast_forw_push_dests_list() - push originators from list onto an skb176* @bat_priv: the bat priv with all the mesh interface information177* @skb: the skb to push the destination addresses onto178* @vid: the vlan identifier179* @head: the list to gather originators from180* @entry_offset: offset of an hlist node in an orig_node structure181* @num_dests: a pointer to store the number of pushed addresses in182* @tvlv_len: stores the amount of currently pushed TVLV bytes183*184* Push the MAC addresses of all originators in the given list onto the given185* skb.186*187* Return: true on success, false otherwise.188*/189static int batadv_mcast_forw_push_dests_list(struct batadv_priv *bat_priv,190struct sk_buff *skb,191unsigned short vid,192struct hlist_head *head,193size_t entry_offset,194unsigned short *num_dests,195unsigned short *tvlv_len)196{197struct hlist_node *node;198struct batadv_orig_node *orig_node;199200rcu_read_lock();201__hlist_for_each_rcu(node, head) {202orig_node = batadv_mcast_forw_orig_entry(node, entry_offset);203if (!orig_node ||204!batadv_mcast_forw_push_dest(bat_priv, skb, vid, orig_node,205num_dests, tvlv_len)) {206rcu_read_unlock();207return false;208}209}210rcu_read_unlock();211212return true;213}214215/**216* batadv_mcast_forw_push_tt() - push originators with interest through TT217* @bat_priv: the bat priv with all the mesh interface information218* @skb: the skb to push the destination addresses onto219* @vid: the vlan identifier220* @num_dests: a pointer to store the number of pushed addresses in221* @tvlv_len: stores the amount of currently pushed TVLV bytes222*223* Push the MAC addresses of all originators which have indicated interest in224* this multicast packet through the translation table onto the given skb.225*226* Return: true on success, false otherwise.227*/228static bool229batadv_mcast_forw_push_tt(struct batadv_priv *bat_priv, struct sk_buff *skb,230unsigned short vid, unsigned short *num_dests,231unsigned short *tvlv_len)232{233struct batadv_tt_orig_list_entry *orig_entry;234235struct batadv_tt_global_entry *tt_global;236const u8 *addr = eth_hdr(skb)->h_dest;237238/* ok */239int ret = true;240241tt_global = batadv_tt_global_hash_find(bat_priv, addr, vid);242if (!tt_global)243goto out;244245rcu_read_lock();246hlist_for_each_entry_rcu(orig_entry, &tt_global->orig_list, list) {247if (!batadv_mcast_forw_push_dest(bat_priv, skb, vid,248orig_entry->orig_node,249num_dests, tvlv_len)) {250ret = false;251break;252}253}254rcu_read_unlock();255256batadv_tt_global_entry_put(tt_global);257258out:259return ret;260}261262/**263* batadv_mcast_forw_push_want_all() - push originators with want-all flag264* @bat_priv: the bat priv with all the mesh interface information265* @skb: the skb to push the destination addresses onto266* @vid: the vlan identifier267* @num_dests: a pointer to store the number of pushed addresses in268* @tvlv_len: stores the amount of currently pushed TVLV bytes269*270* Push the MAC addresses of all originators which have indicated interest in271* this multicast packet through the want-all flag onto the given skb.272*273* Return: true on success, false otherwise.274*/275static bool batadv_mcast_forw_push_want_all(struct batadv_priv *bat_priv,276struct sk_buff *skb,277unsigned short vid,278unsigned short *num_dests,279unsigned short *tvlv_len)280{281struct hlist_head *head = NULL;282size_t offset;283int ret;284285switch (eth_hdr(skb)->h_proto) {286case htons(ETH_P_IP):287head = &bat_priv->mcast.want_all_ipv4_list;288offset = offsetof(struct batadv_orig_node,289mcast_want_all_ipv4_node);290break;291case htons(ETH_P_IPV6):292head = &bat_priv->mcast.want_all_ipv6_list;293offset = offsetof(struct batadv_orig_node,294mcast_want_all_ipv6_node);295break;296default:297return false;298}299300ret = batadv_mcast_forw_push_dests_list(bat_priv, skb, vid, head,301offset, num_dests, tvlv_len);302if (!ret)303return false;304305return true;306}307308/**309* batadv_mcast_forw_push_want_rtr() - push originators with want-router flag310* @bat_priv: the bat priv with all the mesh interface information311* @skb: the skb to push the destination addresses onto312* @vid: the vlan identifier313* @num_dests: a pointer to store the number of pushed addresses in314* @tvlv_len: stores the amount of currently pushed TVLV bytes315*316* Push the MAC addresses of all originators which have indicated interest in317* this multicast packet through the want-all-rtr flag onto the given skb.318*319* Return: true on success, false otherwise.320*/321static bool batadv_mcast_forw_push_want_rtr(struct batadv_priv *bat_priv,322struct sk_buff *skb,323unsigned short vid,324unsigned short *num_dests,325unsigned short *tvlv_len)326{327struct hlist_head *head = NULL;328size_t offset;329int ret;330331switch (eth_hdr(skb)->h_proto) {332case htons(ETH_P_IP):333head = &bat_priv->mcast.want_all_rtr4_list;334offset = offsetof(struct batadv_orig_node,335mcast_want_all_rtr4_node);336break;337case htons(ETH_P_IPV6):338head = &bat_priv->mcast.want_all_rtr6_list;339offset = offsetof(struct batadv_orig_node,340mcast_want_all_rtr6_node);341break;342default:343return false;344}345346ret = batadv_mcast_forw_push_dests_list(bat_priv, skb, vid, head,347offset, num_dests, tvlv_len);348if (!ret)349return false;350351return true;352}353354/**355* batadv_mcast_forw_scrape() - remove bytes within skb data356* @skb: the skb to remove bytes from357* @offset: the offset from the skb data from which to scrape358* @len: the amount of bytes to scrape starting from the offset359*360* Scrapes/removes len bytes from the given skb at the given offset from the361* skb data.362*363* Caller needs to ensure that the region from the skb data's start up364* to/including the to be removed bytes are linearized.365*/366static void batadv_mcast_forw_scrape(struct sk_buff *skb,367unsigned short offset,368unsigned short len)369{370char *to, *from;371372SKB_LINEAR_ASSERT(skb);373374to = skb_pull(skb, len);375from = to - len;376377memmove(to, from, offset);378}379380/**381* batadv_mcast_forw_push_scrape_padding() - remove TVLV padding382* @skb: the skb to potentially adjust the TVLV's padding on383* @tvlv_len: stores the amount of currently pushed TVLV bytes384*385* Remove two padding bytes from the end of the multicast tracker TVLV,386* from before the payload data.387*388* Caller needs to ensure that the TVLV bytes are linearized.389*/390static void batadv_mcast_forw_push_scrape_padding(struct sk_buff *skb,391unsigned short *tvlv_len)392{393const int pad_len = 2;394395batadv_mcast_forw_scrape(skb, *tvlv_len - pad_len, pad_len);396*tvlv_len -= pad_len;397}398399/**400* batadv_mcast_forw_push_insert_padding() - insert TVLV padding401* @skb: the skb to potentially adjust the TVLV's padding on402* @tvlv_len: stores the amount of currently pushed TVLV bytes403*404* Inserts two padding bytes at the end of the multicast tracker TVLV,405* before the payload data in the given skb.406*407* Return: true on success, false otherwise.408*/409static bool batadv_mcast_forw_push_insert_padding(struct sk_buff *skb,410unsigned short *tvlv_len)411{412unsigned short offset = *tvlv_len;413char *to, *from = skb->data;414415to = batadv_mcast_forw_push_padding(skb, tvlv_len);416if (!to)417return false;418419memmove(to, from, offset);420memset(to + offset, 0, *tvlv_len - offset);421return true;422}423424/**425* batadv_mcast_forw_push_adjust_padding() - adjust padding if necessary426* @skb: the skb to potentially adjust the TVLV's padding on427* @count: the estimated number of originators the multicast packet needs to428* be sent to429* @num_dests_pushed: the number of originators that were actually added to the430* multicast packet's tracker TVLV431* @tvlv_len: stores the amount of currently pushed TVLV bytes432*433* Adjusts the padding in the multicast packet's tracker TVLV depending on the434* initially estimated amount of destinations versus the amount of destinations435* that were actually added to the tracker TVLV.436*437* If the initial estimate was correct or at least the oddness was the same then438* no padding adjustment is performed.439* If the initially estimated number was even, so padding was initially added,440* but it turned out to be odd then padding is removed.441* If the initially estimated number was odd, so no padding was initially added,442* but it turned out to be even then padding is added.443*444* Return: true if no padding adjustment is needed or the adjustment was445* successful, false otherwise.446*/447static bool448batadv_mcast_forw_push_adjust_padding(struct sk_buff *skb, int *count,449unsigned short num_dests_pushed,450unsigned short *tvlv_len)451{452int ret = true;453454if (likely((num_dests_pushed % 2) == (*count % 2)))455goto out;456457/**458* estimated even number of destinations, but turned out to be odd459* -> remove padding460*/461if (!(*count % 2) && (num_dests_pushed % 2))462batadv_mcast_forw_push_scrape_padding(skb, tvlv_len);463/**464* estimated odd number of destinations, but turned out to be even465* -> add padding466*/467else if ((*count % 2) && (!(num_dests_pushed % 2)))468ret = batadv_mcast_forw_push_insert_padding(skb, tvlv_len);469470out:471*count = num_dests_pushed;472return ret;473}474475/**476* batadv_mcast_forw_push_dests() - push originator addresses onto an skb477* @bat_priv: the bat priv with all the mesh interface information478* @skb: the skb to push the destination addresses onto479* @vid: the vlan identifier480* @is_routable: indicates whether the destination is routable481* @count: the number of originators the multicast packet needs to be sent to482* @tvlv_len: stores the amount of currently pushed TVLV bytes483*484* Push the MAC addresses of all originators which have indicated interest in485* this multicast packet onto the given skb.486*487* Return: -ENOMEM if there is not enough skb headroom available. Otherwise, on488* success 0.489*/490static int491batadv_mcast_forw_push_dests(struct batadv_priv *bat_priv, struct sk_buff *skb,492unsigned short vid, int is_routable, int *count,493unsigned short *tvlv_len)494{495unsigned short num_dests = 0;496497if (!batadv_mcast_forw_push_est_padding(skb, *count, tvlv_len))498goto err;499500if (!batadv_mcast_forw_push_tt(bat_priv, skb, vid, &num_dests,501tvlv_len))502goto err;503504if (!batadv_mcast_forw_push_want_all(bat_priv, skb, vid, &num_dests,505tvlv_len))506goto err;507508if (is_routable &&509!batadv_mcast_forw_push_want_rtr(bat_priv, skb, vid, &num_dests,510tvlv_len))511goto err;512513if (!batadv_mcast_forw_push_adjust_padding(skb, count, num_dests,514tvlv_len))515goto err;516517return 0;518err:519return -ENOMEM;520}521522/**523* batadv_mcast_forw_push_tracker() - push a multicast tracker TVLV header524* @skb: the skb to push the tracker TVLV onto525* @num_dests: the number of destination addresses to set in the header526* @tvlv_len: stores the amount of currently pushed TVLV bytes527*528* Pushes a multicast tracker TVLV header onto the given skb, including the529* generic TVLV header but excluding the destination MAC addresses.530*531* The provided num_dests value is taken into consideration to set the532* num_dests field in the tracker header and to set the appropriate TVLV length533* value fields.534*535* Return: -ENOMEM if there is not enough skb headroom available. Otherwise, on536* success 0.537*/538static int batadv_mcast_forw_push_tracker(struct sk_buff *skb, int num_dests,539unsigned short *tvlv_len)540{541struct batadv_tvlv_mcast_tracker *mcast_tracker;542struct batadv_tvlv_hdr *tvlv_hdr;543unsigned int tvlv_value_len;544545if (skb_headroom(skb) < sizeof(*mcast_tracker) + sizeof(*tvlv_hdr))546return -ENOMEM;547548tvlv_value_len = sizeof(*mcast_tracker) + *tvlv_len;549if (tvlv_value_len + sizeof(*tvlv_hdr) > U16_MAX)550return -ENOMEM;551552batadv_mcast_forw_skb_push(skb, sizeof(*mcast_tracker), tvlv_len);553mcast_tracker = (struct batadv_tvlv_mcast_tracker *)skb->data;554mcast_tracker->num_dests = htons(num_dests);555556skb_reset_network_header(skb);557558batadv_mcast_forw_skb_push(skb, sizeof(*tvlv_hdr), tvlv_len);559tvlv_hdr = (struct batadv_tvlv_hdr *)skb->data;560tvlv_hdr->type = BATADV_TVLV_MCAST_TRACKER;561tvlv_hdr->version = 1;562tvlv_hdr->len = htons(tvlv_value_len);563564return 0;565}566567/**568* batadv_mcast_forw_push_tvlvs() - push a multicast tracker TVLV onto an skb569* @bat_priv: the bat priv with all the mesh interface information570* @skb: the skb to push the tracker TVLV onto571* @vid: the vlan identifier572* @is_routable: indicates whether the destination is routable573* @count: the number of originators the multicast packet needs to be sent to574* @tvlv_len: stores the amount of currently pushed TVLV bytes575*576* Pushes a multicast tracker TVLV onto the given skb, including the collected577* destination MAC addresses and the generic TVLV header.578*579* Return: -ENOMEM if there is not enough skb headroom available. Otherwise, on580* success 0.581*/582static int583batadv_mcast_forw_push_tvlvs(struct batadv_priv *bat_priv, struct sk_buff *skb,584unsigned short vid, int is_routable, int count,585unsigned short *tvlv_len)586{587int ret;588589ret = batadv_mcast_forw_push_dests(bat_priv, skb, vid, is_routable,590&count, tvlv_len);591if (ret < 0)592return ret;593594ret = batadv_mcast_forw_push_tracker(skb, count, tvlv_len);595if (ret < 0)596return ret;597598return 0;599}600601/**602* batadv_mcast_forw_push_hdr() - push a multicast packet header onto an skb603* @skb: the skb to push the header onto604* @tvlv_len: the total TVLV length value to set in the header605*606* Pushes a batman-adv multicast packet header onto the given skb and sets607* the provided total TVLV length value in it.608*609* Caller needs to ensure enough skb headroom is available.610*611* Return: -ENOMEM if there is not enough skb headroom available. Otherwise, on612* success 0.613*/614static int615batadv_mcast_forw_push_hdr(struct sk_buff *skb, unsigned short tvlv_len)616{617struct batadv_mcast_packet *mcast_packet;618619if (skb_headroom(skb) < sizeof(*mcast_packet))620return -ENOMEM;621622skb_push(skb, sizeof(*mcast_packet));623624mcast_packet = (struct batadv_mcast_packet *)skb->data;625mcast_packet->version = BATADV_COMPAT_VERSION;626mcast_packet->ttl = BATADV_TTL;627mcast_packet->packet_type = BATADV_MCAST;628mcast_packet->reserved = 0;629mcast_packet->tvlv_len = htons(tvlv_len);630631return 0;632}633634/**635* batadv_mcast_forw_scrub_dests() - scrub destinations in a tracker TVLV636* @bat_priv: the bat priv with all the mesh interface information637* @comp_neigh: next hop neighbor to scrub+collect destinations for638* @dest: start MAC entry in original skb's tracker TVLV639* @next_dest: start MAC entry in to be sent skb's tracker TVLV640* @num_dests: number of remaining destination MAC entries to iterate over641*642* This sorts destination entries into either the original batman-adv643* multicast packet or the skb (copy) that is going to be sent to comp_neigh644* next.645*646* In preparation for the next, to be (unicast) transmitted batman-adv multicast647* packet skb to be sent to the given neighbor node, tries to collect all648* originator MAC addresses that have the given neighbor node as their next hop649* in the to be transmitted skb (copy), which next_dest points into. That is we650* zero all destination entries in next_dest which do not have comp_neigh as651* their next hop. And zero all destination entries in the original skb that652* would have comp_neigh as their next hop (to avoid redundant transmissions and653* duplicated payload later).654*/655static void656batadv_mcast_forw_scrub_dests(struct batadv_priv *bat_priv,657struct batadv_neigh_node *comp_neigh, u8 *dest,658u8 *next_dest, u16 num_dests)659{660struct batadv_neigh_node *next_neigh;661662/* skip first entry, this is what we are comparing with */663eth_zero_addr(dest);664dest += ETH_ALEN;665next_dest += ETH_ALEN;666num_dests--;667668batadv_mcast_forw_tracker_for_each_dest2(dest, next_dest, num_dests) {669if (is_zero_ether_addr(next_dest))670continue;671672/* sanity check, we expect unicast destinations */673if (is_multicast_ether_addr(next_dest)) {674eth_zero_addr(dest);675eth_zero_addr(next_dest);676continue;677}678679next_neigh = batadv_orig_to_router(bat_priv, next_dest, NULL);680if (!next_neigh) {681eth_zero_addr(next_dest);682continue;683}684685if (!batadv_compare_eth(next_neigh->addr, comp_neigh->addr)) {686eth_zero_addr(next_dest);687batadv_neigh_node_put(next_neigh);688continue;689}690691/* found an entry for our next packet to transmit, so remove it692* from the original packet693*/694eth_zero_addr(dest);695batadv_neigh_node_put(next_neigh);696}697}698699/**700* batadv_mcast_forw_shrink_fill() - swap slot with next non-zero destination701* @slot: the to be filled zero-MAC destination entry in a tracker TVLV702* @num_dests_slot: remaining entries in tracker TVLV from/including slot703*704* Searches for the next non-zero-MAC destination entry in a tracker TVLV after705* the given slot pointer. And if found, swaps it with the zero-MAC destination706* entry which the slot points to.707*708* Return: true if slot was swapped/filled successfully, false otherwise.709*/710static bool batadv_mcast_forw_shrink_fill(u8 *slot, u16 num_dests_slot)711{712u16 num_dests_filler;713u8 *filler;714715/* sanity check, should not happen */716if (!num_dests_slot)717return false;718719num_dests_filler = num_dests_slot - 1;720filler = slot + ETH_ALEN;721722/* find a candidate to fill the empty slot */723batadv_mcast_forw_tracker_for_each_dest(filler, num_dests_filler) {724if (is_zero_ether_addr(filler))725continue;726727ether_addr_copy(slot, filler);728eth_zero_addr(filler);729return true;730}731732return false;733}734735/**736* batadv_mcast_forw_shrink_pack_dests() - pack destinations of a tracker TVLV737* @skb: the batman-adv multicast packet to compact destinations in738*739* Compacts the originator destination MAC addresses in the multicast tracker740* TVLV of the given multicast packet. This is done by moving all non-zero741* MAC addresses in direction of the skb head and all zero MAC addresses in skb742* tail direction, within the multicast tracker TVLV.743*744* Return: The number of consecutive zero MAC address destinations which are745* now at the end of the multicast tracker TVLV.746*/747static int batadv_mcast_forw_shrink_pack_dests(struct sk_buff *skb)748{749struct batadv_tvlv_mcast_tracker *mcast_tracker;750unsigned char *skb_net_hdr;751u16 num_dests_slot;752u8 *slot;753754skb_net_hdr = skb_network_header(skb);755mcast_tracker = (struct batadv_tvlv_mcast_tracker *)skb_net_hdr;756num_dests_slot = ntohs(mcast_tracker->num_dests);757758slot = (u8 *)mcast_tracker + sizeof(*mcast_tracker);759760batadv_mcast_forw_tracker_for_each_dest(slot, num_dests_slot) {761/* find an empty slot */762if (!is_zero_ether_addr(slot))763continue;764765if (!batadv_mcast_forw_shrink_fill(slot, num_dests_slot))766/* could not find a filler, so we successfully packed767* and can stop - and must not reduce num_dests_slot!768*/769break;770}771772/* num_dests_slot is now the amount of reduced, zeroed773* destinations at the end of the tracker TVLV774*/775return num_dests_slot;776}777778/**779* batadv_mcast_forw_shrink_align_offset() - get new alignment offset780* @num_dests_old: the old, to be updated amount of destination nodes781* @num_dests_reduce: the number of destinations that were removed782*783* Calculates the amount of potential extra alignment offset that is needed to784* adjust the TVLV padding after the change in destination nodes.785*786* Return:787* 0: If no change to padding is needed.788* 2: If padding needs to be removed.789* -2: If padding needs to be added.790*/791static short792batadv_mcast_forw_shrink_align_offset(unsigned int num_dests_old,793unsigned int num_dests_reduce)794{795/* even amount of removed destinations -> no alignment change */796if (!(num_dests_reduce % 2))797return 0;798799/* even to odd amount of destinations -> remove padding */800if (!(num_dests_old % 2))801return 2;802803/* odd to even amount of destinations -> add padding */804return -2;805}806807/**808* batadv_mcast_forw_shrink_update_headers() - update shrunk mc packet headers809* @skb: the batman-adv multicast packet to update headers of810* @num_dests_reduce: the number of destinations that were removed811*812* This updates any fields of a batman-adv multicast packet that are affected813* by the reduced number of destinations in the multicast tracket TVLV. In814* particular this updates:815*816* The num_dest field of the multicast tracker TVLV.817* The TVLV length field of the according generic TVLV header.818* The batman-adv multicast packet's total TVLV length field.819*820* Return: The offset in skb's tail direction at which the new batman-adv821* multicast packet header needs to start.822*/823static unsigned int824batadv_mcast_forw_shrink_update_headers(struct sk_buff *skb,825unsigned int num_dests_reduce)826{827struct batadv_tvlv_mcast_tracker *mcast_tracker;828struct batadv_mcast_packet *mcast_packet;829struct batadv_tvlv_hdr *tvlv_hdr;830unsigned char *skb_net_hdr;831unsigned int offset;832short align_offset;833u16 num_dests;834835skb_net_hdr = skb_network_header(skb);836mcast_tracker = (struct batadv_tvlv_mcast_tracker *)skb_net_hdr;837num_dests = ntohs(mcast_tracker->num_dests);838839align_offset = batadv_mcast_forw_shrink_align_offset(num_dests,840num_dests_reduce);841offset = ETH_ALEN * num_dests_reduce + align_offset;842num_dests -= num_dests_reduce;843844/* update tracker header */845mcast_tracker->num_dests = htons(num_dests);846847/* update tracker's tvlv header's length field */848tvlv_hdr = (struct batadv_tvlv_hdr *)(skb_network_header(skb) -849sizeof(*tvlv_hdr));850tvlv_hdr->len = htons(ntohs(tvlv_hdr->len) - offset);851852/* update multicast packet header's tvlv length field */853mcast_packet = (struct batadv_mcast_packet *)skb->data;854mcast_packet->tvlv_len = htons(ntohs(mcast_packet->tvlv_len) - offset);855856return offset;857}858859/**860* batadv_mcast_forw_shrink_move_headers() - move multicast headers by offset861* @skb: the batman-adv multicast packet to move headers for862* @offset: a non-negative offset to move headers by, towards the skb tail863*864* Moves the batman-adv multicast packet header, its multicast tracker TVLV and865* any TVLVs in between by the given offset in direction towards the tail.866*/867static void868batadv_mcast_forw_shrink_move_headers(struct sk_buff *skb, unsigned int offset)869{870struct batadv_tvlv_mcast_tracker *mcast_tracker;871unsigned char *skb_net_hdr;872unsigned int len;873u16 num_dests;874875skb_net_hdr = skb_network_header(skb);876mcast_tracker = (struct batadv_tvlv_mcast_tracker *)skb_net_hdr;877num_dests = ntohs(mcast_tracker->num_dests);878len = skb_network_offset(skb) + sizeof(*mcast_tracker);879len += num_dests * ETH_ALEN;880881batadv_mcast_forw_scrape(skb, len, offset);882}883884/**885* batadv_mcast_forw_shrink_tracker() - remove zero addresses in a tracker tvlv886* @skb: the batman-adv multicast packet to (potentially) shrink887*888* Removes all destinations with a zero MAC addresses (00:00:00:00:00:00) from889* the given batman-adv multicast packet's tracker TVLV and updates headers890* accordingly to maintain a valid batman-adv multicast packet.891*/892static void batadv_mcast_forw_shrink_tracker(struct sk_buff *skb)893{894unsigned int offset;895u16 dests_reduced;896897dests_reduced = batadv_mcast_forw_shrink_pack_dests(skb);898if (!dests_reduced)899return;900901offset = batadv_mcast_forw_shrink_update_headers(skb, dests_reduced);902batadv_mcast_forw_shrink_move_headers(skb, offset);903}904905/**906* batadv_mcast_forw_packet() - forward a batman-adv multicast packet907* @bat_priv: the bat priv with all the mesh interface information908* @skb: the received or locally generated batman-adv multicast packet909* @local_xmit: indicates that the packet was locally generated and not received910*911* Parses the tracker TVLV of a batman-adv multicast packet and forwards the912* packet as indicated in this TVLV.913*914* Caller needs to set the skb network header to the start of the multicast915* tracker TVLV (excluding the generic TVLV header) and the skb transport header916* to the next byte after this multicast tracker TVLV.917*918* Caller needs to free the skb.919*920* Return: NET_RX_SUCCESS or NET_RX_DROP on success or a negative error921* code on failure. NET_RX_SUCCESS if the received packet is supposed to be922* decapsulated and forwarded to the own mesh interface, NET_RX_DROP otherwise.923*/924static int batadv_mcast_forw_packet(struct batadv_priv *bat_priv,925struct sk_buff *skb, bool local_xmit)926{927struct batadv_tvlv_mcast_tracker *mcast_tracker;928struct batadv_neigh_node *neigh_node;929unsigned long offset, num_dests_off;930struct sk_buff *nexthop_skb;931unsigned char *skb_net_hdr;932bool local_recv = false;933unsigned int tvlv_len;934bool xmitted = false;935u8 *dest, *next_dest;936u16 num_dests;937int ret;938939/* (at least) TVLV part needs to be linearized */940SKB_LINEAR_ASSERT(skb);941942/* check if num_dests is within skb length */943num_dests_off = offsetof(struct batadv_tvlv_mcast_tracker, num_dests);944if (num_dests_off > skb_network_header_len(skb))945return -EINVAL;946947skb_net_hdr = skb_network_header(skb);948mcast_tracker = (struct batadv_tvlv_mcast_tracker *)skb_net_hdr;949num_dests = ntohs(mcast_tracker->num_dests);950951dest = (u8 *)mcast_tracker + sizeof(*mcast_tracker);952953/* check if full tracker tvlv is within skb length */954tvlv_len = sizeof(*mcast_tracker) + ETH_ALEN * num_dests;955if (tvlv_len > skb_network_header_len(skb))956return -EINVAL;957958/* invalidate checksum: */959skb->ip_summed = CHECKSUM_NONE;960961batadv_mcast_forw_tracker_for_each_dest(dest, num_dests) {962if (is_zero_ether_addr(dest))963continue;964965/* only unicast originator addresses supported */966if (is_multicast_ether_addr(dest)) {967eth_zero_addr(dest);968continue;969}970971if (batadv_is_my_mac(bat_priv, dest)) {972eth_zero_addr(dest);973local_recv = true;974continue;975}976977neigh_node = batadv_orig_to_router(bat_priv, dest, NULL);978if (!neigh_node) {979eth_zero_addr(dest);980continue;981}982983nexthop_skb = skb_copy(skb, GFP_ATOMIC);984if (!nexthop_skb) {985batadv_neigh_node_put(neigh_node);986return -ENOMEM;987}988989offset = dest - skb->data;990next_dest = nexthop_skb->data + offset;991992batadv_mcast_forw_scrub_dests(bat_priv, neigh_node, dest,993next_dest, num_dests);994batadv_mcast_forw_shrink_tracker(nexthop_skb);995996batadv_inc_counter(bat_priv, BATADV_CNT_MCAST_TX);997batadv_add_counter(bat_priv, BATADV_CNT_MCAST_TX_BYTES,998nexthop_skb->len + ETH_HLEN);999xmitted = true;1000ret = batadv_send_unicast_skb(nexthop_skb, neigh_node);10011002batadv_neigh_node_put(neigh_node);10031004if (ret < 0)1005return ret;1006}10071008if (xmitted) {1009if (local_xmit) {1010batadv_inc_counter(bat_priv, BATADV_CNT_MCAST_TX_LOCAL);1011batadv_add_counter(bat_priv,1012BATADV_CNT_MCAST_TX_LOCAL_BYTES,1013skb->len -1014skb_transport_offset(skb));1015} else {1016batadv_inc_counter(bat_priv, BATADV_CNT_MCAST_FWD);1017batadv_add_counter(bat_priv, BATADV_CNT_MCAST_FWD_BYTES,1018skb->len + ETH_HLEN);1019}1020}10211022if (local_recv)1023return NET_RX_SUCCESS;1024else1025return NET_RX_DROP;1026}10271028/**1029* batadv_mcast_forw_tracker_tvlv_handler() - handle an mcast tracker tvlv1030* @bat_priv: the bat priv with all the mesh interface information1031* @skb: the received batman-adv multicast packet1032*1033* Parses the tracker TVLV of an incoming batman-adv multicast packet and1034* forwards the packet as indicated in this TVLV.1035*1036* Caller needs to set the skb network header to the start of the multicast1037* tracker TVLV (excluding the generic TVLV header) and the skb transport header1038* to the next byte after this multicast tracker TVLV.1039*1040* Caller needs to free the skb.1041*1042* Return: NET_RX_SUCCESS or NET_RX_DROP on success or a negative error1043* code on failure. NET_RX_SUCCESS if the received packet is supposed to be1044* decapsulated and forwarded to the own mesh interface, NET_RX_DROP otherwise.1045*/1046int batadv_mcast_forw_tracker_tvlv_handler(struct batadv_priv *bat_priv,1047struct sk_buff *skb)1048{1049return batadv_mcast_forw_packet(bat_priv, skb, false);1050}10511052/**1053* batadv_mcast_forw_packet_hdrlen() - multicast packet header length1054* @num_dests: number of destination nodes1055*1056* Calculates the total batman-adv multicast packet header length for a given1057* number of destination nodes (excluding the outer ethernet frame).1058*1059* Return: The calculated total batman-adv multicast packet header length.1060*/1061unsigned int batadv_mcast_forw_packet_hdrlen(unsigned int num_dests)1062{1063/**1064* If the number of destination entries is even then we need to add1065* two byte padding to the tracker TVLV.1066*/1067int padding = (!(num_dests % 2)) ? 2 : 0;10681069return padding + num_dests * ETH_ALEN +1070sizeof(struct batadv_tvlv_mcast_tracker) +1071sizeof(struct batadv_tvlv_hdr) +1072sizeof(struct batadv_mcast_packet);1073}10741075/**1076* batadv_mcast_forw_expand_head() - expand headroom for an mcast packet1077* @bat_priv: the bat priv with all the mesh interface information1078* @skb: the multicast packet to send1079*1080* Tries to expand an skb's headroom so that its head to tail is 12981081* bytes (minimum IPv6 MTU + vlan ethernet header size) large.1082*1083* Return: -EINVAL if the given skb's length is too large or -ENOMEM on memory1084* allocation failure. Otherwise, on success, zero is returned.1085*/1086static int batadv_mcast_forw_expand_head(struct batadv_priv *bat_priv,1087struct sk_buff *skb)1088{1089int hdr_size = VLAN_ETH_HLEN + IPV6_MIN_MTU - skb->len;10901091/* TODO: Could be tightened to actual number of destination nodes?1092* But it's tricky, number of destinations might have increased since1093* we last checked.1094*/1095if (hdr_size < 0) {1096/* batadv_mcast_forw_mode_check_count() should ensure we do not1097* end up here1098*/1099WARN_ON(1);1100return -EINVAL;1101}11021103if (skb_headroom(skb) < hdr_size &&1104pskb_expand_head(skb, hdr_size, 0, GFP_ATOMIC) < 0)1105return -ENOMEM;11061107return 0;1108}11091110/**1111* batadv_mcast_forw_push() - encapsulate skb in a batman-adv multicast packet1112* @bat_priv: the bat priv with all the mesh interface information1113* @skb: the multicast packet to encapsulate and send1114* @vid: the vlan identifier1115* @is_routable: indicates whether the destination is routable1116* @count: the number of originators the multicast packet needs to be sent to1117*1118* Encapsulates the given multicast packet in a batman-adv multicast packet.1119* A multicast tracker TVLV with destination originator addresses for any node1120* that signaled interest in it, that is either via the translation table or the1121* according want-all flags, is attached accordingly.1122*1123* Return: true on success, false otherwise.1124*/1125bool batadv_mcast_forw_push(struct batadv_priv *bat_priv, struct sk_buff *skb,1126unsigned short vid, int is_routable, int count)1127{1128unsigned short tvlv_len = 0;1129int ret;11301131if (batadv_mcast_forw_expand_head(bat_priv, skb) < 0)1132goto err;11331134skb_reset_transport_header(skb);11351136ret = batadv_mcast_forw_push_tvlvs(bat_priv, skb, vid, is_routable,1137count, &tvlv_len);1138if (ret < 0)1139goto err;11401141ret = batadv_mcast_forw_push_hdr(skb, tvlv_len);1142if (ret < 0)1143goto err;11441145return true;11461147err:1148if (tvlv_len)1149skb_pull(skb, tvlv_len);11501151return false;1152}11531154/**1155* batadv_mcast_forw_mcsend() - send a self prepared batman-adv multicast packet1156* @bat_priv: the bat priv with all the mesh interface information1157* @skb: the multicast packet to encapsulate and send1158*1159* Transmits a batman-adv multicast packet that was locally prepared and1160* consumes/frees it.1161*1162* Return: NET_XMIT_DROP on memory allocation failure. NET_XMIT_SUCCESS1163* otherwise.1164*/1165int batadv_mcast_forw_mcsend(struct batadv_priv *bat_priv,1166struct sk_buff *skb)1167{1168int ret = batadv_mcast_forw_packet(bat_priv, skb, true);11691170if (ret < 0) {1171kfree_skb(skb);1172return NET_XMIT_DROP;1173}11741175consume_skb(skb);1176return NET_XMIT_SUCCESS;1177}117811791180