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

     1  package acls
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"strconv"
     7  	"strings"
     8  
     9  	"go.aporeto.io/enforcerd/trireme-lib/policy"
    10  )
    11  
    12  // ErrNoMatch is error returned when no match is found.
    13  var ErrNoMatch = errors.New("No Match")
    14  
    15  // portAction captures the minimum and maximum ports for an action
    16  type portAction struct {
    17  	min     uint16
    18  	max     uint16
    19  	policy  *policy.FlowPolicy
    20  	nomatch bool
    21  }
    22  
    23  // portActionList is a list of Port Actions
    24  type portActionList []*portAction
    25  
    26  // newPortAction parses a port spec and creates the action
    27  func newPortAction(tcpport string, policy *policy.FlowPolicy, nomatch bool) (*portAction, error) {
    28  
    29  	p := &portAction{}
    30  	if strings.Contains(tcpport, ":") {
    31  		parts := strings.Split(tcpport, ":")
    32  		if len(parts) != 2 {
    33  			return nil, fmt.Errorf("invalid port: %s", tcpport)
    34  		}
    35  
    36  		port, err := strconv.Atoi(parts[0])
    37  		if err != nil {
    38  			return nil, err
    39  		}
    40  		p.min = uint16(port)
    41  
    42  		port, err = strconv.Atoi(parts[1])
    43  		if err != nil {
    44  			return nil, err
    45  		}
    46  		p.max = uint16(port)
    47  
    48  	} else {
    49  		port, err := strconv.Atoi(tcpport)
    50  		if err != nil {
    51  			return nil, err
    52  		}
    53  
    54  		p.min = uint16(port)
    55  		p.max = p.min
    56  	}
    57  
    58  	if p.min > p.max {
    59  		return nil, errors.New("min port is greater than max port")
    60  	}
    61  
    62  	p.policy = policy
    63  	p.nomatch = nomatch
    64  
    65  	return p, nil
    66  }
    67  
    68  func (p *portActionList) lookup(port uint16, preReported *policy.FlowPolicy) (report *policy.FlowPolicy, packet *policy.FlowPolicy, err error) {
    69  
    70  	report = preReported
    71  
    72  	// Scan the ports - TODO: better algorithm needed here
    73  	for _, pa := range *p {
    74  		if port >= pa.min && port <= pa.max {
    75  
    76  			if pa.nomatch {
    77  				return report, packet, errNoMatchFromRule
    78  			}
    79  
    80  			// Check observed policies.
    81  			if pa.policy.ObserveAction.Observed() {
    82  				if report == nil {
    83  					report = pa.policy
    84  				}
    85  				if pa.policy.ObserveAction.ObserveContinue() {
    86  					continue
    87  				}
    88  				packet = pa.policy
    89  				return report, packet, nil
    90  			}
    91  
    92  			packet = pa.policy
    93  			if report == nil {
    94  				report = packet
    95  			}
    96  			return report, packet, nil
    97  		}
    98  	}
    99  
   100  	return report, packet, ErrNoMatch
   101  }