Release all ressources on shutdown
This commit is contained in:
parent
24189568b8
commit
338139ad0f
@ -39,6 +39,7 @@ func readConfig(dest string) {
|
|||||||
}
|
}
|
||||||
if strings.HasPrefix(line, "responder") {
|
if strings.HasPrefix(line, "responder") {
|
||||||
obj := configResponder{}
|
obj := configResponder{}
|
||||||
|
filter := ""
|
||||||
for {
|
for {
|
||||||
scanner.Scan()
|
scanner.Scan()
|
||||||
line = scanner.Text()
|
line = scanner.Text()
|
||||||
@ -46,9 +47,10 @@ func readConfig(dest string) {
|
|||||||
obj.Iface = strings.TrimSpace(strings.TrimPrefix(line, "iface"))
|
obj.Iface = strings.TrimSpace(strings.TrimPrefix(line, "iface"))
|
||||||
}
|
}
|
||||||
if strings.HasPrefix(line, "filter") {
|
if strings.HasPrefix(line, "filter") {
|
||||||
obj.Filter = strings.TrimSpace(strings.TrimPrefix(line, "filter"))
|
filter += strings.TrimSpace(strings.TrimPrefix(line, "filter")) + ";"
|
||||||
}
|
}
|
||||||
if strings.HasPrefix(line, "}") {
|
if strings.HasPrefix(line, "}") {
|
||||||
|
obj.Filter = filter
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
48
main.go
48
main.go
@ -6,28 +6,34 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
fmt.Println("PNDPD Version 0.3 by Kioubit")
|
fmt.Println("PNDPD Version 0.4 by Kioubit")
|
||||||
|
|
||||||
|
if len(os.Args) <= 2 {
|
||||||
|
printUsage()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
switch os.Args[1] {
|
||||||
|
case "respond":
|
||||||
|
if len(os.Args) == 4 {
|
||||||
|
go simpleRespond(os.Args[2], parseFilter(os.Args[3]))
|
||||||
|
} else {
|
||||||
|
go simpleRespond(os.Args[2], nil)
|
||||||
|
}
|
||||||
|
case "proxy":
|
||||||
|
go proxy(os.Args[2], os.Args[3])
|
||||||
|
case "readconfig":
|
||||||
|
readConfig(os.Args[2])
|
||||||
|
default:
|
||||||
|
printUsage()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
waitForSignal()
|
||||||
|
}
|
||||||
|
|
||||||
|
func printUsage() {
|
||||||
|
fmt.Println("Specify command")
|
||||||
fmt.Println("Usage: pndpd readconfig <path to file>")
|
fmt.Println("Usage: pndpd readconfig <path to file>")
|
||||||
fmt.Println("Usage: pndpd respond <interface> <optional whitelist of CIDRs separated with a semicolon>")
|
fmt.Println("Usage: pndpd respond <interface> <optional whitelist of CIDRs separated with a semicolon>")
|
||||||
fmt.Println("Usage: pndpd proxy <interface1> <interface2>")
|
fmt.Println("Usage: pndpd proxy <interface1> <interface2>")
|
||||||
|
|
||||||
if len(os.Args) <= 1 {
|
|
||||||
fmt.Println("Specify command")
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
if os.Args[1] == "respond" {
|
|
||||||
if len(os.Args) == 4 {
|
|
||||||
simpleRespond(os.Args[2], parseFilter(os.Args[3]))
|
|
||||||
} else {
|
|
||||||
simpleRespond(os.Args[2], nil)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if os.Args[1] == "proxy" {
|
|
||||||
proxy(os.Args[2], os.Args[3])
|
|
||||||
}
|
|
||||||
|
|
||||||
if os.Args[1] == "readConfig" {
|
|
||||||
readConfig(os.Args[2])
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
60
process.go
60
process.go
@ -5,28 +5,63 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
|
"runtime/pprof"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
var GlobalDebug = false
|
var GlobalDebug = false
|
||||||
|
|
||||||
|
// Items needed for graceful shutdown
|
||||||
|
var stop = make(chan struct{})
|
||||||
|
var stopWg sync.WaitGroup
|
||||||
|
var sigCh = make(chan os.Signal)
|
||||||
|
|
||||||
|
func waitForSignal() {
|
||||||
|
signal.Notify(sigCh, os.Interrupt, syscall.SIGTERM)
|
||||||
|
<-sigCh
|
||||||
|
fmt.Println("Shutting down...")
|
||||||
|
close(stop)
|
||||||
|
if wgWaitTimout(&stopWg, 10*time.Second) {
|
||||||
|
fmt.Println("Done")
|
||||||
|
} else {
|
||||||
|
fmt.Println("Aborting shutdown, since it is taking too long")
|
||||||
|
pprof.Lookup("goroutine").WriteTo(os.Stdout, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func wgWaitTimout(wg *sync.WaitGroup, timeout time.Duration) bool {
|
||||||
|
t := make(chan struct{})
|
||||||
|
go func() {
|
||||||
|
defer close(t)
|
||||||
|
wg.Wait()
|
||||||
|
}()
|
||||||
|
select {
|
||||||
|
case <-t:
|
||||||
|
return true
|
||||||
|
case <-time.After(timeout):
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func simpleRespond(iface string, filter []*net.IPNet) {
|
func simpleRespond(iface string, filter []*net.IPNet) {
|
||||||
|
defer stopWg.Done()
|
||||||
|
stopWg.Add(3) // This function, 2x goroutines
|
||||||
requests := make(chan *NDRequest, 100)
|
requests := make(chan *NDRequest, 100)
|
||||||
defer close(requests)
|
defer close(requests)
|
||||||
go respond(iface, requests, NDP_ADV, filter)
|
go respond(iface, requests, NDP_ADV, filter)
|
||||||
go listen(iface, requests, NDP_SOL)
|
go listen(iface, requests, NDP_SOL)
|
||||||
|
<-stop
|
||||||
sigCh := make(chan os.Signal)
|
|
||||||
signal.Notify(sigCh, os.Interrupt, syscall.SIGTERM)
|
|
||||||
select {
|
|
||||||
case <-sigCh:
|
|
||||||
fmt.Println("Exit")
|
|
||||||
os.Exit(0)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func proxy(iface1, iface2 string) {
|
func proxy(iface1, iface2 string) {
|
||||||
|
defer stopWg.Done()
|
||||||
|
stopWg.Add(9) // This function, 8x goroutines
|
||||||
|
|
||||||
req_iface1_sol_iface2 := make(chan *NDRequest, 100)
|
req_iface1_sol_iface2 := make(chan *NDRequest, 100)
|
||||||
defer close(req_iface1_sol_iface2)
|
defer close(req_iface1_sol_iface2)
|
||||||
go listen(iface1, req_iface1_sol_iface2, NDP_SOL)
|
go listen(iface1, req_iface1_sol_iface2, NDP_SOL)
|
||||||
@ -46,14 +81,7 @@ func proxy(iface1, iface2 string) {
|
|||||||
defer close(req_iface2_adv_iface1)
|
defer close(req_iface2_adv_iface1)
|
||||||
go listen(iface2, req_iface2_adv_iface1, NDP_ADV)
|
go listen(iface2, req_iface2_adv_iface1, NDP_ADV)
|
||||||
go respond(iface1, req_iface2_adv_iface1, NDP_ADV, nil)
|
go respond(iface1, req_iface2_adv_iface1, NDP_ADV, nil)
|
||||||
|
<-stop
|
||||||
sigCh := make(chan os.Signal)
|
|
||||||
signal.Notify(sigCh, os.Interrupt, syscall.SIGTERM)
|
|
||||||
select {
|
|
||||||
case <-sigCh:
|
|
||||||
fmt.Println("Exit")
|
|
||||||
os.Exit(0)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseFilter(f string) []*net.IPNet {
|
func parseFilter(f string) []*net.IPNet {
|
||||||
|
@ -41,7 +41,6 @@ func htons(v uint16) int {
|
|||||||
func htons16(v uint16) uint16 { return v<<8 | v>>8 }
|
func htons16(v uint16) uint16 { return v<<8 | v>>8 }
|
||||||
|
|
||||||
func listen(iface string, responder chan *NDRequest, requestType NDPType) {
|
func listen(iface string, responder chan *NDRequest, requestType NDPType) {
|
||||||
|
|
||||||
niface, err := net.InterfaceByName(iface)
|
niface, err := net.InterfaceByName(iface)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err.Error())
|
panic(err.Error())
|
||||||
@ -55,7 +54,11 @@ func listen(iface string, responder chan *NDRequest, requestType NDPType) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err.Error())
|
fmt.Println(err.Error())
|
||||||
}
|
}
|
||||||
defer syscall.Close(fd)
|
go func() {
|
||||||
|
<-stop
|
||||||
|
syscall.Close(fd)
|
||||||
|
stopWg.Done() // syscall.read does not release when the file descriptor is closed
|
||||||
|
}()
|
||||||
fmt.Println("Obtained fd ", fd)
|
fmt.Println("Obtained fd ", fd)
|
||||||
|
|
||||||
if len([]byte(iface)) > syscall.IFNAMSIZ {
|
if len([]byte(iface)) > syscall.IFNAMSIZ {
|
||||||
|
@ -10,6 +10,7 @@ import (
|
|||||||
var globalFd int
|
var globalFd int
|
||||||
|
|
||||||
func respond(iface string, requests chan *NDRequest, respondType NDPType, filter []*net.IPNet) {
|
func respond(iface string, requests chan *NDRequest, respondType NDPType, filter []*net.IPNet) {
|
||||||
|
defer stopWg.Done()
|
||||||
fd, err := syscall.Socket(syscall.AF_INET6, syscall.SOCK_RAW, syscall.IPPROTO_RAW)
|
fd, err := syscall.Socket(syscall.AF_INET6, syscall.SOCK_RAW, syscall.IPPROTO_RAW)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
@ -46,7 +47,13 @@ func respond(iface string, requests chan *NDRequest, respondType NDPType, filter
|
|||||||
}
|
}
|
||||||
|
|
||||||
for {
|
for {
|
||||||
n := <-requests
|
var n *NDRequest
|
||||||
|
select {
|
||||||
|
case <-stop:
|
||||||
|
return
|
||||||
|
case n = <-requests:
|
||||||
|
}
|
||||||
|
|
||||||
if filter != nil {
|
if filter != nil {
|
||||||
ok := false
|
ok := false
|
||||||
for _, i := range filter {
|
for _, i := range filter {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user