LCOV - code coverage report
Current view: top level - net/netfilter - utils.c (source / functions) Hit Total Coverage
Test: landlock.info Lines: 0 112 0.0 %
Date: 2021-04-22 12:43:58 Functions: 0 9 0.0 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0
       2             : #include <linux/kernel.h>
       3             : #include <linux/netfilter.h>
       4             : #include <linux/netfilter_ipv4.h>
       5             : #include <linux/netfilter_ipv6.h>
       6             : #include <net/netfilter/nf_queue.h>
       7             : #include <net/ip6_checksum.h>
       8             : 
       9             : #ifdef CONFIG_INET
      10           0 : __sum16 nf_ip_checksum(struct sk_buff *skb, unsigned int hook,
      11             :                        unsigned int dataoff, u8 protocol)
      12             : {
      13           0 :         const struct iphdr *iph = ip_hdr(skb);
      14           0 :         __sum16 csum = 0;
      15             : 
      16           0 :         switch (skb->ip_summed) {
      17           0 :         case CHECKSUM_COMPLETE:
      18           0 :                 if (hook != NF_INET_PRE_ROUTING && hook != NF_INET_LOCAL_IN)
      19             :                         break;
      20           0 :                 if ((protocol != IPPROTO_TCP && protocol != IPPROTO_UDP &&
      21           0 :                     !csum_fold(skb->csum)) ||
      22           0 :                     !csum_tcpudp_magic(iph->saddr, iph->daddr,
      23           0 :                                        skb->len - dataoff, protocol,
      24             :                                        skb->csum)) {
      25           0 :                         skb->ip_summed = CHECKSUM_UNNECESSARY;
      26           0 :                         break;
      27             :                 }
      28           0 :                 fallthrough;
      29             :         case CHECKSUM_NONE:
      30           0 :                 if (protocol != IPPROTO_TCP && protocol != IPPROTO_UDP)
      31           0 :                         skb->csum = 0;
      32             :                 else
      33           0 :                         skb->csum = csum_tcpudp_nofold(iph->saddr, iph->daddr,
      34           0 :                                                        skb->len - dataoff,
      35             :                                                        protocol, 0);
      36           0 :                 csum = __skb_checksum_complete(skb);
      37             :         }
      38           0 :         return csum;
      39             : }
      40             : EXPORT_SYMBOL(nf_ip_checksum);
      41             : #endif
      42             : 
      43           0 : static __sum16 nf_ip_checksum_partial(struct sk_buff *skb, unsigned int hook,
      44             :                                       unsigned int dataoff, unsigned int len,
      45             :                                       u8 protocol)
      46             : {
      47           0 :         const struct iphdr *iph = ip_hdr(skb);
      48           0 :         __sum16 csum = 0;
      49             : 
      50           0 :         switch (skb->ip_summed) {
      51           0 :         case CHECKSUM_COMPLETE:
      52           0 :                 if (len == skb->len - dataoff)
      53           0 :                         return nf_ip_checksum(skb, hook, dataoff, protocol);
      54           0 :                 fallthrough;
      55             :         case CHECKSUM_NONE:
      56           0 :                 skb->csum = csum_tcpudp_nofold(iph->saddr, iph->daddr, protocol,
      57           0 :                                                skb->len - dataoff, 0);
      58           0 :                 skb->ip_summed = CHECKSUM_NONE;
      59           0 :                 return __skb_checksum_complete_head(skb, dataoff + len);
      60             :         }
      61             :         return csum;
      62             : }
      63             : 
      64           0 : __sum16 nf_ip6_checksum(struct sk_buff *skb, unsigned int hook,
      65             :                         unsigned int dataoff, u8 protocol)
      66             : {
      67           0 :         const struct ipv6hdr *ip6h = ipv6_hdr(skb);
      68           0 :         __sum16 csum = 0;
      69             : 
      70           0 :         switch (skb->ip_summed) {
      71           0 :         case CHECKSUM_COMPLETE:
      72           0 :                 if (hook != NF_INET_PRE_ROUTING && hook != NF_INET_LOCAL_IN)
      73             :                         break;
      74           0 :                 if (!csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr,
      75           0 :                                      skb->len - dataoff, protocol,
      76             :                                      csum_sub(skb->csum,
      77             :                                               skb_checksum(skb, 0,
      78             :                                                            dataoff, 0)))) {
      79           0 :                         skb->ip_summed = CHECKSUM_UNNECESSARY;
      80           0 :                         break;
      81             :                 }
      82           0 :                 fallthrough;
      83             :         case CHECKSUM_NONE:
      84           0 :                 skb->csum = ~csum_unfold(
      85           0 :                                 csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr,
      86           0 :                                              skb->len - dataoff,
      87             :                                              protocol,
      88             :                                              csum_sub(0,
      89             :                                                       skb_checksum(skb, 0,
      90             :                                                                    dataoff, 0))));
      91           0 :                 csum = __skb_checksum_complete(skb);
      92             :         }
      93           0 :         return csum;
      94             : }
      95             : EXPORT_SYMBOL(nf_ip6_checksum);
      96             : 
      97           0 : static __sum16 nf_ip6_checksum_partial(struct sk_buff *skb, unsigned int hook,
      98             :                                        unsigned int dataoff, unsigned int len,
      99             :                                        u8 protocol)
     100             : {
     101           0 :         const struct ipv6hdr *ip6h = ipv6_hdr(skb);
     102           0 :         __wsum hsum;
     103           0 :         __sum16 csum = 0;
     104             : 
     105           0 :         switch (skb->ip_summed) {
     106           0 :         case CHECKSUM_COMPLETE:
     107           0 :                 if (len == skb->len - dataoff)
     108           0 :                         return nf_ip6_checksum(skb, hook, dataoff, protocol);
     109           0 :                 fallthrough;
     110             :         case CHECKSUM_NONE:
     111           0 :                 hsum = skb_checksum(skb, 0, dataoff, 0);
     112           0 :                 skb->csum = ~csum_unfold(csum_ipv6_magic(&ip6h->saddr,
     113             :                                                          &ip6h->daddr,
     114           0 :                                                          skb->len - dataoff,
     115             :                                                          protocol,
     116             :                                                          csum_sub(0, hsum)));
     117           0 :                 skb->ip_summed = CHECKSUM_NONE;
     118           0 :                 return __skb_checksum_complete_head(skb, dataoff + len);
     119             :         }
     120             :         return csum;
     121             : };
     122             : 
     123           0 : __sum16 nf_checksum(struct sk_buff *skb, unsigned int hook,
     124             :                     unsigned int dataoff, u8 protocol,
     125             :                     unsigned short family)
     126             : {
     127           0 :         __sum16 csum = 0;
     128             : 
     129           0 :         switch (family) {
     130           0 :         case AF_INET:
     131           0 :                 csum = nf_ip_checksum(skb, hook, dataoff, protocol);
     132           0 :                 break;
     133           0 :         case AF_INET6:
     134           0 :                 csum = nf_ip6_checksum(skb, hook, dataoff, protocol);
     135           0 :                 break;
     136             :         }
     137             : 
     138           0 :         return csum;
     139             : }
     140             : EXPORT_SYMBOL_GPL(nf_checksum);
     141             : 
     142           0 : __sum16 nf_checksum_partial(struct sk_buff *skb, unsigned int hook,
     143             :                             unsigned int dataoff, unsigned int len,
     144             :                             u8 protocol, unsigned short family)
     145             : {
     146           0 :         __sum16 csum = 0;
     147             : 
     148           0 :         switch (family) {
     149           0 :         case AF_INET:
     150           0 :                 csum = nf_ip_checksum_partial(skb, hook, dataoff, len,
     151             :                                               protocol);
     152           0 :                 break;
     153           0 :         case AF_INET6:
     154           0 :                 csum = nf_ip6_checksum_partial(skb, hook, dataoff, len,
     155             :                                                protocol);
     156           0 :                 break;
     157             :         }
     158             : 
     159           0 :         return csum;
     160             : }
     161             : EXPORT_SYMBOL_GPL(nf_checksum_partial);
     162             : 
     163           0 : int nf_route(struct net *net, struct dst_entry **dst, struct flowi *fl,
     164             :              bool strict, unsigned short family)
     165             : {
     166           0 :         const struct nf_ipv6_ops *v6ops __maybe_unused;
     167           0 :         int ret = 0;
     168             : 
     169           0 :         switch (family) {
     170           0 :         case AF_INET:
     171           0 :                 ret = nf_ip_route(net, dst, fl, strict);
     172           0 :                 break;
     173           0 :         case AF_INET6:
     174           0 :                 ret = nf_ip6_route(net, dst, fl, strict);
     175           0 :                 break;
     176             :         }
     177             : 
     178           0 :         return ret;
     179             : }
     180             : EXPORT_SYMBOL_GPL(nf_route);
     181             : 
     182           0 : static int nf_ip_reroute(struct sk_buff *skb, const struct nf_queue_entry *entry)
     183             : {
     184             : #ifdef CONFIG_INET
     185           0 :         const struct ip_rt_info *rt_info = nf_queue_entry_reroute(entry);
     186             : 
     187           0 :         if (entry->state.hook == NF_INET_LOCAL_OUT) {
     188           0 :                 const struct iphdr *iph = ip_hdr(skb);
     189             : 
     190           0 :                 if (!(iph->tos == rt_info->tos &&
     191           0 :                       skb->mark == rt_info->mark &&
     192           0 :                       iph->daddr == rt_info->daddr &&
     193           0 :                       iph->saddr == rt_info->saddr))
     194           0 :                         return ip_route_me_harder(entry->state.net, entry->state.sk,
     195             :                                                   skb, RTN_UNSPEC);
     196             :         }
     197             : #endif
     198             :         return 0;
     199             : }
     200             : 
     201           0 : int nf_reroute(struct sk_buff *skb, struct nf_queue_entry *entry)
     202             : {
     203           0 :         const struct nf_ipv6_ops *v6ops;
     204           0 :         int ret = 0;
     205             : 
     206           0 :         switch (entry->state.pf) {
     207           0 :         case AF_INET:
     208           0 :                 ret = nf_ip_reroute(skb, entry);
     209           0 :                 break;
     210             :         case AF_INET6:
     211           0 :                 v6ops = rcu_dereference(nf_ipv6_ops);
     212           0 :                 if (v6ops)
     213           0 :                         ret = v6ops->reroute(skb, entry);
     214             :                 break;
     215             :         }
     216           0 :         return ret;
     217             : }

Generated by: LCOV version 1.14