Merge tag 'nfs-for-5.20-1' of git://git.linux-nfs.org/projects/trondmy/linux-nfs
[platform/kernel/linux-rpi.git] / include / net / udplite.h
1 /* SPDX-License-Identifier: GPL-2.0 */
2 /*
3  *      Definitions for the UDP-Lite (RFC 3828) code.
4  */
5 #ifndef _UDPLITE_H
6 #define _UDPLITE_H
7
8 #include <net/ip6_checksum.h>
9 #include <net/udp.h>
10
11 /* UDP-Lite socket options */
12 #define UDPLITE_SEND_CSCOV   10 /* sender partial coverage (as sent)      */
13 #define UDPLITE_RECV_CSCOV   11 /* receiver partial coverage (threshold ) */
14
15 extern struct proto             udplite_prot;
16 extern struct udp_table         udplite_table;
17
18 /*
19  *      Checksum computation is all in software, hence simpler getfrag.
20  */
21 static __inline__ int udplite_getfrag(void *from, char *to, int  offset,
22                                       int len, int odd, struct sk_buff *skb)
23 {
24         struct msghdr *msg = from;
25         return copy_from_iter_full(to, len, &msg->msg_iter) ? 0 : -EFAULT;
26 }
27
28 /* Designate sk as UDP-Lite socket */
29 static inline int udplite_sk_init(struct sock *sk)
30 {
31         udp_init_sock(sk);
32         udp_sk(sk)->pcflag = UDPLITE_BIT;
33         return 0;
34 }
35
36 /*
37  *      Checksumming routines
38  */
39 static inline int udplite_checksum_init(struct sk_buff *skb, struct udphdr *uh)
40 {
41         u16 cscov;
42
43         /* In UDPv4 a zero checksum means that the transmitter generated no
44          * checksum. UDP-Lite (like IPv6) mandates checksums, hence packets
45          * with a zero checksum field are illegal.                            */
46         if (uh->check == 0) {
47                 net_dbg_ratelimited("UDPLite: zeroed checksum field\n");
48                 return 1;
49         }
50
51         cscov = ntohs(uh->len);
52
53         if (cscov == 0)          /* Indicates that full coverage is required. */
54                 ;
55         else if (cscov < 8  || cscov > skb->len) {
56                 /*
57                  * Coverage length violates RFC 3828: log and discard silently.
58                  */
59                 net_dbg_ratelimited("UDPLite: bad csum coverage %d/%d\n",
60                                     cscov, skb->len);
61                 return 1;
62
63         } else if (cscov < skb->len) {
64                 UDP_SKB_CB(skb)->partial_cov = 1;
65                 UDP_SKB_CB(skb)->cscov = cscov;
66                 if (skb->ip_summed == CHECKSUM_COMPLETE)
67                         skb->ip_summed = CHECKSUM_NONE;
68                 skb->csum_valid = 0;
69         }
70
71         return 0;
72 }
73
74 /* Fast-path computation of checksum. Socket may not be locked. */
75 static inline __wsum udplite_csum(struct sk_buff *skb)
76 {
77         const struct udp_sock *up = udp_sk(skb->sk);
78         const int off = skb_transport_offset(skb);
79         int len = skb->len - off;
80
81         if ((up->pcflag & UDPLITE_SEND_CC) && up->pcslen < len) {
82                 if (0 < up->pcslen)
83                         len = up->pcslen;
84                 udp_hdr(skb)->len = htons(up->pcslen);
85         }
86         skb->ip_summed = CHECKSUM_NONE;     /* no HW support for checksumming */
87
88         return skb_checksum(skb, off, len, 0);
89 }
90
91 void udplite4_register(void);
92 int udplite_get_port(struct sock *sk, unsigned short snum,
93                      int (*scmp)(const struct sock *, const struct sock *));
94 #endif  /* _UDPLITE_H */