Branch data Line data Source code
1 : : /* SPDX-License-Identifier: GPL-2.0-or-later */
2 : : /*
3 : : * INET An implementation of the TCP/IP protocol suite for the LINUX
4 : : * operating system. INET is implemented using the BSD Socket
5 : : * interface as the means of communication with the user level.
6 : : *
7 : : * Checksumming functions for IPv6
8 : : *
9 : : * Authors: Jorge Cwik, <jorge@laser.satlink.net>
10 : : * Arnt Gulbrandsen, <agulbra@nvg.unit.no>
11 : : * Borrows very liberally from tcp.c and ip.c, see those
12 : : * files for more names.
13 : : */
14 : :
15 : : /*
16 : : * Fixes:
17 : : *
18 : : * Ralf Baechle : generic ipv6 checksum
19 : : * <ralf@waldorf-gmbh.de>
20 : : */
21 : :
22 : : #ifndef _CHECKSUM_IPV6_H
23 : : #define _CHECKSUM_IPV6_H
24 : :
25 : : #include <asm/types.h>
26 : : #include <asm/byteorder.h>
27 : : #include <net/ip.h>
28 : : #include <asm/checksum.h>
29 : : #include <linux/in6.h>
30 : : #include <linux/tcp.h>
31 : : #include <linux/ipv6.h>
32 : :
33 : : #ifndef _HAVE_ARCH_IPV6_CSUM
34 : : __sum16 csum_ipv6_magic(const struct in6_addr *saddr,
35 : : const struct in6_addr *daddr,
36 : : __u32 len, __u8 proto, __wsum csum);
37 : : #endif
38 : :
39 : 462 : static inline __wsum ip6_compute_pseudo(struct sk_buff *skb, int proto)
40 : : {
41 : 1386 : return ~csum_unfold(csum_ipv6_magic(&ipv6_hdr(skb)->saddr,
42 : 462 : &ipv6_hdr(skb)->daddr,
43 : : skb->len, proto, 0));
44 : : }
45 : :
46 : 0 : static inline __wsum ip6_gro_compute_pseudo(struct sk_buff *skb, int proto)
47 : : {
48 : : const struct ipv6hdr *iph = skb_gro_network_header(skb);
49 : :
50 : 0 : return ~csum_unfold(csum_ipv6_magic(&iph->saddr, &iph->daddr,
51 : : skb_gro_len(skb), proto, 0));
52 : : }
53 : :
54 : : static __inline__ __sum16 tcp_v6_check(int len,
55 : : const struct in6_addr *saddr,
56 : : const struct in6_addr *daddr,
57 : : __wsum base)
58 : : {
59 : : return csum_ipv6_magic(saddr, daddr, len, IPPROTO_TCP, base);
60 : : }
61 : :
62 : 0 : static inline void __tcp_v6_send_check(struct sk_buff *skb,
63 : : const struct in6_addr *saddr,
64 : : const struct in6_addr *daddr)
65 : : {
66 : : struct tcphdr *th = tcp_hdr(skb);
67 : :
68 [ # # ]: 0 : if (skb->ip_summed == CHECKSUM_PARTIAL) {
69 : 0 : th->check = ~tcp_v6_check(skb->len, saddr, daddr, 0);
70 : 0 : skb->csum_start = skb_transport_header(skb) - skb->head;
71 : 0 : skb->csum_offset = offsetof(struct tcphdr, check);
72 : : } else {
73 : 0 : th->check = tcp_v6_check(skb->len, saddr, daddr,
74 : 0 : csum_partial(th, th->doff << 2,
75 : : skb->csum));
76 : : }
77 : 0 : }
78 : :
79 : : #if IS_ENABLED(CONFIG_IPV6)
80 : 0 : static inline void tcp_v6_send_check(struct sock *sk, struct sk_buff *skb)
81 : : {
82 : : struct ipv6_pinfo *np = inet6_sk(sk);
83 : :
84 : 0 : __tcp_v6_send_check(skb, &np->saddr, &sk->sk_v6_daddr);
85 : 0 : }
86 : : #endif
87 : :
88 : : static inline __sum16 udp_v6_check(int len,
89 : : const struct in6_addr *saddr,
90 : : const struct in6_addr *daddr,
91 : : __wsum base)
92 : : {
93 : 0 : return csum_ipv6_magic(saddr, daddr, len, IPPROTO_UDP, base);
94 : : }
95 : :
96 : : void udp6_set_csum(bool nocheck, struct sk_buff *skb,
97 : : const struct in6_addr *saddr,
98 : : const struct in6_addr *daddr, int len);
99 : :
100 : : int udp6_csum_init(struct sk_buff *skb, struct udphdr *uh, int proto);
101 : : #endif
|