diff options
author | David S. Miller <davem@davemloft.net> | 2008-06-16 21:25:48 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-06-16 21:25:48 -0400 |
commit | caea902f72b053fd0c76d0d3b6b2e057beb3fc64 (patch) | |
tree | 74e8d476b2c51480420e2ef7c9bbae249b6edbc9 /net/ipv6/sit.c | |
parent | 0b4419162aa6c4204843f3a13b48d9ab821d3167 (diff) | |
parent | 65c3e4715b1b934f8dcc002d9f46b4371ca7a9b1 (diff) |
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
Conflicts:
drivers/net/wireless/rt2x00/Kconfig
drivers/net/wireless/rt2x00/rt2x00usb.c
net/sctp/protocol.c
Diffstat (limited to 'net/ipv6/sit.c')
-rw-r--r-- | net/ipv6/sit.c | 44 |
1 files changed, 24 insertions, 20 deletions
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index b0c5080420a8..b7a50e968506 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c | |||
@@ -220,15 +220,18 @@ __ipip6_tunnel_locate_prl(struct ip_tunnel *t, __be32 addr) | |||
220 | 220 | ||
221 | } | 221 | } |
222 | 222 | ||
223 | static int ipip6_tunnel_get_prl(struct ip_tunnel *t, struct ip_tunnel_prl *a) | 223 | static int ipip6_tunnel_get_prl(struct ip_tunnel *t, |
224 | struct ip_tunnel_prl __user *a) | ||
224 | { | 225 | { |
225 | struct ip_tunnel_prl *kp; | 226 | struct ip_tunnel_prl kprl, *kp; |
226 | struct ip_tunnel_prl_entry *prl; | 227 | struct ip_tunnel_prl_entry *prl; |
227 | unsigned int cmax, c = 0, ca, len; | 228 | unsigned int cmax, c = 0, ca, len; |
228 | int ret = 0; | 229 | int ret = 0; |
229 | 230 | ||
230 | cmax = a->datalen / sizeof(*a); | 231 | if (copy_from_user(&kprl, a, sizeof(kprl))) |
231 | if (cmax > 1 && a->addr != htonl(INADDR_ANY)) | 232 | return -EFAULT; |
233 | cmax = kprl.datalen / sizeof(kprl); | ||
234 | if (cmax > 1 && kprl.addr != htonl(INADDR_ANY)) | ||
232 | cmax = 1; | 235 | cmax = 1; |
233 | 236 | ||
234 | /* For simple GET or for root users, | 237 | /* For simple GET or for root users, |
@@ -259,26 +262,25 @@ static int ipip6_tunnel_get_prl(struct ip_tunnel *t, struct ip_tunnel_prl *a) | |||
259 | for (prl = t->prl; prl; prl = prl->next) { | 262 | for (prl = t->prl; prl; prl = prl->next) { |
260 | if (c > cmax) | 263 | if (c > cmax) |
261 | break; | 264 | break; |
262 | if (a->addr != htonl(INADDR_ANY) && prl->addr != a->addr) | 265 | if (kprl.addr != htonl(INADDR_ANY) && prl->addr != kprl.addr) |
263 | continue; | 266 | continue; |
264 | kp[c].addr = prl->addr; | 267 | kp[c].addr = prl->addr; |
265 | kp[c].flags = prl->flags; | 268 | kp[c].flags = prl->flags; |
266 | c++; | 269 | c++; |
267 | if (a->addr != htonl(INADDR_ANY)) | 270 | if (kprl.addr != htonl(INADDR_ANY)) |
268 | break; | 271 | break; |
269 | } | 272 | } |
270 | out: | 273 | out: |
271 | read_unlock(&ipip6_lock); | 274 | read_unlock(&ipip6_lock); |
272 | 275 | ||
273 | len = sizeof(*kp) * c; | 276 | len = sizeof(*kp) * c; |
274 | ret = len ? copy_to_user(a->data, kp, len) : 0; | 277 | ret = 0; |
278 | if ((len && copy_to_user(a + 1, kp, len)) || put_user(len, &a->datalen)) | ||
279 | ret = -EFAULT; | ||
275 | 280 | ||
276 | kfree(kp); | 281 | kfree(kp); |
277 | if (ret) | ||
278 | return -EFAULT; | ||
279 | 282 | ||
280 | a->datalen = len; | 283 | return ret; |
281 | return 0; | ||
282 | } | 284 | } |
283 | 285 | ||
284 | static int | 286 | static int |
@@ -871,11 +873,20 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) | |||
871 | break; | 873 | break; |
872 | 874 | ||
873 | case SIOCGETPRL: | 875 | case SIOCGETPRL: |
876 | err = -EINVAL; | ||
877 | if (dev == sitn->fb_tunnel_dev) | ||
878 | goto done; | ||
879 | err = -ENOENT; | ||
880 | if (!(t = netdev_priv(dev))) | ||
881 | goto done; | ||
882 | err = ipip6_tunnel_get_prl(t, ifr->ifr_ifru.ifru_data); | ||
883 | break; | ||
884 | |||
874 | case SIOCADDPRL: | 885 | case SIOCADDPRL: |
875 | case SIOCDELPRL: | 886 | case SIOCDELPRL: |
876 | case SIOCCHGPRL: | 887 | case SIOCCHGPRL: |
877 | err = -EPERM; | 888 | err = -EPERM; |
878 | if (cmd != SIOCGETPRL && !capable(CAP_NET_ADMIN)) | 889 | if (!capable(CAP_NET_ADMIN)) |
879 | goto done; | 890 | goto done; |
880 | err = -EINVAL; | 891 | err = -EINVAL; |
881 | if (dev == sitn->fb_tunnel_dev) | 892 | if (dev == sitn->fb_tunnel_dev) |
@@ -888,12 +899,6 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) | |||
888 | goto done; | 899 | goto done; |
889 | 900 | ||
890 | switch (cmd) { | 901 | switch (cmd) { |
891 | case SIOCGETPRL: | ||
892 | err = ipip6_tunnel_get_prl(t, &prl); | ||
893 | if (!err && copy_to_user(ifr->ifr_ifru.ifru_data, | ||
894 | &prl, sizeof(prl))) | ||
895 | err = -EFAULT; | ||
896 | break; | ||
897 | case SIOCDELPRL: | 902 | case SIOCDELPRL: |
898 | err = ipip6_tunnel_del_prl(t, &prl); | 903 | err = ipip6_tunnel_del_prl(t, &prl); |
899 | break; | 904 | break; |
@@ -902,8 +907,7 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) | |||
902 | err = ipip6_tunnel_add_prl(t, &prl, cmd == SIOCCHGPRL); | 907 | err = ipip6_tunnel_add_prl(t, &prl, cmd == SIOCCHGPRL); |
903 | break; | 908 | break; |
904 | } | 909 | } |
905 | if (cmd != SIOCGETPRL) | 910 | netdev_state_change(dev); |
906 | netdev_state_change(dev); | ||
907 | break; | 911 | break; |
908 | 912 | ||
909 | default: | 913 | default: |