@@ -3,84 +3,132 @@ package routers
3
3
import (
4
4
"bytes"
5
5
"embed"
6
- "fmt"
6
+ "log"
7
+ "os"
8
+ "strings"
7
9
"text/template"
8
10
9
11
"gitlab.as203038.net/AS203038/looking-glass/server/errs"
10
12
"gitlab.as203038.net/AS203038/looking-glass/server/utils"
11
13
yaml "gopkg.in/yaml.v2"
12
14
)
13
15
16
+ // _tpl_data represents the template data used in the router YAML file.
14
17
type _tpl_data struct {
15
- Cfg * utils.RouterConfig
16
- IP * utils.IPNet
17
- Community string
18
- ASPath string
18
+ Cfg * utils.RouterConfig // Cfg holds the router configuration.
19
+ IP * utils.IPNet // IP holds the IP network information.
20
+ Community string // Community holds the community string.
21
+ ASPath string // ASPath holds the AS path information.
19
22
}
20
23
24
+ // Yaml represents the structure of a YAML file.
21
25
type Yaml struct {
22
- Path string
26
+ Path string // Path represents the file path.
23
27
Template struct {
24
- Name string `yaml:"name"`
28
+ Name string `yaml:"name"` // Name represents the template name.
25
29
Ping struct {
26
- Any []string `yaml:"any"`
27
- IPv4 []string `yaml:"ipv4"`
28
- IPv6 []string `yaml:"ipv6"`
29
- } `yaml:"ping"`
30
+ Any []string `yaml:"any"` // Any represents the list of ping targets for any IP address.
31
+ IPv4 []string `yaml:"ipv4"` // IPv4 represents the list of ping targets for IPv4 addresses.
32
+ IPv6 []string `yaml:"ipv6"` // IPv6 represents the list of ping targets for IPv6 addresses.
33
+ } `yaml:"ping"` // Ping represents the ping section in the template.
30
34
Traceroute struct {
31
- Any []string `yaml:"any"`
32
- IPv4 []string `yaml:"ipv4"`
33
- IPv6 []string `yaml:"ipv6"`
34
- } `yaml:"traceroute"`
35
+ Any []string `yaml:"any"` // Any represents the list of traceroute targets for any IP address.
36
+ IPv4 []string `yaml:"ipv4"` // IPv4 represents the list of traceroute targets for IPv4 addresses.
37
+ IPv6 []string `yaml:"ipv6"` // IPv6 represents the list of traceroute targets for IPv6 addresses.
38
+ } `yaml:"traceroute"` // Traceroute represents the traceroute section in the template.
35
39
BGP struct {
36
- Route []string `yaml:"route"`
37
- Community []string `yaml:"community"`
38
- ASPath []string `yaml:"aspath"`
39
- } `yaml:"bgp"`
40
+ Route []string `yaml:"route"` // Route represents the list of BGP routes.
41
+ Community []string `yaml:"community"` // Community represents the list of BGP communities.
42
+ ASPath []string `yaml:"aspath"` // ASPath represents the list of BGP AS paths.
43
+ } `yaml:"bgp"` // BGP represents the BGP section in the template.
40
44
}
41
45
}
42
46
43
47
//go:embed all:*.yml
44
48
var compiledRouters embed.FS
45
49
50
+ // init is a function that is automatically called before the program starts.
51
+ // It initializes the routers by loading them from the specified directory and bundled routers.
52
+ // It reads YAML files, unmarshals them into router templates, and registers the routers.
53
+ // If the ROUTER_DIR environment variable is set, it loads routers from the specified directory.
54
+ // If the bundled routers exist, it loads them as well.
55
+ // The function logs the registration status of each router.
46
56
func init () {
47
- // Load all routers
57
+ // Check for ROUTER_DIR environment variable
58
+ rd := os .Getenv ("ROUTER_DIR" )
59
+ if rd != "" {
60
+ // Load all routers from ROUTER_DIR
61
+ files , err := os .ReadDir (rd )
62
+ if err != nil {
63
+ log .Panicf ("Could not Read directory %s: %+v" , rd , err )
64
+ }
65
+ log .Printf ("Loading routers from %s\n " , rd )
66
+ for _ , file := range files {
67
+ if file .IsDir () || (! strings .HasSuffix (file .Name (), ".yml" ) && ! strings .HasSuffix (file .Name (), ".yaml" )) {
68
+ continue
69
+ }
70
+ // Rest of the code for processing the file
71
+ y := & Yaml {Path : file .Name ()}
72
+ yamlFile , err := os .ReadFile (rd + "/" + y .Path )
73
+ if err != nil {
74
+ log .Panicf ("Could not Read file %s/%s: %+v" , rd , y .Path , err )
75
+ }
76
+ err = yaml .Unmarshal (yamlFile , & y .Template )
77
+ if err != nil {
78
+ log .Panicf ("Could not Unmarshal file %s/%s: %+v" , rd , y .Path , err )
79
+ }
80
+ if y .Template .Name == "" {
81
+ log .Printf ("Router name cannot be empty (%s/%s)" , rd , y .Path )
82
+ continue
83
+ }
84
+ register (y .Template .Name , y )
85
+ log .Printf ("Router %s (%s/%s) registered\n " , y .Template .Name , rd , y .Path )
86
+ }
87
+ }
88
+
89
+ // Load all bundled routers
48
90
files , err := compiledRouters .ReadDir ("." )
49
91
if err != nil {
50
- panic ( err )
92
+ log . Panicf ( "Could not Read builtin directory: %+v" , err )
51
93
}
52
94
for _ , file := range files {
53
- y := & Yaml {}
54
- y .Path = file .Name ()
95
+ y := & Yaml {Path : file .Name ()}
55
96
yamlFile , err := compiledRouters .ReadFile (y .Path )
56
97
if err != nil {
57
- panic ( err )
98
+ log . Panicf ( "Could not Read file builtin:%s: %+v" , y . Path , err )
58
99
}
59
100
err = yaml .Unmarshal (yamlFile , & y .Template )
60
101
if err != nil {
61
- panic (err )
102
+ log .Panicf ("Could not Unmarshal file builtin:%s: %+v" , y .Path , err )
103
+ }
104
+ if _ , ok := _routers [y .Template .Name ]; ! ok {
105
+ register (y .Template .Name , y )
106
+ log .Printf ("Router %s (builtin:%s) registered\n " , y .Template .Name , y .Path )
107
+ } else {
108
+ log .Printf ("Router %s already registered\n " , y .Template .Name )
62
109
}
63
- register (y .Template .Name , y )
64
- fmt .Printf ("Router %s registered\n " , y .Template .Name )
65
110
}
66
111
}
67
112
113
+ // _tpl is a helper function used to generate a list of strings based on the provided template name and data.
114
+ // It takes a template name and data as input and returns a list of strings generated from the template.
115
+ // The function first determines the appropriate template to use based on the template name and the IP version in the data.
116
+ // It then iterates over the selected template(s), executes them with the provided data, and appends the generated strings to the result list.
117
+ // If no template is found for the given name, the function returns nil and an error of type `errs.OperationUnknown`.
68
118
func (rt * Yaml ) _tpl (name string , data _tpl_data ) ([]string , error ) {
69
119
var tpl []string
70
120
var ret []string
71
121
switch name {
72
122
case "ping" :
73
- if rt .Template .Ping .Any != nil {
74
- tpl = rt .Template .Ping .Any
75
- } else if data .IP .IsIPv4 () {
123
+ tpl = rt .Template .Ping .Any
124
+ if data .IP .IsIPv4 () {
76
125
tpl = rt .Template .Ping .IPv4
77
126
} else if data .IP .IsIPv6 () {
78
127
tpl = rt .Template .Ping .IPv6
79
128
}
80
129
case "traceroute" :
81
- if rt .Template .Traceroute .Any != nil {
82
- tpl = rt .Template .Traceroute .Any
83
- } else if data .IP .IsIPv4 () {
130
+ tpl = rt .Template .Traceroute .Any
131
+ if data .IP .IsIPv4 () {
84
132
tpl = rt .Template .Traceroute .IPv4
85
133
} else if data .IP .IsIPv6 () {
86
134
tpl = rt .Template .Traceroute .IPv6
@@ -110,22 +158,31 @@ func (rt *Yaml) _tpl(name string, data _tpl_data) ([]string, error) {
110
158
return ret , nil
111
159
}
112
160
161
+ // Ping sends a ping request to the specified IP address using the provided router configuration.
162
+ // It returns a slice of strings representing the ping response and an error if any.
113
163
func (rt * Yaml ) Ping (cfg * utils.RouterConfig , ip * utils.IPNet ) ([]string , error ) {
114
164
return rt ._tpl ("ping" , _tpl_data {Cfg : cfg , IP : ip })
115
165
}
116
166
167
+ // Traceroute performs a traceroute operation using the provided router configuration and IP address.
168
+ // It returns a slice of strings representing the traceroute results and an error if any.
117
169
func (rt * Yaml ) Traceroute (cfg * utils.RouterConfig , ip * utils.IPNet ) ([]string , error ) {
118
170
return rt ._tpl ("traceroute" , _tpl_data {Cfg : cfg , IP : ip })
119
171
}
120
172
173
+ // BGPRoute generates BGP route configuration based on the provided RouterConfig and IPNet.
174
+ // It returns a slice of strings representing the generated configuration and an error if any.
121
175
func (rt * Yaml ) BGPRoute (cfg * utils.RouterConfig , ip * utils.IPNet ) ([]string , error ) {
122
176
return rt ._tpl ("bgp.route" , _tpl_data {Cfg : cfg , IP : ip })
123
177
}
124
178
179
+ // BGPCommunity returns a list of strings representing the BGP community values for the given router configuration and community.
125
180
func (rt * Yaml ) BGPCommunity (cfg * utils.RouterConfig , community string ) ([]string , error ) {
126
181
return rt ._tpl ("bgp.community" , _tpl_data {Cfg : cfg , Community : community })
127
182
}
128
183
184
+ // BGPASPath returns a slice of strings representing the BGP AS path for the given router configuration and AS path string.
185
+ // It uses the "_tpl" method to render the "bgp.aspath" template with the provided configuration and AS path.
129
186
func (rt * Yaml ) BGPASPath (cfg * utils.RouterConfig , aspath string ) ([]string , error ) {
130
187
return rt ._tpl ("bgp.aspath" , _tpl_data {Cfg : cfg , ASPath : aspath })
131
188
}
0 commit comments