Skip to content

Commit

Permalink
compile client under freebsd (#1620)
Browse files Browse the repository at this point in the history
Compile netbird client under freebsd and now support netstack and userspace modes.
Refactoring linux specific code to share same code with FreeBSD, move to *_unix.go files.

Not implemented yet:

Kernel mode not supported
DNS probably does not work yet
Routing also probably does not work yet
SSH support did not tested yet
Lack of test environment for freebsd (dedicated VM for github runners under FreeBSD required)
Lack of tests for freebsd specific code
info reporting need to review and also implement, for example OS reported as GENERIC instead of FreeBSD (lack of FreeBSD icon in management interface)
Lack of proper client setup under FreeBSD
Lack of FreeBSD port/package
  • Loading branch information
skillcoder authored and pascal-fischer committed May 31, 2024
1 parent 521f7dd commit 4526f33
Show file tree
Hide file tree
Showing 44 changed files with 810 additions and 145 deletions.
6 changes: 6 additions & 0 deletions client/internal/dns/consts_freebsd.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package dns

const (
fileUncleanShutdownResolvConfLocation = "/var/db/netbird/resolv.conf"
fileUncleanShutdownManagerTypeLocation = "/var/db/netbird/manager"
)
8 changes: 8 additions & 0 deletions client/internal/dns/consts_linux.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
//go:build !android

package dns

const (
fileUncleanShutdownResolvConfLocation = "/var/lib/netbird/resolv.conf"
fileUncleanShutdownManagerTypeLocation = "/var/lib/netbird/manager"
)
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//go:build !android
//go:build (linux && !android) || freebsd

package dns

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//go:build !android
//go:build (linux && !android) || freebsd

package dns

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//go:build !android
//go:build (linux && !android) || freebsd

package dns

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//go:build !android
//go:build (linux && !android) || freebsd

package dns

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//go:build !android
//go:build (linux && !android) || freebsd

package dns

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//go:build !android
//go:build (linux && !android) || freebsd

package dns

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//go:build !android
//go:build (linux && !android) || freebsd

package dns

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//go:build !android
//go:build (linux && !android) || freebsd

package dns

Expand Down Expand Up @@ -108,24 +108,18 @@ func getOSDNSManagerType() (osManagerType, error) {
if strings.Contains(text, "NetworkManager") && isDbusListenerRunning(networkManagerDest, networkManagerDbusObjectNode) && isNetworkManagerSupported() {
return networkManager, nil
}
if strings.Contains(text, "systemd-resolved") && isDbusListenerRunning(systemdResolvedDest, systemdDbusObjectNode) {
if strings.Contains(text, "systemd-resolved") && isSystemdResolvedRunning() {
if checkStub() {
return systemdManager, nil
} else {
return fileManager, nil
}
}
if strings.Contains(text, "resolvconf") {
if isDbusListenerRunning(systemdResolvedDest, systemdDbusObjectNode) {
var value string
err = getSystemdDbusProperty(systemdDbusResolvConfModeProperty, &value)
if err == nil {
if value == systemdDbusResolvConfModeForeign {
return systemdManager, nil
}
}
log.Errorf("got an error while checking systemd resolv conf mode, error: %s", err)
if isSystemdResolveConfMode() {
return systemdManager, nil
}

return resolvConfManager, nil
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//go:build !android
//go:build (linux && !android) || freebsd

package dns

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//go:build !android
//go:build (linux && !android) || freebsd

package dns

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//go:build !android
//go:build (linux && !android) || freebsd

package dns

Expand Down
20 changes: 20 additions & 0 deletions client/internal/dns/systemd_freebsd.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package dns

import (
"errors"
"fmt"
)

var errNotImplemented = errors.New("not implemented")

func newSystemdDbusConfigurator(wgInterface string) (hostManager, error) {
return nil, fmt.Errorf("systemd dns management: %w on freebsd", errNotImplemented)
}

func isSystemdResolvedRunning() bool {
return false
}

func isSystemdResolveConfMode() bool {
return false
}
22 changes: 22 additions & 0 deletions client/internal/dns/systemd_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -242,3 +242,25 @@ func getSystemdDbusProperty(property string, store any) error {

return v.Store(store)
}

func isSystemdResolvedRunning() bool {
return isDbusListenerRunning(systemdResolvedDest, systemdDbusObjectNode)
}

func isSystemdResolveConfMode() bool {
if !isDbusListenerRunning(systemdResolvedDest, systemdDbusObjectNode) {
return false
}

var value string
if err := getSystemdDbusProperty(systemdDbusResolvConfModeProperty, &value); err != nil {
log.Errorf("got an error while checking systemd resolv conf mode, error: %s", err)
return false
}

if value == systemdDbusResolvConfModeForeign {
return true
}

return false
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//go:build !android
//go:build (linux && !android) || freebsd

package dns

Expand All @@ -14,11 +14,6 @@ import (
log "github.com/sirupsen/logrus"
)

const (
fileUncleanShutdownResolvConfLocation = "/var/lib/netbird/resolv.conf"
fileUncleanShutdownManagerTypeLocation = "/var/lib/netbird/manager"
)

func CheckUncleanShutdown(wgIface string) error {
if _, err := os.Stat(fileUncleanShutdownResolvConfLocation); err != nil {
if errors.Is(err, fs.ErrNotExist) {
Expand Down
4 changes: 2 additions & 2 deletions client/internal/engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -546,8 +546,8 @@ func (e *Engine) updateSSH(sshConf *mgmProto.SSHConfig) error {
} else {

if sshConf.GetSshEnabled() {
if runtime.GOOS == "windows" {
log.Warnf("running SSH server on Windows is not supported")
if runtime.GOOS == "windows" || runtime.GOOS == "freebsd" {
log.Warnf("running SSH server on %s is not supported", runtime.GOOS)
return nil
}
// start SSH server if it wasn't running
Expand Down
18 changes: 18 additions & 0 deletions client/internal/routemanager/routeflags_bsd.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//go:build darwin || dragonfly || netbsd || openbsd

package routemanager

import "syscall"

// filterRoutesByFlags - return true if need to ignore such route message because it consists specific flags.
func filterRoutesByFlags(routeMessageFlags int) bool {
if routeMessageFlags&syscall.RTF_UP == 0 {
return true
}

if routeMessageFlags&(syscall.RTF_REJECT|syscall.RTF_BLACKHOLE|syscall.RTF_WASCLONED) != 0 {
return true
}

return false
}
19 changes: 19 additions & 0 deletions client/internal/routemanager/routeflags_freebsd.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
//go:build: freebsd
package routemanager

import "syscall"

// filterRoutesByFlags - return true if need to ignore such route message because it consists specific flags.
func filterRoutesByFlags(routeMessageFlags int) bool {
if routeMessageFlags&syscall.RTF_UP == 0 {
return true
}

// NOTE: syscall.RTF_WASCLONED deprecated in FreeBSD 8.0 (https://www.freebsd.org/releases/8.0R/relnotes-detailed/)
// a concept of cloned route (a route generated by an entry with RTF_CLONING flag) is deprecated.
if routeMessageFlags&(syscall.RTF_REJECT|syscall.RTF_BLACKHOLE) != 0 {
return true
}

return false
}
4 changes: 4 additions & 0 deletions client/internal/routemanager/systemops.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,10 @@ func GetNextHop(ip netip.Addr) (netip.Addr, *net.Interface, error) {

log.Debugf("Route for %s: interface %v nexthop %v, preferred source %v", ip, intf, gateway, preferredSrc)
if gateway == nil {
if runtime.GOOS == "freebsd" {
return netip.Addr{}, intf, nil
}

if preferredSrc == nil {
return netip.Addr{}, nil, ErrRouteNotFound
}
Expand Down
3 changes: 1 addition & 2 deletions client/internal/routemanager/systemops_bsd.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,7 @@ func getRoutesFromTable() ([]netip.Prefix, error) {
return nil, fmt.Errorf("unexpected RIB message type: %d", m.Type)
}

if m.Flags&syscall.RTF_UP == 0 ||
m.Flags&(syscall.RTF_REJECT|syscall.RTF_BLACKHOLE|syscall.RTF_WASCLONED) != 0 {
if filterRoutesByFlags(m.Flags) {
continue
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//go:build darwin && !ios
//go:build (darwin && !ios) || dragonfly || freebsd || netbsd || openbsd

package routemanager

Expand Down
10 changes: 10 additions & 0 deletions client/ssh/window_freebsd.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
//go:build freebsd

package ssh

import (
"os"
)

func setWinSize(file *os.File, width, height int) {
}
12 changes: 8 additions & 4 deletions client/system/info_freebsd.go
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
//go:build freebsd

package system

import (
"bytes"
"context"
"fmt"
"os"
"os/exec"
"runtime"
"strings"
"time"

log "github.com/sirupsen/logrus"

"github.com/netbirdio/netbird/client/system/detect_cloud"
"github.com/netbirdio/netbird/client/system/detect_platform"
"github.com/netbirdio/netbird/version"
Expand All @@ -22,8 +25,8 @@ func GetInfo(ctx context.Context) *Info {
out = _getInfo()
time.Sleep(500 * time.Millisecond)
}
osStr := strings.Replace(out, "\n", "", -1)
osStr = strings.Replace(osStr, "\r\n", "", -1)
osStr := strings.ReplaceAll(out, "\n", "")
osStr = strings.ReplaceAll(osStr, "\r\n", "")
osInfo := strings.Split(osStr, " ")

env := Environment{
Expand All @@ -50,7 +53,8 @@ func _getInfo() string {
cmd.Stderr = &stderr
err := cmd.Run()
if err != nil {
fmt.Println("getInfo:", err)
log.Warnf("getInfo: %s", err)
}

return out.String()
}
2 changes: 1 addition & 1 deletion client/ui/client_ui.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//go:build !(linux && 386)
//go:build !(linux && 386) && !freebsd

package main

Expand Down
8 changes: 8 additions & 0 deletions iface/freebsd/errors.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package freebsd

import "errors"

var (
ErrDoesNotExist = errors.New("does not exist")
ErrNameDoesNotMatch = errors.New("name does not match")
)
Loading

0 comments on commit 4526f33

Please sign in to comment.