blob: 641c086ff54451db73202d2f0a0efdec83ab4d90 [file] [log] [blame]
// Copyright 2021 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//go:build !build_with_native_toolchain
// +build !build_with_native_toolchain
package filter
import (
"sync"
"gvisor.dev/gvisor/pkg/tcpip"
"gvisor.dev/gvisor/pkg/tcpip/header"
"gvisor.dev/gvisor/pkg/tcpip/stack"
)
var _ stack.Matcher = (*filterDisabledNICMatcher)(nil)
// filterDisabledNICMatcher is a stack.Matcher that keeps track of which
// NICs have filtering disabled.
//
// All NICs are considered to have filtering disabled until explicitly
// enabled.
type filterDisabledNICMatcher struct {
mu struct {
sync.RWMutex
// nicNames are the NICs where the filter is enabled on.
nicNames map[string]tcpip.NICID
}
}
// Name implements stack.Matcher.
func (*filterDisabledNICMatcher) Name() string {
return "filterDisabledNICMatcher"
}
// Match implements stack.Matcher.
func (d *filterDisabledNICMatcher) Match(hook stack.Hook, _ *stack.PacketBuffer, inNicName, outNicName string) (matches bool, hotdrop bool) {
if inNicName != "" && d.nicDisabled(inNicName) {
return true, false
}
if outNicName != "" && d.nicDisabled(outNicName) {
return true, false
}
return false, false
}
func (d *filterDisabledNICMatcher) init() {
d.mu.Lock()
defer d.mu.Unlock()
d.mu.nicNames = make(map[string]tcpip.NICID)
}
func (d *filterDisabledNICMatcher) nicDisabled(name string) bool {
d.mu.RLock()
defer d.mu.RUnlock()
_, ok := d.mu.nicNames[name]
return !ok
}
// portMatcher matches port to some range.
type portMatcher struct {
start uint16
end uint16
}
func (m *portMatcher) match(port uint16) bool {
return port >= m.start && port <= m.end
}
func NewTCPSourcePortMatcher(start, end uint16) *TCPSourcePortMatcher {
return &TCPSourcePortMatcher{portMatcher: portMatcher{start, end}}
}
var _ stack.Matcher = (*TCPSourcePortMatcher)(nil)
// TCPSourcePortMatcher matches TCP packets and ports.
type TCPSourcePortMatcher struct {
portMatcher
}
// Name implements stack.Matcher.
func (*TCPSourcePortMatcher) Name() string {
return "TCPSourcePortMatcher"
}
// Match implements stack.Matcher.
func (m *TCPSourcePortMatcher) Match(_ stack.Hook, pkt *stack.PacketBuffer, _, _ string) (matches bool, hotdrop bool) {
tcp := header.TCP(pkt.TransportHeader().View())
if len(tcp) < header.TCPMinimumSize {
// Drop immediately as the packet is invalid.
return false, true
}
return m.portMatcher.match(tcp.SourcePort()), false
}
func NewTCPDestinationPortMatcher(start, end uint16) *TCPDestinationPortMatcher {
return &TCPDestinationPortMatcher{portMatcher: portMatcher{start, end}}
}
var _ stack.Matcher = (*TCPDestinationPortMatcher)(nil)
// TCPDestinationPortMatcher matches TCP packets and ports.
type TCPDestinationPortMatcher struct {
portMatcher
}
// Name implements stack.Matcher.
func (*TCPDestinationPortMatcher) Name() string {
return "TCPDestinationPortMatcher"
}
// Match implements stack.Matcher.
func (m *TCPDestinationPortMatcher) Match(_ stack.Hook, pkt *stack.PacketBuffer, _, _ string) (matches bool, hotdrop bool) {
tcp := header.TCP(pkt.TransportHeader().View())
if len(tcp) < header.TCPMinimumSize {
// Drop immediately as the packet is invalid.
return false, true
}
return m.portMatcher.match(tcp.DestinationPort()), false
}
func NewUDPSourcePortMatcher(start, end uint16) *UDPSourcePortMatcher {
return &UDPSourcePortMatcher{portMatcher: portMatcher{start, end}}
}
var _ stack.Matcher = (*UDPSourcePortMatcher)(nil)
// UDPSourcePortMatcher matches UDP packets and ports.
type UDPSourcePortMatcher struct {
portMatcher
}
// Name implements stack.Matcher.
func (*UDPSourcePortMatcher) Name() string {
return "UDPSourcePortMatcher"
}
// Match implements stack.Matcher.
func (m *UDPSourcePortMatcher) Match(_ stack.Hook, pkt *stack.PacketBuffer, _, _ string) (matches bool, hotdrop bool) {
udp := header.UDP(pkt.TransportHeader().View())
if len(udp) < header.UDPMinimumSize {
// Drop immediately as the packet is invalid.
return false, true
}
return m.portMatcher.match(udp.SourcePort()), false
}
func NewUDPDestinationPortMatcher(start, end uint16) *UDPDestinationPortMatcher {
return &UDPDestinationPortMatcher{portMatcher: portMatcher{start, end}}
}
var _ stack.Matcher = (*UDPDestinationPortMatcher)(nil)
// UDPDestinationPortMatcher matches UDP packets and ports.
type UDPDestinationPortMatcher struct {
portMatcher
}
// Name implements stack.Matcher.
func (*UDPDestinationPortMatcher) Name() string {
return "UDPDestinationPortMatcher"
}
// Match implements stack.Matcher.
func (m *UDPDestinationPortMatcher) Match(_ stack.Hook, pkt *stack.PacketBuffer, _, _ string) (matches bool, hotdrop bool) {
udp := header.UDP(pkt.TransportHeader().View())
if len(udp) < header.UDPMinimumSize {
// Drop immediately as the packet is invalid.
return false, true
}
return m.portMatcher.match(udp.DestinationPort()), false
}