blob: 3c9f0836404fb59f4730a7949e8be7b0961dec21 [file] [log] [blame]
Arnaldo Carvalho de Melo3df80d92005-12-13 23:24:53 -08001/*
2 * DCCP over IPv6
3 * Linux INET6 implementation
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
15#include <linux/config.h>
16#include <linux/module.h>
17#include <linux/random.h>
18#include <linux/xfrm.h>
19
20#include <net/addrconf.h>
21#include <net/inet_common.h>
22#include <net/inet_hashtables.h>
Arnaldo Carvalho de Melo14c85022005-12-27 02:43:12 -020023#include <net/inet_sock.h>
Arnaldo Carvalho de Melo3df80d92005-12-13 23:24:53 -080024#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>
David S. Milleraa0e4e42006-01-06 22:55:39 -080030#include <net/ip6_checksum.h>
Arnaldo Carvalho de Melo3df80d92005-12-13 23:24:53 -080031#include <net/xfrm.h>
32
33#include "dccp.h"
34#include "ipv6.h"
35
Arnaldo Carvalho de Melo72478872006-03-20 22:00:37 -080036/* Socket used for sending RSTs and ACKs */
37static struct socket *dccp_v6_ctl_socket;
38
Arnaldo Carvalho de Melo3df80d92005-12-13 23:24:53 -080039static void dccp_v6_ctl_send_reset(struct sk_buff *skb);
40static void dccp_v6_reqsk_send_ack(struct sk_buff *skb,
41 struct request_sock *req);
42static void dccp_v6_send_check(struct sock *sk, int len, struct sk_buff *skb);
43
44static int dccp_v6_do_rcv(struct sock *sk, struct sk_buff *skb);
45
46static struct inet_connection_sock_af_ops dccp_ipv6_mapped;
47static struct inet_connection_sock_af_ops dccp_ipv6_af_ops;
48
49static int dccp_v6_get_port(struct sock *sk, unsigned short snum)
50{
51 return inet_csk_get_port(&dccp_hashinfo, sk, snum,
52 inet6_csk_bind_conflict);
53}
54
55static void dccp_v6_hash(struct sock *sk)
56{
57 if (sk->sk_state != DCCP_CLOSED) {
58 if (inet_csk(sk)->icsk_af_ops == &dccp_ipv6_mapped) {
Arnaldo Carvalho de Meloc985ed72006-03-20 21:23:39 -080059 dccp_hash(sk);
Arnaldo Carvalho de Melo3df80d92005-12-13 23:24:53 -080060 return;
61 }
62 local_bh_disable();
63 __inet6_hash(&dccp_hashinfo, sk);
64 local_bh_enable();
65 }
66}
67
68static inline u16 dccp_v6_check(struct dccp_hdr *dh, int len,
69 struct in6_addr *saddr,
70 struct in6_addr *daddr,
71 unsigned long base)
72{
73 return csum_ipv6_magic(saddr, daddr, len, IPPROTO_DCCP, base);
74}
75
76static __u32 dccp_v6_init_sequence(struct sock *sk, struct sk_buff *skb)
77{
78 const struct dccp_hdr *dh = dccp_hdr(skb);
79
80 if (skb->protocol == htons(ETH_P_IPV6))
81 return secure_tcpv6_sequence_number(skb->nh.ipv6h->daddr.s6_addr32,
82 skb->nh.ipv6h->saddr.s6_addr32,
83 dh->dccph_dport,
84 dh->dccph_sport);
85 else
86 return secure_dccp_sequence_number(skb->nh.iph->daddr,
87 skb->nh.iph->saddr,
88 dh->dccph_dport,
89 dh->dccph_sport);
90}
91
Arnaldo Carvalho de Melo3df80d92005-12-13 23:24:53 -080092static int dccp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
93 int addr_len)
94{
95 struct sockaddr_in6 *usin = (struct sockaddr_in6 *) uaddr;
Arnaldo Carvalho de Melod83d8462005-12-13 23:26:10 -080096 struct inet_connection_sock *icsk = inet_csk(sk);
Arnaldo Carvalho de Melo3df80d92005-12-13 23:24:53 -080097 struct inet_sock *inet = inet_sk(sk);
98 struct ipv6_pinfo *np = inet6_sk(sk);
99 struct dccp_sock *dp = dccp_sk(sk);
100 struct in6_addr *saddr = NULL, *final_p = NULL, final;
101 struct flowi fl;
102 struct dst_entry *dst;
103 int addr_type;
104 int err;
105
106 dp->dccps_role = DCCP_ROLE_CLIENT;
107
108 if (addr_len < SIN6_LEN_RFC2133)
109 return -EINVAL;
110
111 if (usin->sin6_family != AF_INET6)
112 return -EAFNOSUPPORT;
113
114 memset(&fl, 0, sizeof(fl));
115
116 if (np->sndflow) {
117 fl.fl6_flowlabel = usin->sin6_flowinfo & IPV6_FLOWINFO_MASK;
118 IP6_ECN_flow_init(fl.fl6_flowlabel);
119 if (fl.fl6_flowlabel & IPV6_FLOWLABEL_MASK) {
120 struct ip6_flowlabel *flowlabel;
121 flowlabel = fl6_sock_lookup(sk, fl.fl6_flowlabel);
122 if (flowlabel == NULL)
123 return -EINVAL;
124 ipv6_addr_copy(&usin->sin6_addr, &flowlabel->dst);
125 fl6_sock_release(flowlabel);
126 }
127 }
128
129 /*
130 * connect() to INADDR_ANY means loopback (BSD'ism).
131 */
132
133 if (ipv6_addr_any(&usin->sin6_addr))
134 usin->sin6_addr.s6_addr[15] = 0x1;
135
136 addr_type = ipv6_addr_type(&usin->sin6_addr);
137
138 if(addr_type & IPV6_ADDR_MULTICAST)
139 return -ENETUNREACH;
140
141 if (addr_type & IPV6_ADDR_LINKLOCAL) {
142 if (addr_len >= sizeof(struct sockaddr_in6) &&
143 usin->sin6_scope_id) {
144 /* If interface is set while binding, indices
145 * must coincide.
146 */
147 if (sk->sk_bound_dev_if &&
148 sk->sk_bound_dev_if != usin->sin6_scope_id)
149 return -EINVAL;
150
151 sk->sk_bound_dev_if = usin->sin6_scope_id;
152 }
153
154 /* Connect to link-local address requires an interface */
155 if (!sk->sk_bound_dev_if)
156 return -EINVAL;
157 }
158
159 ipv6_addr_copy(&np->daddr, &usin->sin6_addr);
160 np->flow_label = fl.fl6_flowlabel;
161
162 /*
163 * DCCP over IPv4
164 */
165
166 if (addr_type == IPV6_ADDR_MAPPED) {
Arnaldo Carvalho de Melod83d8462005-12-13 23:26:10 -0800167 u32 exthdrlen = icsk->icsk_ext_hdr_len;
Arnaldo Carvalho de Melo3df80d92005-12-13 23:24:53 -0800168 struct sockaddr_in sin;
169
170 SOCK_DEBUG(sk, "connect: ipv4 mapped\n");
171
172 if (__ipv6_only_sock(sk))
173 return -ENETUNREACH;
174
175 sin.sin_family = AF_INET;
176 sin.sin_port = usin->sin6_port;
177 sin.sin_addr.s_addr = usin->sin6_addr.s6_addr32[3];
178
Arnaldo Carvalho de Melod83d8462005-12-13 23:26:10 -0800179 icsk->icsk_af_ops = &dccp_ipv6_mapped;
Arnaldo Carvalho de Melo3df80d92005-12-13 23:24:53 -0800180 sk->sk_backlog_rcv = dccp_v4_do_rcv;
181
182 err = dccp_v4_connect(sk, (struct sockaddr *)&sin, sizeof(sin));
183
184 if (err) {
Arnaldo Carvalho de Melod83d8462005-12-13 23:26:10 -0800185 icsk->icsk_ext_hdr_len = exthdrlen;
186 icsk->icsk_af_ops = &dccp_ipv6_af_ops;
Arnaldo Carvalho de Melo3df80d92005-12-13 23:24:53 -0800187 sk->sk_backlog_rcv = dccp_v6_do_rcv;
188 goto failure;
189 } else {
190 ipv6_addr_set(&np->saddr, 0, 0, htonl(0x0000FFFF),
191 inet->saddr);
192 ipv6_addr_set(&np->rcv_saddr, 0, 0, htonl(0x0000FFFF),
193 inet->rcv_saddr);
194 }
195
196 return err;
197 }
198
199 if (!ipv6_addr_any(&np->rcv_saddr))
200 saddr = &np->rcv_saddr;
201
202 fl.proto = IPPROTO_DCCP;
203 ipv6_addr_copy(&fl.fl6_dst, &np->daddr);
204 ipv6_addr_copy(&fl.fl6_src, saddr ? saddr : &np->saddr);
205 fl.oif = sk->sk_bound_dev_if;
206 fl.fl_ip_dport = usin->sin6_port;
207 fl.fl_ip_sport = inet->sport;
208
209 if (np->opt && np->opt->srcrt) {
210 struct rt0_hdr *rt0 = (struct rt0_hdr *)np->opt->srcrt;
211 ipv6_addr_copy(&final, &fl.fl6_dst);
212 ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
213 final_p = &final;
214 }
215
216 err = ip6_dst_lookup(sk, &dst, &fl);
217 if (err)
218 goto failure;
219 if (final_p)
220 ipv6_addr_copy(&fl.fl6_dst, final_p);
221
222 if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0)
223 goto failure;
224
225 if (saddr == NULL) {
226 saddr = &fl.fl6_src;
227 ipv6_addr_copy(&np->rcv_saddr, saddr);
228 }
229
230 /* set the source address */
231 ipv6_addr_copy(&np->saddr, saddr);
232 inet->rcv_saddr = LOOPBACK4_IPV6;
233
234 ip6_dst_store(sk, dst, NULL);
235
Arnaldo Carvalho de Melod83d8462005-12-13 23:26:10 -0800236 icsk->icsk_ext_hdr_len = 0;
Arnaldo Carvalho de Melo3df80d92005-12-13 23:24:53 -0800237 if (np->opt)
Arnaldo Carvalho de Melod83d8462005-12-13 23:26:10 -0800238 icsk->icsk_ext_hdr_len = (np->opt->opt_flen +
239 np->opt->opt_nflen);
Arnaldo Carvalho de Melo3df80d92005-12-13 23:24:53 -0800240
241 inet->dport = usin->sin6_port;
242
243 dccp_set_state(sk, DCCP_REQUESTING);
Arnaldo Carvalho de Melod8313f52005-12-13 23:25:44 -0800244 err = inet6_hash_connect(&dccp_death_row, sk);
Arnaldo Carvalho de Melo3df80d92005-12-13 23:24:53 -0800245 if (err)
246 goto late_failure;
247 /* FIXME */
248#if 0
249 dp->dccps_gar = secure_dccp_v6_sequence_number(np->saddr.s6_addr32,
250 np->daddr.s6_addr32,
251 inet->sport,
252 inet->dport);
253#endif
254 err = dccp_connect(sk);
255 if (err)
256 goto late_failure;
257
258 return 0;
259
260late_failure:
261 dccp_set_state(sk, DCCP_CLOSED);
262 __sk_dst_reset(sk);
263failure:
264 inet->dport = 0;
265 sk->sk_route_caps = 0;
266 return err;
267}
268
269static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
Andrea Bittau60fe62e2006-03-20 19:23:32 -0800270 int type, int code, int offset, __be32 info)
Arnaldo Carvalho de Melo3df80d92005-12-13 23:24:53 -0800271{
272 struct ipv6hdr *hdr = (struct ipv6hdr *)skb->data;
273 const struct dccp_hdr *dh = (struct dccp_hdr *)(skb->data + offset);
274 struct ipv6_pinfo *np;
275 struct sock *sk;
276 int err;
277 __u64 seq;
278
279 sk = inet6_lookup(&dccp_hashinfo, &hdr->daddr, dh->dccph_dport,
280 &hdr->saddr, dh->dccph_sport, skb->dev->ifindex);
281
282 if (sk == NULL) {
283 ICMP6_INC_STATS_BH(__in6_dev_get(skb->dev), ICMP6_MIB_INERRORS);
284 return;
285 }
286
287 if (sk->sk_state == DCCP_TIME_WAIT) {
288 inet_twsk_put((struct inet_timewait_sock *)sk);
289 return;
290 }
291
292 bh_lock_sock(sk);
293 if (sock_owned_by_user(sk))
294 NET_INC_STATS_BH(LINUX_MIB_LOCKDROPPEDICMPS);
295
296 if (sk->sk_state == DCCP_CLOSED)
297 goto out;
298
299 np = inet6_sk(sk);
300
301 if (type == ICMPV6_PKT_TOOBIG) {
Arnaldo Carvalho de Melo3df80d92005-12-13 23:24:53 -0800302 struct dst_entry *dst = NULL;
303
304 if (sock_owned_by_user(sk))
305 goto out;
306 if ((1 << sk->sk_state) & (DCCPF_LISTEN | DCCPF_CLOSED))
307 goto out;
308
309 /* icmp should have updated the destination cache entry */
310 dst = __sk_dst_check(sk, np->dst_cookie);
311
312 if (dst == NULL) {
313 struct inet_sock *inet = inet_sk(sk);
314 struct flowi fl;
315
316 /* BUGGG_FUTURE: Again, it is not clear how
317 to handle rthdr case. Ignore this complexity
318 for now.
319 */
320 memset(&fl, 0, sizeof(fl));
321 fl.proto = IPPROTO_DCCP;
322 ipv6_addr_copy(&fl.fl6_dst, &np->daddr);
323 ipv6_addr_copy(&fl.fl6_src, &np->saddr);
324 fl.oif = sk->sk_bound_dev_if;
325 fl.fl_ip_dport = inet->dport;
326 fl.fl_ip_sport = inet->sport;
327
328 if ((err = ip6_dst_lookup(sk, &dst, &fl))) {
329 sk->sk_err_soft = -err;
330 goto out;
331 }
332
333 if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) {
334 sk->sk_err_soft = -err;
335 goto out;
336 }
337
338 } else
339 dst_hold(dst);
340
Arnaldo Carvalho de Melod83d8462005-12-13 23:26:10 -0800341 if (inet_csk(sk)->icsk_pmtu_cookie > dst_mtu(dst)) {
Arnaldo Carvalho de Melo3df80d92005-12-13 23:24:53 -0800342 dccp_sync_mss(sk, dst_mtu(dst));
343 } /* else let the usual retransmit timer handle it */
344 dst_release(dst);
345 goto out;
346 }
347
348 icmpv6_err_convert(type, code, &err);
349
350 seq = DCCP_SKB_CB(skb)->dccpd_seq;
351 /* Might be for an request_sock */
352 switch (sk->sk_state) {
353 struct request_sock *req, **prev;
354 case DCCP_LISTEN:
355 if (sock_owned_by_user(sk))
356 goto out;
357
358 req = inet6_csk_search_req(sk, &prev, dh->dccph_dport,
359 &hdr->daddr, &hdr->saddr,
360 inet6_iif(skb));
361 if (!req)
362 goto out;
363
364 /* ICMPs are not backlogged, hence we cannot get
365 * an established socket here.
366 */
367 BUG_TRAP(req->sk == NULL);
368
369 if (seq != dccp_rsk(req)->dreq_iss) {
370 NET_INC_STATS_BH(LINUX_MIB_OUTOFWINDOWICMPS);
371 goto out;
372 }
373
374 inet_csk_reqsk_queue_drop(sk, req, prev);
375 goto out;
376
377 case DCCP_REQUESTING:
378 case DCCP_RESPOND: /* Cannot happen.
379 It can, it SYNs are crossed. --ANK */
380 if (!sock_owned_by_user(sk)) {
381 DCCP_INC_STATS_BH(DCCP_MIB_ATTEMPTFAILS);
382 sk->sk_err = err;
383 /*
384 * Wake people up to see the error
385 * (see connect in sock.c)
386 */
387 sk->sk_error_report(sk);
388
389 dccp_done(sk);
390 } else
391 sk->sk_err_soft = err;
392 goto out;
393 }
394
395 if (!sock_owned_by_user(sk) && np->recverr) {
396 sk->sk_err = err;
397 sk->sk_error_report(sk);
398 } else
399 sk->sk_err_soft = err;
400
401out:
402 bh_unlock_sock(sk);
403 sock_put(sk);
404}
405
406
407static int dccp_v6_send_response(struct sock *sk, struct request_sock *req,
408 struct dst_entry *dst)
409{
410 struct inet6_request_sock *ireq6 = inet6_rsk(req);
411 struct ipv6_pinfo *np = inet6_sk(sk);
412 struct sk_buff *skb;
413 struct ipv6_txoptions *opt = NULL;
414 struct in6_addr *final_p = NULL, final;
415 struct flowi fl;
416 int err = -1;
417
418 memset(&fl, 0, sizeof(fl));
419 fl.proto = IPPROTO_DCCP;
420 ipv6_addr_copy(&fl.fl6_dst, &ireq6->rmt_addr);
421 ipv6_addr_copy(&fl.fl6_src, &ireq6->loc_addr);
422 fl.fl6_flowlabel = 0;
423 fl.oif = ireq6->iif;
424 fl.fl_ip_dport = inet_rsk(req)->rmt_port;
425 fl.fl_ip_sport = inet_sk(sk)->sport;
426
427 if (dst == NULL) {
428 opt = np->opt;
429 if (opt == NULL &&
430 np->rxopt.bits.osrcrt == 2 &&
431 ireq6->pktopts) {
432 struct sk_buff *pktopts = ireq6->pktopts;
433 struct inet6_skb_parm *rxopt = IP6CB(pktopts);
434 if (rxopt->srcrt)
435 opt = ipv6_invert_rthdr(sk,
436 (struct ipv6_rt_hdr *)(pktopts->nh.raw +
437 rxopt->srcrt));
438 }
439
440 if (opt && opt->srcrt) {
441 struct rt0_hdr *rt0 = (struct rt0_hdr *)opt->srcrt;
442 ipv6_addr_copy(&final, &fl.fl6_dst);
443 ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
444 final_p = &final;
445 }
446
447 err = ip6_dst_lookup(sk, &dst, &fl);
448 if (err)
449 goto done;
450 if (final_p)
451 ipv6_addr_copy(&fl.fl6_dst, final_p);
452 if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0)
453 goto done;
454 }
455
456 skb = dccp_make_response(sk, dst, req);
457 if (skb != NULL) {
458 struct dccp_hdr *dh = dccp_hdr(skb);
459 dh->dccph_checksum = dccp_v6_check(dh, skb->len,
460 &ireq6->loc_addr,
461 &ireq6->rmt_addr,
462 csum_partial((char *)dh,
463 skb->len,
464 skb->csum));
465 ipv6_addr_copy(&fl.fl6_dst, &ireq6->rmt_addr);
466 err = ip6_xmit(sk, skb, &fl, opt, 0);
467 if (err == NET_XMIT_CN)
468 err = 0;
469 }
470
471done:
472 if (opt && opt != np->opt)
473 sock_kfree_s(sk, opt, opt->tot_len);
David S. Miller0cbd7822006-01-31 17:53:37 -0800474 dst_release(dst);
Arnaldo Carvalho de Melo3df80d92005-12-13 23:24:53 -0800475 return err;
476}
477
478static void dccp_v6_reqsk_destructor(struct request_sock *req)
479{
480 if (inet6_rsk(req)->pktopts != NULL)
481 kfree_skb(inet6_rsk(req)->pktopts);
482}
483
484static struct request_sock_ops dccp6_request_sock_ops = {
485 .family = AF_INET6,
486 .obj_size = sizeof(struct dccp6_request_sock),
487 .rtx_syn_ack = dccp_v6_send_response,
488 .send_ack = dccp_v6_reqsk_send_ack,
489 .destructor = dccp_v6_reqsk_destructor,
490 .send_reset = dccp_v6_ctl_send_reset,
491};
492
Arnaldo Carvalho de Melo6d6ee432005-12-13 23:25:19 -0800493static struct timewait_sock_ops dccp6_timewait_sock_ops = {
494 .twsk_obj_size = sizeof(struct dccp6_timewait_sock),
495};
496
Arnaldo Carvalho de Melo3df80d92005-12-13 23:24:53 -0800497static void dccp_v6_send_check(struct sock *sk, int len, struct sk_buff *skb)
498{
499 struct ipv6_pinfo *np = inet6_sk(sk);
500 struct dccp_hdr *dh = dccp_hdr(skb);
501
502 dh->dccph_checksum = csum_ipv6_magic(&np->saddr, &np->daddr,
503 len, IPPROTO_DCCP,
504 csum_partial((char *)dh,
505 dh->dccph_doff << 2,
506 skb->csum));
507}
508
509static void dccp_v6_ctl_send_reset(struct sk_buff *rxskb)
510{
511 struct dccp_hdr *rxdh = dccp_hdr(rxskb), *dh;
512 const int dccp_hdr_reset_len = sizeof(struct dccp_hdr) +
513 sizeof(struct dccp_hdr_ext) +
514 sizeof(struct dccp_hdr_reset);
515 struct sk_buff *skb;
516 struct flowi fl;
517 u64 seqno;
518
519 if (rxdh->dccph_type == DCCP_PKT_RESET)
520 return;
521
522 if (!ipv6_unicast_destination(rxskb))
523 return;
524
525 /*
526 * We need to grab some memory, and put together an RST,
527 * and then put it into the queue to be sent.
528 */
529
530 skb = alloc_skb(MAX_HEADER + sizeof(struct ipv6hdr) +
531 dccp_hdr_reset_len, GFP_ATOMIC);
532 if (skb == NULL)
533 return;
534
535 skb_reserve(skb, MAX_HEADER + sizeof(struct ipv6hdr) +
536 dccp_hdr_reset_len);
537
538 skb->h.raw = skb_push(skb, dccp_hdr_reset_len);
539 dh = dccp_hdr(skb);
540 memset(dh, 0, dccp_hdr_reset_len);
541
542 /* Swap the send and the receive. */
543 dh->dccph_type = DCCP_PKT_RESET;
544 dh->dccph_sport = rxdh->dccph_dport;
545 dh->dccph_dport = rxdh->dccph_sport;
546 dh->dccph_doff = dccp_hdr_reset_len / 4;
547 dh->dccph_x = 1;
548 dccp_hdr_reset(skb)->dccph_reset_code =
549 DCCP_SKB_CB(rxskb)->dccpd_reset_code;
550
551 /* See "8.3.1. Abnormal Termination" in draft-ietf-dccp-spec-11 */
552 seqno = 0;
553 if (DCCP_SKB_CB(rxskb)->dccpd_ack_seq != DCCP_PKT_WITHOUT_ACK_SEQ)
554 dccp_set_seqno(&seqno, DCCP_SKB_CB(rxskb)->dccpd_ack_seq + 1);
555
556 dccp_hdr_set_seq(dh, seqno);
557 dccp_hdr_set_ack(dccp_hdr_ack_bits(skb),
558 DCCP_SKB_CB(rxskb)->dccpd_seq);
559
560 memset(&fl, 0, sizeof(fl));
561 ipv6_addr_copy(&fl.fl6_dst, &rxskb->nh.ipv6h->saddr);
562 ipv6_addr_copy(&fl.fl6_src, &rxskb->nh.ipv6h->daddr);
563 dh->dccph_checksum = csum_ipv6_magic(&fl.fl6_src, &fl.fl6_dst,
564 sizeof(*dh), IPPROTO_DCCP,
565 skb->csum);
566 fl.proto = IPPROTO_DCCP;
567 fl.oif = inet6_iif(rxskb);
568 fl.fl_ip_dport = dh->dccph_dport;
569 fl.fl_ip_sport = dh->dccph_sport;
570
571 /* sk = NULL, but it is safe for now. RST socket required. */
572 if (!ip6_dst_lookup(NULL, &skb->dst, &fl)) {
573 if (xfrm_lookup(&skb->dst, &fl, NULL, 0) >= 0) {
Arnaldo Carvalho de Melo72478872006-03-20 22:00:37 -0800574 ip6_xmit(dccp_v6_ctl_socket->sk, skb, &fl, NULL, 0);
Arnaldo Carvalho de Melo3df80d92005-12-13 23:24:53 -0800575 DCCP_INC_STATS_BH(DCCP_MIB_OUTSEGS);
576 DCCP_INC_STATS_BH(DCCP_MIB_OUTRSTS);
577 return;
578 }
579 }
580
581 kfree_skb(skb);
582}
583
584static void dccp_v6_ctl_send_ack(struct sk_buff *rxskb)
585{
586 struct flowi fl;
587 struct dccp_hdr *rxdh = dccp_hdr(rxskb), *dh;
588 const int dccp_hdr_ack_len = sizeof(struct dccp_hdr) +
589 sizeof(struct dccp_hdr_ext) +
590 sizeof(struct dccp_hdr_ack_bits);
591 struct sk_buff *skb;
592
593 skb = alloc_skb(MAX_HEADER + sizeof(struct ipv6hdr) +
594 dccp_hdr_ack_len, GFP_ATOMIC);
595 if (skb == NULL)
596 return;
597
598 skb_reserve(skb, MAX_HEADER + sizeof(struct ipv6hdr) +
599 dccp_hdr_ack_len);
600
601 skb->h.raw = skb_push(skb, dccp_hdr_ack_len);
602 dh = dccp_hdr(skb);
603 memset(dh, 0, dccp_hdr_ack_len);
604
605 /* Build DCCP header and checksum it. */
606 dh->dccph_type = DCCP_PKT_ACK;
607 dh->dccph_sport = rxdh->dccph_dport;
608 dh->dccph_dport = rxdh->dccph_sport;
609 dh->dccph_doff = dccp_hdr_ack_len / 4;
610 dh->dccph_x = 1;
611
612 dccp_hdr_set_seq(dh, DCCP_SKB_CB(rxskb)->dccpd_ack_seq);
613 dccp_hdr_set_ack(dccp_hdr_ack_bits(skb),
614 DCCP_SKB_CB(rxskb)->dccpd_seq);
615
616 memset(&fl, 0, sizeof(fl));
617 ipv6_addr_copy(&fl.fl6_dst, &rxskb->nh.ipv6h->saddr);
618 ipv6_addr_copy(&fl.fl6_src, &rxskb->nh.ipv6h->daddr);
619
620 /* FIXME: calculate checksum, IPv4 also should... */
621
622 fl.proto = IPPROTO_DCCP;
623 fl.oif = inet6_iif(rxskb);
624 fl.fl_ip_dport = dh->dccph_dport;
625 fl.fl_ip_sport = dh->dccph_sport;
626
627 if (!ip6_dst_lookup(NULL, &skb->dst, &fl)) {
628 if (xfrm_lookup(&skb->dst, &fl, NULL, 0) >= 0) {
Arnaldo Carvalho de Melo72478872006-03-20 22:00:37 -0800629 ip6_xmit(dccp_v6_ctl_socket->sk, skb, &fl, NULL, 0);
Arnaldo Carvalho de Melo3df80d92005-12-13 23:24:53 -0800630 DCCP_INC_STATS_BH(DCCP_MIB_OUTSEGS);
631 return;
632 }
633 }
634
635 kfree_skb(skb);
636}
637
638static void dccp_v6_reqsk_send_ack(struct sk_buff *skb,
639 struct request_sock *req)
640{
641 dccp_v6_ctl_send_ack(skb);
642}
643
644static struct sock *dccp_v6_hnd_req(struct sock *sk,struct sk_buff *skb)
645{
646 const struct dccp_hdr *dh = dccp_hdr(skb);
647 const struct ipv6hdr *iph = skb->nh.ipv6h;
648 struct sock *nsk;
649 struct request_sock **prev;
650 /* Find possible connection requests. */
651 struct request_sock *req = inet6_csk_search_req(sk, &prev,
652 dh->dccph_sport,
653 &iph->saddr,
654 &iph->daddr,
655 inet6_iif(skb));
656 if (req != NULL)
657 return dccp_check_req(sk, skb, req, prev);
658
659 nsk = __inet6_lookup_established(&dccp_hashinfo,
660 &iph->saddr, dh->dccph_sport,
661 &iph->daddr, ntohs(dh->dccph_dport),
662 inet6_iif(skb));
663
664 if (nsk != NULL) {
665 if (nsk->sk_state != DCCP_TIME_WAIT) {
666 bh_lock_sock(nsk);
667 return nsk;
668 }
669 inet_twsk_put((struct inet_timewait_sock *)nsk);
670 return NULL;
671 }
672
673 return sk;
674}
675
676static int dccp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
677{
678 struct inet_request_sock *ireq;
679 struct dccp_sock dp;
680 struct request_sock *req;
681 struct dccp_request_sock *dreq;
682 struct inet6_request_sock *ireq6;
683 struct ipv6_pinfo *np = inet6_sk(sk);
Andrea Bittau60fe62e2006-03-20 19:23:32 -0800684 const __be32 service = dccp_hdr_request(skb)->dccph_req_service;
Arnaldo Carvalho de Melo3df80d92005-12-13 23:24:53 -0800685 struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb);
686 __u8 reset_code = DCCP_RESET_CODE_TOO_BUSY;
687
688 if (skb->protocol == htons(ETH_P_IP))
689 return dccp_v4_conn_request(sk, skb);
690
691 if (!ipv6_unicast_destination(skb))
692 goto drop;
693
694 if (dccp_bad_service_code(sk, service)) {
695 reset_code = DCCP_RESET_CODE_BAD_SERVICE_CODE;
696 goto drop;
697 }
698 /*
699 * There are no SYN attacks on IPv6, yet...
700 */
701 if (inet_csk_reqsk_queue_is_full(sk))
702 goto drop;
703
704 if (sk_acceptq_is_full(sk) && inet_csk_reqsk_queue_young(sk) > 1)
705 goto drop;
706
707 req = inet6_reqsk_alloc(sk->sk_prot->rsk_prot);
708 if (req == NULL)
709 goto drop;
710
711 /* FIXME: process options */
712
713 dccp_openreq_init(req, &dp, skb);
714
715 ireq6 = inet6_rsk(req);
716 ireq = inet_rsk(req);
717 ipv6_addr_copy(&ireq6->rmt_addr, &skb->nh.ipv6h->saddr);
718 ipv6_addr_copy(&ireq6->loc_addr, &skb->nh.ipv6h->daddr);
719 req->rcv_wnd = 100; /* Fake, option parsing will get the
720 right value */
721 ireq6->pktopts = NULL;
722
723 if (ipv6_opt_accepted(sk, skb) ||
724 np->rxopt.bits.rxinfo || np->rxopt.bits.rxoinfo ||
725 np->rxopt.bits.rxhlim || np->rxopt.bits.rxohlim) {
726 atomic_inc(&skb->users);
727 ireq6->pktopts = skb;
728 }
729 ireq6->iif = sk->sk_bound_dev_if;
730
731 /* So that link locals have meaning */
732 if (!sk->sk_bound_dev_if &&
733 ipv6_addr_type(&ireq6->rmt_addr) & IPV6_ADDR_LINKLOCAL)
734 ireq6->iif = inet6_iif(skb);
735
736 /*
737 * Step 3: Process LISTEN state
738 *
739 * Set S.ISR, S.GSR, S.SWL, S.SWH from packet or Init Cookie
740 *
741 * In fact we defer setting S.GSR, S.SWL, S.SWH to
742 * dccp_create_openreq_child.
743 */
744 dreq = dccp_rsk(req);
745 dreq->dreq_isr = dcb->dccpd_seq;
746 dreq->dreq_iss = dccp_v6_init_sequence(sk, skb);
747 dreq->dreq_service = service;
748
749 if (dccp_v6_send_response(sk, req, NULL))
750 goto drop_and_free;
751
752 inet6_csk_reqsk_queue_hash_add(sk, req, DCCP_TIMEOUT_INIT);
753 return 0;
754
755drop_and_free:
756 reqsk_free(req);
757drop:
758 DCCP_INC_STATS_BH(DCCP_MIB_ATTEMPTFAILS);
759 dcb->dccpd_reset_code = reset_code;
760 return -1;
761}
762
763static struct sock *dccp_v6_request_recv_sock(struct sock *sk,
764 struct sk_buff *skb,
765 struct request_sock *req,
766 struct dst_entry *dst)
767{
768 struct inet6_request_sock *ireq6 = inet6_rsk(req);
769 struct ipv6_pinfo *newnp, *np = inet6_sk(sk);
770 struct inet_sock *newinet;
771 struct dccp_sock *newdp;
772 struct dccp6_sock *newdp6;
773 struct sock *newsk;
774 struct ipv6_txoptions *opt;
775
776 if (skb->protocol == htons(ETH_P_IP)) {
777 /*
778 * v6 mapped
779 */
780
781 newsk = dccp_v4_request_recv_sock(sk, skb, req, dst);
782 if (newsk == NULL)
783 return NULL;
784
785 newdp6 = (struct dccp6_sock *)newsk;
786 newdp = dccp_sk(newsk);
787 newinet = inet_sk(newsk);
788 newinet->pinet6 = &newdp6->inet6;
789 newnp = inet6_sk(newsk);
790
791 memcpy(newnp, np, sizeof(struct ipv6_pinfo));
792
793 ipv6_addr_set(&newnp->daddr, 0, 0, htonl(0x0000FFFF),
794 newinet->daddr);
795
796 ipv6_addr_set(&newnp->saddr, 0, 0, htonl(0x0000FFFF),
797 newinet->saddr);
798
799 ipv6_addr_copy(&newnp->rcv_saddr, &newnp->saddr);
800
801 inet_csk(newsk)->icsk_af_ops = &dccp_ipv6_mapped;
802 newsk->sk_backlog_rcv = dccp_v4_do_rcv;
803 newnp->pktoptions = NULL;
804 newnp->opt = NULL;
805 newnp->mcast_oif = inet6_iif(skb);
806 newnp->mcast_hops = skb->nh.ipv6h->hop_limit;
807
808 /*
809 * No need to charge this sock to the relevant IPv6 refcnt debug socks count
810 * here, dccp_create_openreq_child now does this for us, see the comment in
811 * that function for the gory details. -acme
812 */
813
814 /* It is tricky place. Until this moment IPv4 tcp
815 worked with IPv6 icsk.icsk_af_ops.
816 Sync it now.
817 */
Arnaldo Carvalho de Melod83d8462005-12-13 23:26:10 -0800818 dccp_sync_mss(newsk, inet_csk(newsk)->icsk_pmtu_cookie);
Arnaldo Carvalho de Melo3df80d92005-12-13 23:24:53 -0800819
820 return newsk;
821 }
822
823 opt = np->opt;
824
825 if (sk_acceptq_is_full(sk))
826 goto out_overflow;
827
828 if (np->rxopt.bits.osrcrt == 2 &&
829 opt == NULL && ireq6->pktopts) {
830 struct inet6_skb_parm *rxopt = IP6CB(ireq6->pktopts);
831 if (rxopt->srcrt)
832 opt = ipv6_invert_rthdr(sk,
833 (struct ipv6_rt_hdr *)(ireq6->pktopts->nh.raw +
834 rxopt->srcrt));
835 }
836
837 if (dst == NULL) {
838 struct in6_addr *final_p = NULL, final;
839 struct flowi fl;
840
841 memset(&fl, 0, sizeof(fl));
842 fl.proto = IPPROTO_DCCP;
843 ipv6_addr_copy(&fl.fl6_dst, &ireq6->rmt_addr);
844 if (opt && opt->srcrt) {
845 struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt;
846 ipv6_addr_copy(&final, &fl.fl6_dst);
847 ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
848 final_p = &final;
849 }
850 ipv6_addr_copy(&fl.fl6_src, &ireq6->loc_addr);
851 fl.oif = sk->sk_bound_dev_if;
852 fl.fl_ip_dport = inet_rsk(req)->rmt_port;
853 fl.fl_ip_sport = inet_sk(sk)->sport;
854
855 if (ip6_dst_lookup(sk, &dst, &fl))
856 goto out;
857
858 if (final_p)
859 ipv6_addr_copy(&fl.fl6_dst, final_p);
860
861 if ((xfrm_lookup(&dst, &fl, sk, 0)) < 0)
862 goto out;
863 }
864
865 newsk = dccp_create_openreq_child(sk, req, skb);
866 if (newsk == NULL)
867 goto out;
868
869 /*
870 * No need to charge this sock to the relevant IPv6 refcnt debug socks
871 * count here, dccp_create_openreq_child now does this for us, see the
872 * comment in that function for the gory details. -acme
873 */
874
875 ip6_dst_store(newsk, dst, NULL);
876 newsk->sk_route_caps = dst->dev->features &
877 ~(NETIF_F_IP_CSUM | NETIF_F_TSO);
878
879 newdp6 = (struct dccp6_sock *)newsk;
880 newinet = inet_sk(newsk);
881 newinet->pinet6 = &newdp6->inet6;
882 newdp = dccp_sk(newsk);
883 newnp = inet6_sk(newsk);
884
885 memcpy(newnp, np, sizeof(struct ipv6_pinfo));
886
887 ipv6_addr_copy(&newnp->daddr, &ireq6->rmt_addr);
888 ipv6_addr_copy(&newnp->saddr, &ireq6->loc_addr);
889 ipv6_addr_copy(&newnp->rcv_saddr, &ireq6->loc_addr);
890 newsk->sk_bound_dev_if = ireq6->iif;
891
892 /* Now IPv6 options...
893
894 First: no IPv4 options.
895 */
896 newinet->opt = NULL;
897
898 /* Clone RX bits */
899 newnp->rxopt.all = np->rxopt.all;
900
901 /* Clone pktoptions received with SYN */
902 newnp->pktoptions = NULL;
903 if (ireq6->pktopts != NULL) {
904 newnp->pktoptions = skb_clone(ireq6->pktopts, GFP_ATOMIC);
905 kfree_skb(ireq6->pktopts);
906 ireq6->pktopts = NULL;
907 if (newnp->pktoptions)
908 skb_set_owner_r(newnp->pktoptions, newsk);
909 }
910 newnp->opt = NULL;
911 newnp->mcast_oif = inet6_iif(skb);
912 newnp->mcast_hops = skb->nh.ipv6h->hop_limit;
913
914 /* Clone native IPv6 options from listening socket (if any)
915
916 Yes, keeping reference count would be much more clever,
917 but we make one more one thing there: reattach optmem
918 to newsk.
919 */
920 if (opt) {
921 newnp->opt = ipv6_dup_options(newsk, opt);
922 if (opt != np->opt)
923 sock_kfree_s(sk, opt, opt->tot_len);
924 }
925
Arnaldo Carvalho de Melod83d8462005-12-13 23:26:10 -0800926 inet_csk(newsk)->icsk_ext_hdr_len = 0;
Arnaldo Carvalho de Melo3df80d92005-12-13 23:24:53 -0800927 if (newnp->opt)
Arnaldo Carvalho de Melod83d8462005-12-13 23:26:10 -0800928 inet_csk(newsk)->icsk_ext_hdr_len = (newnp->opt->opt_nflen +
929 newnp->opt->opt_flen);
Arnaldo Carvalho de Melo3df80d92005-12-13 23:24:53 -0800930
931 dccp_sync_mss(newsk, dst_mtu(dst));
932
933 newinet->daddr = newinet->saddr = newinet->rcv_saddr = LOOPBACK4_IPV6;
934
935 __inet6_hash(&dccp_hashinfo, newsk);
936 inet_inherit_port(&dccp_hashinfo, sk, newsk);
937
938 return newsk;
939
940out_overflow:
941 NET_INC_STATS_BH(LINUX_MIB_LISTENOVERFLOWS);
942out:
943 NET_INC_STATS_BH(LINUX_MIB_LISTENDROPS);
944 if (opt && opt != np->opt)
945 sock_kfree_s(sk, opt, opt->tot_len);
946 dst_release(dst);
947 return NULL;
948}
949
950/* The socket must have it's spinlock held when we get
951 * here.
952 *
953 * We have a potential double-lock case here, so even when
954 * doing backlog processing we use the BH locking scheme.
955 * This is because we cannot sleep with the original spinlock
956 * held.
957 */
958static int dccp_v6_do_rcv(struct sock *sk, struct sk_buff *skb)
959{
960 struct ipv6_pinfo *np = inet6_sk(sk);
961 struct sk_buff *opt_skb = NULL;
962
963 /* Imagine: socket is IPv6. IPv4 packet arrives,
964 goes to IPv4 receive handler and backlogged.
965 From backlog it always goes here. Kerboom...
966 Fortunately, dccp_rcv_established and rcv_established
967 handle them correctly, but it is not case with
968 dccp_v6_hnd_req and dccp_v6_ctl_send_reset(). --ANK
969 */
970
971 if (skb->protocol == htons(ETH_P_IP))
972 return dccp_v4_do_rcv(sk, skb);
973
974 if (sk_filter(sk, skb, 0))
975 goto discard;
976
977 /*
978 * socket locking is here for SMP purposes as backlog rcv
979 * is currently called with bh processing disabled.
980 */
981
982 /* Do Stevens' IPV6_PKTOPTIONS.
983
984 Yes, guys, it is the only place in our code, where we
985 may make it not affecting IPv4.
986 The rest of code is protocol independent,
987 and I do not like idea to uglify IPv4.
988
989 Actually, all the idea behind IPV6_PKTOPTIONS
990 looks not very well thought. For now we latch
991 options, received in the last packet, enqueued
992 by tcp. Feel free to propose better solution.
993 --ANK (980728)
994 */
995 if (np->rxopt.all)
996 opt_skb = skb_clone(skb, GFP_ATOMIC);
997
998 if (sk->sk_state == DCCP_OPEN) { /* Fast path */
999 if (dccp_rcv_established(sk, skb, dccp_hdr(skb), skb->len))
1000 goto reset;
1001 return 0;
1002 }
1003
1004 if (sk->sk_state == DCCP_LISTEN) {
1005 struct sock *nsk = dccp_v6_hnd_req(sk, skb);
1006 if (!nsk)
1007 goto discard;
1008
1009 /*
1010 * Queue it on the new socket if the new socket is active,
1011 * otherwise we just shortcircuit this and continue with
1012 * the new socket..
1013 */
1014 if(nsk != sk) {
1015 if (dccp_child_process(sk, nsk, skb))
1016 goto reset;
1017 if (opt_skb)
1018 __kfree_skb(opt_skb);
1019 return 0;
1020 }
1021 }
1022
1023 if (dccp_rcv_state_process(sk, skb, dccp_hdr(skb), skb->len))
1024 goto reset;
1025 return 0;
1026
1027reset:
1028 dccp_v6_ctl_send_reset(skb);
1029discard:
1030 if (opt_skb)
1031 __kfree_skb(opt_skb);
1032 kfree_skb(skb);
1033 return 0;
1034}
1035
Patrick McHardy951dbc82006-01-06 23:02:34 -08001036static int dccp_v6_rcv(struct sk_buff **pskb)
Arnaldo Carvalho de Melo3df80d92005-12-13 23:24:53 -08001037{
1038 const struct dccp_hdr *dh;
1039 struct sk_buff *skb = *pskb;
1040 struct sock *sk;
Arnaldo Carvalho de Melo3df80d92005-12-13 23:24:53 -08001041
1042 /* Step 1: Check header basics: */
1043
1044 if (dccp_invalid_packet(skb))
1045 goto discard_it;
1046
1047 dh = dccp_hdr(skb);
1048
1049 DCCP_SKB_CB(skb)->dccpd_seq = dccp_hdr_seq(skb);
1050 DCCP_SKB_CB(skb)->dccpd_type = dh->dccph_type;
1051
1052 if (dccp_packet_without_ack(skb))
1053 DCCP_SKB_CB(skb)->dccpd_ack_seq = DCCP_PKT_WITHOUT_ACK_SEQ;
1054 else
1055 DCCP_SKB_CB(skb)->dccpd_ack_seq = dccp_hdr_ack_seq(skb);
1056
1057 /* Step 2:
1058 * Look up flow ID in table and get corresponding socket */
1059 sk = __inet6_lookup(&dccp_hashinfo, &skb->nh.ipv6h->saddr,
1060 dh->dccph_sport,
1061 &skb->nh.ipv6h->daddr, ntohs(dh->dccph_dport),
1062 inet6_iif(skb));
1063 /*
1064 * Step 2:
1065 * If no socket ...
1066 * Generate Reset(No Connection) unless P.type == Reset
1067 * Drop packet and return
1068 */
1069 if (sk == NULL)
1070 goto no_dccp_socket;
1071
1072 /*
1073 * Step 2:
1074 * ... or S.state == TIMEWAIT,
1075 * Generate Reset(No Connection) unless P.type == Reset
1076 * Drop packet and return
1077 */
1078
1079 if (sk->sk_state == DCCP_TIME_WAIT)
1080 goto do_time_wait;
1081
1082 if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb))
1083 goto discard_and_relse;
1084
Arnaldo Carvalho de Melo25995ff2005-12-27 02:42:22 -02001085 return sk_receive_skb(sk, skb) ? -1 : 0;
Arnaldo Carvalho de Melo3df80d92005-12-13 23:24:53 -08001086
1087no_dccp_socket:
1088 if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb))
1089 goto discard_it;
1090 /*
1091 * Step 2:
1092 * Generate Reset(No Connection) unless P.type == Reset
1093 * Drop packet and return
1094 */
1095 if (dh->dccph_type != DCCP_PKT_RESET) {
1096 DCCP_SKB_CB(skb)->dccpd_reset_code =
1097 DCCP_RESET_CODE_NO_CONNECTION;
1098 dccp_v6_ctl_send_reset(skb);
1099 }
1100discard_it:
1101
1102 /*
1103 * Discard frame
1104 */
1105
1106 kfree_skb(skb);
1107 return 0;
1108
1109discard_and_relse:
1110 sock_put(sk);
1111 goto discard_it;
1112
1113do_time_wait:
1114 inet_twsk_put((struct inet_timewait_sock *)sk);
1115 goto no_dccp_socket;
1116}
1117
1118static struct inet_connection_sock_af_ops dccp_ipv6_af_ops = {
1119 .queue_xmit = inet6_csk_xmit,
1120 .send_check = dccp_v6_send_check,
1121 .rebuild_header = inet6_sk_rebuild_header,
1122 .conn_request = dccp_v6_conn_request,
1123 .syn_recv_sock = dccp_v6_request_recv_sock,
1124 .net_header_len = sizeof(struct ipv6hdr),
1125 .setsockopt = ipv6_setsockopt,
1126 .getsockopt = ipv6_getsockopt,
1127 .addr2sockaddr = inet6_csk_addr2sockaddr,
1128 .sockaddr_len = sizeof(struct sockaddr_in6)
1129};
1130
1131/*
1132 * DCCP over IPv4 via INET6 API
1133 */
1134static struct inet_connection_sock_af_ops dccp_ipv6_mapped = {
1135 .queue_xmit = ip_queue_xmit,
1136 .send_check = dccp_v4_send_check,
1137 .rebuild_header = inet_sk_rebuild_header,
1138 .conn_request = dccp_v6_conn_request,
1139 .syn_recv_sock = dccp_v6_request_recv_sock,
1140 .net_header_len = sizeof(struct iphdr),
1141 .setsockopt = ipv6_setsockopt,
1142 .getsockopt = ipv6_getsockopt,
1143 .addr2sockaddr = inet6_csk_addr2sockaddr,
1144 .sockaddr_len = sizeof(struct sockaddr_in6)
1145};
1146
1147/* NOTE: A lot of things set to zero explicitly by call to
1148 * sk_alloc() so need not be done here.
1149 */
1150static int dccp_v6_init_sock(struct sock *sk)
1151{
Arnaldo Carvalho de Melo72478872006-03-20 22:00:37 -08001152 static __u8 dccp_v6_ctl_sock_initialized;
1153 int err = dccp_init_sock(sk, dccp_v6_ctl_sock_initialized);
Arnaldo Carvalho de Melo3df80d92005-12-13 23:24:53 -08001154
Arnaldo Carvalho de Melo72478872006-03-20 22:00:37 -08001155 if (err == 0) {
1156 if (unlikely(!dccp_v6_ctl_sock_initialized))
1157 dccp_v6_ctl_sock_initialized = 1;
Arnaldo Carvalho de Melo3df80d92005-12-13 23:24:53 -08001158 inet_csk(sk)->icsk_af_ops = &dccp_ipv6_af_ops;
Arnaldo Carvalho de Melo72478872006-03-20 22:00:37 -08001159 }
Arnaldo Carvalho de Melo3df80d92005-12-13 23:24:53 -08001160
1161 return err;
1162}
1163
1164static int dccp_v6_destroy_sock(struct sock *sk)
1165{
Arnaldo Carvalho de Melo3e0fadc2006-03-20 21:23:15 -08001166 dccp_destroy_sock(sk);
Arnaldo Carvalho de Melo3df80d92005-12-13 23:24:53 -08001167 return inet6_destroy_sock(sk);
1168}
1169
1170static struct proto dccp_v6_prot = {
1171 .name = "DCCPv6",
1172 .owner = THIS_MODULE,
1173 .close = dccp_close,
1174 .connect = dccp_v6_connect,
1175 .disconnect = dccp_disconnect,
1176 .ioctl = dccp_ioctl,
1177 .init = dccp_v6_init_sock,
1178 .setsockopt = dccp_setsockopt,
1179 .getsockopt = dccp_getsockopt,
1180 .sendmsg = dccp_sendmsg,
1181 .recvmsg = dccp_recvmsg,
1182 .backlog_rcv = dccp_v6_do_rcv,
1183 .hash = dccp_v6_hash,
1184 .unhash = dccp_unhash,
1185 .accept = inet_csk_accept,
1186 .get_port = dccp_v6_get_port,
1187 .shutdown = dccp_shutdown,
1188 .destroy = dccp_v6_destroy_sock,
1189 .orphan_count = &dccp_orphan_count,
1190 .max_header = MAX_DCCP_HEADER,
1191 .obj_size = sizeof(struct dccp6_sock),
1192 .rsk_prot = &dccp6_request_sock_ops,
Arnaldo Carvalho de Melo6d6ee432005-12-13 23:25:19 -08001193 .twsk_prot = &dccp6_timewait_sock_ops,
Arnaldo Carvalho de Melo3df80d92005-12-13 23:24:53 -08001194};
1195
1196static struct inet6_protocol dccp_v6_protocol = {
1197 .handler = dccp_v6_rcv,
1198 .err_handler = dccp_v6_err,
1199 .flags = INET6_PROTO_NOPOLICY | INET6_PROTO_FINAL,
1200};
1201
1202static struct proto_ops inet6_dccp_ops = {
1203 .family = PF_INET6,
1204 .owner = THIS_MODULE,
1205 .release = inet6_release,
1206 .bind = inet6_bind,
1207 .connect = inet_stream_connect,
1208 .socketpair = sock_no_socketpair,
1209 .accept = inet_accept,
1210 .getname = inet6_getname,
1211 .poll = dccp_poll,
1212 .ioctl = inet6_ioctl,
1213 .listen = inet_dccp_listen,
1214 .shutdown = inet_shutdown,
1215 .setsockopt = sock_common_setsockopt,
1216 .getsockopt = sock_common_getsockopt,
1217 .sendmsg = inet_sendmsg,
1218 .recvmsg = sock_common_recvmsg,
1219 .mmap = sock_no_mmap,
1220 .sendpage = sock_no_sendpage,
1221};
1222
1223static struct inet_protosw dccp_v6_protosw = {
1224 .type = SOCK_DCCP,
1225 .protocol = IPPROTO_DCCP,
1226 .prot = &dccp_v6_prot,
1227 .ops = &inet6_dccp_ops,
1228 .capability = -1,
Arnaldo Carvalho de Melod83d8462005-12-13 23:26:10 -08001229 .flags = INET_PROTOSW_ICSK,
Arnaldo Carvalho de Melo3df80d92005-12-13 23:24:53 -08001230};
1231
Arnaldo Carvalho de Melo72478872006-03-20 22:00:37 -08001232static char dccp_v6_ctl_socket_err_msg[] __initdata =
1233 KERN_ERR "DCCP: Failed to create the control socket.\n";
1234
1235static 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
Arnaldo Carvalho de Melo3df80d92005-12-13 23:24:53 -08001255static int __init dccp_v6_init(void)
1256{
1257 int err = proto_register(&dccp_v6_prot, 1);
1258
1259 if (err != 0)
1260 goto out;
1261
1262 err = inet6_add_protocol(&dccp_v6_protocol, IPPROTO_DCCP);
1263 if (err != 0)
1264 goto out_unregister_proto;
1265
1266 inet6_register_protosw(&dccp_v6_protosw);
Arnaldo Carvalho de Melo72478872006-03-20 22:00:37 -08001267
1268 if (dccp_v6_ctl_sock_init() != 0)
1269 goto out_unregister_protosw;
Arnaldo Carvalho de Melo3df80d92005-12-13 23:24:53 -08001270out:
1271 return err;
Arnaldo Carvalho de Melo72478872006-03-20 22:00:37 -08001272out_unregister_protosw:
1273 inet6_del_protocol(&dccp_v6_protocol, IPPROTO_DCCP);
1274 inet6_unregister_protosw(&dccp_v6_protosw);
Arnaldo Carvalho de Melo3df80d92005-12-13 23:24:53 -08001275out_unregister_proto:
1276 proto_unregister(&dccp_v6_prot);
1277 goto out;
1278}
1279
1280static void __exit dccp_v6_exit(void)
1281{
1282 inet6_del_protocol(&dccp_v6_protocol, IPPROTO_DCCP);
1283 inet6_unregister_protosw(&dccp_v6_protosw);
1284 proto_unregister(&dccp_v6_prot);
1285}
1286
1287module_init(dccp_v6_init);
1288module_exit(dccp_v6_exit);
1289
1290/*
1291 * __stringify doesn't likes enums, so use SOCK_DCCP (6) and IPPROTO_DCCP (33)
1292 * values directly, Also cover the case where the protocol is not specified,
1293 * i.e. net-pf-PF_INET6-proto-0-type-SOCK_DCCP
1294 */
1295MODULE_ALIAS("net-pf-" __stringify(PF_INET6) "-proto-33-type-6");
1296MODULE_ALIAS("net-pf-" __stringify(PF_INET6) "-proto-0-type-6");
1297MODULE_LICENSE("GPL");
1298MODULE_AUTHOR("Arnaldo Carvalho de Melo <acme@mandriva.com>");
1299MODULE_DESCRIPTION("DCCPv6 - Datagram Congestion Controlled Protocol");