Add app source, add vendoring and module support
This commit is contained in:
9677
vendor/github.com/osrg/gobgp/pkg/packet/bgp/bgp.go
generated
vendored
Normal file
9677
vendor/github.com/osrg/gobgp/pkg/packet/bgp/bgp.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
28
vendor/github.com/osrg/gobgp/pkg/packet/bgp/bgpattrtype_string.go
generated
vendored
Normal file
28
vendor/github.com/osrg/gobgp/pkg/packet/bgp/bgpattrtype_string.go
generated
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
// generated by stringer -type BGPAttrType bgp.go; DO NOT EDIT
|
||||
|
||||
package bgp
|
||||
|
||||
import "fmt"
|
||||
|
||||
const (
|
||||
_BGPAttrType_name_0 = "BGP_ATTR_TYPE_ORIGINBGP_ATTR_TYPE_AS_PATHBGP_ATTR_TYPE_NEXT_HOPBGP_ATTR_TYPE_MULTI_EXIT_DISCBGP_ATTR_TYPE_LOCAL_PREFBGP_ATTR_TYPE_ATOMIC_AGGREGATEBGP_ATTR_TYPE_AGGREGATORBGP_ATTR_TYPE_COMMUNITIESBGP_ATTR_TYPE_ORIGINATOR_IDBGP_ATTR_TYPE_CLUSTER_LIST"
|
||||
_BGPAttrType_name_1 = "BGP_ATTR_TYPE_MP_REACH_NLRIBGP_ATTR_TYPE_MP_UNREACH_NLRIBGP_ATTR_TYPE_EXTENDED_COMMUNITIESBGP_ATTR_TYPE_AS4_PATHBGP_ATTR_TYPE_AS4_AGGREGATOR"
|
||||
)
|
||||
|
||||
var (
|
||||
_BGPAttrType_index_0 = [...]uint8{0, 20, 41, 63, 92, 116, 146, 170, 195, 222, 248}
|
||||
_BGPAttrType_index_1 = [...]uint8{0, 27, 56, 90, 112, 140}
|
||||
)
|
||||
|
||||
func (i BGPAttrType) String() string {
|
||||
switch {
|
||||
case 1 <= i && i <= 10:
|
||||
i -= 1
|
||||
return _BGPAttrType_name_0[_BGPAttrType_index_0[i]:_BGPAttrType_index_0[i+1]]
|
||||
case 14 <= i && i <= 18:
|
||||
i -= 14
|
||||
return _BGPAttrType_name_1[_BGPAttrType_index_1[i]:_BGPAttrType_index_1[i+1]]
|
||||
default:
|
||||
return fmt.Sprintf("BGPAttrType(%d)", i)
|
||||
}
|
||||
}
|
||||
327
vendor/github.com/osrg/gobgp/pkg/packet/bgp/constant.go
generated
vendored
Normal file
327
vendor/github.com/osrg/gobgp/pkg/packet/bgp/constant.go
generated
vendored
Normal file
@@ -0,0 +1,327 @@
|
||||
// Copyright (C) 2014 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 bgp
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const AS_TRANS = 23456
|
||||
|
||||
const BGP_PORT = 179
|
||||
|
||||
type FSMState int
|
||||
|
||||
const (
|
||||
BGP_FSM_IDLE FSMState = iota
|
||||
BGP_FSM_CONNECT
|
||||
BGP_FSM_ACTIVE
|
||||
BGP_FSM_OPENSENT
|
||||
BGP_FSM_OPENCONFIRM
|
||||
BGP_FSM_ESTABLISHED
|
||||
)
|
||||
|
||||
// partially taken from http://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml
|
||||
type Protocol int
|
||||
|
||||
const (
|
||||
Unknown Protocol = iota
|
||||
ICMP = 0x01
|
||||
IGMP = 0x02
|
||||
TCP = 0x06
|
||||
EGP = 0x08
|
||||
IGP = 0x09
|
||||
UDP = 0x11
|
||||
RSVP = 0x2e
|
||||
GRE = 0x2f
|
||||
OSPF = 0x59
|
||||
IPIP = 0x5e
|
||||
PIM = 0x67
|
||||
SCTP = 0x84
|
||||
)
|
||||
|
||||
var ProtocolNameMap = map[Protocol]string{
|
||||
Unknown: "unknown",
|
||||
ICMP: "icmp",
|
||||
IGMP: "igmp",
|
||||
TCP: "tcp",
|
||||
EGP: "egp",
|
||||
IGP: "igp",
|
||||
UDP: "udp",
|
||||
RSVP: "rsvp",
|
||||
GRE: "gre",
|
||||
OSPF: "ospf",
|
||||
IPIP: "ipip",
|
||||
PIM: "pim",
|
||||
SCTP: "sctp",
|
||||
}
|
||||
|
||||
func (p Protocol) String() string {
|
||||
name, ok := ProtocolNameMap[p]
|
||||
if !ok {
|
||||
return fmt.Sprintf("%d", p)
|
||||
}
|
||||
return name
|
||||
}
|
||||
|
||||
type TCPFlag int
|
||||
|
||||
const (
|
||||
_ TCPFlag = iota
|
||||
TCP_FLAG_FIN = 0x01
|
||||
TCP_FLAG_SYN = 0x02
|
||||
TCP_FLAG_RST = 0x04
|
||||
TCP_FLAG_PUSH = 0x08
|
||||
TCP_FLAG_ACK = 0x10
|
||||
TCP_FLAG_URGENT = 0x20
|
||||
TCP_FLAG_ECE = 0x40
|
||||
TCP_FLAG_CWR = 0x80
|
||||
)
|
||||
|
||||
var TCPFlagNameMap = map[TCPFlag]string{
|
||||
TCP_FLAG_FIN: "F",
|
||||
TCP_FLAG_SYN: "S",
|
||||
TCP_FLAG_RST: "R",
|
||||
TCP_FLAG_PUSH: "P",
|
||||
TCP_FLAG_ACK: "A",
|
||||
TCP_FLAG_URGENT: "U",
|
||||
TCP_FLAG_CWR: "C",
|
||||
TCP_FLAG_ECE: "E",
|
||||
}
|
||||
|
||||
// Prepares a sorted list of flags because map iterations does not happen
|
||||
// in a consistent order in Golang.
|
||||
var TCPSortedFlags = []TCPFlag{
|
||||
TCP_FLAG_FIN,
|
||||
TCP_FLAG_SYN,
|
||||
TCP_FLAG_RST,
|
||||
TCP_FLAG_PUSH,
|
||||
TCP_FLAG_ACK,
|
||||
TCP_FLAG_URGENT,
|
||||
TCP_FLAG_ECE,
|
||||
TCP_FLAG_CWR,
|
||||
}
|
||||
|
||||
func (f TCPFlag) String() string {
|
||||
flags := make([]string, 0, len(TCPSortedFlags))
|
||||
for _, v := range TCPSortedFlags {
|
||||
if f&v > 0 {
|
||||
flags = append(flags, TCPFlagNameMap[v])
|
||||
}
|
||||
}
|
||||
return strings.Join(flags, "")
|
||||
}
|
||||
|
||||
type BitmaskFlagOp uint8
|
||||
|
||||
const (
|
||||
BITMASK_FLAG_OP_OR BitmaskFlagOp = iota
|
||||
BITMASK_FLAG_OP_MATCH = 0x01
|
||||
BITMASK_FLAG_OP_NOT = 0x02
|
||||
BITMASK_FLAG_OP_NOT_MATCH = 0x03
|
||||
BITMASK_FLAG_OP_AND = 0x40
|
||||
BITMASK_FLAG_OP_END = 0x80
|
||||
)
|
||||
|
||||
var BitmaskFlagOpNameMap = map[BitmaskFlagOp]string{
|
||||
BITMASK_FLAG_OP_OR: " ",
|
||||
BITMASK_FLAG_OP_AND: "&",
|
||||
BITMASK_FLAG_OP_END: "E",
|
||||
BITMASK_FLAG_OP_NOT: "!",
|
||||
BITMASK_FLAG_OP_MATCH: "=",
|
||||
}
|
||||
|
||||
// Note: Meaning of "" is different from that of the numeric operator because
|
||||
// RFC5575 says if the Match bit in the bitmask operand is set, it should be
|
||||
// "strictly" matching against the given value.
|
||||
var BitmaskFlagOpValueMap = map[string]BitmaskFlagOp{
|
||||
" ": BITMASK_FLAG_OP_OR,
|
||||
"": BITMASK_FLAG_OP_OR,
|
||||
"==": BITMASK_FLAG_OP_MATCH,
|
||||
"=": BITMASK_FLAG_OP_MATCH,
|
||||
"!": BITMASK_FLAG_OP_NOT,
|
||||
"!=": BITMASK_FLAG_OP_NOT_MATCH,
|
||||
"=!": BITMASK_FLAG_OP_NOT_MATCH, // For the backward compatibility
|
||||
"&": BITMASK_FLAG_OP_AND,
|
||||
"E": BITMASK_FLAG_OP_END,
|
||||
}
|
||||
|
||||
func (f BitmaskFlagOp) String() string {
|
||||
ops := make([]string, 0)
|
||||
if f&BITMASK_FLAG_OP_AND > 0 {
|
||||
ops = append(ops, BitmaskFlagOpNameMap[BITMASK_FLAG_OP_AND])
|
||||
} else {
|
||||
ops = append(ops, BitmaskFlagOpNameMap[BITMASK_FLAG_OP_OR])
|
||||
}
|
||||
if f&BITMASK_FLAG_OP_NOT > 0 {
|
||||
ops = append(ops, BitmaskFlagOpNameMap[BITMASK_FLAG_OP_NOT])
|
||||
}
|
||||
if f&BITMASK_FLAG_OP_MATCH > 0 {
|
||||
ops = append(ops, BitmaskFlagOpNameMap[BITMASK_FLAG_OP_MATCH])
|
||||
}
|
||||
return strings.Join(ops, "")
|
||||
}
|
||||
|
||||
type FragmentFlag int
|
||||
|
||||
const (
|
||||
FRAG_FLAG_NOT FragmentFlag = iota
|
||||
FRAG_FLAG_DONT = 0x01
|
||||
FRAG_FLAG_IS = 0x02
|
||||
FRAG_FLAG_FIRST = 0x04
|
||||
FRAG_FLAG_LAST = 0x08
|
||||
)
|
||||
|
||||
var FragmentFlagNameMap = map[FragmentFlag]string{
|
||||
FRAG_FLAG_NOT: "not-a-fragment",
|
||||
FRAG_FLAG_DONT: "dont-fragment",
|
||||
FRAG_FLAG_IS: "is-fragment",
|
||||
FRAG_FLAG_FIRST: "first-fragment",
|
||||
FRAG_FLAG_LAST: "last-fragment",
|
||||
}
|
||||
|
||||
// Prepares a sorted list of flags because map iterations does not happen
|
||||
// in a consistent order in Golang.
|
||||
var FragmentSortedFlags = []FragmentFlag{
|
||||
FRAG_FLAG_NOT,
|
||||
FRAG_FLAG_DONT,
|
||||
FRAG_FLAG_IS,
|
||||
FRAG_FLAG_FIRST,
|
||||
FRAG_FLAG_LAST,
|
||||
}
|
||||
|
||||
func (f FragmentFlag) String() string {
|
||||
flags := make([]string, 0, len(FragmentSortedFlags))
|
||||
for _, v := range FragmentSortedFlags {
|
||||
if f&v > 0 {
|
||||
flags = append(flags, FragmentFlagNameMap[v])
|
||||
}
|
||||
}
|
||||
// Note: If multiple bits are set, joins them with "+".
|
||||
return strings.Join(flags, "+")
|
||||
}
|
||||
|
||||
type DECNumOp uint8
|
||||
|
||||
const (
|
||||
DEC_NUM_OP_TRUE DECNumOp = iota // true always with END bit set
|
||||
DEC_NUM_OP_EQ = 0x01
|
||||
DEC_NUM_OP_GT = 0x02
|
||||
DEC_NUM_OP_GT_EQ = 0x03
|
||||
DEC_NUM_OP_LT = 0x04
|
||||
DEC_NUM_OP_LT_EQ = 0x05
|
||||
DEC_NUM_OP_NOT_EQ = 0x06
|
||||
DEC_NUM_OP_FALSE = 0x07 // false always with END bit set
|
||||
DEC_NUM_OP_OR = 0x00
|
||||
DEC_NUM_OP_AND = 0x40
|
||||
DEC_NUM_OP_END = 0x80
|
||||
)
|
||||
|
||||
var DECNumOpNameMap = map[DECNumOp]string{
|
||||
DEC_NUM_OP_TRUE: "true",
|
||||
DEC_NUM_OP_EQ: "==",
|
||||
DEC_NUM_OP_GT: ">",
|
||||
DEC_NUM_OP_GT_EQ: ">=",
|
||||
DEC_NUM_OP_LT: "<",
|
||||
DEC_NUM_OP_LT_EQ: "<=",
|
||||
DEC_NUM_OP_NOT_EQ: "!=",
|
||||
DEC_NUM_OP_FALSE: "false",
|
||||
//DEC_NUM_OP_OR: " ", // duplicate with DEC_NUM_OP_TRUE
|
||||
DEC_NUM_OP_AND: "&",
|
||||
DEC_NUM_OP_END: "E",
|
||||
}
|
||||
|
||||
var DECNumOpValueMap = map[string]DECNumOp{
|
||||
"true": DEC_NUM_OP_TRUE,
|
||||
"": DEC_NUM_OP_EQ,
|
||||
"==": DEC_NUM_OP_EQ,
|
||||
"=": DEC_NUM_OP_EQ,
|
||||
">": DEC_NUM_OP_GT,
|
||||
">=": DEC_NUM_OP_GT_EQ,
|
||||
"<": DEC_NUM_OP_LT,
|
||||
"<=": DEC_NUM_OP_LT_EQ,
|
||||
"!=": DEC_NUM_OP_NOT_EQ,
|
||||
"=!": DEC_NUM_OP_NOT_EQ,
|
||||
"!": DEC_NUM_OP_NOT_EQ,
|
||||
"false": DEC_NUM_OP_FALSE,
|
||||
" ": DEC_NUM_OP_OR,
|
||||
"&": DEC_NUM_OP_AND,
|
||||
"E": DEC_NUM_OP_END,
|
||||
}
|
||||
|
||||
func (f DECNumOp) String() string {
|
||||
ops := make([]string, 0)
|
||||
logicFlag := DECNumOp(f & 0xc0) // higher 2 bits
|
||||
if logicFlag&DEC_NUM_OP_AND > 0 {
|
||||
ops = append(ops, DECNumOpNameMap[DEC_NUM_OP_AND])
|
||||
} else {
|
||||
ops = append(ops, " ") // DEC_NUM_OP_OR
|
||||
}
|
||||
// Omits DEC_NUM_OP_END
|
||||
cmpFlag := DECNumOp(f & 0x7) // lower 3 bits
|
||||
for v, s := range DECNumOpNameMap {
|
||||
if cmpFlag == v {
|
||||
ops = append(ops, s)
|
||||
break
|
||||
}
|
||||
}
|
||||
return strings.Join(ops, "")
|
||||
}
|
||||
|
||||
// Potentially taken from https://www.iana.org/assignments/ieee-802-numbers/ieee-802-numbers.xhtml
|
||||
type EthernetType int
|
||||
|
||||
const (
|
||||
IPv4 EthernetType = 0x0800
|
||||
ARP EthernetType = 0x0806
|
||||
RARP EthernetType = 0x8035
|
||||
VMTP EthernetType = 0x805B
|
||||
APPLE_TALK EthernetType = 0x809B
|
||||
AARP EthernetType = 0x80F3
|
||||
IPX EthernetType = 0x8137
|
||||
SNMP EthernetType = 0x814C
|
||||
NET_BIOS EthernetType = 0x8191
|
||||
XTP EthernetType = 0x817D
|
||||
IPv6 EthernetType = 0x86DD
|
||||
PPPoE_DISCOVERY EthernetType = 0x8863
|
||||
PPPoE_SESSION EthernetType = 0x8864
|
||||
LOOPBACK EthernetType = 0x9000
|
||||
)
|
||||
|
||||
var EthernetTypeNameMap = map[EthernetType]string{
|
||||
IPv4: "ipv4",
|
||||
ARP: "arp",
|
||||
RARP: "rarp",
|
||||
VMTP: "vmtp",
|
||||
APPLE_TALK: "apple-talk",
|
||||
AARP: "aarp",
|
||||
IPX: "ipx",
|
||||
SNMP: "snmp",
|
||||
NET_BIOS: "net-bios",
|
||||
XTP: "xtp",
|
||||
IPv6: "ipv6",
|
||||
PPPoE_DISCOVERY: "pppoe-discovery",
|
||||
PPPoE_SESSION: "pppoe-session",
|
||||
LOOPBACK: "loopback",
|
||||
}
|
||||
|
||||
func (t EthernetType) String() string {
|
||||
if name, ok := EthernetTypeNameMap[t]; ok {
|
||||
return name
|
||||
}
|
||||
return fmt.Sprintf("%d", t)
|
||||
}
|
||||
16
vendor/github.com/osrg/gobgp/pkg/packet/bgp/esitype_string.go
generated
vendored
Normal file
16
vendor/github.com/osrg/gobgp/pkg/packet/bgp/esitype_string.go
generated
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
// generated by stringer -type=ESIType bgp.go validate.go; DO NOT EDIT
|
||||
|
||||
package bgp
|
||||
|
||||
import "fmt"
|
||||
|
||||
const _ESIType_name = "ESI_ARBITRARYESI_LACPESI_MSTPESI_MACESI_ROUTERIDESI_AS"
|
||||
|
||||
var _ESIType_index = [...]uint8{0, 13, 21, 29, 36, 48, 54}
|
||||
|
||||
func (i ESIType) String() string {
|
||||
if i+1 >= ESIType(len(_ESIType_index)) {
|
||||
return fmt.Sprintf("ESIType(%d)", i)
|
||||
}
|
||||
return _ESIType_name[_ESIType_index[i]:_ESIType_index[i+1]]
|
||||
}
|
||||
16
vendor/github.com/osrg/gobgp/pkg/packet/bgp/fsmstate_string.go
generated
vendored
Normal file
16
vendor/github.com/osrg/gobgp/pkg/packet/bgp/fsmstate_string.go
generated
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
// generated by stringer -type=FSMState -output=fsmstate_string.go bgp.go validate.go mrt.go rtr.go constant.go bmp.go esitype_string.go bgpattrtype_string.go; DO NOT EDIT
|
||||
|
||||
package bgp
|
||||
|
||||
import "fmt"
|
||||
|
||||
const _FSMState_name = "BGP_FSM_IDLEBGP_FSM_CONNECTBGP_FSM_ACTIVEBGP_FSM_OPENSENTBGP_FSM_OPENCONFIRMBGP_FSM_ESTABLISHED"
|
||||
|
||||
var _FSMState_index = [...]uint8{0, 12, 27, 41, 57, 76, 95}
|
||||
|
||||
func (i FSMState) String() string {
|
||||
if i < 0 || i >= FSMState(len(_FSMState_index)-1) {
|
||||
return fmt.Sprintf("FSMState(%d)", i)
|
||||
}
|
||||
return _FSMState_name[_FSMState_index[i]:_FSMState_index[i+1]]
|
||||
}
|
||||
126
vendor/github.com/osrg/gobgp/pkg/packet/bgp/helper.go
generated
vendored
Normal file
126
vendor/github.com/osrg/gobgp/pkg/packet/bgp/helper.go
generated
vendored
Normal file
@@ -0,0 +1,126 @@
|
||||
// Copyright (C) 2016 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 bgp
|
||||
|
||||
func NewTestBGPOpenMessage() *BGPMessage {
|
||||
p1 := NewOptionParameterCapability(
|
||||
[]ParameterCapabilityInterface{NewCapRouteRefresh()})
|
||||
p2 := NewOptionParameterCapability(
|
||||
[]ParameterCapabilityInterface{NewCapMultiProtocol(RF_IPv4_UC)})
|
||||
g := &CapGracefulRestartTuple{4, 2, 3}
|
||||
p3 := NewOptionParameterCapability(
|
||||
[]ParameterCapabilityInterface{NewCapGracefulRestart(false, true, 100,
|
||||
[]*CapGracefulRestartTuple{g})})
|
||||
p4 := NewOptionParameterCapability(
|
||||
[]ParameterCapabilityInterface{NewCapFourOctetASNumber(100000)})
|
||||
p5 := NewOptionParameterCapability(
|
||||
[]ParameterCapabilityInterface{NewCapAddPath([]*CapAddPathTuple{NewCapAddPathTuple(RF_IPv4_UC, BGP_ADD_PATH_BOTH)})})
|
||||
return NewBGPOpenMessage(11033, 303, "100.4.10.3",
|
||||
[]OptionParameterInterface{p1, p2, p3, p4, p5})
|
||||
}
|
||||
|
||||
func NewTestBGPUpdateMessage() *BGPMessage {
|
||||
w1 := NewIPAddrPrefix(23, "121.1.3.2")
|
||||
w2 := NewIPAddrPrefix(17, "100.33.3.0")
|
||||
w := []*IPAddrPrefix{w1, w2}
|
||||
|
||||
aspath1 := []AsPathParamInterface{
|
||||
NewAsPathParam(2, []uint16{1000}),
|
||||
NewAsPathParam(1, []uint16{1001, 1002}),
|
||||
NewAsPathParam(2, []uint16{1003, 1004}),
|
||||
}
|
||||
|
||||
aspath2 := []AsPathParamInterface{
|
||||
NewAs4PathParam(2, []uint32{1000000}),
|
||||
NewAs4PathParam(1, []uint32{1000001, 1002}),
|
||||
NewAs4PathParam(2, []uint32{1003, 100004}),
|
||||
}
|
||||
|
||||
aspath3 := []*As4PathParam{
|
||||
NewAs4PathParam(2, []uint32{1000000}),
|
||||
NewAs4PathParam(1, []uint32{1000001, 1002}),
|
||||
NewAs4PathParam(2, []uint32{1003, 100004}),
|
||||
}
|
||||
|
||||
isTransitive := true
|
||||
|
||||
ecommunities := []ExtendedCommunityInterface{
|
||||
NewTwoOctetAsSpecificExtended(EC_SUBTYPE_ROUTE_TARGET, 10003, 3<<20, isTransitive),
|
||||
NewFourOctetAsSpecificExtended(EC_SUBTYPE_ROUTE_TARGET, 1<<20, 300, isTransitive),
|
||||
NewIPv4AddressSpecificExtended(EC_SUBTYPE_ROUTE_TARGET, "192.2.1.2", 3000, isTransitive),
|
||||
NewOpaqueExtended(false, []byte{1, 2, 3, 4, 5, 6, 7}),
|
||||
NewValidationExtended(VALIDATION_STATE_INVALID),
|
||||
NewUnknownExtended(99, []byte{0, 1, 2, 3, 4, 5, 6, 7}),
|
||||
NewESILabelExtended(1000, true),
|
||||
NewESImportRouteTarget("11:22:33:44:55:66"),
|
||||
NewMacMobilityExtended(123, false),
|
||||
}
|
||||
|
||||
prefixes1 := []AddrPrefixInterface{
|
||||
NewLabeledVPNIPAddrPrefix(24, "192.0.9.0", *NewMPLSLabelStack(1, 2, 3),
|
||||
NewRouteDistinguisherTwoOctetAS(256, 10000)),
|
||||
NewLabeledVPNIPAddrPrefix(24, "192.10.8.0", *NewMPLSLabelStack(5, 6, 7, 8),
|
||||
NewRouteDistinguisherIPAddressAS("10.0.1.1", 10001)),
|
||||
}
|
||||
|
||||
prefixes2 := []AddrPrefixInterface{NewIPv6AddrPrefix(128,
|
||||
"fe80:1234:1234:5667:8967:af12:8912:1023")}
|
||||
|
||||
prefixes3 := []AddrPrefixInterface{NewLabeledVPNIPv6AddrPrefix(128,
|
||||
"fe80:1234:1234:5667:8967:af12:1203:33a1", *NewMPLSLabelStack(5, 6),
|
||||
NewRouteDistinguisherFourOctetAS(5, 6))}
|
||||
|
||||
prefixes4 := []AddrPrefixInterface{NewLabeledIPAddrPrefix(25, "192.168.0.0",
|
||||
*NewMPLSLabelStack(5, 6, 7))}
|
||||
|
||||
prefixes5 := []AddrPrefixInterface{
|
||||
NewEVPNEthernetAutoDiscoveryRoute(NewRouteDistinguisherFourOctetAS(5, 6), EthernetSegmentIdentifier{ESI_ARBITRARY, make([]byte, 9)}, 2, 2),
|
||||
NewEVPNMacIPAdvertisementRoute(NewRouteDistinguisherFourOctetAS(5, 6), EthernetSegmentIdentifier{ESI_ARBITRARY, make([]byte, 9)}, 3, "01:23:45:67:89:ab", "192.2.1.2", []uint32{3, 4}),
|
||||
NewEVPNMulticastEthernetTagRoute(NewRouteDistinguisherFourOctetAS(5, 6), 3, "192.2.1.2"),
|
||||
NewEVPNEthernetSegmentRoute(NewRouteDistinguisherFourOctetAS(5, 6), EthernetSegmentIdentifier{ESI_ARBITRARY, make([]byte, 9)}, "192.2.1.1"),
|
||||
NewEVPNIPPrefixRoute(NewRouteDistinguisherFourOctetAS(5, 6), EthernetSegmentIdentifier{ESI_ARBITRARY, make([]byte, 9)}, 5, 24, "192.2.1.0", "192.3.1.1", 5),
|
||||
}
|
||||
|
||||
p := []PathAttributeInterface{
|
||||
NewPathAttributeOrigin(3),
|
||||
NewPathAttributeAsPath(aspath1),
|
||||
NewPathAttributeAsPath(aspath2),
|
||||
NewPathAttributeNextHop("129.1.1.2"),
|
||||
NewPathAttributeMultiExitDisc(1 << 20),
|
||||
NewPathAttributeLocalPref(1 << 22),
|
||||
NewPathAttributeAtomicAggregate(),
|
||||
NewPathAttributeAggregator(uint16(30002), "129.0.2.99"),
|
||||
NewPathAttributeAggregator(uint32(30002), "129.0.2.99"),
|
||||
NewPathAttributeAggregator(uint32(300020), "129.0.2.99"),
|
||||
NewPathAttributeCommunities([]uint32{1, 3}),
|
||||
NewPathAttributeOriginatorId("10.10.0.1"),
|
||||
NewPathAttributeClusterList([]string{"10.10.0.2", "10.10.0.3"}),
|
||||
NewPathAttributeExtendedCommunities(ecommunities),
|
||||
NewPathAttributeAs4Path(aspath3),
|
||||
NewPathAttributeAs4Aggregator(10000, "112.22.2.1"),
|
||||
NewPathAttributeMpReachNLRI("112.22.2.0", prefixes1),
|
||||
NewPathAttributeMpReachNLRI("1023::", prefixes2),
|
||||
NewPathAttributeMpReachNLRI("fe80::", prefixes3),
|
||||
NewPathAttributeMpReachNLRI("129.1.1.1", prefixes4),
|
||||
NewPathAttributeMpReachNLRI("129.1.1.1", prefixes5),
|
||||
NewPathAttributeMpUnreachNLRI(prefixes1),
|
||||
//NewPathAttributeMpReachNLRI("112.22.2.0", []AddrPrefixInterface{}),
|
||||
//NewPathAttributeMpUnreachNLRI([]AddrPrefixInterface{}),
|
||||
NewPathAttributeUnknown(BGP_ATTR_FLAG_TRANSITIVE, 100, []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}),
|
||||
}
|
||||
n := []*IPAddrPrefix{NewIPAddrPrefix(24, "13.2.3.1")}
|
||||
return NewBGPUpdateMessage(w, p, n)
|
||||
}
|
||||
337
vendor/github.com/osrg/gobgp/pkg/packet/bgp/validate.go
generated
vendored
Normal file
337
vendor/github.com/osrg/gobgp/pkg/packet/bgp/validate.go
generated
vendored
Normal file
@@ -0,0 +1,337 @@
|
||||
package bgp
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"math"
|
||||
"net"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// Validator for BGPUpdate
|
||||
func ValidateUpdateMsg(m *BGPUpdate, rfs map[RouteFamily]BGPAddPathMode, isEBGP bool, isConfed bool) (bool, error) {
|
||||
var strongestError error
|
||||
|
||||
eCode := uint8(BGP_ERROR_UPDATE_MESSAGE_ERROR)
|
||||
eSubCodeAttrList := uint8(BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST)
|
||||
eSubCodeMissing := uint8(BGP_ERROR_SUB_MISSING_WELL_KNOWN_ATTRIBUTE)
|
||||
|
||||
if len(m.NLRI) > 0 || len(m.WithdrawnRoutes) > 0 {
|
||||
if _, ok := rfs[RF_IPv4_UC]; !ok {
|
||||
return false, NewMessageError(0, 0, nil, fmt.Sprintf("Address-family rf %d not available for session", RF_IPv4_UC))
|
||||
}
|
||||
}
|
||||
|
||||
seen := make(map[BGPAttrType]PathAttributeInterface)
|
||||
newAttrs := make([]PathAttributeInterface, 0, len(seen))
|
||||
// check path attribute
|
||||
for _, a := range m.PathAttributes {
|
||||
// check duplication
|
||||
if _, ok := seen[a.GetType()]; !ok {
|
||||
seen[a.GetType()] = a
|
||||
newAttrs = append(newAttrs, a)
|
||||
//check specific path attribute
|
||||
ok, err := ValidateAttribute(a, rfs, isEBGP, isConfed)
|
||||
if !ok {
|
||||
if err.(*MessageError).ErrorHandling == ERROR_HANDLING_SESSION_RESET {
|
||||
return false, err
|
||||
} else if err.(*MessageError).Stronger(strongestError) {
|
||||
strongestError = err
|
||||
}
|
||||
}
|
||||
} else if a.GetType() == BGP_ATTR_TYPE_MP_REACH_NLRI || a.GetType() == BGP_ATTR_TYPE_MP_UNREACH_NLRI {
|
||||
eMsg := "the path attribute apears twice. Type : " + strconv.Itoa(int(a.GetType()))
|
||||
return false, NewMessageError(eCode, eSubCodeAttrList, nil, eMsg)
|
||||
} else {
|
||||
eMsg := "the path attribute apears twice. Type : " + strconv.Itoa(int(a.GetType()))
|
||||
e := NewMessageErrorWithErrorHandling(eCode, eSubCodeAttrList, nil, ERROR_HANDLING_ATTRIBUTE_DISCARD, nil, eMsg)
|
||||
if e.(*MessageError).Stronger(strongestError) {
|
||||
strongestError = e
|
||||
}
|
||||
}
|
||||
}
|
||||
m.PathAttributes = newAttrs
|
||||
|
||||
if _, ok := seen[BGP_ATTR_TYPE_MP_REACH_NLRI]; ok || len(m.NLRI) > 0 {
|
||||
// check the existence of well-known mandatory attributes
|
||||
exist := func(attrs []BGPAttrType) (bool, BGPAttrType) {
|
||||
for _, attr := range attrs {
|
||||
_, ok := seen[attr]
|
||||
if !ok {
|
||||
return false, attr
|
||||
}
|
||||
}
|
||||
return true, 0
|
||||
}
|
||||
mandatory := []BGPAttrType{BGP_ATTR_TYPE_ORIGIN, BGP_ATTR_TYPE_AS_PATH}
|
||||
if len(m.NLRI) > 0 {
|
||||
mandatory = append(mandatory, BGP_ATTR_TYPE_NEXT_HOP)
|
||||
}
|
||||
if ok, t := exist(mandatory); !ok {
|
||||
eMsg := "well-known mandatory attributes are not present. type : " + strconv.Itoa(int(t))
|
||||
data := []byte{byte(t)}
|
||||
e := NewMessageErrorWithErrorHandling(eCode, eSubCodeMissing, data, ERROR_HANDLING_TREAT_AS_WITHDRAW, nil, eMsg)
|
||||
if e.(*MessageError).Stronger(strongestError) {
|
||||
strongestError = e
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return strongestError == nil, strongestError
|
||||
}
|
||||
|
||||
func ValidateAttribute(a PathAttributeInterface, rfs map[RouteFamily]BGPAddPathMode, isEBGP bool, isConfed bool) (bool, error) {
|
||||
var strongestError error
|
||||
|
||||
eCode := uint8(BGP_ERROR_UPDATE_MESSAGE_ERROR)
|
||||
eSubCodeBadOrigin := uint8(BGP_ERROR_SUB_INVALID_ORIGIN_ATTRIBUTE)
|
||||
eSubCodeBadNextHop := uint8(BGP_ERROR_SUB_INVALID_NEXT_HOP_ATTRIBUTE)
|
||||
eSubCodeUnknown := uint8(BGP_ERROR_SUB_UNRECOGNIZED_WELL_KNOWN_ATTRIBUTE)
|
||||
eSubCodeMalformedAspath := uint8(BGP_ERROR_SUB_MALFORMED_AS_PATH)
|
||||
|
||||
checkPrefix := func(l []AddrPrefixInterface) error {
|
||||
for _, prefix := range l {
|
||||
rf := AfiSafiToRouteFamily(prefix.AFI(), prefix.SAFI())
|
||||
if _, ok := rfs[rf]; !ok {
|
||||
return NewMessageError(0, 0, nil, fmt.Sprintf("Address-family %s not available for this session", rf))
|
||||
}
|
||||
switch rf {
|
||||
case RF_FS_IPv4_UC, RF_FS_IPv6_UC, RF_FS_IPv4_VPN, RF_FS_IPv6_VPN, RF_FS_L2_VPN:
|
||||
t := BGPFlowSpecType(0)
|
||||
value := make([]FlowSpecComponentInterface, 0)
|
||||
switch rf {
|
||||
case RF_FS_IPv4_UC:
|
||||
value = prefix.(*FlowSpecIPv4Unicast).Value
|
||||
case RF_FS_IPv6_UC:
|
||||
value = prefix.(*FlowSpecIPv6Unicast).Value
|
||||
case RF_FS_IPv4_VPN:
|
||||
value = prefix.(*FlowSpecIPv4VPN).Value
|
||||
case RF_FS_IPv6_VPN:
|
||||
value = prefix.(*FlowSpecIPv6VPN).Value
|
||||
case RF_FS_L2_VPN:
|
||||
value = prefix.(*FlowSpecL2VPN).Value
|
||||
}
|
||||
for _, v := range value {
|
||||
if v.Type() <= t {
|
||||
return NewMessageError(0, 0, nil, fmt.Sprintf("%s nlri violate strict type ordering", rf))
|
||||
}
|
||||
t = v.Type()
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
switch p := a.(type) {
|
||||
case *PathAttributeMpUnreachNLRI:
|
||||
rf := AfiSafiToRouteFamily(p.AFI, p.SAFI)
|
||||
if _, ok := rfs[rf]; !ok {
|
||||
return false, NewMessageError(0, 0, nil, fmt.Sprintf("Address-family rf %d not available for session", rf))
|
||||
}
|
||||
if err := checkPrefix(p.Value); err != nil {
|
||||
return false, err
|
||||
}
|
||||
case *PathAttributeMpReachNLRI:
|
||||
rf := AfiSafiToRouteFamily(p.AFI, p.SAFI)
|
||||
if _, ok := rfs[rf]; !ok {
|
||||
return false, NewMessageError(0, 0, nil, fmt.Sprintf("Address-family rf %d not available for session", rf))
|
||||
}
|
||||
if err := checkPrefix(p.Value); err != nil {
|
||||
return false, err
|
||||
}
|
||||
case *PathAttributeOrigin:
|
||||
v := uint8(p.Value)
|
||||
if v != BGP_ORIGIN_ATTR_TYPE_IGP &&
|
||||
v != BGP_ORIGIN_ATTR_TYPE_EGP &&
|
||||
v != BGP_ORIGIN_ATTR_TYPE_INCOMPLETE {
|
||||
data, _ := a.Serialize()
|
||||
eMsg := "invalid origin attribute. value : " + strconv.Itoa(int(v))
|
||||
e := NewMessageErrorWithErrorHandling(eCode, eSubCodeBadOrigin, data, getErrorHandlingFromPathAttribute(p.GetType()), nil, eMsg)
|
||||
if e.(*MessageError).Stronger(strongestError) {
|
||||
strongestError = e
|
||||
}
|
||||
}
|
||||
case *PathAttributeNextHop:
|
||||
|
||||
isZero := func(ip net.IP) bool {
|
||||
res := ip[0] & 0xff
|
||||
return res == 0x00
|
||||
}
|
||||
|
||||
isClassDorE := func(ip net.IP) bool {
|
||||
res := ip[0] & 0xe0
|
||||
return res == 0xe0
|
||||
}
|
||||
|
||||
//check IP address represents host address
|
||||
if p.Value.IsLoopback() || isZero(p.Value) || isClassDorE(p.Value) {
|
||||
eMsg := "invalid nexthop address"
|
||||
data, _ := a.Serialize()
|
||||
e := NewMessageErrorWithErrorHandling(eCode, eSubCodeBadNextHop, data, getErrorHandlingFromPathAttribute(p.GetType()), nil, eMsg)
|
||||
if e.(*MessageError).Stronger(strongestError) {
|
||||
strongestError = e
|
||||
}
|
||||
}
|
||||
case *PathAttributeAsPath:
|
||||
if isEBGP {
|
||||
if isConfed {
|
||||
if segType := p.Value[0].GetType(); segType != BGP_ASPATH_ATTR_TYPE_CONFED_SEQ {
|
||||
return false, NewMessageError(eCode, eSubCodeMalformedAspath, nil, fmt.Sprintf("segment type is not confederation seq (%d)", segType))
|
||||
}
|
||||
} else {
|
||||
for _, param := range p.Value {
|
||||
segType := param.GetType()
|
||||
switch segType {
|
||||
case BGP_ASPATH_ATTR_TYPE_CONFED_SET, BGP_ASPATH_ATTR_TYPE_CONFED_SEQ:
|
||||
err := NewMessageErrorWithErrorHandling(
|
||||
eCode, eSubCodeMalformedAspath, nil, getErrorHandlingFromPathAttribute(p.GetType()), nil, fmt.Sprintf("segment type confederation(%d) found", segType))
|
||||
if err.(*MessageError).Stronger(strongestError) {
|
||||
strongestError = err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
case *PathAttributeLargeCommunities:
|
||||
uniq := make([]*LargeCommunity, 0, len(p.Values))
|
||||
for _, x := range p.Values {
|
||||
found := false
|
||||
for _, y := range uniq {
|
||||
if x.String() == y.String() {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
uniq = append(uniq, x)
|
||||
}
|
||||
}
|
||||
p.Values = uniq
|
||||
|
||||
case *PathAttributeUnknown:
|
||||
if p.GetFlags()&BGP_ATTR_FLAG_OPTIONAL == 0 {
|
||||
eMsg := fmt.Sprintf("unrecognized well-known attribute %s", p.GetType())
|
||||
data, _ := a.Serialize()
|
||||
return false, NewMessageError(eCode, eSubCodeUnknown, data, eMsg)
|
||||
}
|
||||
}
|
||||
|
||||
return strongestError == nil, strongestError
|
||||
}
|
||||
|
||||
// validator for PathAttribute
|
||||
func validatePathAttributeFlags(t BGPAttrType, flags BGPAttrFlag) string {
|
||||
|
||||
/*
|
||||
* RFC 4271 P.17 For well-known attributes, the Transitive bit MUST be set to 1.
|
||||
*/
|
||||
if flags&BGP_ATTR_FLAG_OPTIONAL == 0 && flags&BGP_ATTR_FLAG_TRANSITIVE == 0 {
|
||||
eMsg := fmt.Sprintf("well-known attribute %s must have transitive flag 1", t)
|
||||
return eMsg
|
||||
}
|
||||
/*
|
||||
* RFC 4271 P.17 For well-known attributes and for optional non-transitive attributes,
|
||||
* the Partial bit MUST be set to 0.
|
||||
*/
|
||||
if flags&BGP_ATTR_FLAG_OPTIONAL == 0 && flags&BGP_ATTR_FLAG_PARTIAL != 0 {
|
||||
eMsg := fmt.Sprintf("well-known attribute %s must have partial bit 0", t)
|
||||
return eMsg
|
||||
}
|
||||
if flags&BGP_ATTR_FLAG_OPTIONAL != 0 && flags&BGP_ATTR_FLAG_TRANSITIVE == 0 && flags&BGP_ATTR_FLAG_PARTIAL != 0 {
|
||||
eMsg := fmt.Sprintf("optional non-transitive attribute %s must have partial bit 0", t)
|
||||
return eMsg
|
||||
}
|
||||
|
||||
// check flags are correct
|
||||
if f, ok := PathAttrFlags[t]; ok {
|
||||
if f != flags & ^BGP_ATTR_FLAG_EXTENDED_LENGTH & ^BGP_ATTR_FLAG_PARTIAL {
|
||||
eMsg := fmt.Sprintf("flags are invalid. attribute type: %s, expect: %s, actual: %s", t, f, flags)
|
||||
return eMsg
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func validateAsPathValueBytes(data []byte) (bool, error) {
|
||||
eCode := uint8(BGP_ERROR_UPDATE_MESSAGE_ERROR)
|
||||
eSubCode := uint8(BGP_ERROR_SUB_MALFORMED_AS_PATH)
|
||||
if len(data)%2 != 0 {
|
||||
return false, NewMessageError(eCode, eSubCode, nil, "AS PATH length is not odd")
|
||||
}
|
||||
|
||||
tryParse := func(data []byte, use4byte bool) (bool, error) {
|
||||
for len(data) > 0 {
|
||||
if len(data) < 2 {
|
||||
return false, NewMessageError(eCode, eSubCode, nil, "AS PATH header is short")
|
||||
}
|
||||
segType := data[0]
|
||||
if segType == 0 || segType > 4 {
|
||||
return false, NewMessageError(eCode, eSubCode, nil, "unknown AS_PATH seg type")
|
||||
}
|
||||
asNum := data[1]
|
||||
data = data[2:]
|
||||
if asNum == 0 || int(asNum) > math.MaxUint8 {
|
||||
return false, NewMessageError(eCode, eSubCode, nil, "AS PATH the number of AS is incorrect")
|
||||
}
|
||||
segLength := int(asNum)
|
||||
if use4byte {
|
||||
segLength *= 4
|
||||
} else {
|
||||
segLength *= 2
|
||||
}
|
||||
if int(segLength) > len(data) {
|
||||
return false, NewMessageError(eCode, eSubCode, nil, "seg length is short")
|
||||
}
|
||||
data = data[segLength:]
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
_, err := tryParse(data, true)
|
||||
if err == nil {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
_, err = tryParse(data, false)
|
||||
if err == nil {
|
||||
return false, nil
|
||||
}
|
||||
return false, NewMessageError(eCode, eSubCode, nil, "can't parse AS_PATH")
|
||||
}
|
||||
|
||||
func ValidateBGPMessage(m *BGPMessage) error {
|
||||
if m.Header.Len > BGP_MAX_MESSAGE_LENGTH {
|
||||
buf := make([]byte, 2)
|
||||
binary.BigEndian.PutUint16(buf, m.Header.Len)
|
||||
return NewMessageError(BGP_ERROR_MESSAGE_HEADER_ERROR, BGP_ERROR_SUB_BAD_MESSAGE_LENGTH, buf, "too long length")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func ValidateOpenMsg(m *BGPOpen, expectedAS uint32) (uint32, error) {
|
||||
if m.Version != 4 {
|
||||
return 0, NewMessageError(BGP_ERROR_OPEN_MESSAGE_ERROR, BGP_ERROR_SUB_UNSUPPORTED_VERSION_NUMBER, nil, fmt.Sprintf("unsupported version %d", m.Version))
|
||||
}
|
||||
|
||||
as := uint32(m.MyAS)
|
||||
for _, p := range m.OptParams {
|
||||
paramCap, y := p.(*OptionParameterCapability)
|
||||
if !y {
|
||||
continue
|
||||
}
|
||||
for _, c := range paramCap.Capability {
|
||||
if c.Code() == BGP_CAP_FOUR_OCTET_AS_NUMBER {
|
||||
cap := c.(*CapFourOctetASNumber)
|
||||
as = cap.CapValue
|
||||
}
|
||||
}
|
||||
}
|
||||
if expectedAS != 0 && as != expectedAS {
|
||||
return 0, NewMessageError(BGP_ERROR_OPEN_MESSAGE_ERROR, BGP_ERROR_SUB_BAD_PEER_AS, nil, fmt.Sprintf("as number mismatch expected %d, received %d", expectedAS, as))
|
||||
}
|
||||
|
||||
if m.HoldTime < 3 && m.HoldTime != 0 {
|
||||
return 0, NewMessageError(BGP_ERROR_OPEN_MESSAGE_ERROR, BGP_ERROR_SUB_UNACCEPTABLE_HOLD_TIME, nil, fmt.Sprintf("unacceptable hold time %d", m.HoldTime))
|
||||
}
|
||||
return as, nil
|
||||
}
|
||||
Reference in New Issue
Block a user