242 lines
6.2 KiB
Go
242 lines
6.2 KiB
Go
package cmd
|
|
|
|
import (
|
|
"fmt"
|
|
"net"
|
|
"regexp"
|
|
"strconv"
|
|
"strings"
|
|
"io/ioutil"
|
|
"golang.org/x/net/route"
|
|
)
|
|
|
|
var defaultRoute4 = [4]byte{0, 0, 0, 0}
|
|
var defaultRoute6 = [16]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
|
var local6 = [16]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}
|
|
|
|
func Inet4AddrToString(ip4 route.Inet4Addr) string {
|
|
return fmt.Sprintf("%v.%v.%v.%v", ip4.IP[0], ip4.IP[1], ip4.IP[2], ip4.IP[3])
|
|
}
|
|
|
|
func Inet6AddrToString(ip6 route.Inet6Addr) string {
|
|
return fmt.Sprintf("%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x",
|
|
ip6.IP[0], ip6.IP[1], ip6.IP[2], ip6.IP[3], ip6.IP[4], ip6.IP[5], ip6.IP[6], ip6.IP[7],
|
|
ip6.IP[8], ip6.IP[9], ip6.IP[10], ip6.IP[11], ip6.IP[12], ip6.IP[13], ip6.IP[14], ip6.IP[15])
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* Initialize default_interface, default_gatway4, default_gateway6
|
|
*****************************************************************************/
|
|
func (jh *JailHost) InitNetworkProperties() {
|
|
rib, _ := route.FetchRIB(0, route.RIBTypeRoute, 0)
|
|
messages, err := route.ParseRIB(route.RIBTypeRoute, rib)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
for _, message := range messages {
|
|
route_message := message.(*route.RouteMessage)
|
|
addresses := route_message.Addrs
|
|
card_index := route_message.Index
|
|
|
|
if addresses[0].Family() == 2 {
|
|
var destination4, gateway4 *route.Inet4Addr
|
|
ok := false
|
|
|
|
if destination4, ok = addresses[0].(*route.Inet4Addr); !ok {
|
|
continue
|
|
}
|
|
|
|
if gateway4, ok = addresses[1].(*route.Inet4Addr); !ok {
|
|
continue
|
|
}
|
|
|
|
if destination4 == nil || gateway4 == nil {
|
|
continue
|
|
}
|
|
|
|
if destination4.IP == defaultRoute4 {
|
|
card, _ := net.InterfaceByIndex(card_index)
|
|
//fmt.Printf("Default IPv4 gateway is %v on card %s\n", Inet4AddrToString(*gateway4), card.Name)
|
|
jh.default_interface = card.Name
|
|
jh.default_gateway4 = Inet4AddrToString(*gateway4)
|
|
}
|
|
} else if addresses[0].Family() == 28 {
|
|
var destination6, gateway6 *route.Inet6Addr
|
|
ok := false
|
|
|
|
if destination6, ok = addresses[0].(*route.Inet6Addr); !ok {
|
|
continue
|
|
}
|
|
|
|
if gateway6, ok = addresses[1].(*route.Inet6Addr); !ok {
|
|
continue
|
|
}
|
|
|
|
if destination6 == nil || gateway6 == nil {
|
|
continue
|
|
}
|
|
|
|
if destination6.IP == defaultRoute6 && gateway6.IP != local6 {
|
|
card, _ := net.InterfaceByIndex(card_index)
|
|
//fmt.Printf("Default IPv6 gateway is %v on card %s\n", Inet6AddrToString(*gateway6), card.Name)
|
|
jh.default_interface = card.Name
|
|
jh.default_gateway6 = Inet6AddrToString(*gateway6)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func (jh *JailHost) GetDefaultInterface() string {
|
|
if len(jh.default_interface) == 0 {
|
|
jh.InitNetworkProperties()
|
|
}
|
|
return jh.default_interface
|
|
}
|
|
|
|
func (jh *JailHost) GetDefaultGateway4() string {
|
|
if len(jh.default_gateway4) == 0 {
|
|
jh.InitNetworkProperties()
|
|
}
|
|
return jh.default_gateway4
|
|
}
|
|
|
|
func (jh *JailHost) GetDefaultGateway6() string {
|
|
if len(jh.default_gateway6) == 0 {
|
|
jh.InitNetworkProperties()
|
|
}
|
|
return jh.default_gateway6
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* Get all network interfaces
|
|
****************************************************************************/
|
|
func (jh *JailHost) GetInterfaces() ([]string, error) {
|
|
var names []string
|
|
|
|
interfaces, err := net.Interfaces()
|
|
if err != nil {
|
|
return names, fmt.Errorf("Error listing network interfaces: %v", err)
|
|
}
|
|
for _, n := range interfaces {
|
|
names = append(names, n.Name)
|
|
}
|
|
|
|
return names, nil
|
|
}
|
|
|
|
func (jh *JailHost) GetBridgeMTU(bridgeName string) (int, error) {
|
|
bridge, err := net.InterfaceByName(bridgeName)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
return bridge.MTU, nil
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* Get all IPv4 currently in use on host
|
|
****************************************************************************/
|
|
func getHostInUseIPv4() ([]string, error) {
|
|
var ips []string
|
|
|
|
re := regexp.MustCompile(ifconfigipv4re)
|
|
|
|
out, err := executeCommand("/sbin/ifconfig")
|
|
if err != nil {
|
|
return ips, fmt.Errorf("Error executing \"/sbin/ifconfig\": %s", err)
|
|
}
|
|
|
|
for _, line := range strings.Split(out, "\n") {
|
|
if re.MatchString(line) {
|
|
ips = append(ips, re.FindStringSubmatch(line)[1])
|
|
}
|
|
}
|
|
|
|
return ips, nil
|
|
}
|
|
|
|
func getHostname() (string, error) {
|
|
out, err := executeCommand("/bin/hostname")
|
|
if err != nil {
|
|
return "", fmt.Errorf("Error executing \"/bin/hostname\": %v", err)
|
|
}
|
|
|
|
return strings.Split(out, "\n")[0], nil
|
|
}
|
|
|
|
func getHostId() (string, error) {
|
|
var content []byte
|
|
var err error
|
|
// return empty string if file does not exist
|
|
if content, err = ioutil.ReadFile("/etc/hostid"); err != nil {
|
|
if strings.HasSuffix(err.Error(), "no such file or directory") {
|
|
return "", nil
|
|
}
|
|
return "", err
|
|
}
|
|
|
|
return strings.Split(string(content), "\n")[0], nil
|
|
}
|
|
|
|
func getArch() (string, error) {
|
|
out, err := executeCommand("/usr/bin/uname -p")
|
|
if err != nil {
|
|
return "", fmt.Errorf("Error executing \"/usr/bin/uname -p\": %v", err)
|
|
}
|
|
|
|
return strings.Split(out, "\n")[0], nil
|
|
}
|
|
|
|
func getFreeBSDVersion() (FreeBSDVersion, error) {
|
|
var version FreeBSDVersion
|
|
regex := `([0-9]{1,2})(\.)?([0-9]{1,2})?\-([^\-]*)(\-)?(p[0-9]{1,2})?`
|
|
|
|
re := regexp.MustCompile(regex)
|
|
|
|
out, err := executeCommand("/bin/freebsd-version")
|
|
if err != nil {
|
|
return version, fmt.Errorf("Error executing \"/bin/freebsd-version\": %v", err)
|
|
}
|
|
|
|
if re.MatchString(out) {
|
|
version.major, err = strconv.Atoi(re.FindStringSubmatch(out)[1])
|
|
if err != nil {
|
|
return version, err
|
|
}
|
|
version.minor, err = strconv.Atoi(re.FindStringSubmatch(out)[3])
|
|
if err != nil {
|
|
return version, err
|
|
}
|
|
version.flavor = strings.Trim(re.FindStringSubmatch(out)[4], "\n")
|
|
|
|
// Skip the 'p' starting patch level
|
|
if len(re.FindStringSubmatch(out)[6]) > 0 {
|
|
version.patchLevel, err = strconv.Atoi(re.FindStringSubmatch(out)[6][1:])
|
|
if err != nil {
|
|
return version, err
|
|
}
|
|
}
|
|
}
|
|
return version, nil
|
|
}
|
|
|
|
func NewJailHost() (JailHost, error) {
|
|
var jh JailHost
|
|
var err error
|
|
|
|
if jh.hostname, err = getHostname(); err != nil {
|
|
return jh, err
|
|
}
|
|
if jh.arch, err = getArch(); err != nil {
|
|
return jh, err
|
|
}
|
|
if jh.hostid, err = getHostId(); err != nil {
|
|
return jh, err
|
|
}
|
|
if jh.version, err = getFreeBSDVersion(); err != nil {
|
|
return jh, err
|
|
}
|
|
return jh, nil
|
|
}
|