Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0 */
0002 /*
0003  *  Definitions for the UDP-Lite (RFC 3828) code.
0004  */
0005 #ifndef _UDPLITE_H
0006 #define _UDPLITE_H
0007 
0008 #include <net/ip6_checksum.h>
0009 #include <net/udp.h>
0010 
0011 /* UDP-Lite socket options */
0012 #define UDPLITE_SEND_CSCOV   10 /* sender partial coverage (as sent)      */
0013 #define UDPLITE_RECV_CSCOV   11 /* receiver partial coverage (threshold ) */
0014 
0015 extern struct proto         udplite_prot;
0016 extern struct udp_table     udplite_table;
0017 
0018 /*
0019  *  Checksum computation is all in software, hence simpler getfrag.
0020  */
0021 static __inline__ int udplite_getfrag(void *from, char *to, int  offset,
0022                       int len, int odd, struct sk_buff *skb)
0023 {
0024     struct msghdr *msg = from;
0025     return copy_from_iter_full(to, len, &msg->msg_iter) ? 0 : -EFAULT;
0026 }
0027 
0028 /* Designate sk as UDP-Lite socket */
0029 static inline int udplite_sk_init(struct sock *sk)
0030 {
0031     udp_init_sock(sk);
0032     udp_sk(sk)->pcflag = UDPLITE_BIT;
0033     return 0;
0034 }
0035 
0036 /*
0037  *  Checksumming routines
0038  */
0039 static inline int udplite_checksum_init(struct sk_buff *skb, struct udphdr *uh)
0040 {
0041     u16 cscov;
0042 
0043         /* In UDPv4 a zero checksum means that the transmitter generated no
0044          * checksum. UDP-Lite (like IPv6) mandates checksums, hence packets
0045          * with a zero checksum field are illegal.                            */
0046     if (uh->check == 0) {
0047         net_dbg_ratelimited("UDPLite: zeroed checksum field\n");
0048         return 1;
0049     }
0050 
0051     cscov = ntohs(uh->len);
0052 
0053     if (cscov == 0)      /* Indicates that full coverage is required. */
0054         ;
0055     else if (cscov < 8  || cscov > skb->len) {
0056         /*
0057          * Coverage length violates RFC 3828: log and discard silently.
0058          */
0059         net_dbg_ratelimited("UDPLite: bad csum coverage %d/%d\n",
0060                     cscov, skb->len);
0061         return 1;
0062 
0063     } else if (cscov < skb->len) {
0064             UDP_SKB_CB(skb)->partial_cov = 1;
0065         UDP_SKB_CB(skb)->cscov = cscov;
0066         if (skb->ip_summed == CHECKSUM_COMPLETE)
0067             skb->ip_summed = CHECKSUM_NONE;
0068         skb->csum_valid = 0;
0069         }
0070 
0071     return 0;
0072 }
0073 
0074 /* Fast-path computation of checksum. Socket may not be locked. */
0075 static inline __wsum udplite_csum(struct sk_buff *skb)
0076 {
0077     const struct udp_sock *up = udp_sk(skb->sk);
0078     const int off = skb_transport_offset(skb);
0079     int len = skb->len - off;
0080 
0081     if ((up->pcflag & UDPLITE_SEND_CC) && up->pcslen < len) {
0082         if (0 < up->pcslen)
0083             len = up->pcslen;
0084         udp_hdr(skb)->len = htons(up->pcslen);
0085     }
0086     skb->ip_summed = CHECKSUM_NONE;     /* no HW support for checksumming */
0087 
0088     return skb_checksum(skb, off, len, 0);
0089 }
0090 
0091 void udplite4_register(void);
0092 int udplite_get_port(struct sock *sk, unsigned short snum,
0093              int (*scmp)(const struct sock *, const struct sock *));
0094 #endif  /* _UDPLITE_H */