2023-08-09 09:08:05 -05:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"log"
|
|
|
|
"math/rand"
|
|
|
|
"net"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/go-ping/ping"
|
2023-08-10 15:15:08 -05:00
|
|
|
|
2023-08-09 09:08:05 -05:00
|
|
|
"github.com/milosgajdos/tenus"
|
|
|
|
)
|
|
|
|
|
|
|
|
func init() {
|
|
|
|
|
|
|
|
ZoreideBridge.initializeHierarchy()
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2023-08-10 15:15:08 -05:00
|
|
|
func (b *AbstractBridge) RefreshArp() {
|
|
|
|
|
|
|
|
// we want the program to recover in case of issues
|
|
|
|
defer func() {
|
|
|
|
if r := recover(); r != nil {
|
|
|
|
|
|
|
|
fmt.Println("An error happened in <RefreshARP()>, but Zoreide recovered. ")
|
|
|
|
fmt.Println("Error was: ", r)
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
|
|
|
b.GArp = new(Gratuitous)
|
|
|
|
|
|
|
|
var err error
|
|
|
|
b.GArp.IP, _, err = net.ParseCIDR(b.BridgeIpCIDR)
|
|
|
|
if err != nil {
|
|
|
|
log.Println("Error parsing CIDR: ", err.Error())
|
|
|
|
}
|
|
|
|
b.GArp.IfaceName = b.ExistingInterface
|
|
|
|
log.Println("ARP Interface name: ", b.GArp.IfaceName)
|
|
|
|
|
|
|
|
SendGratuitous(b.GArp)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2023-08-09 09:08:05 -05:00
|
|
|
func (b *AbstractBridge) initializeHierarchy() {
|
|
|
|
|
2023-08-13 03:54:00 -05:00
|
|
|
b.hIerarchyNumber = rand.Int63()
|
|
|
|
log.Println("Initialized host number: ", b.hIerarchyNumber)
|
2023-08-09 09:08:05 -05:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
func (b *AbstractBridge) configureIpAndBridgeUp() {
|
|
|
|
// we want the program to recover in case of issues
|
|
|
|
defer func() {
|
|
|
|
if r := recover(); r != nil {
|
|
|
|
|
|
|
|
fmt.Println("An error happened in <configureIpAndBridgeUp()>, but Zoreide recovered. ")
|
|
|
|
fmt.Println("Error was: ", r)
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
|
|
|
// first we check the IP is free. Something weird could have happened in some
|
|
|
|
// other server
|
|
|
|
brIp, brIpNet, err := net.ParseCIDR(b.BridgeIpCIDR)
|
|
|
|
if err != nil {
|
2023-08-09 12:38:57 -05:00
|
|
|
log.Println("Error parsing CIDR: ", err.Error())
|
2023-08-09 09:08:05 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
br, err := tenus.NewLinkFrom(b.ExistingInterface)
|
|
|
|
if err != nil {
|
2023-08-09 12:38:57 -05:00
|
|
|
log.Println("Error creating Ethernet Alias: ", err.Error())
|
|
|
|
log.Println("Problematic interface: ", b.ExistingInterface)
|
2023-08-09 09:08:05 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
if err := br.SetLinkIp(brIp, brIpNet); err != nil {
|
2023-08-09 12:38:57 -05:00
|
|
|
log.Println("Error setting UP the IP: ", err.Error())
|
2023-08-10 14:09:17 -05:00
|
|
|
} else {
|
|
|
|
log.Printf("%s configured with %s\n", b.ExistingInterface, brIp.String())
|
2023-08-09 09:08:05 -05:00
|
|
|
}
|
|
|
|
|
2023-08-10 15:15:08 -05:00
|
|
|
// refresh ARP , should not be necessary, but we know, Cisco FA
|
|
|
|
b.RefreshArp()
|
2023-08-09 09:08:05 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
func (b *AbstractBridge) removeIPandBridgeInt() {
|
|
|
|
|
|
|
|
// we want the program to recover in case of issues
|
|
|
|
defer func() {
|
|
|
|
if r := recover(); r != nil {
|
|
|
|
|
|
|
|
fmt.Println("An error happened in <removeIPandBridgeInt()>, but Zoreide recovered. ")
|
|
|
|
fmt.Println("Error was: ", r)
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
|
|
|
br, err := tenus.NewLinkFrom(b.ExistingInterface)
|
|
|
|
if err != nil {
|
2023-08-09 12:38:57 -05:00
|
|
|
log.Println("Error creating Ethernet Handle: ", err.Error())
|
|
|
|
log.Println("Problematic interface: ", b.ExistingInterface)
|
|
|
|
|
2023-08-09 09:08:05 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
brIp, brIpNet, err := net.ParseCIDR(b.BridgeIpCIDR)
|
|
|
|
if err != nil {
|
2023-08-09 12:38:57 -05:00
|
|
|
log.Println("Error parsing CIDR: ", err.Error())
|
2023-08-09 09:08:05 -05:00
|
|
|
}
|
|
|
|
if err := br.UnsetLinkIp(brIp, brIpNet); err != nil {
|
2023-08-09 12:38:57 -05:00
|
|
|
log.Println("Error setting DOWN the IP: ", err.Error())
|
2023-08-09 09:08:05 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2023-08-14 04:52:07 -05:00
|
|
|
func (b *AbstractBridge) IsActive() bool {
|
|
|
|
|
|
|
|
defer func() {
|
|
|
|
if r := recover(); r != nil {
|
|
|
|
fmt.Println("An error happened in <WriteNumberToMulticast()>, but Zoreide recovered. ")
|
|
|
|
fmt.Println("Error was: ", r)
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
|
|
|
var bridgeip string
|
|
|
|
|
|
|
|
brIp, _, err := net.ParseCIDR(b.BridgeIpCIDR)
|
|
|
|
if err != nil {
|
|
|
|
log.Println("IsActive : problem parsing the IP/CIDR: ", err.Error())
|
|
|
|
} else {
|
|
|
|
bridgeip = brIp.String()
|
|
|
|
}
|
2023-08-09 09:08:05 -05:00
|
|
|
|
2023-08-10 14:09:17 -05:00
|
|
|
log.Println("Check for active IP: ", bridgeip)
|
|
|
|
|
2023-08-09 09:08:05 -05:00
|
|
|
pinger, err := ping.NewPinger(bridgeip)
|
|
|
|
if err != nil {
|
2023-08-14 04:52:07 -05:00
|
|
|
log.Println("Unable to ping address: ", bridgeip)
|
2023-08-09 09:08:05 -05:00
|
|
|
log.Println("Ping error: " + err.Error())
|
|
|
|
}
|
|
|
|
// just in case it doesn't stops alone
|
|
|
|
defer pinger.Stop()
|
2023-08-10 14:18:12 -05:00
|
|
|
pinger.Count = 5
|
|
|
|
pinger.Interval = time.Duration(10 * time.Millisecond)
|
2023-08-09 09:08:05 -05:00
|
|
|
pinger.Timeout = time.Duration(1 * time.Second)
|
|
|
|
pinger.Run() // blocks until finished
|
|
|
|
stats := pinger.Statistics()
|
2023-08-10 14:09:17 -05:00
|
|
|
log.Println("Ping results for: ", bridgeip)
|
2023-08-10 14:18:12 -05:00
|
|
|
log.Printf("%d packet sent, %d packet recv\n", pinger.Count, stats.PacketsRecv)
|
|
|
|
log.Println("IsACTIVE: ", stats.PacketsRecv == pinger.Count)
|
2023-08-09 09:08:05 -05:00
|
|
|
|
2023-08-10 14:09:17 -05:00
|
|
|
return stats.PacketsRecv == pinger.Count
|
2023-08-09 09:08:05 -05:00
|
|
|
|
|
|
|
}
|
2023-08-14 04:52:07 -05:00
|
|
|
|
|
|
|
func (b *AbstractBridge) IsAssigned() bool {
|
|
|
|
|
|
|
|
// we want the program to recover in case of issues
|
|
|
|
defer func() {
|
|
|
|
if r := recover(); r != nil {
|
|
|
|
|
|
|
|
fmt.Println("An error happened in <IsAssigned()>, but Zoreide recovered. ")
|
|
|
|
fmt.Println("Error was: ", r)
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
|
|
|
var (
|
|
|
|
ief *net.Interface
|
|
|
|
addrs []net.Addr
|
|
|
|
ipv4Addr net.IP
|
|
|
|
err error
|
|
|
|
bridgeip string
|
|
|
|
)
|
|
|
|
|
|
|
|
brIp, _, err := net.ParseCIDR(b.BridgeIpCIDR)
|
|
|
|
if err != nil {
|
|
|
|
log.Println("IsActive : problem parsing the IP/CIDR: ", err.Error())
|
|
|
|
return false
|
|
|
|
} else {
|
|
|
|
bridgeip = brIp.String()
|
|
|
|
}
|
|
|
|
|
|
|
|
interfaceName := b.ExistingInterface
|
|
|
|
|
|
|
|
if ief, err = net.InterfaceByName(interfaceName); err != nil { // get interface
|
|
|
|
log.Printf("Interface %s does not exist or not manageable\n", interfaceName)
|
|
|
|
log.Printf("Error is: %s\n", err.Error())
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
if addrs, err = ief.Addrs(); err != nil { // get addresses
|
|
|
|
log.Printf("Cannot read IPs of interface %s\n", interfaceName)
|
|
|
|
log.Printf("Error is: %s\n", err.Error())
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
for _, addr := range addrs { // get ipv4 address
|
|
|
|
if ipv4Addr = addr.(*net.IPNet).IP.To4(); ipv4Addr != nil {
|
|
|
|
log.Printf("Error reading IPs for interface %s\n", interfaceName)
|
|
|
|
log.Printf("Error is: %s\n", err.Error())
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if ipv4Addr == nil {
|
|
|
|
log.Printf("interface %s don't have an ipv4 address\n", interfaceName)
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, addr := range addrs {
|
|
|
|
if addr.String() == bridgeip {
|
|
|
|
log.Printf("Ip %s is assigned to interface %s", bridgeip, interfaceName)
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
log.Printf("Ip %s is NOT assigned to interface %s", bridgeip, interfaceName)
|
|
|
|
return false
|
|
|
|
}
|