X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=net%2Fipv4%2Fdevinet.c;h=a85a45964d4230a21498a7672bde2186d8abc368;hb=9bf4aaab3e101692164d49b7ca357651eb691cb6;hp=c9cd619cf43e7c1d2591a5744d56ac1fb80f2d1e;hpb=5273a3df6485dc2ad6aa7ddd441b9a21970f003b;p=linux-2.6.git diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index c9cd619cf..a85a45964 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c @@ -488,8 +488,35 @@ static __inline__ int inet_abc_len(u32 addr) return rc; } +/* + Check that a device is not member of the ipv4root assigned to the process + Return true if this is the case -int devinet_ioctl(unsigned int cmd, void *arg) + If the process is not bound to specific IP, then it returns 0 (all + interface are fine). +*/ +static inline int devinet_notiproot (struct in_ifaddr *ifa) +{ + int ret = 0; + struct nx_info *nxi; + + if ((nxi = current->nx_info)) { + int i; + int nbip = nxi->nbipv4; + __u32 addr = ifa->ifa_local; + ret = 1; + for (i=0; iipv4[i] == addr) { + ret = 0; + break; + } + } + } + return ret; +} + + +int devinet_ioctl(unsigned int cmd, void __user *arg) { struct ifreq ifr; struct sockaddr_in sin_orig; @@ -595,6 +622,8 @@ int devinet_ioctl(unsigned int cmd, void *arg) ret = -EADDRNOTAVAIL; if (!ifa && cmd != SIOCSIFADDR && cmd != SIOCSIFFLAGS) goto done; + if (!ifa_in_nx_info(ifa, current->nx_info)) + goto done; switch(cmd) { case SIOCGIFADDR: /* Get interface address */ @@ -699,6 +728,20 @@ int devinet_ioctl(unsigned int cmd, void *arg) inet_del_ifa(in_dev, ifap, 0); ifa->ifa_mask = sin->sin_addr.s_addr; ifa->ifa_prefixlen = inet_mask_len(ifa->ifa_mask); + + /* See if current broadcast address matches + * with current netmask, then recalculate + * the broadcast address. Otherwise it's a + * funny address, so don't touch it since + * the user seems to know what (s)he's doing... + */ + if ((dev->flags & IFF_BROADCAST) && + (ifa->ifa_prefixlen < 31) && + (ifa->ifa_broadcast == + (ifa->ifa_local|~ifa->ifa_mask))) { + ifa->ifa_broadcast = (ifa->ifa_local | + ~sin->sin_addr.s_addr); + } inet_insert_ifa(ifa); } break; @@ -713,7 +756,7 @@ rarok: goto out; } -static int inet_gifconf(struct net_device *dev, char *buf, int len) +static int inet_gifconf(struct net_device *dev, char __user *buf, int len) { struct in_device *in_dev = __in_dev_get(dev); struct in_ifaddr *ifa; @@ -724,6 +767,8 @@ static int inet_gifconf(struct net_device *dev, char *buf, int len) goto out; for (; ifa; ifa = ifa->ifa_next) { + if (!ifa_in_nx_info(ifa, current->nx_info)) + continue; if (!buf) { done += sizeof(ifr); continue; @@ -1059,6 +1104,8 @@ static int inet_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb) read_lock(&in_dev->lock); for (ifa = in_dev->ifa_list, ip_idx = 0; ifa; ifa = ifa->ifa_next, ip_idx++) { + if (!ifa_in_nx_info(ifa, current->nx_info)) + continue; if (ip_idx < s_ip_idx) continue; if (inet_fill_ifaddr(skb, ifa, NETLINK_CB(cb->skb).pid, @@ -1136,12 +1183,12 @@ void inet_forward_change(void) } static int devinet_sysctl_forward(ctl_table *ctl, int write, - struct file* filp, void *buffer, - size_t *lenp) + struct file* filp, void __user *buffer, + size_t *lenp, loff_t *ppos) { int *valp = ctl->data; int val = *valp; - int ret = proc_dointvec(ctl, write, filp, buffer, lenp); + int ret = proc_dointvec(ctl, write, filp, buffer, lenp, ppos); if (write && *valp != val) { if (valp == &ipv4_devconf.forwarding) @@ -1154,12 +1201,12 @@ static int devinet_sysctl_forward(ctl_table *ctl, int write, } int ipv4_doint_and_flush(ctl_table *ctl, int write, - struct file* filp, void *buffer, - size_t *lenp) + struct file* filp, void __user *buffer, + size_t *lenp, loff_t *ppos) { int *valp = ctl->data; int val = *valp; - int ret = proc_dointvec(ctl, write, filp, buffer, lenp); + int ret = proc_dointvec(ctl, write, filp, buffer, lenp, ppos); if (write && *valp != val) rt_cache_flush(0); @@ -1167,9 +1214,9 @@ int ipv4_doint_and_flush(ctl_table *ctl, int write, return ret; } -int ipv4_doint_and_flush_strategy(ctl_table *table, int *name, int nlen, - void *oldval, size_t *oldlenp, - void *newval, size_t newlen, +int ipv4_doint_and_flush_strategy(ctl_table *table, int __user *name, int nlen, + void __user *oldval, size_t __user *oldlenp, + void __user *newval, size_t newlen, void **context) { int *valp = table->data; @@ -1181,7 +1228,7 @@ int ipv4_doint_and_flush_strategy(ctl_table *table, int *name, int nlen, if (newlen != sizeof(int)) return -EINVAL; - if (get_user(new, (int *)newval)) + if (get_user(new, (int __user *)newval)) return -EFAULT; if (new == *valp)