Update dependencies
This commit is contained in:
154
vendor/tailscale.com/wgengine/wgcfg/writer.go
generated
vendored
Normal file
154
vendor/tailscale.com/wgengine/wgcfg/writer.go
generated
vendored
Normal file
@@ -0,0 +1,154 @@
|
||||
// Copyright (c) Tailscale Inc & AUTHORS
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
package wgcfg
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net/netip"
|
||||
"strconv"
|
||||
|
||||
"tailscale.com/types/key"
|
||||
"tailscale.com/types/logger"
|
||||
)
|
||||
|
||||
// ToUAPI writes cfg in UAPI format to w.
|
||||
// Prev is the previous device Config.
|
||||
//
|
||||
// Prev is required so that we can remove now-defunct peers without having to
|
||||
// remove and re-add all peers, and so that we can avoid writing information
|
||||
// about peers that have not changed since the previous time we wrote our
|
||||
// Config.
|
||||
func (cfg *Config) ToUAPI(logf logger.Logf, w io.Writer, prev *Config) error {
|
||||
var stickyErr error
|
||||
set := func(key, value string) {
|
||||
if stickyErr != nil {
|
||||
return
|
||||
}
|
||||
_, err := fmt.Fprintf(w, "%s=%s\n", key, value)
|
||||
if err != nil {
|
||||
stickyErr = err
|
||||
}
|
||||
}
|
||||
setUint16 := func(key string, value uint16) {
|
||||
set(key, strconv.FormatUint(uint64(value), 10))
|
||||
}
|
||||
setPeer := func(peer Peer) {
|
||||
set("public_key", peer.PublicKey.UntypedHexString())
|
||||
}
|
||||
|
||||
// Device config.
|
||||
if !prev.PrivateKey.Equal(cfg.PrivateKey) {
|
||||
set("private_key", cfg.PrivateKey.UntypedHexString())
|
||||
}
|
||||
|
||||
old := make(map[key.NodePublic]Peer)
|
||||
for _, p := range prev.Peers {
|
||||
old[p.PublicKey] = p
|
||||
}
|
||||
|
||||
// Add/configure all new peers.
|
||||
for _, p := range cfg.Peers {
|
||||
oldPeer, wasPresent := old[p.PublicKey]
|
||||
|
||||
// We only want to write the peer header/version if we're about
|
||||
// to change something about that peer, or if it's a new peer.
|
||||
// Figure out up-front whether we'll need to do anything for
|
||||
// this peer, and skip doing anything if not.
|
||||
//
|
||||
// If the peer was not present in the previous config, this
|
||||
// implies that this is a new peer; set all of these to 'true'
|
||||
// to ensure that we're writing the full peer configuration.
|
||||
willSetEndpoint := oldPeer.WGEndpoint != p.PublicKey || !wasPresent
|
||||
willChangeIPs := !cidrsEqual(oldPeer.AllowedIPs, p.AllowedIPs) || !wasPresent
|
||||
willChangeKeepalive := oldPeer.PersistentKeepalive != p.PersistentKeepalive // if not wasPresent, no need to redundantly set zero (default)
|
||||
|
||||
if !willSetEndpoint && !willChangeIPs && !willChangeKeepalive {
|
||||
// It's safe to skip doing anything here; wireguard-go
|
||||
// will not remove a peer if it's unspecified unless we
|
||||
// tell it to (which we do below if necessary).
|
||||
continue
|
||||
}
|
||||
|
||||
setPeer(p)
|
||||
set("protocol_version", "1")
|
||||
|
||||
// Avoid setting endpoints if the correct one is already known
|
||||
// to WireGuard, because doing so generates a bit more work in
|
||||
// calling magicsock's ParseEndpoint for effectively a no-op.
|
||||
if willSetEndpoint {
|
||||
if wasPresent {
|
||||
// We had an endpoint, and it was wrong.
|
||||
// By construction, this should not happen.
|
||||
// If it does, keep going so that we can recover from it,
|
||||
// but log so that we know about it,
|
||||
// because it is an indicator of other failed invariants.
|
||||
// See corp issue 3016.
|
||||
logf("[unexpected] endpoint changed from %s to %s", oldPeer.WGEndpoint, p.PublicKey)
|
||||
}
|
||||
set("endpoint", p.PublicKey.UntypedHexString())
|
||||
}
|
||||
|
||||
// TODO: replace_allowed_ips is expensive.
|
||||
// If p.AllowedIPs is a strict superset of oldPeer.AllowedIPs,
|
||||
// then skip replace_allowed_ips and instead add only
|
||||
// the new ipps with allowed_ip.
|
||||
if willChangeIPs {
|
||||
set("replace_allowed_ips", "true")
|
||||
for _, ipp := range p.AllowedIPs {
|
||||
set("allowed_ip", ipp.String())
|
||||
}
|
||||
}
|
||||
|
||||
// Set PersistentKeepalive after the peer is otherwise configured,
|
||||
// because it can trigger handshake packets.
|
||||
if willChangeKeepalive {
|
||||
setUint16("persistent_keepalive_interval", p.PersistentKeepalive)
|
||||
}
|
||||
}
|
||||
|
||||
// Remove peers that were present but should no longer be.
|
||||
for _, p := range cfg.Peers {
|
||||
delete(old, p.PublicKey)
|
||||
}
|
||||
for _, p := range old {
|
||||
setPeer(p)
|
||||
set("remove", "true")
|
||||
}
|
||||
|
||||
if stickyErr != nil {
|
||||
stickyErr = fmt.Errorf("ToUAPI: %w", stickyErr)
|
||||
}
|
||||
return stickyErr
|
||||
}
|
||||
|
||||
func cidrsEqual(x, y []netip.Prefix) bool {
|
||||
// TODO: re-implement using netaddr.IPSet.Equal.
|
||||
if len(x) != len(y) {
|
||||
return false
|
||||
}
|
||||
// First see if they're equal in order, without allocating.
|
||||
exact := true
|
||||
for i := range x {
|
||||
if x[i] != y[i] {
|
||||
exact = false
|
||||
break
|
||||
}
|
||||
}
|
||||
if exact {
|
||||
return true
|
||||
}
|
||||
|
||||
// Otherwise, see if they're the same, but out of order.
|
||||
m := make(map[netip.Prefix]bool)
|
||||
for _, v := range x {
|
||||
m[v] = true
|
||||
}
|
||||
for _, v := range y {
|
||||
if !m[v] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
Reference in New Issue
Block a user