func addRoa(addr string, tree *radix.Tree, as uint32, prefix []byte, prefixLen, maxLen uint8) { key := table.IpToRadixkey(prefix, prefixLen) b, _ := tree.Get(key) if b == nil { p := make([]byte, len(prefix)) copy(p, prefix) b := &RoaBucket{ PrefixLen: prefixLen, Prefix: p, entries: []*Roa{NewRoa(addr, maxLen, as)}, } tree.Insert(key, b) } else { bucket := b.(*RoaBucket) for _, r := range bucket.entries { if r.MaxLen == maxLen && r.Src == addr { // we already have? for _, a := range r.AS { if a == as { return } } r.AS = append(r.AS, as) return } } bucket.entries = append(bucket.entries, NewRoa(addr, maxLen, as)) } }
func (m *roaManager) roa2tree(roa *ROA) (*radix.Tree, string) { tree := m.Roas[bgp.RF_IPv4_UC] if roa.Family == bgp.AFI_IP6 { tree = m.Roas[bgp.RF_IPv6_UC] } return tree, table.IpToRadixkey(roa.Prefix.Prefix, roa.Prefix.Length) }
func validateOne(tree *radix.Tree, cidr string, as uint32) config.RpkiValidationResultType { _, n, _ := net.ParseCIDR(cidr) ones, _ := n.Mask.Size() prefixLen := uint8(ones) _, b, _ := tree.LongestPrefix(table.IpToRadixkey(n.IP, prefixLen)) if b == nil { return config.RPKI_VALIDATION_RESULT_TYPE_NOT_FOUND } else { result := config.RPKI_VALIDATION_RESULT_TYPE_INVALID bucket, _ := b.(*roaBucket) for _, r := range bucket.entries { if prefixLen > r.MaxLen { continue } y := func(x uint32, asList []uint32) bool { for _, as := range asList { if x == as { return true } } return false }(as, r.AS) if y { result = config.RPKI_VALIDATION_RESULT_TYPE_VALID break } } return result } }
func validatePath(ownAs uint32, tree *radix.Tree, cidr string, asPath *bgp.PathAttributeAsPath) (config.RpkiValidationResultType, []*roa) { var as uint32 if asPath == nil || len(asPath.Value) == 0 { return config.RPKI_VALIDATION_RESULT_TYPE_NOT_FOUND, []*roa{} } asParam := asPath.Value[len(asPath.Value)-1].(*bgp.As4PathParam) switch asParam.Type { case bgp.BGP_ASPATH_ATTR_TYPE_SEQ: if len(asParam.AS) == 0 { return config.RPKI_VALIDATION_RESULT_TYPE_NOT_FOUND, []*roa{} } as = asParam.AS[len(asParam.AS)-1] case bgp.BGP_ASPATH_ATTR_TYPE_CONFED_SET, bgp.BGP_ASPATH_ATTR_TYPE_CONFED_SEQ: as = ownAs default: return config.RPKI_VALIDATION_RESULT_TYPE_NOT_FOUND, []*roa{} } _, n, _ := net.ParseCIDR(cidr) ones, _ := n.Mask.Size() prefixLen := uint8(ones) _, b, _ := tree.LongestPrefix(table.IpToRadixkey(n.IP, prefixLen)) if b == nil { return config.RPKI_VALIDATION_RESULT_TYPE_NOT_FOUND, []*roa{} } roaList := make([]*roa, 0) result := config.RPKI_VALIDATION_RESULT_TYPE_INVALID bucket, _ := b.(*roaBucket) for _, r := range bucket.entries { if prefixLen > r.MaxLen { continue } y := func(x uint32, asList []uint32) bool { for _, as := range asList { if x == as { return true } } return false }(as, r.AS) if y { return config.RPKI_VALIDATION_RESULT_TYPE_VALID, []*roa{r} } roaList = append(roaList, r) } return result, roaList }
func deleteROA(client *roaClient, family int, tree *radix.Tree, as uint32, prefix []byte, prefixLen, maxLen uint8) { host := client.host key := table.IpToRadixkey(prefix, prefixLen) b, _ := tree.Get(key) isDeleted := func() bool { if b != nil { bucket := b.(*roaBucket) for _, r := range bucket.entries { if r.MaxLen == maxLen && r.Src == host { for idx, a := range r.AS { if a == as { r.AS = append(r.AS[:idx], r.AS[idx+1:]...) if len(bucket.entries) == 0 { tree.Delete(key) } return true } } } } } return false }() if isDeleted { client.records[family]-- isNoPrefix := func() bool { if b, _ := tree.Get(key); b != nil { bucket := b.(*roaBucket) for _, r := range bucket.entries { if r.Src == host { return false } } return true } else { return true } }() if isNoPrefix { client.prefixes[family]-- } } else { log.Info("can't withdraw a roa", net.IP(prefix).String(), as, prefixLen, maxLen) } }
func validatePath(ownAs uint32, tree *radix.Tree, cidr string, asPath *bgp.PathAttributeAsPath) config.RpkiValidationResultType { var as uint32 if len(asPath.Value) == 0 { as = ownAs } else { asParam := asPath.Value[len(asPath.Value)-1].(*bgp.As4PathParam) switch asParam.Type { case bgp.BGP_ASPATH_ATTR_TYPE_SEQ: if len(asParam.AS) == 0 { as = ownAs } else { as = asParam.AS[len(asParam.AS)-1] } case bgp.BGP_ASPATH_ATTR_TYPE_CONFED_SET, bgp.BGP_ASPATH_ATTR_TYPE_CONFED_SEQ: as = ownAs default: return config.RPKI_VALIDATION_RESULT_TYPE_NOT_FOUND } } _, n, _ := net.ParseCIDR(cidr) ones, _ := n.Mask.Size() prefixLen := uint8(ones) _, b, _ := tree.LongestPrefix(table.IpToRadixkey(n.IP, prefixLen)) if b == nil { return config.RPKI_VALIDATION_RESULT_TYPE_NOT_FOUND } bucket, _ := b.(*roaBucket) for _, r := range bucket.entries { if prefixLen > r.MaxLen { continue } if r.AS == as { return config.RPKI_VALIDATION_RESULT_TYPE_VALID } } return config.RPKI_VALIDATION_RESULT_TYPE_INVALID }
func addROA(tree *radix.Tree, as uint32, prefix []byte, prefixLen, maxLen uint8) { key := table.IpToRadixkey(prefix, prefixLen) b, _ := tree.Get(key) if b == nil { p := make([]byte, len(prefix)) copy(p, prefix) r := &roa{ AS: []uint32{as}, MaxLen: maxLen, } b := &roaBucket{ PrefixLen: prefixLen, Prefix: p, entries: []*roa{r}, } tree.Insert(key, b) } else { bucket := b.(*roaBucket) found := false for _, r := range bucket.entries { if r.MaxLen == maxLen { found = true r.AS = append(r.AS, as) } } if found == false { r := &roa{ MaxLen: maxLen, AS: []uint32{as}, } bucket.entries = append(bucket.entries, r) } } }
func addROA(client *roaClient, family int, tree *radix.Tree, as uint32, prefix []byte, prefixLen, maxLen uint8) { host := client.host key := table.IpToRadixkey(prefix, prefixLen) b, _ := tree.Get(key) if b == nil { p := make([]byte, len(prefix)) copy(p, prefix) r := &roa{ AS: []uint32{as}, MaxLen: maxLen, Src: host, } b := &roaBucket{ PrefixLen: prefixLen, Prefix: p, entries: []*roa{r}, } r.bucket = b tree.Insert(key, b) client.prefixes[family]++ client.records[family]++ } else { bucket := b.(*roaBucket) isNewPrefix := func() bool { for _, r := range bucket.entries { if r.Src == host { return false } } return true }() if isNewPrefix { client.prefixes[family]++ } for _, r := range bucket.entries { if r.MaxLen == maxLen && r.Src == host { // we already have? for _, a := range r.AS { if a == as { return } } r.AS = append(r.AS, as) client.records[family]++ return } } r := &roa{ bucket: bucket, MaxLen: maxLen, AS: []uint32{as}, Src: host, } bucket.entries = append(bucket.entries, r) client.records[family]++ } }