Commit 91dfe8ef authored by Herbert Xu's avatar Herbert Xu Committed by James Morris

[IPV4]: inetdev ifa_list handling fixes outside of net/ipv4.

Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: default avatarDavid S. Miller <davem@redhat.com>
parent 2b12caa0
...@@ -50,6 +50,7 @@ ...@@ -50,6 +50,7 @@
#include <linux/random.h> #include <linux/random.h>
#include <linux/pkt_sched.h> #include <linux/pkt_sched.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/rcupdate.h>
#include <net/syncppp.h> #include <net/syncppp.h>
...@@ -767,9 +768,9 @@ static void sppp_cisco_input (struct sppp *sp, struct sk_buff *skb) ...@@ -767,9 +768,9 @@ static void sppp_cisco_input (struct sppp *sp, struct sk_buff *skb)
struct in_ifaddr *ifa; struct in_ifaddr *ifa;
u32 addr = 0, mask = ~0; /* FIXME: is the mask correct? */ u32 addr = 0, mask = ~0; /* FIXME: is the mask correct? */
#ifdef CONFIG_INET #ifdef CONFIG_INET
if ((in_dev=in_dev_get(dev)) != NULL) rcu_read_lock();
if ((in_dev = __in_dev_get(dev)) != NULL)
{ {
read_lock(&in_dev->lock);
for (ifa=in_dev->ifa_list; ifa != NULL; for (ifa=in_dev->ifa_list; ifa != NULL;
ifa=ifa->ifa_next) { ifa=ifa->ifa_next) {
if (strcmp(dev->name, ifa->ifa_label) == 0) if (strcmp(dev->name, ifa->ifa_label) == 0)
...@@ -779,9 +780,8 @@ static void sppp_cisco_input (struct sppp *sp, struct sk_buff *skb) ...@@ -779,9 +780,8 @@ static void sppp_cisco_input (struct sppp *sp, struct sk_buff *skb)
break; break;
} }
} }
read_unlock(&in_dev->lock);
in_dev_put(in_dev);
} }
rcu_read_unlock();
#endif #endif
/* I hope both addr and mask are in the net order */ /* I hope both addr and mask are in the net order */
sppp_cisco_send (sp, CISCO_ADDR_REPLY, addr, mask); sppp_cisco_send (sp, CISCO_ADDR_REPLY, addr, mask);
......
...@@ -106,6 +106,7 @@ static const char StripVersion[] = "1.3A-STUART.CHESHIRE"; ...@@ -106,6 +106,7 @@ static const char StripVersion[] = "1.3A-STUART.CHESHIRE";
#include <linux/seq_file.h> #include <linux/seq_file.h>
#include <linux/serial.h> #include <linux/serial.h>
#include <linux/serialP.h> #include <linux/serialP.h>
#include <linux/rcupdate.h>
#include <net/arp.h> #include <net/arp.h>
#include <linux/ip.h> #include <linux/ip.h>
...@@ -1348,14 +1349,17 @@ static unsigned char *strip_make_packet(unsigned char *buffer, ...@@ -1348,14 +1349,17 @@ static unsigned char *strip_make_packet(unsigned char *buffer,
*/ */
if (haddr.c[0] == 0xFF) { if (haddr.c[0] == 0xFF) {
u32 brd = 0; u32 brd = 0;
struct in_device *in_dev = in_dev_get(strip_info->dev); struct in_device *in_dev;
if (in_dev == NULL)
rcu_read_lock();
in_dev = __in_dev_get(strip_info->dev);
if (in_dev == NULL) {
rcu_read_unlock();
return NULL; return NULL;
read_lock(&in_dev->lock); }
if (in_dev->ifa_list) if (in_dev->ifa_list)
brd = in_dev->ifa_list->ifa_broadcast; brd = in_dev->ifa_list->ifa_broadcast;
read_unlock(&in_dev->lock); rcu_read_unlock();
in_dev_put(in_dev);
/* arp_query returns 1 if it succeeds in looking up the address, 0 if it fails */ /* arp_query returns 1 if it succeeds in looking up the address, 0 if it fails */
if (!arp_query(haddr.c, brd, strip_info->dev)) { if (!arp_query(haddr.c, brd, strip_info->dev)) {
...@@ -1500,17 +1504,18 @@ static void strip_send(struct strip *strip_info, struct sk_buff *skb) ...@@ -1500,17 +1504,18 @@ static void strip_send(struct strip *strip_info, struct sk_buff *skb)
} }
if (1) { if (1) {
struct in_device *in_dev = in_dev_get(strip_info->dev); struct in_device *in_dev;
brd = addr = 0; brd = addr = 0;
rcu_read_lock();
in_dev = __in_dev_get(strip_info->dev);
if (in_dev) { if (in_dev) {
read_lock(&in_dev->lock);
if (in_dev->ifa_list) { if (in_dev->ifa_list) {
brd = in_dev->ifa_list->ifa_broadcast; brd = in_dev->ifa_list->ifa_broadcast;
addr = in_dev->ifa_list->ifa_local; addr = in_dev->ifa_list->ifa_local;
} }
read_unlock(&in_dev->lock);
in_dev_put(in_dev);
} }
rcu_read_unlock();
} }
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/netpoll.h> #include <linux/netpoll.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/rcupdate.h>
#include <net/tcp.h> #include <net/tcp.h>
#include <net/udp.h> #include <net/udp.h>
...@@ -572,16 +573,18 @@ int netpoll_setup(struct netpoll *np) ...@@ -572,16 +573,18 @@ int netpoll_setup(struct netpoll *np)
memcpy(np->local_mac, ndev->dev_addr, 6); memcpy(np->local_mac, ndev->dev_addr, 6);
if (!np->local_ip) { if (!np->local_ip) {
in_dev = in_dev_get(ndev); rcu_read_lock();
in_dev = __in_dev_get(ndev);
if (!in_dev) { if (!in_dev) {
rcu_read_unlock();
printk(KERN_ERR "%s: no IP address for %s, aborting\n", printk(KERN_ERR "%s: no IP address for %s, aborting\n",
np->name, np->dev_name); np->name, np->dev_name);
goto release; goto release;
} }
np->local_ip = ntohl(in_dev->ifa_list->ifa_local); np->local_ip = ntohl(in_dev->ifa_list->ifa_local);
in_dev_put(in_dev); rcu_read_unlock();
printk(KERN_INFO "%s: local IP %d.%d.%d.%d\n", printk(KERN_INFO "%s: local IP %d.%d.%d.%d\n",
np->name, HIPQUAD(np->local_ip)); np->name, HIPQUAD(np->local_ip));
} }
......
...@@ -70,6 +70,7 @@ ...@@ -70,6 +70,7 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/inet.h> #include <linux/inet.h>
#include <linux/rcupdate.h>
#include <asm/byteorder.h> #include <asm/byteorder.h>
#include <asm/bitops.h> #include <asm/bitops.h>
#include <asm/io.h> #include <asm/io.h>
...@@ -263,14 +264,17 @@ static struct net_device *setup_inject(struct pktgen_info* info) ...@@ -263,14 +264,17 @@ static struct net_device *setup_inject(struct pktgen_info* info)
info->saddr_min = 0; info->saddr_min = 0;
info->saddr_max = 0; info->saddr_max = 0;
if (strlen(info->src_min) == 0) { if (strlen(info->src_min) == 0) {
struct in_device *in_dev = in_dev_get(odev); struct in_device *in_dev;
rcu_read_lock();
in_dev = __in_dev_get(odev);
if (in_dev) { if (in_dev) {
if (in_dev->ifa_list) { if (in_dev->ifa_list) {
info->saddr_min = in_dev->ifa_list->ifa_address; info->saddr_min = in_dev->ifa_list->ifa_address;
info->saddr_max = info->saddr_min; info->saddr_max = info->saddr_min;
} }
in_dev_put(in_dev);
} }
rcu_read_unlock();
} }
else { else {
info->saddr_min = in_aton(info->src_min); info->saddr_min = in_aton(info->src_min);
......
...@@ -39,6 +39,7 @@ ...@@ -39,6 +39,7 @@
#include <net/udp.h> #include <net/udp.h>
#include <net/ip.h> #include <net/ip.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/rcupdate.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/system.h> #include <asm/system.h>
...@@ -401,16 +402,17 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock, ...@@ -401,16 +402,17 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock,
y.x maps to IP a.b.c.x. This should be replaced with something y.x maps to IP a.b.c.x. This should be replaced with something
more flexible and more aware of subnet masks. */ more flexible and more aware of subnet masks. */
{ {
struct in_device *idev = in_dev_get(dev); struct in_device *idev;
unsigned long network = 0; unsigned long network = 0;
rcu_read_lock();
idev = __in_dev_get(dev);
if (idev) { if (idev) {
read_lock(&idev->lock);
if (idev->ifa_list) if (idev->ifa_list)
network = ntohl(idev->ifa_list->ifa_address) & network = ntohl(idev->ifa_list->ifa_address) &
0xffffff00; /* !!! */ 0xffffff00; /* !!! */
read_unlock(&idev->lock);
in_dev_put(idev);
} }
rcu_read_unlock();
udpdest.sin_addr.s_addr = htonl(network | addr.station); udpdest.sin_addr.s_addr = htonl(network | addr.station);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment