diff options
author | FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> | 2016-03-04 12:35:23 +0900 |
---|---|---|
committer | FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> | 2016-03-04 15:09:11 +0900 |
commit | 80bd1289acf006bb9e4bdf858f0fbe1eabd0a4c7 (patch) | |
tree | c61f76d9545e8dfcb55906cbd928c8dce8fe6ede | |
parent | c46d6be52f93b94cf92ac7cbe4af4f141d5cfb3c (diff) |
packet fix FlowSpecComponentItem's Serialize
- don't overwrite length if it was initialized because the length
can't calculated from the value. For exmaple, assuming using one
byte for port number < 255 is probably wrong.
- don't touch FlowSpecComponentItem's Op value. Mutating is a bad
idea.
Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
-rw-r--r-- | packet/bgp.go | 52 |
1 files changed, 29 insertions, 23 deletions
diff --git a/packet/bgp.go b/packet/bgp.go index c71d1489..e136c807 100644 --- a/packet/bgp.go +++ b/packet/bgp.go @@ -2519,32 +2519,38 @@ func (v *FlowSpecComponentItem) Serialize() ([]byte, error) { } if v.Op < 0 || v.Op > math.MaxUint8 { return nil, fmt.Errorf("invalid op size: %d", v.Op) - } - for i := 0; i < 3; i++ { - if v.Value < (1 << ((1 << uint(i)) * 8)) { - buf := make([]byte, 1+(1<<uint(i))) - switch i { - case 0: - buf[1] = byte(v.Value) - v.Op &^= 0x30 - case 1: - binary.BigEndian.PutUint16(buf[1:], uint16(v.Value)) - v.Op |= 0x10 - v.Op &^= 0x20 - case 2: - binary.BigEndian.PutUint32(buf[1:], uint32(v.Value)) - v.Op &^= 0x10 - v.Op |= 0x20 - case 3: - binary.BigEndian.PutUint64(buf[1:], uint64(v.Value)) - v.Op |= 0x30 + } + order := uint32(math.Log2(float64(v.Len()))) + // we don't know if not initialized properly or initialized to + // zero... + if order == 0 { + order = func() uint32 { + for i := 0; i < 3; i++ { + if v.Value < (1 << ((1 << uint(i)) * 8)) { + return uint32(i) + } } - buf[0] = byte(v.Op) - return buf, nil - } + // return invalid order + return 4 + }() + } + + buf := make([]byte, 1+(1<<order)) + buf[0] = byte(uint32(v.Op) | order << 4) + switch order { + case 0: + buf[1] = byte(v.Value) + case 1: + binary.BigEndian.PutUint16(buf[1:], uint16(v.Value)) + case 2: + binary.BigEndian.PutUint32(buf[1:], uint32(v.Value)) + case 3: + binary.BigEndian.PutUint64(buf[1:], uint64(v.Value)) + default: + return nil, fmt.Errorf("invalid value size(too big): %d", v.Value) } - return nil, fmt.Errorf("invalid value size(too big): %d", v.Value) + return buf, nil } func NewFlowSpecComponentItem(op int, value int) *FlowSpecComponentItem { |