LCOV - code coverage report
Current view: top level - net/ipv6 - esp6.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 3 515 0.6 %
Date: 2022-03-28 16:04:14 Functions: 1 22 4.5 %
Branches: 2 256 0.8 %

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: GPL-2.0-or-later
       2                 :            : /*
       3                 :            :  * Copyright (C)2002 USAGI/WIDE Project
       4                 :            :  *
       5                 :            :  * Authors
       6                 :            :  *
       7                 :            :  *      Mitsuru KANDA @USAGI       : IPv6 Support
       8                 :            :  *      Kazunori MIYAZAWA @USAGI   :
       9                 :            :  *      Kunihiro Ishiguro <kunihiro@ipinfusion.com>
      10                 :            :  *
      11                 :            :  *      This file is derived from net/ipv4/esp.c
      12                 :            :  */
      13                 :            : 
      14                 :            : #define pr_fmt(fmt) "IPv6: " fmt
      15                 :            : 
      16                 :            : #include <crypto/aead.h>
      17                 :            : #include <crypto/authenc.h>
      18                 :            : #include <linux/err.h>
      19                 :            : #include <linux/module.h>
      20                 :            : #include <net/ip.h>
      21                 :            : #include <net/xfrm.h>
      22                 :            : #include <net/esp.h>
      23                 :            : #include <linux/scatterlist.h>
      24                 :            : #include <linux/kernel.h>
      25                 :            : #include <linux/pfkeyv2.h>
      26                 :            : #include <linux/random.h>
      27                 :            : #include <linux/slab.h>
      28                 :            : #include <linux/spinlock.h>
      29                 :            : #include <net/ip6_route.h>
      30                 :            : #include <net/icmp.h>
      31                 :            : #include <net/ipv6.h>
      32                 :            : #include <net/protocol.h>
      33                 :            : #include <linux/icmpv6.h>
      34                 :            : 
      35                 :            : #include <linux/highmem.h>
      36                 :            : 
      37                 :            : struct esp_skb_cb {
      38                 :            :         struct xfrm_skb_cb xfrm;
      39                 :            :         void *tmp;
      40                 :            : };
      41                 :            : 
      42                 :            : #define ESP_SKB_CB(__skb) ((struct esp_skb_cb *)&((__skb)->cb[0]))
      43                 :            : 
      44                 :            : /*
      45                 :            :  * Allocate an AEAD request structure with extra space for SG and IV.
      46                 :            :  *
      47                 :            :  * For alignment considerations the upper 32 bits of the sequence number are
      48                 :            :  * placed at the front, if present. Followed by the IV, the request and finally
      49                 :            :  * the SG list.
      50                 :            :  *
      51                 :            :  * TODO: Use spare space in skb for this where possible.
      52                 :            :  */
      53                 :          0 : static void *esp_alloc_tmp(struct crypto_aead *aead, int nfrags, int seqihlen)
      54                 :            : {
      55                 :          0 :         unsigned int len;
      56                 :            : 
      57                 :          0 :         len = seqihlen;
      58                 :            : 
      59         [ #  # ]:          0 :         len += crypto_aead_ivsize(aead);
      60                 :            : 
      61         [ #  # ]:          0 :         if (len) {
      62                 :          0 :                 len += crypto_aead_alignmask(aead) &
      63                 :            :                        ~(crypto_tfm_ctx_alignment() - 1);
      64                 :          0 :                 len = ALIGN(len, crypto_tfm_ctx_alignment());
      65                 :            :         }
      66                 :            : 
      67         [ #  # ]:          0 :         len += sizeof(struct aead_request) + crypto_aead_reqsize(aead);
      68                 :          0 :         len = ALIGN(len, __alignof__(struct scatterlist));
      69                 :            : 
      70                 :          0 :         len += sizeof(struct scatterlist) * nfrags;
      71                 :            : 
      72         [ #  # ]:          0 :         return kmalloc(len, GFP_ATOMIC);
      73                 :            : }
      74                 :            : 
      75                 :          0 : static inline __be32 *esp_tmp_seqhi(void *tmp)
      76                 :            : {
      77                 :          0 :         return PTR_ALIGN((__be32 *)tmp, __alignof__(__be32));
      78                 :            : }
      79                 :            : 
      80                 :          0 : static inline u8 *esp_tmp_iv(struct crypto_aead *aead, void *tmp, int seqhilen)
      81                 :            : {
      82                 :          0 :         return crypto_aead_ivsize(aead) ?
      83                 :          0 :                PTR_ALIGN((u8 *)tmp + seqhilen,
      84   [ #  #  #  # ]:          0 :                          crypto_aead_alignmask(aead) + 1) : tmp + seqhilen;
      85                 :            : }
      86                 :            : 
      87                 :          0 : static inline struct aead_request *esp_tmp_req(struct crypto_aead *aead, u8 *iv)
      88                 :            : {
      89                 :          0 :         struct aead_request *req;
      90                 :            : 
      91                 :          0 :         req = (void *)PTR_ALIGN(iv + crypto_aead_ivsize(aead),
      92                 :            :                                 crypto_tfm_ctx_alignment());
      93         [ #  # ]:          0 :         aead_request_set_tfm(req, aead);
      94                 :          0 :         return req;
      95                 :            : }
      96                 :            : 
      97                 :          0 : static inline struct scatterlist *esp_req_sg(struct crypto_aead *aead,
      98                 :            :                                              struct aead_request *req)
      99                 :            : {
     100                 :          0 :         return (void *)ALIGN((unsigned long)(req + 1) +
     101                 :            :                              crypto_aead_reqsize(aead),
     102                 :            :                              __alignof__(struct scatterlist));
     103                 :            : }
     104                 :            : 
     105                 :            : static void esp_ssg_unref(struct xfrm_state *x, void *tmp)
     106                 :            : {
     107                 :            :         struct crypto_aead *aead = x->data;
     108                 :            :         int seqhilen = 0;
     109                 :            :         u8 *iv;
     110                 :            :         struct aead_request *req;
     111                 :            :         struct scatterlist *sg;
     112                 :            : 
     113                 :            :         if (x->props.flags & XFRM_STATE_ESN)
     114                 :            :                 seqhilen += sizeof(__be32);
     115                 :            : 
     116                 :            :         iv = esp_tmp_iv(aead, tmp, seqhilen);
     117                 :            :         req = esp_tmp_req(aead, iv);
     118                 :            : 
     119                 :            :         /* Unref skb_frag_pages in the src scatterlist if necessary.
     120                 :            :          * Skip the first sg which comes from skb->data.
     121                 :            :          */
     122                 :            :         if (req->src != req->dst)
     123                 :            :                 for (sg = sg_next(req->src); sg; sg = sg_next(sg))
     124                 :            :                         put_page(sg_page(sg));
     125                 :            : }
     126                 :            : 
     127                 :          0 : static void esp_output_done(struct crypto_async_request *base, int err)
     128                 :            : {
     129                 :          0 :         struct sk_buff *skb = base->data;
     130         [ #  # ]:          0 :         struct xfrm_offload *xo = xfrm_offload(skb);
     131                 :          0 :         void *tmp;
     132                 :          0 :         struct xfrm_state *x;
     133                 :            : 
     134   [ #  #  #  # ]:          0 :         if (xo && (xo->flags & XFRM_DEV_RESUME)) {
     135                 :          0 :                 struct sec_path *sp = skb_sec_path(skb);
     136                 :            : 
     137                 :          0 :                 x = sp->xvec[sp->len - 1];
     138                 :            :         } else {
     139                 :          0 :                 x = skb_dst(skb)->xfrm;
     140                 :            :         }
     141                 :            : 
     142                 :          0 :         tmp = ESP_SKB_CB(skb)->tmp;
     143                 :          0 :         esp_ssg_unref(x, tmp);
     144                 :          0 :         kfree(tmp);
     145                 :            : 
     146   [ #  #  #  # ]:          0 :         if (xo && (xo->flags & XFRM_DEV_RESUME)) {
     147         [ #  # ]:          0 :                 if (err) {
     148                 :          0 :                         XFRM_INC_STATS(xs_net(x), LINUX_MIB_XFRMOUTSTATEPROTOERROR);
     149                 :          0 :                         kfree_skb(skb);
     150                 :          0 :                         return;
     151                 :            :                 }
     152                 :            : 
     153                 :          0 :                 skb_push(skb, skb->data - skb_mac_header(skb));
     154         [ #  # ]:          0 :                 secpath_reset(skb);
     155                 :            :                 xfrm_dev_resume(skb);
     156                 :            :         } else {
     157                 :          0 :                 xfrm_output_resume(skb, err);
     158                 :            :         }
     159                 :            : }
     160                 :            : 
     161                 :            : /* Move ESP header back into place. */
     162                 :          0 : static void esp_restore_header(struct sk_buff *skb, unsigned int offset)
     163                 :            : {
     164                 :          0 :         struct ip_esp_hdr *esph = (void *)(skb->data + offset);
     165                 :          0 :         void *tmp = ESP_SKB_CB(skb)->tmp;
     166                 :          0 :         __be32 *seqhi = esp_tmp_seqhi(tmp);
     167                 :            : 
     168                 :          0 :         esph->seq_no = esph->spi;
     169                 :          0 :         esph->spi = *seqhi;
     170                 :            : }
     171                 :            : 
     172                 :          0 : static void esp_output_restore_header(struct sk_buff *skb)
     173                 :            : {
     174                 :          0 :         esp_restore_header(skb, skb_transport_offset(skb) - sizeof(__be32));
     175                 :          0 : }
     176                 :            : 
     177                 :            : static struct ip_esp_hdr *esp_output_set_esn(struct sk_buff *skb,
     178                 :            :                                              struct xfrm_state *x,
     179                 :            :                                              struct ip_esp_hdr *esph,
     180                 :            :                                              __be32 *seqhi)
     181                 :            : {
     182                 :            :         /* For ESN we move the header forward by 4 bytes to
     183                 :            :          * accomodate the high bits.  We will move it back after
     184                 :            :          * encryption.
     185                 :            :          */
     186                 :            :         if ((x->props.flags & XFRM_STATE_ESN)) {
     187                 :            :                 struct xfrm_offload *xo = xfrm_offload(skb);
     188                 :            : 
     189                 :            :                 esph = (void *)(skb_transport_header(skb) - sizeof(__be32));
     190                 :            :                 *seqhi = esph->spi;
     191                 :            :                 if (xo)
     192                 :            :                         esph->seq_no = htonl(xo->seq.hi);
     193                 :            :                 else
     194                 :            :                         esph->seq_no = htonl(XFRM_SKB_CB(skb)->seq.output.hi);
     195                 :            :         }
     196                 :            : 
     197                 :            :         esph->spi = x->id.spi;
     198                 :            : 
     199                 :            :         return esph;
     200                 :            : }
     201                 :            : 
     202                 :          0 : static void esp_output_done_esn(struct crypto_async_request *base, int err)
     203                 :            : {
     204                 :          0 :         struct sk_buff *skb = base->data;
     205                 :            : 
     206                 :          0 :         esp_output_restore_header(skb);
     207                 :          0 :         esp_output_done(base, err);
     208                 :          0 : }
     209                 :            : 
     210                 :          0 : static void esp_output_fill_trailer(u8 *tail, int tfclen, int plen, __u8 proto)
     211                 :            : {
     212                 :            :         /* Fill padding... */
     213         [ #  # ]:          0 :         if (tfclen) {
     214                 :          0 :                 memset(tail, 0, tfclen);
     215                 :          0 :                 tail += tfclen;
     216                 :            :         }
     217                 :          0 :         do {
     218                 :          0 :                 int i;
     219         [ #  # ]:          0 :                 for (i = 0; i < plen - 2; i++)
     220                 :          0 :                         tail[i] = i + 1;
     221                 :          0 :         } while (0);
     222                 :          0 :         tail[plen - 2] = plen - 2;
     223                 :          0 :         tail[plen - 1] = proto;
     224                 :          0 : }
     225                 :            : 
     226                 :          0 : int esp6_output_head(struct xfrm_state *x, struct sk_buff *skb, struct esp_info *esp)
     227                 :            : {
     228                 :          0 :         u8 *tail;
     229                 :          0 :         u8 *vaddr;
     230                 :          0 :         int nfrags;
     231                 :          0 :         struct page *page;
     232                 :          0 :         struct sk_buff *trailer;
     233                 :          0 :         int tailen = esp->tailen;
     234                 :            : 
     235         [ #  # ]:          0 :         if (!skb_cloned(skb)) {
     236   [ #  #  #  # ]:          0 :                 if (tailen <= skb_tailroom(skb)) {
     237                 :          0 :                         nfrags = 1;
     238                 :          0 :                         trailer = skb;
     239                 :          0 :                         tail = skb_tail_pointer(trailer);
     240                 :            : 
     241                 :          0 :                         goto skip_cow;
     242         [ #  # ]:          0 :                 } else if ((skb_shinfo(skb)->nr_frags < MAX_SKB_FRAGS)
     243         [ #  # ]:          0 :                            && !skb_has_frag_list(skb)) {
     244                 :          0 :                         int allocsize;
     245                 :          0 :                         struct sock *sk = skb->sk;
     246                 :          0 :                         struct page_frag *pfrag = &x->xfrag;
     247                 :            : 
     248                 :          0 :                         esp->inplace = false;
     249                 :            : 
     250                 :          0 :                         allocsize = ALIGN(tailen, L1_CACHE_BYTES);
     251                 :            : 
     252                 :          0 :                         spin_lock_bh(&x->lock);
     253                 :            : 
     254         [ #  # ]:          0 :                         if (unlikely(!skb_page_frag_refill(allocsize, pfrag, GFP_ATOMIC))) {
     255                 :          0 :                                 spin_unlock_bh(&x->lock);
     256                 :          0 :                                 goto cow;
     257                 :            :                         }
     258                 :            : 
     259                 :          0 :                         page = pfrag->page;
     260         [ #  # ]:          0 :                         get_page(page);
     261                 :            : 
     262                 :          0 :                         vaddr = kmap_atomic(page);
     263                 :            : 
     264                 :          0 :                         tail = vaddr + pfrag->offset;
     265                 :            : 
     266                 :          0 :                         esp_output_fill_trailer(tail, esp->tfclen, esp->plen, esp->proto);
     267                 :            : 
     268                 :          0 :                         kunmap_atomic(vaddr);
     269                 :            : 
     270         [ #  # ]:          0 :                         nfrags = skb_shinfo(skb)->nr_frags;
     271                 :            : 
     272         [ #  # ]:          0 :                         __skb_fill_page_desc(skb, nfrags, page, pfrag->offset,
     273                 :            :                                              tailen);
     274                 :          0 :                         skb_shinfo(skb)->nr_frags = ++nfrags;
     275                 :            : 
     276                 :          0 :                         pfrag->offset = pfrag->offset + allocsize;
     277                 :            : 
     278                 :          0 :                         spin_unlock_bh(&x->lock);
     279                 :            : 
     280                 :          0 :                         nfrags++;
     281                 :            : 
     282                 :          0 :                         skb->len += tailen;
     283                 :          0 :                         skb->data_len += tailen;
     284                 :          0 :                         skb->truesize += tailen;
     285   [ #  #  #  # ]:          0 :                         if (sk && sk_fullsock(sk))
     286                 :          0 :                                 refcount_add(tailen, &sk->sk_wmem_alloc);
     287                 :            : 
     288                 :          0 :                         goto out;
     289                 :            :                 }
     290                 :            :         }
     291                 :            : 
     292                 :          0 : cow:
     293                 :          0 :         nfrags = skb_cow_data(skb, tailen, &trailer);
     294         [ #  # ]:          0 :         if (nfrags < 0)
     295                 :          0 :                 goto out;
     296                 :          0 :         tail = skb_tail_pointer(trailer);
     297                 :            : 
     298                 :          0 : skip_cow:
     299                 :          0 :         esp_output_fill_trailer(tail, esp->tfclen, esp->plen, esp->proto);
     300                 :          0 :         pskb_put(skb, trailer, tailen);
     301                 :            : 
     302                 :          0 : out:
     303                 :          0 :         return nfrags;
     304                 :            : }
     305                 :            : EXPORT_SYMBOL_GPL(esp6_output_head);
     306                 :            : 
     307                 :          0 : int esp6_output_tail(struct xfrm_state *x, struct sk_buff *skb, struct esp_info *esp)
     308                 :            : {
     309                 :          0 :         u8 *iv;
     310                 :          0 :         int alen;
     311                 :          0 :         void *tmp;
     312                 :          0 :         int ivlen;
     313                 :          0 :         int assoclen;
     314                 :          0 :         int seqhilen;
     315                 :          0 :         __be32 *seqhi;
     316                 :          0 :         struct page *page;
     317                 :          0 :         struct ip_esp_hdr *esph;
     318                 :          0 :         struct aead_request *req;
     319                 :          0 :         struct crypto_aead *aead;
     320                 :          0 :         struct scatterlist *sg, *dsg;
     321                 :          0 :         int err = -ENOMEM;
     322                 :            : 
     323                 :          0 :         assoclen = sizeof(struct ip_esp_hdr);
     324                 :          0 :         seqhilen = 0;
     325                 :            : 
     326         [ #  # ]:          0 :         if (x->props.flags & XFRM_STATE_ESN) {
     327                 :          0 :                 seqhilen += sizeof(__be32);
     328                 :          0 :                 assoclen += sizeof(__be32);
     329                 :            :         }
     330                 :            : 
     331                 :          0 :         aead = x->data;
     332                 :          0 :         alen = crypto_aead_authsize(aead);
     333                 :          0 :         ivlen = crypto_aead_ivsize(aead);
     334                 :            : 
     335                 :          0 :         tmp = esp_alloc_tmp(aead, esp->nfrags + 2, seqhilen);
     336         [ #  # ]:          0 :         if (!tmp)
     337                 :          0 :                 goto error;
     338                 :            : 
     339                 :          0 :         seqhi = esp_tmp_seqhi(tmp);
     340         [ #  # ]:          0 :         iv = esp_tmp_iv(aead, tmp, seqhilen);
     341         [ #  # ]:          0 :         req = esp_tmp_req(aead, iv);
     342         [ #  # ]:          0 :         sg = esp_req_sg(aead, req);
     343                 :            : 
     344         [ #  # ]:          0 :         if (esp->inplace)
     345                 :            :                 dsg = sg;
     346                 :            :         else
     347                 :          0 :                 dsg = &sg[esp->nfrags];
     348                 :            : 
     349                 :          0 :         esph = esp_output_set_esn(skb, x, ip_esp_hdr(skb), seqhi);
     350                 :            : 
     351                 :          0 :         sg_init_table(sg, esp->nfrags);
     352                 :          0 :         err = skb_to_sgvec(skb, sg,
     353                 :          0 :                            (unsigned char *)esph - skb->data,
     354                 :          0 :                            assoclen + ivlen + esp->clen + alen);
     355         [ #  # ]:          0 :         if (unlikely(err < 0))
     356                 :          0 :                 goto error_free;
     357                 :            : 
     358         [ #  # ]:          0 :         if (!esp->inplace) {
     359                 :          0 :                 int allocsize;
     360                 :          0 :                 struct page_frag *pfrag = &x->xfrag;
     361                 :            : 
     362                 :          0 :                 allocsize = ALIGN(skb->data_len, L1_CACHE_BYTES);
     363                 :            : 
     364                 :          0 :                 spin_lock_bh(&x->lock);
     365         [ #  # ]:          0 :                 if (unlikely(!skb_page_frag_refill(allocsize, pfrag, GFP_ATOMIC))) {
     366                 :          0 :                         spin_unlock_bh(&x->lock);
     367                 :          0 :                         goto error_free;
     368                 :            :                 }
     369                 :            : 
     370         [ #  # ]:          0 :                 skb_shinfo(skb)->nr_frags = 1;
     371                 :            : 
     372                 :          0 :                 page = pfrag->page;
     373         [ #  # ]:          0 :                 get_page(page);
     374                 :            :                 /* replace page frags in skb with new page */
     375         [ #  # ]:          0 :                 __skb_fill_page_desc(skb, 0, page, pfrag->offset, skb->data_len);
     376                 :          0 :                 pfrag->offset = pfrag->offset + allocsize;
     377                 :          0 :                 spin_unlock_bh(&x->lock);
     378                 :            : 
     379                 :          0 :                 sg_init_table(dsg, skb_shinfo(skb)->nr_frags + 1);
     380                 :          0 :                 err = skb_to_sgvec(skb, dsg,
     381                 :          0 :                                    (unsigned char *)esph - skb->data,
     382                 :          0 :                                    assoclen + ivlen + esp->clen + alen);
     383         [ #  # ]:          0 :                 if (unlikely(err < 0))
     384                 :          0 :                         goto error_free;
     385                 :            :         }
     386                 :            : 
     387         [ #  # ]:          0 :         if ((x->props.flags & XFRM_STATE_ESN))
     388                 :          0 :                 aead_request_set_callback(req, 0, esp_output_done_esn, skb);
     389                 :            :         else
     390                 :          0 :                 aead_request_set_callback(req, 0, esp_output_done, skb);
     391                 :            : 
     392                 :          0 :         aead_request_set_crypt(req, sg, dsg, ivlen + esp->clen, iv);
     393                 :          0 :         aead_request_set_ad(req, assoclen);
     394                 :            : 
     395                 :          0 :         memset(iv, 0, ivlen);
     396                 :          0 :         memcpy(iv + ivlen - min(ivlen, 8), (u8 *)&esp->seqno + 8 - min(ivlen, 8),
     397                 :          0 :                min(ivlen, 8));
     398                 :            : 
     399                 :          0 :         ESP_SKB_CB(skb)->tmp = tmp;
     400                 :          0 :         err = crypto_aead_encrypt(req);
     401                 :            : 
     402   [ #  #  #  # ]:          0 :         switch (err) {
     403                 :          0 :         case -EINPROGRESS:
     404                 :          0 :                 goto error;
     405                 :            : 
     406                 :          0 :         case -ENOSPC:
     407                 :          0 :                 err = NET_XMIT_DROP;
     408                 :          0 :                 break;
     409                 :            : 
     410                 :          0 :         case 0:
     411         [ #  # ]:          0 :                 if ((x->props.flags & XFRM_STATE_ESN))
     412                 :          0 :                         esp_output_restore_header(skb);
     413                 :            :         }
     414                 :            : 
     415         [ #  # ]:          0 :         if (sg != dsg)
     416                 :          0 :                 esp_ssg_unref(x, tmp);
     417                 :            : 
     418                 :          0 : error_free:
     419                 :          0 :         kfree(tmp);
     420                 :          0 : error:
     421                 :          0 :         return err;
     422                 :            : }
     423                 :            : EXPORT_SYMBOL_GPL(esp6_output_tail);
     424                 :            : 
     425                 :          0 : static int esp6_output(struct xfrm_state *x, struct sk_buff *skb)
     426                 :            : {
     427                 :          0 :         int alen;
     428                 :          0 :         int blksize;
     429                 :          0 :         struct ip_esp_hdr *esph;
     430                 :          0 :         struct crypto_aead *aead;
     431                 :          0 :         struct esp_info esp;
     432                 :            : 
     433                 :          0 :         esp.inplace = true;
     434                 :            : 
     435         [ #  # ]:          0 :         esp.proto = *skb_mac_header(skb);
     436                 :          0 :         *skb_mac_header(skb) = IPPROTO_ESP;
     437                 :            : 
     438                 :            :         /* skb is pure payload to encrypt */
     439                 :            : 
     440                 :          0 :         aead = x->data;
     441         [ #  # ]:          0 :         alen = crypto_aead_authsize(aead);
     442                 :            : 
     443                 :          0 :         esp.tfclen = 0;
     444         [ #  # ]:          0 :         if (x->tfcpad) {
     445                 :          0 :                 struct xfrm_dst *dst = (struct xfrm_dst *)skb_dst(skb);
     446                 :          0 :                 u32 padto;
     447                 :            : 
     448                 :          0 :                 padto = min(x->tfcpad, xfrm_state_mtu(x, dst->child_mtu_cached));
     449         [ #  # ]:          0 :                 if (skb->len < padto)
     450                 :          0 :                         esp.tfclen = padto - skb->len;
     451                 :            :         }
     452                 :          0 :         blksize = ALIGN(crypto_aead_blocksize(aead), 4);
     453                 :          0 :         esp.clen = ALIGN(skb->len + 2 + esp.tfclen, blksize);
     454                 :          0 :         esp.plen = esp.clen - skb->len - esp.tfclen;
     455                 :          0 :         esp.tailen = esp.tfclen + esp.plen + alen;
     456                 :            : 
     457                 :          0 :         esp.nfrags = esp6_output_head(x, skb, &esp);
     458         [ #  # ]:          0 :         if (esp.nfrags < 0)
     459                 :            :                 return esp.nfrags;
     460                 :            : 
     461                 :          0 :         esph = ip_esp_hdr(skb);
     462                 :          0 :         esph->spi = x->id.spi;
     463                 :            : 
     464                 :          0 :         esph->seq_no = htonl(XFRM_SKB_CB(skb)->seq.output.low);
     465                 :          0 :         esp.seqno = cpu_to_be64(XFRM_SKB_CB(skb)->seq.output.low +
     466                 :            :                             ((u64)XFRM_SKB_CB(skb)->seq.output.hi << 32));
     467                 :            : 
     468                 :          0 :         skb_push(skb, -skb_network_offset(skb));
     469                 :            : 
     470                 :          0 :         return esp6_output_tail(x, skb, &esp);
     471                 :            : }
     472                 :            : 
     473                 :          0 : static inline int esp_remove_trailer(struct sk_buff *skb)
     474                 :            : {
     475         [ #  # ]:          0 :         struct xfrm_state *x = xfrm_input_state(skb);
     476         [ #  # ]:          0 :         struct xfrm_offload *xo = xfrm_offload(skb);
     477                 :          0 :         struct crypto_aead *aead = x->data;
     478                 :          0 :         int alen, hlen, elen;
     479                 :          0 :         int padlen, trimlen;
     480                 :          0 :         __wsum csumdiff;
     481                 :          0 :         u8 nexthdr[2];
     482                 :          0 :         int ret;
     483                 :            : 
     484         [ #  # ]:          0 :         alen = crypto_aead_authsize(aead);
     485         [ #  # ]:          0 :         hlen = sizeof(struct ip_esp_hdr) + crypto_aead_ivsize(aead);
     486                 :          0 :         elen = skb->len - hlen;
     487                 :            : 
     488   [ #  #  #  # ]:          0 :         if (xo && (xo->flags & XFRM_ESP_NO_TRAILER)) {
     489                 :          0 :                 ret = xo->proto;
     490                 :          0 :                 goto out;
     491                 :            :         }
     492                 :            : 
     493                 :          0 :         ret = skb_copy_bits(skb, skb->len - alen - 2, nexthdr, 2);
     494         [ #  # ]:          0 :         BUG_ON(ret);
     495                 :            : 
     496                 :          0 :         ret = -EINVAL;
     497                 :          0 :         padlen = nexthdr[0];
     498         [ #  # ]:          0 :         if (padlen + 2 + alen >= elen) {
     499                 :          0 :                 net_dbg_ratelimited("ipsec esp packet is garbage padlen=%d, elen=%d\n",
     500                 :            :                                     padlen + 2, elen - alen);
     501                 :          0 :                 goto out;
     502                 :            :         }
     503                 :            : 
     504                 :          0 :         trimlen = alen + padlen + 2;
     505         [ #  # ]:          0 :         if (skb->ip_summed == CHECKSUM_COMPLETE) {
     506                 :          0 :                 csumdiff = skb_checksum(skb, skb->len - trimlen, trimlen, 0);
     507                 :          0 :                 skb->csum = csum_block_sub(skb->csum, csumdiff,
     508         [ #  # ]:          0 :                                            skb->len - trimlen);
     509                 :            :         }
     510                 :          0 :         pskb_trim(skb, skb->len - trimlen);
     511                 :            : 
     512                 :          0 :         ret = nexthdr[1];
     513                 :            : 
     514                 :          0 : out:
     515                 :          0 :         return ret;
     516                 :            : }
     517                 :            : 
     518                 :          0 : int esp6_input_done2(struct sk_buff *skb, int err)
     519                 :            : {
     520         [ #  # ]:          0 :         struct xfrm_state *x = xfrm_input_state(skb);
     521         [ #  # ]:          0 :         struct xfrm_offload *xo = xfrm_offload(skb);
     522                 :          0 :         struct crypto_aead *aead = x->data;
     523         [ #  # ]:          0 :         int hlen = sizeof(struct ip_esp_hdr) + crypto_aead_ivsize(aead);
     524         [ #  # ]:          0 :         int hdr_len = skb_network_header_len(skb);
     525                 :            : 
     526   [ #  #  #  # ]:          0 :         if (!xo || (xo && !(xo->flags & CRYPTO_DONE)))
     527                 :          0 :                 kfree(ESP_SKB_CB(skb)->tmp);
     528                 :            : 
     529         [ #  # ]:          0 :         if (unlikely(err))
     530                 :          0 :                 goto out;
     531                 :            : 
     532                 :          0 :         err = esp_remove_trailer(skb);
     533         [ #  # ]:          0 :         if (unlikely(err < 0))
     534                 :          0 :                 goto out;
     535                 :            : 
     536                 :          0 :         skb_postpull_rcsum(skb, skb_network_header(skb),
     537                 :            :                            skb_network_header_len(skb));
     538                 :          0 :         skb_pull_rcsum(skb, hlen);
     539         [ #  # ]:          0 :         if (x->props.mode == XFRM_MODE_TUNNEL)
     540                 :          0 :                 skb_reset_transport_header(skb);
     541                 :            :         else
     542                 :          0 :                 skb_set_transport_header(skb, -hdr_len);
     543                 :            : 
     544                 :            :         /* RFC4303: Drop dummy packets without any error */
     545         [ #  # ]:          0 :         if (err == IPPROTO_NONE)
     546                 :          0 :                 err = -EINVAL;
     547                 :            : 
     548                 :          0 : out:
     549                 :          0 :         return err;
     550                 :            : }
     551                 :            : EXPORT_SYMBOL_GPL(esp6_input_done2);
     552                 :            : 
     553                 :          0 : static void esp_input_done(struct crypto_async_request *base, int err)
     554                 :            : {
     555                 :          0 :         struct sk_buff *skb = base->data;
     556                 :            : 
     557                 :          0 :         xfrm_input_resume(skb, esp6_input_done2(skb, err));
     558                 :          0 : }
     559                 :            : 
     560                 :          0 : static void esp_input_restore_header(struct sk_buff *skb)
     561                 :            : {
     562                 :          0 :         esp_restore_header(skb, 0);
     563         [ #  # ]:          0 :         __skb_pull(skb, 4);
     564                 :          0 : }
     565                 :            : 
     566                 :          0 : static void esp_input_set_header(struct sk_buff *skb, __be32 *seqhi)
     567                 :            : {
     568         [ #  # ]:          0 :         struct xfrm_state *x = xfrm_input_state(skb);
     569                 :            : 
     570                 :            :         /* For ESN we move the header forward by 4 bytes to
     571                 :            :          * accomodate the high bits.  We will move it back after
     572                 :            :          * decryption.
     573                 :            :          */
     574         [ #  # ]:          0 :         if ((x->props.flags & XFRM_STATE_ESN)) {
     575                 :          0 :                 struct ip_esp_hdr *esph = skb_push(skb, 4);
     576                 :            : 
     577                 :          0 :                 *seqhi = esph->spi;
     578                 :          0 :                 esph->spi = esph->seq_no;
     579                 :          0 :                 esph->seq_no = XFRM_SKB_CB(skb)->seq.input.hi;
     580                 :            :         }
     581                 :          0 : }
     582                 :            : 
     583                 :          0 : static void esp_input_done_esn(struct crypto_async_request *base, int err)
     584                 :            : {
     585                 :          0 :         struct sk_buff *skb = base->data;
     586                 :            : 
     587                 :          0 :         esp_input_restore_header(skb);
     588                 :          0 :         esp_input_done(base, err);
     589                 :          0 : }
     590                 :            : 
     591                 :          0 : static int esp6_input(struct xfrm_state *x, struct sk_buff *skb)
     592                 :            : {
     593                 :          0 :         struct crypto_aead *aead = x->data;
     594                 :          0 :         struct aead_request *req;
     595                 :          0 :         struct sk_buff *trailer;
     596                 :          0 :         int ivlen = crypto_aead_ivsize(aead);
     597                 :          0 :         int elen = skb->len - sizeof(struct ip_esp_hdr) - ivlen;
     598                 :          0 :         int nfrags;
     599                 :          0 :         int assoclen;
     600                 :          0 :         int seqhilen;
     601                 :          0 :         int ret = 0;
     602                 :          0 :         void *tmp;
     603                 :          0 :         __be32 *seqhi;
     604                 :          0 :         u8 *iv;
     605                 :          0 :         struct scatterlist *sg;
     606                 :            : 
     607         [ #  # ]:          0 :         if (!pskb_may_pull(skb, sizeof(struct ip_esp_hdr) + ivlen)) {
     608                 :          0 :                 ret = -EINVAL;
     609                 :          0 :                 goto out;
     610                 :            :         }
     611                 :            : 
     612         [ #  # ]:          0 :         if (elen <= 0) {
     613                 :          0 :                 ret = -EINVAL;
     614                 :          0 :                 goto out;
     615                 :            :         }
     616                 :            : 
     617                 :          0 :         assoclen = sizeof(struct ip_esp_hdr);
     618                 :          0 :         seqhilen = 0;
     619                 :            : 
     620         [ #  # ]:          0 :         if (x->props.flags & XFRM_STATE_ESN) {
     621                 :          0 :                 seqhilen += sizeof(__be32);
     622                 :          0 :                 assoclen += seqhilen;
     623                 :            :         }
     624                 :            : 
     625         [ #  # ]:          0 :         if (!skb_cloned(skb)) {
     626         [ #  # ]:          0 :                 if (!skb_is_nonlinear(skb)) {
     627                 :          0 :                         nfrags = 1;
     628                 :            : 
     629                 :          0 :                         goto skip_cow;
     630         [ #  # ]:          0 :                 } else if (!skb_has_frag_list(skb)) {
     631                 :          0 :                         nfrags = skb_shinfo(skb)->nr_frags;
     632                 :          0 :                         nfrags++;
     633                 :            : 
     634                 :          0 :                         goto skip_cow;
     635                 :            :                 }
     636                 :            :         }
     637                 :            : 
     638                 :          0 :         nfrags = skb_cow_data(skb, 0, &trailer);
     639         [ #  # ]:          0 :         if (nfrags < 0) {
     640                 :          0 :                 ret = -EINVAL;
     641                 :          0 :                 goto out;
     642                 :            :         }
     643                 :            : 
     644                 :          0 : skip_cow:
     645                 :          0 :         ret = -ENOMEM;
     646                 :          0 :         tmp = esp_alloc_tmp(aead, nfrags, seqhilen);
     647         [ #  # ]:          0 :         if (!tmp)
     648                 :          0 :                 goto out;
     649                 :            : 
     650                 :          0 :         ESP_SKB_CB(skb)->tmp = tmp;
     651                 :          0 :         seqhi = esp_tmp_seqhi(tmp);
     652         [ #  # ]:          0 :         iv = esp_tmp_iv(aead, tmp, seqhilen);
     653                 :          0 :         req = esp_tmp_req(aead, iv);
     654                 :          0 :         sg = esp_req_sg(aead, req);
     655                 :            : 
     656                 :          0 :         esp_input_set_header(skb, seqhi);
     657                 :            : 
     658                 :          0 :         sg_init_table(sg, nfrags);
     659                 :          0 :         ret = skb_to_sgvec(skb, sg, 0, skb->len);
     660         [ #  # ]:          0 :         if (unlikely(ret < 0)) {
     661                 :          0 :                 kfree(tmp);
     662                 :          0 :                 goto out;
     663                 :            :         }
     664                 :            : 
     665                 :          0 :         skb->ip_summed = CHECKSUM_NONE;
     666                 :            : 
     667         [ #  # ]:          0 :         if ((x->props.flags & XFRM_STATE_ESN))
     668                 :          0 :                 aead_request_set_callback(req, 0, esp_input_done_esn, skb);
     669                 :            :         else
     670                 :          0 :                 aead_request_set_callback(req, 0, esp_input_done, skb);
     671                 :            : 
     672                 :          0 :         aead_request_set_crypt(req, sg, sg, elen + ivlen, iv);
     673                 :          0 :         aead_request_set_ad(req, assoclen);
     674                 :            : 
     675                 :          0 :         ret = crypto_aead_decrypt(req);
     676         [ #  # ]:          0 :         if (ret == -EINPROGRESS)
     677                 :          0 :                 goto out;
     678                 :            : 
     679         [ #  # ]:          0 :         if ((x->props.flags & XFRM_STATE_ESN))
     680                 :          0 :                 esp_input_restore_header(skb);
     681                 :            : 
     682                 :          0 :         ret = esp6_input_done2(skb, ret);
     683                 :            : 
     684                 :          0 : out:
     685                 :          0 :         return ret;
     686                 :            : }
     687                 :            : 
     688                 :          0 : static int esp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
     689                 :            :                     u8 type, u8 code, int offset, __be32 info)
     690                 :            : {
     691         [ #  # ]:          0 :         struct net *net = dev_net(skb->dev);
     692                 :          0 :         const struct ipv6hdr *iph = (const struct ipv6hdr *)skb->data;
     693                 :          0 :         struct ip_esp_hdr *esph = (struct ip_esp_hdr *)(skb->data + offset);
     694                 :          0 :         struct xfrm_state *x;
     695                 :            : 
     696                 :          0 :         if (type != ICMPV6_PKT_TOOBIG &&
     697         [ #  # ]:          0 :             type != NDISC_REDIRECT)
     698                 :            :                 return 0;
     699                 :            : 
     700                 :          0 :         x = xfrm_state_lookup(net, skb->mark, (const xfrm_address_t *)&iph->daddr,
     701                 :            :                               esph->spi, IPPROTO_ESP, AF_INET6);
     702         [ #  # ]:          0 :         if (!x)
     703                 :            :                 return 0;
     704                 :            : 
     705         [ #  # ]:          0 :         if (type == NDISC_REDIRECT)
     706                 :          0 :                 ip6_redirect(skb, net, skb->dev->ifindex, 0,
     707                 :            :                              sock_net_uid(net, NULL));
     708                 :            :         else
     709                 :          0 :                 ip6_update_pmtu(skb, net, info, 0, 0, sock_net_uid(net, NULL));
     710                 :          0 :         xfrm_state_put(x);
     711                 :            : 
     712                 :          0 :         return 0;
     713                 :            : }
     714                 :            : 
     715                 :          0 : static void esp6_destroy(struct xfrm_state *x)
     716                 :            : {
     717                 :          0 :         struct crypto_aead *aead = x->data;
     718                 :            : 
     719         [ #  # ]:          0 :         if (!aead)
     720                 :            :                 return;
     721                 :            : 
     722                 :          0 :         crypto_free_aead(aead);
     723                 :            : }
     724                 :            : 
     725                 :          0 : static int esp_init_aead(struct xfrm_state *x)
     726                 :            : {
     727                 :          0 :         char aead_name[CRYPTO_MAX_ALG_NAME];
     728                 :          0 :         struct crypto_aead *aead;
     729                 :          0 :         int err;
     730                 :            : 
     731                 :          0 :         err = -ENAMETOOLONG;
     732                 :          0 :         if (snprintf(aead_name, CRYPTO_MAX_ALG_NAME, "%s(%s)",
     733         [ #  # ]:          0 :                      x->geniv, x->aead->alg_name) >= CRYPTO_MAX_ALG_NAME)
     734                 :          0 :                 goto error;
     735                 :            : 
     736                 :          0 :         aead = crypto_alloc_aead(aead_name, 0, 0);
     737         [ #  # ]:          0 :         err = PTR_ERR(aead);
     738         [ #  # ]:          0 :         if (IS_ERR(aead))
     739                 :          0 :                 goto error;
     740                 :            : 
     741                 :          0 :         x->data = aead;
     742                 :            : 
     743                 :          0 :         err = crypto_aead_setkey(aead, x->aead->alg_key,
     744                 :          0 :                                  (x->aead->alg_key_len + 7) / 8);
     745         [ #  # ]:          0 :         if (err)
     746                 :          0 :                 goto error;
     747                 :            : 
     748                 :          0 :         err = crypto_aead_setauthsize(aead, x->aead->alg_icv_len / 8);
     749         [ #  # ]:          0 :         if (err)
     750                 :          0 :                 goto error;
     751                 :            : 
     752                 :          0 : error:
     753                 :          0 :         return err;
     754                 :            : }
     755                 :            : 
     756                 :          0 : static int esp_init_authenc(struct xfrm_state *x)
     757                 :            : {
     758                 :          0 :         struct crypto_aead *aead;
     759                 :          0 :         struct crypto_authenc_key_param *param;
     760                 :          0 :         struct rtattr *rta;
     761                 :          0 :         char *key;
     762                 :          0 :         char *p;
     763                 :          0 :         char authenc_name[CRYPTO_MAX_ALG_NAME];
     764                 :          0 :         unsigned int keylen;
     765                 :          0 :         int err;
     766                 :            : 
     767                 :          0 :         err = -EINVAL;
     768         [ #  # ]:          0 :         if (!x->ealg)
     769                 :          0 :                 goto error;
     770                 :            : 
     771                 :          0 :         err = -ENAMETOOLONG;
     772                 :            : 
     773         [ #  # ]:          0 :         if ((x->props.flags & XFRM_STATE_ESN)) {
     774   [ #  #  #  #  :          0 :                 if (snprintf(authenc_name, CRYPTO_MAX_ALG_NAME,
                   #  # ]
     775                 :            :                              "%s%sauthencesn(%s,%s)%s",
     776                 :            :                              x->geniv ?: "", x->geniv ? "(" : "",
     777                 :          0 :                              x->aalg ? x->aalg->alg_name : "digest_null",
     778         [ #  # ]:          0 :                              x->ealg->alg_name,
     779         [ #  # ]:          0 :                              x->geniv ? ")" : "") >= CRYPTO_MAX_ALG_NAME)
     780                 :          0 :                         goto error;
     781                 :            :         } else {
     782   [ #  #  #  #  :          0 :                 if (snprintf(authenc_name, CRYPTO_MAX_ALG_NAME,
                   #  # ]
     783                 :            :                              "%s%sauthenc(%s,%s)%s",
     784                 :            :                              x->geniv ?: "", x->geniv ? "(" : "",
     785                 :          0 :                              x->aalg ? x->aalg->alg_name : "digest_null",
     786         [ #  # ]:          0 :                              x->ealg->alg_name,
     787         [ #  # ]:          0 :                              x->geniv ? ")" : "") >= CRYPTO_MAX_ALG_NAME)
     788                 :          0 :                         goto error;
     789                 :            :         }
     790                 :            : 
     791                 :          0 :         aead = crypto_alloc_aead(authenc_name, 0, 0);
     792         [ #  # ]:          0 :         err = PTR_ERR(aead);
     793         [ #  # ]:          0 :         if (IS_ERR(aead))
     794                 :          0 :                 goto error;
     795                 :            : 
     796                 :          0 :         x->data = aead;
     797                 :            : 
     798         [ #  # ]:          0 :         keylen = (x->aalg ? (x->aalg->alg_key_len + 7) / 8 : 0) +
     799                 :          0 :                  (x->ealg->alg_key_len + 7) / 8 + RTA_SPACE(sizeof(*param));
     800                 :          0 :         err = -ENOMEM;
     801         [ #  # ]:          0 :         key = kmalloc(keylen, GFP_KERNEL);
     802         [ #  # ]:          0 :         if (!key)
     803                 :          0 :                 goto error;
     804                 :            : 
     805                 :          0 :         p = key;
     806                 :          0 :         rta = (void *)p;
     807                 :          0 :         rta->rta_type = CRYPTO_AUTHENC_KEYA_PARAM;
     808                 :          0 :         rta->rta_len = RTA_LENGTH(sizeof(*param));
     809                 :          0 :         param = RTA_DATA(rta);
     810                 :          0 :         p += RTA_SPACE(sizeof(*param));
     811                 :            : 
     812         [ #  # ]:          0 :         if (x->aalg) {
     813                 :          0 :                 struct xfrm_algo_desc *aalg_desc;
     814                 :            : 
     815                 :          0 :                 memcpy(p, x->aalg->alg_key, (x->aalg->alg_key_len + 7) / 8);
     816                 :          0 :                 p += (x->aalg->alg_key_len + 7) / 8;
     817                 :            : 
     818                 :          0 :                 aalg_desc = xfrm_aalg_get_byname(x->aalg->alg_name, 0);
     819         [ #  # ]:          0 :                 BUG_ON(!aalg_desc);
     820                 :            : 
     821                 :          0 :                 err = -EINVAL;
     822         [ #  # ]:          0 :                 if (aalg_desc->uinfo.auth.icv_fullbits / 8 !=
     823                 :            :                     crypto_aead_authsize(aead)) {
     824                 :          0 :                         pr_info("ESP: %s digestsize %u != %hu\n",
     825                 :            :                                 x->aalg->alg_name,
     826                 :            :                                 crypto_aead_authsize(aead),
     827                 :            :                                 aalg_desc->uinfo.auth.icv_fullbits / 8);
     828                 :          0 :                         goto free_key;
     829                 :            :                 }
     830                 :            : 
     831                 :          0 :                 err = crypto_aead_setauthsize(
     832                 :          0 :                         aead, x->aalg->alg_trunc_len / 8);
     833         [ #  # ]:          0 :                 if (err)
     834                 :          0 :                         goto free_key;
     835                 :            :         }
     836                 :            : 
     837                 :          0 :         param->enckeylen = cpu_to_be32((x->ealg->alg_key_len + 7) / 8);
     838                 :          0 :         memcpy(p, x->ealg->alg_key, (x->ealg->alg_key_len + 7) / 8);
     839                 :            : 
     840                 :          0 :         err = crypto_aead_setkey(aead, key, keylen);
     841                 :            : 
     842                 :          0 : free_key:
     843                 :          0 :         kfree(key);
     844                 :            : 
     845                 :          0 : error:
     846                 :          0 :         return err;
     847                 :            : }
     848                 :            : 
     849                 :          0 : static int esp6_init_state(struct xfrm_state *x)
     850                 :            : {
     851                 :          0 :         struct crypto_aead *aead;
     852                 :          0 :         u32 align;
     853                 :          0 :         int err;
     854                 :            : 
     855         [ #  # ]:          0 :         if (x->encap)
     856                 :            :                 return -EINVAL;
     857                 :            : 
     858                 :          0 :         x->data = NULL;
     859                 :            : 
     860         [ #  # ]:          0 :         if (x->aead)
     861                 :          0 :                 err = esp_init_aead(x);
     862                 :            :         else
     863                 :          0 :                 err = esp_init_authenc(x);
     864                 :            : 
     865         [ #  # ]:          0 :         if (err)
     866                 :          0 :                 goto error;
     867                 :            : 
     868                 :          0 :         aead = x->data;
     869                 :            : 
     870      [ #  #  # ]:          0 :         x->props.header_len = sizeof(struct ip_esp_hdr) +
     871                 :            :                               crypto_aead_ivsize(aead);
     872      [ #  #  # ]:          0 :         switch (x->props.mode) {
     873                 :          0 :         case XFRM_MODE_BEET:
     874         [ #  # ]:          0 :                 if (x->sel.family != AF_INET6)
     875                 :          0 :                         x->props.header_len += IPV4_BEET_PHMAXLEN +
     876                 :            :                                                (sizeof(struct ipv6hdr) - sizeof(struct iphdr));
     877                 :            :                 break;
     878                 :            :         default:
     879                 :            :         case XFRM_MODE_TRANSPORT:
     880                 :            :                 break;
     881                 :          0 :         case XFRM_MODE_TUNNEL:
     882                 :          0 :                 x->props.header_len += sizeof(struct ipv6hdr);
     883                 :          0 :                 break;
     884                 :            :         }
     885                 :            : 
     886                 :          0 :         align = ALIGN(crypto_aead_blocksize(aead), 4);
     887                 :          0 :         x->props.trailer_len = align + 1 + crypto_aead_authsize(aead);
     888                 :            : 
     889                 :            : error:
     890                 :            :         return err;
     891                 :            : }
     892                 :            : 
     893                 :          0 : static int esp6_rcv_cb(struct sk_buff *skb, int err)
     894                 :            : {
     895                 :          0 :         return 0;
     896                 :            : }
     897                 :            : 
     898                 :            : static const struct xfrm_type esp6_type = {
     899                 :            :         .description    = "ESP6",
     900                 :            :         .owner          = THIS_MODULE,
     901                 :            :         .proto          = IPPROTO_ESP,
     902                 :            :         .flags          = XFRM_TYPE_REPLAY_PROT,
     903                 :            :         .init_state     = esp6_init_state,
     904                 :            :         .destructor     = esp6_destroy,
     905                 :            :         .input          = esp6_input,
     906                 :            :         .output         = esp6_output,
     907                 :            :         .hdr_offset     = xfrm6_find_1stfragopt,
     908                 :            : };
     909                 :            : 
     910                 :            : static struct xfrm6_protocol esp6_protocol = {
     911                 :            :         .handler        =       xfrm6_rcv,
     912                 :            :         .cb_handler     =       esp6_rcv_cb,
     913                 :            :         .err_handler    =       esp6_err,
     914                 :            :         .priority       =       0,
     915                 :            : };
     916                 :            : 
     917                 :         13 : static int __init esp6_init(void)
     918                 :            : {
     919         [ -  + ]:         13 :         if (xfrm_register_type(&esp6_type, AF_INET6) < 0) {
     920                 :          0 :                 pr_info("%s: can't add xfrm type\n", __func__);
     921                 :          0 :                 return -EAGAIN;
     922                 :            :         }
     923         [ -  + ]:         13 :         if (xfrm6_protocol_register(&esp6_protocol, IPPROTO_ESP) < 0) {
     924                 :          0 :                 pr_info("%s: can't add protocol\n", __func__);
     925                 :          0 :                 xfrm_unregister_type(&esp6_type, AF_INET6);
     926                 :          0 :                 return -EAGAIN;
     927                 :            :         }
     928                 :            : 
     929                 :            :         return 0;
     930                 :            : }
     931                 :            : 
     932                 :          0 : static void __exit esp6_fini(void)
     933                 :            : {
     934         [ #  # ]:          0 :         if (xfrm6_protocol_deregister(&esp6_protocol, IPPROTO_ESP) < 0)
     935                 :          0 :                 pr_info("%s: can't remove protocol\n", __func__);
     936                 :          0 :         xfrm_unregister_type(&esp6_type, AF_INET6);
     937                 :          0 : }
     938                 :            : 
     939                 :            : module_init(esp6_init);
     940                 :            : module_exit(esp6_fini);
     941                 :            : 
     942                 :            : MODULE_LICENSE("GPL");
     943                 :            : MODULE_ALIAS_XFRM_TYPE(AF_INET6, XFRM_PROTO_ESP);

Generated by: LCOV version 1.14