···9595 return false;9696}97979898-#define atomic_dec_not_zero(v) atomic_add_unless((v), -1, 0)9998/* create a new aggregated packet and add this packet to it */10099static void new_aggregated_packet(unsigned char *packet_buff, int packet_len,101100 unsigned long send_time, bool direct_link,
+27-18
net/batman-adv/gateway_client.c
···127127 return;128128129129 curr_gw = gw_get_selected_gw_node(bat_priv);130130- if (!curr_gw)130130+ if (curr_gw)131131 goto out;132132133133 rcu_read_lock();···310310 struct hlist_node *node;311311 struct gw_node *gw_node, *curr_gw;312312313313+ /**314314+ * Note: We don't need a NULL check here, since curr_gw never gets315315+ * dereferenced. If curr_gw is NULL we also should not exit as we may316316+ * have this gateway in our list (duplication check!) even though we317317+ * have no currently selected gateway.318318+ */313319 curr_gw = gw_get_selected_gw_node(bat_priv);314314- if (!curr_gw)315315- goto out;316320317321 rcu_read_lock();318322 hlist_for_each_entry_rcu(gw_node, node, &bat_priv->gw_list, list) {···354350 gw_deselect(bat_priv);355351unlock:356352 rcu_read_unlock();357357-out:353353+358354 if (curr_gw)359355 gw_node_free_ref(curr_gw);360356}···439435{440436 struct net_device *net_dev = (struct net_device *)seq->private;441437 struct bat_priv *bat_priv = netdev_priv(net_dev);438438+ struct hard_iface *primary_if;442439 struct gw_node *gw_node;443440 struct hlist_node *node;444444- int gw_count = 0;441441+ int gw_count = 0, ret = 0;445442446446- if (!bat_priv->primary_if) {447447-448448- return seq_printf(seq, "BATMAN mesh %s disabled - please "449449- "specify interfaces to enable it\n",450450- net_dev->name);443443+ primary_if = primary_if_get_selected(bat_priv);444444+ if (!primary_if) {445445+ ret = seq_printf(seq, "BATMAN mesh %s disabled - please "446446+ "specify interfaces to enable it\n",447447+ net_dev->name);448448+ goto out;451449 }452450453453- if (bat_priv->primary_if->if_status != IF_ACTIVE) {454454-455455- return seq_printf(seq, "BATMAN mesh %s disabled - "456456- "primary interface not active\n",457457- net_dev->name);451451+ if (primary_if->if_status != IF_ACTIVE) {452452+ ret = seq_printf(seq, "BATMAN mesh %s disabled - "453453+ "primary interface not active\n",454454+ net_dev->name);455455+ goto out;458456 }459457460458 seq_printf(seq, " %-12s (%s/%i) %17s [%10s]: gw_class ... "461459 "[B.A.T.M.A.N. adv %s%s, MainIF/MAC: %s/%pM (%s)]\n",462460 "Gateway", "#", TQ_MAX_VALUE, "Nexthop",463461 "outgoingIF", SOURCE_VERSION, REVISION_VERSION_STR,464464- bat_priv->primary_if->net_dev->name,465465- bat_priv->primary_if->net_dev->dev_addr, net_dev->name);462462+ primary_if->net_dev->name,463463+ primary_if->net_dev->dev_addr, net_dev->name);466464467465 rcu_read_lock();468466 hlist_for_each_entry_rcu(gw_node, node, &bat_priv->gw_list, list) {···482476 if (gw_count == 0)483477 seq_printf(seq, "No gateways in range ...\n");484478485485- return 0;479479+out:480480+ if (primary_if)481481+ hardif_free_ref(primary_if);482482+ return ret;486483}487484488485int gw_is_target(struct bat_priv *bat_priv, struct sk_buff *skb)
+57-26
net/batman-adv/hard-interface.c
···110110 return hard_iface;111111}112112113113-static void update_primary_addr(struct bat_priv *bat_priv)113113+static void primary_if_update_addr(struct bat_priv *bat_priv)114114{115115 struct vis_packet *vis_packet;116116+ struct hard_iface *primary_if;117117+118118+ primary_if = primary_if_get_selected(bat_priv);119119+ if (!primary_if)120120+ goto out;116121117122 vis_packet = (struct vis_packet *)118123 bat_priv->my_vis_info->skb_packet->data;119119- memcpy(vis_packet->vis_orig,120120- bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN);124124+ memcpy(vis_packet->vis_orig, primary_if->net_dev->dev_addr, ETH_ALEN);121125 memcpy(vis_packet->sender_orig,122122- bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN);126126+ primary_if->net_dev->dev_addr, ETH_ALEN);127127+128128+out:129129+ if (primary_if)130130+ hardif_free_ref(primary_if);123131}124132125125-static void set_primary_if(struct bat_priv *bat_priv,126126- struct hard_iface *hard_iface)133133+static void primary_if_select(struct bat_priv *bat_priv,134134+ struct hard_iface *new_hard_iface)127135{136136+ struct hard_iface *curr_hard_iface;128137 struct batman_packet *batman_packet;129129- struct hard_iface *old_if;130138131131- if (hard_iface && !atomic_inc_not_zero(&hard_iface->refcount))132132- hard_iface = NULL;139139+ spin_lock_bh(&hardif_list_lock);133140134134- old_if = bat_priv->primary_if;135135- bat_priv->primary_if = hard_iface;141141+ if (new_hard_iface && !atomic_inc_not_zero(&new_hard_iface->refcount))142142+ new_hard_iface = NULL;136143137137- if (old_if)138138- hardif_free_ref(old_if);144144+ curr_hard_iface = bat_priv->primary_if;145145+ rcu_assign_pointer(bat_priv->primary_if, new_hard_iface);139146140140- if (!bat_priv->primary_if)141141- return;147147+ if (curr_hard_iface)148148+ hardif_free_ref(curr_hard_iface);142149143143- batman_packet = (struct batman_packet *)(hard_iface->packet_buff);150150+ if (!new_hard_iface)151151+ goto out;152152+153153+ batman_packet = (struct batman_packet *)(new_hard_iface->packet_buff);144154 batman_packet->flags = PRIMARIES_FIRST_HOP;145155 batman_packet->ttl = TTL;146156147147- update_primary_addr(bat_priv);157157+ primary_if_update_addr(bat_priv);148158149159 /***150160 * hacky trick to make sure that we send the HNA information via151161 * our new primary interface152162 */153163 atomic_set(&bat_priv->hna_local_changed, 1);164164+165165+out:166166+ spin_unlock_bh(&hardif_list_lock);154167}155168156169static bool hardif_is_iface_up(struct hard_iface *hard_iface)···249236static void hardif_activate_interface(struct hard_iface *hard_iface)250237{251238 struct bat_priv *bat_priv;239239+ struct hard_iface *primary_if = NULL;252240253241 if (hard_iface->if_status != IF_INACTIVE)254254- return;242242+ goto out;255243256244 bat_priv = netdev_priv(hard_iface->soft_iface);257245···263249 * the first active interface becomes our primary interface or264250 * the next active interface after the old primay interface was removed265251 */266266- if (!bat_priv->primary_if)267267- set_primary_if(bat_priv, hard_iface);252252+ primary_if = primary_if_get_selected(bat_priv);253253+ if (!primary_if)254254+ primary_if_select(bat_priv, hard_iface);268255269256 bat_info(hard_iface->soft_iface, "Interface activated: %s\n",270257 hard_iface->net_dev->name);271258272259 update_min_mtu(hard_iface->soft_iface);273273- return;260260+261261+out:262262+ if (primary_if)263263+ hardif_free_ref(primary_if);274264}275265276266static void hardif_deactivate_interface(struct hard_iface *hard_iface)···404386void hardif_disable_interface(struct hard_iface *hard_iface)405387{406388 struct bat_priv *bat_priv = netdev_priv(hard_iface->soft_iface);389389+ struct hard_iface *primary_if = NULL;407390408391 if (hard_iface->if_status == IF_ACTIVE)409392 hardif_deactivate_interface(hard_iface);410393411394 if (hard_iface->if_status != IF_INACTIVE)412412- return;395395+ goto out;413396414397 bat_info(hard_iface->soft_iface, "Removing interface: %s\n",415398 hard_iface->net_dev->name);···419400 bat_priv->num_ifaces--;420401 orig_hash_del_if(hard_iface, bat_priv->num_ifaces);421402422422- if (hard_iface == bat_priv->primary_if) {403403+ primary_if = primary_if_get_selected(bat_priv);404404+ if (hard_iface == primary_if) {423405 struct hard_iface *new_if;424406425407 new_if = hardif_get_active(hard_iface->soft_iface);426426- set_primary_if(bat_priv, new_if);408408+ primary_if_select(bat_priv, new_if);427409428410 if (new_if)429411 hardif_free_ref(new_if);···445425446426 hard_iface->soft_iface = NULL;447427 hardif_free_ref(hard_iface);428428+429429+out:430430+ if (primary_if)431431+ hardif_free_ref(primary_if);448432}449433450434static struct hard_iface *hardif_add_interface(struct net_device *net_dev)···538514{539515 struct net_device *net_dev = (struct net_device *)ptr;540516 struct hard_iface *hard_iface = hardif_get_by_netdev(net_dev);517517+ struct hard_iface *primary_if = NULL;541518 struct bat_priv *bat_priv;542519543520 if (!hard_iface && event == NETDEV_REGISTER)···574549 update_mac_addresses(hard_iface);575550576551 bat_priv = netdev_priv(hard_iface->soft_iface);577577- if (hard_iface == bat_priv->primary_if)578578- update_primary_addr(bat_priv);552552+ primary_if = primary_if_get_selected(bat_priv);553553+ if (!primary_if)554554+ goto hardif_put;555555+556556+ if (hard_iface == primary_if)557557+ primary_if_update_addr(bat_priv);579558 break;580559 default:581560 break;···588559hardif_put:589560 hardif_free_ref(hard_iface);590561out:562562+ if (primary_if)563563+ hardif_free_ref(primary_if);591564 return NOTIFY_DONE;592565}593566