aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/raw.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6/raw.c')
-rw-r--r--net/ipv6/raw.c69
1 files changed, 24 insertions, 45 deletions
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index 0a6fbc1d1a50..6193b124cbc7 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -53,6 +53,7 @@
53#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) 53#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
54#include <net/mip6.h> 54#include <net/mip6.h>
55#endif 55#endif
56#include <linux/mroute6.h>
56 57
57#include <net/raw.h> 58#include <net/raw.h>
58#include <net/rawv6.h> 59#include <net/rawv6.h>
@@ -62,20 +63,9 @@
62#include <linux/seq_file.h> 63#include <linux/seq_file.h>
63 64
64static struct raw_hashinfo raw_v6_hashinfo = { 65static struct raw_hashinfo raw_v6_hashinfo = {
65 .lock = __RW_LOCK_UNLOCKED(), 66 .lock = __RW_LOCK_UNLOCKED(raw_v6_hashinfo.lock),
66}; 67};
67 68
68static void raw_v6_hash(struct sock *sk)
69{
70 raw_hash_sk(sk, &raw_v6_hashinfo);
71}
72
73static void raw_v6_unhash(struct sock *sk)
74{
75 raw_unhash_sk(sk, &raw_v6_hashinfo);
76}
77
78
79static struct sock *__raw_v6_lookup(struct net *net, struct sock *sk, 69static struct sock *__raw_v6_lookup(struct net *net, struct sock *sk,
80 unsigned short num, struct in6_addr *loc_addr, 70 unsigned short num, struct in6_addr *loc_addr,
81 struct in6_addr *rmt_addr, int dif) 71 struct in6_addr *rmt_addr, int dif)
@@ -87,7 +77,7 @@ static struct sock *__raw_v6_lookup(struct net *net, struct sock *sk,
87 if (inet_sk(sk)->num == num) { 77 if (inet_sk(sk)->num == num) {
88 struct ipv6_pinfo *np = inet6_sk(sk); 78 struct ipv6_pinfo *np = inet6_sk(sk);
89 79
90 if (sk->sk_net != net) 80 if (!net_eq(sock_net(sk), net))
91 continue; 81 continue;
92 82
93 if (!ipv6_addr_any(&np->daddr) && 83 if (!ipv6_addr_any(&np->daddr) &&
@@ -179,15 +169,10 @@ static int ipv6_raw_deliver(struct sk_buff *skb, int nexthdr)
179 read_lock(&raw_v6_hashinfo.lock); 169 read_lock(&raw_v6_hashinfo.lock);
180 sk = sk_head(&raw_v6_hashinfo.ht[hash]); 170 sk = sk_head(&raw_v6_hashinfo.ht[hash]);
181 171
182 /*
183 * The first socket found will be delivered after
184 * delivery to transport protocols.
185 */
186
187 if (sk == NULL) 172 if (sk == NULL)
188 goto out; 173 goto out;
189 174
190 net = skb->dev->nd_net; 175 net = dev_net(skb->dev);
191 sk = __raw_v6_lookup(net, sk, nexthdr, daddr, saddr, IP6CB(skb)->iif); 176 sk = __raw_v6_lookup(net, sk, nexthdr, daddr, saddr, IP6CB(skb)->iif);
192 177
193 while (sk) { 178 while (sk) {
@@ -291,7 +276,7 @@ static int rawv6_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len)
291 if (!sk->sk_bound_dev_if) 276 if (!sk->sk_bound_dev_if)
292 goto out; 277 goto out;
293 278
294 dev = dev_get_by_index(sk->sk_net, sk->sk_bound_dev_if); 279 dev = dev_get_by_index(sock_net(sk), sk->sk_bound_dev_if);
295 if (!dev) { 280 if (!dev) {
296 err = -ENODEV; 281 err = -ENODEV;
297 goto out; 282 goto out;
@@ -304,7 +289,7 @@ static int rawv6_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len)
304 v4addr = LOOPBACK4_IPV6; 289 v4addr = LOOPBACK4_IPV6;
305 if (!(addr_type & IPV6_ADDR_MULTICAST)) { 290 if (!(addr_type & IPV6_ADDR_MULTICAST)) {
306 err = -EADDRNOTAVAIL; 291 err = -EADDRNOTAVAIL;
307 if (!ipv6_chk_addr(sk->sk_net, &addr->sin6_addr, 292 if (!ipv6_chk_addr(sock_net(sk), &addr->sin6_addr,
308 dev, 0)) { 293 dev, 0)) {
309 if (dev) 294 if (dev)
310 dev_put(dev); 295 dev_put(dev);
@@ -372,11 +357,11 @@ void raw6_icmp_error(struct sk_buff *skb, int nexthdr,
372 read_lock(&raw_v6_hashinfo.lock); 357 read_lock(&raw_v6_hashinfo.lock);
373 sk = sk_head(&raw_v6_hashinfo.ht[hash]); 358 sk = sk_head(&raw_v6_hashinfo.ht[hash]);
374 if (sk != NULL) { 359 if (sk != NULL) {
375 struct ipv6hdr *hdr = (struct ipv6hdr *) skb->data; 360 /* Note: ipv6_hdr(skb) != skb->data */
376 361 struct ipv6hdr *ip6h = (struct ipv6hdr *)skb->data;
377 saddr = &hdr->saddr; 362 saddr = &ip6h->saddr;
378 daddr = &hdr->daddr; 363 daddr = &ip6h->daddr;
379 net = skb->dev->nd_net; 364 net = dev_net(skb->dev);
380 365
381 while ((sk = __raw_v6_lookup(net, sk, nexthdr, saddr, daddr, 366 while ((sk = __raw_v6_lookup(net, sk, nexthdr, saddr, daddr,
382 IP6CB(skb)->iif))) { 367 IP6CB(skb)->iif))) {
@@ -822,15 +807,6 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
822 fl.fl6_flowlabel = np->flow_label; 807 fl.fl6_flowlabel = np->flow_label;
823 } 808 }
824 809
825 if (ipv6_addr_any(daddr)) {
826 /*
827 * unspecified destination address
828 * treated as error... is this correct ?
829 */
830 fl6_sock_release(flowlabel);
831 return(-EINVAL);
832 }
833
834 if (fl.oif == 0) 810 if (fl.oif == 0)
835 fl.oif = sk->sk_bound_dev_if; 811 fl.oif = sk->sk_bound_dev_if;
836 812
@@ -863,7 +839,10 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
863 if (err) 839 if (err)
864 goto out; 840 goto out;
865 841
866 ipv6_addr_copy(&fl.fl6_dst, daddr); 842 if (!ipv6_addr_any(daddr))
843 ipv6_addr_copy(&fl.fl6_dst, daddr);
844 else
845 fl.fl6_dst.s6_addr[15] = 0x1; /* :: means loopback (BSD'ism) */
867 if (ipv6_addr_any(&fl.fl6_src) && !ipv6_addr_any(&np->saddr)) 846 if (ipv6_addr_any(&fl.fl6_src) && !ipv6_addr_any(&np->saddr))
868 ipv6_addr_copy(&fl.fl6_src, &np->saddr); 847 ipv6_addr_copy(&fl.fl6_src, &np->saddr);
869 848
@@ -898,9 +877,7 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
898 else 877 else
899 hlimit = np->hop_limit; 878 hlimit = np->hop_limit;
900 if (hlimit < 0) 879 if (hlimit < 0)
901 hlimit = dst_metric(dst, RTAX_HOPLIMIT); 880 hlimit = ip6_dst_hoplimit(dst);
902 if (hlimit < 0)
903 hlimit = ipv6_get_hoplimit(dst->dev);
904 } 881 }
905 882
906 if (tclass < 0) { 883 if (tclass < 0) {
@@ -1155,7 +1132,11 @@ static int rawv6_ioctl(struct sock *sk, int cmd, unsigned long arg)
1155 } 1132 }
1156 1133
1157 default: 1134 default:
1135#ifdef CONFIG_IPV6_MROUTE
1136 return ip6mr_ioctl(sk, cmd, (void __user *)arg);
1137#else
1158 return -ENOIOCTLCMD; 1138 return -ENOIOCTLCMD;
1139#endif
1159 } 1140 }
1160} 1141}
1161 1142
@@ -1163,7 +1144,7 @@ static void rawv6_close(struct sock *sk, long timeout)
1163{ 1144{
1164 if (inet_sk(sk)->num == IPPROTO_RAW) 1145 if (inet_sk(sk)->num == IPPROTO_RAW)
1165 ip6_ra_control(sk, -1, NULL); 1146 ip6_ra_control(sk, -1, NULL);
1166 1147 ip6mr_sk_done(sk);
1167 sk_common_release(sk); 1148 sk_common_release(sk);
1168} 1149}
1169 1150
@@ -1186,8 +1167,6 @@ static int rawv6_init_sk(struct sock *sk)
1186 return(0); 1167 return(0);
1187} 1168}
1188 1169
1189DEFINE_PROTO_INUSE(rawv6)
1190
1191struct proto rawv6_prot = { 1170struct proto rawv6_prot = {
1192 .name = "RAWv6", 1171 .name = "RAWv6",
1193 .owner = THIS_MODULE, 1172 .owner = THIS_MODULE,
@@ -1203,14 +1182,14 @@ struct proto rawv6_prot = {
1203 .recvmsg = rawv6_recvmsg, 1182 .recvmsg = rawv6_recvmsg,
1204 .bind = rawv6_bind, 1183 .bind = rawv6_bind,
1205 .backlog_rcv = rawv6_rcv_skb, 1184 .backlog_rcv = rawv6_rcv_skb,
1206 .hash = raw_v6_hash, 1185 .hash = raw_hash_sk,
1207 .unhash = raw_v6_unhash, 1186 .unhash = raw_unhash_sk,
1208 .obj_size = sizeof(struct raw6_sock), 1187 .obj_size = sizeof(struct raw6_sock),
1188 .h.raw_hash = &raw_v6_hashinfo,
1209#ifdef CONFIG_COMPAT 1189#ifdef CONFIG_COMPAT
1210 .compat_setsockopt = compat_rawv6_setsockopt, 1190 .compat_setsockopt = compat_rawv6_setsockopt,
1211 .compat_getsockopt = compat_rawv6_getsockopt, 1191 .compat_getsockopt = compat_rawv6_getsockopt,
1212#endif 1192#endif
1213 REF_PROTO_INUSE(rawv6)
1214}; 1193};
1215 1194
1216#ifdef CONFIG_PROC_FS 1195#ifdef CONFIG_PROC_FS