diff --git a/cmd/api/v5/ceci.go b/cmd/api/v5/ceci.go index c9b2a7c..1fa9d03 100755 --- a/cmd/api/v5/ceci.go +++ b/cmd/api/v5/ceci.go @@ -1,6 +1,8 @@ package v5 import ( + "strings" + "github.com/luscis/openlan/cmd/api" "github.com/luscis/openlan/pkg/schema" "github.com/urfave/cli/v2" @@ -10,48 +12,32 @@ type Ceci struct { Cmd } -func (u Ceci) Url(prefix, name string) string { - return prefix + "/api/interface/" + name + "/ceci" -} - -func (u Ceci) Tmpl() string { - return `# total {{ len . }} -{{ps -16 "Name"}} {{ps -8 "Configure"}} -{{- range . }} -{{ps -16 .Name}} {{pi .Configure}} -{{- end }} -` -} - -func (u Ceci) List(c *cli.Context) error { - url := u.Url(c.String("url"), "") - clt := u.NewHttp(c.String("token")) - var items []schema.Ceci - if err := clt.GetJSON(url, &items); err != nil { - return err - } - return u.Out(items, c.String("format"), u.Tmpl()) +func (u Ceci) Url(prefix string) string { + return prefix + "/api/network/ceci/tcp" } func (u Ceci) Add(c *cli.Context) error { - name := c.String("name") - rate := &schema.Ceci{ - Name: name, + target := strings.Split(c.String("target"), ",") + data := &schema.CeciTcp{ + Mode: c.String("mode"), + Listen: c.String("listen"), + Target: target, } - url := u.Url(c.String("url"), name) + url := u.Url(c.String("url")) clt := u.NewHttp(c.String("token")) - if err := clt.PostJSON(url, rate, nil); err != nil { + if err := clt.PostJSON(url, data, nil); err != nil { return err } return nil } func (u Ceci) Remove(c *cli.Context) error { - name := c.String("name") - - url := u.Url(c.String("url"), name) + data := &schema.CeciTcp{ + Listen: c.String("listen"), + } + url := u.Url(c.String("url")) clt := u.NewHttp(c.String("token")) - if err := clt.DeleteJSON(url, nil, nil); err != nil { + if err := clt.DeleteJSON(url, data, nil); err != nil { return err } return nil @@ -60,29 +46,24 @@ func (u Ceci) Remove(c *cli.Context) error { func (u Ceci) Commands(app *api.App) { app.Command(&cli.Command{ Name: "ceci", - Usage: "Ceci proxy", + Usage: "Ceci TCP proxy", Subcommands: []*cli.Command{ - { - Name: "list", - Usage: "Display all ceci proxy", - Aliases: []string{"ls"}, - Action: u.List, - }, { Name: "add", - Usage: "Add a ceci proxy", + Usage: "Add a ceci TCP", Flags: []cli.Flag{ - &cli.StringFlag{Name: "name", Required: true}, - &cli.StringFlag{Name: "file", Required: true}, + &cli.StringFlag{Name: "listen", Required: true}, + &cli.StringFlag{Name: "mode", Required: true}, + &cli.StringFlag{Name: "target"}, }, Action: u.Add, }, { Name: "remove", - Usage: "Remove a ceci proxy", + Usage: "Remove a ceci TCP", Aliases: []string{"rm"}, Flags: []cli.Flag{ - &cli.StringFlag{Name: "name", Required: true}, + &cli.StringFlag{Name: "listen", Required: true}, }, Action: u.Remove, }, diff --git a/cmd/api/v5/cmd.go b/cmd/api/v5/cmd.go index 3a0342e..eced225 100755 --- a/cmd/api/v5/cmd.go +++ b/cmd/api/v5/cmd.go @@ -40,7 +40,7 @@ func Commands(app *api.App) { Log{}.Commands(app) ZTrust{}.Commands(app) Rate{}.Commands(app) - Ceci{}.Commands(app) BGP{}.Commands(app) + Ceci{}.Commands(app) Prefix{}.Commands(app) } diff --git a/cmd/api/v5/system.go b/cmd/api/v5/system.go index 3b3ae7f..1427c6b 100644 --- a/cmd/api/v5/system.go +++ b/cmd/api/v5/system.go @@ -89,10 +89,9 @@ func (v Log) Add(c *cli.Context) error { func (v Log) Commands(app *api.App) { app.Command(&cli.Command{ - Name: "log", - Aliases: []string{"v"}, - Usage: "show log information", - Action: v.List, + Name: "log", + Usage: "show log information", + Action: v.List, Subcommands: []*cli.Command{ { Name: "set", diff --git a/cmd/api/v5/version.go b/cmd/api/v5/version.go index d88a84f..fc10c76 100755 --- a/cmd/api/v5/version.go +++ b/cmd/api/v5/version.go @@ -33,9 +33,8 @@ func (v Version) List(c *cli.Context) error { func (v Version) Commands(app *api.App) { app.Command(&cli.Command{ - Name: "version", - Aliases: []string{"v"}, - Usage: "show version information", - Action: v.List, + Name: "version", + Usage: "show version information", + Action: v.List, }) } diff --git a/dist/rootfs/etc/openlan/switch/network/ceci.json.example b/dist/rootfs/etc/openlan/switch/network/ceci.json.example index 1a80a3c..9ccd6d7 100755 --- a/dist/rootfs/etc/openlan/switch/network/ceci.json.example +++ b/dist/rootfs/etc/openlan/switch/network/ceci.json.example @@ -9,12 +9,11 @@ "192.168.1.11:80", "192.168.1.12:80" ] - } - ], - "http": [ + }, { + "mode": "http", "listen": "0.0.0.0:80" } - ] + ], } } \ No newline at end of file diff --git a/pkg/api/api.go b/pkg/api/api.go index e1501b4..532e8e3 100755 --- a/pkg/api/api.go +++ b/pkg/api/api.go @@ -151,9 +151,15 @@ type BgpApi interface { DelAdvertis(data schema.BgpPrefix) } +type CeciApi interface { + AddTcp(data schema.CeciTcp) + DelTcp(data schema.CeciTcp) +} + type callApi struct { ipsecApi IPSecApi bgpApi BgpApi + ceciApi CeciApi workers map[string]NetworkApi } @@ -171,14 +177,18 @@ func (i *callApi) ListWorker(call func(w NetworkApi)) { } } -func (i *callApi) SetIPSecer(value IPSecApi) { +func (i *callApi) SetIPSecApi(value IPSecApi) { i.ipsecApi = value } -func (i *callApi) SetBgper(value BgpApi) { +func (i *callApi) SetBgpApi(value BgpApi) { i.bgpApi = value } +func (i *callApi) SetCeciApi(value CeciApi) { + i.ceciApi = value +} + var Call = &callApi{ workers: make(map[string]NetworkApi), } diff --git a/pkg/api/ceci.go b/pkg/api/ceci.go new file mode 100755 index 0000000..84b979b --- /dev/null +++ b/pkg/api/ceci.go @@ -0,0 +1,52 @@ +package api + +import ( + "net/http" + + "github.com/gorilla/mux" + "github.com/luscis/openlan/pkg/libol" + "github.com/luscis/openlan/pkg/schema" +) + +type Ceci struct { + cs SwitchApi +} + +func (h Ceci) Router(router *mux.Router) { + router.HandleFunc("/api/network/ceci/tcp", h.Get).Methods("GET") + router.HandleFunc("/api/network/ceci/tcp", h.Post).Methods("POST") + router.HandleFunc("/api/network/ceci/tcp", h.Remove).Methods("DELETE") +} + +func (h Ceci) Get(w http.ResponseWriter, r *http.Request) { + libol.Debug("Ceci.Get %s") + ResponseJson(w, nil) +} + +func (h Ceci) Post(w http.ResponseWriter, r *http.Request) { + data := schema.CeciTcp{} + if err := GetData(r, &data); err != nil { + http.Error(w, err.Error(), http.StatusBadRequest) + return + } + if Call.ceciApi == nil { + http.Error(w, "network is nil", http.StatusBadRequest) + return + } + Call.ceciApi.AddTcp(data) + ResponseMsg(w, 0, "") +} + +func (h Ceci) Remove(w http.ResponseWriter, r *http.Request) { + data := schema.CeciTcp{} + if err := GetData(r, &data); err != nil { + http.Error(w, err.Error(), http.StatusBadRequest) + return + } + if Call.ceciApi == nil { + http.Error(w, "network is nil", http.StatusBadRequest) + return + } + Call.ceciApi.DelTcp(data) + ResponseMsg(w, 0, "") +} diff --git a/pkg/api/url.go b/pkg/api/url.go index 2e81d09..2149703 100755 --- a/pkg/api/url.go +++ b/pkg/api/url.go @@ -5,6 +5,7 @@ import "github.com/gorilla/mux" func Add(router *mux.Router, cs SwitchApi) { Link{cs: cs}.Router(router) User{}.Router(router) + Ceci{}.Router(router) Bgp{}.Router(router) IPSec{}.Router(router) Prefix{}.Router(router) diff --git a/pkg/config/ceci.go b/pkg/config/ceci.go index 9426180..002afc7 100644 --- a/pkg/config/ceci.go +++ b/pkg/config/ceci.go @@ -4,33 +4,24 @@ import "fmt" type CeciTcp struct { Name string `json:"-" yaml:"-"` + Mode string `json:"mode" yaml:"mode"` Listen string `json:"listen" yaml:"listen"` Target []string `json:"target,omitempty" yaml:"target,omitempty"` } func (s *CeciTcp) Correct() { + if s.Mode == "" { + s.Mode = "tcp" + } } func (s *CeciTcp) Id() string { return fmt.Sprintf("%s", s.Listen) } -type CeciHttp struct { - Name string `json:"-" yaml:"-"` - Listen string `json:"listen" yaml:"listen"` -} - -func (s *CeciHttp) Correct() { -} - -func (s *CeciHttp) Id() string { - return fmt.Sprintf("%s", s.Listen) -} - type CeciSpecifies struct { - Name string `json:"-" yaml:"-"` - Tcp []*CeciTcp `json:"tcp" yaml:"tcp"` - Http []*CeciHttp `json:"http" yaml:"http"` + Name string `json:"-" yaml:"-"` + Tcp []*CeciTcp `json:"tcp" yaml:"tcp"` } func (s *CeciSpecifies) Correct() { @@ -40,12 +31,6 @@ func (s *CeciSpecifies) Correct() { for _, t := range s.Tcp { t.Correct() } - if s.Http == nil { - s.Http = make([]*CeciHttp, 0) - } - for _, t := range s.Http { - t.Correct() - } } func (s *CeciSpecifies) FindTcp(value *CeciTcp) (*CeciTcp, int) { @@ -72,28 +57,3 @@ func (s *CeciSpecifies) DelTcp(value *CeciTcp) (*CeciTcp, bool) { } return obj, find != -1 } - -func (s *CeciSpecifies) FindHttp(value *CeciHttp) (*CeciHttp, int) { - for index, obj := range s.Http { - if obj.Id() == value.Id() { - return obj, index - } - } - return nil, -1 -} - -func (s *CeciSpecifies) AddHttp(value *CeciHttp) bool { - _, find := s.FindHttp(value) - if find == -1 { - s.Http = append(s.Http, value) - } - return find == -1 -} - -func (s *CeciSpecifies) DelHttp(value *CeciHttp) (*CeciHttp, bool) { - obj, find := s.FindHttp(value) - if find != -1 { - s.Http = append(s.Http[:find], s.Http[find+1:]...) - } - return obj, find != -1 -} diff --git a/pkg/schema/ceci.go b/pkg/schema/ceci.go index 204615c..9cd9f12 100644 --- a/pkg/schema/ceci.go +++ b/pkg/schema/ceci.go @@ -4,3 +4,9 @@ type Ceci struct { Name string `json:"name"` Config interface{} `json:"config"` } + +type CeciTcp struct { + Mode string `json:"mode"` + Listen string `json:"listen"` + Target []string `json:"target,omitempty"` +} diff --git a/pkg/switch/ceci_linux.go b/pkg/switch/ceci_linux.go index 230c05e..094c38c 100644 --- a/pkg/switch/ceci_linux.go +++ b/pkg/switch/ceci_linux.go @@ -1,15 +1,18 @@ package cswitch import ( + "os" "os/exec" "github.com/luscis/openlan/pkg/api" co "github.com/luscis/openlan/pkg/config" "github.com/luscis/openlan/pkg/libol" + "github.com/luscis/openlan/pkg/schema" ) const ( CeciBin = "/usr/bin/openceci" + CeciDir = "/var/openlan/ceci/" ) type CeciWorker struct { @@ -29,18 +32,33 @@ func (w *CeciWorker) Initialize() { w.out.Info("CeciWorker.Initialize") } +func (w *CeciWorker) killPid(name string) { + if libol.FileExist(name) != nil { + return + } + + pid, _ := os.ReadFile(name) + kill, _ := exec.LookPath("kill") + cmd := exec.Command(kill, string(pid)) + if err := cmd.Run(); err != nil { + w.out.Warn("CeciWorker.killPid:%s: %s", pid, err) + return + } +} + func (w *CeciWorker) reloadTcp(obj *co.CeciTcp) { - name := "/var/openlan/ceci/" + obj.Id() + name := CeciDir + obj.Id() out, err := libol.CreateFile(name + ".log") if err != nil { w.out.Warn("CeciWorker.reloadTcp: %s", err) return } + w.killPid(name + ".pid") libol.MarshalSave(obj, name+".yaml", true) libol.Go(func() { w.out.Info("CeciWorker.reloadTcp: %s", obj.Id()) - cmd := exec.Command(CeciBin, "-mode", "tcp", "-conf", name+".yaml") + cmd := exec.Command(CeciBin, "-mode", obj.Mode, "-conf", name+".yaml", "-write-pid", name+".pid") cmd.Stdout = out cmd.Stderr = out if err := cmd.Run(); err != nil { @@ -50,27 +68,6 @@ func (w *CeciWorker) reloadTcp(obj *co.CeciTcp) { }) } -func (w *CeciWorker) reloadHttp(obj *co.CeciHttp) { - name := "/var/openlan/ceci/" + obj.Id() - out, err := libol.CreateFile(name + ".log") - if err != nil { - w.out.Warn("CeciWorker.reloadTcp: %s", err) - return - } - - libol.MarshalSave(obj, name+".yaml", true) - libol.Go(func() { - w.out.Info("CeciWorker.reloadHttp: %s", obj.Id()) - cmd := exec.Command(CeciBin, "-mode", "http", "-conf", name+".yaml") - cmd.Stdout = out - cmd.Stderr = out - if err := cmd.Run(); err != nil { - w.out.Warn("CeciWorker.reloadHttp: %s", err) - return - } - }) -} - func (w *CeciWorker) Start(v api.SwitchApi) { w.uuid = v.UUID() w.out.Info("CeciWorker.Start") @@ -78,9 +75,6 @@ func (w *CeciWorker) Start(v api.SwitchApi) { for _, obj := range w.spec.Tcp { w.reloadTcp(obj) } - for _, obj := range w.spec.Http { - w.reloadHttp(obj) - } } func (w *CeciWorker) Stop() { @@ -92,3 +86,31 @@ func (w *CeciWorker) Reload(v api.SwitchApi) { w.Initialize() w.Start(v) } + +func (w *CeciWorker) AddTcp(data schema.CeciTcp) { + obj := &co.CeciTcp{ + Mode: data.Mode, + Listen: data.Listen, + Target: data.Target, + } + + obj.Correct() + if t, _ := w.spec.FindTcp(obj); t == nil { + w.spec.AddTcp(obj) + } else { + t.Target = data.Target + } + + w.reloadTcp(obj) +} + +func (w *CeciWorker) DelTcp(data schema.CeciTcp) { + obj := &co.CeciTcp{ + Listen: data.Listen, + } + obj.Correct() + if _, removed := w.spec.DelTcp(obj); removed { + name := CeciDir + obj.Id() + w.killPid(name + ".pid") + } +} diff --git a/pkg/switch/network_linux.go b/pkg/switch/network_linux.go index 930e3aa..86f80f8 100755 --- a/pkg/switch/network_linux.go +++ b/pkg/switch/network_linux.go @@ -24,17 +24,17 @@ func NewNetworker(c *co.Network) api.NetworkApi { switch c.Provider { case "ipsec": secer := NewIPSecWorker(c) - api.Call.SetIPSecer(secer) + api.Call.SetIPSecApi(secer) obj = secer case "bgp": bgper := NewBgpWorker(c) - api.Call.SetBgper(bgper) + api.Call.SetBgpApi(bgper) obj = bgper case "router": obj = NewRouterWorker(c) case "ceci": cecer := NewCeciWorker(c) - //api.Call.SetBgper(bgper) + api.Call.SetCeciApi(cecer) obj = cecer default: obj = NewOpenLANWorker(c)