aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/sit.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2008-06-16 21:25:48 -0400
committerDavid S. Miller <davem@davemloft.net>2008-06-16 21:25:48 -0400
commitcaea902f72b053fd0c76d0d3b6b2e057beb3fc64 (patch)
tree74e8d476b2c51480420e2ef7c9bbae249b6edbc9 /net/ipv6/sit.c
parent0b4419162aa6c4204843f3a13b48d9ab821d3167 (diff)
parent65c3e4715b1b934f8dcc002d9f46b4371ca7a9b1 (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.c44
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
223static int ipip6_tunnel_get_prl(struct ip_tunnel *t, struct ip_tunnel_prl *a) 223static 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 }
270out: 273out:
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
284static int 286static 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: