blob: 1f073edb7eb0f16cef42e2105fedf968b3de458d [file] [log] [blame]
// Copyright 2019 The gVisor authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package iptables
import (
"github.com/google/netstack/tcpip/buffer"
)
// A Hook specifies one of the hooks built into the network stack.
//
// Userspace app Userspace app
// ^ |
// | v
// [Input] [Output]
// ^ |
// | v
// | routing
// | |
// | v
// ----->[Prerouting]----->routing----->[Forward]---------[Postrouting]----->
type Hook uint
// These values correspond to values in include/uapi/linux/netfilter.h.
const (
// Prerouting happens before a packet is routed to applications or to
// be forwarded.
Prerouting Hook = iota
// Input happens before a packet reaches an application.
Input
// Forward happens once it's decided that a packet should be forwarded
// to another host.
Forward
// Output happens after a packet is written by an application to be
// sent out.
Output
// Postrouting happens just before a packet goes out on the wire.
Postrouting
// The total number of hooks.
NumHooks
)
// A Verdict is returned by a rule's target to indicate how traversal of rules
// should (or should not) continue.
type Verdict int
const (
// Accept indicates the packet should continue traversing netstack as
// normal.
Accept Verdict = iota
// Drop inicates the packet should be dropped, stopping traversing
// netstack.
Drop
// Stolen indicates the packet was co-opted by the target and should
// stop traversing netstack.
Stolen
// Queue indicates the packet should be queued for userspace processing.
Queue
// Repeat indicates the packet should re-traverse the chains for the
// current hook.
Repeat
// None indicates no verdict was reached.
None
// Jump indicates a jump to another chain.
Jump
// Continue indicates that traversal should continue at the next rule.
Continue
// Return indicates that traversal should return to the calling chain.
Return
)
// IPTables holds all the tables for a netstack.
type IPTables struct {
// Tables maps table names to tables. User tables have arbitrary names.
Tables map[string]Table
// Priorities maps each hook to a list of table names. The order of the
// list is the order in which each table should be visited for that
// hook.
Priorities map[Hook][]string
}
// A Table defines a set of chains and hooks into the network stack. The
// currently supported tables are:
// * nat
// * mangle
type Table struct {
// BuiltinChains holds the un-deletable chains built into netstack. If
// a hook isn't present in the map, this table doesn't utilize that
// hook.
BuiltinChains map[Hook]Chain
// DefaultTargets holds a target for each hook that will be executed if
// chain traversal doesn't yield a verdict.
DefaultTargets map[Hook]Target
// UserChains holds user-defined chains for the keyed by name. Users
// can give their chains arbitrary names.
UserChains map[string]Chain
// Chains maps names to chains for both builtin and user-defined chains.
// Its entries point to Chains already either in BuiltinChains or
// UserChains, and its purpose is to make looking up tables by name
// fast.
Chains map[string]*Chain
// Metadata holds information about the Table that is useful to users
// of IPTables, but not to the netstack IPTables code itself.
metadata interface{}
}
// ValidHooks returns a bitmap of the builtin hooks for the given table.
func (table *Table) ValidHooks() uint32 {
hooks := uint32(0)
for hook, _ := range table.BuiltinChains {
hooks |= 1 << hook
}
return hooks
}
// Metadata returns the metadata object stored in table.
func (table *Table) Metadata() interface{} {
return table.metadata
}
// SetMetadata sets the metadata object stored in table.
func (table *Table) SetMetadata(metadata interface{}) {
table.metadata = metadata
}
// A Chain defines a list of rules for packet processing. When a packet
// traverses a chain, it is checked against each rule until either a rule
// returns a verdict or the chain ends.
//
// By convention, builtin chains end with a rule that matches everything and
// returns either Accept or Drop. User-defined chains end with Return. These
// aren't strictly necessary here, but the iptables tool writes tables this way.
type Chain struct {
// Name is the chain name.
Name string
// Rules is the list of rules to traverse.
Rules []Rule
}
// A Rule is a packet processing rule. It consists of two pieces. First it
// contains zero or more matchers, each of which is a specification of which
// packets this rule applies to. If there are no matchers in the rule, it
// applies to any packet.
type Rule struct {
// Matchers is the list of matchers for this rule.
Matchers []Matcher
// Target is the action to invoke if all the matchers match the packet.
Target Target
}
// A Matcher is the interface for matching packets.
type Matcher interface {
// Match returns whether the packet matches and whether the packet
// should be "hotdropped", i.e. dropped immediately. This is usually
// used for suspicious packets.
Match(hook Hook, packet buffer.VectorisedView, interfaceName string) (matches bool, hotdrop bool)
}
// A Target is the interface for taking an action for a packet.
type Target interface {
// Action takes an action on the packet and returns a verdict on how
// traversal should (or should not) continue. If the return value is
// Jump, it also returns the name of the chain to jump to.
Action(packet buffer.VectorisedView) (Verdict, string)
}