diff options
Diffstat (limited to 'net/dccp')
-rw-r--r-- | net/dccp/Kconfig | 9 | ||||
-rw-r--r-- | net/dccp/ccids/ccid3.c | 9 | ||||
-rw-r--r-- | net/dccp/dccp.h | 4 | ||||
-rw-r--r-- | net/dccp/ipv4.c | 65 | ||||
-rw-r--r-- | net/dccp/ipv6.c | 44 | ||||
-rw-r--r-- | net/dccp/proto.c | 6 |
6 files changed, 72 insertions, 65 deletions
diff --git a/net/dccp/Kconfig b/net/dccp/Kconfig index 24a6981e209a..7e096ba8454f 100644 --- a/net/dccp/Kconfig +++ b/net/dccp/Kconfig | |||
@@ -40,15 +40,6 @@ config IP_DCCP_DEBUG | |||
40 | 40 | ||
41 | Just say N. | 41 | Just say N. |
42 | 42 | ||
43 | config IP_DCCP_UNLOAD_HACK | ||
44 | depends on IP_DCCP=m && IP_DCCP_CCID3=m | ||
45 | bool "DCCP control sock unload hack" | ||
46 | ---help--- | ||
47 | Enable this to be able to unload the dccp module when the it | ||
48 | has only one refcount held, the control sock one. Just execute | ||
49 | "rmmod dccp_ccid3 dccp" | ||
50 | |||
51 | Just say N. | ||
52 | endmenu | 43 | endmenu |
53 | 44 | ||
54 | endmenu | 45 | endmenu |
diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c index ff6a0d7076ef..ff426a900999 100644 --- a/net/dccp/ccids/ccid3.c +++ b/net/dccp/ccids/ccid3.c | |||
@@ -1211,15 +1211,6 @@ module_init(ccid3_module_init); | |||
1211 | 1211 | ||
1212 | static __exit void ccid3_module_exit(void) | 1212 | static __exit void ccid3_module_exit(void) |
1213 | { | 1213 | { |
1214 | #ifdef CONFIG_IP_DCCP_UNLOAD_HACK | ||
1215 | /* | ||
1216 | * Hack to use while developing, so that we get rid of the control | ||
1217 | * sock, that is what keeps a refcount on dccp.ko -acme | ||
1218 | */ | ||
1219 | extern void dccp_ctl_sock_exit(void); | ||
1220 | |||
1221 | dccp_ctl_sock_exit(); | ||
1222 | #endif | ||
1223 | ccid_unregister(&ccid3); | 1214 | ccid_unregister(&ccid3); |
1224 | 1215 | ||
1225 | if (ccid3_tx_hist != NULL) { | 1216 | if (ccid3_tx_hist != NULL) { |
diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h index 6fcc9d47ae8c..d57d21351149 100644 --- a/net/dccp/dccp.h +++ b/net/dccp/dccp.h | |||
@@ -177,7 +177,7 @@ extern int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb, | |||
177 | extern int dccp_rcv_established(struct sock *sk, struct sk_buff *skb, | 177 | extern int dccp_rcv_established(struct sock *sk, struct sk_buff *skb, |
178 | const struct dccp_hdr *dh, const unsigned len); | 178 | const struct dccp_hdr *dh, const unsigned len); |
179 | 179 | ||
180 | extern int dccp_init_sock(struct sock *sk); | 180 | extern int dccp_init_sock(struct sock *sk, const __u8 ctl_sock_initialized); |
181 | extern int dccp_destroy_sock(struct sock *sk); | 181 | extern int dccp_destroy_sock(struct sock *sk); |
182 | 182 | ||
183 | extern void dccp_close(struct sock *sk, long timeout); | 183 | extern void dccp_close(struct sock *sk, long timeout); |
@@ -337,8 +337,6 @@ extern void dccp_insert_option(struct sock *sk, struct sk_buff *skb, | |||
337 | unsigned char option, | 337 | unsigned char option, |
338 | const void *value, unsigned char len); | 338 | const void *value, unsigned char len); |
339 | 339 | ||
340 | extern struct socket *dccp_ctl_socket; | ||
341 | |||
342 | extern void dccp_timestamp(const struct sock *sk, struct timeval *tv); | 340 | extern void dccp_timestamp(const struct sock *sk, struct timeval *tv); |
343 | 341 | ||
344 | static inline suseconds_t timeval_usecs(const struct timeval *tv) | 342 | static inline suseconds_t timeval_usecs(const struct timeval *tv) |
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: |
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; |
diff --git a/net/dccp/proto.c b/net/dccp/proto.c index f644c1a23c4d..baccaf35ffbd 100644 --- a/net/dccp/proto.c +++ b/net/dccp/proto.c | |||
@@ -163,11 +163,10 @@ void dccp_unhash(struct sock *sk) | |||
163 | 163 | ||
164 | EXPORT_SYMBOL_GPL(dccp_unhash); | 164 | EXPORT_SYMBOL_GPL(dccp_unhash); |
165 | 165 | ||
166 | int dccp_init_sock(struct sock *sk) | 166 | int dccp_init_sock(struct sock *sk, const __u8 ctl_sock_initialized) |
167 | { | 167 | { |
168 | struct dccp_sock *dp = dccp_sk(sk); | 168 | struct dccp_sock *dp = dccp_sk(sk); |
169 | struct inet_connection_sock *icsk = inet_csk(sk); | 169 | struct inet_connection_sock *icsk = inet_csk(sk); |
170 | static int dccp_ctl_socket_init = 1; | ||
171 | 170 | ||
172 | dccp_options_init(&dp->dccps_options); | 171 | dccp_options_init(&dp->dccps_options); |
173 | do_gettimeofday(&dp->dccps_epoch); | 172 | do_gettimeofday(&dp->dccps_epoch); |
@@ -179,7 +178,7 @@ int dccp_init_sock(struct sock *sk) | |||
179 | * lets leave it here, later the real solution is to do this in a | 178 | * lets leave it here, later the real solution is to do this in a |
180 | * setsockopt(CCIDs-I-want/accept). -acme | 179 | * setsockopt(CCIDs-I-want/accept). -acme |
181 | */ | 180 | */ |
182 | if (likely(!dccp_ctl_socket_init)) { | 181 | if (likely(ctl_sock_initialized)) { |
183 | int rc = dccp_feat_init(sk); | 182 | int rc = dccp_feat_init(sk); |
184 | 183 | ||
185 | if (rc) | 184 | if (rc) |
@@ -211,7 +210,6 @@ int dccp_init_sock(struct sock *sk) | |||
211 | /* control socket doesn't need feat nego */ | 210 | /* control socket doesn't need feat nego */ |
212 | INIT_LIST_HEAD(&dp->dccps_options.dccpo_pending); | 211 | INIT_LIST_HEAD(&dp->dccps_options.dccpo_pending); |
213 | INIT_LIST_HEAD(&dp->dccps_options.dccpo_conf); | 212 | INIT_LIST_HEAD(&dp->dccps_options.dccpo_conf); |
214 | dccp_ctl_socket_init = 0; | ||
215 | } | 213 | } |
216 | 214 | ||
217 | dccp_init_xmit_timers(sk); | 215 | dccp_init_xmit_timers(sk); |