Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0-or-later */
0002 /*
0003  * INET     An implementation of the TCP/IP protocol suite for the LINUX
0004  *      operating system.  INET is implemented using the  BSD Socket
0005  *      interface as the means of communication with the user level.
0006  *
0007  *      Checksumming functions for IPv6
0008  *
0009  * Authors: Jorge Cwik, <jorge@laser.satlink.net>
0010  *      Arnt Gulbrandsen, <agulbra@nvg.unit.no>
0011  *      Borrows very liberally from tcp.c and ip.c, see those
0012  *      files for more names.
0013  */
0014 
0015 /*
0016  *  Fixes:
0017  *
0018  *  Ralf Baechle            :   generic ipv6 checksum
0019  *  <ralf@waldorf-gmbh.de>
0020  */
0021 
0022 #ifndef _CHECKSUM_IPV6_H
0023 #define _CHECKSUM_IPV6_H
0024 
0025 #include <asm/types.h>
0026 #include <asm/byteorder.h>
0027 #include <net/ip.h>
0028 #include <asm/checksum.h>
0029 #include <linux/in6.h>
0030 #include <linux/tcp.h>
0031 #include <linux/ipv6.h>
0032 
0033 #ifndef _HAVE_ARCH_IPV6_CSUM
0034 __sum16 csum_ipv6_magic(const struct in6_addr *saddr,
0035             const struct in6_addr *daddr,
0036             __u32 len, __u8 proto, __wsum csum);
0037 #endif
0038 
0039 static inline __wsum ip6_compute_pseudo(struct sk_buff *skb, int proto)
0040 {
0041     return ~csum_unfold(csum_ipv6_magic(&ipv6_hdr(skb)->saddr,
0042                         &ipv6_hdr(skb)->daddr,
0043                         skb->len, proto, 0));
0044 }
0045 
0046 static __inline__ __sum16 tcp_v6_check(int len,
0047                    const struct in6_addr *saddr,
0048                    const struct in6_addr *daddr,
0049                    __wsum base)
0050 {
0051     return csum_ipv6_magic(saddr, daddr, len, IPPROTO_TCP, base);
0052 }
0053 
0054 static inline void __tcp_v6_send_check(struct sk_buff *skb,
0055                        const struct in6_addr *saddr,
0056                        const struct in6_addr *daddr)
0057 {
0058     struct tcphdr *th = tcp_hdr(skb);
0059 
0060     th->check = ~tcp_v6_check(skb->len, saddr, daddr, 0);
0061     skb->csum_start = skb_transport_header(skb) - skb->head;
0062     skb->csum_offset = offsetof(struct tcphdr, check);
0063 }
0064 
0065 static inline void tcp_v6_gso_csum_prep(struct sk_buff *skb)
0066 {
0067     struct ipv6hdr *ipv6h = ipv6_hdr(skb);
0068     struct tcphdr *th = tcp_hdr(skb);
0069 
0070     ipv6h->payload_len = 0;
0071     th->check = ~tcp_v6_check(0, &ipv6h->saddr, &ipv6h->daddr, 0);
0072 }
0073 
0074 static inline __sum16 udp_v6_check(int len,
0075                    const struct in6_addr *saddr,
0076                    const struct in6_addr *daddr,
0077                    __wsum base)
0078 {
0079     return csum_ipv6_magic(saddr, daddr, len, IPPROTO_UDP, base);
0080 }
0081 
0082 void udp6_set_csum(bool nocheck, struct sk_buff *skb,
0083            const struct in6_addr *saddr,
0084            const struct in6_addr *daddr, int len);
0085 
0086 int udp6_csum_init(struct sk_buff *skb, struct udphdr *uh, int proto);
0087 #endif