summaryrefslogtreecommitdiffstats
path: root/net/ipv4/devinet.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4/devinet.c')
-rw-r--r--net/ipv4/devinet.c34
1 files changed, 20 insertions, 14 deletions
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index c8b0fbbc8..ff2c930d1 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -1,7 +1,7 @@
/*
* NET3 IP device support routines.
*
- * Version: $Id: devinet.c,v 1.28 1999/05/08 20:00:16 davem Exp $
+ * Version: $Id: devinet.c,v 1.32 1999/06/09 11:15:33 davem Exp $
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -607,41 +607,39 @@ inet_gifconf(struct device *dev, char *buf, int len)
{
struct in_device *in_dev = dev->ip_ptr;
struct in_ifaddr *ifa;
- struct ifreq ifr;
+ struct ifreq *ifr = (struct ifreq *) buf;
int done=0;
if (in_dev==NULL || (ifa=in_dev->ifa_list)==NULL)
return 0;
for ( ; ifa; ifa = ifa->ifa_next) {
- if (!buf) {
+ if (!ifr) {
done += sizeof(ifr);
continue;
}
if (len < (int) sizeof(ifr))
return done;
- memset(&ifr, 0, sizeof(struct ifreq));
+ memset(ifr, 0, sizeof(struct ifreq));
if (ifa->ifa_label)
- strcpy(ifr.ifr_name, ifa->ifa_label);
+ strcpy(ifr->ifr_name, ifa->ifa_label);
else
- strcpy(ifr.ifr_name, dev->name);
+ strcpy(ifr->ifr_name, dev->name);
- (*(struct sockaddr_in *) &ifr.ifr_addr).sin_family = AF_INET;
- (*(struct sockaddr_in *) &ifr.ifr_addr).sin_addr.s_addr = ifa->ifa_local;
+ (*(struct sockaddr_in *) &ifr->ifr_addr).sin_family = AF_INET;
+ (*(struct sockaddr_in *) &ifr->ifr_addr).sin_addr.s_addr = ifa->ifa_local;
- if (copy_to_user(buf, &ifr, sizeof(struct ifreq)))
- return -EFAULT;
- buf += sizeof(struct ifreq);
+ ifr++;
len -= sizeof(struct ifreq);
done += sizeof(struct ifreq);
}
return done;
}
-u32 inet_select_addr(struct device *dev, u32 dst, int scope)
+u32 inet_select_addr(const struct device *dev, u32 dst, int scope)
{
u32 addr = 0;
- struct in_device *in_dev = dev->ip_ptr;
+ const struct in_device *in_dev = dev->ip_ptr;
if (in_dev == NULL)
return 0;
@@ -661,15 +659,19 @@ u32 inet_select_addr(struct device *dev, u32 dst, int scope)
in this case. It is importnat that lo is the first interface
in dev_base list.
*/
+ read_lock(&dev_base_lock);
for (dev=dev_base; dev; dev=dev->next) {
if ((in_dev=dev->ip_ptr) == NULL)
continue;
for_primary_ifa(in_dev) {
- if (ifa->ifa_scope <= scope)
+ if (ifa->ifa_scope <= scope) {
+ read_unlock(&dev_base_lock);
return ifa->ifa_local;
+ }
} endfor_ifa(in_dev);
}
+ read_unlock(&dev_base_lock);
return 0;
}
@@ -790,6 +792,7 @@ static int inet_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
s_idx = cb->args[0];
s_ip_idx = ip_idx = cb->args[1];
+ read_lock(&dev_base_lock);
for (dev=dev_base, idx=0; dev; dev = dev->next, idx++) {
if (idx < s_idx)
continue;
@@ -807,6 +810,7 @@ static int inet_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
}
}
done:
+ read_unlock(&dev_base_lock);
cb->args[0] = idx;
cb->args[1] = ip_idx;
@@ -881,11 +885,13 @@ void inet_forward_change()
ipv4_devconf.accept_redirects = !on;
ipv4_devconf_dflt.forwarding = on;
+ read_lock(&dev_base_lock);
for (dev = dev_base; dev; dev = dev->next) {
struct in_device *in_dev = dev->ip_ptr;
if (in_dev)
in_dev->cnf.forwarding = on;
}
+ read_unlock(&dev_base_lock);
rt_cache_flush(0);