-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathroute.go
More file actions
109 lines (87 loc) · 2.31 KB
/
Copy pathroute.go
File metadata and controls
109 lines (87 loc) · 2.31 KB
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
package clusterf
import (
"fmt"
"github.com/qmsk/clusterf/config"
"github.com/qmsk/clusterf/ipvs"
"net"
)
type Routes map[string]Route
// Return most-specific matching route for given IPv4/IPv6 IP
func (routes Routes) Lookup(ip net.IP) *Route {
var matchRoute Route
var matchLength int = -1
for _, route := range routes {
if match, routeLength := route.match(ip); !match {
} else if routeLength > matchLength {
matchRoute = route
matchLength = routeLength
}
}
if matchLength < 0 {
return nil
} else {
return &matchRoute
}
}
// Update state from config
func configRoutes(configRoutes map[string]config.Route) (Routes, error) {
newRoutes := make(Routes)
for routeName, configRoute := range configRoutes {
var route Route
if err := route.config(configRoute); err != nil {
return nil, fmt.Errorf("Config route %v: %v", routeName, err)
} else {
newRoutes[routeName] = route
}
}
return newRoutes, nil
}
type Route struct {
// default -> nil
Prefix *net.IPNet
// attributes
Gateway net.IP
IPVSMethod *ipvs.FwdMethod // or nil
}
// Build new route state from config
func (route *Route) config(configRoute config.Route) error {
if configRoute.Prefix == "" {
route.Prefix = nil // default
} else if _, ipnet, err := net.ParseCIDR(configRoute.Prefix); err != nil {
return fmt.Errorf("Invalid Prefix: %s", configRoute.Prefix)
} else {
route.Prefix = ipnet
}
if configRoute.Gateway == "" {
route.Gateway = nil
} else if ip := net.ParseIP(configRoute.Gateway); ip == nil {
return fmt.Errorf("Invalid Gateway: %s", configRoute.Gateway)
} else if ip4 := ip.To4(); ip4 != nil {
// normalize from v4-in-v6 form
route.Gateway = ip4
} else {
route.Gateway = ip
}
if configRoute.IPVSMethod == "" {
route.IPVSMethod = nil
} else if fwdMethod, err := ipvs.ParseFwdMethod(configRoute.IPVSMethod); err != nil {
return err
} else {
route.IPVSMethod = &fwdMethod
}
return nil
}
// Match given ip within our prefix
// Returns true if matches, with the length of the matching prefix
// Returns false otherwise
func (route Route) match(ip net.IP) (match bool, length int) {
if route.Prefix == nil {
// default match
return true, 0
} else if !route.Prefix.Contains(ip) {
} else {
prefixLength, _ := route.Prefix.Mask.Size()
return true, prefixLength
}
return false, 0
}