mirror of
https://github.com/siderolabs/talos.git
synced 2025-09-17 03:41:11 +02:00
Some via dependabot, some via go-mod-outdated. Signed-off-by: Andrey Smirnov <andrey.smirnov@talos-systems.com>
154 lines
3.4 KiB
Go
154 lines
3.4 KiB
Go
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
|
package kubespan
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"os"
|
|
|
|
"github.com/hashicorp/go-multierror"
|
|
"github.com/vishvananda/netlink"
|
|
"golang.org/x/sys/unix"
|
|
)
|
|
|
|
// RulesManager manages routing rules outside of controllers/resources scope.
|
|
//
|
|
// TODO: this might be refactored later to support routing rules in the native network resources.
|
|
type RulesManager interface {
|
|
Install() error
|
|
Cleanup() error
|
|
}
|
|
|
|
// NewRulesManager initializes new RulesManager.
|
|
func NewRulesManager(targetTable, internalMark int) RulesManager {
|
|
return &rulesManager{
|
|
TargetTable: targetTable,
|
|
InternalMark: internalMark,
|
|
}
|
|
}
|
|
|
|
type rulesManager struct {
|
|
TargetTable int
|
|
InternalMark int
|
|
}
|
|
|
|
// Install routing rules.
|
|
func (m *rulesManager) Install() error {
|
|
nc, err := netlink.NewHandle()
|
|
if err != nil {
|
|
return fmt.Errorf("failed to get netlink handle: %w", err)
|
|
}
|
|
|
|
defer nc.Close()
|
|
|
|
if err := nc.RuleAdd(&netlink.Rule{
|
|
Priority: nextRuleNumber(nc, unix.AF_INET),
|
|
Family: unix.AF_INET,
|
|
Table: m.TargetTable,
|
|
Mark: m.InternalMark,
|
|
Mask: -1,
|
|
Goto: -1,
|
|
Flow: -1,
|
|
SuppressIfgroup: -1,
|
|
SuppressPrefixlen: -1,
|
|
}); err != nil {
|
|
if !errors.Is(err, os.ErrExist) {
|
|
return fmt.Errorf("failed to add IPv4 table-mark rule: %w", err)
|
|
}
|
|
}
|
|
|
|
if err := nc.RuleAdd(&netlink.Rule{
|
|
Priority: nextRuleNumber(nc, unix.AF_INET6),
|
|
Family: unix.AF_INET6,
|
|
Table: m.TargetTable,
|
|
Mark: m.InternalMark,
|
|
Mask: -1,
|
|
Goto: -1,
|
|
Flow: -1,
|
|
SuppressIfgroup: -1,
|
|
SuppressPrefixlen: -1,
|
|
}); err != nil {
|
|
if !errors.Is(err, os.ErrExist) {
|
|
return fmt.Errorf("failed to add IPv6 table-mark rule: %w", err)
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (m *rulesManager) deleteRulesFamily(nc *netlink.Handle, family int) error {
|
|
var merr *multierror.Error
|
|
|
|
list, err := nc.RuleList(family)
|
|
if err != nil {
|
|
merr = multierror.Append(merr, fmt.Errorf("failed to get route rules: %w", err))
|
|
}
|
|
|
|
for _, r := range list {
|
|
if r.Table == m.TargetTable &&
|
|
r.Mark == m.InternalMark {
|
|
thisRule := r
|
|
|
|
if err := nc.RuleDel(&thisRule); err != nil {
|
|
if !errors.Is(err, os.ErrNotExist) {
|
|
merr = multierror.Append(merr, err)
|
|
}
|
|
}
|
|
|
|
break
|
|
}
|
|
}
|
|
|
|
return merr.ErrorOrNil()
|
|
}
|
|
|
|
// Cleanup the installed routing rules.
|
|
func (m *rulesManager) Cleanup() error {
|
|
var merr *multierror.Error
|
|
|
|
nc, err := netlink.NewHandle()
|
|
if err != nil {
|
|
return fmt.Errorf("failed to get netlink handle: %w", err)
|
|
}
|
|
|
|
defer nc.Close()
|
|
|
|
if err = m.deleteRulesFamily(nc, unix.AF_INET); err != nil {
|
|
merr = multierror.Append(merr, fmt.Errorf("failed to delete all IPv4 route rules: %w", err))
|
|
}
|
|
|
|
if err = m.deleteRulesFamily(nc, unix.AF_INET6); err != nil {
|
|
merr = multierror.Append(merr, fmt.Errorf("failed to delete all IPv6 route rules: %w", err))
|
|
}
|
|
|
|
return merr.ErrorOrNil()
|
|
}
|
|
|
|
func nextRuleNumber(nc *netlink.Handle, family int) int {
|
|
list, err := nc.RuleList(family)
|
|
if err != nil {
|
|
return 0
|
|
}
|
|
|
|
for i := 32500; i > 0; i-- {
|
|
var found bool
|
|
|
|
for _, r := range list {
|
|
if r.Priority == i {
|
|
found = true
|
|
|
|
break
|
|
}
|
|
}
|
|
|
|
if !found {
|
|
return i
|
|
}
|
|
}
|
|
|
|
return 0
|
|
}
|