diff --git a/cmd/api/v5/bgp.go b/cmd/api/v5/bgp.go index 4f7c33d..2e0db2b 100644 --- a/cmd/api/v5/bgp.go +++ b/cmd/api/v5/bgp.go @@ -2,10 +2,11 @@ package v5 import ( "github.com/luscis/openlan/cmd/api" + "github.com/luscis/openlan/pkg/schema" "github.com/urfave/cli/v2" ) -// openlan bgp enable --route-id 1.1.1.1 --as-path 30 +// openlan bgp enable --router-id 1.1.1.1 --local-as 30 // openlan bgp disable // openlan bgp add neighbor --address 1.1.1.2 --remote-as 32 @@ -14,18 +15,38 @@ type BGP struct { } func (b BGP) Url(prefix string) string { - return prefix + "/api/bgp" + return prefix + "/api/network/bgp" } func (b BGP) List(c *cli.Context) error { - return nil + url := b.Url(c.String("url")) + clt := b.NewHttp(c.String("token")) + var data schema.Bgp + if err := clt.GetJSON(url, &data); err != nil { + return err + } + return b.Out(data, "yaml", "") } func (b BGP) Enable(c *cli.Context) error { + data := &schema.Bgp{ + LocalAs: c.Int("local-as"), + RouterId: c.String("router-id"), + } + url := b.Url(c.String("url")) + clt := b.NewHttp(c.String("token")) + if err := clt.PostJSON(url, data, nil); err != nil { + return err + } return nil } func (b BGP) Disable(c *cli.Context) error { + url := b.Url(c.String("url")) + clt := b.NewHttp(c.String("token")) + if err := clt.DeleteJSON(url, nil, nil); err != nil { + return err + } return nil } @@ -41,8 +62,12 @@ func (b BGP) Commands(app *api.App) { Action: b.List, }, { - Name: "enable", - Usage: "Enable bgp", + Name: "enable", + Usage: "Enable bgp", + Flags: []cli.Flag{ + &cli.StringFlag{Name: "router-id", Required: true}, + &cli.IntFlag{Name: "local-as", Required: true}, + }, Action: b.Enable, }, { @@ -60,28 +85,31 @@ type Neighbor struct { } func (s Neighbor) Url(prefix string) string { - return prefix + "/api/bgp/neighbor/" + return prefix + "/api/network/bgp/neighbor" } func (s Neighbor) Add(c *cli.Context) error { + data := &schema.BgpNeighbor{ + RemoteAs: c.Int("remote-as"), + Address: c.String("address"), + } url := s.Url(c.String("url")) - clt := s.NewHttp(c.String("token")) - if err := clt.PostJSON(url, nil, nil); err != nil { + if err := clt.PostJSON(url, data, nil); err != nil { return err } - return nil } func (s Neighbor) Remove(c *cli.Context) error { + data := &schema.BgpNeighbor{ + Address: c.String("address"), + } url := s.Url(c.String("url")) - clt := s.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 } @@ -91,15 +119,22 @@ func (s Neighbor) Commands() *cli.Command { Usage: "BGP neighbor", Subcommands: []*cli.Command{ { - Name: "add", - Usage: "Add BGP neighbor", + Name: "add", + Usage: "Add BGP neighbor", + Flags: []cli.Flag{ + &cli.StringFlag{Name: "address", Required: true}, + &cli.IntFlag{Name: "remote-as", Required: true}, + }, Action: s.Add, }, { Name: "remove", Aliases: []string{"rm"}, Usage: "Remove BGP neighbor", - Action: s.Remove, + Flags: []cli.Flag{ + &cli.StringFlag{Name: "address", Required: true}, + }, + Action: s.Remove, }, }, } diff --git a/dist/rootfs/var/openlan/script/switch.sh b/dist/rootfs/var/openlan/script/switch.sh index d6895ca..c967a67 100755 --- a/dist/rootfs/var/openlan/script/switch.sh +++ b/dist/rootfs/var/openlan/script/switch.sh @@ -14,13 +14,38 @@ sysctl -p /etc/sysctl.d/90-openlan.conf /usr/bin/env find /var/openlan/openvpn -name '*client.ovpn' -delete /usr/bin/env find /var/openlan/openvpn -name '*client.tmpl' -delete -if [ ! -e "/etc/openlan/switch/switch.yaml" ]; then -cat >> /etc/openlan/switch/switch.yaml << EOF +if [ ! -e /etc/openlan/switch/switch.yaml ]; then + cat > /etc/openlan/switch/switch.yaml << EOF crypt secret: cb2ff088a34d EOF fi +if [ ! -e /etc/openlan/switch/network/ipsec.json ]; then + cat > /etc/openlan/switch/network/ipsec.json << EOF +{ + "name": "ipsec", + "provider": "ipsec" +} +EOF +fi + +if [ ! -e /etc/openlan/switch/network/bgp.json ]; then + cat > /etc/openlan/switch/network/bgp.json << EOF +{ + "name": "bgp", + "provider": "bgp" +} +EOF +fi + +for dir in acl findhop link output route network qos; do + if [ -e /etc/openlan/switch/$dir ]; then + continue + fi + mkdir -p /etc/openlan/switch/$dir +done + # wait ipsec service while true; do if ipsec status ; then diff --git a/pkg/api/api.go b/pkg/api/api.go index ed46dc3..95b3586 100755 --- a/pkg/api/api.go +++ b/pkg/api/api.go @@ -128,9 +128,9 @@ type IPSecer interface { type Bgper interface { Enable(data schema.Bgp) Disable() + Get() *schema.Bgp AddNeighbor(data schema.BgpNeighbor) DelNeighbor(data schema.BgpNeighbor) - ListNeighbor(call func(obj schema.BgpNeighbor)) } type APICall struct { diff --git a/pkg/api/bgp.go b/pkg/api/bgp.go new file mode 100755 index 0000000..dec20bf --- /dev/null +++ b/pkg/api/bgp.go @@ -0,0 +1,82 @@ +package api + +import ( + "net/http" + + "github.com/gorilla/mux" + "github.com/luscis/openlan/pkg/libol" + "github.com/luscis/openlan/pkg/schema" +) + +type Bgp struct { + Switcher Switcher +} + +func (h Bgp) Router(router *mux.Router) { + router.HandleFunc("/api/network/bgp", h.Get).Methods("GET") + router.HandleFunc("/api/network/bgp", h.Post).Methods("POST") + router.HandleFunc("/api/network/bgp", h.Remove).Methods("DELETE") + router.HandleFunc("/api/network/bgp/neighbor", h.RemoveNeighbor).Methods("DELETE") + router.HandleFunc("/api/network/bgp/neighbor", h.AddNeighbor).Methods("POST") +} + +func (h Bgp) Get(w http.ResponseWriter, r *http.Request) { + libol.Debug("Bgp.Get %s") + if Call.bgper == nil { + http.Error(w, "network is nil", http.StatusBadRequest) + return + } + data := Call.bgper.Get() + ResponseJson(w, data) +} + +func (h Bgp) Post(w http.ResponseWriter, r *http.Request) { + data := schema.Bgp{} + if err := GetData(r, &data); err != nil { + http.Error(w, err.Error(), http.StatusBadRequest) + return + } + if Call.bgper == nil { + http.Error(w, "network is nil", http.StatusBadRequest) + return + } + Call.bgper.Enable(data) + ResponseMsg(w, 0, "") +} + +func (h Bgp) Remove(w http.ResponseWriter, r *http.Request) { + if Call.bgper == nil { + http.Error(w, "network is nil", http.StatusBadRequest) + return + } + Call.bgper.Disable() + ResponseMsg(w, 0, "") +} + +func (h Bgp) RemoveNeighbor(w http.ResponseWriter, r *http.Request) { + nei := schema.BgpNeighbor{} + if err := GetData(r, &nei); err != nil { + http.Error(w, err.Error(), http.StatusBadRequest) + return + } + if Call.bgper == nil { + http.Error(w, "network is nil", http.StatusBadRequest) + return + } + Call.bgper.DelNeighbor(nei) + ResponseMsg(w, 0, "") +} + +func (h Bgp) AddNeighbor(w http.ResponseWriter, r *http.Request) { + nei := schema.BgpNeighbor{} + if err := GetData(r, &nei); err != nil { + http.Error(w, err.Error(), http.StatusBadRequest) + return + } + if Call.bgper == nil { + http.Error(w, "network is nil", http.StatusBadRequest) + return + } + Call.bgper.AddNeighbor(nei) + ResponseMsg(w, 0, "") +} diff --git a/pkg/api/url.go b/pkg/api/url.go index 493d2a3..c287a8e 100755 --- a/pkg/api/url.go +++ b/pkg/api/url.go @@ -5,9 +5,10 @@ import "github.com/gorilla/mux" func Add(router *mux.Router, switcher Switcher) { Link{Switcher: switcher}.Router(router) User{}.Router(router) + Bgp{}.Router(router) + IPSec{}.Router(router) Neighbor{}.Router(router) Access{}.Router(router) - Network{Switcher: switcher}.Router(router) OnLine{}.Router(router) Lease{}.Router(router) Server{Switcher: switcher}.Router(router) @@ -23,8 +24,8 @@ func Add(router *mux.Router, switcher Switcher) { Output{Switcher: switcher}.Router(router) ACL{}.Router(router) Route{Switcher: switcher}.Router(router) - IPSec{}.Router(router) FindHop{}.Router(router) Rate{Switcher: switcher}.Router(router) SNAT{}.Router(router) + Network{Switcher: switcher}.Router(router) } diff --git a/pkg/config/bgp.go b/pkg/config/bgp.go index c3a8a1e..942a29c 100644 --- a/pkg/config/bgp.go +++ b/pkg/config/bgp.go @@ -20,7 +20,7 @@ func (s *BgpNeighbor) Id() string { type BgpSpecifies struct { Name string `json:"-" yaml:"-"` LocalAs int `json:"localas" yaml:"localas"` - RouteId string `json:"routeid" yaml:"routeid"` + RouterId string `json:"routerid" yaml:"routerid"` Neighbors []*BgpNeighbor `json:"neighbors" yaml:"neighbors"` } diff --git a/pkg/schema/bgp.go b/pkg/schema/bgp.go index f779c2c..eca7ca7 100644 --- a/pkg/schema/bgp.go +++ b/pkg/schema/bgp.go @@ -8,6 +8,6 @@ type BgpNeighbor struct { type Bgp struct { LocalAs int `json:"localas"` - RouteId string `json:"routeid"` + RouterId string `json:"routerid"` Neighbors []BgpNeighbor `json:"neighbors"` } diff --git a/pkg/switch/bgp_linux.go b/pkg/switch/bgp_linux.go index 1ecb431..b545cc1 100644 --- a/pkg/switch/bgp_linux.go +++ b/pkg/switch/bgp_linux.go @@ -29,14 +29,9 @@ func NewBgpWorker(c *co.Network) *BgpWorker { } var BgpTmpl = `! GENERATE BY OPENALN -{{- range .Neighbors }} -! -ip prefix-list {{ .Address }}-out seq 10 permit any -ip prefix-list {{ .Address }}-in seq 10 permit any -{{- end }} -! +{{- if .RouterId }} router bgp {{ .LocalAs }} - bgp router-id {{ .RouteId }} + bgp router-id {{ .RouterId }} no bgp default ipv4-unicast {{- range .Neighbors }} neighbor {{ .Address }} remote-as {{ .RemoteAs }} @@ -54,6 +49,12 @@ router bgp {{ .LocalAs }} exit {{- range .Neighbors }} ! +ip prefix-list {{ .Address }}-out seq 10 permit any +ip prefix-list {{ .Address }}-in seq 10 permit any +{{- end }} +! +{{- range .Neighbors }} +! route-map {{ .Address }}-in permit 10 match ip address prefix-list {{ .Address }}-in exit @@ -64,6 +65,7 @@ route-map {{ .Address }}-out permit 10 match ip address prefix-list {{ .Address }}-out exit {{- end }} +{{- end }} ! ` @@ -108,11 +110,29 @@ func (w *BgpWorker) Stop() { func (w *BgpWorker) Enable(data schema.Bgp) { w.spec.LocalAs = data.LocalAs - w.spec.RouteId = data.RouteId + w.spec.RouterId = data.RouterId w.reload() } func (w *BgpWorker) Disable() { + w.spec.RouterId = "" + w.spec.LocalAs = 0 + w.reload() +} + +func (w *BgpWorker) Get() *schema.Bgp { + data := &schema.Bgp{ + LocalAs: w.spec.LocalAs, + RouterId: w.spec.RouterId, + } + for _, nei := range w.spec.Neighbors { + obj := schema.BgpNeighbor{ + Address: nei.Address, + RemoteAs: nei.RemoteAs, + } + data.Neighbors = append(data.Neighbors, obj) + } + return data } func (w *BgpWorker) Reload(v api.Switcher) { @@ -142,13 +162,3 @@ func (w *BgpWorker) DelNeighbor(data schema.BgpNeighbor) { w.reload() } } - -func (w *BgpWorker) ListNeighbor(call func(obj schema.BgpNeighbor)) { - for _, nei := range w.spec.Neighbors { - obj := schema.BgpNeighbor{ - Address: nei.Address, - RemoteAs: nei.RemoteAs, - } - call(obj) - } -}