github.com/contiv/libOpenflow@v0.0.0-20210609050114-d967b14cc688/protocol/ipv6.go (about) 1 package protocol 2 3 import ( 4 "encoding/binary" 5 "errors" 6 "net" 7 8 "github.com/contiv/libOpenflow/util" 9 ) 10 11 const ( 12 Type_HBH = 0x0 13 Type_Routing = 0x2b 14 Type_Fragment = 0x2c 15 ) 16 17 type IPv6 struct { 18 Version uint8 //4-bits 19 TrafficClass uint8 20 FlowLabel uint32 //20-bits 21 Length uint16 22 NextHeader uint8 23 HopLimit uint8 24 NWSrc net.IP 25 NWDst net.IP 26 HbhHeader *HopByHopHeader 27 RoutingHeader *RoutingHeader 28 FragmentHeader *FragmentHeader 29 Data util.Message 30 } 31 32 func (i *IPv6) Len() (n uint16) { 33 length := uint16(40) 34 if i.HbhHeader != nil { 35 length += i.HbhHeader.Len() 36 } 37 if i.RoutingHeader != nil { 38 length += i.RoutingHeader.Len() 39 } 40 if i.FragmentHeader != nil { 41 length += i.FragmentHeader.Len() 42 } 43 length += i.Data.Len() 44 return length 45 } 46 47 func (i *IPv6) MarshalBinary() (data []byte, err error) { 48 data = make([]byte, int(i.Len())) 49 b := make([]byte, 0) 50 n := 0 51 52 ihl := (i.Version << 4) | (i.TrafficClass>>4)&0x0f 53 data[n] = ihl 54 n += 1 55 data[n] = (i.TrafficClass<<4)&0xf0 | uint8(i.FlowLabel>>16) 56 n += 1 57 binary.BigEndian.PutUint16(data[n:], uint16(i.FlowLabel)) 58 n += 2 59 binary.BigEndian.PutUint16(data[n:], i.Length) 60 n += 2 61 data[n] = i.NextHeader 62 n += 1 63 data[n] = i.HopLimit 64 n += 1 65 copy(data[n:], i.NWSrc) 66 n += 16 67 copy(data[n:], i.NWDst) 68 n += 16 69 70 checkExtHeader := true 71 nxtHeader := i.NextHeader 72 for checkExtHeader { 73 var err error 74 var hBytes []byte 75 switch nxtHeader { 76 case Type_HBH: 77 checkExtHeader = true 78 nxtHeader = i.HbhHeader.NextHeader 79 hBytes, err = i.HbhHeader.MarshalBinary() 80 case Type_Routing: 81 checkExtHeader = true 82 nxtHeader = i.RoutingHeader.NextHeader 83 hBytes, err = i.RoutingHeader.MarshalBinary() 84 case Type_Fragment: 85 checkExtHeader = true 86 nxtHeader = i.FragmentHeader.NextHeader 87 hBytes, err = i.FragmentHeader.MarshalBinary() 88 default: 89 checkExtHeader = false 90 break 91 } 92 if err != nil { 93 return nil, err 94 } 95 copy(data[n:], hBytes) 96 n += len(hBytes) 97 } 98 99 if i.Data != nil { 100 b, err = i.Data.MarshalBinary() 101 if err != nil { 102 return 103 } 104 copy(data[n:], b) 105 n += len(b) 106 } 107 return 108 } 109 110 func (i *IPv6) UnmarshalBinary(data []byte) error { 111 if len(data) < 40 { 112 return errors.New("The []byte is too short to unmarshal a full IPv6 message.") 113 } 114 n := 0 115 116 var ihl uint8 117 ihl = data[n] 118 i.Version = ihl >> 4 119 tcLeft := (ihl & 0x0f) << 4 120 n += 1 121 tc := data[n] 122 i.TrafficClass = tcLeft | (tc >> 4) 123 n += 1 124 i.FlowLabel = binary.BigEndian.Uint32(data[0:4]) & 0x000FFFFF 125 n += 2 126 i.Length = binary.BigEndian.Uint16(data[n:]) 127 n += 2 128 i.NextHeader = data[n] 129 n += 1 130 i.HopLimit = data[n] 131 n += 1 132 i.NWSrc = data[n : n+16] 133 n += 16 134 i.NWDst = data[n : n+16] 135 n += 16 136 137 checkExtHeader := true 138 nxtHeader := i.NextHeader 139 checkXHeader: 140 for checkExtHeader { 141 switch nxtHeader { 142 case Type_HBH: 143 checkExtHeader = true 144 i.HbhHeader = NewHopByHopHeader() 145 err := i.HbhHeader.UnmarshalBinary(data[n:]) 146 if err != nil { 147 return err 148 } 149 nxtHeader = i.HbhHeader.NextHeader 150 n += int(i.HbhHeader.Len()) 151 case Type_Routing: 152 checkExtHeader = true 153 i.RoutingHeader = NewRoutingHeader() 154 err := i.RoutingHeader.UnmarshalBinary(data[n:]) 155 if err != nil { 156 return err 157 } 158 nxtHeader = i.RoutingHeader.NextHeader 159 n += int(i.RoutingHeader.Len()) 160 case Type_Fragment: 161 checkExtHeader = true 162 i.FragmentHeader = NewFragmentHeader() 163 err := i.FragmentHeader.UnmarshalBinary(data[n:]) 164 if err != nil { 165 return err 166 } 167 nxtHeader = i.FragmentHeader.NextHeader 168 n += int(i.FragmentHeader.Len()) 169 case Type_IPv6ICMP: 170 i.Data = NewICMP() 171 break checkXHeader 172 case Type_UDP: 173 i.Data = NewUDP() 174 break checkXHeader 175 default: 176 i.Data = new(util.Buffer) 177 break checkXHeader 178 } 179 } 180 return i.Data.UnmarshalBinary(data[n:]) 181 } 182 183 type Option struct { 184 Type uint8 185 Length uint8 186 Data []byte 187 } 188 189 func (o *Option) Len() uint16 { 190 return uint16(o.Length + 2) 191 } 192 193 func (o *Option) MarshalBinary() (data []byte, err error) { 194 data = make([]byte, int(o.Len())) 195 n := 0 196 data[n] = o.Type 197 n += 1 198 data[n] = o.Length 199 n += 1 200 copy(data[n:], o.Data) 201 return data, nil 202 } 203 204 func (o *Option) UnmarshalBinary(data []byte) error { 205 n := 0 206 o.Type = data[n] 207 n += 1 208 o.Length = data[n] 209 n += 1 210 if (len(data) - 2) < int(o.Length) { 211 return errors.New("The []byte is too short to unmarshal a full Option message.") 212 } 213 o.Data = make([]byte, o.Length) 214 copy(o.Data, data[n:n+int(o.Length)]) 215 return nil 216 } 217 218 type HopByHopHeader struct { 219 NextHeader uint8 220 HEL uint8 221 Options []*Option 222 } 223 224 func (h *HopByHopHeader) Len() uint16 { 225 return 8 * uint16(h.HEL+1) 226 } 227 228 func (h *HopByHopHeader) MarshalBinary() (data []byte, err error) { 229 data = make([]byte, int(h.Len())) 230 n := 0 231 data[n] = h.NextHeader 232 n += 1 233 data[n] = h.HEL 234 n += 1 235 for _, o := range h.Options { 236 ob, err := o.MarshalBinary() 237 if err != nil { 238 return data, err 239 } 240 copy(data[n:], ob) 241 n += int(o.Len()) 242 } 243 return data, nil 244 } 245 246 func (h *HopByHopHeader) UnmarshalBinary(data []byte) error { 247 n := 0 248 h.NextHeader = data[n] 249 n += 1 250 h.HEL = data[n] 251 if len(data) < 8*int(h.HEL+1) { 252 return errors.New("The []byte is too short to unmarshal a full HopByHopHeader message.") 253 } 254 n += 1 255 for n < int(h.Len()) { 256 o := new(Option) 257 err := o.UnmarshalBinary(data[n:]) 258 if err != nil { 259 return err 260 } 261 n += int(o.Len()) 262 h.Options = append(h.Options, o) 263 } 264 return nil 265 } 266 267 func NewHopByHopHeader() *HopByHopHeader { 268 return new(HopByHopHeader) 269 } 270 271 type RoutingHeader struct { 272 NextHeader uint8 273 HEL uint8 274 RoutingType uint8 275 SegmentsLeft uint8 276 Data *util.Buffer 277 } 278 279 func (h *RoutingHeader) Len() uint16 { 280 return 8 * uint16(h.HEL+1) 281 } 282 283 func (h *RoutingHeader) MarshalBinary() (data []byte, err error) { 284 data = make([]byte, int(h.Len())) 285 n := 0 286 data[n] = h.NextHeader 287 n += 1 288 data[n] = h.HEL 289 n += 1 290 data[n] = h.RoutingType 291 n += 1 292 data[n] = h.SegmentsLeft 293 n += 1 294 copy(data[n:], h.Data.Bytes()) 295 return data, nil 296 } 297 298 func (h *RoutingHeader) UnmarshalBinary(data []byte) error { 299 n := 0 300 h.NextHeader = data[n] 301 n += 1 302 h.HEL = data[n] 303 if len(data) < 8*int(h.HEL+1) { 304 return errors.New("The []byte is too short to unmarshal a full RoutingHeader message.") 305 } 306 n += 1 307 h.RoutingType = data[n] 308 n += 1 309 h.SegmentsLeft = data[n] 310 n += 1 311 h.Data = new(util.Buffer) 312 err := h.Data.UnmarshalBinary(data[n:h.Len()]) 313 if err != nil { 314 return err 315 } 316 return nil 317 } 318 319 func NewRoutingHeader() *RoutingHeader { 320 return new(RoutingHeader) 321 } 322 323 type FragmentHeader struct { 324 NextHeader uint8 325 Reserved uint8 326 FragmentOffset uint16 327 MoreFragments bool 328 Identification uint32 329 } 330 331 func (h *FragmentHeader) Len() uint16 { 332 return uint16(8) 333 } 334 335 func (h *FragmentHeader) MarshalBinary() (data []byte, err error) { 336 data = make([]byte, int(h.Len())) 337 n := 0 338 data[n] = h.NextHeader 339 n += 1 340 data[n] = h.Reserved 341 n += 1 342 fragment := h.FragmentOffset << 3 343 if h.MoreFragments { 344 fragment |= uint16(1) 345 } 346 binary.BigEndian.PutUint16(data[n:], fragment) 347 n += 2 348 binary.BigEndian.PutUint32(data[n:], h.Identification) 349 return data, nil 350 } 351 352 func (h *FragmentHeader) UnmarshalBinary(data []byte) error { 353 if len(data) < int(h.Len()) { 354 return errors.New("The []byte is too short to unmarshal a full FragmentHeader message.") 355 } 356 n := 0 357 h.NextHeader = data[n] 358 n += 1 359 h.Reserved = data[n] 360 n += 1 361 fragment := binary.BigEndian.Uint16(data[n:]) 362 n += 2 363 h.FragmentOffset = fragment >> 3 364 h.MoreFragments = (fragment & uint16(1)) == uint16(1) 365 h.Identification = binary.BigEndian.Uint32(data[n:]) 366 n += 4 367 return nil 368 } 369 370 func NewFragmentHeader() *FragmentHeader { 371 return new(FragmentHeader) 372 }