summaryrefslogtreecommitdiffhomepage
path: root/server/rpki.go
blob: 6ad6aa0a85d508fc3b9e7ebed3748d8c09f4f5c2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
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
}