diff options
-rw-r--r-- | net/dccp/dccp.h | 4 | ||||
-rw-r--r-- | net/dccp/ipv4.c | 106 | ||||
-rw-r--r-- | net/dccp/ipv6.c | 4 | ||||
-rw-r--r-- | net/dccp/proto.c | 102 |
4 files changed, 112 insertions, 104 deletions
diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h index cd7c5d069ae4..8f3903be5598 100644 --- a/net/dccp/dccp.h +++ b/net/dccp/dccp.h | |||
@@ -228,8 +228,8 @@ extern int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb, | |||
228 | extern int dccp_rcv_established(struct sock *sk, struct sk_buff *skb, | 228 | extern int dccp_rcv_established(struct sock *sk, struct sk_buff *skb, |
229 | const struct dccp_hdr *dh, const unsigned len); | 229 | const struct dccp_hdr *dh, const unsigned len); |
230 | 230 | ||
231 | extern int dccp_v4_init_sock(struct sock *sk); | 231 | extern int dccp_init_sock(struct sock *sk); |
232 | extern int dccp_v4_destroy_sock(struct sock *sk); | 232 | extern int dccp_destroy_sock(struct sock *sk); |
233 | 233 | ||
234 | extern void dccp_close(struct sock *sk, long timeout); | 234 | extern void dccp_close(struct sock *sk, long timeout); |
235 | extern struct sk_buff *dccp_make_response(struct sock *sk, | 235 | extern struct sk_buff *dccp_make_response(struct sock *sk, |
diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index 3baf4c76a89d..b26a4f8df4dc 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c | |||
@@ -1008,109 +1008,15 @@ struct inet_connection_sock_af_ops dccp_ipv4_af_ops = { | |||
1008 | .sockaddr_len = sizeof(struct sockaddr_in), | 1008 | .sockaddr_len = sizeof(struct sockaddr_in), |
1009 | }; | 1009 | }; |
1010 | 1010 | ||
1011 | int dccp_v4_init_sock(struct sock *sk) | 1011 | static int dccp_v4_init_sock(struct sock *sk) |
1012 | { | 1012 | { |
1013 | struct dccp_sock *dp = dccp_sk(sk); | 1013 | const int err = dccp_init_sock(sk); |
1014 | struct inet_connection_sock *icsk = inet_csk(sk); | ||
1015 | static int dccp_ctl_socket_init = 1; | ||
1016 | |||
1017 | dccp_options_init(&dp->dccps_options); | ||
1018 | do_gettimeofday(&dp->dccps_epoch); | ||
1019 | |||
1020 | /* | ||
1021 | * FIXME: We're hardcoding the CCID, and doing this at this point makes | ||
1022 | * the listening (master) sock get CCID control blocks, which is not | ||
1023 | * necessary, but for now, to not mess with the test userspace apps, | ||
1024 | * lets leave it here, later the real solution is to do this in a | ||
1025 | * setsockopt(CCIDs-I-want/accept). -acme | ||
1026 | */ | ||
1027 | if (likely(!dccp_ctl_socket_init)) { | ||
1028 | int rc = dccp_feat_init(sk); | ||
1029 | |||
1030 | if (rc) | ||
1031 | return rc; | ||
1032 | |||
1033 | if (dp->dccps_options.dccpo_send_ack_vector) { | ||
1034 | dp->dccps_hc_rx_ackvec = dccp_ackvec_alloc(GFP_KERNEL); | ||
1035 | if (dp->dccps_hc_rx_ackvec == NULL) | ||
1036 | return -ENOMEM; | ||
1037 | } | ||
1038 | dp->dccps_hc_rx_ccid = | ||
1039 | ccid_hc_rx_new(dp->dccps_options.dccpo_rx_ccid, | ||
1040 | sk, GFP_KERNEL); | ||
1041 | dp->dccps_hc_tx_ccid = | ||
1042 | ccid_hc_tx_new(dp->dccps_options.dccpo_tx_ccid, | ||
1043 | sk, GFP_KERNEL); | ||
1044 | if (unlikely(dp->dccps_hc_rx_ccid == NULL || | ||
1045 | dp->dccps_hc_tx_ccid == NULL)) { | ||
1046 | ccid_hc_rx_delete(dp->dccps_hc_rx_ccid, sk); | ||
1047 | ccid_hc_tx_delete(dp->dccps_hc_tx_ccid, sk); | ||
1048 | if (dp->dccps_options.dccpo_send_ack_vector) { | ||
1049 | dccp_ackvec_free(dp->dccps_hc_rx_ackvec); | ||
1050 | dp->dccps_hc_rx_ackvec = NULL; | ||
1051 | } | ||
1052 | dp->dccps_hc_rx_ccid = dp->dccps_hc_tx_ccid = NULL; | ||
1053 | return -ENOMEM; | ||
1054 | } | ||
1055 | } else { | ||
1056 | /* control socket doesn't need feat nego */ | ||
1057 | INIT_LIST_HEAD(&dp->dccps_options.dccpo_pending); | ||
1058 | INIT_LIST_HEAD(&dp->dccps_options.dccpo_conf); | ||
1059 | dccp_ctl_socket_init = 0; | ||
1060 | } | ||
1061 | |||
1062 | dccp_init_xmit_timers(sk); | ||
1063 | icsk->icsk_rto = DCCP_TIMEOUT_INIT; | ||
1064 | sk->sk_state = DCCP_CLOSED; | ||
1065 | sk->sk_write_space = dccp_write_space; | ||
1066 | icsk->icsk_af_ops = &dccp_ipv4_af_ops; | ||
1067 | icsk->icsk_sync_mss = dccp_sync_mss; | ||
1068 | dp->dccps_mss_cache = 536; | ||
1069 | dp->dccps_role = DCCP_ROLE_UNDEFINED; | ||
1070 | dp->dccps_service = DCCP_SERVICE_INVALID_VALUE; | ||
1071 | dp->dccps_l_ack_ratio = dp->dccps_r_ack_ratio = 1; | ||
1072 | |||
1073 | return 0; | ||
1074 | } | ||
1075 | |||
1076 | EXPORT_SYMBOL_GPL(dccp_v4_init_sock); | ||
1077 | 1014 | ||
1078 | int dccp_v4_destroy_sock(struct sock *sk) | 1015 | if (err == 0) |
1079 | { | 1016 | inet_csk(sk)->icsk_af_ops = &dccp_ipv4_af_ops; |
1080 | struct dccp_sock *dp = dccp_sk(sk); | 1017 | return err; |
1081 | |||
1082 | /* | ||
1083 | * DCCP doesn't use sk_write_queue, just sk_send_head | ||
1084 | * for retransmissions | ||
1085 | */ | ||
1086 | if (sk->sk_send_head != NULL) { | ||
1087 | kfree_skb(sk->sk_send_head); | ||
1088 | sk->sk_send_head = NULL; | ||
1089 | } | ||
1090 | |||
1091 | /* Clean up a referenced DCCP bind bucket. */ | ||
1092 | if (inet_csk(sk)->icsk_bind_hash != NULL) | ||
1093 | inet_put_port(&dccp_hashinfo, sk); | ||
1094 | |||
1095 | kfree(dp->dccps_service_list); | ||
1096 | dp->dccps_service_list = NULL; | ||
1097 | |||
1098 | if (dp->dccps_options.dccpo_send_ack_vector) { | ||
1099 | dccp_ackvec_free(dp->dccps_hc_rx_ackvec); | ||
1100 | dp->dccps_hc_rx_ackvec = NULL; | ||
1101 | } | ||
1102 | ccid_hc_rx_delete(dp->dccps_hc_rx_ccid, sk); | ||
1103 | ccid_hc_tx_delete(dp->dccps_hc_tx_ccid, sk); | ||
1104 | dp->dccps_hc_rx_ccid = dp->dccps_hc_tx_ccid = NULL; | ||
1105 | |||
1106 | /* clean up feature negotiation state */ | ||
1107 | dccp_feat_clean(sk); | ||
1108 | |||
1109 | return 0; | ||
1110 | } | 1018 | } |
1111 | 1019 | ||
1112 | EXPORT_SYMBOL_GPL(dccp_v4_destroy_sock); | ||
1113 | |||
1114 | static void dccp_v4_reqsk_destructor(struct request_sock *req) | 1020 | static void dccp_v4_reqsk_destructor(struct request_sock *req) |
1115 | { | 1021 | { |
1116 | kfree(inet_rsk(req)->opt); | 1022 | kfree(inet_rsk(req)->opt); |
@@ -1147,7 +1053,7 @@ struct proto dccp_prot = { | |||
1147 | .accept = inet_csk_accept, | 1053 | .accept = inet_csk_accept, |
1148 | .get_port = dccp_v4_get_port, | 1054 | .get_port = dccp_v4_get_port, |
1149 | .shutdown = dccp_shutdown, | 1055 | .shutdown = dccp_shutdown, |
1150 | .destroy = dccp_v4_destroy_sock, | 1056 | .destroy = dccp_destroy_sock, |
1151 | .orphan_count = &dccp_orphan_count, | 1057 | .orphan_count = &dccp_orphan_count, |
1152 | .max_header = MAX_DCCP_HEADER, | 1058 | .max_header = MAX_DCCP_HEADER, |
1153 | .obj_size = sizeof(struct dccp_sock), | 1059 | .obj_size = sizeof(struct dccp_sock), |
diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c index ad5a1c66362d..84651bc6453b 100644 --- a/net/dccp/ipv6.c +++ b/net/dccp/ipv6.c | |||
@@ -1146,7 +1146,7 @@ static struct inet_connection_sock_af_ops dccp_ipv6_mapped = { | |||
1146 | */ | 1146 | */ |
1147 | static int dccp_v6_init_sock(struct sock *sk) | 1147 | static int dccp_v6_init_sock(struct sock *sk) |
1148 | { | 1148 | { |
1149 | int err = dccp_v4_init_sock(sk); | 1149 | int err = dccp_init_sock(sk); |
1150 | 1150 | ||
1151 | if (err == 0) | 1151 | if (err == 0) |
1152 | inet_csk(sk)->icsk_af_ops = &dccp_ipv6_af_ops; | 1152 | inet_csk(sk)->icsk_af_ops = &dccp_ipv6_af_ops; |
@@ -1156,7 +1156,7 @@ static int dccp_v6_init_sock(struct sock *sk) | |||
1156 | 1156 | ||
1157 | static int dccp_v6_destroy_sock(struct sock *sk) | 1157 | static int dccp_v6_destroy_sock(struct sock *sk) |
1158 | { | 1158 | { |
1159 | dccp_v4_destroy_sock(sk); | 1159 | dccp_destroy_sock(sk); |
1160 | return inet6_destroy_sock(sk); | 1160 | return inet6_destroy_sock(sk); |
1161 | } | 1161 | } |
1162 | 1162 | ||
diff --git a/net/dccp/proto.c b/net/dccp/proto.c index 6403e9306ddb..1c32def26533 100644 --- a/net/dccp/proto.c +++ b/net/dccp/proto.c | |||
@@ -97,6 +97,108 @@ const char *dccp_state_name(const int state) | |||
97 | 97 | ||
98 | EXPORT_SYMBOL_GPL(dccp_state_name); | 98 | EXPORT_SYMBOL_GPL(dccp_state_name); |
99 | 99 | ||
100 | int dccp_init_sock(struct sock *sk) | ||
101 | { | ||
102 | struct dccp_sock *dp = dccp_sk(sk); | ||
103 | struct inet_connection_sock *icsk = inet_csk(sk); | ||
104 | static int dccp_ctl_socket_init = 1; | ||
105 | |||
106 | dccp_options_init(&dp->dccps_options); | ||
107 | do_gettimeofday(&dp->dccps_epoch); | ||
108 | |||
109 | /* | ||
110 | * FIXME: We're hardcoding the CCID, and doing this at this point makes | ||
111 | * the listening (master) sock get CCID control blocks, which is not | ||
112 | * necessary, but for now, to not mess with the test userspace apps, | ||
113 | * lets leave it here, later the real solution is to do this in a | ||
114 | * setsockopt(CCIDs-I-want/accept). -acme | ||
115 | */ | ||
116 | if (likely(!dccp_ctl_socket_init)) { | ||
117 | int rc = dccp_feat_init(sk); | ||
118 | |||
119 | if (rc) | ||
120 | return rc; | ||
121 | |||
122 | if (dp->dccps_options.dccpo_send_ack_vector) { | ||
123 | dp->dccps_hc_rx_ackvec = dccp_ackvec_alloc(GFP_KERNEL); | ||
124 | if (dp->dccps_hc_rx_ackvec == NULL) | ||
125 | return -ENOMEM; | ||
126 | } | ||
127 | dp->dccps_hc_rx_ccid = | ||
128 | ccid_hc_rx_new(dp->dccps_options.dccpo_rx_ccid, | ||
129 | sk, GFP_KERNEL); | ||
130 | dp->dccps_hc_tx_ccid = | ||
131 | ccid_hc_tx_new(dp->dccps_options.dccpo_tx_ccid, | ||
132 | sk, GFP_KERNEL); | ||
133 | if (unlikely(dp->dccps_hc_rx_ccid == NULL || | ||
134 | dp->dccps_hc_tx_ccid == NULL)) { | ||
135 | ccid_hc_rx_delete(dp->dccps_hc_rx_ccid, sk); | ||
136 | ccid_hc_tx_delete(dp->dccps_hc_tx_ccid, sk); | ||
137 | if (dp->dccps_options.dccpo_send_ack_vector) { | ||
138 | dccp_ackvec_free(dp->dccps_hc_rx_ackvec); | ||
139 | dp->dccps_hc_rx_ackvec = NULL; | ||
140 | } | ||
141 | dp->dccps_hc_rx_ccid = dp->dccps_hc_tx_ccid = NULL; | ||
142 | return -ENOMEM; | ||
143 | } | ||
144 | } else { | ||
145 | /* control socket doesn't need feat nego */ | ||
146 | INIT_LIST_HEAD(&dp->dccps_options.dccpo_pending); | ||
147 | INIT_LIST_HEAD(&dp->dccps_options.dccpo_conf); | ||
148 | dccp_ctl_socket_init = 0; | ||
149 | } | ||
150 | |||
151 | dccp_init_xmit_timers(sk); | ||
152 | icsk->icsk_rto = DCCP_TIMEOUT_INIT; | ||
153 | sk->sk_state = DCCP_CLOSED; | ||
154 | sk->sk_write_space = dccp_write_space; | ||
155 | icsk->icsk_sync_mss = dccp_sync_mss; | ||
156 | dp->dccps_mss_cache = 536; | ||
157 | dp->dccps_role = DCCP_ROLE_UNDEFINED; | ||
158 | dp->dccps_service = DCCP_SERVICE_INVALID_VALUE; | ||
159 | dp->dccps_l_ack_ratio = dp->dccps_r_ack_ratio = 1; | ||
160 | |||
161 | return 0; | ||
162 | } | ||
163 | |||
164 | EXPORT_SYMBOL_GPL(dccp_init_sock); | ||
165 | |||
166 | int dccp_destroy_sock(struct sock *sk) | ||
167 | { | ||
168 | struct dccp_sock *dp = dccp_sk(sk); | ||
169 | |||
170 | /* | ||
171 | * DCCP doesn't use sk_write_queue, just sk_send_head | ||
172 | * for retransmissions | ||
173 | */ | ||
174 | if (sk->sk_send_head != NULL) { | ||
175 | kfree_skb(sk->sk_send_head); | ||
176 | sk->sk_send_head = NULL; | ||
177 | } | ||
178 | |||
179 | /* Clean up a referenced DCCP bind bucket. */ | ||
180 | if (inet_csk(sk)->icsk_bind_hash != NULL) | ||
181 | inet_put_port(&dccp_hashinfo, sk); | ||
182 | |||
183 | kfree(dp->dccps_service_list); | ||
184 | dp->dccps_service_list = NULL; | ||
185 | |||
186 | if (dp->dccps_options.dccpo_send_ack_vector) { | ||
187 | dccp_ackvec_free(dp->dccps_hc_rx_ackvec); | ||
188 | dp->dccps_hc_rx_ackvec = NULL; | ||
189 | } | ||
190 | ccid_hc_rx_delete(dp->dccps_hc_rx_ccid, sk); | ||
191 | ccid_hc_tx_delete(dp->dccps_hc_tx_ccid, sk); | ||
192 | dp->dccps_hc_rx_ccid = dp->dccps_hc_tx_ccid = NULL; | ||
193 | |||
194 | /* clean up feature negotiation state */ | ||
195 | dccp_feat_clean(sk); | ||
196 | |||
197 | return 0; | ||
198 | } | ||
199 | |||
200 | EXPORT_SYMBOL_GPL(dccp_destroy_sock); | ||
201 | |||
100 | static inline int dccp_listen_start(struct sock *sk) | 202 | static inline int dccp_listen_start(struct sock *sk) |
101 | { | 203 | { |
102 | struct dccp_sock *dp = dccp_sk(sk); | 204 | struct dccp_sock *dp = dccp_sk(sk); |