github.com/osrg/gobgp/v3@v3.30.0/pkg/packet/rtr/rtr.go (about) 1 // Copyright (C) 2015 Nippon Telegraph and Telephone Corporation. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 12 // implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 16 package rtr 17 18 import ( 19 "encoding/binary" 20 "fmt" 21 "net" 22 ) 23 24 const ( 25 RPKI_DEFAULT_PORT = 323 26 ) 27 28 const ( 29 RTR_SERIAL_NOTIFY = iota 30 RTR_SERIAL_QUERY 31 RTR_RESET_QUERY 32 RTR_CACHE_RESPONSE 33 RTR_IPV4_PREFIX 34 _ 35 RTR_IPV6_PREFIX 36 RTR_END_OF_DATA 37 RTR_CACHE_RESET 38 _ 39 RTR_ERROR_REPORT 40 ) 41 42 const ( 43 RTR_SERIAL_NOTIFY_LEN = 12 44 RTR_SERIAL_QUERY_LEN = 12 45 RTR_RESET_QUERY_LEN = 8 46 RTR_CACHE_RESPONSE_LEN = 8 47 RTR_IPV4_PREFIX_LEN = 20 48 RTR_IPV6_PREFIX_LEN = 32 49 RTR_END_OF_DATA_LEN = 12 50 RTR_CACHE_RESET_LEN = 8 51 RTR_MIN_LEN = 8 52 RTR_ERROR_REPORT_ERR_PDU_LEN = 4 53 RTR_ERROR_REPORT_ERR_TEXT_LEN = 4 54 ) 55 56 const ( 57 WITHDRAWAL uint8 = iota 58 ANNOUNCEMENT 59 ) 60 61 const ( 62 CORRUPT_DATA uint16 = iota 63 INTERNAL_ERROR 64 NO_DATA_AVAILABLE 65 INVALID_REQUEST 66 UNSUPPORTED_PROTOCOL_VERSION 67 UNSUPPORTED_PDU_TYPE 68 WITHDRAWAL_OF_UNKNOWN_RECORD 69 DUPLICATE_ANNOUNCEMENT_RECORD 70 ) 71 72 type RTRMessage interface { 73 DecodeFromBytes([]byte) error 74 Serialize() ([]byte, error) 75 } 76 77 type RTRCommon struct { 78 Version uint8 79 Type uint8 80 SessionID uint16 81 Len uint32 82 SerialNumber uint32 83 } 84 85 func (m *RTRCommon) DecodeFromBytes(data []byte) error { 86 m.Version = data[0] 87 m.Type = data[1] 88 m.SessionID = binary.BigEndian.Uint16(data[2:4]) 89 m.Len = binary.BigEndian.Uint32(data[4:8]) 90 m.SerialNumber = binary.BigEndian.Uint32(data[8:12]) 91 return nil 92 } 93 94 func (m *RTRCommon) Serialize() ([]byte, error) { 95 data := make([]byte, m.Len) 96 data[0] = m.Version 97 data[1] = m.Type 98 binary.BigEndian.PutUint16(data[2:4], m.SessionID) 99 binary.BigEndian.PutUint32(data[4:8], m.Len) 100 binary.BigEndian.PutUint32(data[8:12], m.SerialNumber) 101 return data, nil 102 } 103 104 type RTRSerialNotify struct { 105 RTRCommon 106 } 107 108 func NewRTRSerialNotify(id uint16, sn uint32) *RTRSerialNotify { 109 return &RTRSerialNotify{ 110 RTRCommon{ 111 Type: RTR_SERIAL_NOTIFY, 112 SessionID: id, 113 Len: RTR_SERIAL_NOTIFY_LEN, 114 SerialNumber: sn, 115 }, 116 } 117 } 118 119 type RTRSerialQuery struct { 120 RTRCommon 121 } 122 123 func NewRTRSerialQuery(id uint16, sn uint32) *RTRSerialQuery { 124 return &RTRSerialQuery{ 125 RTRCommon{ 126 Type: RTR_SERIAL_QUERY, 127 SessionID: id, 128 Len: RTR_SERIAL_QUERY_LEN, 129 SerialNumber: sn, 130 }, 131 } 132 } 133 134 type RTRReset struct { 135 Version uint8 136 Type uint8 137 Len uint32 138 } 139 140 func (m *RTRReset) DecodeFromBytes(data []byte) error { 141 m.Version = data[0] 142 m.Type = data[1] 143 m.Len = binary.BigEndian.Uint32(data[4:8]) 144 return nil 145 } 146 147 func (m *RTRReset) Serialize() ([]byte, error) { 148 data := make([]byte, m.Len) 149 data[0] = m.Version 150 data[1] = m.Type 151 binary.BigEndian.PutUint32(data[4:8], m.Len) 152 return data, nil 153 } 154 155 type RTRResetQuery struct { 156 RTRReset 157 } 158 159 func NewRTRResetQuery() *RTRResetQuery { 160 return &RTRResetQuery{ 161 RTRReset{ 162 Type: RTR_RESET_QUERY, 163 Len: RTR_RESET_QUERY_LEN, 164 }, 165 } 166 } 167 168 type RTRCacheResponse struct { 169 Version uint8 170 Type uint8 171 SessionID uint16 172 Len uint32 173 } 174 175 func (m *RTRCacheResponse) DecodeFromBytes(data []byte) error { 176 m.Version = data[0] 177 m.Type = data[1] 178 m.SessionID = binary.BigEndian.Uint16(data[2:4]) 179 m.Len = binary.BigEndian.Uint32(data[4:8]) 180 return nil 181 } 182 183 func (m *RTRCacheResponse) Serialize() ([]byte, error) { 184 data := make([]byte, m.Len) 185 data[0] = m.Version 186 data[1] = m.Type 187 binary.BigEndian.PutUint16(data[2:4], m.SessionID) 188 binary.BigEndian.PutUint32(data[4:8], m.Len) 189 return data, nil 190 } 191 192 func NewRTRCacheResponse(id uint16) *RTRCacheResponse { 193 return &RTRCacheResponse{ 194 Type: RTR_CACHE_RESPONSE, 195 SessionID: id, 196 Len: RTR_CACHE_RESPONSE_LEN, 197 } 198 } 199 200 type RTRIPPrefix struct { 201 Version uint8 202 Type uint8 203 Len uint32 204 Flags uint8 205 PrefixLen uint8 206 MaxLen uint8 207 Prefix net.IP 208 AS uint32 209 } 210 211 func (m *RTRIPPrefix) DecodeFromBytes(data []byte) error { 212 m.Version = data[0] 213 m.Type = data[1] 214 m.Len = binary.BigEndian.Uint32(data[4:8]) 215 m.Flags = data[8] 216 m.PrefixLen = data[9] 217 m.MaxLen = data[10] 218 if m.Type == RTR_IPV4_PREFIX { 219 m.Prefix = net.IP(data[12:16]).To4() 220 m.AS = binary.BigEndian.Uint32(data[16:20]) 221 } else { 222 m.Prefix = net.IP(data[12:28]).To16() 223 m.AS = binary.BigEndian.Uint32(data[28:32]) 224 } 225 return nil 226 } 227 228 func (m *RTRIPPrefix) Serialize() ([]byte, error) { 229 data := make([]byte, m.Len) 230 data[0] = m.Version 231 data[1] = m.Type 232 binary.BigEndian.PutUint32(data[4:8], m.Len) 233 data[8] = m.Flags 234 data[9] = m.PrefixLen 235 data[10] = m.MaxLen 236 if m.Type == RTR_IPV4_PREFIX { 237 copy(data[12:16], m.Prefix.To4()) 238 binary.BigEndian.PutUint32(data[16:20], m.AS) 239 } else { 240 copy(data[12:28], m.Prefix.To16()) 241 binary.BigEndian.PutUint32(data[28:32], m.AS) 242 } 243 return data, nil 244 } 245 246 func NewRTRIPPrefix(prefix net.IP, prefixLen, maxLen uint8, as uint32, flags uint8) *RTRIPPrefix { 247 var pduType uint8 248 var pduLen uint32 249 if prefix.To4() != nil && prefixLen <= 32 { 250 pduType = RTR_IPV4_PREFIX 251 pduLen = RTR_IPV4_PREFIX_LEN 252 } else { 253 pduType = RTR_IPV6_PREFIX 254 pduLen = RTR_IPV6_PREFIX_LEN 255 } 256 257 return &RTRIPPrefix{ 258 Type: pduType, 259 Len: pduLen, 260 Flags: flags, 261 PrefixLen: prefixLen, 262 MaxLen: maxLen, 263 Prefix: prefix, 264 AS: as, 265 } 266 } 267 268 type RTREndOfData struct { 269 RTRCommon 270 } 271 272 func NewRTREndOfData(id uint16, sn uint32) *RTREndOfData { 273 return &RTREndOfData{ 274 RTRCommon{ 275 Type: RTR_END_OF_DATA, 276 SessionID: id, 277 Len: RTR_END_OF_DATA_LEN, 278 SerialNumber: sn, 279 }, 280 } 281 } 282 283 type RTRCacheReset struct { 284 RTRReset 285 } 286 287 func NewRTRCacheReset() *RTRCacheReset { 288 return &RTRCacheReset{ 289 RTRReset{ 290 Type: RTR_CACHE_RESET, 291 Len: RTR_CACHE_RESET_LEN, 292 }, 293 } 294 } 295 296 type RTRErrorReport struct { 297 Version uint8 298 Type uint8 299 ErrorCode uint16 300 Len uint32 301 PDULen uint32 302 PDU []byte 303 TextLen uint32 304 Text []byte 305 } 306 307 func (m *RTRErrorReport) DecodeFromBytes(data []byte) error { 308 m.Version = data[0] 309 m.Type = data[1] 310 m.ErrorCode = binary.BigEndian.Uint16(data[2:4]) 311 m.Len = binary.BigEndian.Uint32(data[4:8]) 312 m.PDULen = binary.BigEndian.Uint32(data[8:12]) 313 m.PDU = make([]byte, m.PDULen) 314 copy(m.PDU, data[12:12+m.PDULen]) 315 m.TextLen = binary.BigEndian.Uint32(data[12+m.PDULen : 16+m.PDULen]) 316 m.Text = make([]byte, m.TextLen) 317 copy(m.Text, data[16+m.PDULen:]) 318 return nil 319 } 320 321 func (m *RTRErrorReport) Serialize() ([]byte, error) { 322 data := make([]byte, m.Len) 323 data[0] = m.Version 324 data[1] = m.Type 325 binary.BigEndian.PutUint16(data[2:4], m.ErrorCode) 326 binary.BigEndian.PutUint32(data[4:8], m.Len) 327 binary.BigEndian.PutUint32(data[8:12], m.PDULen) 328 copy(data[12:], m.PDU) 329 binary.BigEndian.PutUint32(data[12+m.PDULen:16+m.PDULen], m.TextLen) 330 copy(data[16+m.PDULen:], m.Text) 331 return data, nil 332 } 333 334 func NewRTRErrorReport(errCode uint16, errPDU []byte, errMsg []byte) *RTRErrorReport { 335 pdu := &RTRErrorReport{Type: RTR_ERROR_REPORT, ErrorCode: errCode} 336 if errPDU != nil { 337 if errPDU[1] == RTR_ERROR_REPORT { 338 return nil 339 } 340 pdu.PDULen = uint32(len(errPDU)) 341 pdu.PDU = errPDU 342 } 343 if errMsg != nil { 344 pdu.Text = errMsg 345 pdu.TextLen = uint32(len(errMsg)) 346 } 347 pdu.Len = uint32(RTR_MIN_LEN) + uint32(RTR_ERROR_REPORT_ERR_PDU_LEN) + pdu.PDULen + uint32(RTR_ERROR_REPORT_ERR_TEXT_LEN) + pdu.TextLen 348 return pdu 349 } 350 351 func SplitRTR(data []byte, atEOF bool) (advance int, token []byte, err error) { 352 if atEOF && len(data) == 0 || len(data) < RTR_MIN_LEN { 353 return 0, nil, nil 354 } 355 356 totalLen := binary.BigEndian.Uint32(data[4:8]) 357 if totalLen < RTR_MIN_LEN { 358 return 0, nil, fmt.Errorf("invalid length: %d", totalLen) 359 } 360 if uint32(len(data)) < totalLen { 361 return 0, nil, nil 362 } 363 return int(totalLen), data[0:totalLen], nil 364 } 365 366 func ParseRTR(data []byte) (RTRMessage, error) { 367 var msg RTRMessage 368 switch data[1] { 369 case RTR_SERIAL_NOTIFY: 370 msg = &RTRSerialNotify{} 371 case RTR_SERIAL_QUERY: 372 msg = &RTRSerialQuery{} 373 case RTR_RESET_QUERY: 374 msg = &RTRResetQuery{} 375 case RTR_CACHE_RESPONSE: 376 msg = &RTRCacheResponse{} 377 case RTR_IPV4_PREFIX: 378 msg = &RTRIPPrefix{} 379 case RTR_IPV6_PREFIX: 380 msg = &RTRIPPrefix{} 381 case RTR_END_OF_DATA: 382 msg = &RTREndOfData{} 383 case RTR_CACHE_RESET: 384 msg = &RTRCacheReset{} 385 case RTR_ERROR_REPORT: 386 msg = &RTRErrorReport{} 387 default: 388 return nil, fmt.Errorf("unknown RTR message type %d", data[1]) 389 } 390 err := msg.DecodeFromBytes(data) 391 return msg, err 392 }