diff options
Diffstat (limited to 'server')
-rw-r--r-- | server/grpc_server.go | 21 | ||||
-rw-r--r-- | server/rpki.go | 121 | ||||
-rw-r--r-- | server/server.go | 8 |
3 files changed, 149 insertions, 1 deletions
diff --git a/server/grpc_server.go b/server/grpc_server.go index 4a652c4f..a4e61be7 100644 --- a/server/grpc_server.go +++ b/server/grpc_server.go @@ -83,6 +83,7 @@ const ( REQ_MONITOR_GLOBAL_BEST_CHANGED REQ_MONITOR_NEIGHBOR_PEER_STATE REQ_MRT_GLOBAL_RIB + REQ_RPKI ) const GRPC_PORT = 8080 @@ -621,6 +622,26 @@ END: return err } +func (s *Server) GetRPKI(arg *api.Arguments, stream api.Grpc_GetRPKIServer) error { + rf, err := convertAf2Rf(arg.Af) + if err != nil { + return err + } + req := NewGrpcRequest(REQ_RPKI, "", rf, nil) + s.bgpServerCh <- req + + for res := range req.ResponseCh { + if err := res.Err(); err != nil { + log.Debug(err.Error()) + return err + } + if err := stream.Send(res.Data.(*api.ROA)); err != nil { + return err + } + } + return nil +} + type GrpcRequest struct { RequestType int RemoteAddr string diff --git a/server/rpki.go b/server/rpki.go new file mode 100644 index 00000000..6ad6aa0a --- /dev/null +++ b/server/rpki.go @@ -0,0 +1,121 @@ +// Copyright (C) 2015 Nippon Telegraph and Telephone Corporation. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +// implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package server + +import ( + "bufio" + "fmt" + "github.com/osrg/gobgp/api" + "github.com/osrg/gobgp/packet" + "net" +) + +type roa struct { + AS uint32 + PrefixLen uint8 + MaxLen uint8 + Prefix net.IP +} + +func (r *roa) key() string { + return fmt.Sprintf("%s/%d", r.Prefix.String(), r.PrefixLen) +} + +func (r *roa) toApiStruct() *api.ROA { + return &api.ROA{ + As: r.AS, + Prefixlen: uint32(r.PrefixLen), + Maxlen: uint32(r.MaxLen), + Prefix: r.Prefix.String(), + } +} + +type roaClient struct { + roas map[bgp.RouteFamily]map[string]*roa + outgoing chan *roa +} + +func (c *roaClient) recieveROA() chan *roa { + return c.outgoing +} + +func (c *roaClient) handleRTRMsg(r *roa) { + if r.Prefix.To4() != nil { + c.roas[bgp.RF_IPv4_UC][r.key()] = r + } else { + c.roas[bgp.RF_IPv6_UC][r.key()] = r + } +} + +func (c *roaClient) handleGRPC(grpcReq *GrpcRequest) { + if roas, ok := c.roas[grpcReq.RouteFamily]; ok { + for _, r := range roas { + result := &GrpcResponse{} + result.Data = r.toApiStruct() + grpcReq.ResponseCh <- result + } + } + close(grpcReq.ResponseCh) +} + +func newROAClient(url string) (*roaClient, error) { + c := &roaClient{ + roas: make(map[bgp.RouteFamily]map[string]*roa), + } + c.roas[bgp.RF_IPv4_UC] = make(map[string]*roa) + c.roas[bgp.RF_IPv6_UC] = make(map[string]*roa) + + if url == "" { + return c, nil + } + + conn, err := net.Dial("tcp", url) + if err != nil { + return c, err + } + + r := bgp.NewRTRResetQuery() + data, _ := r.Serialize() + conn.Write(data) + reader := bufio.NewReader(conn) + scanner := bufio.NewScanner(reader) + scanner.Split(bgp.SplitRTR) + + ch := make(chan *roa) + c.outgoing = ch + + go func(ch chan *roa) { + for scanner.Scan() { + m, _ := bgp.ParseRTR(scanner.Bytes()) + if m != nil { + switch msg := m.(type) { + case *bgp.RTRIPPrefix: + p := make([]byte, len(msg.Prefix)) + copy(p, msg.Prefix) + ch <- &roa{ + AS: msg.AS, + PrefixLen: msg.PrefixLen, + MaxLen: msg.MaxLen, + Prefix: p, + } + } + + } + } + }(ch) + + return c, nil +} diff --git a/server/server.go b/server/server.go index ef0b2ce3..dfc7058a 100644 --- a/server/server.go +++ b/server/server.go @@ -79,9 +79,10 @@ type BgpServer struct { neighborMap map[string]*Peer localRibMap map[string]*LocalRib zclient *zebra.Client + roaClient *roaClient } -func NewBgpServer(port int) *BgpServer { +func NewBgpServer(port int, roaURL string) *BgpServer { b := BgpServer{} b.globalTypeCh = make(chan config.Global) b.addedPeerCh = make(chan config.Neighbor) @@ -91,6 +92,7 @@ func NewBgpServer(port int) *BgpServer { b.localRibMap = make(map[string]*LocalRib) b.neighborMap = make(map[string]*Peer) b.listenPort = port + b.roaClient, _ = newROAClient(roaURL) return &b } @@ -214,6 +216,8 @@ func (server *BgpServer) Serve() { } select { + case rmsg := <-server.roaClient.recieveROA(): + server.roaClient.handleRTRMsg(rmsg) case zmsg := <-zapiMsgCh: handleZapiMsg(zmsg) case conn := <-acceptCh: @@ -1289,6 +1293,8 @@ func (server *BgpServer) handleGrpc(grpcReq *GrpcRequest) []*SenderMsg { server.broadcastReqs = append(server.broadcastReqs, grpcReq) case REQ_MRT_GLOBAL_RIB: server.handleMrt(grpcReq) + case REQ_RPKI: + server.roaClient.handleGRPC(grpcReq) default: errmsg := fmt.Errorf("Unknown request type: %v", grpcReq.RequestType) result := &GrpcResponse{ |