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  }