.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* |
---|
2 | 3 | * net/dccp/ipv4.c |
---|
3 | 4 | * |
---|
4 | 5 | * An implementation of the DCCP protocol |
---|
5 | 6 | * Arnaldo Carvalho de Melo <acme@conectiva.com.br> |
---|
6 | | - * |
---|
7 | | - * This program is free software; you can redistribute it and/or |
---|
8 | | - * modify it under the terms of the GNU General Public License |
---|
9 | | - * as published by the Free Software Foundation; either version |
---|
10 | | - * 2 of the License, or (at your option) any later version. |
---|
11 | 7 | */ |
---|
12 | 8 | |
---|
13 | 9 | #include <linux/dccp.h> |
---|
.. | .. |
---|
134 | 130 | * This unhashes the socket and releases the local port, if necessary. |
---|
135 | 131 | */ |
---|
136 | 132 | dccp_set_state(sk, DCCP_CLOSED); |
---|
| 133 | + if (!(sk->sk_userlocks & SOCK_BINDADDR_LOCK)) |
---|
| 134 | + inet_reset_saddr(sk); |
---|
137 | 135 | ip_rt_put(rt); |
---|
138 | 136 | sk->sk_route_caps = 0; |
---|
139 | 137 | inet->inet_dport = 0; |
---|
.. | .. |
---|
231 | 229 | * check at all. A more general error queue to queue errors for later handling |
---|
232 | 230 | * is probably better. |
---|
233 | 231 | */ |
---|
234 | | -static void dccp_v4_err(struct sk_buff *skb, u32 info) |
---|
| 232 | +static int dccp_v4_err(struct sk_buff *skb, u32 info) |
---|
235 | 233 | { |
---|
236 | 234 | const struct iphdr *iph = (struct iphdr *)skb->data; |
---|
237 | 235 | const u8 offset = iph->ihl << 2; |
---|
.. | .. |
---|
245 | 243 | int err; |
---|
246 | 244 | struct net *net = dev_net(skb->dev); |
---|
247 | 245 | |
---|
248 | | - /* Only need dccph_dport & dccph_sport which are the first |
---|
249 | | - * 4 bytes in dccp header. |
---|
250 | | - * Our caller (icmp_socket_deliver()) already pulled 8 bytes for us. |
---|
251 | | - */ |
---|
252 | | - BUILD_BUG_ON(offsetofend(struct dccp_hdr, dccph_sport) > 8); |
---|
253 | | - BUILD_BUG_ON(offsetofend(struct dccp_hdr, dccph_dport) > 8); |
---|
| 246 | + if (!pskb_may_pull(skb, offset + sizeof(*dh))) |
---|
| 247 | + return -EINVAL; |
---|
| 248 | + dh = (struct dccp_hdr *)(skb->data + offset); |
---|
| 249 | + if (!pskb_may_pull(skb, offset + __dccp_basic_hdr_len(dh))) |
---|
| 250 | + return -EINVAL; |
---|
| 251 | + iph = (struct iphdr *)skb->data; |
---|
254 | 252 | dh = (struct dccp_hdr *)(skb->data + offset); |
---|
255 | 253 | |
---|
256 | 254 | sk = __inet_lookup_established(net, &dccp_hashinfo, |
---|
.. | .. |
---|
259 | 257 | inet_iif(skb), 0); |
---|
260 | 258 | if (!sk) { |
---|
261 | 259 | __ICMP_INC_STATS(net, ICMP_MIB_INERRORS); |
---|
262 | | - return; |
---|
| 260 | + return -ENOENT; |
---|
263 | 261 | } |
---|
264 | 262 | |
---|
265 | 263 | if (sk->sk_state == DCCP_TIME_WAIT) { |
---|
266 | 264 | inet_twsk_put(inet_twsk(sk)); |
---|
267 | | - return; |
---|
| 265 | + return 0; |
---|
268 | 266 | } |
---|
269 | 267 | seq = dccp_hdr_seq(dh); |
---|
270 | | - if (sk->sk_state == DCCP_NEW_SYN_RECV) |
---|
271 | | - return dccp_req_err(sk, seq); |
---|
| 268 | + if (sk->sk_state == DCCP_NEW_SYN_RECV) { |
---|
| 269 | + dccp_req_err(sk, seq); |
---|
| 270 | + return 0; |
---|
| 271 | + } |
---|
272 | 272 | |
---|
273 | 273 | bh_lock_sock(sk); |
---|
274 | 274 | /* If too many ICMPs get dropped on busy |
---|
.. | .. |
---|
357 | 357 | out: |
---|
358 | 358 | bh_unlock_sock(sk); |
---|
359 | 359 | sock_put(sk); |
---|
| 360 | + return 0; |
---|
360 | 361 | } |
---|
361 | 362 | |
---|
362 | 363 | static inline __sum16 dccp_v4_csum_finish(struct sk_buff *skb, |
---|
.. | .. |
---|
428 | 429 | |
---|
429 | 430 | if (__inet_inherit_port(sk, newsk) < 0) |
---|
430 | 431 | goto put_and_exit; |
---|
431 | | - *own_req = inet_ehash_nolisten(newsk, req_to_sk(req_unhash)); |
---|
| 432 | + *own_req = inet_ehash_nolisten(newsk, req_to_sk(req_unhash), NULL); |
---|
432 | 433 | if (*own_req) |
---|
433 | 434 | ireq->ireq_opt = NULL; |
---|
434 | 435 | else |
---|
.. | .. |
---|
465 | 466 | .fl4_dport = dccp_hdr(skb)->dccph_sport, |
---|
466 | 467 | }; |
---|
467 | 468 | |
---|
468 | | - security_skb_classify_flow(skb, flowi4_to_flowi(&fl4)); |
---|
| 469 | + security_skb_classify_flow(skb, flowi4_to_flowi_common(&fl4)); |
---|
469 | 470 | rt = ip_route_output_flow(net, &fl4, sk); |
---|
470 | 471 | if (IS_ERR(rt)) { |
---|
471 | 472 | IP_INC_STATS(net, IPSTATS_MIB_OUTNOROUTES); |
---|
.. | .. |
---|
496 | 497 | rcu_read_lock(); |
---|
497 | 498 | err = ip_build_and_send_pkt(skb, sk, ireq->ir_loc_addr, |
---|
498 | 499 | ireq->ir_rmt_addr, |
---|
499 | | - rcu_dereference(ireq->ireq_opt)); |
---|
| 500 | + rcu_dereference(ireq->ireq_opt), |
---|
| 501 | + inet_sk(sk)->tos); |
---|
500 | 502 | rcu_read_unlock(); |
---|
501 | 503 | err = net_xmit_eval(err); |
---|
502 | 504 | } |
---|
.. | .. |
---|
538 | 540 | local_bh_disable(); |
---|
539 | 541 | bh_lock_sock(ctl_sk); |
---|
540 | 542 | err = ip_build_and_send_pkt(skb, ctl_sk, |
---|
541 | | - rxiph->daddr, rxiph->saddr, NULL); |
---|
| 543 | + rxiph->daddr, rxiph->saddr, NULL, |
---|
| 544 | + inet_sk(ctl_sk)->tos); |
---|
542 | 545 | bh_unlock_sock(ctl_sk); |
---|
543 | 546 | |
---|
544 | 547 | if (net_xmit_eval(err) == 0) { |
---|
.. | .. |
---|
695 | 698 | |
---|
696 | 699 | /** |
---|
697 | 700 | * dccp_invalid_packet - check for malformed packets |
---|
| 701 | + * @skb: Packet to validate |
---|
| 702 | + * |
---|
698 | 703 | * Implements RFC 4340, 8.5: Step 1: Check header basics |
---|
699 | 704 | * Packets that fail these checks are ignored and do not receive Resets. |
---|
700 | 705 | */ |
---|
.. | .. |
---|
730 | 735 | return 1; |
---|
731 | 736 | } |
---|
732 | 737 | /* |
---|
733 | | - * If P.Data Offset is too too large for packet, drop packet and return |
---|
| 738 | + * If P.Data Offset is too large for packet, drop packet and return |
---|
734 | 739 | */ |
---|
735 | 740 | if (!pskb_may_pull(skb, dccph_doff * sizeof(u32))) { |
---|
736 | 741 | DCCP_WARN("P.Data Offset(%u) too large\n", dccph_doff); |
---|
.. | .. |
---|
872 | 877 | |
---|
873 | 878 | if (!xfrm4_policy_check(sk, XFRM_POLICY_IN, skb)) |
---|
874 | 879 | goto discard_and_relse; |
---|
875 | | - nf_reset(skb); |
---|
| 880 | + nf_reset_ct(skb); |
---|
876 | 881 | |
---|
877 | 882 | return __sk_receive_skb(sk, skb, 1, dh->dccph_doff * 4, refcounted); |
---|
878 | 883 | |
---|
.. | .. |
---|
912 | 917 | .getsockopt = ip_getsockopt, |
---|
913 | 918 | .addr2sockaddr = inet_csk_addr2sockaddr, |
---|
914 | 919 | .sockaddr_len = sizeof(struct sockaddr_in), |
---|
915 | | -#ifdef CONFIG_COMPAT |
---|
916 | | - .compat_setsockopt = compat_ip_setsockopt, |
---|
917 | | - .compat_getsockopt = compat_ip_getsockopt, |
---|
918 | | -#endif |
---|
919 | 920 | }; |
---|
920 | 921 | |
---|
921 | 922 | static int dccp_v4_init_sock(struct sock *sk) |
---|
.. | .. |
---|
962 | 963 | .rsk_prot = &dccp_request_sock_ops, |
---|
963 | 964 | .twsk_prot = &dccp_timewait_sock_ops, |
---|
964 | 965 | .h.hashinfo = &dccp_hashinfo, |
---|
965 | | -#ifdef CONFIG_COMPAT |
---|
966 | | - .compat_setsockopt = compat_dccp_setsockopt, |
---|
967 | | - .compat_getsockopt = compat_dccp_getsockopt, |
---|
968 | | -#endif |
---|
969 | 966 | }; |
---|
970 | 967 | |
---|
971 | 968 | static const struct net_protocol dccp_v4_protocol = { |
---|
.. | .. |
---|
988 | 985 | /* FIXME: work on tcp_poll to rename it to inet_csk_poll */ |
---|
989 | 986 | .poll = dccp_poll, |
---|
990 | 987 | .ioctl = inet_ioctl, |
---|
| 988 | + .gettstamp = sock_gettstamp, |
---|
991 | 989 | /* FIXME: work on inet_listen to rename it to sock_common_listen */ |
---|
992 | 990 | .listen = inet_dccp_listen, |
---|
993 | 991 | .shutdown = inet_shutdown, |
---|
.. | .. |
---|
997 | 995 | .recvmsg = sock_common_recvmsg, |
---|
998 | 996 | .mmap = sock_no_mmap, |
---|
999 | 997 | .sendpage = sock_no_sendpage, |
---|
1000 | | -#ifdef CONFIG_COMPAT |
---|
1001 | | - .compat_setsockopt = compat_sock_common_setsockopt, |
---|
1002 | | - .compat_getsockopt = compat_sock_common_getsockopt, |
---|
1003 | | -#endif |
---|
1004 | 998 | }; |
---|
1005 | 999 | |
---|
1006 | 1000 | static struct inet_protosw dccp_v4_protosw = { |
---|