diff options
Diffstat (limited to 'net/dccp/ipv6.c')
-rw-r--r-- | net/dccp/ipv6.c | 44 |
1 files changed, 40 insertions, 4 deletions
diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c index 904967bf2fe9..3c9f0836404f 100644 --- a/net/dccp/ipv6.c +++ b/net/dccp/ipv6.c | |||
@@ -33,6 +33,9 @@ | |||
33 | #include "dccp.h" | 33 | #include "dccp.h" |
34 | #include "ipv6.h" | 34 | #include "ipv6.h" |
35 | 35 | ||
36 | /* Socket used for sending RSTs and ACKs */ | ||
37 | static struct socket *dccp_v6_ctl_socket; | ||
38 | |||
36 | static void dccp_v6_ctl_send_reset(struct sk_buff *skb); | 39 | static void dccp_v6_ctl_send_reset(struct sk_buff *skb); |
37 | static void dccp_v6_reqsk_send_ack(struct sk_buff *skb, | 40 | static void dccp_v6_reqsk_send_ack(struct sk_buff *skb, |
38 | struct request_sock *req); | 41 | struct request_sock *req); |
@@ -568,7 +571,7 @@ static void dccp_v6_ctl_send_reset(struct sk_buff *rxskb) | |||
568 | /* sk = NULL, but it is safe for now. RST socket required. */ | 571 | /* sk = NULL, but it is safe for now. RST socket required. */ |
569 | if (!ip6_dst_lookup(NULL, &skb->dst, &fl)) { | 572 | if (!ip6_dst_lookup(NULL, &skb->dst, &fl)) { |
570 | if (xfrm_lookup(&skb->dst, &fl, NULL, 0) >= 0) { | 573 | if (xfrm_lookup(&skb->dst, &fl, NULL, 0) >= 0) { |
571 | ip6_xmit(NULL, skb, &fl, NULL, 0); | 574 | ip6_xmit(dccp_v6_ctl_socket->sk, skb, &fl, NULL, 0); |
572 | DCCP_INC_STATS_BH(DCCP_MIB_OUTSEGS); | 575 | DCCP_INC_STATS_BH(DCCP_MIB_OUTSEGS); |
573 | DCCP_INC_STATS_BH(DCCP_MIB_OUTRSTS); | 576 | DCCP_INC_STATS_BH(DCCP_MIB_OUTRSTS); |
574 | return; | 577 | return; |
@@ -623,7 +626,7 @@ static void dccp_v6_ctl_send_ack(struct sk_buff *rxskb) | |||
623 | 626 | ||
624 | if (!ip6_dst_lookup(NULL, &skb->dst, &fl)) { | 627 | if (!ip6_dst_lookup(NULL, &skb->dst, &fl)) { |
625 | if (xfrm_lookup(&skb->dst, &fl, NULL, 0) >= 0) { | 628 | if (xfrm_lookup(&skb->dst, &fl, NULL, 0) >= 0) { |
626 | ip6_xmit(NULL, skb, &fl, NULL, 0); | 629 | ip6_xmit(dccp_v6_ctl_socket->sk, skb, &fl, NULL, 0); |
627 | DCCP_INC_STATS_BH(DCCP_MIB_OUTSEGS); | 630 | DCCP_INC_STATS_BH(DCCP_MIB_OUTSEGS); |
628 | return; | 631 | return; |
629 | } | 632 | } |
@@ -1146,10 +1149,14 @@ static struct inet_connection_sock_af_ops dccp_ipv6_mapped = { | |||
1146 | */ | 1149 | */ |
1147 | static int dccp_v6_init_sock(struct sock *sk) | 1150 | static int dccp_v6_init_sock(struct sock *sk) |
1148 | { | 1151 | { |
1149 | int err = dccp_init_sock(sk); | 1152 | static __u8 dccp_v6_ctl_sock_initialized; |
1153 | int err = dccp_init_sock(sk, dccp_v6_ctl_sock_initialized); | ||
1150 | 1154 | ||
1151 | if (err == 0) | 1155 | if (err == 0) { |
1156 | if (unlikely(!dccp_v6_ctl_sock_initialized)) | ||
1157 | dccp_v6_ctl_sock_initialized = 1; | ||
1152 | inet_csk(sk)->icsk_af_ops = &dccp_ipv6_af_ops; | 1158 | inet_csk(sk)->icsk_af_ops = &dccp_ipv6_af_ops; |
1159 | } | ||
1153 | 1160 | ||
1154 | return err; | 1161 | return err; |
1155 | } | 1162 | } |
@@ -1222,6 +1229,29 @@ static struct inet_protosw dccp_v6_protosw = { | |||
1222 | .flags = INET_PROTOSW_ICSK, | 1229 | .flags = INET_PROTOSW_ICSK, |
1223 | }; | 1230 | }; |
1224 | 1231 | ||
1232 | static char dccp_v6_ctl_socket_err_msg[] __initdata = | ||
1233 | KERN_ERR "DCCP: Failed to create the control socket.\n"; | ||
1234 | |||
1235 | static int __init dccp_v6_ctl_sock_init(void) | ||
1236 | { | ||
1237 | int rc = sock_create_kern(PF_INET6, SOCK_DCCP, IPPROTO_DCCP, | ||
1238 | &dccp_v6_ctl_socket); | ||
1239 | if (rc < 0) | ||
1240 | printk(dccp_v6_ctl_socket_err_msg); | ||
1241 | else { | ||
1242 | dccp_v6_ctl_socket->sk->sk_allocation = GFP_ATOMIC; | ||
1243 | inet_sk(dccp_v6_ctl_socket->sk)->uc_ttl = -1; | ||
1244 | |||
1245 | /* Unhash it so that IP input processing does not even | ||
1246 | * see it, we do not wish this socket to see incoming | ||
1247 | * packets. | ||
1248 | */ | ||
1249 | dccp_v6_ctl_socket->sk->sk_prot->unhash(dccp_v6_ctl_socket->sk); | ||
1250 | } | ||
1251 | |||
1252 | return rc; | ||
1253 | } | ||
1254 | |||
1225 | static int __init dccp_v6_init(void) | 1255 | static int __init dccp_v6_init(void) |
1226 | { | 1256 | { |
1227 | int err = proto_register(&dccp_v6_prot, 1); | 1257 | int err = proto_register(&dccp_v6_prot, 1); |
@@ -1234,8 +1264,14 @@ static int __init dccp_v6_init(void) | |||
1234 | goto out_unregister_proto; | 1264 | goto out_unregister_proto; |
1235 | 1265 | ||
1236 | inet6_register_protosw(&dccp_v6_protosw); | 1266 | inet6_register_protosw(&dccp_v6_protosw); |
1267 | |||
1268 | if (dccp_v6_ctl_sock_init() != 0) | ||
1269 | goto out_unregister_protosw; | ||
1237 | out: | 1270 | out: |
1238 | return err; | 1271 | return err; |
1272 | out_unregister_protosw: | ||
1273 | inet6_del_protocol(&dccp_v6_protocol, IPPROTO_DCCP); | ||
1274 | inet6_unregister_protosw(&dccp_v6_protosw); | ||
1239 | out_unregister_proto: | 1275 | out_unregister_proto: |
1240 | proto_unregister(&dccp_v6_prot); | 1276 | proto_unregister(&dccp_v6_prot); |
1241 | goto out; | 1277 | goto out; |