-
Notifications
You must be signed in to change notification settings - Fork 1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fixup! add metadata providers for azure, alicloud, ikoula and oracle …
…cloud infrastructure Signed-off-by: Steve Fan <29133953+stevefan1999-personal@users.noreply.github.com>
- Loading branch information
1 parent
7808cbc
commit e765469
Showing
324 changed files
with
104,954 additions
and
386 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
package main | ||
|
||
import ( | ||
"github.com/sirupsen/logrus" | ||
) | ||
|
||
// DHCPServerLocator locate DHCP servers | ||
type DHCPServerLocator interface { | ||
Probe() (possibleServers []string, err error) | ||
} | ||
|
||
// FindPossibleDHCPServers find possible dhcp servers | ||
func FindPossibleDHCPServers() (possibleDhcpServAddr []string, err error) { | ||
var locatorFacade interface{} | ||
|
||
state := "file" | ||
loop: | ||
for { | ||
switch state { | ||
case "file": | ||
logrus.WithField("method", "existing DHCP lease information"). | ||
Infof("checking DHCP servers") | ||
locatorFacade = &DHCPServerLeaseFileLocator{} | ||
state = "run" | ||
case "direct": | ||
logrus.WithField("method", "directly send DHCP packets"). | ||
Infof("checking DHCP servers") | ||
locatorFacade = &DHCPServerDirectLocator{} | ||
state = "run" | ||
case "run": | ||
if locator, ok := locatorFacade.(DHCPServerLocator); ok { | ||
possibleDhcpServAddr, err = locator.Probe() | ||
if err != nil { | ||
if _, ok := locatorFacade.(*DHCPServerLeaseFileLocator); ok { | ||
logrus.WithError(err). | ||
Warn("cannot find DHCP server") | ||
state = "direct" | ||
} else { | ||
state = "fail" | ||
} | ||
} else { | ||
state = "Success" | ||
} | ||
} else { | ||
state = "fail" | ||
} | ||
case "fail": | ||
logrus. | ||
Debug("unable to find DHCP servers with known methods") | ||
break loop | ||
case "Success": | ||
logrus.WithField("servers", possibleDhcpServAddr). | ||
Debugf("found DHCP servers") | ||
break loop | ||
} | ||
} | ||
return | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
package main | ||
|
||
import ( | ||
"net" | ||
"regexp" | ||
"sync" | ||
"time" | ||
|
||
"github.com/digineo/go-dhclient" | ||
"github.com/sirupsen/logrus" | ||
"github.com/thoas/go-funk" | ||
) | ||
|
||
// DHCPServerDirectLocator This is an extreme method of trying to find a DHCP server by sending DHCP packets directly | ||
type DHCPServerDirectLocator struct { | ||
|
||
} | ||
|
||
// ethernetInterfaceNamesRegex a simple regex to determine ethernet interfaces | ||
// example: eth0, eth1, enps1p4 | ||
var ethernetInterfaceNamesRegex = regexp.MustCompile(`eth\d+|enp\d+s\d+`) | ||
|
||
// Probe find DHCP servers | ||
func (d *DHCPServerDirectLocator) Probe() (possibleAddresses []string, err error) { | ||
defer func() { | ||
if err == nil { | ||
possibleAddresses = funk.UniqString(possibleAddresses) | ||
} | ||
}() | ||
|
||
var ifaces []net.Interface | ||
ifaces, err = net.Interfaces() | ||
if err != nil { | ||
return | ||
} | ||
ifaces = funk.Filter(ifaces, func (p net.Interface) bool { | ||
return ethernetInterfaceNamesRegex.MatchString(p.Name) | ||
}).([]net.Interface) | ||
|
||
var wg sync.WaitGroup | ||
for _, iface := range ifaces { | ||
wg.Add(1) | ||
go func(wg *sync.WaitGroup, iface *net.Interface) { | ||
logrus.Debugf("starting DHCP broadcast on interface %s...", iface.Name) | ||
|
||
var client dhclient.Client | ||
client = dhclient.Client{Iface: iface, OnBound: func(lease *dhclient.Lease) { | ||
// I think this could potentially panic here because what if the wait group instead timing out? | ||
// then the method exits and GC kicks in causing the possibleAddresses array to be in undefined state/garbage value | ||
// i.e. UAF, but anyway this is just a small utility and panicking is acceptable, | ||
// and using select to handle these situations by gracefully stopping all spawned goroutines would probably be nicer | ||
possibleAddresses = append(possibleAddresses, lease.ServerID.String()) | ||
go client.Stop() | ||
wg.Done() | ||
}} | ||
client.Start() | ||
}(&wg, &iface) | ||
} | ||
|
||
// either wait group finishes or time out after 30 seconds | ||
waitTimeout(&wg, 30*time.Second) | ||
return | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
package main | ||
|
||
import ( | ||
"path/filepath" | ||
"regexp" | ||
|
||
"github.com/thoas/go-funk" | ||
) | ||
|
||
// DHCPServerLeaseFileLocator Find dhcp server by looking up the lease file generated. | ||
// This implies the existence of dhclient | ||
type DHCPServerLeaseFileLocator struct { | ||
|
||
} | ||
|
||
const ( | ||
// DHCPDirsPattern This is to match dhcp and dhcp3 and various many others | ||
DHCPDirsPattern = "/var/lib/dhcp*/*.leases" | ||
) | ||
|
||
// DHCPServerRegex I do not care about whether the IP address is correct, rather I assumed the DHCP client | ||
// will always produce and validate the DHCP server to be in octet range | ||
// IP address example: 127.10.0.1 | ||
var DHCPServerRegex = regexp.MustCompile(`option[ \t]+dhcp-server-identifier[ \t]+((?:[0-9]{1,3}\.){3}[0-9]{1,3});?`) | ||
|
||
// Probe Guesses possible DHCP server addresses | ||
// Used here to figure out the metadata service server | ||
func (d *DHCPServerLeaseFileLocator) Probe() (possibleAddresses []string, err error) { | ||
// i actually wanted set data structure in golang...and golang team said barely anybody use it so nope | ||
// f*ck it, i roll my own. ken thompson why would you make such a stupid mistake? | ||
defer func() { | ||
if err == nil { | ||
possibleAddresses = funk.UniqString(possibleAddresses) | ||
} | ||
}() | ||
|
||
var matches []string | ||
// error or no match | ||
if matches, err = filepath.Glob(DHCPDirsPattern); err != nil || len(matches) < 1 { | ||
return | ||
} | ||
|
||
for _, value := range matches { | ||
// fail fast if there's an error already | ||
if err != nil { | ||
return | ||
} | ||
func() { | ||
var file MemoryMappedFile | ||
if file, err = OpenMemoryMappedFile(value); err != nil { | ||
return | ||
} | ||
defer func() { | ||
if err = file.Close(); err != nil { | ||
return | ||
} | ||
}() | ||
|
||
// submatch 0 is the matched expression source | ||
// so starting from submatch 1 it will be the capture groups...at least 2 elements | ||
if submatches := DHCPServerRegex.FindSubmatch(*file.data); len(submatches) > 1 { | ||
possibleAddresses = funk.Map(funk.Tail(submatches), func(submatch []byte) string { | ||
return string(submatch) | ||
}).([]string) | ||
} | ||
}() | ||
} | ||
return | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
package main | ||
|
||
import ( | ||
"os" | ||
"syscall" | ||
) | ||
|
||
// MemoryMappedFile A file and its mapped memory. Linux exclusive | ||
type MemoryMappedFile struct { | ||
file *os.File | ||
data *[]byte | ||
} | ||
|
||
// OpenMemoryMappedFile opens a file and mmap it | ||
func OpenMemoryMappedFile(path string) (mmf MemoryMappedFile, err error) { | ||
var ( | ||
stat os.FileInfo | ||
data []byte | ||
) | ||
// can't really use := because name shadowing | ||
if mmf.file, err = os.Open(path); err != nil { | ||
return | ||
} | ||
if stat, err = mmf.file.Stat(); err != nil { | ||
return | ||
} | ||
// since we work on linux exclusive platform this is fine | ||
if data, err = syscall.Mmap(int(mmf.file.Fd()), 0, int(stat.Size()), syscall.PROT_READ, syscall.MAP_SHARED); err != nil { | ||
return | ||
} | ||
mmf.data = &data | ||
return | ||
} | ||
|
||
// Close munmap the mmap'd buffer if the file has opened before and then close the file | ||
func (m *MemoryMappedFile) Close() (err error) { | ||
if m.file != nil { | ||
if m.data != nil { | ||
err = syscall.Munmap(*m.data) | ||
m.data = nil | ||
} | ||
if err == nil { | ||
err = m.file.Close() | ||
m.file = nil | ||
} | ||
} | ||
return | ||
} | ||
|
||
|
Oops, something went wrong.