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 }