LCOV - code coverage report
Current view: top level - bpfilter/cgen/matcher - icmp.c (source / functions) Coverage Total Hit
Test: coverage.lcov Lines: 88.2 % 34 30
Test Date: 2025-11-24 12:34:34 Functions: 100.0 % 4 4
Branches: 45.8 % 24 11

             Branch data     Line data    Source code
       1                 :             : /* SPDX-License-Identifier: GPL-2.0-only */
       2                 :             : /*
       3                 :             :  * Copyright (c) 2022 Meta Platforms, Inc. and affiliates.
       4                 :             :  */
       5                 :             : 
       6                 :             : #include <linux/bpf.h>
       7                 :             : #include <linux/bpf_common.h>
       8                 :             : #include <linux/icmp.h>
       9                 :             : #include <linux/icmpv6.h>
      10                 :             : #include <linux/in.h>
      11                 :             : 
      12                 :             : #include <errno.h>
      13                 :             : 
      14                 :             : #include <bpfilter/matcher.h>
      15                 :             : 
      16                 :             : #include "cgen/program.h"
      17                 :             : 
      18                 :         204 : static int _bf_matcher_generate_icmp_fields(struct bf_program *program,
      19                 :             :                                             const struct bf_matcher *matcher,
      20                 :             :                                             const size_t offset)
      21                 :             : {
      22                 :         204 :     const uint8_t value = *(uint8_t *)bf_matcher_payload(matcher);
      23                 :             : 
      24         [ -  + ]:         204 :     EMIT(program, BPF_LDX_MEM(BPF_B, BPF_REG_1, BPF_REG_6, offset));
      25                 :             : 
      26      [ +  +  - ]:         204 :     switch (bf_matcher_get_op(matcher)) {
      27                 :         104 :     case BF_MATCHER_EQ:
      28         [ -  + ]:         104 :         EMIT_FIXUP_JMP_NEXT_RULE(program,
      29                 :             :                                  BPF_JMP_IMM(BPF_JNE, BPF_REG_1, value, 0));
      30                 :         104 :         break;
      31                 :         100 :     case BF_MATCHER_NE:
      32         [ -  + ]:         100 :         EMIT_FIXUP_JMP_NEXT_RULE(program,
      33                 :             :                                  BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, value, 0));
      34                 :         100 :         break;
      35                 :           0 :     default:
      36         [ #  # ]:           0 :         return bf_err_r(-EINVAL, "unknown matcher operator '%s' (%d)",
      37                 :             :                         bf_matcher_op_to_str(bf_matcher_get_op(matcher)),
      38                 :             :                         bf_matcher_get_op(matcher));
      39                 :             :     }
      40                 :             : 
      41                 :             :     return 0;
      42                 :             : }
      43                 :             : 
      44                 :         100 : static int _bf_matcher_generate_icmp6_fields(struct bf_program *program,
      45                 :             :                                              const struct bf_matcher *matcher)
      46                 :             : {
      47                 :         100 :     size_t offset = bf_matcher_get_type(matcher) == BF_MATCHER_ICMPV6_TYPE ?
      48                 :         100 :                         offsetof(struct icmp6hdr, icmp6_type) :
      49                 :             :                         offsetof(struct icmp6hdr, icmp6_code);
      50                 :             : 
      51         [ -  + ]:         100 :     EMIT_FIXUP_JMP_NEXT_RULE(
      52                 :             :         program, BPF_JMP_IMM(BPF_JNE, BPF_REG_8, IPPROTO_ICMPV6, 0));
      53         [ -  + ]:         100 :     EMIT(program,
      54                 :             :          BPF_LDX_MEM(BPF_DW, BPF_REG_6, BPF_REG_10, BF_PROG_CTX_OFF(l4_hdr)));
      55                 :             : 
      56                 :         100 :     return _bf_matcher_generate_icmp_fields(program, matcher, offset);
      57                 :             : }
      58                 :             : 
      59                 :         104 : static int _bf_matcher_generate_icmp4_fields(struct bf_program *program,
      60                 :             :                                              const struct bf_matcher *matcher)
      61                 :             : {
      62                 :         104 :     size_t offset = bf_matcher_get_type(matcher) == BF_MATCHER_ICMP_TYPE ?
      63                 :         104 :                         offsetof(struct icmphdr, type) :
      64                 :             :                         offsetof(struct icmphdr, code);
      65                 :             : 
      66         [ -  + ]:         104 :     EMIT_FIXUP_JMP_NEXT_RULE(program,
      67                 :             :                              BPF_JMP_IMM(BPF_JNE, BPF_REG_8, IPPROTO_ICMP, 0));
      68         [ -  + ]:         104 :     EMIT(program,
      69                 :             :          BPF_LDX_MEM(BPF_DW, BPF_REG_6, BPF_REG_10, BF_PROG_CTX_OFF(l4_hdr)));
      70                 :             : 
      71                 :         104 :     return _bf_matcher_generate_icmp_fields(program, matcher, offset);
      72                 :             : }
      73                 :             : 
      74                 :         204 : int bf_matcher_generate_icmp(struct bf_program *program,
      75                 :             :                              const struct bf_matcher *matcher)
      76                 :             : {
      77                 :             :     int r;
      78                 :             : 
      79      [ +  +  - ]:         204 :     switch (bf_matcher_get_type(matcher)) {
      80                 :         104 :     case BF_MATCHER_ICMP_TYPE:
      81                 :             :     case BF_MATCHER_ICMP_CODE:
      82                 :         104 :         r = _bf_matcher_generate_icmp4_fields(program, matcher);
      83                 :         104 :         break;
      84                 :         100 :     case BF_MATCHER_ICMPV6_TYPE:
      85                 :             :     case BF_MATCHER_ICMPV6_CODE:
      86                 :         100 :         r = _bf_matcher_generate_icmp6_fields(program, matcher);
      87                 :         100 :         break;
      88                 :           0 :     default:
      89         [ #  # ]:           0 :         return bf_err_r(-EINVAL, "unknown matcher type %d",
      90                 :             :                         bf_matcher_get_type(matcher));
      91                 :             :     };
      92                 :             : 
      93                 :             :     return r;
      94                 :             : }
        

Generated by: LCOV version 2.0-1