Make the user interface a module, Rework modules
This commit is contained in:
parent
0f580cbbbd
commit
6ebee06861
142
config.go
142
config.go
@ -10,24 +10,6 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
type configResponder struct {
|
||||
Iface string
|
||||
Filter string
|
||||
autosense string
|
||||
instance *pndp.ResponderObj
|
||||
}
|
||||
|
||||
type configProxy struct {
|
||||
Iface1 string
|
||||
Iface2 string
|
||||
Filter string
|
||||
autosense string
|
||||
instance *pndp.ProxyObj
|
||||
}
|
||||
|
||||
var allResponders []*configResponder
|
||||
var allProxies []*configProxy
|
||||
|
||||
func readConfig(dest string) {
|
||||
file, err := os.Open(dest)
|
||||
if err != nil {
|
||||
@ -52,120 +34,40 @@ func readConfig(dest string) {
|
||||
continue
|
||||
}
|
||||
|
||||
if strings.HasPrefix(line, "responder") && strings.Contains(line, "{") {
|
||||
obj := configResponder{}
|
||||
filter := ""
|
||||
if strings.HasSuffix(line, "{") {
|
||||
option := strings.TrimSuffix(strings.TrimSpace(line), "{")
|
||||
option = strings.TrimSpace(option)
|
||||
module, command := modules.GetCommand(option)
|
||||
var lines = make([]string, 0)
|
||||
if module != nil {
|
||||
for {
|
||||
if !scanner.Scan() {
|
||||
break
|
||||
}
|
||||
line = strings.TrimSpace(scanner.Text())
|
||||
if strings.HasPrefix(line, "iface") {
|
||||
obj.Iface = strings.TrimSpace(strings.TrimPrefix(line, "iface"))
|
||||
}
|
||||
if strings.HasPrefix(line, "filter") {
|
||||
filter += strings.TrimSpace(strings.TrimPrefix(line, "filter")) + ";"
|
||||
if strings.Contains(line, ";") {
|
||||
panic("Invalid config file syntax")
|
||||
}
|
||||
}
|
||||
if strings.HasPrefix(line, "autosense") {
|
||||
obj.autosense = strings.TrimSpace(strings.TrimPrefix(line, "autosense"))
|
||||
}
|
||||
if strings.HasPrefix(line, "}") {
|
||||
obj.Filter = strings.TrimSuffix(filter, ";")
|
||||
line := strings.TrimSpace(scanner.Text())
|
||||
if strings.Contains(line, "}") {
|
||||
break
|
||||
}
|
||||
|
||||
lines = append(lines, line)
|
||||
}
|
||||
modules.ExecuteInit(module, modules.CallbackInfo{
|
||||
CallbackType: modules.Config,
|
||||
Command: command,
|
||||
Arguments: lines,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
allResponders = append(allResponders, &obj)
|
||||
} else if strings.HasPrefix(line, "proxy") && strings.Contains(line, "{") {
|
||||
obj := configProxy{}
|
||||
filter := ""
|
||||
for {
|
||||
if !scanner.Scan() {
|
||||
break
|
||||
}
|
||||
line = strings.TrimSpace(scanner.Text())
|
||||
if strings.HasPrefix(line, "iface1") {
|
||||
obj.Iface1 = strings.TrimSpace(strings.TrimPrefix(line, "iface1"))
|
||||
}
|
||||
if strings.HasPrefix(line, "iface2") {
|
||||
obj.Iface2 = strings.TrimSpace(strings.TrimPrefix(line, "iface2"))
|
||||
}
|
||||
if strings.HasPrefix(line, "filter") {
|
||||
filter += strings.TrimSpace(strings.TrimPrefix(line, "filter")) + ";"
|
||||
if strings.Contains(line, ";") {
|
||||
panic("Invalid config file syntax")
|
||||
}
|
||||
}
|
||||
if strings.HasPrefix(line, "autosense") {
|
||||
obj.autosense = strings.TrimSpace(strings.TrimPrefix(line, "autosense"))
|
||||
}
|
||||
if strings.HasPrefix(line, "}") {
|
||||
obj.Filter = strings.TrimSuffix(filter, ";")
|
||||
break
|
||||
}
|
||||
if strings.HasPrefix(line, "}") {
|
||||
break
|
||||
}
|
||||
}
|
||||
allProxies = append(allProxies, &obj)
|
||||
} else if strings.Contains(line, "{") {
|
||||
option := strings.TrimSuffix(strings.TrimSpace(line), "{")
|
||||
option = strings.TrimSpace(option)
|
||||
if modules.ModuleList != nil {
|
||||
for i := range modules.ModuleList {
|
||||
for d := range (*modules.ModuleList[i]).Option {
|
||||
if (*modules.ModuleList[i]).Option[d].Option == option {
|
||||
var lines []string
|
||||
for {
|
||||
if !scanner.Scan() {
|
||||
break
|
||||
}
|
||||
line = strings.TrimSpace(scanner.Text())
|
||||
if strings.HasPrefix(line, "}") {
|
||||
break
|
||||
}
|
||||
lines = append(lines, line)
|
||||
}
|
||||
(*modules.ModuleList[i]).Callback(modules.Callback{
|
||||
CallbackType: modules.Config,
|
||||
Option: option,
|
||||
Arguments: lines,
|
||||
})
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if modules.ExistsBlockingModule() {
|
||||
modules.ExecuteComplete()
|
||||
waitForSignal()
|
||||
modules.ShutdownAll()
|
||||
}
|
||||
|
||||
if err := scanner.Err(); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
for _, n := range allProxies {
|
||||
o := pndp.NewProxy(n.Iface1, n.Iface2, pndp.ParseFilter(n.Filter), n.autosense)
|
||||
n.instance = o
|
||||
o.Start()
|
||||
}
|
||||
|
||||
for _, n := range allResponders {
|
||||
o := pndp.NewResponder(n.Iface, pndp.ParseFilter(n.Filter), n.autosense)
|
||||
n.instance = o
|
||||
o.Start()
|
||||
}
|
||||
|
||||
WaitForSignal()
|
||||
|
||||
for _, n := range allProxies {
|
||||
n.instance.Stop()
|
||||
}
|
||||
|
||||
for _, n := range allResponders {
|
||||
n.instance.Stop()
|
||||
panic(err)
|
||||
}
|
||||
|
||||
}
|
||||
|
63
main.go
63
main.go
@ -5,12 +5,12 @@ import (
|
||||
"os"
|
||||
"os/signal"
|
||||
"pndpd/modules"
|
||||
"pndpd/pndp"
|
||||
_ "pndpd/modules/userInterface"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
// WaitForSignal Waits (blocking) for the program to be interrupted by the OS
|
||||
func WaitForSignal() {
|
||||
// waitForSignal Waits (blocking) for the program to be interrupted by the OS
|
||||
func waitForSignal() {
|
||||
var sigCh = make(chan os.Signal, 1)
|
||||
signal.Notify(sigCh, os.Interrupt, syscall.SIGTERM)
|
||||
<-sigCh
|
||||
@ -18,57 +18,32 @@ func WaitForSignal() {
|
||||
}
|
||||
|
||||
func main() {
|
||||
fmt.Println("PNDPD Version 1.2 - Kioubit 2021")
|
||||
if modules.ModuleList != nil {
|
||||
fmt.Print("Loaded Modules: Core ")
|
||||
for i := range modules.ModuleList {
|
||||
fmt.Print((*modules.ModuleList[i]).Name + " ")
|
||||
}
|
||||
fmt.Println()
|
||||
}
|
||||
fmt.Println("PNDPD Version 1.2.1 - Kioubit 2021")
|
||||
|
||||
if len(os.Args) <= 2 {
|
||||
printUsage()
|
||||
return
|
||||
}
|
||||
|
||||
switch os.Args[1] {
|
||||
case "respond":
|
||||
var r *pndp.ResponderObj
|
||||
if len(os.Args) == 4 {
|
||||
r = pndp.NewResponder(os.Args[2], pndp.ParseFilter(os.Args[3]), "")
|
||||
r.Start()
|
||||
} else {
|
||||
r = pndp.NewResponder(os.Args[2], nil, "")
|
||||
r.Start()
|
||||
}
|
||||
WaitForSignal()
|
||||
r.Stop()
|
||||
case "proxy":
|
||||
var p *pndp.ProxyObj
|
||||
if len(os.Args) == 5 {
|
||||
p = pndp.NewProxy(os.Args[2], os.Args[3], pndp.ParseFilter(os.Args[4]), "")
|
||||
} else {
|
||||
p = pndp.NewProxy(os.Args[2], os.Args[3], nil, "")
|
||||
}
|
||||
WaitForSignal()
|
||||
p.Stop()
|
||||
case "config":
|
||||
readConfig(os.Args[2])
|
||||
default:
|
||||
for i := range modules.ModuleList {
|
||||
for d := range (*modules.ModuleList[i]).Option {
|
||||
if (*modules.ModuleList[i]).Option[d].Option == os.Args[1] {
|
||||
(*modules.ModuleList[i]).Callback(modules.Callback{
|
||||
module, command := modules.GetCommand(os.Args[1])
|
||||
if module != nil {
|
||||
modules.ExecuteInit(module, modules.CallbackInfo{
|
||||
CallbackType: modules.CommandLine,
|
||||
Option: os.Args[1],
|
||||
Arguments: os.Args[1:],
|
||||
Command: command,
|
||||
Arguments: os.Args[2:],
|
||||
})
|
||||
return
|
||||
}
|
||||
}
|
||||
if modules.ExistsBlockingModule() {
|
||||
modules.ExecuteComplete()
|
||||
waitForSignal()
|
||||
modules.ShutdownAll()
|
||||
}
|
||||
} else {
|
||||
printUsage()
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -77,11 +52,9 @@ func printUsage() {
|
||||
fmt.Println("More options and additional documentation in the example config file")
|
||||
fmt.Println("Usage:")
|
||||
fmt.Println("pndpd config <path to file>")
|
||||
fmt.Println("pndpd respond <interface> <optional whitelist of CIDRs separated by a semicolon>")
|
||||
fmt.Println("pndpd proxy <interface1> <interface2> <optional whitelist of CIDRs separated by a semicolon applied to interface2>")
|
||||
for i := range modules.ModuleList {
|
||||
for d := range (*modules.ModuleList[i]).Option {
|
||||
fmt.Println((*modules.ModuleList[i]).Option[d].Description)
|
||||
for d := range (*modules.ModuleList[i]).Commands {
|
||||
fmt.Println("pndpd", (*modules.ModuleList[i]).Commands[d].Description)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,29 +7,39 @@ import (
|
||||
|
||||
// This is an example module that is not imported by the main program
|
||||
func init() {
|
||||
option := []modules.Option{{
|
||||
Option: "command1",
|
||||
commands := []modules.Command{{
|
||||
CommandText: "command1",
|
||||
Description: "This is the usage description for command1",
|
||||
BlockTerminate: true,
|
||||
}, {
|
||||
Option: "command2",
|
||||
CommandText: "command2",
|
||||
Description: "This is the usage description for command2",
|
||||
BlockTerminate: false,
|
||||
},
|
||||
}
|
||||
modules.RegisterModule("Example", option, callback)
|
||||
modules.RegisterModule("Example", commands, initCallback, completeCallback, shutdownCallback)
|
||||
}
|
||||
|
||||
func callback(callback modules.Callback) {
|
||||
func initCallback(callback modules.CallbackInfo) {
|
||||
if callback.CallbackType == modules.CommandLine {
|
||||
// The command registered by the module has been run in the commandline
|
||||
// "arguments" contains the os.Args[] passed to the program after the command registered by this module
|
||||
fmt.Println("Command: ", callback.Option)
|
||||
fmt.Println("Command: ", callback.Command.CommandText)
|
||||
fmt.Println(callback.Arguments)
|
||||
|
||||
} else {
|
||||
// The command registered by the module was found in the config file
|
||||
// "arguments" contains the lines between the curly braces
|
||||
fmt.Println("Command: ", callback.Option)
|
||||
fmt.Println("Command: ", callback.Command.CommandText)
|
||||
fmt.Println(callback.Arguments)
|
||||
}
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
func completeCallback() {
|
||||
//Called after the program has passed all options by calls to initCallback()
|
||||
}
|
||||
|
||||
func shutdownCallback() {
|
||||
fmt.Println("Terminate all work")
|
||||
}
|
||||
|
@ -4,13 +4,16 @@ var ModuleList []*Module
|
||||
|
||||
type Module struct {
|
||||
Name string
|
||||
Option []Option
|
||||
Callback func(Callback)
|
||||
Commands []Command
|
||||
InitCallback func(CallbackInfo)
|
||||
CompleteCallback func()
|
||||
ShutdownCallback func()
|
||||
}
|
||||
|
||||
type Option struct {
|
||||
Option string
|
||||
type Command struct {
|
||||
CommandText string
|
||||
Description string
|
||||
BlockTerminate bool
|
||||
}
|
||||
|
||||
type CallbackType int
|
||||
@ -20,16 +23,63 @@ const (
|
||||
Config CallbackType = 1
|
||||
)
|
||||
|
||||
type Callback struct {
|
||||
type CallbackInfo struct {
|
||||
CallbackType CallbackType
|
||||
Option string
|
||||
Command Command
|
||||
Arguments []string
|
||||
}
|
||||
|
||||
func RegisterModule(name string, option []Option, Callback func(Callback)) {
|
||||
func RegisterModule(name string, commands []Command, initCallback func(CallbackInfo), CompleteCallback func(), shutdownCallback func()) {
|
||||
ModuleList = append(ModuleList, &Module{
|
||||
Name: name,
|
||||
Option: option,
|
||||
Callback: Callback,
|
||||
Commands: commands,
|
||||
InitCallback: initCallback,
|
||||
CompleteCallback: CompleteCallback,
|
||||
ShutdownCallback: shutdownCallback,
|
||||
})
|
||||
}
|
||||
|
||||
func GetCommand(target string) (*Module, Command) {
|
||||
for i := range ModuleList {
|
||||
for _, command := range ModuleList[i].Commands {
|
||||
if command.CommandText == target {
|
||||
return ModuleList[i], command
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil, Command{}
|
||||
}
|
||||
|
||||
var runningModules []*Module
|
||||
|
||||
func ExecuteInit(module *Module, info CallbackInfo) {
|
||||
if info.Command.BlockTerminate {
|
||||
found := false
|
||||
for _, n := range runningModules {
|
||||
if n == module {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
runningModules = append(runningModules, module)
|
||||
}
|
||||
}
|
||||
module.InitCallback(info)
|
||||
}
|
||||
|
||||
func ExecuteComplete() {
|
||||
for i := range runningModules {
|
||||
(*runningModules[i]).CompleteCallback()
|
||||
}
|
||||
}
|
||||
|
||||
func ShutdownAll() {
|
||||
for i := range runningModules {
|
||||
(*runningModules[i]).ShutdownCallback()
|
||||
}
|
||||
}
|
||||
|
||||
func ExistsBlockingModule() bool {
|
||||
return len(runningModules) != 0
|
||||
}
|
||||
|
162
modules/userInterface/userInterface.go
Normal file
162
modules/userInterface/userInterface.go
Normal file
@ -0,0 +1,162 @@
|
||||
package userInterface
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"pndpd/modules"
|
||||
"pndpd/pndp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func init() {
|
||||
commands := []modules.Command{{
|
||||
CommandText: "proxy",
|
||||
Description: "proxy <interface1> <interface2> <optional whitelist of CIDRs separated by a semicolon applied to interface2>",
|
||||
BlockTerminate: true,
|
||||
}, {
|
||||
CommandText: "responder",
|
||||
Description: "responder <interface> <optional whitelist of CIDRs separated by a semicolon>",
|
||||
BlockTerminate: true,
|
||||
}, {
|
||||
CommandText: "modules",
|
||||
Description: "modules available - list available modules",
|
||||
BlockTerminate: false,
|
||||
}}
|
||||
modules.RegisterModule("Core", commands, initCallback, completeCallback, shutdownCallback)
|
||||
}
|
||||
|
||||
type configResponder struct {
|
||||
Iface string
|
||||
Filter string
|
||||
autosense string
|
||||
instance *pndp.ResponderObj
|
||||
}
|
||||
|
||||
type configProxy struct {
|
||||
Iface1 string
|
||||
Iface2 string
|
||||
Filter string
|
||||
autosense string
|
||||
instance *pndp.ProxyObj
|
||||
}
|
||||
|
||||
var allResponders []*configResponder
|
||||
var allProxies []*configProxy
|
||||
|
||||
func initCallback(callback modules.CallbackInfo) {
|
||||
if callback.CallbackType == modules.CommandLine {
|
||||
switch callback.Command.CommandText {
|
||||
case "proxy":
|
||||
if len(callback.Arguments) == 3 {
|
||||
allProxies = append(allProxies, &configProxy{
|
||||
Iface1: callback.Arguments[0],
|
||||
Iface2: callback.Arguments[1],
|
||||
Filter: callback.Arguments[2],
|
||||
autosense: "",
|
||||
instance: nil,
|
||||
})
|
||||
} else {
|
||||
allProxies = append(allProxies, &configProxy{
|
||||
Iface1: callback.Arguments[0],
|
||||
Iface2: callback.Arguments[1],
|
||||
Filter: "",
|
||||
autosense: "",
|
||||
instance: nil,
|
||||
})
|
||||
}
|
||||
case "responder":
|
||||
if len(callback.Arguments) == 2 {
|
||||
allResponders = append(allResponders, &configResponder{
|
||||
Iface: callback.Arguments[0],
|
||||
Filter: callback.Arguments[1],
|
||||
autosense: "",
|
||||
instance: nil,
|
||||
})
|
||||
} else {
|
||||
allResponders = append(allResponders, &configResponder{
|
||||
Iface: callback.Arguments[0],
|
||||
Filter: "",
|
||||
autosense: "",
|
||||
instance: nil,
|
||||
})
|
||||
}
|
||||
case "modules":
|
||||
if modules.ModuleList != nil {
|
||||
fmt.Print("Available Modules: ")
|
||||
for i := range modules.ModuleList {
|
||||
fmt.Print((*modules.ModuleList[i]).Name + " ")
|
||||
}
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
switch callback.Command.CommandText {
|
||||
case "proxy":
|
||||
obj := configProxy{}
|
||||
filter := ""
|
||||
for _, n := range callback.Arguments {
|
||||
if strings.HasPrefix(n, "iface1") {
|
||||
obj.Iface1 = strings.TrimSpace(strings.TrimPrefix(n, "iface1"))
|
||||
}
|
||||
if strings.HasPrefix(n, "iface2") {
|
||||
obj.Iface2 = strings.TrimSpace(strings.TrimPrefix(n, "iface2"))
|
||||
}
|
||||
if strings.HasPrefix(n, "filter") {
|
||||
filter += strings.TrimSpace(strings.TrimPrefix(n, "filter")) + ";"
|
||||
if strings.Contains(n, ";") {
|
||||
panic("Invalid config file syntax")
|
||||
}
|
||||
}
|
||||
if strings.HasPrefix(n, "autosense") {
|
||||
obj.autosense = strings.TrimSpace(strings.TrimPrefix(n, "autosense"))
|
||||
}
|
||||
}
|
||||
obj.Filter = strings.TrimSuffix(filter, ";")
|
||||
allProxies = append(allProxies, &obj)
|
||||
case "responder":
|
||||
obj := configResponder{}
|
||||
filter := ""
|
||||
for _, n := range callback.Arguments {
|
||||
if strings.HasPrefix(n, "iface") {
|
||||
obj.Iface = strings.TrimSpace(strings.TrimPrefix(n, "iface"))
|
||||
}
|
||||
if strings.HasPrefix(n, "filter") {
|
||||
filter += strings.TrimSpace(strings.TrimPrefix(n, "filter")) + ";"
|
||||
if strings.Contains(n, ";") {
|
||||
panic("Invalid config file syntax")
|
||||
}
|
||||
}
|
||||
if strings.HasPrefix(n, "autosense") {
|
||||
obj.autosense = strings.TrimSpace(strings.TrimPrefix(n, "autosense"))
|
||||
}
|
||||
|
||||
}
|
||||
obj.Filter = strings.TrimSuffix(filter, ";")
|
||||
allResponders = append(allResponders, &obj)
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func completeCallback() {
|
||||
for _, n := range allProxies {
|
||||
o := pndp.NewProxy(n.Iface1, n.Iface2, pndp.ParseFilter(n.Filter), n.autosense)
|
||||
n.instance = o
|
||||
o.Start()
|
||||
}
|
||||
for _, n := range allResponders {
|
||||
o := pndp.NewResponder(n.Iface, pndp.ParseFilter(n.Filter), n.autosense)
|
||||
n.instance = o
|
||||
o.Start()
|
||||
}
|
||||
}
|
||||
func shutdownCallback() {
|
||||
for _, n := range allProxies {
|
||||
n.instance.Stop()
|
||||
}
|
||||
|
||||
for _, n := range allResponders {
|
||||
n.instance.Stop()
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user