diff options
Diffstat (limited to 'net/dccp/ipv4.c')
-rw-r--r-- | net/dccp/ipv4.c | 65 |
1 files changed, 29 insertions, 36 deletions
diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index 3fe958eb4bf3..f53bce590ade 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c | |||
@@ -32,6 +32,13 @@ | |||
32 | #include "dccp.h" | 32 | #include "dccp.h" |
33 | #include "feat.h" | 33 | #include "feat.h" |
34 | 34 | ||
35 | /* | ||
36 | * This is the global socket data structure used for responding to | ||
37 | * the Out-of-the-blue (OOTB) packets. A control sock will be created | ||
38 | * for this socket at the initialization time. | ||
39 | */ | ||
40 | static struct socket *dccp_v4_ctl_socket; | ||
41 | |||
35 | static int dccp_v4_get_port(struct sock *sk, const unsigned short snum) | 42 | static int dccp_v4_get_port(struct sock *sk, const unsigned short snum) |
36 | { | 43 | { |
37 | return inet_csk_get_port(&dccp_hashinfo, sk, snum, | 44 | return inet_csk_get_port(&dccp_hashinfo, sk, snum, |
@@ -226,11 +233,11 @@ static void dccp_v4_ctl_send_ack(struct sk_buff *rxskb) | |||
226 | dccp_hdr_set_ack(dccp_hdr_ack_bits(skb), | 233 | dccp_hdr_set_ack(dccp_hdr_ack_bits(skb), |
227 | DCCP_SKB_CB(rxskb)->dccpd_seq); | 234 | DCCP_SKB_CB(rxskb)->dccpd_seq); |
228 | 235 | ||
229 | bh_lock_sock(dccp_ctl_socket->sk); | 236 | bh_lock_sock(dccp_v4_ctl_socket->sk); |
230 | err = ip_build_and_send_pkt(skb, dccp_ctl_socket->sk, | 237 | err = ip_build_and_send_pkt(skb, dccp_v4_ctl_socket->sk, |
231 | rxskb->nh.iph->daddr, | 238 | rxskb->nh.iph->daddr, |
232 | rxskb->nh.iph->saddr, NULL); | 239 | rxskb->nh.iph->saddr, NULL); |
233 | bh_unlock_sock(dccp_ctl_socket->sk); | 240 | bh_unlock_sock(dccp_v4_ctl_socket->sk); |
234 | 241 | ||
235 | if (err == NET_XMIT_CN || err == 0) { | 242 | if (err == NET_XMIT_CN || err == 0) { |
236 | DCCP_INC_STATS_BH(DCCP_MIB_OUTSEGS); | 243 | DCCP_INC_STATS_BH(DCCP_MIB_OUTSEGS); |
@@ -704,7 +711,7 @@ static void dccp_v4_ctl_send_reset(struct sk_buff *rxskb) | |||
704 | if (((struct rtable *)rxskb->dst)->rt_type != RTN_LOCAL) | 711 | if (((struct rtable *)rxskb->dst)->rt_type != RTN_LOCAL) |
705 | return; | 712 | return; |
706 | 713 | ||
707 | dst = dccp_v4_route_skb(dccp_ctl_socket->sk, rxskb); | 714 | dst = dccp_v4_route_skb(dccp_v4_ctl_socket->sk, rxskb); |
708 | if (dst == NULL) | 715 | if (dst == NULL) |
709 | return; | 716 | return; |
710 | 717 | ||
@@ -741,11 +748,11 @@ static void dccp_v4_ctl_send_reset(struct sk_buff *rxskb) | |||
741 | dh->dccph_checksum = dccp_v4_checksum(skb, rxskb->nh.iph->saddr, | 748 | dh->dccph_checksum = dccp_v4_checksum(skb, rxskb->nh.iph->saddr, |
742 | rxskb->nh.iph->daddr); | 749 | rxskb->nh.iph->daddr); |
743 | 750 | ||
744 | bh_lock_sock(dccp_ctl_socket->sk); | 751 | bh_lock_sock(dccp_v4_ctl_socket->sk); |
745 | err = ip_build_and_send_pkt(skb, dccp_ctl_socket->sk, | 752 | err = ip_build_and_send_pkt(skb, dccp_v4_ctl_socket->sk, |
746 | rxskb->nh.iph->daddr, | 753 | rxskb->nh.iph->daddr, |
747 | rxskb->nh.iph->saddr, NULL); | 754 | rxskb->nh.iph->saddr, NULL); |
748 | bh_unlock_sock(dccp_ctl_socket->sk); | 755 | bh_unlock_sock(dccp_v4_ctl_socket->sk); |
749 | 756 | ||
750 | if (err == NET_XMIT_CN || err == 0) { | 757 | if (err == NET_XMIT_CN || err == 0) { |
751 | DCCP_INC_STATS_BH(DCCP_MIB_OUTSEGS); | 758 | DCCP_INC_STATS_BH(DCCP_MIB_OUTSEGS); |
@@ -997,10 +1004,15 @@ static struct inet_connection_sock_af_ops dccp_ipv4_af_ops = { | |||
997 | 1004 | ||
998 | static int dccp_v4_init_sock(struct sock *sk) | 1005 | static int dccp_v4_init_sock(struct sock *sk) |
999 | { | 1006 | { |
1000 | const int err = dccp_init_sock(sk); | 1007 | static __u8 dccp_v4_ctl_sock_initialized; |
1008 | int err = dccp_init_sock(sk, dccp_v4_ctl_sock_initialized); | ||
1001 | 1009 | ||
1002 | if (err == 0) | 1010 | if (err == 0) { |
1011 | if (unlikely(!dccp_v4_ctl_sock_initialized)) | ||
1012 | dccp_v4_ctl_sock_initialized = 1; | ||
1003 | inet_csk(sk)->icsk_af_ops = &dccp_ipv4_af_ops; | 1013 | inet_csk(sk)->icsk_af_ops = &dccp_ipv4_af_ops; |
1014 | } | ||
1015 | |||
1004 | return err; | 1016 | return err; |
1005 | } | 1017 | } |
1006 | 1018 | ||
@@ -1087,48 +1099,29 @@ static struct inet_protosw dccp_v4_protosw = { | |||
1087 | .flags = INET_PROTOSW_ICSK, | 1099 | .flags = INET_PROTOSW_ICSK, |
1088 | }; | 1100 | }; |
1089 | 1101 | ||
1090 | /* | 1102 | static char dccp_v4_ctl_socket_err_msg[] __initdata = |
1091 | * This is the global socket data structure used for responding to | ||
1092 | * the Out-of-the-blue (OOTB) packets. A control sock will be created | ||
1093 | * for this socket at the initialization time. | ||
1094 | */ | ||
1095 | struct socket *dccp_ctl_socket; | ||
1096 | |||
1097 | static char dccp_ctl_socket_err_msg[] __initdata = | ||
1098 | KERN_ERR "DCCP: Failed to create the control socket.\n"; | 1103 | KERN_ERR "DCCP: Failed to create the control socket.\n"; |
1099 | 1104 | ||
1100 | static int __init dccp_ctl_sock_init(void) | 1105 | static int __init dccp_v4_ctl_sock_init(void) |
1101 | { | 1106 | { |
1102 | int rc = sock_create_kern(PF_INET, SOCK_DCCP, IPPROTO_DCCP, | 1107 | int rc = sock_create_kern(PF_INET, SOCK_DCCP, IPPROTO_DCCP, |
1103 | &dccp_ctl_socket); | 1108 | &dccp_v4_ctl_socket); |
1104 | if (rc < 0) | 1109 | if (rc < 0) |
1105 | printk(dccp_ctl_socket_err_msg); | 1110 | printk(dccp_v4_ctl_socket_err_msg); |
1106 | else { | 1111 | else { |
1107 | dccp_ctl_socket->sk->sk_allocation = GFP_ATOMIC; | 1112 | dccp_v4_ctl_socket->sk->sk_allocation = GFP_ATOMIC; |
1108 | inet_sk(dccp_ctl_socket->sk)->uc_ttl = -1; | 1113 | inet_sk(dccp_v4_ctl_socket->sk)->uc_ttl = -1; |
1109 | 1114 | ||
1110 | /* Unhash it so that IP input processing does not even | 1115 | /* Unhash it so that IP input processing does not even |
1111 | * see it, we do not wish this socket to see incoming | 1116 | * see it, we do not wish this socket to see incoming |
1112 | * packets. | 1117 | * packets. |
1113 | */ | 1118 | */ |
1114 | dccp_ctl_socket->sk->sk_prot->unhash(dccp_ctl_socket->sk); | 1119 | dccp_v4_ctl_socket->sk->sk_prot->unhash(dccp_v4_ctl_socket->sk); |
1115 | } | 1120 | } |
1116 | 1121 | ||
1117 | return rc; | 1122 | return rc; |
1118 | } | 1123 | } |
1119 | 1124 | ||
1120 | #ifdef CONFIG_IP_DCCP_UNLOAD_HACK | ||
1121 | void dccp_ctl_sock_exit(void) | ||
1122 | { | ||
1123 | if (dccp_ctl_socket != NULL) { | ||
1124 | sock_release(dccp_ctl_socket); | ||
1125 | dccp_ctl_socket = NULL; | ||
1126 | } | ||
1127 | } | ||
1128 | |||
1129 | EXPORT_SYMBOL_GPL(dccp_ctl_sock_exit); | ||
1130 | #endif | ||
1131 | |||
1132 | static int __init dccp_v4_init(void) | 1125 | static int __init dccp_v4_init(void) |
1133 | { | 1126 | { |
1134 | int err = proto_register(&dccp_v4_prot, 1); | 1127 | int err = proto_register(&dccp_v4_prot, 1); |
@@ -1142,7 +1135,7 @@ static int __init dccp_v4_init(void) | |||
1142 | 1135 | ||
1143 | inet_register_protosw(&dccp_v4_protosw); | 1136 | inet_register_protosw(&dccp_v4_protosw); |
1144 | 1137 | ||
1145 | err = dccp_ctl_sock_init(); | 1138 | err = dccp_v4_ctl_sock_init(); |
1146 | if (err) | 1139 | if (err) |
1147 | goto out_unregister_protosw; | 1140 | goto out_unregister_protosw; |
1148 | out: | 1141 | out: |