Coverage Report

Created: 2025-12-31 06:41

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/lldpd/src/daemon/pattern.c
Line
Count
Source
1
/* -*- mode: c; c-file-style: "openbsd" -*- */
2
/*
3
 * Copyright (c) 2008 Vincent Bernat <bernat@luffy.cx>
4
 *
5
 * Permission to use, copy, modify, and/or distribute this software for any
6
 * purpose with or without fee is hereby granted, provided that the above
7
 * copyright notice and this permission notice appear in all copies.
8
 *
9
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16
 */
17
18
#include "lldpd.h"
19
20
#include <string.h>
21
#include <fnmatch.h>
22
23
/**
24
 * Match a list of patterns.
25
 *
26
 * @param string   String to match against the list of patterns
27
 * @param patterns List of comma separated patterns. A pattern may
28
 *                 begin by `!` to negate it. In this case, it is
29
 *                 denied. A pattern may begin with `!!`. In this
30
 *                 case, it is allowed back. Each pattern will then be
31
 *                 matched against `fnmatch()` function.
32
 * @param found    Value to return if the pattern isn't found. Should be either
33
 *                 PATTERN_MATCH_ALLOWED or PATTERN_MACTH_DENIED.
34
 *
35
 * If a pattern is found matching and denied at the same time, it
36
 * will be denied. If it is both allowed and denied, it
37
 * will be allowed.
38
 *
39
 * @return PATTERN_MATCH_DENIED if the string matches a denied pattern which is not
40
 *         allowed or if the pattern wasn't found and `found` was set to
41
 *         PATTERN_MATCH_DENIED. Otherwise, return PATTERN_MATCH_ALLOWED unless the
42
 *         interface match is exact, in this case return PATTERN_MATCH_ALLOWED_EXACT.
43
 */
44
enum pattern_match_result
45
pattern_match(char *string, char *patterns, int found)
46
0
{
47
0
  char *pattern;
48
0
  int denied = 0;
49
0
  found = found ? PATTERN_MATCH_ALLOWED : PATTERN_MATCH_DENIED;
50
51
0
  if ((patterns = strdup(patterns)) == NULL) {
52
0
    log_warnx("interfaces", "unable to allocate memory");
53
0
    return PATTERN_MATCH_DENIED;
54
0
  }
55
56
0
  for (pattern = strtok(patterns, ","); pattern != NULL;
57
0
       pattern = strtok(NULL, ",")) {
58
0
    if ((pattern[0] == '!') && (pattern[1] == '!') &&
59
0
        (fnmatch(pattern + 2, string, 0) == 0)) {
60
      /* Allowed. No need to search further. */
61
0
      found = (strcmp(pattern + 2, string)) ?
62
0
          PATTERN_MATCH_ALLOWED :
63
0
          PATTERN_MATCH_ALLOWED_EXACT;
64
0
      break;
65
0
    }
66
0
    if ((pattern[0] == '!') && (fnmatch(pattern + 1, string, 0) == 0)) {
67
0
      denied = 1;
68
0
      found = PATTERN_MATCH_DENIED;
69
0
    } else if (!denied && fnmatch(pattern, string, 0) == 0) {
70
0
      if (!strcmp(pattern, string)) {
71
0
        found = PATTERN_MATCH_ALLOWED_EXACT;
72
0
      } else if (found < 2) {
73
0
        found = PATTERN_MATCH_ALLOWED;
74
0
      }
75
0
    }
76
0
  }
77
78
0
  free(patterns);
79
0
  return found;
80
0
}