aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/raw.c
diff options
context:
space:
mode:
authorAndrea Bastoni <bastoni@cs.unc.edu>2010-05-30 19:16:45 -0400
committerAndrea Bastoni <bastoni@cs.unc.edu>2010-05-30 19:16:45 -0400
commitada47b5fe13d89735805b566185f4885f5a3f750 (patch)
tree644b88f8a71896307d71438e9b3af49126ffb22b /net/ipv6/raw.c
parent43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff)
parent3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff)
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'net/ipv6/raw.c')
-rw-r--r--net/ipv6/raw.c65
1 files changed, 31 insertions, 34 deletions
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index 4f24570b0869..8763b1a0814a 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -21,6 +21,7 @@
21#include <linux/errno.h> 21#include <linux/errno.h>
22#include <linux/types.h> 22#include <linux/types.h>
23#include <linux/socket.h> 23#include <linux/socket.h>
24#include <linux/slab.h>
24#include <linux/sockios.h> 25#include <linux/sockios.h>
25#include <linux/net.h> 26#include <linux/net.h>
26#include <linux/in6.h> 27#include <linux/in6.h>
@@ -72,7 +73,7 @@ static struct sock *__raw_v6_lookup(struct net *net, struct sock *sk,
72 int is_multicast = ipv6_addr_is_multicast(loc_addr); 73 int is_multicast = ipv6_addr_is_multicast(loc_addr);
73 74
74 sk_for_each_from(sk, node) 75 sk_for_each_from(sk, node)
75 if (inet_sk(sk)->num == num) { 76 if (inet_sk(sk)->inet_num == num) {
76 struct ipv6_pinfo *np = inet6_sk(sk); 77 struct ipv6_pinfo *np = inet6_sk(sk);
77 78
78 if (!net_eq(sock_net(sk), net)) 79 if (!net_eq(sock_net(sk), net))
@@ -249,7 +250,7 @@ static int rawv6_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len)
249 250
250 /* Raw sockets are IPv6 only */ 251 /* Raw sockets are IPv6 only */
251 if (addr_type == IPV6_ADDR_MAPPED) 252 if (addr_type == IPV6_ADDR_MAPPED)
252 return(-EADDRNOTAVAIL); 253 return -EADDRNOTAVAIL;
253 254
254 lock_sock(sk); 255 lock_sock(sk);
255 256
@@ -257,6 +258,7 @@ static int rawv6_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len)
257 if (sk->sk_state != TCP_CLOSE) 258 if (sk->sk_state != TCP_CLOSE)
258 goto out; 259 goto out;
259 260
261 rcu_read_lock();
260 /* Check if the address belongs to the host. */ 262 /* Check if the address belongs to the host. */
261 if (addr_type != IPV6_ADDR_ANY) { 263 if (addr_type != IPV6_ADDR_ANY) {
262 struct net_device *dev = NULL; 264 struct net_device *dev = NULL;
@@ -272,13 +274,13 @@ static int rawv6_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len)
272 274
273 /* Binding to link-local address requires an interface */ 275 /* Binding to link-local address requires an interface */
274 if (!sk->sk_bound_dev_if) 276 if (!sk->sk_bound_dev_if)
275 goto out; 277 goto out_unlock;
276 278
277 dev = dev_get_by_index(sock_net(sk), sk->sk_bound_dev_if); 279 err = -ENODEV;
278 if (!dev) { 280 dev = dev_get_by_index_rcu(sock_net(sk),
279 err = -ENODEV; 281 sk->sk_bound_dev_if);
280 goto out; 282 if (!dev)
281 } 283 goto out_unlock;
282 } 284 }
283 285
284 /* ipv4 addr of the socket is invalid. Only the 286 /* ipv4 addr of the socket is invalid. Only the
@@ -289,20 +291,18 @@ static int rawv6_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len)
289 err = -EADDRNOTAVAIL; 291 err = -EADDRNOTAVAIL;
290 if (!ipv6_chk_addr(sock_net(sk), &addr->sin6_addr, 292 if (!ipv6_chk_addr(sock_net(sk), &addr->sin6_addr,
291 dev, 0)) { 293 dev, 0)) {
292 if (dev) 294 goto out_unlock;
293 dev_put(dev);
294 goto out;
295 } 295 }
296 } 296 }
297 if (dev)
298 dev_put(dev);
299 } 297 }
300 298
301 inet->rcv_saddr = inet->saddr = v4addr; 299 inet->inet_rcv_saddr = inet->inet_saddr = v4addr;
302 ipv6_addr_copy(&np->rcv_saddr, &addr->sin6_addr); 300 ipv6_addr_copy(&np->rcv_saddr, &addr->sin6_addr);
303 if (!(addr_type & IPV6_ADDR_MULTICAST)) 301 if (!(addr_type & IPV6_ADDR_MULTICAST))
304 ipv6_addr_copy(&np->saddr, &addr->sin6_addr); 302 ipv6_addr_copy(&np->saddr, &addr->sin6_addr);
305 err = 0; 303 err = 0;
304out_unlock:
305 rcu_read_unlock();
306out: 306out:
307 release_sock(sk); 307 release_sock(sk);
308 return err; 308 return err;
@@ -381,8 +381,7 @@ static inline int rawv6_rcv_skb(struct sock * sk, struct sk_buff * skb)
381 } 381 }
382 382
383 /* Charge it to the socket. */ 383 /* Charge it to the socket. */
384 if (sock_queue_rcv_skb(sk,skb)<0) { 384 if (sock_queue_rcv_skb(sk, skb) < 0) {
385 atomic_inc(&sk->sk_drops);
386 kfree_skb(skb); 385 kfree_skb(skb);
387 return NET_RX_DROP; 386 return NET_RX_DROP;
388 } 387 }
@@ -416,14 +415,14 @@ int rawv6_rcv(struct sock *sk, struct sk_buff *skb)
416 skb_network_header_len(skb)); 415 skb_network_header_len(skb));
417 if (!csum_ipv6_magic(&ipv6_hdr(skb)->saddr, 416 if (!csum_ipv6_magic(&ipv6_hdr(skb)->saddr,
418 &ipv6_hdr(skb)->daddr, 417 &ipv6_hdr(skb)->daddr,
419 skb->len, inet->num, skb->csum)) 418 skb->len, inet->inet_num, skb->csum))
420 skb->ip_summed = CHECKSUM_UNNECESSARY; 419 skb->ip_summed = CHECKSUM_UNNECESSARY;
421 } 420 }
422 if (!skb_csum_unnecessary(skb)) 421 if (!skb_csum_unnecessary(skb))
423 skb->csum = ~csum_unfold(csum_ipv6_magic(&ipv6_hdr(skb)->saddr, 422 skb->csum = ~csum_unfold(csum_ipv6_magic(&ipv6_hdr(skb)->saddr,
424 &ipv6_hdr(skb)->daddr, 423 &ipv6_hdr(skb)->daddr,
425 skb->len, 424 skb->len,
426 inet->num, 0)); 425 inet->inet_num, 0));
427 426
428 if (inet->hdrincl) { 427 if (inet->hdrincl) {
429 if (skb_checksum_complete(skb)) { 428 if (skb_checksum_complete(skb)) {
@@ -497,7 +496,7 @@ static int rawv6_recvmsg(struct kiocb *iocb, struct sock *sk,
497 sin6->sin6_scope_id = IP6CB(skb)->iif; 496 sin6->sin6_scope_id = IP6CB(skb)->iif;
498 } 497 }
499 498
500 sock_recv_timestamp(msg, sk, skb); 499 sock_recv_ts_and_drops(msg, sk, skb);
501 500
502 if (np->rxopt.all) 501 if (np->rxopt.all)
503 datagram_recv_ctl(sk, msg, skb); 502 datagram_recv_ctl(sk, msg, skb);
@@ -518,7 +517,6 @@ csum_copy_err:
518 as some normal condition. 517 as some normal condition.
519 */ 518 */
520 err = (flags&MSG_DONTWAIT) ? -EAGAIN : -EHOSTUNREACH; 519 err = (flags&MSG_DONTWAIT) ? -EAGAIN : -EHOSTUNREACH;
521 atomic_inc(&sk->sk_drops);
522 goto out; 520 goto out;
523} 521}
524 522
@@ -766,8 +764,8 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
766 proto = ntohs(sin6->sin6_port); 764 proto = ntohs(sin6->sin6_port);
767 765
768 if (!proto) 766 if (!proto)
769 proto = inet->num; 767 proto = inet->inet_num;
770 else if (proto != inet->num) 768 else if (proto != inet->inet_num)
771 return(-EINVAL); 769 return(-EINVAL);
772 770
773 if (proto > 255) 771 if (proto > 255)
@@ -800,7 +798,7 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
800 if (sk->sk_state != TCP_ESTABLISHED) 798 if (sk->sk_state != TCP_ESTABLISHED)
801 return -EDESTADDRREQ; 799 return -EDESTADDRREQ;
802 800
803 proto = inet->num; 801 proto = inet->inet_num;
804 daddr = &np->daddr; 802 daddr = &np->daddr;
805 fl.fl6_flowlabel = np->flow_label; 803 fl.fl6_flowlabel = np->flow_label;
806 } 804 }
@@ -967,7 +965,7 @@ static int do_rawv6_setsockopt(struct sock *sk, int level, int optname,
967 965
968 switch (optname) { 966 switch (optname) {
969 case IPV6_CHECKSUM: 967 case IPV6_CHECKSUM:
970 if (inet_sk(sk)->num == IPPROTO_ICMPV6 && 968 if (inet_sk(sk)->inet_num == IPPROTO_ICMPV6 &&
971 level == IPPROTO_IPV6) { 969 level == IPPROTO_IPV6) {
972 /* 970 /*
973 * RFC3542 tells that IPV6_CHECKSUM socket 971 * RFC3542 tells that IPV6_CHECKSUM socket
@@ -1007,7 +1005,7 @@ static int rawv6_setsockopt(struct sock *sk, int level, int optname,
1007 break; 1005 break;
1008 1006
1009 case SOL_ICMPV6: 1007 case SOL_ICMPV6:
1010 if (inet_sk(sk)->num != IPPROTO_ICMPV6) 1008 if (inet_sk(sk)->inet_num != IPPROTO_ICMPV6)
1011 return -EOPNOTSUPP; 1009 return -EOPNOTSUPP;
1012 return rawv6_seticmpfilter(sk, level, optname, optval, 1010 return rawv6_seticmpfilter(sk, level, optname, optval,
1013 optlen); 1011 optlen);
@@ -1030,7 +1028,7 @@ static int compat_rawv6_setsockopt(struct sock *sk, int level, int optname,
1030 case SOL_RAW: 1028 case SOL_RAW:
1031 break; 1029 break;
1032 case SOL_ICMPV6: 1030 case SOL_ICMPV6:
1033 if (inet_sk(sk)->num != IPPROTO_ICMPV6) 1031 if (inet_sk(sk)->inet_num != IPPROTO_ICMPV6)
1034 return -EOPNOTSUPP; 1032 return -EOPNOTSUPP;
1035 return rawv6_seticmpfilter(sk, level, optname, optval, optlen); 1033 return rawv6_seticmpfilter(sk, level, optname, optval, optlen);
1036 case SOL_IPV6: 1034 case SOL_IPV6:
@@ -1087,7 +1085,7 @@ static int rawv6_getsockopt(struct sock *sk, int level, int optname,
1087 break; 1085 break;
1088 1086
1089 case SOL_ICMPV6: 1087 case SOL_ICMPV6:
1090 if (inet_sk(sk)->num != IPPROTO_ICMPV6) 1088 if (inet_sk(sk)->inet_num != IPPROTO_ICMPV6)
1091 return -EOPNOTSUPP; 1089 return -EOPNOTSUPP;
1092 return rawv6_geticmpfilter(sk, level, optname, optval, 1090 return rawv6_geticmpfilter(sk, level, optname, optval,
1093 optlen); 1091 optlen);
@@ -1110,7 +1108,7 @@ static int compat_rawv6_getsockopt(struct sock *sk, int level, int optname,
1110 case SOL_RAW: 1108 case SOL_RAW:
1111 break; 1109 break;
1112 case SOL_ICMPV6: 1110 case SOL_ICMPV6:
1113 if (inet_sk(sk)->num != IPPROTO_ICMPV6) 1111 if (inet_sk(sk)->inet_num != IPPROTO_ICMPV6)
1114 return -EOPNOTSUPP; 1112 return -EOPNOTSUPP;
1115 return rawv6_geticmpfilter(sk, level, optname, optval, optlen); 1113 return rawv6_geticmpfilter(sk, level, optname, optval, optlen);
1116 case SOL_IPV6: 1114 case SOL_IPV6:
@@ -1157,7 +1155,7 @@ static int rawv6_ioctl(struct sock *sk, int cmd, unsigned long arg)
1157 1155
1158static void rawv6_close(struct sock *sk, long timeout) 1156static void rawv6_close(struct sock *sk, long timeout)
1159{ 1157{
1160 if (inet_sk(sk)->num == IPPROTO_RAW) 1158 if (inet_sk(sk)->inet_num == IPPROTO_RAW)
1161 ip6_ra_control(sk, -1); 1159 ip6_ra_control(sk, -1);
1162 ip6mr_sk_done(sk); 1160 ip6mr_sk_done(sk);
1163 sk_common_release(sk); 1161 sk_common_release(sk);
@@ -1176,7 +1174,7 @@ static int rawv6_init_sk(struct sock *sk)
1176{ 1174{
1177 struct raw6_sock *rp = raw6_sk(sk); 1175 struct raw6_sock *rp = raw6_sk(sk);
1178 1176
1179 switch (inet_sk(sk)->num) { 1177 switch (inet_sk(sk)->inet_num) {
1180 case IPPROTO_ICMPV6: 1178 case IPPROTO_ICMPV6:
1181 rp->checksum = 1; 1179 rp->checksum = 1;
1182 rp->offset = 2; 1180 rp->offset = 2;
@@ -1226,7 +1224,7 @@ static void raw6_sock_seq_show(struct seq_file *seq, struct sock *sp, int i)
1226 dest = &np->daddr; 1224 dest = &np->daddr;
1227 src = &np->rcv_saddr; 1225 src = &np->rcv_saddr;
1228 destp = 0; 1226 destp = 0;
1229 srcp = inet_sk(sp)->num; 1227 srcp = inet_sk(sp)->inet_num;
1230 seq_printf(seq, 1228 seq_printf(seq,
1231 "%4d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X " 1229 "%4d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X "
1232 "%02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %p %d\n", 1230 "%02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %p %d\n",
@@ -1278,7 +1276,7 @@ static const struct file_operations raw6_seq_fops = {
1278 .release = seq_release_net, 1276 .release = seq_release_net,
1279}; 1277};
1280 1278
1281static int raw6_init_net(struct net *net) 1279static int __net_init raw6_init_net(struct net *net)
1282{ 1280{
1283 if (!proc_net_fops_create(net, "raw6", S_IRUGO, &raw6_seq_fops)) 1281 if (!proc_net_fops_create(net, "raw6", S_IRUGO, &raw6_seq_fops))
1284 return -ENOMEM; 1282 return -ENOMEM;
@@ -1286,7 +1284,7 @@ static int raw6_init_net(struct net *net)
1286 return 0; 1284 return 0;
1287} 1285}
1288 1286
1289static void raw6_exit_net(struct net *net) 1287static void __net_exit raw6_exit_net(struct net *net)
1290{ 1288{
1291 proc_net_remove(net, "raw6"); 1289 proc_net_remove(net, "raw6");
1292} 1290}
@@ -1338,7 +1336,6 @@ static struct inet_protosw rawv6_protosw = {
1338 .protocol = IPPROTO_IP, /* wild card */ 1336 .protocol = IPPROTO_IP, /* wild card */
1339 .prot = &rawv6_prot, 1337 .prot = &rawv6_prot,
1340 .ops = &inet6_sockraw_ops, 1338 .ops = &inet6_sockraw_ops,
1341 .capability = CAP_NET_RAW,
1342 .no_check = UDP_CSUM_DEFAULT, 1339 .no_check = UDP_CSUM_DEFAULT,
1343 .flags = INET_PROTOSW_REUSE, 1340 .flags = INET_PROTOSW_REUSE,
1344}; 1341};