summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorFUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>2016-03-04 12:35:23 +0900
committerFUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>2016-03-04 15:09:11 +0900
commit80bd1289acf006bb9e4bdf858f0fbe1eabd0a4c7 (patch)
treec61f76d9545e8dfcb55906cbd928c8dce8fe6ede
parentc46d6be52f93b94cf92ac7cbe4af4f141d5cfb3c (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.go52
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 {