aboutsummaryrefslogtreecommitdiffstats
path: root/net/dccp/ipv6.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/dccp/ipv6.c')
-rw-r--r--net/dccp/ipv6.c385
1 files changed, 190 insertions, 195 deletions
diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c
index 718509dcb24d..ed4a50263802 100644
--- a/net/dccp/ipv6.c
+++ b/net/dccp/ipv6.c
@@ -36,11 +36,6 @@
36/* Socket used for sending RSTs and ACKs */ 36/* Socket used for sending RSTs and ACKs */
37static struct socket *dccp_v6_ctl_socket; 37static struct socket *dccp_v6_ctl_socket;
38 38
39static void dccp_v6_ctl_send_reset(struct sk_buff *skb);
40static void dccp_v6_send_check(struct sock *sk, int len, struct sk_buff *skb);
41
42static int dccp_v6_do_rcv(struct sock *sk, struct sk_buff *skb);
43
44static struct inet_connection_sock_af_ops dccp_ipv6_mapped; 39static struct inet_connection_sock_af_ops dccp_ipv6_mapped;
45static struct inet_connection_sock_af_ops dccp_ipv6_af_ops; 40static struct inet_connection_sock_af_ops dccp_ipv6_af_ops;
46 41
@@ -87,183 +82,6 @@ static __u32 dccp_v6_init_sequence(struct sock *sk, struct sk_buff *skb)
87 dh->dccph_sport); 82 dh->dccph_sport);
88} 83}
89 84
90static int dccp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
91 int addr_len)
92{
93 struct sockaddr_in6 *usin = (struct sockaddr_in6 *)uaddr;
94 struct inet_connection_sock *icsk = inet_csk(sk);
95 struct inet_sock *inet = inet_sk(sk);
96 struct ipv6_pinfo *np = inet6_sk(sk);
97 struct dccp_sock *dp = dccp_sk(sk);
98 struct in6_addr *saddr = NULL, *final_p = NULL, final;
99 struct flowi fl;
100 struct dst_entry *dst;
101 int addr_type;
102 int err;
103
104 dp->dccps_role = DCCP_ROLE_CLIENT;
105
106 if (addr_len < SIN6_LEN_RFC2133)
107 return -EINVAL;
108
109 if (usin->sin6_family != AF_INET6)
110 return -EAFNOSUPPORT;
111
112 memset(&fl, 0, sizeof(fl));
113
114 if (np->sndflow) {
115 fl.fl6_flowlabel = usin->sin6_flowinfo & IPV6_FLOWINFO_MASK;
116 IP6_ECN_flow_init(fl.fl6_flowlabel);
117 if (fl.fl6_flowlabel & IPV6_FLOWLABEL_MASK) {
118 struct ip6_flowlabel *flowlabel;
119 flowlabel = fl6_sock_lookup(sk, fl.fl6_flowlabel);
120 if (flowlabel == NULL)
121 return -EINVAL;
122 ipv6_addr_copy(&usin->sin6_addr, &flowlabel->dst);
123 fl6_sock_release(flowlabel);
124 }
125 }
126 /*
127 * connect() to INADDR_ANY means loopback (BSD'ism).
128 */
129 if (ipv6_addr_any(&usin->sin6_addr))
130 usin->sin6_addr.s6_addr[15] = 1;
131
132 addr_type = ipv6_addr_type(&usin->sin6_addr);
133
134 if (addr_type & IPV6_ADDR_MULTICAST)
135 return -ENETUNREACH;
136
137 if (addr_type & IPV6_ADDR_LINKLOCAL) {
138 if (addr_len >= sizeof(struct sockaddr_in6) &&
139 usin->sin6_scope_id) {
140 /* If interface is set while binding, indices
141 * must coincide.
142 */
143 if (sk->sk_bound_dev_if &&
144 sk->sk_bound_dev_if != usin->sin6_scope_id)
145 return -EINVAL;
146
147 sk->sk_bound_dev_if = usin->sin6_scope_id;
148 }
149
150 /* Connect to link-local address requires an interface */
151 if (!sk->sk_bound_dev_if)
152 return -EINVAL;
153 }
154
155 ipv6_addr_copy(&np->daddr, &usin->sin6_addr);
156 np->flow_label = fl.fl6_flowlabel;
157
158 /*
159 * DCCP over IPv4
160 */
161 if (addr_type == IPV6_ADDR_MAPPED) {
162 u32 exthdrlen = icsk->icsk_ext_hdr_len;
163 struct sockaddr_in sin;
164
165 SOCK_DEBUG(sk, "connect: ipv4 mapped\n");
166
167 if (__ipv6_only_sock(sk))
168 return -ENETUNREACH;
169
170 sin.sin_family = AF_INET;
171 sin.sin_port = usin->sin6_port;
172 sin.sin_addr.s_addr = usin->sin6_addr.s6_addr32[3];
173
174 icsk->icsk_af_ops = &dccp_ipv6_mapped;
175 sk->sk_backlog_rcv = dccp_v4_do_rcv;
176
177 err = dccp_v4_connect(sk, (struct sockaddr *)&sin, sizeof(sin));
178 if (err) {
179 icsk->icsk_ext_hdr_len = exthdrlen;
180 icsk->icsk_af_ops = &dccp_ipv6_af_ops;
181 sk->sk_backlog_rcv = dccp_v6_do_rcv;
182 goto failure;
183 } else {
184 ipv6_addr_set(&np->saddr, 0, 0, htonl(0x0000FFFF),
185 inet->saddr);
186 ipv6_addr_set(&np->rcv_saddr, 0, 0, htonl(0x0000FFFF),
187 inet->rcv_saddr);
188 }
189
190 return err;
191 }
192
193 if (!ipv6_addr_any(&np->rcv_saddr))
194 saddr = &np->rcv_saddr;
195
196 fl.proto = IPPROTO_DCCP;
197 ipv6_addr_copy(&fl.fl6_dst, &np->daddr);
198 ipv6_addr_copy(&fl.fl6_src, saddr ? saddr : &np->saddr);
199 fl.oif = sk->sk_bound_dev_if;
200 fl.fl_ip_dport = usin->sin6_port;
201 fl.fl_ip_sport = inet->sport;
202 security_sk_classify_flow(sk, &fl);
203
204 if (np->opt != NULL && np->opt->srcrt != NULL) {
205 const struct rt0_hdr *rt0 = (struct rt0_hdr *)np->opt->srcrt;
206
207 ipv6_addr_copy(&final, &fl.fl6_dst);
208 ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
209 final_p = &final;
210 }
211
212 err = ip6_dst_lookup(sk, &dst, &fl);
213 if (err)
214 goto failure;
215
216 if (final_p)
217 ipv6_addr_copy(&fl.fl6_dst, final_p);
218
219 err = xfrm_lookup(&dst, &fl, sk, 0);
220 if (err < 0)
221 goto failure;
222
223 if (saddr == NULL) {
224 saddr = &fl.fl6_src;
225 ipv6_addr_copy(&np->rcv_saddr, saddr);
226 }
227
228 /* set the source address */
229 ipv6_addr_copy(&np->saddr, saddr);
230 inet->rcv_saddr = LOOPBACK4_IPV6;
231
232 __ip6_dst_store(sk, dst, NULL, NULL);
233
234 icsk->icsk_ext_hdr_len = 0;
235 if (np->opt != NULL)
236 icsk->icsk_ext_hdr_len = (np->opt->opt_flen +
237 np->opt->opt_nflen);
238
239 inet->dport = usin->sin6_port;
240
241 dccp_set_state(sk, DCCP_REQUESTING);
242 err = inet6_hash_connect(&dccp_death_row, sk);
243 if (err)
244 goto late_failure;
245 /* FIXME */
246#if 0
247 dp->dccps_gar = secure_dccp_v6_sequence_number(np->saddr.s6_addr32,
248 np->daddr.s6_addr32,
249 inet->sport,
250 inet->dport);
251#endif
252 err = dccp_connect(sk);
253 if (err)
254 goto late_failure;
255
256 return 0;
257
258late_failure:
259 dccp_set_state(sk, DCCP_CLOSED);
260 __sk_dst_reset(sk);
261failure:
262 inet->dport = 0;
263 sk->sk_route_caps = 0;
264 return err;
265}
266
267static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, 85static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
268 int type, int code, int offset, __be32 info) 86 int type, int code, int offset, __be32 info)
269{ 87{
@@ -487,19 +305,6 @@ static void dccp_v6_reqsk_destructor(struct request_sock *req)
487 kfree_skb(inet6_rsk(req)->pktopts); 305 kfree_skb(inet6_rsk(req)->pktopts);
488} 306}
489 307
490static struct request_sock_ops dccp6_request_sock_ops = {
491 .family = AF_INET6,
492 .obj_size = sizeof(struct dccp6_request_sock),
493 .rtx_syn_ack = dccp_v6_send_response,
494 .send_ack = dccp_reqsk_send_ack,
495 .destructor = dccp_v6_reqsk_destructor,
496 .send_reset = dccp_v6_ctl_send_reset,
497};
498
499static struct timewait_sock_ops dccp6_timewait_sock_ops = {
500 .twsk_obj_size = sizeof(struct dccp6_timewait_sock),
501};
502
503static void dccp_v6_send_check(struct sock *sk, int len, struct sk_buff *skb) 308static void dccp_v6_send_check(struct sock *sk, int len, struct sk_buff *skb)
504{ 309{
505 struct ipv6_pinfo *np = inet6_sk(sk); 310 struct ipv6_pinfo *np = inet6_sk(sk);
@@ -580,6 +385,15 @@ static void dccp_v6_ctl_send_reset(struct sk_buff *rxskb)
580 kfree_skb(skb); 385 kfree_skb(skb);
581} 386}
582 387
388static struct request_sock_ops dccp6_request_sock_ops = {
389 .family = AF_INET6,
390 .obj_size = sizeof(struct dccp6_request_sock),
391 .rtx_syn_ack = dccp_v6_send_response,
392 .send_ack = dccp_reqsk_send_ack,
393 .destructor = dccp_v6_reqsk_destructor,
394 .send_reset = dccp_v6_ctl_send_reset,
395};
396
583static struct sock *dccp_v6_hnd_req(struct sock *sk,struct sk_buff *skb) 397static struct sock *dccp_v6_hnd_req(struct sock *sk,struct sk_buff *skb)
584{ 398{
585 const struct dccp_hdr *dh = dccp_hdr(skb); 399 const struct dccp_hdr *dh = dccp_hdr(skb);
@@ -1062,6 +876,183 @@ discard_and_relse:
1062 goto discard_it; 876 goto discard_it;
1063} 877}
1064 878
879static int dccp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
880 int addr_len)
881{
882 struct sockaddr_in6 *usin = (struct sockaddr_in6 *)uaddr;
883 struct inet_connection_sock *icsk = inet_csk(sk);
884 struct inet_sock *inet = inet_sk(sk);
885 struct ipv6_pinfo *np = inet6_sk(sk);
886 struct dccp_sock *dp = dccp_sk(sk);
887 struct in6_addr *saddr = NULL, *final_p = NULL, final;
888 struct flowi fl;
889 struct dst_entry *dst;
890 int addr_type;
891 int err;
892
893 dp->dccps_role = DCCP_ROLE_CLIENT;
894
895 if (addr_len < SIN6_LEN_RFC2133)
896 return -EINVAL;
897
898 if (usin->sin6_family != AF_INET6)
899 return -EAFNOSUPPORT;
900
901 memset(&fl, 0, sizeof(fl));
902
903 if (np->sndflow) {
904 fl.fl6_flowlabel = usin->sin6_flowinfo & IPV6_FLOWINFO_MASK;
905 IP6_ECN_flow_init(fl.fl6_flowlabel);
906 if (fl.fl6_flowlabel & IPV6_FLOWLABEL_MASK) {
907 struct ip6_flowlabel *flowlabel;
908 flowlabel = fl6_sock_lookup(sk, fl.fl6_flowlabel);
909 if (flowlabel == NULL)
910 return -EINVAL;
911 ipv6_addr_copy(&usin->sin6_addr, &flowlabel->dst);
912 fl6_sock_release(flowlabel);
913 }
914 }
915 /*
916 * connect() to INADDR_ANY means loopback (BSD'ism).
917 */
918 if (ipv6_addr_any(&usin->sin6_addr))
919 usin->sin6_addr.s6_addr[15] = 1;
920
921 addr_type = ipv6_addr_type(&usin->sin6_addr);
922
923 if (addr_type & IPV6_ADDR_MULTICAST)
924 return -ENETUNREACH;
925
926 if (addr_type & IPV6_ADDR_LINKLOCAL) {
927 if (addr_len >= sizeof(struct sockaddr_in6) &&
928 usin->sin6_scope_id) {
929 /* If interface is set while binding, indices
930 * must coincide.
931 */
932 if (sk->sk_bound_dev_if &&
933 sk->sk_bound_dev_if != usin->sin6_scope_id)
934 return -EINVAL;
935
936 sk->sk_bound_dev_if = usin->sin6_scope_id;
937 }
938
939 /* Connect to link-local address requires an interface */
940 if (!sk->sk_bound_dev_if)
941 return -EINVAL;
942 }
943
944 ipv6_addr_copy(&np->daddr, &usin->sin6_addr);
945 np->flow_label = fl.fl6_flowlabel;
946
947 /*
948 * DCCP over IPv4
949 */
950 if (addr_type == IPV6_ADDR_MAPPED) {
951 u32 exthdrlen = icsk->icsk_ext_hdr_len;
952 struct sockaddr_in sin;
953
954 SOCK_DEBUG(sk, "connect: ipv4 mapped\n");
955
956 if (__ipv6_only_sock(sk))
957 return -ENETUNREACH;
958
959 sin.sin_family = AF_INET;
960 sin.sin_port = usin->sin6_port;
961 sin.sin_addr.s_addr = usin->sin6_addr.s6_addr32[3];
962
963 icsk->icsk_af_ops = &dccp_ipv6_mapped;
964 sk->sk_backlog_rcv = dccp_v4_do_rcv;
965
966 err = dccp_v4_connect(sk, (struct sockaddr *)&sin, sizeof(sin));
967 if (err) {
968 icsk->icsk_ext_hdr_len = exthdrlen;
969 icsk->icsk_af_ops = &dccp_ipv6_af_ops;
970 sk->sk_backlog_rcv = dccp_v6_do_rcv;
971 goto failure;
972 } else {
973 ipv6_addr_set(&np->saddr, 0, 0, htonl(0x0000FFFF),
974 inet->saddr);
975 ipv6_addr_set(&np->rcv_saddr, 0, 0, htonl(0x0000FFFF),
976 inet->rcv_saddr);
977 }
978
979 return err;
980 }
981
982 if (!ipv6_addr_any(&np->rcv_saddr))
983 saddr = &np->rcv_saddr;
984
985 fl.proto = IPPROTO_DCCP;
986 ipv6_addr_copy(&fl.fl6_dst, &np->daddr);
987 ipv6_addr_copy(&fl.fl6_src, saddr ? saddr : &np->saddr);
988 fl.oif = sk->sk_bound_dev_if;
989 fl.fl_ip_dport = usin->sin6_port;
990 fl.fl_ip_sport = inet->sport;
991 security_sk_classify_flow(sk, &fl);
992
993 if (np->opt != NULL && np->opt->srcrt != NULL) {
994 const struct rt0_hdr *rt0 = (struct rt0_hdr *)np->opt->srcrt;
995
996 ipv6_addr_copy(&final, &fl.fl6_dst);
997 ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
998 final_p = &final;
999 }
1000
1001 err = ip6_dst_lookup(sk, &dst, &fl);
1002 if (err)
1003 goto failure;
1004
1005 if (final_p)
1006 ipv6_addr_copy(&fl.fl6_dst, final_p);
1007
1008 err = xfrm_lookup(&dst, &fl, sk, 0);
1009 if (err < 0)
1010 goto failure;
1011
1012 if (saddr == NULL) {
1013 saddr = &fl.fl6_src;
1014 ipv6_addr_copy(&np->rcv_saddr, saddr);
1015 }
1016
1017 /* set the source address */
1018 ipv6_addr_copy(&np->saddr, saddr);
1019 inet->rcv_saddr = LOOPBACK4_IPV6;
1020
1021 __ip6_dst_store(sk, dst, NULL, NULL);
1022
1023 icsk->icsk_ext_hdr_len = 0;
1024 if (np->opt != NULL)
1025 icsk->icsk_ext_hdr_len = (np->opt->opt_flen +
1026 np->opt->opt_nflen);
1027
1028 inet->dport = usin->sin6_port;
1029
1030 dccp_set_state(sk, DCCP_REQUESTING);
1031 err = inet6_hash_connect(&dccp_death_row, sk);
1032 if (err)
1033 goto late_failure;
1034 /* FIXME */
1035#if 0
1036 dp->dccps_gar = secure_dccp_v6_sequence_number(np->saddr.s6_addr32,
1037 np->daddr.s6_addr32,
1038 inet->sport,
1039 inet->dport);
1040#endif
1041 err = dccp_connect(sk);
1042 if (err)
1043 goto late_failure;
1044
1045 return 0;
1046
1047late_failure:
1048 dccp_set_state(sk, DCCP_CLOSED);
1049 __sk_dst_reset(sk);
1050failure:
1051 inet->dport = 0;
1052 sk->sk_route_caps = 0;
1053 return err;
1054}
1055
1065static struct inet_connection_sock_af_ops dccp_ipv6_af_ops = { 1056static struct inet_connection_sock_af_ops dccp_ipv6_af_ops = {
1066 .queue_xmit = inet6_csk_xmit, 1057 .queue_xmit = inet6_csk_xmit,
1067 .send_check = dccp_v6_send_check, 1058 .send_check = dccp_v6_send_check,
@@ -1122,6 +1113,10 @@ static int dccp_v6_destroy_sock(struct sock *sk)
1122 return inet6_destroy_sock(sk); 1113 return inet6_destroy_sock(sk);
1123} 1114}
1124 1115
1116static struct timewait_sock_ops dccp6_timewait_sock_ops = {
1117 .twsk_obj_size = sizeof(struct dccp6_timewait_sock),
1118};
1119
1125static struct proto dccp_v6_prot = { 1120static struct proto dccp_v6_prot = {
1126 .name = "DCCPv6", 1121 .name = "DCCPv6",
1127 .owner = THIS_MODULE, 1122 .owner = THIS_MODULE,