1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * net/dccp/ipv4.c
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * An implementation of the DCCP protocol
6*4882a593Smuzhiyun * Arnaldo Carvalho de Melo <acme@conectiva.com.br>
7*4882a593Smuzhiyun */
8*4882a593Smuzhiyun
9*4882a593Smuzhiyun #include <linux/dccp.h>
10*4882a593Smuzhiyun #include <linux/icmp.h>
11*4882a593Smuzhiyun #include <linux/slab.h>
12*4882a593Smuzhiyun #include <linux/module.h>
13*4882a593Smuzhiyun #include <linux/skbuff.h>
14*4882a593Smuzhiyun #include <linux/random.h>
15*4882a593Smuzhiyun
16*4882a593Smuzhiyun #include <net/icmp.h>
17*4882a593Smuzhiyun #include <net/inet_common.h>
18*4882a593Smuzhiyun #include <net/inet_hashtables.h>
19*4882a593Smuzhiyun #include <net/inet_sock.h>
20*4882a593Smuzhiyun #include <net/protocol.h>
21*4882a593Smuzhiyun #include <net/sock.h>
22*4882a593Smuzhiyun #include <net/timewait_sock.h>
23*4882a593Smuzhiyun #include <net/tcp_states.h>
24*4882a593Smuzhiyun #include <net/xfrm.h>
25*4882a593Smuzhiyun #include <net/secure_seq.h>
26*4882a593Smuzhiyun
27*4882a593Smuzhiyun #include "ackvec.h"
28*4882a593Smuzhiyun #include "ccid.h"
29*4882a593Smuzhiyun #include "dccp.h"
30*4882a593Smuzhiyun #include "feat.h"
31*4882a593Smuzhiyun
32*4882a593Smuzhiyun /*
33*4882a593Smuzhiyun * The per-net dccp.v4_ctl_sk socket is used for responding to
34*4882a593Smuzhiyun * the Out-of-the-blue (OOTB) packets. A control sock will be created
35*4882a593Smuzhiyun * for this socket at the initialization time.
36*4882a593Smuzhiyun */
37*4882a593Smuzhiyun
dccp_v4_connect(struct sock * sk,struct sockaddr * uaddr,int addr_len)38*4882a593Smuzhiyun int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
39*4882a593Smuzhiyun {
40*4882a593Smuzhiyun const struct sockaddr_in *usin = (struct sockaddr_in *)uaddr;
41*4882a593Smuzhiyun struct inet_sock *inet = inet_sk(sk);
42*4882a593Smuzhiyun struct dccp_sock *dp = dccp_sk(sk);
43*4882a593Smuzhiyun __be16 orig_sport, orig_dport;
44*4882a593Smuzhiyun __be32 daddr, nexthop;
45*4882a593Smuzhiyun struct flowi4 *fl4;
46*4882a593Smuzhiyun struct rtable *rt;
47*4882a593Smuzhiyun int err;
48*4882a593Smuzhiyun struct ip_options_rcu *inet_opt;
49*4882a593Smuzhiyun
50*4882a593Smuzhiyun dp->dccps_role = DCCP_ROLE_CLIENT;
51*4882a593Smuzhiyun
52*4882a593Smuzhiyun if (addr_len < sizeof(struct sockaddr_in))
53*4882a593Smuzhiyun return -EINVAL;
54*4882a593Smuzhiyun
55*4882a593Smuzhiyun if (usin->sin_family != AF_INET)
56*4882a593Smuzhiyun return -EAFNOSUPPORT;
57*4882a593Smuzhiyun
58*4882a593Smuzhiyun nexthop = daddr = usin->sin_addr.s_addr;
59*4882a593Smuzhiyun
60*4882a593Smuzhiyun inet_opt = rcu_dereference_protected(inet->inet_opt,
61*4882a593Smuzhiyun lockdep_sock_is_held(sk));
62*4882a593Smuzhiyun if (inet_opt != NULL && inet_opt->opt.srr) {
63*4882a593Smuzhiyun if (daddr == 0)
64*4882a593Smuzhiyun return -EINVAL;
65*4882a593Smuzhiyun nexthop = inet_opt->opt.faddr;
66*4882a593Smuzhiyun }
67*4882a593Smuzhiyun
68*4882a593Smuzhiyun orig_sport = inet->inet_sport;
69*4882a593Smuzhiyun orig_dport = usin->sin_port;
70*4882a593Smuzhiyun fl4 = &inet->cork.fl.u.ip4;
71*4882a593Smuzhiyun rt = ip_route_connect(fl4, nexthop, inet->inet_saddr,
72*4882a593Smuzhiyun RT_CONN_FLAGS(sk), sk->sk_bound_dev_if,
73*4882a593Smuzhiyun IPPROTO_DCCP,
74*4882a593Smuzhiyun orig_sport, orig_dport, sk);
75*4882a593Smuzhiyun if (IS_ERR(rt))
76*4882a593Smuzhiyun return PTR_ERR(rt);
77*4882a593Smuzhiyun
78*4882a593Smuzhiyun if (rt->rt_flags & (RTCF_MULTICAST | RTCF_BROADCAST)) {
79*4882a593Smuzhiyun ip_rt_put(rt);
80*4882a593Smuzhiyun return -ENETUNREACH;
81*4882a593Smuzhiyun }
82*4882a593Smuzhiyun
83*4882a593Smuzhiyun if (inet_opt == NULL || !inet_opt->opt.srr)
84*4882a593Smuzhiyun daddr = fl4->daddr;
85*4882a593Smuzhiyun
86*4882a593Smuzhiyun if (inet->inet_saddr == 0)
87*4882a593Smuzhiyun inet->inet_saddr = fl4->saddr;
88*4882a593Smuzhiyun sk_rcv_saddr_set(sk, inet->inet_saddr);
89*4882a593Smuzhiyun inet->inet_dport = usin->sin_port;
90*4882a593Smuzhiyun sk_daddr_set(sk, daddr);
91*4882a593Smuzhiyun
92*4882a593Smuzhiyun inet_csk(sk)->icsk_ext_hdr_len = 0;
93*4882a593Smuzhiyun if (inet_opt)
94*4882a593Smuzhiyun inet_csk(sk)->icsk_ext_hdr_len = inet_opt->opt.optlen;
95*4882a593Smuzhiyun /*
96*4882a593Smuzhiyun * Socket identity is still unknown (sport may be zero).
97*4882a593Smuzhiyun * However we set state to DCCP_REQUESTING and not releasing socket
98*4882a593Smuzhiyun * lock select source port, enter ourselves into the hash tables and
99*4882a593Smuzhiyun * complete initialization after this.
100*4882a593Smuzhiyun */
101*4882a593Smuzhiyun dccp_set_state(sk, DCCP_REQUESTING);
102*4882a593Smuzhiyun err = inet_hash_connect(&dccp_death_row, sk);
103*4882a593Smuzhiyun if (err != 0)
104*4882a593Smuzhiyun goto failure;
105*4882a593Smuzhiyun
106*4882a593Smuzhiyun rt = ip_route_newports(fl4, rt, orig_sport, orig_dport,
107*4882a593Smuzhiyun inet->inet_sport, inet->inet_dport, sk);
108*4882a593Smuzhiyun if (IS_ERR(rt)) {
109*4882a593Smuzhiyun err = PTR_ERR(rt);
110*4882a593Smuzhiyun rt = NULL;
111*4882a593Smuzhiyun goto failure;
112*4882a593Smuzhiyun }
113*4882a593Smuzhiyun /* OK, now commit destination to socket. */
114*4882a593Smuzhiyun sk_setup_caps(sk, &rt->dst);
115*4882a593Smuzhiyun
116*4882a593Smuzhiyun dp->dccps_iss = secure_dccp_sequence_number(inet->inet_saddr,
117*4882a593Smuzhiyun inet->inet_daddr,
118*4882a593Smuzhiyun inet->inet_sport,
119*4882a593Smuzhiyun inet->inet_dport);
120*4882a593Smuzhiyun inet->inet_id = prandom_u32();
121*4882a593Smuzhiyun
122*4882a593Smuzhiyun err = dccp_connect(sk);
123*4882a593Smuzhiyun rt = NULL;
124*4882a593Smuzhiyun if (err != 0)
125*4882a593Smuzhiyun goto failure;
126*4882a593Smuzhiyun out:
127*4882a593Smuzhiyun return err;
128*4882a593Smuzhiyun failure:
129*4882a593Smuzhiyun /*
130*4882a593Smuzhiyun * This unhashes the socket and releases the local port, if necessary.
131*4882a593Smuzhiyun */
132*4882a593Smuzhiyun dccp_set_state(sk, DCCP_CLOSED);
133*4882a593Smuzhiyun if (!(sk->sk_userlocks & SOCK_BINDADDR_LOCK))
134*4882a593Smuzhiyun inet_reset_saddr(sk);
135*4882a593Smuzhiyun ip_rt_put(rt);
136*4882a593Smuzhiyun sk->sk_route_caps = 0;
137*4882a593Smuzhiyun inet->inet_dport = 0;
138*4882a593Smuzhiyun goto out;
139*4882a593Smuzhiyun }
140*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(dccp_v4_connect);
141*4882a593Smuzhiyun
142*4882a593Smuzhiyun /*
143*4882a593Smuzhiyun * This routine does path mtu discovery as defined in RFC1191.
144*4882a593Smuzhiyun */
dccp_do_pmtu_discovery(struct sock * sk,const struct iphdr * iph,u32 mtu)145*4882a593Smuzhiyun static inline void dccp_do_pmtu_discovery(struct sock *sk,
146*4882a593Smuzhiyun const struct iphdr *iph,
147*4882a593Smuzhiyun u32 mtu)
148*4882a593Smuzhiyun {
149*4882a593Smuzhiyun struct dst_entry *dst;
150*4882a593Smuzhiyun const struct inet_sock *inet = inet_sk(sk);
151*4882a593Smuzhiyun const struct dccp_sock *dp = dccp_sk(sk);
152*4882a593Smuzhiyun
153*4882a593Smuzhiyun /* We are not interested in DCCP_LISTEN and request_socks (RESPONSEs
154*4882a593Smuzhiyun * send out by Linux are always < 576bytes so they should go through
155*4882a593Smuzhiyun * unfragmented).
156*4882a593Smuzhiyun */
157*4882a593Smuzhiyun if (sk->sk_state == DCCP_LISTEN)
158*4882a593Smuzhiyun return;
159*4882a593Smuzhiyun
160*4882a593Smuzhiyun dst = inet_csk_update_pmtu(sk, mtu);
161*4882a593Smuzhiyun if (!dst)
162*4882a593Smuzhiyun return;
163*4882a593Smuzhiyun
164*4882a593Smuzhiyun /* Something is about to be wrong... Remember soft error
165*4882a593Smuzhiyun * for the case, if this connection will not able to recover.
166*4882a593Smuzhiyun */
167*4882a593Smuzhiyun if (mtu < dst_mtu(dst) && ip_dont_fragment(sk, dst))
168*4882a593Smuzhiyun sk->sk_err_soft = EMSGSIZE;
169*4882a593Smuzhiyun
170*4882a593Smuzhiyun mtu = dst_mtu(dst);
171*4882a593Smuzhiyun
172*4882a593Smuzhiyun if (inet->pmtudisc != IP_PMTUDISC_DONT &&
173*4882a593Smuzhiyun ip_sk_accept_pmtu(sk) &&
174*4882a593Smuzhiyun inet_csk(sk)->icsk_pmtu_cookie > mtu) {
175*4882a593Smuzhiyun dccp_sync_mss(sk, mtu);
176*4882a593Smuzhiyun
177*4882a593Smuzhiyun /*
178*4882a593Smuzhiyun * From RFC 4340, sec. 14.1:
179*4882a593Smuzhiyun *
180*4882a593Smuzhiyun * DCCP-Sync packets are the best choice for upward
181*4882a593Smuzhiyun * probing, since DCCP-Sync probes do not risk application
182*4882a593Smuzhiyun * data loss.
183*4882a593Smuzhiyun */
184*4882a593Smuzhiyun dccp_send_sync(sk, dp->dccps_gsr, DCCP_PKT_SYNC);
185*4882a593Smuzhiyun } /* else let the usual retransmit timer handle it */
186*4882a593Smuzhiyun }
187*4882a593Smuzhiyun
dccp_do_redirect(struct sk_buff * skb,struct sock * sk)188*4882a593Smuzhiyun static void dccp_do_redirect(struct sk_buff *skb, struct sock *sk)
189*4882a593Smuzhiyun {
190*4882a593Smuzhiyun struct dst_entry *dst = __sk_dst_check(sk, 0);
191*4882a593Smuzhiyun
192*4882a593Smuzhiyun if (dst)
193*4882a593Smuzhiyun dst->ops->redirect(dst, sk, skb);
194*4882a593Smuzhiyun }
195*4882a593Smuzhiyun
dccp_req_err(struct sock * sk,u64 seq)196*4882a593Smuzhiyun void dccp_req_err(struct sock *sk, u64 seq)
197*4882a593Smuzhiyun {
198*4882a593Smuzhiyun struct request_sock *req = inet_reqsk(sk);
199*4882a593Smuzhiyun struct net *net = sock_net(sk);
200*4882a593Smuzhiyun
201*4882a593Smuzhiyun /*
202*4882a593Smuzhiyun * ICMPs are not backlogged, hence we cannot get an established
203*4882a593Smuzhiyun * socket here.
204*4882a593Smuzhiyun */
205*4882a593Smuzhiyun if (!between48(seq, dccp_rsk(req)->dreq_iss, dccp_rsk(req)->dreq_gss)) {
206*4882a593Smuzhiyun __NET_INC_STATS(net, LINUX_MIB_OUTOFWINDOWICMPS);
207*4882a593Smuzhiyun } else {
208*4882a593Smuzhiyun /*
209*4882a593Smuzhiyun * Still in RESPOND, just remove it silently.
210*4882a593Smuzhiyun * There is no good way to pass the error to the newly
211*4882a593Smuzhiyun * created socket, and POSIX does not want network
212*4882a593Smuzhiyun * errors returned from accept().
213*4882a593Smuzhiyun */
214*4882a593Smuzhiyun inet_csk_reqsk_queue_drop(req->rsk_listener, req);
215*4882a593Smuzhiyun }
216*4882a593Smuzhiyun reqsk_put(req);
217*4882a593Smuzhiyun }
218*4882a593Smuzhiyun EXPORT_SYMBOL(dccp_req_err);
219*4882a593Smuzhiyun
220*4882a593Smuzhiyun /*
221*4882a593Smuzhiyun * This routine is called by the ICMP module when it gets some sort of error
222*4882a593Smuzhiyun * condition. If err < 0 then the socket should be closed and the error
223*4882a593Smuzhiyun * returned to the user. If err > 0 it's just the icmp type << 8 | icmp code.
224*4882a593Smuzhiyun * After adjustment header points to the first 8 bytes of the tcp header. We
225*4882a593Smuzhiyun * need to find the appropriate port.
226*4882a593Smuzhiyun *
227*4882a593Smuzhiyun * The locking strategy used here is very "optimistic". When someone else
228*4882a593Smuzhiyun * accesses the socket the ICMP is just dropped and for some paths there is no
229*4882a593Smuzhiyun * check at all. A more general error queue to queue errors for later handling
230*4882a593Smuzhiyun * is probably better.
231*4882a593Smuzhiyun */
dccp_v4_err(struct sk_buff * skb,u32 info)232*4882a593Smuzhiyun static int dccp_v4_err(struct sk_buff *skb, u32 info)
233*4882a593Smuzhiyun {
234*4882a593Smuzhiyun const struct iphdr *iph = (struct iphdr *)skb->data;
235*4882a593Smuzhiyun const u8 offset = iph->ihl << 2;
236*4882a593Smuzhiyun const struct dccp_hdr *dh;
237*4882a593Smuzhiyun struct dccp_sock *dp;
238*4882a593Smuzhiyun struct inet_sock *inet;
239*4882a593Smuzhiyun const int type = icmp_hdr(skb)->type;
240*4882a593Smuzhiyun const int code = icmp_hdr(skb)->code;
241*4882a593Smuzhiyun struct sock *sk;
242*4882a593Smuzhiyun __u64 seq;
243*4882a593Smuzhiyun int err;
244*4882a593Smuzhiyun struct net *net = dev_net(skb->dev);
245*4882a593Smuzhiyun
246*4882a593Smuzhiyun /* Only need dccph_dport & dccph_sport which are the first
247*4882a593Smuzhiyun * 4 bytes in dccp header.
248*4882a593Smuzhiyun * Our caller (icmp_socket_deliver()) already pulled 8 bytes for us.
249*4882a593Smuzhiyun */
250*4882a593Smuzhiyun BUILD_BUG_ON(offsetofend(struct dccp_hdr, dccph_sport) > 8);
251*4882a593Smuzhiyun BUILD_BUG_ON(offsetofend(struct dccp_hdr, dccph_dport) > 8);
252*4882a593Smuzhiyun dh = (struct dccp_hdr *)(skb->data + offset);
253*4882a593Smuzhiyun
254*4882a593Smuzhiyun sk = __inet_lookup_established(net, &dccp_hashinfo,
255*4882a593Smuzhiyun iph->daddr, dh->dccph_dport,
256*4882a593Smuzhiyun iph->saddr, ntohs(dh->dccph_sport),
257*4882a593Smuzhiyun inet_iif(skb), 0);
258*4882a593Smuzhiyun if (!sk) {
259*4882a593Smuzhiyun __ICMP_INC_STATS(net, ICMP_MIB_INERRORS);
260*4882a593Smuzhiyun return -ENOENT;
261*4882a593Smuzhiyun }
262*4882a593Smuzhiyun
263*4882a593Smuzhiyun if (sk->sk_state == DCCP_TIME_WAIT) {
264*4882a593Smuzhiyun inet_twsk_put(inet_twsk(sk));
265*4882a593Smuzhiyun return 0;
266*4882a593Smuzhiyun }
267*4882a593Smuzhiyun seq = dccp_hdr_seq(dh);
268*4882a593Smuzhiyun if (sk->sk_state == DCCP_NEW_SYN_RECV) {
269*4882a593Smuzhiyun dccp_req_err(sk, seq);
270*4882a593Smuzhiyun return 0;
271*4882a593Smuzhiyun }
272*4882a593Smuzhiyun
273*4882a593Smuzhiyun bh_lock_sock(sk);
274*4882a593Smuzhiyun /* If too many ICMPs get dropped on busy
275*4882a593Smuzhiyun * servers this needs to be solved differently.
276*4882a593Smuzhiyun */
277*4882a593Smuzhiyun if (sock_owned_by_user(sk))
278*4882a593Smuzhiyun __NET_INC_STATS(net, LINUX_MIB_LOCKDROPPEDICMPS);
279*4882a593Smuzhiyun
280*4882a593Smuzhiyun if (sk->sk_state == DCCP_CLOSED)
281*4882a593Smuzhiyun goto out;
282*4882a593Smuzhiyun
283*4882a593Smuzhiyun dp = dccp_sk(sk);
284*4882a593Smuzhiyun if ((1 << sk->sk_state) & ~(DCCPF_REQUESTING | DCCPF_LISTEN) &&
285*4882a593Smuzhiyun !between48(seq, dp->dccps_awl, dp->dccps_awh)) {
286*4882a593Smuzhiyun __NET_INC_STATS(net, LINUX_MIB_OUTOFWINDOWICMPS);
287*4882a593Smuzhiyun goto out;
288*4882a593Smuzhiyun }
289*4882a593Smuzhiyun
290*4882a593Smuzhiyun switch (type) {
291*4882a593Smuzhiyun case ICMP_REDIRECT:
292*4882a593Smuzhiyun if (!sock_owned_by_user(sk))
293*4882a593Smuzhiyun dccp_do_redirect(skb, sk);
294*4882a593Smuzhiyun goto out;
295*4882a593Smuzhiyun case ICMP_SOURCE_QUENCH:
296*4882a593Smuzhiyun /* Just silently ignore these. */
297*4882a593Smuzhiyun goto out;
298*4882a593Smuzhiyun case ICMP_PARAMETERPROB:
299*4882a593Smuzhiyun err = EPROTO;
300*4882a593Smuzhiyun break;
301*4882a593Smuzhiyun case ICMP_DEST_UNREACH:
302*4882a593Smuzhiyun if (code > NR_ICMP_UNREACH)
303*4882a593Smuzhiyun goto out;
304*4882a593Smuzhiyun
305*4882a593Smuzhiyun if (code == ICMP_FRAG_NEEDED) { /* PMTU discovery (RFC1191) */
306*4882a593Smuzhiyun if (!sock_owned_by_user(sk))
307*4882a593Smuzhiyun dccp_do_pmtu_discovery(sk, iph, info);
308*4882a593Smuzhiyun goto out;
309*4882a593Smuzhiyun }
310*4882a593Smuzhiyun
311*4882a593Smuzhiyun err = icmp_err_convert[code].errno;
312*4882a593Smuzhiyun break;
313*4882a593Smuzhiyun case ICMP_TIME_EXCEEDED:
314*4882a593Smuzhiyun err = EHOSTUNREACH;
315*4882a593Smuzhiyun break;
316*4882a593Smuzhiyun default:
317*4882a593Smuzhiyun goto out;
318*4882a593Smuzhiyun }
319*4882a593Smuzhiyun
320*4882a593Smuzhiyun switch (sk->sk_state) {
321*4882a593Smuzhiyun case DCCP_REQUESTING:
322*4882a593Smuzhiyun case DCCP_RESPOND:
323*4882a593Smuzhiyun if (!sock_owned_by_user(sk)) {
324*4882a593Smuzhiyun __DCCP_INC_STATS(DCCP_MIB_ATTEMPTFAILS);
325*4882a593Smuzhiyun sk->sk_err = err;
326*4882a593Smuzhiyun
327*4882a593Smuzhiyun sk->sk_error_report(sk);
328*4882a593Smuzhiyun
329*4882a593Smuzhiyun dccp_done(sk);
330*4882a593Smuzhiyun } else
331*4882a593Smuzhiyun sk->sk_err_soft = err;
332*4882a593Smuzhiyun goto out;
333*4882a593Smuzhiyun }
334*4882a593Smuzhiyun
335*4882a593Smuzhiyun /* If we've already connected we will keep trying
336*4882a593Smuzhiyun * until we time out, or the user gives up.
337*4882a593Smuzhiyun *
338*4882a593Smuzhiyun * rfc1122 4.2.3.9 allows to consider as hard errors
339*4882a593Smuzhiyun * only PROTO_UNREACH and PORT_UNREACH (well, FRAG_FAILED too,
340*4882a593Smuzhiyun * but it is obsoleted by pmtu discovery).
341*4882a593Smuzhiyun *
342*4882a593Smuzhiyun * Note, that in modern internet, where routing is unreliable
343*4882a593Smuzhiyun * and in each dark corner broken firewalls sit, sending random
344*4882a593Smuzhiyun * errors ordered by their masters even this two messages finally lose
345*4882a593Smuzhiyun * their original sense (even Linux sends invalid PORT_UNREACHs)
346*4882a593Smuzhiyun *
347*4882a593Smuzhiyun * Now we are in compliance with RFCs.
348*4882a593Smuzhiyun * --ANK (980905)
349*4882a593Smuzhiyun */
350*4882a593Smuzhiyun
351*4882a593Smuzhiyun inet = inet_sk(sk);
352*4882a593Smuzhiyun if (!sock_owned_by_user(sk) && inet->recverr) {
353*4882a593Smuzhiyun sk->sk_err = err;
354*4882a593Smuzhiyun sk->sk_error_report(sk);
355*4882a593Smuzhiyun } else /* Only an error on timeout */
356*4882a593Smuzhiyun sk->sk_err_soft = err;
357*4882a593Smuzhiyun out:
358*4882a593Smuzhiyun bh_unlock_sock(sk);
359*4882a593Smuzhiyun sock_put(sk);
360*4882a593Smuzhiyun return 0;
361*4882a593Smuzhiyun }
362*4882a593Smuzhiyun
dccp_v4_csum_finish(struct sk_buff * skb,__be32 src,__be32 dst)363*4882a593Smuzhiyun static inline __sum16 dccp_v4_csum_finish(struct sk_buff *skb,
364*4882a593Smuzhiyun __be32 src, __be32 dst)
365*4882a593Smuzhiyun {
366*4882a593Smuzhiyun return csum_tcpudp_magic(src, dst, skb->len, IPPROTO_DCCP, skb->csum);
367*4882a593Smuzhiyun }
368*4882a593Smuzhiyun
dccp_v4_send_check(struct sock * sk,struct sk_buff * skb)369*4882a593Smuzhiyun void dccp_v4_send_check(struct sock *sk, struct sk_buff *skb)
370*4882a593Smuzhiyun {
371*4882a593Smuzhiyun const struct inet_sock *inet = inet_sk(sk);
372*4882a593Smuzhiyun struct dccp_hdr *dh = dccp_hdr(skb);
373*4882a593Smuzhiyun
374*4882a593Smuzhiyun dccp_csum_outgoing(skb);
375*4882a593Smuzhiyun dh->dccph_checksum = dccp_v4_csum_finish(skb,
376*4882a593Smuzhiyun inet->inet_saddr,
377*4882a593Smuzhiyun inet->inet_daddr);
378*4882a593Smuzhiyun }
379*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(dccp_v4_send_check);
380*4882a593Smuzhiyun
dccp_v4_init_sequence(const struct sk_buff * skb)381*4882a593Smuzhiyun static inline u64 dccp_v4_init_sequence(const struct sk_buff *skb)
382*4882a593Smuzhiyun {
383*4882a593Smuzhiyun return secure_dccp_sequence_number(ip_hdr(skb)->daddr,
384*4882a593Smuzhiyun ip_hdr(skb)->saddr,
385*4882a593Smuzhiyun dccp_hdr(skb)->dccph_dport,
386*4882a593Smuzhiyun dccp_hdr(skb)->dccph_sport);
387*4882a593Smuzhiyun }
388*4882a593Smuzhiyun
389*4882a593Smuzhiyun /*
390*4882a593Smuzhiyun * The three way handshake has completed - we got a valid ACK or DATAACK -
391*4882a593Smuzhiyun * now create the new socket.
392*4882a593Smuzhiyun *
393*4882a593Smuzhiyun * This is the equivalent of TCP's tcp_v4_syn_recv_sock
394*4882a593Smuzhiyun */
dccp_v4_request_recv_sock(const struct sock * sk,struct sk_buff * skb,struct request_sock * req,struct dst_entry * dst,struct request_sock * req_unhash,bool * own_req)395*4882a593Smuzhiyun struct sock *dccp_v4_request_recv_sock(const struct sock *sk,
396*4882a593Smuzhiyun struct sk_buff *skb,
397*4882a593Smuzhiyun struct request_sock *req,
398*4882a593Smuzhiyun struct dst_entry *dst,
399*4882a593Smuzhiyun struct request_sock *req_unhash,
400*4882a593Smuzhiyun bool *own_req)
401*4882a593Smuzhiyun {
402*4882a593Smuzhiyun struct inet_request_sock *ireq;
403*4882a593Smuzhiyun struct inet_sock *newinet;
404*4882a593Smuzhiyun struct sock *newsk;
405*4882a593Smuzhiyun
406*4882a593Smuzhiyun if (sk_acceptq_is_full(sk))
407*4882a593Smuzhiyun goto exit_overflow;
408*4882a593Smuzhiyun
409*4882a593Smuzhiyun newsk = dccp_create_openreq_child(sk, req, skb);
410*4882a593Smuzhiyun if (newsk == NULL)
411*4882a593Smuzhiyun goto exit_nonewsk;
412*4882a593Smuzhiyun
413*4882a593Smuzhiyun newinet = inet_sk(newsk);
414*4882a593Smuzhiyun ireq = inet_rsk(req);
415*4882a593Smuzhiyun sk_daddr_set(newsk, ireq->ir_rmt_addr);
416*4882a593Smuzhiyun sk_rcv_saddr_set(newsk, ireq->ir_loc_addr);
417*4882a593Smuzhiyun newinet->inet_saddr = ireq->ir_loc_addr;
418*4882a593Smuzhiyun RCU_INIT_POINTER(newinet->inet_opt, rcu_dereference(ireq->ireq_opt));
419*4882a593Smuzhiyun newinet->mc_index = inet_iif(skb);
420*4882a593Smuzhiyun newinet->mc_ttl = ip_hdr(skb)->ttl;
421*4882a593Smuzhiyun newinet->inet_id = prandom_u32();
422*4882a593Smuzhiyun
423*4882a593Smuzhiyun if (dst == NULL && (dst = inet_csk_route_child_sock(sk, newsk, req)) == NULL)
424*4882a593Smuzhiyun goto put_and_exit;
425*4882a593Smuzhiyun
426*4882a593Smuzhiyun sk_setup_caps(newsk, dst);
427*4882a593Smuzhiyun
428*4882a593Smuzhiyun dccp_sync_mss(newsk, dst_mtu(dst));
429*4882a593Smuzhiyun
430*4882a593Smuzhiyun if (__inet_inherit_port(sk, newsk) < 0)
431*4882a593Smuzhiyun goto put_and_exit;
432*4882a593Smuzhiyun *own_req = inet_ehash_nolisten(newsk, req_to_sk(req_unhash), NULL);
433*4882a593Smuzhiyun if (*own_req)
434*4882a593Smuzhiyun ireq->ireq_opt = NULL;
435*4882a593Smuzhiyun else
436*4882a593Smuzhiyun newinet->inet_opt = NULL;
437*4882a593Smuzhiyun return newsk;
438*4882a593Smuzhiyun
439*4882a593Smuzhiyun exit_overflow:
440*4882a593Smuzhiyun __NET_INC_STATS(sock_net(sk), LINUX_MIB_LISTENOVERFLOWS);
441*4882a593Smuzhiyun exit_nonewsk:
442*4882a593Smuzhiyun dst_release(dst);
443*4882a593Smuzhiyun exit:
444*4882a593Smuzhiyun __NET_INC_STATS(sock_net(sk), LINUX_MIB_LISTENDROPS);
445*4882a593Smuzhiyun return NULL;
446*4882a593Smuzhiyun put_and_exit:
447*4882a593Smuzhiyun newinet->inet_opt = NULL;
448*4882a593Smuzhiyun inet_csk_prepare_forced_close(newsk);
449*4882a593Smuzhiyun dccp_done(newsk);
450*4882a593Smuzhiyun goto exit;
451*4882a593Smuzhiyun }
452*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(dccp_v4_request_recv_sock);
453*4882a593Smuzhiyun
dccp_v4_route_skb(struct net * net,struct sock * sk,struct sk_buff * skb)454*4882a593Smuzhiyun static struct dst_entry* dccp_v4_route_skb(struct net *net, struct sock *sk,
455*4882a593Smuzhiyun struct sk_buff *skb)
456*4882a593Smuzhiyun {
457*4882a593Smuzhiyun struct rtable *rt;
458*4882a593Smuzhiyun const struct iphdr *iph = ip_hdr(skb);
459*4882a593Smuzhiyun struct flowi4 fl4 = {
460*4882a593Smuzhiyun .flowi4_oif = inet_iif(skb),
461*4882a593Smuzhiyun .daddr = iph->saddr,
462*4882a593Smuzhiyun .saddr = iph->daddr,
463*4882a593Smuzhiyun .flowi4_tos = RT_CONN_FLAGS(sk),
464*4882a593Smuzhiyun .flowi4_proto = sk->sk_protocol,
465*4882a593Smuzhiyun .fl4_sport = dccp_hdr(skb)->dccph_dport,
466*4882a593Smuzhiyun .fl4_dport = dccp_hdr(skb)->dccph_sport,
467*4882a593Smuzhiyun };
468*4882a593Smuzhiyun
469*4882a593Smuzhiyun security_skb_classify_flow(skb, flowi4_to_flowi_common(&fl4));
470*4882a593Smuzhiyun rt = ip_route_output_flow(net, &fl4, sk);
471*4882a593Smuzhiyun if (IS_ERR(rt)) {
472*4882a593Smuzhiyun IP_INC_STATS(net, IPSTATS_MIB_OUTNOROUTES);
473*4882a593Smuzhiyun return NULL;
474*4882a593Smuzhiyun }
475*4882a593Smuzhiyun
476*4882a593Smuzhiyun return &rt->dst;
477*4882a593Smuzhiyun }
478*4882a593Smuzhiyun
dccp_v4_send_response(const struct sock * sk,struct request_sock * req)479*4882a593Smuzhiyun static int dccp_v4_send_response(const struct sock *sk, struct request_sock *req)
480*4882a593Smuzhiyun {
481*4882a593Smuzhiyun int err = -1;
482*4882a593Smuzhiyun struct sk_buff *skb;
483*4882a593Smuzhiyun struct dst_entry *dst;
484*4882a593Smuzhiyun struct flowi4 fl4;
485*4882a593Smuzhiyun
486*4882a593Smuzhiyun dst = inet_csk_route_req(sk, &fl4, req);
487*4882a593Smuzhiyun if (dst == NULL)
488*4882a593Smuzhiyun goto out;
489*4882a593Smuzhiyun
490*4882a593Smuzhiyun skb = dccp_make_response(sk, dst, req);
491*4882a593Smuzhiyun if (skb != NULL) {
492*4882a593Smuzhiyun const struct inet_request_sock *ireq = inet_rsk(req);
493*4882a593Smuzhiyun struct dccp_hdr *dh = dccp_hdr(skb);
494*4882a593Smuzhiyun
495*4882a593Smuzhiyun dh->dccph_checksum = dccp_v4_csum_finish(skb, ireq->ir_loc_addr,
496*4882a593Smuzhiyun ireq->ir_rmt_addr);
497*4882a593Smuzhiyun rcu_read_lock();
498*4882a593Smuzhiyun err = ip_build_and_send_pkt(skb, sk, ireq->ir_loc_addr,
499*4882a593Smuzhiyun ireq->ir_rmt_addr,
500*4882a593Smuzhiyun rcu_dereference(ireq->ireq_opt),
501*4882a593Smuzhiyun inet_sk(sk)->tos);
502*4882a593Smuzhiyun rcu_read_unlock();
503*4882a593Smuzhiyun err = net_xmit_eval(err);
504*4882a593Smuzhiyun }
505*4882a593Smuzhiyun
506*4882a593Smuzhiyun out:
507*4882a593Smuzhiyun dst_release(dst);
508*4882a593Smuzhiyun return err;
509*4882a593Smuzhiyun }
510*4882a593Smuzhiyun
dccp_v4_ctl_send_reset(const struct sock * sk,struct sk_buff * rxskb)511*4882a593Smuzhiyun static void dccp_v4_ctl_send_reset(const struct sock *sk, struct sk_buff *rxskb)
512*4882a593Smuzhiyun {
513*4882a593Smuzhiyun int err;
514*4882a593Smuzhiyun const struct iphdr *rxiph;
515*4882a593Smuzhiyun struct sk_buff *skb;
516*4882a593Smuzhiyun struct dst_entry *dst;
517*4882a593Smuzhiyun struct net *net = dev_net(skb_dst(rxskb)->dev);
518*4882a593Smuzhiyun struct sock *ctl_sk = net->dccp.v4_ctl_sk;
519*4882a593Smuzhiyun
520*4882a593Smuzhiyun /* Never send a reset in response to a reset. */
521*4882a593Smuzhiyun if (dccp_hdr(rxskb)->dccph_type == DCCP_PKT_RESET)
522*4882a593Smuzhiyun return;
523*4882a593Smuzhiyun
524*4882a593Smuzhiyun if (skb_rtable(rxskb)->rt_type != RTN_LOCAL)
525*4882a593Smuzhiyun return;
526*4882a593Smuzhiyun
527*4882a593Smuzhiyun dst = dccp_v4_route_skb(net, ctl_sk, rxskb);
528*4882a593Smuzhiyun if (dst == NULL)
529*4882a593Smuzhiyun return;
530*4882a593Smuzhiyun
531*4882a593Smuzhiyun skb = dccp_ctl_make_reset(ctl_sk, rxskb);
532*4882a593Smuzhiyun if (skb == NULL)
533*4882a593Smuzhiyun goto out;
534*4882a593Smuzhiyun
535*4882a593Smuzhiyun rxiph = ip_hdr(rxskb);
536*4882a593Smuzhiyun dccp_hdr(skb)->dccph_checksum = dccp_v4_csum_finish(skb, rxiph->saddr,
537*4882a593Smuzhiyun rxiph->daddr);
538*4882a593Smuzhiyun skb_dst_set(skb, dst_clone(dst));
539*4882a593Smuzhiyun
540*4882a593Smuzhiyun local_bh_disable();
541*4882a593Smuzhiyun bh_lock_sock(ctl_sk);
542*4882a593Smuzhiyun err = ip_build_and_send_pkt(skb, ctl_sk,
543*4882a593Smuzhiyun rxiph->daddr, rxiph->saddr, NULL,
544*4882a593Smuzhiyun inet_sk(ctl_sk)->tos);
545*4882a593Smuzhiyun bh_unlock_sock(ctl_sk);
546*4882a593Smuzhiyun
547*4882a593Smuzhiyun if (net_xmit_eval(err) == 0) {
548*4882a593Smuzhiyun __DCCP_INC_STATS(DCCP_MIB_OUTSEGS);
549*4882a593Smuzhiyun __DCCP_INC_STATS(DCCP_MIB_OUTRSTS);
550*4882a593Smuzhiyun }
551*4882a593Smuzhiyun local_bh_enable();
552*4882a593Smuzhiyun out:
553*4882a593Smuzhiyun dst_release(dst);
554*4882a593Smuzhiyun }
555*4882a593Smuzhiyun
dccp_v4_reqsk_destructor(struct request_sock * req)556*4882a593Smuzhiyun static void dccp_v4_reqsk_destructor(struct request_sock *req)
557*4882a593Smuzhiyun {
558*4882a593Smuzhiyun dccp_feat_list_purge(&dccp_rsk(req)->dreq_featneg);
559*4882a593Smuzhiyun kfree(rcu_dereference_protected(inet_rsk(req)->ireq_opt, 1));
560*4882a593Smuzhiyun }
561*4882a593Smuzhiyun
dccp_syn_ack_timeout(const struct request_sock * req)562*4882a593Smuzhiyun void dccp_syn_ack_timeout(const struct request_sock *req)
563*4882a593Smuzhiyun {
564*4882a593Smuzhiyun }
565*4882a593Smuzhiyun EXPORT_SYMBOL(dccp_syn_ack_timeout);
566*4882a593Smuzhiyun
567*4882a593Smuzhiyun static struct request_sock_ops dccp_request_sock_ops __read_mostly = {
568*4882a593Smuzhiyun .family = PF_INET,
569*4882a593Smuzhiyun .obj_size = sizeof(struct dccp_request_sock),
570*4882a593Smuzhiyun .rtx_syn_ack = dccp_v4_send_response,
571*4882a593Smuzhiyun .send_ack = dccp_reqsk_send_ack,
572*4882a593Smuzhiyun .destructor = dccp_v4_reqsk_destructor,
573*4882a593Smuzhiyun .send_reset = dccp_v4_ctl_send_reset,
574*4882a593Smuzhiyun .syn_ack_timeout = dccp_syn_ack_timeout,
575*4882a593Smuzhiyun };
576*4882a593Smuzhiyun
dccp_v4_conn_request(struct sock * sk,struct sk_buff * skb)577*4882a593Smuzhiyun int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
578*4882a593Smuzhiyun {
579*4882a593Smuzhiyun struct inet_request_sock *ireq;
580*4882a593Smuzhiyun struct request_sock *req;
581*4882a593Smuzhiyun struct dccp_request_sock *dreq;
582*4882a593Smuzhiyun const __be32 service = dccp_hdr_request(skb)->dccph_req_service;
583*4882a593Smuzhiyun struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb);
584*4882a593Smuzhiyun
585*4882a593Smuzhiyun /* Never answer to DCCP_PKT_REQUESTs send to broadcast or multicast */
586*4882a593Smuzhiyun if (skb_rtable(skb)->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST))
587*4882a593Smuzhiyun return 0; /* discard, don't send a reset here */
588*4882a593Smuzhiyun
589*4882a593Smuzhiyun if (dccp_bad_service_code(sk, service)) {
590*4882a593Smuzhiyun dcb->dccpd_reset_code = DCCP_RESET_CODE_BAD_SERVICE_CODE;
591*4882a593Smuzhiyun goto drop;
592*4882a593Smuzhiyun }
593*4882a593Smuzhiyun /*
594*4882a593Smuzhiyun * TW buckets are converted to open requests without
595*4882a593Smuzhiyun * limitations, they conserve resources and peer is
596*4882a593Smuzhiyun * evidently real one.
597*4882a593Smuzhiyun */
598*4882a593Smuzhiyun dcb->dccpd_reset_code = DCCP_RESET_CODE_TOO_BUSY;
599*4882a593Smuzhiyun if (inet_csk_reqsk_queue_is_full(sk))
600*4882a593Smuzhiyun goto drop;
601*4882a593Smuzhiyun
602*4882a593Smuzhiyun if (sk_acceptq_is_full(sk))
603*4882a593Smuzhiyun goto drop;
604*4882a593Smuzhiyun
605*4882a593Smuzhiyun req = inet_reqsk_alloc(&dccp_request_sock_ops, sk, true);
606*4882a593Smuzhiyun if (req == NULL)
607*4882a593Smuzhiyun goto drop;
608*4882a593Smuzhiyun
609*4882a593Smuzhiyun if (dccp_reqsk_init(req, dccp_sk(sk), skb))
610*4882a593Smuzhiyun goto drop_and_free;
611*4882a593Smuzhiyun
612*4882a593Smuzhiyun dreq = dccp_rsk(req);
613*4882a593Smuzhiyun if (dccp_parse_options(sk, dreq, skb))
614*4882a593Smuzhiyun goto drop_and_free;
615*4882a593Smuzhiyun
616*4882a593Smuzhiyun if (security_inet_conn_request(sk, skb, req))
617*4882a593Smuzhiyun goto drop_and_free;
618*4882a593Smuzhiyun
619*4882a593Smuzhiyun ireq = inet_rsk(req);
620*4882a593Smuzhiyun sk_rcv_saddr_set(req_to_sk(req), ip_hdr(skb)->daddr);
621*4882a593Smuzhiyun sk_daddr_set(req_to_sk(req), ip_hdr(skb)->saddr);
622*4882a593Smuzhiyun ireq->ir_mark = inet_request_mark(sk, skb);
623*4882a593Smuzhiyun ireq->ireq_family = AF_INET;
624*4882a593Smuzhiyun ireq->ir_iif = sk->sk_bound_dev_if;
625*4882a593Smuzhiyun
626*4882a593Smuzhiyun /*
627*4882a593Smuzhiyun * Step 3: Process LISTEN state
628*4882a593Smuzhiyun *
629*4882a593Smuzhiyun * Set S.ISR, S.GSR, S.SWL, S.SWH from packet or Init Cookie
630*4882a593Smuzhiyun *
631*4882a593Smuzhiyun * Setting S.SWL/S.SWH to is deferred to dccp_create_openreq_child().
632*4882a593Smuzhiyun */
633*4882a593Smuzhiyun dreq->dreq_isr = dcb->dccpd_seq;
634*4882a593Smuzhiyun dreq->dreq_gsr = dreq->dreq_isr;
635*4882a593Smuzhiyun dreq->dreq_iss = dccp_v4_init_sequence(skb);
636*4882a593Smuzhiyun dreq->dreq_gss = dreq->dreq_iss;
637*4882a593Smuzhiyun dreq->dreq_service = service;
638*4882a593Smuzhiyun
639*4882a593Smuzhiyun if (dccp_v4_send_response(sk, req))
640*4882a593Smuzhiyun goto drop_and_free;
641*4882a593Smuzhiyun
642*4882a593Smuzhiyun inet_csk_reqsk_queue_hash_add(sk, req, DCCP_TIMEOUT_INIT);
643*4882a593Smuzhiyun reqsk_put(req);
644*4882a593Smuzhiyun return 0;
645*4882a593Smuzhiyun
646*4882a593Smuzhiyun drop_and_free:
647*4882a593Smuzhiyun reqsk_free(req);
648*4882a593Smuzhiyun drop:
649*4882a593Smuzhiyun __DCCP_INC_STATS(DCCP_MIB_ATTEMPTFAILS);
650*4882a593Smuzhiyun return -1;
651*4882a593Smuzhiyun }
652*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(dccp_v4_conn_request);
653*4882a593Smuzhiyun
dccp_v4_do_rcv(struct sock * sk,struct sk_buff * skb)654*4882a593Smuzhiyun int dccp_v4_do_rcv(struct sock *sk, struct sk_buff *skb)
655*4882a593Smuzhiyun {
656*4882a593Smuzhiyun struct dccp_hdr *dh = dccp_hdr(skb);
657*4882a593Smuzhiyun
658*4882a593Smuzhiyun if (sk->sk_state == DCCP_OPEN) { /* Fast path */
659*4882a593Smuzhiyun if (dccp_rcv_established(sk, skb, dh, skb->len))
660*4882a593Smuzhiyun goto reset;
661*4882a593Smuzhiyun return 0;
662*4882a593Smuzhiyun }
663*4882a593Smuzhiyun
664*4882a593Smuzhiyun /*
665*4882a593Smuzhiyun * Step 3: Process LISTEN state
666*4882a593Smuzhiyun * If P.type == Request or P contains a valid Init Cookie option,
667*4882a593Smuzhiyun * (* Must scan the packet's options to check for Init
668*4882a593Smuzhiyun * Cookies. Only Init Cookies are processed here,
669*4882a593Smuzhiyun * however; other options are processed in Step 8. This
670*4882a593Smuzhiyun * scan need only be performed if the endpoint uses Init
671*4882a593Smuzhiyun * Cookies *)
672*4882a593Smuzhiyun * (* Generate a new socket and switch to that socket *)
673*4882a593Smuzhiyun * Set S := new socket for this port pair
674*4882a593Smuzhiyun * S.state = RESPOND
675*4882a593Smuzhiyun * Choose S.ISS (initial seqno) or set from Init Cookies
676*4882a593Smuzhiyun * Initialize S.GAR := S.ISS
677*4882a593Smuzhiyun * Set S.ISR, S.GSR, S.SWL, S.SWH from packet or Init Cookies
678*4882a593Smuzhiyun * Continue with S.state == RESPOND
679*4882a593Smuzhiyun * (* A Response packet will be generated in Step 11 *)
680*4882a593Smuzhiyun * Otherwise,
681*4882a593Smuzhiyun * Generate Reset(No Connection) unless P.type == Reset
682*4882a593Smuzhiyun * Drop packet and return
683*4882a593Smuzhiyun *
684*4882a593Smuzhiyun * NOTE: the check for the packet types is done in
685*4882a593Smuzhiyun * dccp_rcv_state_process
686*4882a593Smuzhiyun */
687*4882a593Smuzhiyun
688*4882a593Smuzhiyun if (dccp_rcv_state_process(sk, skb, dh, skb->len))
689*4882a593Smuzhiyun goto reset;
690*4882a593Smuzhiyun return 0;
691*4882a593Smuzhiyun
692*4882a593Smuzhiyun reset:
693*4882a593Smuzhiyun dccp_v4_ctl_send_reset(sk, skb);
694*4882a593Smuzhiyun kfree_skb(skb);
695*4882a593Smuzhiyun return 0;
696*4882a593Smuzhiyun }
697*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(dccp_v4_do_rcv);
698*4882a593Smuzhiyun
699*4882a593Smuzhiyun /**
700*4882a593Smuzhiyun * dccp_invalid_packet - check for malformed packets
701*4882a593Smuzhiyun * @skb: Packet to validate
702*4882a593Smuzhiyun *
703*4882a593Smuzhiyun * Implements RFC 4340, 8.5: Step 1: Check header basics
704*4882a593Smuzhiyun * Packets that fail these checks are ignored and do not receive Resets.
705*4882a593Smuzhiyun */
dccp_invalid_packet(struct sk_buff * skb)706*4882a593Smuzhiyun int dccp_invalid_packet(struct sk_buff *skb)
707*4882a593Smuzhiyun {
708*4882a593Smuzhiyun const struct dccp_hdr *dh;
709*4882a593Smuzhiyun unsigned int cscov;
710*4882a593Smuzhiyun u8 dccph_doff;
711*4882a593Smuzhiyun
712*4882a593Smuzhiyun if (skb->pkt_type != PACKET_HOST)
713*4882a593Smuzhiyun return 1;
714*4882a593Smuzhiyun
715*4882a593Smuzhiyun /* If the packet is shorter than 12 bytes, drop packet and return */
716*4882a593Smuzhiyun if (!pskb_may_pull(skb, sizeof(struct dccp_hdr))) {
717*4882a593Smuzhiyun DCCP_WARN("pskb_may_pull failed\n");
718*4882a593Smuzhiyun return 1;
719*4882a593Smuzhiyun }
720*4882a593Smuzhiyun
721*4882a593Smuzhiyun dh = dccp_hdr(skb);
722*4882a593Smuzhiyun
723*4882a593Smuzhiyun /* If P.type is not understood, drop packet and return */
724*4882a593Smuzhiyun if (dh->dccph_type >= DCCP_PKT_INVALID) {
725*4882a593Smuzhiyun DCCP_WARN("invalid packet type\n");
726*4882a593Smuzhiyun return 1;
727*4882a593Smuzhiyun }
728*4882a593Smuzhiyun
729*4882a593Smuzhiyun /*
730*4882a593Smuzhiyun * If P.Data Offset is too small for packet type, drop packet and return
731*4882a593Smuzhiyun */
732*4882a593Smuzhiyun dccph_doff = dh->dccph_doff;
733*4882a593Smuzhiyun if (dccph_doff < dccp_hdr_len(skb) / sizeof(u32)) {
734*4882a593Smuzhiyun DCCP_WARN("P.Data Offset(%u) too small\n", dccph_doff);
735*4882a593Smuzhiyun return 1;
736*4882a593Smuzhiyun }
737*4882a593Smuzhiyun /*
738*4882a593Smuzhiyun * If P.Data Offset is too large for packet, drop packet and return
739*4882a593Smuzhiyun */
740*4882a593Smuzhiyun if (!pskb_may_pull(skb, dccph_doff * sizeof(u32))) {
741*4882a593Smuzhiyun DCCP_WARN("P.Data Offset(%u) too large\n", dccph_doff);
742*4882a593Smuzhiyun return 1;
743*4882a593Smuzhiyun }
744*4882a593Smuzhiyun dh = dccp_hdr(skb);
745*4882a593Smuzhiyun /*
746*4882a593Smuzhiyun * If P.type is not Data, Ack, or DataAck and P.X == 0 (the packet
747*4882a593Smuzhiyun * has short sequence numbers), drop packet and return
748*4882a593Smuzhiyun */
749*4882a593Smuzhiyun if ((dh->dccph_type < DCCP_PKT_DATA ||
750*4882a593Smuzhiyun dh->dccph_type > DCCP_PKT_DATAACK) && dh->dccph_x == 0) {
751*4882a593Smuzhiyun DCCP_WARN("P.type (%s) not Data || [Data]Ack, while P.X == 0\n",
752*4882a593Smuzhiyun dccp_packet_name(dh->dccph_type));
753*4882a593Smuzhiyun return 1;
754*4882a593Smuzhiyun }
755*4882a593Smuzhiyun
756*4882a593Smuzhiyun /*
757*4882a593Smuzhiyun * If P.CsCov is too large for the packet size, drop packet and return.
758*4882a593Smuzhiyun * This must come _before_ checksumming (not as RFC 4340 suggests).
759*4882a593Smuzhiyun */
760*4882a593Smuzhiyun cscov = dccp_csum_coverage(skb);
761*4882a593Smuzhiyun if (cscov > skb->len) {
762*4882a593Smuzhiyun DCCP_WARN("P.CsCov %u exceeds packet length %d\n",
763*4882a593Smuzhiyun dh->dccph_cscov, skb->len);
764*4882a593Smuzhiyun return 1;
765*4882a593Smuzhiyun }
766*4882a593Smuzhiyun
767*4882a593Smuzhiyun /* If header checksum is incorrect, drop packet and return.
768*4882a593Smuzhiyun * (This step is completed in the AF-dependent functions.) */
769*4882a593Smuzhiyun skb->csum = skb_checksum(skb, 0, cscov, 0);
770*4882a593Smuzhiyun
771*4882a593Smuzhiyun return 0;
772*4882a593Smuzhiyun }
773*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(dccp_invalid_packet);
774*4882a593Smuzhiyun
775*4882a593Smuzhiyun /* this is called when real data arrives */
dccp_v4_rcv(struct sk_buff * skb)776*4882a593Smuzhiyun static int dccp_v4_rcv(struct sk_buff *skb)
777*4882a593Smuzhiyun {
778*4882a593Smuzhiyun const struct dccp_hdr *dh;
779*4882a593Smuzhiyun const struct iphdr *iph;
780*4882a593Smuzhiyun bool refcounted;
781*4882a593Smuzhiyun struct sock *sk;
782*4882a593Smuzhiyun int min_cov;
783*4882a593Smuzhiyun
784*4882a593Smuzhiyun /* Step 1: Check header basics */
785*4882a593Smuzhiyun
786*4882a593Smuzhiyun if (dccp_invalid_packet(skb))
787*4882a593Smuzhiyun goto discard_it;
788*4882a593Smuzhiyun
789*4882a593Smuzhiyun iph = ip_hdr(skb);
790*4882a593Smuzhiyun /* Step 1: If header checksum is incorrect, drop packet and return */
791*4882a593Smuzhiyun if (dccp_v4_csum_finish(skb, iph->saddr, iph->daddr)) {
792*4882a593Smuzhiyun DCCP_WARN("dropped packet with invalid checksum\n");
793*4882a593Smuzhiyun goto discard_it;
794*4882a593Smuzhiyun }
795*4882a593Smuzhiyun
796*4882a593Smuzhiyun dh = dccp_hdr(skb);
797*4882a593Smuzhiyun
798*4882a593Smuzhiyun DCCP_SKB_CB(skb)->dccpd_seq = dccp_hdr_seq(dh);
799*4882a593Smuzhiyun DCCP_SKB_CB(skb)->dccpd_type = dh->dccph_type;
800*4882a593Smuzhiyun
801*4882a593Smuzhiyun dccp_pr_debug("%8.8s src=%pI4@%-5d dst=%pI4@%-5d seq=%llu",
802*4882a593Smuzhiyun dccp_packet_name(dh->dccph_type),
803*4882a593Smuzhiyun &iph->saddr, ntohs(dh->dccph_sport),
804*4882a593Smuzhiyun &iph->daddr, ntohs(dh->dccph_dport),
805*4882a593Smuzhiyun (unsigned long long) DCCP_SKB_CB(skb)->dccpd_seq);
806*4882a593Smuzhiyun
807*4882a593Smuzhiyun if (dccp_packet_without_ack(skb)) {
808*4882a593Smuzhiyun DCCP_SKB_CB(skb)->dccpd_ack_seq = DCCP_PKT_WITHOUT_ACK_SEQ;
809*4882a593Smuzhiyun dccp_pr_debug_cat("\n");
810*4882a593Smuzhiyun } else {
811*4882a593Smuzhiyun DCCP_SKB_CB(skb)->dccpd_ack_seq = dccp_hdr_ack_seq(skb);
812*4882a593Smuzhiyun dccp_pr_debug_cat(", ack=%llu\n", (unsigned long long)
813*4882a593Smuzhiyun DCCP_SKB_CB(skb)->dccpd_ack_seq);
814*4882a593Smuzhiyun }
815*4882a593Smuzhiyun
816*4882a593Smuzhiyun lookup:
817*4882a593Smuzhiyun sk = __inet_lookup_skb(&dccp_hashinfo, skb, __dccp_hdr_len(dh),
818*4882a593Smuzhiyun dh->dccph_sport, dh->dccph_dport, 0, &refcounted);
819*4882a593Smuzhiyun if (!sk) {
820*4882a593Smuzhiyun dccp_pr_debug("failed to look up flow ID in table and "
821*4882a593Smuzhiyun "get corresponding socket\n");
822*4882a593Smuzhiyun goto no_dccp_socket;
823*4882a593Smuzhiyun }
824*4882a593Smuzhiyun
825*4882a593Smuzhiyun /*
826*4882a593Smuzhiyun * Step 2:
827*4882a593Smuzhiyun * ... or S.state == TIMEWAIT,
828*4882a593Smuzhiyun * Generate Reset(No Connection) unless P.type == Reset
829*4882a593Smuzhiyun * Drop packet and return
830*4882a593Smuzhiyun */
831*4882a593Smuzhiyun if (sk->sk_state == DCCP_TIME_WAIT) {
832*4882a593Smuzhiyun dccp_pr_debug("sk->sk_state == DCCP_TIME_WAIT: do_time_wait\n");
833*4882a593Smuzhiyun inet_twsk_put(inet_twsk(sk));
834*4882a593Smuzhiyun goto no_dccp_socket;
835*4882a593Smuzhiyun }
836*4882a593Smuzhiyun
837*4882a593Smuzhiyun if (sk->sk_state == DCCP_NEW_SYN_RECV) {
838*4882a593Smuzhiyun struct request_sock *req = inet_reqsk(sk);
839*4882a593Smuzhiyun struct sock *nsk;
840*4882a593Smuzhiyun
841*4882a593Smuzhiyun sk = req->rsk_listener;
842*4882a593Smuzhiyun if (unlikely(sk->sk_state != DCCP_LISTEN)) {
843*4882a593Smuzhiyun inet_csk_reqsk_queue_drop_and_put(sk, req);
844*4882a593Smuzhiyun goto lookup;
845*4882a593Smuzhiyun }
846*4882a593Smuzhiyun sock_hold(sk);
847*4882a593Smuzhiyun refcounted = true;
848*4882a593Smuzhiyun nsk = dccp_check_req(sk, skb, req);
849*4882a593Smuzhiyun if (!nsk) {
850*4882a593Smuzhiyun reqsk_put(req);
851*4882a593Smuzhiyun goto discard_and_relse;
852*4882a593Smuzhiyun }
853*4882a593Smuzhiyun if (nsk == sk) {
854*4882a593Smuzhiyun reqsk_put(req);
855*4882a593Smuzhiyun } else if (dccp_child_process(sk, nsk, skb)) {
856*4882a593Smuzhiyun dccp_v4_ctl_send_reset(sk, skb);
857*4882a593Smuzhiyun goto discard_and_relse;
858*4882a593Smuzhiyun } else {
859*4882a593Smuzhiyun sock_put(sk);
860*4882a593Smuzhiyun return 0;
861*4882a593Smuzhiyun }
862*4882a593Smuzhiyun }
863*4882a593Smuzhiyun /*
864*4882a593Smuzhiyun * RFC 4340, sec. 9.2.1: Minimum Checksum Coverage
865*4882a593Smuzhiyun * o if MinCsCov = 0, only packets with CsCov = 0 are accepted
866*4882a593Smuzhiyun * o if MinCsCov > 0, also accept packets with CsCov >= MinCsCov
867*4882a593Smuzhiyun */
868*4882a593Smuzhiyun min_cov = dccp_sk(sk)->dccps_pcrlen;
869*4882a593Smuzhiyun if (dh->dccph_cscov && (min_cov == 0 || dh->dccph_cscov < min_cov)) {
870*4882a593Smuzhiyun dccp_pr_debug("Packet CsCov %d does not satisfy MinCsCov %d\n",
871*4882a593Smuzhiyun dh->dccph_cscov, min_cov);
872*4882a593Smuzhiyun /* FIXME: "Such packets SHOULD be reported using Data Dropped
873*4882a593Smuzhiyun * options (Section 11.7) with Drop Code 0, Protocol
874*4882a593Smuzhiyun * Constraints." */
875*4882a593Smuzhiyun goto discard_and_relse;
876*4882a593Smuzhiyun }
877*4882a593Smuzhiyun
878*4882a593Smuzhiyun if (!xfrm4_policy_check(sk, XFRM_POLICY_IN, skb))
879*4882a593Smuzhiyun goto discard_and_relse;
880*4882a593Smuzhiyun nf_reset_ct(skb);
881*4882a593Smuzhiyun
882*4882a593Smuzhiyun return __sk_receive_skb(sk, skb, 1, dh->dccph_doff * 4, refcounted);
883*4882a593Smuzhiyun
884*4882a593Smuzhiyun no_dccp_socket:
885*4882a593Smuzhiyun if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb))
886*4882a593Smuzhiyun goto discard_it;
887*4882a593Smuzhiyun /*
888*4882a593Smuzhiyun * Step 2:
889*4882a593Smuzhiyun * If no socket ...
890*4882a593Smuzhiyun * Generate Reset(No Connection) unless P.type == Reset
891*4882a593Smuzhiyun * Drop packet and return
892*4882a593Smuzhiyun */
893*4882a593Smuzhiyun if (dh->dccph_type != DCCP_PKT_RESET) {
894*4882a593Smuzhiyun DCCP_SKB_CB(skb)->dccpd_reset_code =
895*4882a593Smuzhiyun DCCP_RESET_CODE_NO_CONNECTION;
896*4882a593Smuzhiyun dccp_v4_ctl_send_reset(sk, skb);
897*4882a593Smuzhiyun }
898*4882a593Smuzhiyun
899*4882a593Smuzhiyun discard_it:
900*4882a593Smuzhiyun kfree_skb(skb);
901*4882a593Smuzhiyun return 0;
902*4882a593Smuzhiyun
903*4882a593Smuzhiyun discard_and_relse:
904*4882a593Smuzhiyun if (refcounted)
905*4882a593Smuzhiyun sock_put(sk);
906*4882a593Smuzhiyun goto discard_it;
907*4882a593Smuzhiyun }
908*4882a593Smuzhiyun
909*4882a593Smuzhiyun static const struct inet_connection_sock_af_ops dccp_ipv4_af_ops = {
910*4882a593Smuzhiyun .queue_xmit = ip_queue_xmit,
911*4882a593Smuzhiyun .send_check = dccp_v4_send_check,
912*4882a593Smuzhiyun .rebuild_header = inet_sk_rebuild_header,
913*4882a593Smuzhiyun .conn_request = dccp_v4_conn_request,
914*4882a593Smuzhiyun .syn_recv_sock = dccp_v4_request_recv_sock,
915*4882a593Smuzhiyun .net_header_len = sizeof(struct iphdr),
916*4882a593Smuzhiyun .setsockopt = ip_setsockopt,
917*4882a593Smuzhiyun .getsockopt = ip_getsockopt,
918*4882a593Smuzhiyun .addr2sockaddr = inet_csk_addr2sockaddr,
919*4882a593Smuzhiyun .sockaddr_len = sizeof(struct sockaddr_in),
920*4882a593Smuzhiyun };
921*4882a593Smuzhiyun
dccp_v4_init_sock(struct sock * sk)922*4882a593Smuzhiyun static int dccp_v4_init_sock(struct sock *sk)
923*4882a593Smuzhiyun {
924*4882a593Smuzhiyun static __u8 dccp_v4_ctl_sock_initialized;
925*4882a593Smuzhiyun int err = dccp_init_sock(sk, dccp_v4_ctl_sock_initialized);
926*4882a593Smuzhiyun
927*4882a593Smuzhiyun if (err == 0) {
928*4882a593Smuzhiyun if (unlikely(!dccp_v4_ctl_sock_initialized))
929*4882a593Smuzhiyun dccp_v4_ctl_sock_initialized = 1;
930*4882a593Smuzhiyun inet_csk(sk)->icsk_af_ops = &dccp_ipv4_af_ops;
931*4882a593Smuzhiyun }
932*4882a593Smuzhiyun
933*4882a593Smuzhiyun return err;
934*4882a593Smuzhiyun }
935*4882a593Smuzhiyun
936*4882a593Smuzhiyun static struct timewait_sock_ops dccp_timewait_sock_ops = {
937*4882a593Smuzhiyun .twsk_obj_size = sizeof(struct inet_timewait_sock),
938*4882a593Smuzhiyun };
939*4882a593Smuzhiyun
940*4882a593Smuzhiyun static struct proto dccp_v4_prot = {
941*4882a593Smuzhiyun .name = "DCCP",
942*4882a593Smuzhiyun .owner = THIS_MODULE,
943*4882a593Smuzhiyun .close = dccp_close,
944*4882a593Smuzhiyun .connect = dccp_v4_connect,
945*4882a593Smuzhiyun .disconnect = dccp_disconnect,
946*4882a593Smuzhiyun .ioctl = dccp_ioctl,
947*4882a593Smuzhiyun .init = dccp_v4_init_sock,
948*4882a593Smuzhiyun .setsockopt = dccp_setsockopt,
949*4882a593Smuzhiyun .getsockopt = dccp_getsockopt,
950*4882a593Smuzhiyun .sendmsg = dccp_sendmsg,
951*4882a593Smuzhiyun .recvmsg = dccp_recvmsg,
952*4882a593Smuzhiyun .backlog_rcv = dccp_v4_do_rcv,
953*4882a593Smuzhiyun .hash = inet_hash,
954*4882a593Smuzhiyun .unhash = inet_unhash,
955*4882a593Smuzhiyun .accept = inet_csk_accept,
956*4882a593Smuzhiyun .get_port = inet_csk_get_port,
957*4882a593Smuzhiyun .shutdown = dccp_shutdown,
958*4882a593Smuzhiyun .destroy = dccp_destroy_sock,
959*4882a593Smuzhiyun .orphan_count = &dccp_orphan_count,
960*4882a593Smuzhiyun .max_header = MAX_DCCP_HEADER,
961*4882a593Smuzhiyun .obj_size = sizeof(struct dccp_sock),
962*4882a593Smuzhiyun .slab_flags = SLAB_TYPESAFE_BY_RCU,
963*4882a593Smuzhiyun .rsk_prot = &dccp_request_sock_ops,
964*4882a593Smuzhiyun .twsk_prot = &dccp_timewait_sock_ops,
965*4882a593Smuzhiyun .h.hashinfo = &dccp_hashinfo,
966*4882a593Smuzhiyun };
967*4882a593Smuzhiyun
968*4882a593Smuzhiyun static const struct net_protocol dccp_v4_protocol = {
969*4882a593Smuzhiyun .handler = dccp_v4_rcv,
970*4882a593Smuzhiyun .err_handler = dccp_v4_err,
971*4882a593Smuzhiyun .no_policy = 1,
972*4882a593Smuzhiyun .netns_ok = 1,
973*4882a593Smuzhiyun .icmp_strict_tag_validation = 1,
974*4882a593Smuzhiyun };
975*4882a593Smuzhiyun
976*4882a593Smuzhiyun static const struct proto_ops inet_dccp_ops = {
977*4882a593Smuzhiyun .family = PF_INET,
978*4882a593Smuzhiyun .owner = THIS_MODULE,
979*4882a593Smuzhiyun .release = inet_release,
980*4882a593Smuzhiyun .bind = inet_bind,
981*4882a593Smuzhiyun .connect = inet_stream_connect,
982*4882a593Smuzhiyun .socketpair = sock_no_socketpair,
983*4882a593Smuzhiyun .accept = inet_accept,
984*4882a593Smuzhiyun .getname = inet_getname,
985*4882a593Smuzhiyun /* FIXME: work on tcp_poll to rename it to inet_csk_poll */
986*4882a593Smuzhiyun .poll = dccp_poll,
987*4882a593Smuzhiyun .ioctl = inet_ioctl,
988*4882a593Smuzhiyun .gettstamp = sock_gettstamp,
989*4882a593Smuzhiyun /* FIXME: work on inet_listen to rename it to sock_common_listen */
990*4882a593Smuzhiyun .listen = inet_dccp_listen,
991*4882a593Smuzhiyun .shutdown = inet_shutdown,
992*4882a593Smuzhiyun .setsockopt = sock_common_setsockopt,
993*4882a593Smuzhiyun .getsockopt = sock_common_getsockopt,
994*4882a593Smuzhiyun .sendmsg = inet_sendmsg,
995*4882a593Smuzhiyun .recvmsg = sock_common_recvmsg,
996*4882a593Smuzhiyun .mmap = sock_no_mmap,
997*4882a593Smuzhiyun .sendpage = sock_no_sendpage,
998*4882a593Smuzhiyun };
999*4882a593Smuzhiyun
1000*4882a593Smuzhiyun static struct inet_protosw dccp_v4_protosw = {
1001*4882a593Smuzhiyun .type = SOCK_DCCP,
1002*4882a593Smuzhiyun .protocol = IPPROTO_DCCP,
1003*4882a593Smuzhiyun .prot = &dccp_v4_prot,
1004*4882a593Smuzhiyun .ops = &inet_dccp_ops,
1005*4882a593Smuzhiyun .flags = INET_PROTOSW_ICSK,
1006*4882a593Smuzhiyun };
1007*4882a593Smuzhiyun
dccp_v4_init_net(struct net * net)1008*4882a593Smuzhiyun static int __net_init dccp_v4_init_net(struct net *net)
1009*4882a593Smuzhiyun {
1010*4882a593Smuzhiyun if (dccp_hashinfo.bhash == NULL)
1011*4882a593Smuzhiyun return -ESOCKTNOSUPPORT;
1012*4882a593Smuzhiyun
1013*4882a593Smuzhiyun return inet_ctl_sock_create(&net->dccp.v4_ctl_sk, PF_INET,
1014*4882a593Smuzhiyun SOCK_DCCP, IPPROTO_DCCP, net);
1015*4882a593Smuzhiyun }
1016*4882a593Smuzhiyun
dccp_v4_exit_net(struct net * net)1017*4882a593Smuzhiyun static void __net_exit dccp_v4_exit_net(struct net *net)
1018*4882a593Smuzhiyun {
1019*4882a593Smuzhiyun inet_ctl_sock_destroy(net->dccp.v4_ctl_sk);
1020*4882a593Smuzhiyun }
1021*4882a593Smuzhiyun
dccp_v4_exit_batch(struct list_head * net_exit_list)1022*4882a593Smuzhiyun static void __net_exit dccp_v4_exit_batch(struct list_head *net_exit_list)
1023*4882a593Smuzhiyun {
1024*4882a593Smuzhiyun inet_twsk_purge(&dccp_hashinfo, AF_INET);
1025*4882a593Smuzhiyun }
1026*4882a593Smuzhiyun
1027*4882a593Smuzhiyun static struct pernet_operations dccp_v4_ops = {
1028*4882a593Smuzhiyun .init = dccp_v4_init_net,
1029*4882a593Smuzhiyun .exit = dccp_v4_exit_net,
1030*4882a593Smuzhiyun .exit_batch = dccp_v4_exit_batch,
1031*4882a593Smuzhiyun };
1032*4882a593Smuzhiyun
dccp_v4_init(void)1033*4882a593Smuzhiyun static int __init dccp_v4_init(void)
1034*4882a593Smuzhiyun {
1035*4882a593Smuzhiyun int err = proto_register(&dccp_v4_prot, 1);
1036*4882a593Smuzhiyun
1037*4882a593Smuzhiyun if (err)
1038*4882a593Smuzhiyun goto out;
1039*4882a593Smuzhiyun
1040*4882a593Smuzhiyun inet_register_protosw(&dccp_v4_protosw);
1041*4882a593Smuzhiyun
1042*4882a593Smuzhiyun err = register_pernet_subsys(&dccp_v4_ops);
1043*4882a593Smuzhiyun if (err)
1044*4882a593Smuzhiyun goto out_destroy_ctl_sock;
1045*4882a593Smuzhiyun
1046*4882a593Smuzhiyun err = inet_add_protocol(&dccp_v4_protocol, IPPROTO_DCCP);
1047*4882a593Smuzhiyun if (err)
1048*4882a593Smuzhiyun goto out_proto_unregister;
1049*4882a593Smuzhiyun
1050*4882a593Smuzhiyun out:
1051*4882a593Smuzhiyun return err;
1052*4882a593Smuzhiyun out_proto_unregister:
1053*4882a593Smuzhiyun unregister_pernet_subsys(&dccp_v4_ops);
1054*4882a593Smuzhiyun out_destroy_ctl_sock:
1055*4882a593Smuzhiyun inet_unregister_protosw(&dccp_v4_protosw);
1056*4882a593Smuzhiyun proto_unregister(&dccp_v4_prot);
1057*4882a593Smuzhiyun goto out;
1058*4882a593Smuzhiyun }
1059*4882a593Smuzhiyun
dccp_v4_exit(void)1060*4882a593Smuzhiyun static void __exit dccp_v4_exit(void)
1061*4882a593Smuzhiyun {
1062*4882a593Smuzhiyun inet_del_protocol(&dccp_v4_protocol, IPPROTO_DCCP);
1063*4882a593Smuzhiyun unregister_pernet_subsys(&dccp_v4_ops);
1064*4882a593Smuzhiyun inet_unregister_protosw(&dccp_v4_protosw);
1065*4882a593Smuzhiyun proto_unregister(&dccp_v4_prot);
1066*4882a593Smuzhiyun }
1067*4882a593Smuzhiyun
1068*4882a593Smuzhiyun module_init(dccp_v4_init);
1069*4882a593Smuzhiyun module_exit(dccp_v4_exit);
1070*4882a593Smuzhiyun
1071*4882a593Smuzhiyun /*
1072*4882a593Smuzhiyun * __stringify doesn't likes enums, so use SOCK_DCCP (6) and IPPROTO_DCCP (33)
1073*4882a593Smuzhiyun * values directly, Also cover the case where the protocol is not specified,
1074*4882a593Smuzhiyun * i.e. net-pf-PF_INET-proto-0-type-SOCK_DCCP
1075*4882a593Smuzhiyun */
1076*4882a593Smuzhiyun MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_INET, 33, 6);
1077*4882a593Smuzhiyun MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_INET, 0, 6);
1078*4882a593Smuzhiyun MODULE_LICENSE("GPL");
1079*4882a593Smuzhiyun MODULE_AUTHOR("Arnaldo Carvalho de Melo <acme@mandriva.com>");
1080*4882a593Smuzhiyun MODULE_DESCRIPTION("DCCP - Datagram Congestion Controlled Protocol");
1081