patch-2.4.19 linux-2.4.19/net/netrom/nr_route.c

Next file: linux-2.4.19/net/netsyms.c
Previous file: linux-2.4.19/net/netrom/nr_loopback.c
Back to the patch index
Back to the overall index

diff -urN linux-2.4.18/net/netrom/nr_route.c linux-2.4.19/net/netrom/nr_route.c
@@ -19,6 +19,7 @@
  *			Alan Cox(GW4PTS) Added the firewall hooks.
  *	NET/ROM 006	Jonathan(G4KLX)	Added the setting of digipeated neighbours.
  *			Tomi(OH2BNS)	Routing quality and link failure changes.
+ *					Device refcnt fixes.
  */
 
 #include <linux/errno.h>
@@ -66,11 +67,15 @@
 	struct nr_node  *nr_node;
 	struct nr_neigh *nr_neigh;
 	struct nr_route nr_route;
+	struct net_device *tdev;
 	unsigned long flags;
 	int i, found;
 
-	if (nr_dev_get(nr) != NULL)	/* Can't add routes to ourself */
+	/* Can't add routes to ourself */
+	if ((tdev = nr_dev_get(nr)) != NULL) {
+		dev_put(tdev);
 		return -EINVAL;
+	}
 
 	for (nr_node = nr_node_list; nr_node != NULL; nr_node = nr_node->next)
 		if (ax25cmp(nr, &nr_node->callsign) == 0)
@@ -124,6 +129,8 @@
 			memcpy(nr_neigh->digipeat, ax25_digi, sizeof(ax25_digi));
 		}
 
+		dev_hold(nr_neigh->dev);
+
 		save_flags(flags);
 		cli();
 
@@ -294,6 +301,7 @@
 	if ((s = nr_neigh_list) == nr_neigh) {
 		nr_neigh_list = nr_neigh->next;
 		restore_flags(flags);
+		dev_put(nr_neigh->dev);
 		if (nr_neigh->digipeat != NULL)
 			kfree(nr_neigh->digipeat);
 		kfree(nr_neigh);
@@ -304,6 +312,7 @@
 		if (s->next == nr_neigh) {
 			s->next = nr_neigh->next;
 			restore_flags(flags);
+			dev_put(nr_neigh->dev);
 			if (nr_neigh->digipeat != NULL)
 				kfree(nr_neigh->digipeat);
 			kfree(nr_neigh);
@@ -404,6 +413,8 @@
 		memcpy(nr_neigh->digipeat, ax25_digi, sizeof(ax25_digi));
 	}
 
+	dev_hold(nr_neigh->dev);
+
 	save_flags(flags);
 	cli();
 
@@ -570,6 +581,10 @@
 			if (first == NULL || strncmp(dev->name, first->name, 3) < 0)
 				first = dev;
 	}
+
+	if (first != NULL)
+		dev_hold(first);
+
 	read_unlock(&dev_base_lock);
 
 	return first;
@@ -620,6 +635,7 @@
 {
 	struct nr_route_struct nr_route;
 	struct net_device *dev;
+	int ret;
 
 	switch (cmd) {
 
@@ -628,23 +644,30 @@
 				return -EFAULT;
 			if ((dev = nr_ax25_dev_get(nr_route.device)) == NULL)
 				return -EINVAL;
-			if (nr_route.ndigis < 0 || nr_route.ndigis > AX25_MAX_DIGIS)
+			if (nr_route.ndigis < 0 || nr_route.ndigis > AX25_MAX_DIGIS) {
+				dev_put(dev);
 				return -EINVAL;
+			}
 			switch (nr_route.type) {
 				case NETROM_NODE:
-					return nr_add_node(&nr_route.callsign,
+					ret = nr_add_node(&nr_route.callsign,
 						nr_route.mnemonic,
 						&nr_route.neighbour,
 						nr_call_to_digi(nr_route.ndigis, nr_route.digipeaters),
 						dev, nr_route.quality,
 						nr_route.obs_count);
+					break;
 				case NETROM_NEIGH:
-					return nr_add_neigh(&nr_route.callsign,
+					ret = nr_add_neigh(&nr_route.callsign,
 						nr_call_to_digi(nr_route.ndigis, nr_route.digipeaters),
 						dev, nr_route.quality);
+					break;
 				default:
-					return -EINVAL;
+					ret = -EINVAL;
+					break;
 			}
+			dev_put(dev);
+			return ret;
 
 		case SIOCDELRT:
 			if (copy_from_user(&nr_route, arg, sizeof(struct nr_route_struct)))
@@ -653,14 +676,19 @@
 				return -EINVAL;
 			switch (nr_route.type) {
 				case NETROM_NODE:
-					return nr_del_node(&nr_route.callsign,
+					ret = nr_del_node(&nr_route.callsign,
 						&nr_route.neighbour, dev);
+					break;
 				case NETROM_NEIGH:
-					return nr_del_neigh(&nr_route.callsign,
+					ret = nr_del_neigh(&nr_route.callsign,
 						dev, nr_route.quality);
+					break;
 				default:
-					return -EINVAL;
+					ret = -EINVAL;
+					break;
 			}
+			dev_put(dev);
+			return ret;
 
 		case SIOCNRDECOBS:
 			return nr_dec_obs();
@@ -717,10 +745,15 @@
 			    ax25->ax25_dev->dev, 0, sysctl_netrom_obsolescence_count_initialiser);
 
 	if ((dev = nr_dev_get(nr_dest)) != NULL) {	/* Its for me */
+		int ret;
+
 		if (ax25 == NULL)			/* Its from me */
-			return nr_loopback_queue(skb);
+			ret = nr_loopback_queue(skb);
 		else
-			return nr_rx_frame(skb, dev);
+			ret = nr_rx_frame(skb, dev);
+
+		dev_put(dev);
+		return ret;
 	}
 
 	if (!sysctl_netrom_routing_control && ax25 != NULL)
@@ -747,6 +780,8 @@
 
 	nr_neigh->ax25 = ax25_send_frame(skb, 256, (ax25_address *)dev->dev_addr, &nr_neigh->callsign, nr_neigh->digipeat, nr_neigh->dev);
 
+	dev_put(dev);
+
 	return (nr_neigh->ax25 != NULL);
 }
 

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)