summaryrefslogtreecommitdiffhomepage
path: root/packet/bgp/bgp.go
diff options
context:
space:
mode:
authorIWASE Yusuke <iwase.yusuke0@gmail.com>2017-11-28 11:39:42 +0900
committerFUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>2017-11-28 15:23:04 +0900
commit76c289ea3624502f12d03ee9a5a34340d571df88 (patch)
tree15120098ecd56f831b119edfb87503cd8b69c1bf /packet/bgp/bgp.go
parent5440f32fcd85264b659d126573f447a80eb3db31 (diff)
packet/bgp: Use fixed len types in FlowSpec components
Currently, the "FlowSpecComponentItem" uses int type for the "Op" and "Value" fields, but Golang int type has 4 bytes length on the 32-bit env and 8 bytes length on the 64-bit env. For example, to support the SNAP (Type 20) rule, which has 5 bytes value field, int type has not enough length on 32-bit env. This patch fixes to use the fixed length integer types for the FlowSpec components and avoid overflows of value range. Signed-off-by: IWASE Yusuke <iwase.yusuke0@gmail.com>
Diffstat (limited to 'packet/bgp/bgp.go')
-rw-r--r--packet/bgp/bgp.go90
1 files changed, 45 insertions, 45 deletions
diff --git a/packet/bgp/bgp.go b/packet/bgp/bgp.go
index 86b4cfd7..b7abe886 100644
--- a/packet/bgp/bgp.go
+++ b/packet/bgp/bgp.go
@@ -2988,7 +2988,7 @@ func normalizeFlowSpecOpValues(args []string) []string {
// Parses the FlowSpec numeric operator using the given submatch which should be
// the return value of func (*Regexp) FindStringSubmatch.
-func parseFlowSpecNumericOperator(submatch []string) (operator int, err error) {
+func parseFlowSpecNumericOperator(submatch []string) (operator uint8, err error) {
if submatch[1] == "&" {
operator = DEC_NUM_OP_AND
}
@@ -2996,7 +2996,7 @@ func parseFlowSpecNumericOperator(submatch []string) (operator int, err error) {
if !ok {
return 0, fmt.Errorf("invalid numeric operator: %s%s", submatch[1], submatch[2])
}
- operator |= int(value)
+ operator |= uint8(value)
return operator, nil
}
@@ -3006,7 +3006,7 @@ func parseFlowSpecNumericOperator(submatch []string) (operator int, err error) {
// Note: Each of the args should be formatted in single pair of operator and
// value before calling this function.
// e.g.) "&==100", ">=200" or "&<300"
-func parseFlowSpecNumericOpValues(typ BGPFlowSpecType, args []string, validationFunc func(int) error) (FlowSpecComponentInterface, error) {
+func parseFlowSpecNumericOpValues(typ BGPFlowSpecType, args []string, validationFunc func(uint64) error) (FlowSpecComponentInterface, error) {
argsLen := len(args)
items := make([]*FlowSpecComponentItem, 0, argsLen)
re := regexp.MustCompile("(&?)(==|=|>|>=|<|<=|!|!=|=!)?(\\d+|-\\d|true|false)")
@@ -3023,15 +3023,15 @@ func parseFlowSpecNumericOpValues(typ BGPFlowSpecType, args []string, validation
return nil, err
}
// "true" and "false" is operator, but here handles them as value.
- value := 0
+ var value uint64
switch m[3] {
case "true", "false":
if idx != argsLen-1 {
return nil, fmt.Errorf("%s should be the last of each rule", m[3])
}
- operator = int(DECNumOpValueMap[m[3]])
+ operator = uint8(DECNumOpValueMap[m[3]])
default:
- if value, err = strconv.Atoi(m[3]); err != nil {
+ if value, err = strconv.ParseUint(m[3], 10, 64); err != nil {
return nil, fmt.Errorf("invalid numeric value: %s", m[3])
}
if err = validationFunc(value); err != nil {
@@ -3042,7 +3042,7 @@ func parseFlowSpecNumericOpValues(typ BGPFlowSpecType, args []string, validation
}
// Marks end-of-list bit
- items[argsLen-1].Op |= int(DEC_NUM_OP_END)
+ items[argsLen-1].Op |= uint8(DEC_NUM_OP_END)
return NewFlowSpecComponent(typ, items), nil
}
@@ -3050,8 +3050,8 @@ func parseFlowSpecNumericOpValues(typ BGPFlowSpecType, args []string, validation
func flowSpecNumeric1ByteParser(_ RouteFamily, typ BGPFlowSpecType, args []string) (FlowSpecComponentInterface, error) {
args = normalizeFlowSpecOpValues(args)
- f := func(i int) error {
- if 0 <= i && i <= 0xff { // 1 byte
+ f := func(i uint64) error {
+ if i <= 0xff { // 1 byte
return nil
}
return fmt.Errorf("%s range exceeded", typ.String())
@@ -3063,8 +3063,8 @@ func flowSpecNumeric1ByteParser(_ RouteFamily, typ BGPFlowSpecType, args []strin
func flowSpecNumeric2BytesParser(_ RouteFamily, typ BGPFlowSpecType, args []string) (FlowSpecComponentInterface, error) {
args = normalizeFlowSpecOpValues(args)
- f := func(i int) error {
- if 0 <= i && i <= 0xffff { // 2 bytes
+ f := func(i uint64) error {
+ if i <= 0xffff { // 2 bytes
return nil
}
return fmt.Errorf("%s range exceeded", typ.String())
@@ -3075,7 +3075,7 @@ func flowSpecNumeric2BytesParser(_ RouteFamily, typ BGPFlowSpecType, args []stri
// Parses the FlowSpec bitmask operand using the given submatch which should be
// the return value of func (*Regexp) FindStringSubmatch.
-func parseFlowSpecBitmaskOperand(submatch []string) (operand int, err error) {
+func parseFlowSpecBitmaskOperand(submatch []string) (operand uint8, err error) {
if submatch[1] == "&" {
operand = BITMASK_FLAG_OP_AND
}
@@ -3083,7 +3083,7 @@ func parseFlowSpecBitmaskOperand(submatch []string) (operand int, err error) {
if !ok {
return 0, fmt.Errorf("invalid bitmask operand: %s%s", submatch[1], submatch[2])
}
- operand |= int(value)
+ operand |= uint8(value)
return operand, nil
}
@@ -3173,8 +3173,8 @@ func flowSpecIpProtoParser(_ RouteFamily, typ BGPFlowSpecType, args []string) (F
}
args = strings.Split(s, " ")
- f := func(i int) error {
- if 0 <= i && i <= 0xff { // 1 byte
+ f := func(i uint64) error {
+ if i <= 0xff { // 1 byte
return nil
}
return fmt.Errorf("%s range exceeded", typ.String())
@@ -3211,10 +3211,10 @@ func flowSpecTcpFlagParser(_ RouteFamily, typ BGPFlowSpecType, args []string) (F
if err != nil {
return nil, err
}
- value := 0
+ var value uint64
for flag, name := range TCPFlagNameMap {
if strings.Contains(m[4], name) {
- value |= int(flag)
+ value |= uint64(flag)
}
}
items = append(items, NewFlowSpecComponentItem(operand, value))
@@ -3229,8 +3229,8 @@ func flowSpecTcpFlagParser(_ RouteFamily, typ BGPFlowSpecType, args []string) (F
func flowSpecDscpParser(_ RouteFamily, typ BGPFlowSpecType, args []string) (FlowSpecComponentInterface, error) {
args = normalizeFlowSpecOpValues(args)
- f := func(i int) error {
- if 0 <= i && i < 64 { // 6 bits
+ f := func(i uint64) error {
+ if i < 64 { // 6 bits
return nil
}
return fmt.Errorf("%s range exceeded", typ.String())
@@ -3267,12 +3267,12 @@ func flowSpecFragmentParser(_ RouteFamily, typ BGPFlowSpecType, args []string) (
if err != nil {
return nil, err
}
- value := 0
+ var value uint64
// Example:
// m[3] = "first-fragment+last-fragment"
for flag, name := range FragmentFlagNameMap {
if strings.Contains(m[3], name) {
- value |= int(flag)
+ value |= uint64(flag)
}
}
items = append(items, NewFlowSpecComponentItem(operand, value))
@@ -3292,8 +3292,8 @@ func flowSpecLabelParser(rf RouteFamily, typ BGPFlowSpecType, args []string) (Fl
args = normalizeFlowSpecOpValues(args)
- f := func(i int) error {
- if 0 <= i && i <= 0xfffff { // 20 bits
+ f := func(i uint64) error {
+ if i <= 0xfffff { // 20 bits
return nil
}
return fmt.Errorf("flow label range exceeded")
@@ -3321,8 +3321,8 @@ func flowSpecEtherTypeParser(rf RouteFamily, typ BGPFlowSpecType, args []string)
}
args = strings.Split(s, " ")
- f := func(i int) error {
- if 0 <= i && i <= 0xffff { // 2 bytes
+ f := func(i uint64) error {
+ if i <= 0xffff { // 2 bytes
return nil
}
return fmt.Errorf("%s range exceeded", typ.String())
@@ -3366,8 +3366,8 @@ func flowSpecSnapParser(rf RouteFamily, typ BGPFlowSpecType, args []string) (Flo
args = normalizeFlowSpecOpValues(args)
- f := func(i int) error {
- if 0 <= i && i <= 0xffffffffff { // 5 bytes
+ f := func(i uint64) error {
+ if i <= 0xffffffffff { // 5 bytes
return nil
}
return fmt.Errorf("%s range exceeded", typ.String())
@@ -3388,8 +3388,8 @@ func flowSpecVlanIDParser(rf RouteFamily, typ BGPFlowSpecType, args []string) (F
}
args = strings.Split(s, " ")
- f := func(i int) error {
- if 0 <= i && i <= 4095 { // 12 bits
+ f := func(i uint64) error {
+ if i <= 4095 { // 12 bits
return nil
}
return fmt.Errorf("%s range exceeded", typ.String())
@@ -3410,8 +3410,8 @@ func flowSpecVlanCosParser(rf RouteFamily, typ BGPFlowSpecType, args []string) (
}
args = strings.Split(s, " ")
- f := func(i int) error {
- if 0 <= i && i <= 7 { // 3 bits
+ f := func(i uint64) error {
+ if i <= 7 { // 3 bits
return nil
}
return fmt.Errorf("%s range exceeded", typ.String())
@@ -3691,8 +3691,8 @@ func NewFlowSpecDestinationMac(mac net.HardwareAddr) *FlowSpecDestinationMac {
}
type FlowSpecComponentItem struct {
- Op int `json:"op"`
- Value int `json:"value"`
+ Op uint8 `json:"op"`
+ Value uint64 `json:"value"`
}
func (v *FlowSpecComponentItem) Len() int {
@@ -3725,7 +3725,7 @@ func (v *FlowSpecComponentItem) Serialize() ([]byte, error) {
return buf, nil
}
-func NewFlowSpecComponentItem(op int, value int) *FlowSpecComponentItem {
+func NewFlowSpecComponentItem(op uint8, value uint64) *FlowSpecComponentItem {
v := &FlowSpecComponentItem{op, value}
order := uint32(math.Log2(float64(v.Len())))
// we don't know if not initialized properly or initialized to
@@ -3744,7 +3744,7 @@ func NewFlowSpecComponentItem(op int, value int) *FlowSpecComponentItem {
if order > 3 {
return nil
}
- v.Op = int(uint32(v.Op) | order<<4)
+ v.Op = uint8(uint32(v.Op) | order<<4)
return v
}
@@ -3766,8 +3766,8 @@ func (p *FlowSpecComponent) DecodeFromBytes(data []byte, options ...*Marshalling
l := 1 << ((op >> 4) & 0x3) // (min, max) = (1, 8)
v := make([]byte, 8)
copy(v[8-l:], data[1:1+l])
- i := int(binary.BigEndian.Uint64(v))
- item := &FlowSpecComponentItem{int(op), i}
+ i := binary.BigEndian.Uint64(v)
+ item := &FlowSpecComponentItem{op, i}
p.Items = append(p.Items, item)
if end > 0 {
break
@@ -3807,20 +3807,20 @@ func (p *FlowSpecComponent) Type() BGPFlowSpecType {
return p.typ
}
-func formatRaw(op int, value int) string {
+func formatRaw(op uint8, value uint64) string {
return fmt.Sprintf("op:%b,value:%d", op, value)
}
-func formatNumeric(op int, value int) string {
+func formatNumeric(op uint8, value uint64) string {
cmpFlag := DECNumOp(op & 0x7) // lower 3 bits
if cmpFlag == DEC_NUM_OP_TRUE || cmpFlag == DEC_NUM_OP_FALSE {
// Omit value field
return DECNumOp(op).String()
}
- return fmt.Sprint(DECNumOp(op).String(), strconv.Itoa(value))
+ return fmt.Sprint(DECNumOp(op).String(), value)
}
-func formatProto(op int, value int) string {
+func formatProto(op uint8, value uint64) string {
cmpFlag := DECNumOp(op & 0x7) // lower 3 bits
if cmpFlag == DEC_NUM_OP_TRUE || cmpFlag == DEC_NUM_OP_FALSE {
// Omit value field
@@ -3829,15 +3829,15 @@ func formatProto(op int, value int) string {
return fmt.Sprint(DECNumOp(op).String(), Protocol(value).String())
}
-func formatTCPFlag(op int, value int) string {
+func formatTCPFlag(op uint8, value uint64) string {
return fmt.Sprint(BitmaskFlagOp(op).String(), TCPFlag(value).String())
}
-func formatFragment(op int, value int) string {
+func formatFragment(op uint8, value uint64) string {
return fmt.Sprint(BitmaskFlagOp(op).String(), FragmentFlag(value).String())
}
-func formatEtherType(op int, value int) string {
+func formatEtherType(op uint8, value uint64) string {
cmpFlag := DECNumOp(op & 0x7) // lower 3 bits
if cmpFlag == DEC_NUM_OP_TRUE || cmpFlag == DEC_NUM_OP_FALSE {
// Omit value field
@@ -3846,7 +3846,7 @@ func formatEtherType(op int, value int) string {
return fmt.Sprint(DECNumOp(op).String(), EthernetType(value).String())
}
-var flowSpecFormatMap = map[BGPFlowSpecType]func(op int, value int) string{
+var flowSpecFormatMap = map[BGPFlowSpecType]func(op uint8, value uint64) string{
FLOW_SPEC_TYPE_UNKNOWN: formatRaw,
FLOW_SPEC_TYPE_IP_PROTO: formatProto,
FLOW_SPEC_TYPE_PORT: formatNumeric,