github.com/aporeto-inc/trireme-lib@v10.358.0+incompatible/controller/internal/enforcer/acls/icmpacl.go (about)

     1  package acls
     2  
     3  import (
     4  	"net"
     5  	"strconv"
     6  	"strings"
     7  
     8  	"go.aporeto.io/enforcerd/trireme-lib/policy"
     9  )
    10  
    11  type icmpRule struct {
    12  	baseRule           string
    13  	listOfDisjunctives []string
    14  	policy             *policy.FlowPolicy
    15  }
    16  
    17  func (rule *icmpRule) match(icmpType, icmpCode int8) (*policy.FlowPolicy, bool) {
    18  
    19  	type evaluator func(int8) bool
    20  
    21  	processList := func(vs []string, f func(string) evaluator) []evaluator {
    22  		vals := make([]evaluator, len(vs))
    23  
    24  		for i, v := range vs {
    25  			vals[i] = f(v)
    26  		}
    27  
    28  		return vals
    29  	}
    30  
    31  	genCodes := func(val string) evaluator {
    32  
    33  		genCode := func(v string) evaluator {
    34  
    35  			switch splits := strings.Split(v, ":"); len(splits) {
    36  			case 1:
    37  				numVal, _ := strconv.Atoi(v)
    38  				return func(input int8) bool { return input == int8(numVal) }
    39  			default:
    40  				min := splits[0]
    41  				max := splits[1]
    42  
    43  				minVal, _ := strconv.Atoi(min)
    44  				maxVal, _ := strconv.Atoi(max)
    45  
    46  				return func(input int8) bool { return input >= int8(minVal) && input <= int8(maxVal) }
    47  			}
    48  		}
    49  
    50  		splits := strings.Split(val, ",")
    51  		vals := processList(splits, genCode)
    52  
    53  		return func(input int8) bool {
    54  			result := false
    55  			for _, v := range vals {
    56  				result = result || v(input)
    57  			}
    58  
    59  			return result
    60  		}
    61  	}
    62  
    63  	processSingleTypeCode := func(icmpTypeCode string) (evaluator, evaluator) {
    64  		splits := strings.Split(icmpTypeCode, "/")
    65  
    66  		var typeEval evaluator
    67  		var codeEval evaluator
    68  
    69  		typeEval = func(val int8) bool { return true }
    70  		codeEval = func(val int8) bool { return true }
    71  
    72  		for i, val := range splits {
    73  			switch i {
    74  			case 0:
    75  			case 1:
    76  				codeVal, _ := strconv.Atoi(val)
    77  				typeEval = func(input int8) bool { return input == int8(codeVal) }
    78  			case 2:
    79  				codeEval = genCodes(val)
    80  			}
    81  		}
    82  
    83  		return typeEval, codeEval
    84  	}
    85  
    86  	matches := func(icmpType, icmpCode int8, icmpTypeCode string) bool {
    87  		typeMatch, codeMatch := processSingleTypeCode(icmpTypeCode)
    88  		return typeMatch(icmpType) && codeMatch(icmpCode)
    89  	}
    90  
    91  	if !matches(icmpType, icmpCode, rule.baseRule) {
    92  		return rule.policy, false
    93  	}
    94  
    95  	action := true
    96  
    97  	for _, r := range rule.listOfDisjunctives {
    98  		action = false
    99  		if matches(icmpType, icmpCode, r) {
   100  			return rule.policy, true
   101  		}
   102  	}
   103  
   104  	return rule.policy, action
   105  }
   106  
   107  func (a *acl) matchICMPRule(ip net.IP, icmpType int8, icmpCode int8) (*policy.FlowPolicy, *policy.FlowPolicy, error) {
   108  
   109  	var report *policy.FlowPolicy
   110  	var match bool
   111  
   112  	lookup := func(val interface{}) bool {
   113  		if val != nil {
   114  			icmpRules := val.([]*icmpRule)
   115  			for _, icmpRule := range icmpRules {
   116  				report, match = icmpRule.match(icmpType, icmpCode)
   117  				if match {
   118  					return true
   119  				}
   120  			}
   121  			return false
   122  		}
   123  
   124  		return false
   125  	}
   126  
   127  	a.icmpCache.RunFuncOnLpmIP(ip, lookup)
   128  
   129  	if !match {
   130  		return nil, nil, errNotFound
   131  	}
   132  
   133  	return report, report, nil
   134  }