| // 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. |
| |
| // +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 |
| } |