-
Notifications
You must be signed in to change notification settings - Fork 0
/
netnsref.go
65 lines (60 loc) · 1.58 KB
/
netnsref.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
// (c) Siemens AG 2023
//
// SPDX-License-Identifier: MIT
// Turns Linux kernel network namespace identifiers into filesystem references.
package main
import (
"fmt"
"io/ioutil"
"os"
"syscall"
"unicode"
log "github.com/sirupsen/logrus"
"github.com/thediveo/go-mntinfo"
)
// netnsPath returns a filesystem reference to the network namespace in question.
// It searches both the processes as well as bindmount'ed network namespaces...
func netnsPath(netns uint64) string {
// First search in processes for a suitable netns filesystem reference...
procpids, err := ioutil.ReadDir("/proc")
if err == nil {
for _, procpid := range procpids {
// Skip all non-process entries and aliases in /proc.
if r := rune(procpid.Name()[0]); !procpid.IsDir() || !unicode.IsDigit(r) {
continue
}
// See which network namespace this process is in -- ignoring
// the fact that individual threads might be elsewhere...
ref := fmt.Sprintf("/proc/%s/ns/net", procpid.Name())
finfo, err := os.Stat(ref)
if err != nil {
continue
}
stat, ok := finfo.Sys().(*syscall.Stat_t)
if !ok {
continue
}
if stat.Ino == netns {
return ref
}
}
} else {
log.Errorf("/proc failed: %s", err.Error())
}
// Then search bindmount'ed network namespaces for a match...
for _, mount := range mntinfo.MountsOfType(-1, "nsfs") {
finfo, err := os.Stat(mount.MountPoint)
if err != nil {
continue
}
stat, ok := finfo.Sys().(*syscall.Stat_t)
if !ok {
continue
}
if stat.Ino == netns {
return mount.MountPoint
}
}
// Nope. Fail. Nothing found here.
return ""
}