ASoC: Add mc13783 codec
[deliverable/linux.git] / net / dccp / ipv6.c
CommitLineData
3df80d93
ACM
1/*
2 * DCCP over IPv6
45329e71 3 * Linux INET6 implementation
3df80d93
ACM
4 *
5 * Based on net/dccp6/ipv6.c
6 *
7 * Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version
12 * 2 of the License, or (at your option) any later version.
13 */
14
3df80d93
ACM
15#include <linux/module.h>
16#include <linux/random.h>
5a0e3ad6 17#include <linux/slab.h>
3df80d93
ACM
18#include <linux/xfrm.h>
19
20#include <net/addrconf.h>
21#include <net/inet_common.h>
22#include <net/inet_hashtables.h>
14c85021 23#include <net/inet_sock.h>
3df80d93
ACM
24#include <net/inet6_connection_sock.h>
25#include <net/inet6_hashtables.h>
26#include <net/ip6_route.h>
27#include <net/ipv6.h>
28#include <net/protocol.h>
29#include <net/transp_v6.h>
aa0e4e4a 30#include <net/ip6_checksum.h>
3df80d93 31#include <net/xfrm.h>
6e5714ea 32#include <net/secure_seq.h>
3df80d93
ACM
33
34#include "dccp.h"
35#include "ipv6.h"
4b79f0af 36#include "feat.h"
3df80d93 37
13f51d82 38/* The per-net dccp.v6_ctl_sk is used for sending RSTs and ACKs */
72478873 39
3b401a81
SH
40static const struct inet_connection_sock_af_ops dccp_ipv6_mapped;
41static const struct inet_connection_sock_af_ops dccp_ipv6_af_ops;
3df80d93 42
3df80d93
ACM
43static void dccp_v6_hash(struct sock *sk)
44{
45 if (sk->sk_state != DCCP_CLOSED) {
46 if (inet_csk(sk)->icsk_af_ops == &dccp_ipv6_mapped) {
ab1e0a13 47 inet_hash(sk);
3df80d93
ACM
48 return;
49 }
50 local_bh_disable();
9327f705 51 __inet6_hash(sk, NULL);
3df80d93
ACM
52 local_bh_enable();
53 }
54}
55
6f4e5fff 56/* add pseudo-header to DCCP checksum stored in skb->csum */
868c86bc 57static inline __sum16 dccp_v6_csum_finish(struct sk_buff *skb,
b71d1d42
ED
58 const struct in6_addr *saddr,
59 const struct in6_addr *daddr)
3df80d93 60{
6f4e5fff
GR
61 return csum_ipv6_magic(saddr, daddr, skb->len, IPPROTO_DCCP, skb->csum);
62}
63
bb296246 64static inline void dccp_v6_send_check(struct sock *sk, struct sk_buff *skb)
6f4e5fff
GR
65{
66 struct ipv6_pinfo *np = inet6_sk(sk);
67 struct dccp_hdr *dh = dccp_hdr(skb);
68
69 dccp_csum_outgoing(skb);
70 dh->dccph_checksum = dccp_v6_csum_finish(skb, &np->saddr, &np->daddr);
3df80d93
ACM
71}
72
6e5714ea 73static inline __u64 dccp_v6_init_sequence(struct sk_buff *skb)
d7f7365f 74{
0660e03f
ACM
75 return secure_dccpv6_sequence_number(ipv6_hdr(skb)->daddr.s6_addr32,
76 ipv6_hdr(skb)->saddr.s6_addr32,
d7f7365f
GR
77 dccp_hdr(skb)->dccph_dport,
78 dccp_hdr(skb)->dccph_sport );
79
3df80d93
ACM
80}
81
3df80d93 82static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
d5fdd6ba 83 u8 type, u8 code, int offset, __be32 info)
3df80d93 84{
b71d1d42 85 const struct ipv6hdr *hdr = (const struct ipv6hdr *)skb->data;
3df80d93 86 const struct dccp_hdr *dh = (struct dccp_hdr *)(skb->data + offset);
e0bcfb0c 87 struct dccp_sock *dp;
3df80d93
ACM
88 struct ipv6_pinfo *np;
89 struct sock *sk;
90 int err;
91 __u64 seq;
ca12a1a4 92 struct net *net = dev_net(skb->dev);
3df80d93 93
860239c5
WY
94 if (skb->len < offset + sizeof(*dh) ||
95 skb->len < offset + __dccp_basic_hdr_len(dh)) {
e41b5368
DL
96 ICMP6_INC_STATS_BH(net, __in6_dev_get(skb->dev),
97 ICMP6_MIB_INERRORS);
860239c5
WY
98 return;
99 }
100
ca12a1a4 101 sk = inet6_lookup(net, &dccp_hashinfo,
671a1c74 102 &hdr->daddr, dh->dccph_dport,
d86e0dac 103 &hdr->saddr, dh->dccph_sport, inet6_iif(skb));
3df80d93
ACM
104
105 if (sk == NULL) {
e41b5368
DL
106 ICMP6_INC_STATS_BH(net, __in6_dev_get(skb->dev),
107 ICMP6_MIB_INERRORS);
3df80d93
ACM
108 return;
109 }
110
111 if (sk->sk_state == DCCP_TIME_WAIT) {
9469c7b4 112 inet_twsk_put(inet_twsk(sk));
3df80d93
ACM
113 return;
114 }
115
116 bh_lock_sock(sk);
117 if (sock_owned_by_user(sk))
de0744af 118 NET_INC_STATS_BH(net, LINUX_MIB_LOCKDROPPEDICMPS);
3df80d93
ACM
119
120 if (sk->sk_state == DCCP_CLOSED)
121 goto out;
122
e0bcfb0c
WY
123 dp = dccp_sk(sk);
124 seq = dccp_hdr_seq(dh);
125 if ((1 << sk->sk_state) & ~(DCCPF_REQUESTING | DCCPF_LISTEN) &&
126 !between48(seq, dp->dccps_awl, dp->dccps_awh)) {
127 NET_INC_STATS_BH(net, LINUX_MIB_OUTOFWINDOWICMPS);
128 goto out;
129 }
130
3df80d93
ACM
131 np = inet6_sk(sk);
132
133 if (type == ICMPV6_PKT_TOOBIG) {
3df80d93
ACM
134 struct dst_entry *dst = NULL;
135
136 if (sock_owned_by_user(sk))
137 goto out;
138 if ((1 << sk->sk_state) & (DCCPF_LISTEN | DCCPF_CLOSED))
139 goto out;
140
141 /* icmp should have updated the destination cache entry */
142 dst = __sk_dst_check(sk, np->dst_cookie);
3df80d93
ACM
143 if (dst == NULL) {
144 struct inet_sock *inet = inet_sk(sk);
4c9483b2 145 struct flowi6 fl6;
3df80d93
ACM
146
147 /* BUGGG_FUTURE: Again, it is not clear how
148 to handle rthdr case. Ignore this complexity
149 for now.
150 */
4c9483b2
DM
151 memset(&fl6, 0, sizeof(fl6));
152 fl6.flowi6_proto = IPPROTO_DCCP;
4e3fd7a0
AD
153 fl6.daddr = np->daddr;
154 fl6.saddr = np->saddr;
4c9483b2 155 fl6.flowi6_oif = sk->sk_bound_dev_if;
1958b856
DM
156 fl6.fl6_dport = inet->inet_dport;
157 fl6.fl6_sport = inet->inet_sport;
4c9483b2
DM
158 security_sk_classify_flow(sk, flowi6_to_flowi(&fl6));
159
160 dst = ip6_dst_lookup_flow(sk, &fl6, NULL, false);
68d0c6d3
DM
161 if (IS_ERR(dst)) {
162 sk->sk_err_soft = -PTR_ERR(dst);
3df80d93
ACM
163 goto out;
164 }
3df80d93
ACM
165 } else
166 dst_hold(dst);
167
d83d8461 168 if (inet_csk(sk)->icsk_pmtu_cookie > dst_mtu(dst)) {
3df80d93
ACM
169 dccp_sync_mss(sk, dst_mtu(dst));
170 } /* else let the usual retransmit timer handle it */
171 dst_release(dst);
172 goto out;
173 }
174
175 icmpv6_err_convert(type, code, &err);
176
3df80d93
ACM
177 /* Might be for an request_sock */
178 switch (sk->sk_state) {
179 struct request_sock *req, **prev;
180 case DCCP_LISTEN:
181 if (sock_owned_by_user(sk))
182 goto out;
183
184 req = inet6_csk_search_req(sk, &prev, dh->dccph_dport,
185 &hdr->daddr, &hdr->saddr,
186 inet6_iif(skb));
45329e71 187 if (req == NULL)
3df80d93
ACM
188 goto out;
189
45329e71
ACM
190 /*
191 * ICMPs are not backlogged, hence we cannot get an established
192 * socket here.
3df80d93 193 */
547b792c 194 WARN_ON(req->sk != NULL);
3df80d93 195
f541fb7e
SJ
196 if (!between48(seq, dccp_rsk(req)->dreq_iss,
197 dccp_rsk(req)->dreq_gss)) {
de0744af 198 NET_INC_STATS_BH(net, LINUX_MIB_OUTOFWINDOWICMPS);
3df80d93
ACM
199 goto out;
200 }
201
202 inet_csk_reqsk_queue_drop(sk, req, prev);
203 goto out;
204
205 case DCCP_REQUESTING:
206 case DCCP_RESPOND: /* Cannot happen.
45329e71 207 It can, it SYNs are crossed. --ANK */
3df80d93
ACM
208 if (!sock_owned_by_user(sk)) {
209 DCCP_INC_STATS_BH(DCCP_MIB_ATTEMPTFAILS);
210 sk->sk_err = err;
211 /*
212 * Wake people up to see the error
213 * (see connect in sock.c)
214 */
215 sk->sk_error_report(sk);
3df80d93
ACM
216 dccp_done(sk);
217 } else
218 sk->sk_err_soft = err;
219 goto out;
220 }
221
222 if (!sock_owned_by_user(sk) && np->recverr) {
223 sk->sk_err = err;
224 sk->sk_error_report(sk);
225 } else
226 sk->sk_err_soft = err;
227
228out:
229 bh_unlock_sock(sk);
230 sock_put(sk);
231}
232
233
e6b4d113
WAS
234static int dccp_v6_send_response(struct sock *sk, struct request_sock *req,
235 struct request_values *rv_unused)
3df80d93
ACM
236{
237 struct inet6_request_sock *ireq6 = inet6_rsk(req);
238 struct ipv6_pinfo *np = inet6_sk(sk);
239 struct sk_buff *skb;
240 struct ipv6_txoptions *opt = NULL;
20c59de2 241 struct in6_addr *final_p, final;
4c9483b2 242 struct flowi6 fl6;
3df80d93 243 int err = -1;
fd80eb94 244 struct dst_entry *dst;
3df80d93 245
4c9483b2
DM
246 memset(&fl6, 0, sizeof(fl6));
247 fl6.flowi6_proto = IPPROTO_DCCP;
4e3fd7a0
AD
248 fl6.daddr = ireq6->rmt_addr;
249 fl6.saddr = ireq6->loc_addr;
4c9483b2
DM
250 fl6.flowlabel = 0;
251 fl6.flowi6_oif = ireq6->iif;
1958b856
DM
252 fl6.fl6_dport = inet_rsk(req)->rmt_port;
253 fl6.fl6_sport = inet_rsk(req)->loc_port;
4c9483b2 254 security_req_classify_flow(req, flowi6_to_flowi(&fl6));
3df80d93 255
fd80eb94 256 opt = np->opt;
3df80d93 257
4c9483b2 258 final_p = fl6_update_dst(&fl6, opt, &final);
3df80d93 259
4c9483b2 260 dst = ip6_dst_lookup_flow(sk, &fl6, final_p, false);
68d0c6d3
DM
261 if (IS_ERR(dst)) {
262 err = PTR_ERR(dst);
263 dst = NULL;
fd80eb94 264 goto done;
68d0c6d3 265 }
3df80d93
ACM
266
267 skb = dccp_make_response(sk, dst, req);
268 if (skb != NULL) {
269 struct dccp_hdr *dh = dccp_hdr(skb);
45329e71 270
6f4e5fff
GR
271 dh->dccph_checksum = dccp_v6_csum_finish(skb,
272 &ireq6->loc_addr,
273 &ireq6->rmt_addr);
4e3fd7a0 274 fl6.daddr = ireq6->rmt_addr;
b903d324 275 err = ip6_xmit(sk, skb, &fl6, opt, np->tclass);
b9df3cb8 276 err = net_xmit_eval(err);
3df80d93
ACM
277 }
278
279done:
45329e71 280 if (opt != NULL && opt != np->opt)
3df80d93 281 sock_kfree_s(sk, opt, opt->tot_len);
0cbd7825 282 dst_release(dst);
3df80d93
ACM
283 return err;
284}
285
286static void dccp_v6_reqsk_destructor(struct request_sock *req)
287{
d99a7bd2 288 dccp_feat_list_purge(&dccp_rsk(req)->dreq_featneg);
3df80d93
ACM
289 if (inet6_rsk(req)->pktopts != NULL)
290 kfree_skb(inet6_rsk(req)->pktopts);
291}
292
cfb6eeb4 293static void dccp_v6_ctl_send_reset(struct sock *sk, struct sk_buff *rxskb)
3df80d93 294{
b71d1d42 295 const struct ipv6hdr *rxip6h;
3df80d93 296 struct sk_buff *skb;
4c9483b2 297 struct flowi6 fl6;
adf30907 298 struct net *net = dev_net(skb_dst(rxskb)->dev);
334527d3 299 struct sock *ctl_sk = net->dccp.v6_ctl_sk;
adf30907 300 struct dst_entry *dst;
3df80d93 301
e356d37a 302 if (dccp_hdr(rxskb)->dccph_type == DCCP_PKT_RESET)
3df80d93
ACM
303 return;
304
305 if (!ipv6_unicast_destination(rxskb))
45329e71 306 return;
3df80d93 307
02047741 308 skb = dccp_ctl_make_reset(ctl_sk, rxskb);
45329e71 309 if (skb == NULL)
8109b02b 310 return;
3df80d93 311
0660e03f 312 rxip6h = ipv6_hdr(rxskb);
e356d37a
GR
313 dccp_hdr(skb)->dccph_checksum = dccp_v6_csum_finish(skb, &rxip6h->saddr,
314 &rxip6h->daddr);
6f4e5fff 315
4c9483b2 316 memset(&fl6, 0, sizeof(fl6));
4e3fd7a0
AD
317 fl6.daddr = rxip6h->saddr;
318 fl6.saddr = rxip6h->daddr;
6f4e5fff 319
4c9483b2
DM
320 fl6.flowi6_proto = IPPROTO_DCCP;
321 fl6.flowi6_oif = inet6_iif(rxskb);
1958b856
DM
322 fl6.fl6_dport = dccp_hdr(skb)->dccph_dport;
323 fl6.fl6_sport = dccp_hdr(skb)->dccph_sport;
4c9483b2 324 security_skb_classify_flow(rxskb, flowi6_to_flowi(&fl6));
3df80d93
ACM
325
326 /* sk = NULL, but it is safe for now. RST socket required. */
4c9483b2 327 dst = ip6_dst_lookup_flow(ctl_sk, &fl6, NULL, false);
68d0c6d3
DM
328 if (!IS_ERR(dst)) {
329 skb_dst_set(skb, dst);
b903d324 330 ip6_xmit(ctl_sk, skb, &fl6, NULL, 0);
68d0c6d3
DM
331 DCCP_INC_STATS_BH(DCCP_MIB_OUTSEGS);
332 DCCP_INC_STATS_BH(DCCP_MIB_OUTRSTS);
333 return;
3df80d93
ACM
334 }
335
336 kfree_skb(skb);
337}
338
73c9e02c
GR
339static struct request_sock_ops dccp6_request_sock_ops = {
340 .family = AF_INET6,
341 .obj_size = sizeof(struct dccp6_request_sock),
342 .rtx_syn_ack = dccp_v6_send_response,
343 .send_ack = dccp_reqsk_send_ack,
344 .destructor = dccp_v6_reqsk_destructor,
345 .send_reset = dccp_v6_ctl_send_reset,
346};
347
3df80d93
ACM
348static struct sock *dccp_v6_hnd_req(struct sock *sk,struct sk_buff *skb)
349{
350 const struct dccp_hdr *dh = dccp_hdr(skb);
0660e03f 351 const struct ipv6hdr *iph = ipv6_hdr(skb);
3df80d93
ACM
352 struct sock *nsk;
353 struct request_sock **prev;
354 /* Find possible connection requests. */
355 struct request_sock *req = inet6_csk_search_req(sk, &prev,
356 dh->dccph_sport,
357 &iph->saddr,
358 &iph->daddr,
359 inet6_iif(skb));
360 if (req != NULL)
361 return dccp_check_req(sk, skb, req, prev);
362
671a1c74 363 nsk = __inet6_lookup_established(sock_net(sk), &dccp_hashinfo,
3df80d93
ACM
364 &iph->saddr, dh->dccph_sport,
365 &iph->daddr, ntohs(dh->dccph_dport),
366 inet6_iif(skb));
3df80d93
ACM
367 if (nsk != NULL) {
368 if (nsk->sk_state != DCCP_TIME_WAIT) {
369 bh_lock_sock(nsk);
370 return nsk;
371 }
9469c7b4 372 inet_twsk_put(inet_twsk(nsk));
3df80d93
ACM
373 return NULL;
374 }
375
376 return sk;
377}
378
379static int dccp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
380{
3df80d93
ACM
381 struct request_sock *req;
382 struct dccp_request_sock *dreq;
383 struct inet6_request_sock *ireq6;
384 struct ipv6_pinfo *np = inet6_sk(sk);
8109b02b 385 const __be32 service = dccp_hdr_request(skb)->dccph_req_service;
3df80d93 386 struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb);
3df80d93
ACM
387
388 if (skb->protocol == htons(ETH_P_IP))
389 return dccp_v4_conn_request(sk, skb);
390
391 if (!ipv6_unicast_destination(skb))
4a5409a5 392 return 0; /* discard, don't send a reset here */
3df80d93
ACM
393
394 if (dccp_bad_service_code(sk, service)) {
4a5409a5 395 dcb->dccpd_reset_code = DCCP_RESET_CODE_BAD_SERVICE_CODE;
3df80d93 396 goto drop;
8109b02b 397 }
3df80d93 398 /*
45329e71 399 * There are no SYN attacks on IPv6, yet...
3df80d93 400 */
4a5409a5 401 dcb->dccpd_reset_code = DCCP_RESET_CODE_TOO_BUSY;
3df80d93 402 if (inet_csk_reqsk_queue_is_full(sk))
45329e71 403 goto drop;
3df80d93
ACM
404
405 if (sk_acceptq_is_full(sk) && inet_csk_reqsk_queue_young(sk) > 1)
406 goto drop;
407
82709531 408 req = inet6_reqsk_alloc(&dccp6_request_sock_ops);
3df80d93
ACM
409 if (req == NULL)
410 goto drop;
411
ac75773c
GR
412 if (dccp_reqsk_init(req, dccp_sk(sk), skb))
413 goto drop_and_free;
3df80d93 414
8b819412
GR
415 dreq = dccp_rsk(req);
416 if (dccp_parse_options(sk, dreq, skb))
417 goto drop_and_free;
418
4237c75c
VY
419 if (security_inet_conn_request(sk, skb, req))
420 goto drop_and_free;
421
3df80d93 422 ireq6 = inet6_rsk(req);
4e3fd7a0
AD
423 ireq6->rmt_addr = ipv6_hdr(skb)->saddr;
424 ireq6->loc_addr = ipv6_hdr(skb)->daddr;
3df80d93
ACM
425
426 if (ipv6_opt_accepted(sk, skb) ||
427 np->rxopt.bits.rxinfo || np->rxopt.bits.rxoinfo ||
428 np->rxopt.bits.rxhlim || np->rxopt.bits.rxohlim) {
429 atomic_inc(&skb->users);
430 ireq6->pktopts = skb;
431 }
432 ireq6->iif = sk->sk_bound_dev_if;
433
434 /* So that link locals have meaning */
435 if (!sk->sk_bound_dev_if &&
436 ipv6_addr_type(&ireq6->rmt_addr) & IPV6_ADDR_LINKLOCAL)
437 ireq6->iif = inet6_iif(skb);
438
45329e71 439 /*
3df80d93
ACM
440 * Step 3: Process LISTEN state
441 *
d83ca5ac 442 * Set S.ISR, S.GSR, S.SWL, S.SWH from packet or Init Cookie
3df80d93 443 *
f541fb7e 444 * Setting S.SWL/S.SWH to is deferred to dccp_create_openreq_child().
3df80d93 445 */
3df80d93 446 dreq->dreq_isr = dcb->dccpd_seq;
f541fb7e 447 dreq->dreq_gsr = dreq->dreq_isr;
865e9022 448 dreq->dreq_iss = dccp_v6_init_sequence(skb);
f541fb7e 449 dreq->dreq_gss = dreq->dreq_iss;
3df80d93
ACM
450 dreq->dreq_service = service;
451
e6b4d113 452 if (dccp_v6_send_response(sk, req, NULL))
3df80d93
ACM
453 goto drop_and_free;
454
455 inet6_csk_reqsk_queue_hash_add(sk, req, DCCP_TIMEOUT_INIT);
456 return 0;
457
458drop_and_free:
459 reqsk_free(req);
460drop:
461 DCCP_INC_STATS_BH(DCCP_MIB_ATTEMPTFAILS);
3df80d93
ACM
462 return -1;
463}
464
465static struct sock *dccp_v6_request_recv_sock(struct sock *sk,
466 struct sk_buff *skb,
467 struct request_sock *req,
468 struct dst_entry *dst)
469{
470 struct inet6_request_sock *ireq6 = inet6_rsk(req);
471 struct ipv6_pinfo *newnp, *np = inet6_sk(sk);
472 struct inet_sock *newinet;
3df80d93
ACM
473 struct dccp6_sock *newdp6;
474 struct sock *newsk;
475 struct ipv6_txoptions *opt;
476
477 if (skb->protocol == htons(ETH_P_IP)) {
478 /*
479 * v6 mapped
480 */
3df80d93 481 newsk = dccp_v4_request_recv_sock(sk, skb, req, dst);
45329e71 482 if (newsk == NULL)
3df80d93
ACM
483 return NULL;
484
485 newdp6 = (struct dccp6_sock *)newsk;
3df80d93
ACM
486 newinet = inet_sk(newsk);
487 newinet->pinet6 = &newdp6->inet6;
488 newnp = inet6_sk(newsk);
489
490 memcpy(newnp, np, sizeof(struct ipv6_pinfo));
491
c720c7e8 492 ipv6_addr_set_v4mapped(newinet->inet_daddr, &newnp->daddr);
3df80d93 493
c720c7e8 494 ipv6_addr_set_v4mapped(newinet->inet_saddr, &newnp->saddr);
3df80d93 495
4e3fd7a0 496 newnp->rcv_saddr = newnp->saddr;
3df80d93
ACM
497
498 inet_csk(newsk)->icsk_af_ops = &dccp_ipv6_mapped;
499 newsk->sk_backlog_rcv = dccp_v4_do_rcv;
500 newnp->pktoptions = NULL;
501 newnp->opt = NULL;
502 newnp->mcast_oif = inet6_iif(skb);
0660e03f 503 newnp->mcast_hops = ipv6_hdr(skb)->hop_limit;
3df80d93
ACM
504
505 /*
506 * No need to charge this sock to the relevant IPv6 refcnt debug socks count
507 * here, dccp_create_openreq_child now does this for us, see the comment in
508 * that function for the gory details. -acme
509 */
510
511 /* It is tricky place. Until this moment IPv4 tcp
512 worked with IPv6 icsk.icsk_af_ops.
513 Sync it now.
514 */
d83d8461 515 dccp_sync_mss(newsk, inet_csk(newsk)->icsk_pmtu_cookie);
3df80d93
ACM
516
517 return newsk;
518 }
519
520 opt = np->opt;
521
522 if (sk_acceptq_is_full(sk))
523 goto out_overflow;
524
3df80d93 525 if (dst == NULL) {
20c59de2 526 struct in6_addr *final_p, final;
4c9483b2
DM
527 struct flowi6 fl6;
528
529 memset(&fl6, 0, sizeof(fl6));
530 fl6.flowi6_proto = IPPROTO_DCCP;
4e3fd7a0 531 fl6.daddr = ireq6->rmt_addr;
4c9483b2 532 final_p = fl6_update_dst(&fl6, opt, &final);
4e3fd7a0 533 fl6.saddr = ireq6->loc_addr;
4c9483b2 534 fl6.flowi6_oif = sk->sk_bound_dev_if;
1958b856
DM
535 fl6.fl6_dport = inet_rsk(req)->rmt_port;
536 fl6.fl6_sport = inet_rsk(req)->loc_port;
4c9483b2
DM
537 security_sk_classify_flow(sk, flowi6_to_flowi(&fl6));
538
539 dst = ip6_dst_lookup_flow(sk, &fl6, final_p, false);
68d0c6d3 540 if (IS_ERR(dst))
3df80d93 541 goto out;
45329e71 542 }
3df80d93
ACM
543
544 newsk = dccp_create_openreq_child(sk, req, skb);
545 if (newsk == NULL)
093d2823 546 goto out_nonewsk;
3df80d93
ACM
547
548 /*
549 * No need to charge this sock to the relevant IPv6 refcnt debug socks
550 * count here, dccp_create_openreq_child now does this for us, see the
551 * comment in that function for the gory details. -acme
552 */
553
8e1ef0a9 554 __ip6_dst_store(newsk, dst, NULL, NULL);
45329e71
ACM
555 newsk->sk_route_caps = dst->dev->features & ~(NETIF_F_IP_CSUM |
556 NETIF_F_TSO);
3df80d93
ACM
557 newdp6 = (struct dccp6_sock *)newsk;
558 newinet = inet_sk(newsk);
559 newinet->pinet6 = &newdp6->inet6;
3df80d93
ACM
560 newnp = inet6_sk(newsk);
561
562 memcpy(newnp, np, sizeof(struct ipv6_pinfo));
563
4e3fd7a0
AD
564 newnp->daddr = ireq6->rmt_addr;
565 newnp->saddr = ireq6->loc_addr;
566 newnp->rcv_saddr = ireq6->loc_addr;
3df80d93
ACM
567 newsk->sk_bound_dev_if = ireq6->iif;
568
45329e71 569 /* Now IPv6 options...
3df80d93
ACM
570
571 First: no IPv4 options.
572 */
f6d8bd05 573 newinet->inet_opt = NULL;
3df80d93
ACM
574
575 /* Clone RX bits */
576 newnp->rxopt.all = np->rxopt.all;
577
578 /* Clone pktoptions received with SYN */
579 newnp->pktoptions = NULL;
580 if (ireq6->pktopts != NULL) {
581 newnp->pktoptions = skb_clone(ireq6->pktopts, GFP_ATOMIC);
582 kfree_skb(ireq6->pktopts);
583 ireq6->pktopts = NULL;
584 if (newnp->pktoptions)
585 skb_set_owner_r(newnp->pktoptions, newsk);
586 }
587 newnp->opt = NULL;
588 newnp->mcast_oif = inet6_iif(skb);
0660e03f 589 newnp->mcast_hops = ipv6_hdr(skb)->hop_limit;
3df80d93 590
45329e71
ACM
591 /*
592 * Clone native IPv6 options from listening socket (if any)
593 *
594 * Yes, keeping reference count would be much more clever, but we make
595 * one more one thing there: reattach optmem to newsk.
3df80d93 596 */
45329e71 597 if (opt != NULL) {
3df80d93
ACM
598 newnp->opt = ipv6_dup_options(newsk, opt);
599 if (opt != np->opt)
600 sock_kfree_s(sk, opt, opt->tot_len);
601 }
602
d83d8461 603 inet_csk(newsk)->icsk_ext_hdr_len = 0;
45329e71 604 if (newnp->opt != NULL)
d83d8461
ACM
605 inet_csk(newsk)->icsk_ext_hdr_len = (newnp->opt->opt_nflen +
606 newnp->opt->opt_flen);
3df80d93
ACM
607
608 dccp_sync_mss(newsk, dst_mtu(dst));
609
c720c7e8
ED
610 newinet->inet_daddr = newinet->inet_saddr = LOOPBACK4_IPV6;
611 newinet->inet_rcv_saddr = LOOPBACK4_IPV6;
3df80d93 612
093d2823
BS
613 if (__inet_inherit_port(sk, newsk) < 0) {
614 sock_put(newsk);
615 goto out;
616 }
9327f705 617 __inet6_hash(newsk, NULL);
3df80d93
ACM
618
619 return newsk;
620
621out_overflow:
de0744af 622 NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENOVERFLOWS);
093d2823
BS
623out_nonewsk:
624 dst_release(dst);
3df80d93 625out:
de0744af 626 NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS);
45329e71 627 if (opt != NULL && opt != np->opt)
3df80d93 628 sock_kfree_s(sk, opt, opt->tot_len);
3df80d93
ACM
629 return NULL;
630}
631
632/* The socket must have it's spinlock held when we get
633 * here.
634 *
635 * We have a potential double-lock case here, so even when
636 * doing backlog processing we use the BH locking scheme.
637 * This is because we cannot sleep with the original spinlock
638 * held.
639 */
640static int dccp_v6_do_rcv(struct sock *sk, struct sk_buff *skb)
641{
642 struct ipv6_pinfo *np = inet6_sk(sk);
643 struct sk_buff *opt_skb = NULL;
644
645 /* Imagine: socket is IPv6. IPv4 packet arrives,
646 goes to IPv4 receive handler and backlogged.
647 From backlog it always goes here. Kerboom...
648 Fortunately, dccp_rcv_established and rcv_established
649 handle them correctly, but it is not case with
650 dccp_v6_hnd_req and dccp_v6_ctl_send_reset(). --ANK
651 */
652
653 if (skb->protocol == htons(ETH_P_IP))
654 return dccp_v4_do_rcv(sk, skb);
655
fda9ef5d 656 if (sk_filter(sk, skb))
3df80d93
ACM
657 goto discard;
658
659 /*
45329e71
ACM
660 * socket locking is here for SMP purposes as backlog rcv is currently
661 * called with bh processing disabled.
3df80d93
ACM
662 */
663
664 /* Do Stevens' IPV6_PKTOPTIONS.
665
666 Yes, guys, it is the only place in our code, where we
667 may make it not affecting IPv4.
668 The rest of code is protocol independent,
669 and I do not like idea to uglify IPv4.
670
671 Actually, all the idea behind IPV6_PKTOPTIONS
672 looks not very well thought. For now we latch
673 options, received in the last packet, enqueued
674 by tcp. Feel free to propose better solution.
c9eaf173 675 --ANK (980728)
3df80d93
ACM
676 */
677 if (np->rxopt.all)
89e7e577
GR
678 /*
679 * FIXME: Add handling of IPV6_PKTOPTIONS skb. See the comments below
680 * (wrt ipv6_pktopions) and net/ipv6/tcp_ipv6.c for an example.
681 */
3df80d93
ACM
682 opt_skb = skb_clone(skb, GFP_ATOMIC);
683
684 if (sk->sk_state == DCCP_OPEN) { /* Fast path */
685 if (dccp_rcv_established(sk, skb, dccp_hdr(skb), skb->len))
686 goto reset;
fd169f15 687 if (opt_skb) {
89e7e577 688 /* XXX This is where we would goto ipv6_pktoptions. */
fd169f15
DM
689 __kfree_skb(opt_skb);
690 }
3df80d93
ACM
691 return 0;
692 }
693
d83ca5ac
GR
694 /*
695 * Step 3: Process LISTEN state
696 * If S.state == LISTEN,
697 * If P.type == Request or P contains a valid Init Cookie option,
698 * (* Must scan the packet's options to check for Init
699 * Cookies. Only Init Cookies are processed here,
700 * however; other options are processed in Step 8. This
701 * scan need only be performed if the endpoint uses Init
702 * Cookies *)
703 * (* Generate a new socket and switch to that socket *)
704 * Set S := new socket for this port pair
705 * S.state = RESPOND
706 * Choose S.ISS (initial seqno) or set from Init Cookies
707 * Initialize S.GAR := S.ISS
708 * Set S.ISR, S.GSR, S.SWL, S.SWH from packet or Init Cookies
709 * Continue with S.state == RESPOND
710 * (* A Response packet will be generated in Step 11 *)
711 * Otherwise,
712 * Generate Reset(No Connection) unless P.type == Reset
713 * Drop packet and return
714 *
715 * NOTE: the check for the packet types is done in
716 * dccp_rcv_state_process
717 */
45329e71 718 if (sk->sk_state == DCCP_LISTEN) {
3df80d93 719 struct sock *nsk = dccp_v6_hnd_req(sk, skb);
3df80d93 720
45329e71
ACM
721 if (nsk == NULL)
722 goto discard;
3df80d93
ACM
723 /*
724 * Queue it on the new socket if the new socket is active,
725 * otherwise we just shortcircuit this and continue with
726 * the new socket..
727 */
8109b02b 728 if (nsk != sk) {
3df80d93
ACM
729 if (dccp_child_process(sk, nsk, skb))
730 goto reset;
45329e71 731 if (opt_skb != NULL)
3df80d93
ACM
732 __kfree_skb(opt_skb);
733 return 0;
734 }
735 }
736
737 if (dccp_rcv_state_process(sk, skb, dccp_hdr(skb), skb->len))
738 goto reset;
fd169f15 739 if (opt_skb) {
89e7e577 740 /* XXX This is where we would goto ipv6_pktoptions. */
fd169f15
DM
741 __kfree_skb(opt_skb);
742 }
3df80d93
ACM
743 return 0;
744
745reset:
cfb6eeb4 746 dccp_v6_ctl_send_reset(sk, skb);
3df80d93 747discard:
45329e71 748 if (opt_skb != NULL)
3df80d93
ACM
749 __kfree_skb(opt_skb);
750 kfree_skb(skb);
751 return 0;
752}
753
e5bbef20 754static int dccp_v6_rcv(struct sk_buff *skb)
3df80d93
ACM
755{
756 const struct dccp_hdr *dh;
3df80d93 757 struct sock *sk;
6f4e5fff 758 int min_cov;
3df80d93 759
6f4e5fff 760 /* Step 1: Check header basics */
3df80d93
ACM
761
762 if (dccp_invalid_packet(skb))
763 goto discard_it;
764
6f4e5fff 765 /* Step 1: If header checksum is incorrect, drop packet and return. */
0660e03f
ACM
766 if (dccp_v6_csum_finish(skb, &ipv6_hdr(skb)->saddr,
767 &ipv6_hdr(skb)->daddr)) {
59348b19 768 DCCP_WARN("dropped packet with invalid checksum\n");
6f4e5fff
GR
769 goto discard_it;
770 }
771
3df80d93
ACM
772 dh = dccp_hdr(skb);
773
fde20105 774 DCCP_SKB_CB(skb)->dccpd_seq = dccp_hdr_seq(dh);
3df80d93
ACM
775 DCCP_SKB_CB(skb)->dccpd_type = dh->dccph_type;
776
777 if (dccp_packet_without_ack(skb))
778 DCCP_SKB_CB(skb)->dccpd_ack_seq = DCCP_PKT_WITHOUT_ACK_SEQ;
779 else
780 DCCP_SKB_CB(skb)->dccpd_ack_seq = dccp_hdr_ack_seq(skb);
781
782 /* Step 2:
8109b02b 783 * Look up flow ID in table and get corresponding socket */
9a1f27c4
ACM
784 sk = __inet6_lookup_skb(&dccp_hashinfo, skb,
785 dh->dccph_sport, dh->dccph_dport);
45329e71 786 /*
3df80d93 787 * Step 2:
8109b02b 788 * If no socket ...
3df80d93 789 */
d23c7107
GR
790 if (sk == NULL) {
791 dccp_pr_debug("failed to look up flow ID in table and "
792 "get corresponding socket\n");
3df80d93 793 goto no_dccp_socket;
d23c7107 794 }
3df80d93 795
45329e71 796 /*
3df80d93 797 * Step 2:
8109b02b 798 * ... or S.state == TIMEWAIT,
3df80d93
ACM
799 * Generate Reset(No Connection) unless P.type == Reset
800 * Drop packet and return
801 */
d23c7107
GR
802 if (sk->sk_state == DCCP_TIME_WAIT) {
803 dccp_pr_debug("sk->sk_state == DCCP_TIME_WAIT: do_time_wait\n");
804 inet_twsk_put(inet_twsk(sk));
805 goto no_dccp_socket;
806 }
3df80d93 807
6f4e5fff
GR
808 /*
809 * RFC 4340, sec. 9.2.1: Minimum Checksum Coverage
8109b02b
ACM
810 * o if MinCsCov = 0, only packets with CsCov = 0 are accepted
811 * o if MinCsCov > 0, also accept packets with CsCov >= MinCsCov
6f4e5fff
GR
812 */
813 min_cov = dccp_sk(sk)->dccps_pcrlen;
814 if (dh->dccph_cscov && (min_cov == 0 || dh->dccph_cscov < min_cov)) {
815 dccp_pr_debug("Packet CsCov %d does not satisfy MinCsCov %d\n",
816 dh->dccph_cscov, min_cov);
817 /* FIXME: send Data Dropped option (see also dccp_v4_rcv) */
818 goto discard_and_relse;
819 }
820
3df80d93
ACM
821 if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb))
822 goto discard_and_relse;
823
58a5a7b9 824 return sk_receive_skb(sk, skb, 1) ? -1 : 0;
3df80d93
ACM
825
826no_dccp_socket:
827 if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb))
828 goto discard_it;
829 /*
830 * Step 2:
8109b02b 831 * If no socket ...
3df80d93
ACM
832 * Generate Reset(No Connection) unless P.type == Reset
833 * Drop packet and return
834 */
835 if (dh->dccph_type != DCCP_PKT_RESET) {
836 DCCP_SKB_CB(skb)->dccpd_reset_code =
837 DCCP_RESET_CODE_NO_CONNECTION;
cfb6eeb4 838 dccp_v6_ctl_send_reset(sk, skb);
3df80d93 839 }
3df80d93 840
d23c7107 841discard_it:
3df80d93
ACM
842 kfree_skb(skb);
843 return 0;
844
845discard_and_relse:
846 sock_put(sk);
847 goto discard_it;
3df80d93
ACM
848}
849
73c9e02c
GR
850static int dccp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
851 int addr_len)
852{
853 struct sockaddr_in6 *usin = (struct sockaddr_in6 *)uaddr;
854 struct inet_connection_sock *icsk = inet_csk(sk);
855 struct inet_sock *inet = inet_sk(sk);
856 struct ipv6_pinfo *np = inet6_sk(sk);
857 struct dccp_sock *dp = dccp_sk(sk);
20c59de2 858 struct in6_addr *saddr = NULL, *final_p, final;
4c9483b2 859 struct flowi6 fl6;
73c9e02c
GR
860 struct dst_entry *dst;
861 int addr_type;
862 int err;
863
864 dp->dccps_role = DCCP_ROLE_CLIENT;
865
866 if (addr_len < SIN6_LEN_RFC2133)
867 return -EINVAL;
868
869 if (usin->sin6_family != AF_INET6)
870 return -EAFNOSUPPORT;
871
4c9483b2 872 memset(&fl6, 0, sizeof(fl6));
73c9e02c
GR
873
874 if (np->sndflow) {
4c9483b2
DM
875 fl6.flowlabel = usin->sin6_flowinfo & IPV6_FLOWINFO_MASK;
876 IP6_ECN_flow_init(fl6.flowlabel);
877 if (fl6.flowlabel & IPV6_FLOWLABEL_MASK) {
73c9e02c 878 struct ip6_flowlabel *flowlabel;
4c9483b2 879 flowlabel = fl6_sock_lookup(sk, fl6.flowlabel);
73c9e02c
GR
880 if (flowlabel == NULL)
881 return -EINVAL;
4e3fd7a0 882 usin->sin6_addr = flowlabel->dst;
73c9e02c
GR
883 fl6_sock_release(flowlabel);
884 }
885 }
886 /*
887 * connect() to INADDR_ANY means loopback (BSD'ism).
888 */
889 if (ipv6_addr_any(&usin->sin6_addr))
890 usin->sin6_addr.s6_addr[15] = 1;
891
892 addr_type = ipv6_addr_type(&usin->sin6_addr);
893
894 if (addr_type & IPV6_ADDR_MULTICAST)
895 return -ENETUNREACH;
896
897 if (addr_type & IPV6_ADDR_LINKLOCAL) {
898 if (addr_len >= sizeof(struct sockaddr_in6) &&
899 usin->sin6_scope_id) {
900 /* If interface is set while binding, indices
901 * must coincide.
902 */
903 if (sk->sk_bound_dev_if &&
904 sk->sk_bound_dev_if != usin->sin6_scope_id)
905 return -EINVAL;
906
907 sk->sk_bound_dev_if = usin->sin6_scope_id;
908 }
909
910 /* Connect to link-local address requires an interface */
911 if (!sk->sk_bound_dev_if)
912 return -EINVAL;
913 }
914
4e3fd7a0 915 np->daddr = usin->sin6_addr;
4c9483b2 916 np->flow_label = fl6.flowlabel;
73c9e02c
GR
917
918 /*
919 * DCCP over IPv4
920 */
921 if (addr_type == IPV6_ADDR_MAPPED) {
922 u32 exthdrlen = icsk->icsk_ext_hdr_len;
923 struct sockaddr_in sin;
924
925 SOCK_DEBUG(sk, "connect: ipv4 mapped\n");
926
927 if (__ipv6_only_sock(sk))
928 return -ENETUNREACH;
929
930 sin.sin_family = AF_INET;
931 sin.sin_port = usin->sin6_port;
932 sin.sin_addr.s_addr = usin->sin6_addr.s6_addr32[3];
933
934 icsk->icsk_af_ops = &dccp_ipv6_mapped;
935 sk->sk_backlog_rcv = dccp_v4_do_rcv;
936
937 err = dccp_v4_connect(sk, (struct sockaddr *)&sin, sizeof(sin));
938 if (err) {
939 icsk->icsk_ext_hdr_len = exthdrlen;
940 icsk->icsk_af_ops = &dccp_ipv6_af_ops;
941 sk->sk_backlog_rcv = dccp_v6_do_rcv;
942 goto failure;
73c9e02c 943 }
c720c7e8
ED
944 ipv6_addr_set_v4mapped(inet->inet_saddr, &np->saddr);
945 ipv6_addr_set_v4mapped(inet->inet_rcv_saddr, &np->rcv_saddr);
73c9e02c
GR
946
947 return err;
948 }
949
950 if (!ipv6_addr_any(&np->rcv_saddr))
951 saddr = &np->rcv_saddr;
952
4c9483b2 953 fl6.flowi6_proto = IPPROTO_DCCP;
4e3fd7a0
AD
954 fl6.daddr = np->daddr;
955 fl6.saddr = saddr ? *saddr : np->saddr;
4c9483b2 956 fl6.flowi6_oif = sk->sk_bound_dev_if;
1958b856
DM
957 fl6.fl6_dport = usin->sin6_port;
958 fl6.fl6_sport = inet->inet_sport;
4c9483b2 959 security_sk_classify_flow(sk, flowi6_to_flowi(&fl6));
73c9e02c 960
4c9483b2 961 final_p = fl6_update_dst(&fl6, np->opt, &final);
73c9e02c 962
4c9483b2 963 dst = ip6_dst_lookup_flow(sk, &fl6, final_p, true);
68d0c6d3
DM
964 if (IS_ERR(dst)) {
965 err = PTR_ERR(dst);
73c9e02c 966 goto failure;
14e50e57 967 }
73c9e02c
GR
968
969 if (saddr == NULL) {
4c9483b2 970 saddr = &fl6.saddr;
4e3fd7a0 971 np->rcv_saddr = *saddr;
73c9e02c
GR
972 }
973
974 /* set the source address */
4e3fd7a0 975 np->saddr = *saddr;
c720c7e8 976 inet->inet_rcv_saddr = LOOPBACK4_IPV6;
73c9e02c
GR
977
978 __ip6_dst_store(sk, dst, NULL, NULL);
979
980 icsk->icsk_ext_hdr_len = 0;
981 if (np->opt != NULL)
982 icsk->icsk_ext_hdr_len = (np->opt->opt_flen +
983 np->opt->opt_nflen);
984
c720c7e8 985 inet->inet_dport = usin->sin6_port;
73c9e02c
GR
986
987 dccp_set_state(sk, DCCP_REQUESTING);
988 err = inet6_hash_connect(&dccp_death_row, sk);
989 if (err)
990 goto late_failure;
d7f7365f
GR
991
992 dp->dccps_iss = secure_dccpv6_sequence_number(np->saddr.s6_addr32,
993 np->daddr.s6_addr32,
c720c7e8
ED
994 inet->inet_sport,
995 inet->inet_dport);
73c9e02c
GR
996 err = dccp_connect(sk);
997 if (err)
998 goto late_failure;
999
1000 return 0;
1001
1002late_failure:
1003 dccp_set_state(sk, DCCP_CLOSED);
1004 __sk_dst_reset(sk);
1005failure:
c720c7e8 1006 inet->inet_dport = 0;
73c9e02c
GR
1007 sk->sk_route_caps = 0;
1008 return err;
1009}
1010
3b401a81 1011static const struct inet_connection_sock_af_ops dccp_ipv6_af_ops = {
543d9cfe
ACM
1012 .queue_xmit = inet6_csk_xmit,
1013 .send_check = dccp_v6_send_check,
1014 .rebuild_header = inet6_sk_rebuild_header,
1015 .conn_request = dccp_v6_conn_request,
1016 .syn_recv_sock = dccp_v6_request_recv_sock,
1017 .net_header_len = sizeof(struct ipv6hdr),
1018 .setsockopt = ipv6_setsockopt,
1019 .getsockopt = ipv6_getsockopt,
1020 .addr2sockaddr = inet6_csk_addr2sockaddr,
1021 .sockaddr_len = sizeof(struct sockaddr_in6),
ab1e0a13 1022 .bind_conflict = inet6_csk_bind_conflict,
3fdadf7d 1023#ifdef CONFIG_COMPAT
543d9cfe
ACM
1024 .compat_setsockopt = compat_ipv6_setsockopt,
1025 .compat_getsockopt = compat_ipv6_getsockopt,
3fdadf7d 1026#endif
3df80d93
ACM
1027};
1028
1029/*
1030 * DCCP over IPv4 via INET6 API
1031 */
3b401a81 1032static const struct inet_connection_sock_af_ops dccp_ipv6_mapped = {
543d9cfe
ACM
1033 .queue_xmit = ip_queue_xmit,
1034 .send_check = dccp_v4_send_check,
1035 .rebuild_header = inet_sk_rebuild_header,
1036 .conn_request = dccp_v6_conn_request,
1037 .syn_recv_sock = dccp_v6_request_recv_sock,
1038 .net_header_len = sizeof(struct iphdr),
1039 .setsockopt = ipv6_setsockopt,
1040 .getsockopt = ipv6_getsockopt,
1041 .addr2sockaddr = inet6_csk_addr2sockaddr,
1042 .sockaddr_len = sizeof(struct sockaddr_in6),
3fdadf7d 1043#ifdef CONFIG_COMPAT
543d9cfe
ACM
1044 .compat_setsockopt = compat_ipv6_setsockopt,
1045 .compat_getsockopt = compat_ipv6_getsockopt,
3fdadf7d 1046#endif
3df80d93
ACM
1047};
1048
1049/* NOTE: A lot of things set to zero explicitly by call to
1050 * sk_alloc() so need not be done here.
1051 */
1052static int dccp_v6_init_sock(struct sock *sk)
1053{
72478873
ACM
1054 static __u8 dccp_v6_ctl_sock_initialized;
1055 int err = dccp_init_sock(sk, dccp_v6_ctl_sock_initialized);
3df80d93 1056
72478873
ACM
1057 if (err == 0) {
1058 if (unlikely(!dccp_v6_ctl_sock_initialized))
1059 dccp_v6_ctl_sock_initialized = 1;
3df80d93 1060 inet_csk(sk)->icsk_af_ops = &dccp_ipv6_af_ops;
72478873 1061 }
3df80d93
ACM
1062
1063 return err;
1064}
1065
7d06b2e0 1066static void dccp_v6_destroy_sock(struct sock *sk)
3df80d93 1067{
3e0fadc5 1068 dccp_destroy_sock(sk);
7d06b2e0 1069 inet6_destroy_sock(sk);
3df80d93
ACM
1070}
1071
73c9e02c
GR
1072static struct timewait_sock_ops dccp6_timewait_sock_ops = {
1073 .twsk_obj_size = sizeof(struct dccp6_timewait_sock),
1074};
1075
3df80d93 1076static struct proto dccp_v6_prot = {
543d9cfe
ACM
1077 .name = "DCCPv6",
1078 .owner = THIS_MODULE,
1079 .close = dccp_close,
1080 .connect = dccp_v6_connect,
1081 .disconnect = dccp_disconnect,
1082 .ioctl = dccp_ioctl,
1083 .init = dccp_v6_init_sock,
1084 .setsockopt = dccp_setsockopt,
1085 .getsockopt = dccp_getsockopt,
1086 .sendmsg = dccp_sendmsg,
1087 .recvmsg = dccp_recvmsg,
1088 .backlog_rcv = dccp_v6_do_rcv,
1089 .hash = dccp_v6_hash,
ab1e0a13 1090 .unhash = inet_unhash,
543d9cfe 1091 .accept = inet_csk_accept,
ab1e0a13 1092 .get_port = inet_csk_get_port,
543d9cfe
ACM
1093 .shutdown = dccp_shutdown,
1094 .destroy = dccp_v6_destroy_sock,
1095 .orphan_count = &dccp_orphan_count,
1096 .max_header = MAX_DCCP_HEADER,
1097 .obj_size = sizeof(struct dccp6_sock),
3ab5aee7 1098 .slab_flags = SLAB_DESTROY_BY_RCU,
543d9cfe
ACM
1099 .rsk_prot = &dccp6_request_sock_ops,
1100 .twsk_prot = &dccp6_timewait_sock_ops,
39d8cda7 1101 .h.hashinfo = &dccp_hashinfo,
3fdadf7d 1102#ifdef CONFIG_COMPAT
543d9cfe
ACM
1103 .compat_setsockopt = compat_dccp_setsockopt,
1104 .compat_getsockopt = compat_dccp_getsockopt,
3fdadf7d 1105#endif
3df80d93
ACM
1106};
1107
41135cc8 1108static const struct inet6_protocol dccp_v6_protocol = {
45329e71
ACM
1109 .handler = dccp_v6_rcv,
1110 .err_handler = dccp_v6_err,
1111 .flags = INET6_PROTO_NOPOLICY | INET6_PROTO_FINAL,
3df80d93
ACM
1112};
1113
5708e868 1114static const struct proto_ops inet6_dccp_ops = {
543d9cfe
ACM
1115 .family = PF_INET6,
1116 .owner = THIS_MODULE,
1117 .release = inet6_release,
1118 .bind = inet6_bind,
1119 .connect = inet_stream_connect,
1120 .socketpair = sock_no_socketpair,
1121 .accept = inet_accept,
1122 .getname = inet6_getname,
1123 .poll = dccp_poll,
1124 .ioctl = inet6_ioctl,
1125 .listen = inet_dccp_listen,
1126 .shutdown = inet_shutdown,
1127 .setsockopt = sock_common_setsockopt,
1128 .getsockopt = sock_common_getsockopt,
1129 .sendmsg = inet_sendmsg,
1130 .recvmsg = sock_common_recvmsg,
1131 .mmap = sock_no_mmap,
1132 .sendpage = sock_no_sendpage,
3fdadf7d 1133#ifdef CONFIG_COMPAT
543d9cfe
ACM
1134 .compat_setsockopt = compat_sock_common_setsockopt,
1135 .compat_getsockopt = compat_sock_common_getsockopt,
3fdadf7d 1136#endif
3df80d93
ACM
1137};
1138
1139static struct inet_protosw dccp_v6_protosw = {
1140 .type = SOCK_DCCP,
1141 .protocol = IPPROTO_DCCP,
1142 .prot = &dccp_v6_prot,
1143 .ops = &inet6_dccp_ops,
d83d8461 1144 .flags = INET_PROTOSW_ICSK,
3df80d93
ACM
1145};
1146
2c8c1e72 1147static int __net_init dccp_v6_init_net(struct net *net)
8231bd27 1148{
d14a0ebd
GR
1149 if (dccp_hashinfo.bhash == NULL)
1150 return -ESOCKTNOSUPPORT;
334527d3 1151
d14a0ebd
GR
1152 return inet_ctl_sock_create(&net->dccp.v6_ctl_sk, PF_INET6,
1153 SOCK_DCCP, IPPROTO_DCCP, net);
8231bd27
PE
1154}
1155
2c8c1e72 1156static void __net_exit dccp_v6_exit_net(struct net *net)
8231bd27 1157{
334527d3 1158 inet_ctl_sock_destroy(net->dccp.v6_ctl_sk);
8231bd27
PE
1159}
1160
1161static struct pernet_operations dccp_v6_ops = {
1162 .init = dccp_v6_init_net,
1163 .exit = dccp_v6_exit_net,
1164};
1165
3df80d93
ACM
1166static int __init dccp_v6_init(void)
1167{
1168 int err = proto_register(&dccp_v6_prot, 1);
1169
1170 if (err != 0)
1171 goto out;
1172
1173 err = inet6_add_protocol(&dccp_v6_protocol, IPPROTO_DCCP);
1174 if (err != 0)
1175 goto out_unregister_proto;
1176
1177 inet6_register_protosw(&dccp_v6_protosw);
72478873 1178
8231bd27
PE
1179 err = register_pernet_subsys(&dccp_v6_ops);
1180 if (err != 0)
1181 goto out_destroy_ctl_sock;
3df80d93
ACM
1182out:
1183 return err;
8231bd27
PE
1184
1185out_destroy_ctl_sock:
72478873
ACM
1186 inet6_del_protocol(&dccp_v6_protocol, IPPROTO_DCCP);
1187 inet6_unregister_protosw(&dccp_v6_protosw);
3df80d93
ACM
1188out_unregister_proto:
1189 proto_unregister(&dccp_v6_prot);
1190 goto out;
1191}
1192
1193static void __exit dccp_v6_exit(void)
1194{
8231bd27 1195 unregister_pernet_subsys(&dccp_v6_ops);
3df80d93
ACM
1196 inet6_del_protocol(&dccp_v6_protocol, IPPROTO_DCCP);
1197 inet6_unregister_protosw(&dccp_v6_protosw);
1198 proto_unregister(&dccp_v6_prot);
1199}
1200
1201module_init(dccp_v6_init);
1202module_exit(dccp_v6_exit);
1203
1204/*
1205 * __stringify doesn't likes enums, so use SOCK_DCCP (6) and IPPROTO_DCCP (33)
1206 * values directly, Also cover the case where the protocol is not specified,
1207 * i.e. net-pf-PF_INET6-proto-0-type-SOCK_DCCP
1208 */
7131c6c7
JD
1209MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_INET6, 33, 6);
1210MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_INET6, 0, 6);
3df80d93
ACM
1211MODULE_LICENSE("GPL");
1212MODULE_AUTHOR("Arnaldo Carvalho de Melo <acme@mandriva.com>");
1213MODULE_DESCRIPTION("DCCPv6 - Datagram Congestion Controlled Protocol");
This page took 0.684687 seconds and 5 git commands to generate.