diff --git a/.forgejo/workflows/prerelease.yml b/.forgejo/workflows/prerelease.yml index 0326071..42d3a75 100644 --- a/.forgejo/workflows/prerelease.yml +++ b/.forgejo/workflows/prerelease.yml @@ -32,7 +32,12 @@ jobs: matrix: goos: [linux] goarch: [amd64] - binaries: [db, metadata, metacli, agent] + binaries: + - db + - metadata + - metacli + - agent + - netns uses: ./.forgejo/workflows/build.yml with: tag: ${{ needs.set-release-target.outputs.release_cible }} diff --git a/cmd/netns/main.go b/cmd/netns/main.go new file mode 100644 index 0000000..e1729f7 --- /dev/null +++ b/cmd/netns/main.go @@ -0,0 +1,40 @@ +package main + +import ( + "flag" + "fmt" + "os" + + "git.g3e.fr/syonad/two/internal/netns" +) + +var ( + netns_name = flag.String("netns", "", "Network namespace à faire") + action = flag.String("action", "", "Action a faire") +) + +func main() { + flag.Parse() + + switch *action { + case "create": + err := netns.Create(*netns_name) + if err != nil { + fmt.Println(err) + } + case "delete": + err := netns.Delete(*netns_name) + if err != nil { + fmt.Println(err) + } + case "check": + if netns.Exist(*netns_name) { + fmt.Printf("netns %s exist\n", *netns_name) + } else { + fmt.Printf("netns %s do not exist\n", *netns_name) + } + default: + fmt.Printf("Available commande:\n - create\n - delete\n - check\n") + os.Exit(1) + } +} diff --git a/internal/netns/call.go b/internal/netns/call.go new file mode 100644 index 0000000..da326fd --- /dev/null +++ b/internal/netns/call.go @@ -0,0 +1,5 @@ +package netns + +func Call(name string, fn func() error) error { + return call(name, fn) +} diff --git a/internal/netns/call_linux.go b/internal/netns/call_linux.go new file mode 100644 index 0000000..b23ac19 --- /dev/null +++ b/internal/netns/call_linux.go @@ -0,0 +1,44 @@ +//go:build linux + +package netns + +import ( + "fmt" + "os" + "runtime" + + "golang.org/x/sys/unix" +) + +func call(name string, fn func() error) error { + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + // sauvegarde du netns courant + orig, err := os.Open("/proc/self/ns/net") + if err != nil { + return err + } + defer orig.Close() + + // entrer dans le netns cible + f, err := os.Open(fmt.Sprintf("/var/run/netns/%s", name)) + if err != nil { + return err + } + defer f.Close() + + if err := unix.Setns(int(f.Fd()), unix.CLONE_NEWNET); err != nil { + return err + } + + // exécuter la fonction dans le netns + err = fn() + + // toujours revenir au netns d'origine + if restoreErr := unix.Setns(int(orig.Fd()), unix.CLONE_NEWNET); restoreErr != nil { + return restoreErr + } + + return err +} diff --git a/internal/netns/call_other.go b/internal/netns/call_other.go new file mode 100644 index 0000000..14a8924 --- /dev/null +++ b/internal/netns/call_other.go @@ -0,0 +1,7 @@ +//go:build !linux + +package netns + +func call(name string, fn func() error) error { + return fn() +} diff --git a/internal/netns/create.go b/internal/netns/create.go new file mode 100644 index 0000000..d6ca305 --- /dev/null +++ b/internal/netns/create.go @@ -0,0 +1,5 @@ +package netns + +func Create(name string) error { + return create(name) +} diff --git a/internal/netns/create_linux.go b/internal/netns/create_linux.go new file mode 100644 index 0000000..8ee0afa --- /dev/null +++ b/internal/netns/create_linux.go @@ -0,0 +1,55 @@ +//go:build linux + +package netns + +import ( + "os" + + "golang.org/x/sys/unix" +) + +func create(name string) error { + base := "/var/run/netns" + path := base + "/" + name + + if err := os.MkdirAll(base, 0755); err != nil { + return err + } + + // fichier cible + f, err := os.Create(path) + if err != nil { + return err + } + f.Close() + + // sauvegarde du netns courant + orig, err := os.Open("/proc/self/ns/net") + if err != nil { + return err + } + defer orig.Close() + + // nouveau netns + if err := unix.Unshare(unix.CLONE_NEWNET); err != nil { + return err + } + + // bind mount du netns courant vers /var/run/netns/ + if err := unix.Mount( + "/proc/self/ns/net", + path, + "", + unix.MS_BIND, + "", + ); err != nil { + return err + } + + // revenir au netns original + if err := unix.Setns(int(orig.Fd()), unix.CLONE_NEWNET); err != nil { + return err + } + + return nil +} diff --git a/internal/netns/create_other.go b/internal/netns/create_other.go new file mode 100644 index 0000000..3c0fd66 --- /dev/null +++ b/internal/netns/create_other.go @@ -0,0 +1,5 @@ +//go:build !linux + +package netns + +func create(string) error { return nil } diff --git a/internal/netns/delete.go b/internal/netns/delete.go new file mode 100644 index 0000000..af0a585 --- /dev/null +++ b/internal/netns/delete.go @@ -0,0 +1,5 @@ +package netns + +func Delete(name string) error { + return delete(name) +} diff --git a/internal/netns/delete_linux.go b/internal/netns/delete_linux.go new file mode 100644 index 0000000..ac0af1f --- /dev/null +++ b/internal/netns/delete_linux.go @@ -0,0 +1,18 @@ +//go:build linux + +package netns + +import ( + "os" + + "golang.org/x/sys/unix" +) + +func delete(name string) error { + path := "/var/run/netns/" + name + + if err := unix.Unmount(path, unix.MNT_DETACH); err != nil { + return err + } + return os.Remove(path) +} diff --git a/internal/netns/delete_other.go b/internal/netns/delete_other.go new file mode 100644 index 0000000..186d355 --- /dev/null +++ b/internal/netns/delete_other.go @@ -0,0 +1,5 @@ +//go:build !linux + +package netns + +func delete(string) error { return nil } diff --git a/internal/netns/exist.go b/internal/netns/exist.go new file mode 100644 index 0000000..7783dd9 --- /dev/null +++ b/internal/netns/exist.go @@ -0,0 +1,14 @@ +package netns + +import ( + "os" +) + +func exist(name string) bool { + _, err := os.Stat("/var/run/netns/" + name) + return err == nil +} + +func Exist(name string) bool { + return exist(name) +}