Skip to content

Commit

Permalink
protocols package
Browse files Browse the repository at this point in the history
Signed-off-by: Elazar Gershuni <[email protected]>
  • Loading branch information
Elazar Gershuni authored and elazarg committed Mar 12, 2024
1 parent 414c1bf commit 8b01294
Show file tree
Hide file tree
Showing 3 changed files with 183 additions and 0 deletions.
20 changes: 20 additions & 0 deletions pkg/netp/common.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Copyright 2020- IBM Inc. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package netp

type Protocol interface {
// InverseDirection returns the response expected for a request made using this protocol
InverseDirection() Protocol
}

type AnyProtocol struct{}

func (t AnyProtocol) InverseDirection() Protocol { return AnyProtocol{} }

type ProtocolString string

const (
ProtocolStringTCP ProtocolString = "TCP"
ProtocolStringUDP ProtocolString = "UDP"
ProtocolStringICMP ProtocolString = "ICMP"
)
128 changes: 128 additions & 0 deletions pkg/netp/icmp.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
// Copyright 2020- IBM Inc. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package netp

import (
"fmt"
"log"
)

type ICMPTypeCode struct {
// ICMP type allowed.
Type int

// ICMP code allowed. If omitted, any code is allowed
Code *int
}

type ICMP struct {
typeCode *ICMPTypeCode
}

func NewICMP(typeCode *ICMPTypeCode) (ICMP, error) {
err := ValidateICMP(typeCode)
if err != nil {
return ICMP{}, err
}
return ICMP{typeCode: typeCode}, nil
}

func (t ICMP) ICMPTypeCode() *ICMPTypeCode {
if t.typeCode == nil {
return nil
}
if t.typeCode.Code == nil {
return t.typeCode
}
// avoid aliasing and mutation by someone else
code := *t.typeCode.Code
return &ICMPTypeCode{Type: t.typeCode.Type, Code: &code}
}

func (t ICMP) InverseDirection() Protocol {
if t.typeCode == nil {
return nil
}

if invType := inverseICMPType(t.typeCode.Type); invType != undefinedICMP {
return ICMP{typeCode: &ICMPTypeCode{Type: invType, Code: t.typeCode.Code}}
}
return nil
}

// Based on https://datatracker.ietf.org/doc/html/rfc792

const (
EchoReply = 0
DestinationUnreachable = 3
SourceQuench = 4
Redirect = 5
Echo = 8
TimeExceeded = 11
ParameterProblem = 12
Timestamp = 13
TimestampReply = 14
InformationRequest = 15
InformationReply = 16

undefinedICMP = -2
)

// inverseICMPType returns the reply type for request type and vice versa.
// When there is no inverse, returns undefinedICMP
func inverseICMPType(t int) int {
switch t {
case Echo:
return EchoReply
case EchoReply:
return Echo

case Timestamp:
return TimestampReply
case TimestampReply:
return Timestamp

case InformationRequest:
return InformationReply
case InformationReply:
return InformationRequest

case DestinationUnreachable, SourceQuench, Redirect, TimeExceeded, ParameterProblem:
return undefinedICMP
default:
log.Panicf("Impossible ICMP type: %v", t)
}
return undefinedICMP
}

//nolint:revive // magic numbers are fine here
func ValidateICMP(typeCode *ICMPTypeCode) error {
if typeCode == nil {
return nil
}
maxCodes := map[int]int{
EchoReply: 0,
DestinationUnreachable: 5,
SourceQuench: 0,
Redirect: 3,
Echo: 0,
TimeExceeded: 1,
ParameterProblem: 0,
Timestamp: 0,
TimestampReply: 0,
InformationRequest: 0,
InformationReply: 0,
}
maxCode, ok := maxCodes[typeCode.Type]
if !ok {
return fmt.Errorf("invalid ICMP type %v", typeCode.Type)
}
if *typeCode.Code > maxCode {
return fmt.Errorf("ICMP code %v is invalid for ICMP type %v", *typeCode.Code, typeCode.Type)
}
return nil
}

func (t ICMP) ProtocolString() ProtocolString {
return ProtocolStringICMP
}
35 changes: 35 additions & 0 deletions pkg/netp/tcpudp.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Copyright 2020- IBM Inc. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package netp

import "github.com/np-guard/models/pkg/interval"

const MinPort = 1
const MaxPort = 65535

type PortRangePair struct {
SrcPort interval.Interval
DstPort interval.Interval
}

type TCPUDP struct {
IsTCP bool
PortRangePair PortRangePair
}

func (t TCPUDP) InverseDirection() Protocol {
if !t.IsTCP {
return nil
}
return TCPUDP{
IsTCP: true,
PortRangePair: PortRangePair{SrcPort: t.PortRangePair.DstPort, DstPort: t.PortRangePair.SrcPort},
}
}

func (t TCPUDP) ProtocolString() ProtocolString {
if t.IsTCP {
return ProtocolStringTCP
}
return ProtocolStringUDP
}

0 comments on commit 8b01294

Please sign in to comment.