package config import ( "fmt" "net" "strconv" "strings" "github.com/luscis/openlan/pkg/libol" ) var ( EspAuth = "8bc736635c0642aebc20ba5420c3e93a" EspCrypt = "4ac161f6635843b8b02c60cc36822515" EspLocalUdp = 4500 EspRemoteUdp = 4500 ) func Addr2Cidr(addr string) string { if !strings.Contains(addr, "/") { return addr + "/32" } return addr } func SetLocalUdp(port string) { if udp, err := strconv.Atoi(port); err == nil { EspLocalUdp = udp } } type EspState struct { Local string `json:"local,omitempty"` LocalIp net.IP `json:"localAddr,omitempty"` Remote string `json:"remote,omitempty"` RemotePort int `json:"remotePort,omitempty"` RemoteIp net.IP `json:"remoteAddr,omitempty"` Encap string `json:"encapsulation,omitempty"` Auth string `json:"auth,omitempty"` Crypt string `json:"crypt,omitempty"` } func (s *EspState) Padding(value string, size int) string { return strings.Repeat(value, 64/len(value))[:size] } func (s *EspState) Merge(obj *EspState) { if obj == nil { return } if s.Local == "" { s.Local = obj.Local } if s.Auth == "" { s.Auth = obj.Auth } if s.Crypt == "" { s.Crypt = obj.Crypt } if s.RemotePort == 0 { s.RemotePort = obj.RemotePort } } func (s *EspState) Correct() { if addr, _ := net.LookupIP(s.Local); len(addr) > 0 { s.LocalIp = addr[0] } if addr, _ := net.LookupIP(s.Remote); len(addr) > 0 { s.RemoteIp = addr[0] } if s.LocalIp == nil && s.RemoteIp != nil { addr, _ := libol.GetLocalByGw(s.RemoteIp.String()) s.Local = addr.String() s.LocalIp = addr } if s.Crypt == "" { s.Crypt = s.Auth } if s.Auth == "" { s.Auth = EspAuth } if s.Crypt == "" { s.Crypt = EspCrypt } if s.Encap == "" { s.Encap = "udp" } if s.RemotePort == 0 { s.RemotePort = EspRemoteUdp } s.Auth = s.Padding(s.Auth, 32) s.Crypt = s.Padding(s.Crypt, 32) } type EspPolicy struct { Source string `json:"source,omitempty"` Dest string `json:"destination,omitempty"` Priority int `json:"priority,omitempty"` } func (p *EspPolicy) Correct() { if p.Source == "" { p.Source = "0.0.0.0/0" } p.Priority = 128 - libol.GetPrefixLen(p.Dest) } type EspMember struct { Name string `json:"name,omitempty"` Address string `json:"address,omitempty"` Peer string `json:"peer"` Spi int `json:"spi"` State EspState `json:"state"` Policies []*EspPolicy `json:"policies"` } func (m *EspMember) Correct() { if m.Name == "" { m.Name = fmt.Sprintf("spi:%d", m.Spi) } else if m.Spi == 0 { _, _ = fmt.Sscanf(m.Name, "spi:%d", &m.Spi) } if m.Address == "" || m.Peer == "" { return } m.Peer = Addr2Cidr(m.Peer) m.Address = Addr2Cidr(m.Address) m.State.Correct() if m.Policies == nil { m.Policies = make([]*EspPolicy, 0, 2) } found := -1 for index, pol := range m.Policies { pol.Correct() if pol.Dest != m.Peer { continue } found = index } if found < 0 { pol := &EspPolicy{ Dest: m.Peer, } pol.Correct() m.Policies = append(m.Policies, pol) } } func (m *EspMember) AddPolicy(obj *EspPolicy) { found := -1 for index, po := range m.Policies { if po.Dest != obj.Dest { continue } found = index po.Source = obj.Source break } if found < 0 { obj.Correct() m.Policies = append(m.Policies, obj) } } func (m *EspMember) RemovePolicy(dest string) bool { found := -1 for index, po := range m.Policies { if po.Dest != dest { continue } found = index break } if found >= 0 { copy(m.Policies[found:], m.Policies[found+1:]) m.Policies = m.Policies[:len(m.Policies)-1] } return found >= 0 } type EspSpecifies struct { Name string `json:"name"` Address string `json:"address,omitempty"` State EspState `json:"state,omitempty"` Members []*EspMember `json:"members"` Listen string `json:"listen,omitempty"` TcpMss int `json:"tcpMss"` } func (n *EspSpecifies) Correct() { if n.Listen != "" { addr, port := libol.GetHostPort(n.Listen) if addr != "" { n.State.Local = addr } if port != "" { SetLocalUdp(port) } } n.State.Correct() for _, m := range n.Members { if m.Address == "" { m.Address = n.Address } m.State.Merge(&n.State) m.Correct() } if n.TcpMss == 0 { n.TcpMss = 1430 // 1460 - 20 - 8 } } func (n *EspSpecifies) GetMember(name string) *EspMember { for _, mem := range n.Members { if mem.Name == name { return mem } } return nil } func (n *EspSpecifies) HasRemote(name, addr string) bool { for _, mem := range n.Members { state := mem.State if state.Remote != name || state.RemoteIp.String() == addr { continue } return true } return false } func (n *EspSpecifies) AddMember(obj *EspMember) { found := -1 for index, mem := range n.Members { if mem.Spi != obj.Spi && mem.Name != obj.Name { continue } found = index if len(obj.Policies) == 0 { obj.Policies = mem.Policies } n.Members[index] = obj break } if found < 0 { n.Members = append(n.Members, obj) } } func (n *EspSpecifies) DelMember(name string) bool { found := -1 for index, mem := range n.Members { if mem.Name != name { continue } found = index break } if found >= 0 { copy(n.Members[found:], n.Members[found+1:]) n.Members = n.Members[:len(n.Members)-1] } return found >= 0 }