github.com/osrg/gobgp@v2.0.0+incompatible/pkg/server/rpki.go (about)

     1  // Copyright (C) 2015,2016 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 server
    17  
    18  import (
    19  	"encoding/binary"
    20  	"fmt"
    21  	"io"
    22  	"net"
    23  	"sort"
    24  	"strconv"
    25  	"time"
    26  
    27  	"github.com/osrg/gobgp/internal/pkg/config"
    28  	"github.com/osrg/gobgp/internal/pkg/table"
    29  	"github.com/osrg/gobgp/pkg/packet/bgp"
    30  	"github.com/osrg/gobgp/pkg/packet/rtr"
    31  
    32  	"github.com/armon/go-radix"
    33  	log "github.com/sirupsen/logrus"
    34  	"golang.org/x/net/context"
    35  )
    36  
    37  const (
    38  	connectRetryInterval = 30
    39  )
    40  
    41  func before(a, b uint32) bool {
    42  	return int32(a-b) < 0
    43  }
    44  
    45  type roaBucket struct {
    46  	Prefix  *table.IPPrefix
    47  	entries []*table.ROA
    48  }
    49  
    50  func (r *roaBucket) GetEntries() []*table.ROA {
    51  	return r.entries
    52  }
    53  
    54  type roas []*table.ROA
    55  
    56  func (r roas) Len() int {
    57  	return len(r)
    58  }
    59  
    60  func (r roas) Swap(i, j int) {
    61  	r[i], r[j] = r[j], r[i]
    62  }
    63  
    64  func (r roas) Less(i, j int) bool {
    65  	r1 := r[i]
    66  	r2 := r[j]
    67  
    68  	if r1.MaxLen < r2.MaxLen {
    69  		return true
    70  	} else if r1.MaxLen > r2.MaxLen {
    71  		return false
    72  	}
    73  
    74  	if r1.AS < r2.AS {
    75  		return true
    76  	}
    77  	return false
    78  }
    79  
    80  type roaEventType uint8
    81  
    82  const (
    83  	roaConnected roaEventType = iota
    84  	roaDisconnected
    85  	roaRTR
    86  	roaLifetimeout
    87  )
    88  
    89  type roaEvent struct {
    90  	EventType roaEventType
    91  	Src       string
    92  	Data      []byte
    93  	conn      *net.TCPConn
    94  }
    95  
    96  type roaManager struct {
    97  	AS        uint32
    98  	Roas      map[bgp.RouteFamily]*radix.Tree
    99  	eventCh   chan *roaEvent
   100  	clientMap map[string]*roaClient
   101  }
   102  
   103  func newROAManager(as uint32) (*roaManager, error) {
   104  	m := &roaManager{
   105  		AS:   as,
   106  		Roas: make(map[bgp.RouteFamily]*radix.Tree),
   107  	}
   108  	m.Roas[bgp.RF_IPv4_UC] = radix.New()
   109  	m.Roas[bgp.RF_IPv6_UC] = radix.New()
   110  	m.eventCh = make(chan *roaEvent)
   111  	m.clientMap = make(map[string]*roaClient)
   112  	return m, nil
   113  }
   114  
   115  func (m *roaManager) enabled() bool {
   116  	return len(m.clientMap) != 0
   117  }
   118  
   119  func (m *roaManager) SetAS(as uint32) error {
   120  	if m.AS != 0 {
   121  		return fmt.Errorf("AS was already configured")
   122  	}
   123  	m.AS = as
   124  	return nil
   125  }
   126  
   127  func (m *roaManager) AddServer(host string, lifetime int64) error {
   128  	address, port, err := net.SplitHostPort(host)
   129  	if err != nil {
   130  		return err
   131  	}
   132  	if lifetime == 0 {
   133  		lifetime = 3600
   134  	}
   135  	if _, ok := m.clientMap[host]; ok {
   136  		return fmt.Errorf("ROA server exists %s", host)
   137  	}
   138  	m.clientMap[host] = newRoaClient(address, port, m.eventCh, lifetime)
   139  	return nil
   140  }
   141  
   142  func (m *roaManager) DeleteServer(host string) error {
   143  	client, ok := m.clientMap[host]
   144  	if !ok {
   145  		return fmt.Errorf("ROA server doesn't exists %s", host)
   146  	}
   147  	client.stop()
   148  	m.deleteAllROA(host)
   149  	delete(m.clientMap, host)
   150  	return nil
   151  }
   152  
   153  func (m *roaManager) deleteAllROA(network string) {
   154  	for _, tree := range m.Roas {
   155  		deleteKeys := make([]string, 0, tree.Len())
   156  		tree.Walk(func(s string, v interface{}) bool {
   157  			b, _ := v.(*roaBucket)
   158  			newEntries := make([]*table.ROA, 0, len(b.entries))
   159  			for _, r := range b.entries {
   160  				if r.Src != network {
   161  					newEntries = append(newEntries, r)
   162  				}
   163  			}
   164  			if len(newEntries) > 0 {
   165  				b.entries = newEntries
   166  			} else {
   167  				deleteKeys = append(deleteKeys, s)
   168  			}
   169  			return false
   170  		})
   171  		for _, key := range deleteKeys {
   172  			tree.Delete(key)
   173  		}
   174  	}
   175  }
   176  
   177  func (m *roaManager) Enable(address string) error {
   178  	for network, client := range m.clientMap {
   179  		add, _, _ := net.SplitHostPort(network)
   180  		if add == address {
   181  			client.enable(client.serialNumber)
   182  			return nil
   183  		}
   184  	}
   185  	return fmt.Errorf("ROA server not found %s", address)
   186  }
   187  
   188  func (m *roaManager) Disable(address string) error {
   189  	for network, client := range m.clientMap {
   190  		add, _, _ := net.SplitHostPort(network)
   191  		if add == address {
   192  			client.reset()
   193  			m.deleteAllROA(add)
   194  			return nil
   195  		}
   196  	}
   197  	return fmt.Errorf("ROA server not found %s", address)
   198  }
   199  
   200  func (m *roaManager) Reset(address string) error {
   201  	return m.Disable(address)
   202  }
   203  
   204  func (m *roaManager) SoftReset(address string) error {
   205  	for network, client := range m.clientMap {
   206  		add, _, _ := net.SplitHostPort(network)
   207  		if add == address {
   208  			client.softReset()
   209  			m.deleteAllROA(network)
   210  			return nil
   211  		}
   212  	}
   213  	return fmt.Errorf("ROA server not found %s", address)
   214  }
   215  
   216  func (m *roaManager) ReceiveROA() chan *roaEvent {
   217  	return m.eventCh
   218  }
   219  
   220  func (c *roaClient) lifetimeout() {
   221  	c.eventCh <- &roaEvent{
   222  		EventType: roaLifetimeout,
   223  		Src:       c.host,
   224  	}
   225  }
   226  
   227  func (m *roaManager) HandleROAEvent(ev *roaEvent) {
   228  	client, y := m.clientMap[ev.Src]
   229  	if !y {
   230  		if ev.EventType == roaConnected {
   231  			ev.conn.Close()
   232  		}
   233  		log.WithFields(log.Fields{"Topic": "rpki"}).Errorf("Can't find %s ROA server configuration", ev.Src)
   234  		return
   235  	}
   236  	switch ev.EventType {
   237  	case roaDisconnected:
   238  		log.WithFields(log.Fields{"Topic": "rpki"}).Infof("ROA server %s is disconnected", ev.Src)
   239  		client.state.Downtime = time.Now().Unix()
   240  		// clear state
   241  		client.endOfData = false
   242  		client.pendingROAs = make([]*table.ROA, 0)
   243  		client.state.RpkiMessages = config.RpkiMessages{}
   244  		client.conn = nil
   245  		go client.tryConnect()
   246  		client.timer = time.AfterFunc(time.Duration(client.lifetime)*time.Second, client.lifetimeout)
   247  		client.oldSessionID = client.sessionID
   248  	case roaConnected:
   249  		log.WithFields(log.Fields{"Topic": "rpki"}).Infof("ROA server %s is connected", ev.Src)
   250  		client.conn = ev.conn
   251  		client.state.Uptime = time.Now().Unix()
   252  		go client.established()
   253  	case roaRTR:
   254  		m.handleRTRMsg(client, &client.state, ev.Data)
   255  	case roaLifetimeout:
   256  		// a) already reconnected but hasn't received
   257  		// EndOfData -> needs to delete stale ROAs
   258  		// b) not reconnected -> needs to delete stale ROAs
   259  		//
   260  		// c) already reconnected and received EndOfData so
   261  		// all stale ROAs were deleted -> timer was cancelled
   262  		// so should not be here.
   263  		if client.oldSessionID != client.sessionID {
   264  			log.WithFields(log.Fields{"Topic": "rpki"}).Infof("Reconnected to %s. Ignore timeout", client.host)
   265  		} else {
   266  			log.WithFields(log.Fields{"Topic": "rpki"}).Infof("Deleting all ROAs due to timeout with:%s", client.host)
   267  			m.deleteAllROA(client.host)
   268  		}
   269  	}
   270  }
   271  
   272  func (m *roaManager) roa2tree(roa *table.ROA) (*radix.Tree, string) {
   273  	tree := m.Roas[bgp.RF_IPv4_UC]
   274  	if roa.Family == bgp.AFI_IP6 {
   275  		tree = m.Roas[bgp.RF_IPv6_UC]
   276  	}
   277  	return tree, table.IpToRadixkey(roa.Prefix.Prefix, roa.Prefix.Length)
   278  }
   279  
   280  func (m *roaManager) deleteROA(roa *table.ROA) {
   281  	tree, key := m.roa2tree(roa)
   282  	b, _ := tree.Get(key)
   283  	if b != nil {
   284  		bucket := b.(*roaBucket)
   285  		newEntries := make([]*table.ROA, 0, len(bucket.entries))
   286  		for _, r := range bucket.entries {
   287  			if !r.Equal(roa) {
   288  				newEntries = append(newEntries, r)
   289  			}
   290  		}
   291  		if len(newEntries) != len(bucket.entries) {
   292  			bucket.entries = newEntries
   293  			if len(newEntries) == 0 {
   294  				tree.Delete(key)
   295  			}
   296  			return
   297  		}
   298  	}
   299  	log.WithFields(log.Fields{
   300  		"Topic":         "rpki",
   301  		"Prefix":        roa.Prefix.Prefix.String(),
   302  		"Prefix Length": roa.Prefix.Length,
   303  		"AS":            roa.AS,
   304  		"Max Length":    roa.MaxLen,
   305  	}).Info("Can't withdraw a ROA")
   306  }
   307  
   308  func (m *roaManager) DeleteROA(roa *table.ROA) {
   309  	m.deleteROA(roa)
   310  }
   311  
   312  func (m *roaManager) addROA(roa *table.ROA) {
   313  	tree, key := m.roa2tree(roa)
   314  	b, _ := tree.Get(key)
   315  	var bucket *roaBucket
   316  	if b == nil {
   317  		bucket = &roaBucket{
   318  			Prefix:  roa.Prefix,
   319  			entries: make([]*table.ROA, 0),
   320  		}
   321  		tree.Insert(key, bucket)
   322  	} else {
   323  		bucket = b.(*roaBucket)
   324  		for _, r := range bucket.entries {
   325  			if r.Equal(roa) {
   326  				// we already have the same one
   327  				return
   328  			}
   329  		}
   330  	}
   331  	bucket.entries = append(bucket.entries, roa)
   332  }
   333  
   334  func (m *roaManager) AddROA(roa *table.ROA) {
   335  	m.addROA(roa)
   336  }
   337  
   338  func (m *roaManager) handleRTRMsg(client *roaClient, state *config.RpkiServerState, buf []byte) {
   339  	received := &state.RpkiMessages.RpkiReceived
   340  
   341  	m1, err := rtr.ParseRTR(buf)
   342  	if err == nil {
   343  		switch msg := m1.(type) {
   344  		case *rtr.RTRSerialNotify:
   345  			if before(client.serialNumber, msg.RTRCommon.SerialNumber) {
   346  				client.enable(client.serialNumber)
   347  			} else if client.serialNumber == msg.RTRCommon.SerialNumber {
   348  				// nothing
   349  			} else {
   350  				// should not happen. try to get the whole ROAs.
   351  				client.softReset()
   352  			}
   353  			received.SerialNotify++
   354  		case *rtr.RTRSerialQuery:
   355  		case *rtr.RTRResetQuery:
   356  		case *rtr.RTRCacheResponse:
   357  			received.CacheResponse++
   358  			client.endOfData = false
   359  		case *rtr.RTRIPPrefix:
   360  			family := bgp.AFI_IP
   361  			if msg.Type == rtr.RTR_IPV4_PREFIX {
   362  				received.Ipv4Prefix++
   363  			} else {
   364  				family = bgp.AFI_IP6
   365  				received.Ipv6Prefix++
   366  			}
   367  			roa := table.NewROA(family, msg.Prefix, msg.PrefixLen, msg.MaxLen, msg.AS, client.host)
   368  			if (msg.Flags & 1) == 1 {
   369  				if client.endOfData {
   370  					m.addROA(roa)
   371  				} else {
   372  					client.pendingROAs = append(client.pendingROAs, roa)
   373  				}
   374  			} else {
   375  				m.deleteROA(roa)
   376  			}
   377  		case *rtr.RTREndOfData:
   378  			received.EndOfData++
   379  			if client.sessionID != msg.RTRCommon.SessionID {
   380  				// remove all ROAs related with the
   381  				// previous session
   382  				m.deleteAllROA(client.host)
   383  			}
   384  			client.sessionID = msg.RTRCommon.SessionID
   385  			client.serialNumber = msg.RTRCommon.SerialNumber
   386  			client.endOfData = true
   387  			if client.timer != nil {
   388  				client.timer.Stop()
   389  				client.timer = nil
   390  			}
   391  			for _, roa := range client.pendingROAs {
   392  				m.addROA(roa)
   393  			}
   394  			client.pendingROAs = make([]*table.ROA, 0)
   395  		case *rtr.RTRCacheReset:
   396  			client.softReset()
   397  			received.CacheReset++
   398  		case *rtr.RTRErrorReport:
   399  			received.Error++
   400  		}
   401  	} else {
   402  		log.WithFields(log.Fields{
   403  			"Topic": "rpki",
   404  			"Host":  client.host,
   405  			"Error": err,
   406  		}).Info("Failed to parse an RTR message")
   407  	}
   408  }
   409  
   410  func (m *roaManager) GetServers() []*config.RpkiServer {
   411  	f := func(tree *radix.Tree) (map[string]uint32, map[string]uint32) {
   412  		records := make(map[string]uint32)
   413  		prefixes := make(map[string]uint32)
   414  
   415  		tree.Walk(func(s string, v interface{}) bool {
   416  			b, _ := v.(*roaBucket)
   417  			tmpRecords := make(map[string]uint32)
   418  			for _, roa := range b.entries {
   419  				tmpRecords[roa.Src]++
   420  			}
   421  
   422  			for src, r := range tmpRecords {
   423  				if r > 0 {
   424  					records[src] += r
   425  					prefixes[src]++
   426  				}
   427  			}
   428  			return false
   429  		})
   430  		return records, prefixes
   431  	}
   432  
   433  	recordsV4, prefixesV4 := f(m.Roas[bgp.RF_IPv4_UC])
   434  	recordsV6, prefixesV6 := f(m.Roas[bgp.RF_IPv6_UC])
   435  
   436  	l := make([]*config.RpkiServer, 0, len(m.clientMap))
   437  	for _, client := range m.clientMap {
   438  		state := &client.state
   439  
   440  		if client.conn == nil {
   441  			state.Up = false
   442  		} else {
   443  			state.Up = true
   444  		}
   445  		f := func(m map[string]uint32, key string) uint32 {
   446  			if r, ok := m[key]; ok {
   447  				return r
   448  			}
   449  			return 0
   450  		}
   451  		state.RecordsV4 = f(recordsV4, client.host)
   452  		state.RecordsV6 = f(recordsV6, client.host)
   453  		state.PrefixesV4 = f(prefixesV4, client.host)
   454  		state.PrefixesV6 = f(prefixesV6, client.host)
   455  		state.SerialNumber = client.serialNumber
   456  
   457  		addr, port, _ := net.SplitHostPort(client.host)
   458  		l = append(l, &config.RpkiServer{
   459  			Config: config.RpkiServerConfig{
   460  				Address: addr,
   461  				// Note: RpkiServerConfig.Port is uint32 type, but the TCP/UDP
   462  				// port is 16-bit length.
   463  				Port: func() uint32 { p, _ := strconv.ParseUint(port, 10, 16); return uint32(p) }(),
   464  			},
   465  			State: client.state,
   466  		})
   467  	}
   468  	return l
   469  }
   470  
   471  func (m *roaManager) GetRoa(family bgp.RouteFamily) ([]*table.ROA, error) {
   472  	if len(m.clientMap) == 0 {
   473  		return []*table.ROA{}, fmt.Errorf("RPKI server isn't configured.")
   474  	}
   475  	var rfList []bgp.RouteFamily
   476  	switch family {
   477  	case bgp.RF_IPv4_UC:
   478  		rfList = []bgp.RouteFamily{bgp.RF_IPv4_UC}
   479  	case bgp.RF_IPv6_UC:
   480  		rfList = []bgp.RouteFamily{bgp.RF_IPv6_UC}
   481  	default:
   482  		rfList = []bgp.RouteFamily{bgp.RF_IPv4_UC, bgp.RF_IPv6_UC}
   483  	}
   484  	l := make([]*table.ROA, 0)
   485  	for _, rf := range rfList {
   486  		if tree, ok := m.Roas[rf]; ok {
   487  			tree.Walk(func(s string, v interface{}) bool {
   488  				b, _ := v.(*roaBucket)
   489  				var roaList roas
   490  				for _, r := range b.entries {
   491  					roaList = append(roaList, r)
   492  				}
   493  				sort.Sort(roaList)
   494  				for _, roa := range roaList {
   495  					l = append(l, roa)
   496  				}
   497  				return false
   498  			})
   499  		}
   500  	}
   501  	return l, nil
   502  }
   503  
   504  func validatePath(ownAs uint32, tree *radix.Tree, cidr string, asPath *bgp.PathAttributeAsPath) *table.Validation {
   505  	var as uint32
   506  
   507  	validation := &table.Validation{
   508  		Status:          config.RPKI_VALIDATION_RESULT_TYPE_NOT_FOUND,
   509  		Reason:          table.RPKI_VALIDATION_REASON_TYPE_NONE,
   510  		Matched:         make([]*table.ROA, 0),
   511  		UnmatchedLength: make([]*table.ROA, 0),
   512  		UnmatchedAs:     make([]*table.ROA, 0),
   513  	}
   514  
   515  	if asPath == nil || len(asPath.Value) == 0 {
   516  		as = ownAs
   517  	} else {
   518  		param := asPath.Value[len(asPath.Value)-1]
   519  		switch param.GetType() {
   520  		case bgp.BGP_ASPATH_ATTR_TYPE_SEQ:
   521  			asList := param.GetAS()
   522  			if len(asList) == 0 {
   523  				as = ownAs
   524  			} else {
   525  				as = asList[len(asList)-1]
   526  			}
   527  		case bgp.BGP_ASPATH_ATTR_TYPE_CONFED_SET, bgp.BGP_ASPATH_ATTR_TYPE_CONFED_SEQ:
   528  			as = ownAs
   529  		default:
   530  			return validation
   531  		}
   532  	}
   533  	_, n, _ := net.ParseCIDR(cidr)
   534  	ones, _ := n.Mask.Size()
   535  	prefixLen := uint8(ones)
   536  	key := table.IpToRadixkey(n.IP, prefixLen)
   537  	_, b, _ := tree.LongestPrefix(key)
   538  	if b == nil {
   539  		return validation
   540  	}
   541  
   542  	var bucket *roaBucket
   543  	fn := radix.WalkFn(func(k string, v interface{}) bool {
   544  		bucket, _ = v.(*roaBucket)
   545  		for _, r := range bucket.entries {
   546  			if prefixLen <= r.MaxLen {
   547  				if r.AS != 0 && r.AS == as {
   548  					validation.Matched = append(validation.Matched, r)
   549  				} else {
   550  					validation.UnmatchedAs = append(validation.UnmatchedAs, r)
   551  				}
   552  			} else {
   553  				validation.UnmatchedLength = append(validation.UnmatchedLength, r)
   554  			}
   555  		}
   556  		return false
   557  	})
   558  	tree.WalkPath(key, fn)
   559  
   560  	if len(validation.Matched) != 0 {
   561  		validation.Status = config.RPKI_VALIDATION_RESULT_TYPE_VALID
   562  		validation.Reason = table.RPKI_VALIDATION_REASON_TYPE_NONE
   563  	} else if len(validation.UnmatchedAs) != 0 {
   564  		validation.Status = config.RPKI_VALIDATION_RESULT_TYPE_INVALID
   565  		validation.Reason = table.RPKI_VALIDATION_REASON_TYPE_AS
   566  	} else if len(validation.UnmatchedLength) != 0 {
   567  		validation.Status = config.RPKI_VALIDATION_RESULT_TYPE_INVALID
   568  		validation.Reason = table.RPKI_VALIDATION_REASON_TYPE_LENGTH
   569  	} else {
   570  		validation.Status = config.RPKI_VALIDATION_RESULT_TYPE_NOT_FOUND
   571  		validation.Reason = table.RPKI_VALIDATION_REASON_TYPE_NONE
   572  	}
   573  
   574  	return validation
   575  }
   576  
   577  func (m *roaManager) validate(path *table.Path) *table.Validation {
   578  	if len(m.clientMap) == 0 || path.IsWithdraw || path.IsEOR() {
   579  		// RPKI isn't enabled or invalid path
   580  		return nil
   581  	}
   582  	if tree, ok := m.Roas[path.GetRouteFamily()]; ok {
   583  		return validatePath(m.AS, tree, path.GetNlri().String(), path.GetAsPath())
   584  	}
   585  	return nil
   586  }
   587  
   588  type roaClient struct {
   589  	host         string
   590  	conn         *net.TCPConn
   591  	state        config.RpkiServerState
   592  	eventCh      chan *roaEvent
   593  	sessionID    uint16
   594  	oldSessionID uint16
   595  	serialNumber uint32
   596  	timer        *time.Timer
   597  	lifetime     int64
   598  	endOfData    bool
   599  	pendingROAs  []*table.ROA
   600  	cancelfnc    context.CancelFunc
   601  	ctx          context.Context
   602  }
   603  
   604  func newRoaClient(address, port string, ch chan *roaEvent, lifetime int64) *roaClient {
   605  	ctx, cancel := context.WithCancel(context.Background())
   606  	c := &roaClient{
   607  		host:        net.JoinHostPort(address, port),
   608  		eventCh:     ch,
   609  		lifetime:    lifetime,
   610  		pendingROAs: make([]*table.ROA, 0),
   611  		ctx:         ctx,
   612  		cancelfnc:   cancel,
   613  	}
   614  	go c.tryConnect()
   615  	return c
   616  }
   617  
   618  func (c *roaClient) enable(serial uint32) error {
   619  	if c.conn != nil {
   620  		r := rtr.NewRTRSerialQuery(c.sessionID, serial)
   621  		data, _ := r.Serialize()
   622  		_, err := c.conn.Write(data)
   623  		if err != nil {
   624  			return err
   625  		}
   626  		c.state.RpkiMessages.RpkiSent.SerialQuery++
   627  	}
   628  	return nil
   629  }
   630  
   631  func (c *roaClient) softReset() error {
   632  	if c.conn != nil {
   633  		r := rtr.NewRTRResetQuery()
   634  		data, _ := r.Serialize()
   635  		_, err := c.conn.Write(data)
   636  		if err != nil {
   637  			return err
   638  		}
   639  		c.state.RpkiMessages.RpkiSent.ResetQuery++
   640  		c.endOfData = false
   641  		c.pendingROAs = make([]*table.ROA, 0)
   642  	}
   643  	return nil
   644  }
   645  
   646  func (c *roaClient) reset() {
   647  	if c.conn != nil {
   648  		c.conn.Close()
   649  	}
   650  }
   651  
   652  func (c *roaClient) stop() {
   653  	c.cancelfnc()
   654  	c.reset()
   655  }
   656  
   657  func (c *roaClient) tryConnect() {
   658  	for {
   659  		select {
   660  		case <-c.ctx.Done():
   661  			return
   662  		default:
   663  		}
   664  		if conn, err := net.Dial("tcp", c.host); err != nil {
   665  			// better to use context with timeout
   666  			time.Sleep(connectRetryInterval * time.Second)
   667  		} else {
   668  			c.eventCh <- &roaEvent{
   669  				EventType: roaConnected,
   670  				Src:       c.host,
   671  				conn:      conn.(*net.TCPConn),
   672  			}
   673  			return
   674  		}
   675  	}
   676  }
   677  
   678  func (c *roaClient) established() (err error) {
   679  	defer func() {
   680  		c.conn.Close()
   681  		c.eventCh <- &roaEvent{
   682  			EventType: roaDisconnected,
   683  			Src:       c.host,
   684  		}
   685  	}()
   686  
   687  	if err := c.softReset(); err != nil {
   688  		return err
   689  	}
   690  
   691  	for {
   692  		header := make([]byte, rtr.RTR_MIN_LEN)
   693  		if _, err = io.ReadFull(c.conn, header); err != nil {
   694  			return err
   695  		}
   696  		totalLen := binary.BigEndian.Uint32(header[4:8])
   697  		if totalLen < rtr.RTR_MIN_LEN {
   698  			return fmt.Errorf("too short header length %v", totalLen)
   699  		}
   700  
   701  		body := make([]byte, totalLen-rtr.RTR_MIN_LEN)
   702  		if _, err = io.ReadFull(c.conn, body); err != nil {
   703  			return
   704  		}
   705  
   706  		c.eventCh <- &roaEvent{
   707  			EventType: roaRTR,
   708  			Src:       c.host,
   709  			Data:      append(header, body...),
   710  		}
   711  	}
   712  }