github.com/osrg/gobgp@v2.0.0+incompatible/internal/pkg/zebra/zapi.go (about)

     1  // Copyright (C) 2014, 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 zebra
    17  
    18  import (
    19  	"encoding/binary"
    20  	"errors"
    21  	"fmt"
    22  	"io"
    23  	"math"
    24  	"net"
    25  	"strings"
    26  	"syscall"
    27  
    28  	log "github.com/sirupsen/logrus"
    29  
    30  	"github.com/osrg/gobgp/pkg/packet/bgp"
    31  )
    32  
    33  const (
    34  	HEADER_MARKER     = 255
    35  	FRR_HEADER_MARKER = 254
    36  	INTERFACE_NAMSIZ  = 20
    37  )
    38  
    39  const (
    40  	MinZapiVer uint8 = 2
    41  	MaxZapiVer uint8 = 6
    42  )
    43  
    44  // Internal Interface Status.
    45  type INTERFACE_STATUS uint8
    46  
    47  const (
    48  	INTERFACE_ACTIVE        INTERFACE_STATUS = 0x01
    49  	INTERFACE_SUB           INTERFACE_STATUS = 0x02
    50  	INTERFACE_LINKDETECTION INTERFACE_STATUS = 0x04
    51  	INTERFACE_VRF_LOOPBACK  INTERFACE_STATUS = 0x08
    52  )
    53  
    54  // Interface Link Layer Types.
    55  //go:generate stringer -type=LINK_TYPE
    56  type LINK_TYPE uint32
    57  
    58  const (
    59  	LINK_TYPE_UNKNOWN LINK_TYPE = iota
    60  	LINK_TYPE_ETHER
    61  	LINK_TYPE_EETHER
    62  	LINK_TYPE_AX25
    63  	LINK_TYPE_PRONET
    64  	LINK_TYPE_IEEE802
    65  	LINK_TYPE_ARCNET
    66  	LINK_TYPE_APPLETLK
    67  	LINK_TYPE_DLCI
    68  	LINK_TYPE_ATM
    69  	LINK_TYPE_METRICOM
    70  	LINK_TYPE_IEEE1394
    71  	LINK_TYPE_EUI64
    72  	LINK_TYPE_INFINIBAND
    73  	LINK_TYPE_SLIP
    74  	LINK_TYPE_CSLIP
    75  	LINK_TYPE_SLIP6
    76  	LINK_TYPE_CSLIP6
    77  	LINK_TYPE_RSRVD
    78  	LINK_TYPE_ADAPT
    79  	LINK_TYPE_ROSE
    80  	LINK_TYPE_X25
    81  	LINK_TYPE_PPP
    82  	LINK_TYPE_CHDLC
    83  	LINK_TYPE_LAPB
    84  	LINK_TYPE_RAWHDLC
    85  	LINK_TYPE_IPIP
    86  	LINK_TYPE_IPIP6
    87  	LINK_TYPE_FRAD
    88  	LINK_TYPE_SKIP
    89  	LINK_TYPE_LOOPBACK
    90  	LINK_TYPE_LOCALTLK
    91  	LINK_TYPE_FDDI
    92  	LINK_TYPE_SIT
    93  	LINK_TYPE_IPDDP
    94  	LINK_TYPE_IPGRE
    95  	LINK_TYPE_IP6GRE
    96  	LINK_TYPE_PIMREG
    97  	LINK_TYPE_HIPPI
    98  	LINK_TYPE_ECONET
    99  	LINK_TYPE_IRDA
   100  	LINK_TYPE_FCPP
   101  	LINK_TYPE_FCAL
   102  	LINK_TYPE_FCPL
   103  	LINK_TYPE_FCFABRIC
   104  	LINK_TYPE_IEEE802_TR
   105  	LINK_TYPE_IEEE80211
   106  	LINK_TYPE_IEEE80211_RADIOTAP
   107  	LINK_TYPE_IEEE802154
   108  	LINK_TYPE_IEEE802154_PHY
   109  )
   110  
   111  const VRF_DEFAULT = 0
   112  const MAXPATH_NUM = 64
   113  const MPLS_MAX_LABEL = 16
   114  
   115  func HeaderSize(version uint8) uint16 {
   116  	switch version {
   117  	case 3, 4:
   118  		return 8
   119  	case 5, 6:
   120  		return 10
   121  	default:
   122  		return 6
   123  	}
   124  }
   125  
   126  func (t INTERFACE_STATUS) String() string {
   127  	ss := make([]string, 0, 3)
   128  	if t&INTERFACE_ACTIVE > 0 {
   129  		ss = append(ss, "ACTIVE")
   130  	}
   131  	if t&INTERFACE_SUB > 0 {
   132  		ss = append(ss, "SUB")
   133  	}
   134  	if t&INTERFACE_LINKDETECTION > 0 {
   135  		ss = append(ss, "LINKDETECTION")
   136  	}
   137  	if t&INTERFACE_VRF_LOOPBACK > 0 {
   138  		ss = append(ss, "VRF_LOOPBACK")
   139  	}
   140  	return strings.Join(ss, "|")
   141  }
   142  
   143  // Interface Connected Address Flags
   144  type INTERFACE_ADDRESS_FLAG uint8
   145  
   146  const (
   147  	INTERFACE_ADDRESS_SECONDARY  INTERFACE_ADDRESS_FLAG = 0x01
   148  	INTERFACE_ADDRESS_PEER       INTERFACE_ADDRESS_FLAG = 0x02
   149  	INTERFACE_ADDRESS_UNNUMBERED INTERFACE_ADDRESS_FLAG = 0x04
   150  )
   151  
   152  func (t INTERFACE_ADDRESS_FLAG) String() string {
   153  	ss := make([]string, 0, 3)
   154  	if t&INTERFACE_ADDRESS_SECONDARY > 0 {
   155  		ss = append(ss, "SECONDARY")
   156  	}
   157  	if t&INTERFACE_ADDRESS_PEER > 0 {
   158  		ss = append(ss, "PEER")
   159  	}
   160  	if t&INTERFACE_ADDRESS_UNNUMBERED > 0 {
   161  		ss = append(ss, "UNNUMBERED")
   162  	}
   163  	return strings.Join(ss, "|")
   164  }
   165  
   166  // Address Family Identifier.
   167  //go:generate stringer -type=AFI
   168  type AFI uint8
   169  
   170  const (
   171  	AFI_IP    AFI = 1
   172  	AFI_IP6   AFI = 2
   173  	AFI_ETHER AFI = 3
   174  	AFI_MAX   AFI = 4
   175  )
   176  
   177  // Subsequent Address Family Identifier.
   178  //go:generate stringer -type=SAFI
   179  type SAFI uint8
   180  
   181  const (
   182  	_ SAFI = iota
   183  	SAFI_UNICAST
   184  	SAFI_MULTICAST
   185  	SAFI_RESERVED_3
   186  	SAFI_MPLS_VPN
   187  	SAFI_MAX
   188  )
   189  
   190  // API Types.
   191  //go:generate stringer -type=API_TYPE
   192  type API_TYPE uint16
   193  
   194  // For FRRouting version 6. (ZAPI version 6)
   195  const (
   196  	FRR_ZAPI6_INTERFACE_ADD API_TYPE = iota
   197  	FRR_ZAPI6_INTERFACE_DELETE
   198  	FRR_ZAPI6_INTERFACE_ADDRESS_ADD
   199  	FRR_ZAPI6_INTERFACE_ADDRESS_DELETE
   200  	FRR_ZAPI6_INTERFACE_UP
   201  	FRR_ZAPI6_INTERFACE_DOWN
   202  	FRR_ZAPI6_INTERFACE_SET_MASTER
   203  	FRR_ZAPI6_ROUTE_ADD
   204  	FRR_ZAPI6_ROUTE_DELETE
   205  	FRR_ZAPI6_ROUTE_NOTIFY_OWNER
   206  	FRR_ZAPI6_REDISTRIBUTE_ADD
   207  	FRR_ZAPI6_REDISTRIBUTE_DELETE
   208  	FRR_ZAPI6_REDISTRIBUTE_DEFAULT_ADD
   209  	FRR_ZAPI6_REDISTRIBUTE_DEFAULT_DELETE
   210  	FRR_ZAPI6_ROUTER_ID_ADD
   211  	FRR_ZAPI6_ROUTER_ID_DELETE
   212  	FRR_ZAPI6_ROUTER_ID_UPDATE
   213  	FRR_ZAPI6_HELLO
   214  	FRR_ZAPI6_CAPABILITIES
   215  	FRR_ZAPI6_NEXTHOP_REGISTER
   216  	FRR_ZAPI6_NEXTHOP_UNREGISTER
   217  	FRR_ZAPI6_NEXTHOP_UPDATE
   218  	FRR_ZAPI6_INTERFACE_NBR_ADDRESS_ADD
   219  	FRR_ZAPI6_INTERFACE_NBR_ADDRESS_DELETE
   220  	FRR_ZAPI6_INTERFACE_BFD_DEST_UPDATE
   221  	FRR_ZAPI6_IMPORT_ROUTE_REGISTER
   222  	FRR_ZAPI6_IMPORT_ROUTE_UNREGISTER
   223  	FRR_ZAPI6_IMPORT_CHECK_UPDATE
   224  	FRR_ZAPI6_IPV4_ROUTE_IPV6_NEXTHOP_ADD
   225  	FRR_ZAPI6_BFD_DEST_REGISTER
   226  	FRR_ZAPI6_BFD_DEST_DEREGISTER
   227  	FRR_ZAPI6_BFD_DEST_UPDATE
   228  	FRR_ZAPI6_BFD_DEST_REPLAY
   229  	FRR_ZAPI6_REDISTRIBUTE_ROUTE_ADD
   230  	FRR_ZAPI6_REDISTRIBUTE_ROUTE_DEL
   231  	FRR_ZAPI6_VRF_UNREGISTER
   232  	FRR_ZAPI6_VRF_ADD
   233  	FRR_ZAPI6_VRF_DELETE
   234  	FRR_ZAPI6_VRF_LABEL
   235  	FRR_ZAPI6_INTERFACE_VRF_UPDATE
   236  	FRR_ZAPI6_BFD_CLIENT_REGISTER
   237  	FRR_ZAPI6_BFD_CLIENT_DEREGISTER
   238  	FRR_ZAPI6_INTERFACE_ENABLE_RADV
   239  	FRR_ZAPI6_INTERFACE_DISABLE_RADV
   240  	FRR_ZAPI6_IPV4_NEXTHOP_LOOKUP_MRIB
   241  	FRR_ZAPI6_INTERFACE_LINK_PARAMS
   242  	FRR_ZAPI6_MPLS_LABELS_ADD
   243  	FRR_ZAPI6_MPLS_LABELS_DELETE
   244  	FRR_ZAPI6_IPMR_ROUTE_STATS
   245  	FRR_ZAPI6_LABEL_MANAGER_CONNECT
   246  	FRR_ZAPI6_GET_LABEL_CHUNK
   247  	FRR_ZAPI6_RELEASE_LABEL_CHUNK
   248  	FRR_ZAPI6_FEC_REGISTER
   249  	FRR_ZAPI6_FEC_UNREGISTER
   250  	FRR_ZAPI6_FEC_UPDATE
   251  	FRR_ZAPI6_ADVERTISE_DEFAULT_GW
   252  	FRR_ZAPI6_ADVERTISE_SUBNET
   253  	FRR_ZAPI6_ADVERTISE_ALL_VNI
   254  	FRR_ZAPI6_LOCAL_ES_ADD
   255  	FRR_ZAPI6_LOCAL_ES_DEL
   256  	FRR_ZAPI6_VNI_ADD
   257  	FRR_ZAPI6_VNI_DEL
   258  	FRR_ZAPI6_L3VNI_ADD
   259  	FRR_ZAPI6_L3VNI_DEL
   260  	FRR_ZAPI6_REMOTE_VTEP_ADD
   261  	FRR_ZAPI6_REMOTE_VTEP_DEL
   262  	FRR_ZAPI6_MACIP_ADD
   263  	FRR_ZAPI6_MACIP_DEL
   264  	FRR_ZAPI6_IP_PREFIX_ROUTE_ADD
   265  	FRR_ZAPI6_IP_PREFIX_ROUTE_DEL
   266  	FRR_ZAPI6_REMOTE_MACIP_ADD
   267  	FRR_ZAPI6_REMOTE_MACIP_DEL
   268  	FRR_ZAPI6_PW_ADD
   269  	FRR_ZAPI6_PW_DELETE
   270  	FRR_ZAPI6_PW_SET
   271  	FRR_ZAPI6_PW_UNSET
   272  	FRR_ZAPI6_PW_STATUS_UPDATE
   273  	FRR_ZAPI6_RULE_ADD
   274  	FRR_ZAPI6_RULE_DELETE
   275  	FRR_ZAPI6_RULE_NOTIFY_OWNER
   276  	FRR_ZAPI6_TABLE_MANAGER_CONNECT
   277  	FRR_ZAPI6_GET_TABLE_CHUNK
   278  	FRR_ZAPI6_RELEASE_TABLE_CHUNK
   279  	FRR_ZAPI6_IPSET_CREATE
   280  	FRR_ZAPI6_IPSET_DESTROY
   281  	FRR_ZAPI6_IPSET_ENTRY_ADD
   282  	FRR_ZAPI6_IPSET_ENTRY_DELETE
   283  	FRR_ZAPI6_IPSET_NOTIFY_OWNER
   284  	FRR_ZAPI6_IPSET_ENTRY_NOTIFY_OWNER
   285  	FRR_ZAPI6_IPTABLE_ADD
   286  	FRR_ZAPI6_IPTABLE_DELETE
   287  	FRR_ZAPI6_IPTABLE_NOTIFY_OWNER
   288  )
   289  
   290  // For FRRouting version 4 and 5. (ZAPI version 5)
   291  const (
   292  	FRR_ZAPI5_INTERFACE_ADD API_TYPE = iota
   293  	FRR_ZAPI5_INTERFACE_DELETE
   294  	FRR_ZAPI5_INTERFACE_ADDRESS_ADD
   295  	FRR_ZAPI5_INTERFACE_ADDRESS_DELETE
   296  	FRR_ZAPI5_INTERFACE_UP
   297  	FRR_ZAPI5_INTERFACE_DOWN
   298  	FRR_ZAPI5_INTERFACE_SET_MASTER
   299  	FRR_ZAPI5_ROUTE_ADD
   300  	FRR_ZAPI5_ROUTE_DELETE
   301  	FRR_ZAPI5_ROUTE_NOTIFY_OWNER
   302  	FRR_ZAPI5_IPV4_ROUTE_ADD
   303  	FRR_ZAPI5_IPV4_ROUTE_DELETE
   304  	FRR_ZAPI5_IPV6_ROUTE_ADD
   305  	FRR_ZAPI5_IPV6_ROUTE_DELETE
   306  	FRR_ZAPI5_REDISTRIBUTE_ADD
   307  	FRR_ZAPI5_REDISTRIBUTE_DELETE
   308  	FRR_ZAPI5_REDISTRIBUTE_DEFAULT_ADD
   309  	FRR_ZAPI5_REDISTRIBUTE_DEFAULT_DELETE
   310  	FRR_ZAPI5_ROUTER_ID_ADD
   311  	FRR_ZAPI5_ROUTER_ID_DELETE
   312  	FRR_ZAPI5_ROUTER_ID_UPDATE
   313  	FRR_ZAPI5_HELLO
   314  	FRR_ZAPI5_CAPABILITIES
   315  	FRR_ZAPI5_NEXTHOP_REGISTER
   316  	FRR_ZAPI5_NEXTHOP_UNREGISTER
   317  	FRR_ZAPI5_NEXTHOP_UPDATE
   318  	FRR_ZAPI5_INTERFACE_NBR_ADDRESS_ADD
   319  	FRR_ZAPI5_INTERFACE_NBR_ADDRESS_DELETE
   320  	FRR_ZAPI5_INTERFACE_BFD_DEST_UPDATE
   321  	FRR_ZAPI5_IMPORT_ROUTE_REGISTER
   322  	FRR_ZAPI5_IMPORT_ROUTE_UNREGISTER
   323  	FRR_ZAPI5_IMPORT_CHECK_UPDATE
   324  	FRR_ZAPI5_IPV4_ROUTE_IPV6_NEXTHOP_ADD
   325  	FRR_ZAPI5_BFD_DEST_REGISTER
   326  	FRR_ZAPI5_BFD_DEST_DEREGISTER
   327  	FRR_ZAPI5_BFD_DEST_UPDATE
   328  	FRR_ZAPI5_BFD_DEST_REPLAY
   329  	FRR_ZAPI5_REDISTRIBUTE_ROUTE_ADD
   330  	FRR_ZAPI5_REDISTRIBUTE_ROUTE_DEL
   331  	FRR_ZAPI5_VRF_UNREGISTER
   332  	FRR_ZAPI5_VRF_ADD
   333  	FRR_ZAPI5_VRF_DELETE
   334  	FRR_ZAPI5_VRF_LABEL
   335  	FRR_ZAPI5_INTERFACE_VRF_UPDATE
   336  	FRR_ZAPI5_BFD_CLIENT_REGISTER
   337  	FRR_ZAPI5_INTERFACE_ENABLE_RADV
   338  	FRR_ZAPI5_INTERFACE_DISABLE_RADV
   339  	FRR_ZAPI5_IPV4_NEXTHOP_LOOKUP_MRIB
   340  	FRR_ZAPI5_INTERFACE_LINK_PARAMS
   341  	FRR_ZAPI5_MPLS_LABELS_ADD
   342  	FRR_ZAPI5_MPLS_LABELS_DELETE
   343  	FRR_ZAPI5_IPMR_ROUTE_STATS
   344  	FRR_ZAPI5_LABEL_MANAGER_CONNECT
   345  	FRR_ZAPI5_LABEL_MANAGER_CONNECT_ASYNC
   346  	FRR_ZAPI5_GET_LABEL_CHUNK
   347  	FRR_ZAPI5_RELEASE_LABEL_CHUNK
   348  	FRR_ZAPI5_FEC_REGISTER
   349  	FRR_ZAPI5_FEC_UNREGISTER
   350  	FRR_ZAPI5_FEC_UPDATE
   351  	FRR_ZAPI5_ADVERTISE_DEFAULT_GW
   352  	FRR_ZAPI5_ADVERTISE_SUBNET
   353  	FRR_ZAPI5_ADVERTISE_ALL_VNI
   354  	FRR_ZAPI5_VNI_ADD
   355  	FRR_ZAPI5_VNI_DEL
   356  	FRR_ZAPI5_L3VNI_ADD
   357  	FRR_ZAPI5_L3VNI_DEL
   358  	FRR_ZAPI5_REMOTE_VTEP_ADD
   359  	FRR_ZAPI5_REMOTE_VTEP_DEL
   360  	FRR_ZAPI5_MACIP_ADD
   361  	FRR_ZAPI5_MACIP_DEL
   362  	FRR_ZAPI5_IP_PREFIX_ROUTE_ADD
   363  	FRR_ZAPI5_IP_PREFIX_ROUTE_DEL
   364  	FRR_ZAPI5_REMOTE_MACIP_ADD
   365  	FRR_ZAPI5_REMOTE_MACIP_DEL
   366  	FRR_ZAPI5_PW_ADD
   367  	FRR_ZAPI5_PW_DELETE
   368  	FRR_ZAPI5_PW_SET
   369  	FRR_ZAPI5_PW_UNSET
   370  	FRR_ZAPI5_PW_STATUS_UPDATE
   371  	FRR_ZAPI5_RULE_ADD
   372  	FRR_ZAPI5_RULE_DELETE
   373  	FRR_ZAPI5_RULE_NOTIFY_OWNER
   374  	FRR_ZAPI5_TABLE_MANAGER_CONNECT
   375  	FRR_ZAPI5_GET_TABLE_CHUNK
   376  	FRR_ZAPI5_RELEASE_TABLE_CHUNK
   377  	FRR_ZAPI5_IPSET_CREATE
   378  	FRR_ZAPI5_IPSET_DESTROY
   379  	FRR_ZAPI5_IPSET_ENTRY_ADD
   380  	FRR_ZAPI5_IPSET_ENTRY_DELETE
   381  	FRR_ZAPI5_IPSET_NOTIFY_OWNER
   382  	FRR_ZAPI5_IPSET_ENTRY_NOTIFY_OWNER
   383  	FRR_ZAPI5_IPTABLE_ADD
   384  	FRR_ZAPI5_IPTABLE_DELETE
   385  	FRR_ZAPI5_IPTABLE_NOTIFY_OWNER
   386  )
   387  
   388  // For FRRouting.
   389  const (
   390  	FRR_INTERFACE_ADD API_TYPE = iota
   391  	FRR_INTERFACE_DELETE
   392  	FRR_INTERFACE_ADDRESS_ADD
   393  	FRR_INTERFACE_ADDRESS_DELETE
   394  	FRR_INTERFACE_UP
   395  	FRR_INTERFACE_DOWN
   396  	FRR_IPV4_ROUTE_ADD
   397  	FRR_IPV4_ROUTE_DELETE
   398  	FRR_IPV6_ROUTE_ADD
   399  	FRR_IPV6_ROUTE_DELETE
   400  	FRR_REDISTRIBUTE_ADD
   401  	FRR_REDISTRIBUTE_DELETE
   402  	FRR_REDISTRIBUTE_DEFAULT_ADD
   403  	FRR_REDISTRIBUTE_DEFAULT_DELETE
   404  	FRR_ROUTER_ID_ADD
   405  	FRR_ROUTER_ID_DELETE
   406  	FRR_ROUTER_ID_UPDATE
   407  	FRR_HELLO
   408  	FRR_NEXTHOP_REGISTER
   409  	FRR_NEXTHOP_UNREGISTER
   410  	FRR_NEXTHOP_UPDATE
   411  	FRR_INTERFACE_NBR_ADDRESS_ADD
   412  	FRR_INTERFACE_NBR_ADDRESS_DELETE
   413  	FRR_INTERFACE_BFD_DEST_UPDATE
   414  	FRR_IMPORT_ROUTE_REGISTER
   415  	FRR_IMPORT_ROUTE_UNREGISTER
   416  	FRR_IMPORT_CHECK_UPDATE
   417  	FRR_IPV4_ROUTE_IPV6_NEXTHOP_ADD
   418  	FRR_BFD_DEST_REGISTER
   419  	FRR_BFD_DEST_DEREGISTER
   420  	FRR_BFD_DEST_UPDATE
   421  	FRR_BFD_DEST_REPLAY
   422  	FRR_REDISTRIBUTE_IPV4_ADD
   423  	FRR_REDISTRIBUTE_IPV4_DEL
   424  	FRR_REDISTRIBUTE_IPV6_ADD
   425  	FRR_REDISTRIBUTE_IPV6_DEL
   426  	FRR_VRF_UNREGISTER
   427  	FRR_VRF_ADD
   428  	FRR_VRF_DELETE
   429  	FRR_INTERFACE_VRF_UPDATE
   430  	FRR_BFD_CLIENT_REGISTER
   431  	FRR_INTERFACE_ENABLE_RADV
   432  	FRR_INTERFACE_DISABLE_RADV
   433  	FRR_IPV4_NEXTHOP_LOOKUP_MRIB
   434  	FRR_INTERFACE_LINK_PARAMS
   435  	FRR_MPLS_LABELS_ADD
   436  	FRR_MPLS_LABELS_DELETE
   437  	FRR_IPV4_NEXTHOP_ADD
   438  	FRR_IPV4_NEXTHOP_DELETE
   439  	FRR_IPV6_NEXTHOP_ADD
   440  	FRR_IPV6_NEXTHOP_DELETE
   441  	FRR_IPMR_ROUTE_STATS
   442  	FRR_LABEL_MANAGER_CONNECT
   443  	FRR_GET_LABEL_CHUNK
   444  	FRR_RELEASE_LABEL_CHUNK
   445  	FRR_PW_ADD
   446  	FRR_PW_DELETE
   447  	FRR_PW_SET
   448  	FRR_PW_UNSET
   449  	FRR_PW_STATUS_UPDATE
   450  )
   451  
   452  // For Quagga.
   453  const (
   454  	_ API_TYPE = iota
   455  	INTERFACE_ADD
   456  	INTERFACE_DELETE
   457  	INTERFACE_ADDRESS_ADD
   458  	INTERFACE_ADDRESS_DELETE
   459  	INTERFACE_UP
   460  	INTERFACE_DOWN
   461  	IPV4_ROUTE_ADD
   462  	IPV4_ROUTE_DELETE
   463  	IPV6_ROUTE_ADD
   464  	IPV6_ROUTE_DELETE
   465  	REDISTRIBUTE_ADD
   466  	REDISTRIBUTE_DELETE
   467  	REDISTRIBUTE_DEFAULT_ADD
   468  	REDISTRIBUTE_DEFAULT_DELETE
   469  	IPV4_NEXTHOP_LOOKUP
   470  	IPV6_NEXTHOP_LOOKUP
   471  	IPV4_IMPORT_LOOKUP
   472  	IPV6_IMPORT_LOOKUP
   473  	INTERFACE_RENAME
   474  	ROUTER_ID_ADD
   475  	ROUTER_ID_DELETE
   476  	ROUTER_ID_UPDATE
   477  	HELLO
   478  	IPV4_NEXTHOP_LOOKUP_MRIB
   479  	VRF_UNREGISTER
   480  	INTERFACE_LINK_PARAMS
   481  	NEXTHOP_REGISTER
   482  	NEXTHOP_UNREGISTER
   483  	NEXTHOP_UPDATE
   484  	MESSAGE_MAX
   485  )
   486  
   487  // Route Types.
   488  //go:generate stringer -type=ROUTE_TYPE
   489  type ROUTE_TYPE uint8
   490  
   491  // For FRRouting version 6 (ZAPI version 6).
   492  const (
   493  	FRR_ZAPI6_ROUTE_SYSTEM ROUTE_TYPE = iota
   494  	FRR_ZAPI6_ROUTE_KERNEL
   495  	FRR_ZAPI6_ROUTE_CONNECT
   496  	FRR_ZAPI6_ROUTE_STATIC
   497  	FRR_ZAPI6_ROUTE_RIP
   498  	FRR_ZAPI6_ROUTE_RIPNG
   499  	FRR_ZAPI6_ROUTE_OSPF
   500  	FRR_ZAPI6_ROUTE_OSPF6
   501  	FRR_ZAPI6_ROUTE_ISIS
   502  	FRR_ZAPI6_ROUTE_BGP
   503  	FRR_ZAPI6_ROUTE_PIM
   504  	FRR_ZAPI6_ROUTE_EIGRP
   505  	FRR_ZAPI6_ROUTE_NHRP
   506  	FRR_ZAPI6_ROUTE_HSLS
   507  	FRR_ZAPI6_ROUTE_OLSR
   508  	FRR_ZAPI6_ROUTE_TABLE
   509  	FRR_ZAPI6_ROUTE_LDP
   510  	FRR_ZAPI6_ROUTE_VNC
   511  	FRR_ZAPI6_ROUTE_VNC_DIRECT
   512  	FRR_ZAPI6_ROUTE_VNC_DIRECT_RH
   513  	FRR_ZAPI6_ROUTE_BGP_DIRECT
   514  	FRR_ZAPI6_ROUTE_BGP_DIRECT_EXT
   515  	FRR_ZAPI6_ROUTE_BABEL
   516  	FRR_ZAPI6_ROUTE_SHARP
   517  	FRR_ZAPI6_ROUTE_PBR
   518  	FRR_ZAPI6_ROUTE_BFD
   519  	FRR_ZAPI6_ROUTE_ALL
   520  	FRR_ZAPI6_ROUTE_MAX
   521  )
   522  
   523  // For FRRouting version 4 and 5 (ZAPI version 5).
   524  const (
   525  	FRR_ZAPI5_ROUTE_SYSTEM ROUTE_TYPE = iota
   526  	FRR_ZAPI5_ROUTE_KERNEL
   527  	FRR_ZAPI5_ROUTE_CONNECT
   528  	FRR_ZAPI5_ROUTE_STATIC
   529  	FRR_ZAPI5_ROUTE_RIP
   530  	FRR_ZAPI5_ROUTE_RIPNG
   531  	FRR_ZAPI5_ROUTE_OSPF
   532  	FRR_ZAPI5_ROUTE_OSPF6
   533  	FRR_ZAPI5_ROUTE_ISIS
   534  	FRR_ZAPI5_ROUTE_BGP
   535  	FRR_ZAPI5_ROUTE_PIM
   536  	FRR_ZAPI5_ROUTE_EIGRP
   537  	FRR_ZAPI5_ROUTE_NHRP
   538  	FRR_ZAPI5_ROUTE_HSLS
   539  	FRR_ZAPI5_ROUTE_OLSR
   540  	FRR_ZAPI5_ROUTE_TABLE
   541  	FRR_ZAPI5_ROUTE_LDP
   542  	FRR_ZAPI5_ROUTE_VNC
   543  	FRR_ZAPI5_ROUTE_VNC_DIRECT
   544  	FRR_ZAPI5_ROUTE_VNC_DIRECT_RH
   545  	FRR_ZAPI5_ROUTE_BGP_DIRECT
   546  	FRR_ZAPI5_ROUTE_BGP_DIRECT_EXT
   547  	FRR_ZAPI5_ROUTE_BABEL
   548  	FRR_ZAPI5_ROUTE_SHARP
   549  	FRR_ZAPI5_ROUTE_PBR
   550  	FRR_ZAPI5_ROUTE_ALL
   551  	FRR_ZAPI5_ROUTE_MAX
   552  )
   553  
   554  // For FRRouting.
   555  const (
   556  	FRR_ROUTE_SYSTEM ROUTE_TYPE = iota
   557  	FRR_ROUTE_KERNEL
   558  	FRR_ROUTE_CONNECT
   559  	FRR_ROUTE_STATIC
   560  	FRR_ROUTE_RIP
   561  	FRR_ROUTE_RIPNG
   562  	FRR_ROUTE_OSPF
   563  	FRR_ROUTE_OSPF6
   564  	FRR_ROUTE_ISIS
   565  	FRR_ROUTE_BGP
   566  	FRR_ROUTE_PIM
   567  	FRR_ROUTE_HSLS
   568  	FRR_ROUTE_OLSR
   569  	FRR_ROUTE_TABLE
   570  	FRR_ROUTE_LDP
   571  	FRR_ROUTE_VNC
   572  	FRR_ROUTE_VNC_DIRECT
   573  	FRR_ROUTE_VNC_DIRECT_RH
   574  	FRR_ROUTE_BGP_DIRECT
   575  	FRR_ROUTE_BGP_DIRECT_EXT
   576  	FRR_ROUTE_ALL
   577  	FRR_ROUTE_MAX
   578  )
   579  
   580  // For Quagga.
   581  const (
   582  	ROUTE_SYSTEM ROUTE_TYPE = iota
   583  	ROUTE_KERNEL
   584  	ROUTE_CONNECT
   585  	ROUTE_STATIC
   586  	ROUTE_RIP
   587  	ROUTE_RIPNG
   588  	ROUTE_OSPF
   589  	ROUTE_OSPF6
   590  	ROUTE_ISIS
   591  	ROUTE_BGP
   592  	ROUTE_PIM
   593  	ROUTE_HSLS
   594  	ROUTE_OLSR
   595  	ROUTE_BABEL
   596  	ROUTE_MAX
   597  )
   598  
   599  var routeTypeValueMapFrrZapi6 = map[string]ROUTE_TYPE{
   600  	"system":             FRR_ZAPI6_ROUTE_SYSTEM,
   601  	"kernel":             FRR_ZAPI6_ROUTE_KERNEL,
   602  	"connect":            FRR_ZAPI6_ROUTE_CONNECT, // hack for backward compatibility
   603  	"directly-connected": FRR_ZAPI6_ROUTE_CONNECT,
   604  	"static":             FRR_ZAPI6_ROUTE_STATIC,
   605  	"rip":                FRR_ZAPI6_ROUTE_RIP,
   606  	"ripng":              FRR_ZAPI6_ROUTE_RIPNG,
   607  	"ospf":               FRR_ZAPI6_ROUTE_OSPF,
   608  	"ospf3":              FRR_ZAPI6_ROUTE_OSPF6,
   609  	"isis":               FRR_ZAPI6_ROUTE_ISIS,
   610  	"bgp":                FRR_ZAPI6_ROUTE_BGP,
   611  	"pim":                FRR_ZAPI6_ROUTE_PIM,
   612  	"eigrp":              FRR_ZAPI6_ROUTE_EIGRP,
   613  	"nhrp":               FRR_ZAPI6_ROUTE_EIGRP,
   614  	"hsls":               FRR_ZAPI6_ROUTE_HSLS,
   615  	"olsr":               FRR_ZAPI6_ROUTE_OLSR,
   616  	"table":              FRR_ZAPI6_ROUTE_TABLE,
   617  	"ldp":                FRR_ZAPI6_ROUTE_LDP,
   618  	"vnc":                FRR_ZAPI6_ROUTE_VNC,
   619  	"vnc-direct":         FRR_ZAPI6_ROUTE_VNC_DIRECT,
   620  	"vnc-direct-rh":      FRR_ZAPI6_ROUTE_VNC_DIRECT_RH,
   621  	"bgp-direct":         FRR_ZAPI6_ROUTE_BGP_DIRECT,
   622  	"bgp-direct-ext":     FRR_ZAPI6_ROUTE_BGP_DIRECT_EXT,
   623  	"babel":              FRR_ZAPI6_ROUTE_BABEL,
   624  	"sharp":              FRR_ZAPI6_ROUTE_SHARP,
   625  	"pbr":                FRR_ZAPI6_ROUTE_PBR,
   626  	"bfd":                FRR_ZAPI6_ROUTE_BFD,
   627  	"all":                FRR_ZAPI6_ROUTE_ALL,
   628  }
   629  
   630  var routeTypeValueMapFrrZapi5 = map[string]ROUTE_TYPE{
   631  	"system":             FRR_ZAPI5_ROUTE_SYSTEM,
   632  	"kernel":             FRR_ZAPI5_ROUTE_KERNEL,
   633  	"connect":            FRR_ZAPI5_ROUTE_CONNECT, // hack for backward compatibility
   634  	"directly-connected": FRR_ZAPI5_ROUTE_CONNECT,
   635  	"static":             FRR_ZAPI5_ROUTE_STATIC,
   636  	"rip":                FRR_ZAPI5_ROUTE_RIP,
   637  	"ripng":              FRR_ZAPI5_ROUTE_RIPNG,
   638  	"ospf":               FRR_ZAPI5_ROUTE_OSPF,
   639  	"ospf3":              FRR_ZAPI5_ROUTE_OSPF6,
   640  	"isis":               FRR_ZAPI5_ROUTE_ISIS,
   641  	"bgp":                FRR_ZAPI5_ROUTE_BGP,
   642  	"pim":                FRR_ZAPI5_ROUTE_PIM,
   643  	"eigrp":              FRR_ZAPI5_ROUTE_EIGRP,
   644  	"nhrp":               FRR_ZAPI5_ROUTE_EIGRP,
   645  	"hsls":               FRR_ZAPI5_ROUTE_HSLS,
   646  	"olsr":               FRR_ZAPI5_ROUTE_OLSR,
   647  	"table":              FRR_ZAPI5_ROUTE_TABLE,
   648  	"ldp":                FRR_ZAPI5_ROUTE_LDP,
   649  	"vnc":                FRR_ZAPI5_ROUTE_VNC,
   650  	"vnc-direct":         FRR_ZAPI5_ROUTE_VNC_DIRECT,
   651  	"vnc-direct-rh":      FRR_ZAPI5_ROUTE_VNC_DIRECT_RH,
   652  	"bgp-direct":         FRR_ZAPI5_ROUTE_BGP_DIRECT,
   653  	"bgp-direct-ext":     FRR_ZAPI5_ROUTE_BGP_DIRECT_EXT,
   654  	"babel":              FRR_ZAPI5_ROUTE_BABEL,
   655  	"sharp":              FRR_ZAPI5_ROUTE_SHARP,
   656  	"pbr":                FRR_ZAPI5_ROUTE_PBR,
   657  	"all":                FRR_ZAPI5_ROUTE_ALL,
   658  }
   659  
   660  var routeTypeValueMapFrr = map[string]ROUTE_TYPE{
   661  	"system":             FRR_ROUTE_SYSTEM,
   662  	"kernel":             FRR_ROUTE_KERNEL,
   663  	"connect":            FRR_ROUTE_CONNECT, // hack for backward compatibility
   664  	"directly-connected": FRR_ROUTE_CONNECT,
   665  	"static":             FRR_ROUTE_STATIC,
   666  	"rip":                FRR_ROUTE_RIP,
   667  	"ripng":              FRR_ROUTE_RIPNG,
   668  	"ospf":               FRR_ROUTE_OSPF,
   669  	"ospf3":              FRR_ROUTE_OSPF6,
   670  	"isis":               FRR_ROUTE_ISIS,
   671  	"bgp":                FRR_ROUTE_BGP,
   672  	"pim":                FRR_ROUTE_PIM,
   673  	"hsls":               FRR_ROUTE_HSLS,
   674  	"olsr":               FRR_ROUTE_OLSR,
   675  	"table":              FRR_ROUTE_TABLE,
   676  	"ldp":                FRR_ROUTE_LDP,
   677  	"vnc":                FRR_ROUTE_VNC,
   678  	"vnc-direct":         FRR_ROUTE_VNC_DIRECT,
   679  	"vnc-direct-rh":      FRR_ROUTE_VNC_DIRECT_RH,
   680  	"bgp-direct":         FRR_ROUTE_BGP_DIRECT,
   681  	"bgp-direct-ext":     FRR_ROUTE_BGP_DIRECT_EXT,
   682  	"all":                FRR_ROUTE_ALL,
   683  }
   684  
   685  var routeTypeValueMap = map[string]ROUTE_TYPE{
   686  	"system":             ROUTE_SYSTEM,
   687  	"kernel":             ROUTE_KERNEL,
   688  	"connect":            ROUTE_CONNECT, // hack for backward compatibility
   689  	"directly-connected": ROUTE_CONNECT,
   690  	"static":             ROUTE_STATIC,
   691  	"rip":                ROUTE_RIP,
   692  	"ripng":              ROUTE_RIPNG,
   693  	"ospf":               ROUTE_OSPF,
   694  	"ospf3":              ROUTE_OSPF6,
   695  	"isis":               ROUTE_ISIS,
   696  	"bgp":                ROUTE_BGP,
   697  	"pim":                ROUTE_PIM,
   698  	"hsls":               ROUTE_HSLS,
   699  	"olsr":               ROUTE_OLSR,
   700  	"babel":              ROUTE_BABEL,
   701  }
   702  
   703  func RouteTypeFromString(typ string, version uint8) (ROUTE_TYPE, error) {
   704  	delegateRouteTypeValueMap := routeTypeValueMap
   705  	if version == 4 {
   706  		delegateRouteTypeValueMap = routeTypeValueMapFrr
   707  	} else if version == 5 {
   708  		delegateRouteTypeValueMap = routeTypeValueMapFrrZapi5
   709  	} else if version >= 6 {
   710  		delegateRouteTypeValueMap = routeTypeValueMapFrrZapi6
   711  	}
   712  	t, ok := delegateRouteTypeValueMap[typ]
   713  	if ok {
   714  		return t, nil
   715  	}
   716  	return t, fmt.Errorf("unknown route type: %s", typ)
   717  }
   718  
   719  func addressFamilyFromApi(Api API_TYPE, version uint8) uint8 {
   720  	if version <= 3 {
   721  		switch Api {
   722  		case IPV4_ROUTE_ADD, IPV4_ROUTE_DELETE, IPV4_NEXTHOP_LOOKUP, IPV4_IMPORT_LOOKUP:
   723  			return syscall.AF_INET
   724  		case IPV6_ROUTE_ADD, IPV6_ROUTE_DELETE, IPV6_NEXTHOP_LOOKUP, IPV6_IMPORT_LOOKUP:
   725  			return syscall.AF_INET6
   726  		}
   727  	} else if version == 4 {
   728  		switch Api {
   729  		case FRR_REDISTRIBUTE_IPV4_ADD, FRR_REDISTRIBUTE_IPV4_DEL, FRR_IPV4_ROUTE_ADD, FRR_IPV4_ROUTE_DELETE, FRR_IPV4_NEXTHOP_LOOKUP_MRIB:
   730  			return syscall.AF_INET
   731  		case FRR_REDISTRIBUTE_IPV6_ADD, FRR_REDISTRIBUTE_IPV6_DEL, FRR_IPV6_ROUTE_ADD, FRR_IPV6_ROUTE_DELETE:
   732  			return syscall.AF_INET6
   733  		}
   734  	} else if version == 5 {
   735  		switch Api {
   736  		case FRR_ZAPI5_IPV4_ROUTE_ADD, FRR_ZAPI5_IPV4_ROUTE_DELETE, FRR_ZAPI5_IPV4_NEXTHOP_LOOKUP_MRIB:
   737  			return syscall.AF_INET
   738  		case FRR_ZAPI5_IPV6_ROUTE_ADD, FRR_ZAPI5_IPV6_ROUTE_DELETE:
   739  			return syscall.AF_INET6
   740  		}
   741  	}
   742  	return syscall.AF_UNSPEC
   743  }
   744  
   745  func addressByteLength(family uint8) (int, error) {
   746  	switch family {
   747  	case syscall.AF_INET:
   748  		return net.IPv4len, nil
   749  	case syscall.AF_INET6:
   750  		return net.IPv6len, nil
   751  	}
   752  	return 0, fmt.Errorf("unknown address family: %d", family)
   753  }
   754  
   755  func ipFromFamily(family uint8, buf []byte) net.IP {
   756  	switch family {
   757  	case syscall.AF_INET:
   758  		return net.IP(buf).To4()
   759  	case syscall.AF_INET6:
   760  		return net.IP(buf).To16()
   761  	}
   762  	return nil
   763  }
   764  
   765  // API Message Flags.
   766  type MESSAGE_FLAG uint8
   767  
   768  // For FRRouting version 4, 5 and 6 (ZAPI version 5 and 6).
   769  const (
   770  	FRR_ZAPI5_MESSAGE_NEXTHOP  MESSAGE_FLAG = 0x01
   771  	FRR_ZAPI5_MESSAGE_DISTANCE MESSAGE_FLAG = 0x02
   772  	FRR_ZAPI5_MESSAGE_METRIC   MESSAGE_FLAG = 0x04
   773  	FRR_ZAPI5_MESSAGE_TAG      MESSAGE_FLAG = 0x08
   774  	FRR_ZAPI5_MESSAGE_MTU      MESSAGE_FLAG = 0x10
   775  	FRR_ZAPI5_MESSAGE_SRCPFX   MESSAGE_FLAG = 0x20
   776  	FRR_ZAPI5_MESSAGE_LABEL    MESSAGE_FLAG = 0x40
   777  	FRR_ZAPI5_MESSAGE_TABLEID  MESSAGE_FLAG = 0x80
   778  )
   779  
   780  // For FRRouting.
   781  const (
   782  	FRR_MESSAGE_NEXTHOP  MESSAGE_FLAG = 0x01
   783  	FRR_MESSAGE_IFINDEX  MESSAGE_FLAG = 0x02
   784  	FRR_MESSAGE_DISTANCE MESSAGE_FLAG = 0x04
   785  	FRR_MESSAGE_METRIC   MESSAGE_FLAG = 0x08
   786  	FRR_MESSAGE_TAG      MESSAGE_FLAG = 0x10
   787  	FRR_MESSAGE_MTU      MESSAGE_FLAG = 0x20
   788  	FRR_MESSAGE_SRCPFX   MESSAGE_FLAG = 0x40
   789  )
   790  
   791  // For Quagga.
   792  const (
   793  	MESSAGE_NEXTHOP  MESSAGE_FLAG = 0x01
   794  	MESSAGE_IFINDEX  MESSAGE_FLAG = 0x02
   795  	MESSAGE_DISTANCE MESSAGE_FLAG = 0x04
   796  	MESSAGE_METRIC   MESSAGE_FLAG = 0x08
   797  	MESSAGE_MTU      MESSAGE_FLAG = 0x10
   798  	MESSAGE_TAG      MESSAGE_FLAG = 0x20
   799  )
   800  
   801  func (t MESSAGE_FLAG) String(version uint8) string {
   802  	var ss []string
   803  	if (version <= 3 && t&MESSAGE_NEXTHOP > 0) ||
   804  		(version == 4 && t&FRR_MESSAGE_NEXTHOP > 0) ||
   805  		(version >= 5 && t&FRR_ZAPI5_MESSAGE_NEXTHOP > 0) {
   806  		ss = append(ss, "NEXTHOP")
   807  	}
   808  	if (version <= 3 && t&MESSAGE_IFINDEX > 0) || (version == 4 && t&FRR_MESSAGE_IFINDEX > 0) {
   809  		ss = append(ss, "IFINDEX")
   810  	}
   811  	if (version <= 3 && t&MESSAGE_DISTANCE > 0) ||
   812  		(version == 4 && t&FRR_MESSAGE_DISTANCE > 0) ||
   813  		(version >= 5 && t&FRR_ZAPI5_MESSAGE_DISTANCE > 0) {
   814  		ss = append(ss, "DISTANCE")
   815  	}
   816  	if (version <= 3 && t&MESSAGE_METRIC > 0) ||
   817  		(version == 4 && t&FRR_MESSAGE_METRIC > 0) ||
   818  		(version >= 5 && t&FRR_ZAPI5_MESSAGE_METRIC > 0) {
   819  		ss = append(ss, "METRIC")
   820  	}
   821  	if (version <= 3 && t&MESSAGE_MTU > 0) || (version == 4 && t&FRR_MESSAGE_MTU > 0) ||
   822  		(version >= 5 && t&FRR_ZAPI5_MESSAGE_MTU > 0) {
   823  		ss = append(ss, "MTU")
   824  	}
   825  	if (version <= 3 && t&MESSAGE_TAG > 0) || (version == 4 && t&FRR_MESSAGE_TAG > 0) ||
   826  		(version >= 5 && t&FRR_ZAPI5_MESSAGE_TAG > 0) {
   827  		ss = append(ss, "TAG")
   828  	}
   829  	if (version == 4 && t&FRR_MESSAGE_SRCPFX > 0) ||
   830  		(version >= 5 && t&FRR_ZAPI5_MESSAGE_SRCPFX > 0) {
   831  		ss = append(ss, "SRCPFX")
   832  	}
   833  	if version >= 5 && t&FRR_ZAPI5_MESSAGE_LABEL > 0 {
   834  		ss = append(ss, "LABEL")
   835  	}
   836  
   837  	return strings.Join(ss, "|")
   838  }
   839  
   840  // Message Flags
   841  type FLAG uint64
   842  
   843  const (
   844  	FLAG_INTERNAL        FLAG = 0x01
   845  	FLAG_SELFROUTE       FLAG = 0x02
   846  	FLAG_BLACKHOLE       FLAG = 0x04
   847  	FLAG_IBGP            FLAG = 0x08
   848  	FLAG_SELECTED        FLAG = 0x10
   849  	FLAG_CHANGED         FLAG = 0x20
   850  	FLAG_STATIC          FLAG = 0x40
   851  	FLAG_REJECT          FLAG = 0x80
   852  	FLAG_SCOPE_LINK      FLAG = 0x100
   853  	FLAG_FIB_OVERRIDE    FLAG = 0x200
   854  	FLAG_EVPN_ROUTE      FLAG = 0x400
   855  	FLAG_RR_USE_DISTANCE FLAG = 0x800
   856  )
   857  
   858  func (t FLAG) String() string {
   859  	var ss []string
   860  	if t&FLAG_INTERNAL > 0 {
   861  		ss = append(ss, "FLAG_INTERNAL")
   862  	}
   863  	if t&FLAG_SELFROUTE > 0 {
   864  		ss = append(ss, "FLAG_SELFROUTE")
   865  	}
   866  	if t&FLAG_BLACKHOLE > 0 {
   867  		ss = append(ss, "FLAG_BLACKHOLE")
   868  	}
   869  	if t&FLAG_IBGP > 0 {
   870  		ss = append(ss, "FLAG_IBGP")
   871  	}
   872  	if t&FLAG_SELECTED > 0 {
   873  		ss = append(ss, "FLAG_SELECTED")
   874  	}
   875  	if t&FLAG_CHANGED > 0 {
   876  		ss = append(ss, "FLAG_CHANGED")
   877  	}
   878  	if t&FLAG_STATIC > 0 {
   879  		ss = append(ss, "FLAG_STATIC")
   880  	}
   881  	if t&FLAG_REJECT > 0 {
   882  		ss = append(ss, "FLAG_REJECT")
   883  	}
   884  	if t&FLAG_SCOPE_LINK > 0 {
   885  		ss = append(ss, "FLAG_SCOPE_LINK")
   886  	}
   887  	if t&FLAG_FIB_OVERRIDE > 0 {
   888  		ss = append(ss, "FLAG_FIB_OVERRIDE")
   889  	}
   890  	if t&FLAG_EVPN_ROUTE > 0 {
   891  		ss = append(ss, "FLAG_EVPN_ROUTE")
   892  	}
   893  	if t&FLAG_RR_USE_DISTANCE > 0 {
   894  		ss = append(ss, "FLAG_RR_USE_DISTANCE")
   895  	}
   896  
   897  	return strings.Join(ss, "|")
   898  }
   899  
   900  // Nexthop Types.
   901  //go:generate stringer -type=NEXTHOP_TYPE
   902  type NEXTHOP_TYPE uint8
   903  
   904  // For FRRouting.
   905  const (
   906  	_ NEXTHOP_TYPE = iota
   907  	FRR_NEXTHOP_TYPE_IFINDEX
   908  	FRR_NEXTHOP_TYPE_IPV4
   909  	FRR_NEXTHOP_TYPE_IPV4_IFINDEX
   910  	FRR_NEXTHOP_TYPE_IPV6
   911  	FRR_NEXTHOP_TYPE_IPV6_IFINDEX
   912  	FRR_NEXTHOP_TYPE_BLACKHOLE
   913  )
   914  
   915  // For Quagga.
   916  const (
   917  	_ NEXTHOP_TYPE = iota
   918  	NEXTHOP_TYPE_IFINDEX
   919  	NEXTHOP_TYPE_IFNAME
   920  	NEXTHOP_TYPE_IPV4
   921  	NEXTHOP_TYPE_IPV4_IFINDEX
   922  	NEXTHOP_TYPE_IPV4_IFNAME
   923  	NEXTHOP_TYPE_IPV6
   924  	NEXTHOP_TYPE_IPV6_IFINDEX
   925  	NEXTHOP_TYPE_IPV6_IFNAME
   926  	NEXTHOP_TYPE_BLACKHOLE
   927  )
   928  
   929  // Nexthop Flags.
   930  //go:generate stringer -type=NEXTHOP_FLAG
   931  type NEXTHOP_FLAG uint8
   932  
   933  const (
   934  	NEXTHOP_FLAG_ACTIVE     NEXTHOP_FLAG = 0x01 // This nexthop is alive.
   935  	NEXTHOP_FLAG_FIB        NEXTHOP_FLAG = 0x02 // FIB nexthop.
   936  	NEXTHOP_FLAG_RECURSIVE  NEXTHOP_FLAG = 0x04 // Recursive nexthop.
   937  	NEXTHOP_FLAG_ONLINK     NEXTHOP_FLAG = 0x08 // Nexthop should be installed onlink.
   938  	NEXTHOP_FLAG_MATCHED    NEXTHOP_FLAG = 0x10 // Already matched vs a nexthop
   939  	NEXTHOP_FLAG_FILTERED   NEXTHOP_FLAG = 0x20 // rmap filtered (version >= 4)
   940  	NEXTHOP_FLAG_DUPLICATE  NEXTHOP_FLAG = 0x40 // nexthop duplicates (version >= 5)
   941  	NEXTHOP_FLAG_EVPN_RVTEP NEXTHOP_FLAG = 0x80 // EVPN remote vtep nexthop (version >= 5)
   942  )
   943  
   944  // Interface PTM Enable Configuration.
   945  //go:generate stringer -type=PTM_ENABLE
   946  type PTM_ENABLE uint8
   947  
   948  const (
   949  	PTM_ENABLE_OFF    PTM_ENABLE = 0
   950  	PTM_ENABLE_ON     PTM_ENABLE = 1
   951  	PTM_ENABLE_UNSPEC PTM_ENABLE = 2
   952  )
   953  
   954  // PTM Status.
   955  //go:generate stringer -type=PTM_STATUS
   956  type PTM_STATUS uint8
   957  
   958  const (
   959  	PTM_STATUS_DOWN    PTM_STATUS = 0
   960  	PTM_STATUS_UP      PTM_STATUS = 1
   961  	PTM_STATUS_UNKNOWN PTM_STATUS = 2
   962  )
   963  
   964  type Client struct {
   965  	outgoing      chan *Message
   966  	incoming      chan *Message
   967  	redistDefault ROUTE_TYPE
   968  	conn          net.Conn
   969  	Version       uint8
   970  }
   971  
   972  func NewClient(network, address string, typ ROUTE_TYPE, version uint8) (*Client, error) {
   973  	conn, err := net.Dial(network, address)
   974  	if err != nil {
   975  		return nil, err
   976  	}
   977  	outgoing := make(chan *Message)
   978  	incoming := make(chan *Message, 64)
   979  	if version < MinZapiVer {
   980  		version = MinZapiVer
   981  	} else if version > MaxZapiVer {
   982  		version = MaxZapiVer
   983  	}
   984  
   985  	c := &Client{
   986  		outgoing:      outgoing,
   987  		incoming:      incoming,
   988  		redistDefault: typ,
   989  		conn:          conn,
   990  		Version:       version,
   991  	}
   992  
   993  	go func() {
   994  		for {
   995  			m, more := <-outgoing
   996  			if more {
   997  				b, err := m.Serialize()
   998  				if err != nil {
   999  					log.WithFields(log.Fields{
  1000  						"Topic": "Zebra",
  1001  					}).Warnf("failed to serialize: %v", m)
  1002  					continue
  1003  				}
  1004  
  1005  				_, err = conn.Write(b)
  1006  				if err != nil {
  1007  					log.WithFields(log.Fields{
  1008  						"Topic": "Zebra",
  1009  					}).Errorf("failed to write: %s", err)
  1010  					ChannelClose(outgoing)
  1011  					return
  1012  				}
  1013  			} else {
  1014  				log.Debug("finish outgoing loop")
  1015  				return
  1016  			}
  1017  		}
  1018  	}()
  1019  
  1020  	// Send HELLO/ROUTER_ID_ADD messages to negotiate the Zebra message version.
  1021  	c.SendHello()
  1022  	c.SendRouterIDAdd()
  1023  
  1024  	receiveSingleMsg := func() (*Message, error) {
  1025  		headerBuf, err := readAll(conn, int(HeaderSize(version)))
  1026  		if err != nil {
  1027  			log.WithFields(log.Fields{
  1028  				"Topic": "Zebra",
  1029  				"Error": err,
  1030  			}).Error("failed to read header")
  1031  			return nil, err
  1032  		}
  1033  
  1034  		hd := &Header{}
  1035  		err = hd.DecodeFromBytes(headerBuf)
  1036  		if c.Version != hd.Version {
  1037  			log.WithFields(log.Fields{
  1038  				"Topic": "Zebra",
  1039  			}).Warnf("ZAPI version mismatch. configured version: %d, version of received message:%d", c.Version, hd.Version)
  1040  			return nil, errors.New("ZAPI version mismatch")
  1041  		}
  1042  		if err != nil {
  1043  			log.WithFields(log.Fields{
  1044  				"Topic": "Zebra",
  1045  				"Data":  headerBuf,
  1046  				"Error": err,
  1047  			}).Error("failed to decode header")
  1048  			return nil, err
  1049  		}
  1050  
  1051  		bodyBuf, err := readAll(conn, int(hd.Len-HeaderSize(version)))
  1052  		if err != nil {
  1053  			log.WithFields(log.Fields{
  1054  				"Topic":  "Zebra",
  1055  				"Header": hd,
  1056  				"Error":  err,
  1057  			}).Error("failed to read body")
  1058  			return nil, err
  1059  		}
  1060  
  1061  		m, err := ParseMessage(hd, bodyBuf)
  1062  		if err != nil {
  1063  			// Just outputting warnings (not error message) and ignore this
  1064  			// error considering the case that body parser is not implemented
  1065  			// yet.
  1066  			log.WithFields(log.Fields{
  1067  				"Topic":  "Zebra",
  1068  				"Header": hd,
  1069  				"Data":   bodyBuf,
  1070  				"Error":  err,
  1071  			}).Warn("failed to decode body")
  1072  			return nil, nil
  1073  		}
  1074  		log.WithFields(log.Fields{
  1075  			"Topic":   "Zebra",
  1076  			"Message": m,
  1077  		}).Debug("read message from zebra")
  1078  
  1079  		return m, nil
  1080  	}
  1081  
  1082  	// Try to receive the first message from Zebra.
  1083  	if m, err := receiveSingleMsg(); err != nil {
  1084  		c.Close()
  1085  		// Return error explicitly in order to retry connection.
  1086  		return nil, err
  1087  	} else if m != nil {
  1088  		incoming <- m
  1089  	}
  1090  
  1091  	// Start receive loop only when the first message successfully received.
  1092  	go func() {
  1093  		defer ChannelClose(incoming)
  1094  		for {
  1095  			if m, err := receiveSingleMsg(); err != nil {
  1096  				return
  1097  			} else if m != nil {
  1098  				incoming <- m
  1099  			}
  1100  		}
  1101  	}()
  1102  
  1103  	return c, nil
  1104  }
  1105  
  1106  func readAll(conn net.Conn, length int) ([]byte, error) {
  1107  	buf := make([]byte, length)
  1108  	_, err := io.ReadFull(conn, buf)
  1109  	return buf, err
  1110  }
  1111  
  1112  func (c *Client) Receive() chan *Message {
  1113  	return c.incoming
  1114  }
  1115  
  1116  func (c *Client) Send(m *Message) {
  1117  	defer func() {
  1118  		if err := recover(); err != nil {
  1119  			log.WithFields(log.Fields{
  1120  				"Topic": "Zebra",
  1121  			}).Debugf("recovered: %s", err)
  1122  		}
  1123  	}()
  1124  	log.WithFields(log.Fields{
  1125  		"Topic":  "Zebra",
  1126  		"Header": m.Header,
  1127  		"Body":   m.Body,
  1128  	}).Debug("send command to zebra")
  1129  	c.outgoing <- m
  1130  }
  1131  
  1132  func (c *Client) SendCommand(command API_TYPE, vrfId uint32, body Body) error {
  1133  	var marker uint8 = HEADER_MARKER
  1134  	if c.Version >= 4 {
  1135  		marker = FRR_HEADER_MARKER
  1136  	}
  1137  	m := &Message{
  1138  		Header: Header{
  1139  			Len:     HeaderSize(c.Version),
  1140  			Marker:  marker,
  1141  			Version: c.Version,
  1142  			VrfId:   vrfId,
  1143  			Command: command,
  1144  		},
  1145  		Body: body,
  1146  	}
  1147  	c.Send(m)
  1148  	return nil
  1149  }
  1150  
  1151  func (c *Client) SendHello() error {
  1152  	if c.redistDefault > 0 {
  1153  		command := HELLO
  1154  		if c.Version == 4 {
  1155  			command = FRR_HELLO
  1156  		} else if c.Version == 5 {
  1157  			command = FRR_ZAPI5_HELLO
  1158  		} else if c.Version >= 6 {
  1159  			command = FRR_ZAPI6_HELLO
  1160  		}
  1161  		body := &HelloBody{
  1162  			RedistDefault: c.redistDefault,
  1163  			Instance:      0,
  1164  		}
  1165  		return c.SendCommand(command, VRF_DEFAULT, body)
  1166  	}
  1167  	return nil
  1168  }
  1169  
  1170  func (c *Client) SendRouterIDAdd() error {
  1171  	command := ROUTER_ID_ADD
  1172  	if c.Version == 4 {
  1173  		command = FRR_ROUTER_ID_ADD
  1174  	} else if c.Version == 5 {
  1175  		command = FRR_ZAPI5_ROUTER_ID_ADD
  1176  	} else if c.Version >= 6 {
  1177  		command = FRR_ZAPI6_ROUTER_ID_ADD
  1178  	}
  1179  	return c.SendCommand(command, VRF_DEFAULT, nil)
  1180  }
  1181  
  1182  func (c *Client) SendInterfaceAdd() error {
  1183  	command := INTERFACE_ADD
  1184  	if c.Version == 4 {
  1185  		command = FRR_INTERFACE_ADD
  1186  	} else if c.Version >= 5 {
  1187  		command = FRR_ZAPI5_INTERFACE_ADD
  1188  	}
  1189  	return c.SendCommand(command, VRF_DEFAULT, nil)
  1190  }
  1191  
  1192  func (c *Client) SendRedistribute(t ROUTE_TYPE, vrfId uint32) error {
  1193  	command := REDISTRIBUTE_ADD
  1194  	if c.redistDefault != t {
  1195  		bodies := make([]*RedistributeBody, 0)
  1196  		if c.Version <= 3 {
  1197  			bodies = append(bodies, &RedistributeBody{
  1198  				Redist: t,
  1199  			})
  1200  		} else { // version >= 4
  1201  			command = FRR_REDISTRIBUTE_ADD
  1202  			if c.Version == 5 {
  1203  				command = FRR_ZAPI5_REDISTRIBUTE_ADD
  1204  			} else if c.Version >= 6 {
  1205  				command = FRR_ZAPI6_REDISTRIBUTE_ADD
  1206  			}
  1207  			for _, afi := range []AFI{AFI_IP, AFI_IP6} {
  1208  				bodies = append(bodies, &RedistributeBody{
  1209  					Afi:      afi,
  1210  					Redist:   t,
  1211  					Instance: 0,
  1212  				})
  1213  			}
  1214  		}
  1215  
  1216  		for _, body := range bodies {
  1217  			return c.SendCommand(command, vrfId, body)
  1218  		}
  1219  	}
  1220  
  1221  	return nil
  1222  }
  1223  
  1224  func (c *Client) SendRedistributeDelete(t ROUTE_TYPE) error {
  1225  	if t < ROUTE_MAX {
  1226  		command := REDISTRIBUTE_DELETE
  1227  		if c.Version == 4 {
  1228  			command = FRR_REDISTRIBUTE_DELETE
  1229  		} else if c.Version == 5 {
  1230  			command = FRR_ZAPI5_REDISTRIBUTE_DELETE
  1231  		} else if c.Version >= 6 {
  1232  			command = FRR_ZAPI6_REDISTRIBUTE_DELETE
  1233  		}
  1234  		body := &RedistributeBody{
  1235  			Redist: t,
  1236  		}
  1237  		return c.SendCommand(command, VRF_DEFAULT, body)
  1238  	} else {
  1239  		return fmt.Errorf("unknown route type: %d", t)
  1240  	}
  1241  }
  1242  
  1243  func (c *Client) SendIPRoute(vrfId uint32, body *IPRouteBody, isWithdraw bool) error {
  1244  	command := IPV4_ROUTE_ADD
  1245  	if c.Version <= 3 {
  1246  		if body.Prefix.Prefix.To4() != nil {
  1247  			if isWithdraw {
  1248  				command = IPV4_ROUTE_DELETE
  1249  			}
  1250  		} else {
  1251  			if isWithdraw {
  1252  				command = IPV6_ROUTE_DELETE
  1253  			} else {
  1254  				command = IPV6_ROUTE_ADD
  1255  			}
  1256  		}
  1257  	} else if c.Version == 4 { // version >= 4
  1258  		if body.Prefix.Prefix.To4() != nil {
  1259  			if isWithdraw {
  1260  				command = FRR_IPV4_ROUTE_DELETE
  1261  			} else {
  1262  				command = FRR_IPV4_ROUTE_ADD
  1263  			}
  1264  		} else {
  1265  			if isWithdraw {
  1266  				command = FRR_IPV6_ROUTE_DELETE
  1267  			} else {
  1268  				command = FRR_IPV6_ROUTE_ADD
  1269  			}
  1270  		}
  1271  	} else { // version >= 5 (version 6 uses the same value as version 5)
  1272  		if isWithdraw {
  1273  			command = FRR_ZAPI5_ROUTE_DELETE
  1274  		} else {
  1275  			command = FRR_ZAPI5_ROUTE_ADD
  1276  		}
  1277  	}
  1278  	return c.SendCommand(command, vrfId, body)
  1279  }
  1280  
  1281  func (c *Client) SendNexthopRegister(vrfId uint32, body *NexthopRegisterBody, isWithdraw bool) error {
  1282  	// Note: NEXTHOP_REGISTER and NEXTHOP_UNREGISTER messages are not
  1283  	// supported in Zebra protocol version<3.
  1284  	if c.Version < 3 {
  1285  		return fmt.Errorf("NEXTHOP_REGISTER/NEXTHOP_UNREGISTER are not supported in version: %d", c.Version)
  1286  	}
  1287  	command := NEXTHOP_REGISTER
  1288  	if c.Version == 3 {
  1289  		if isWithdraw {
  1290  			command = NEXTHOP_UNREGISTER
  1291  		}
  1292  	} else if c.Version == 4 { // version == 4
  1293  		if isWithdraw {
  1294  			command = FRR_NEXTHOP_UNREGISTER
  1295  		} else {
  1296  			command = FRR_NEXTHOP_REGISTER
  1297  		}
  1298  	} else if c.Version == 5 { // version == 5
  1299  		if isWithdraw {
  1300  			command = FRR_ZAPI5_NEXTHOP_UNREGISTER
  1301  		} else {
  1302  			command = FRR_ZAPI5_NEXTHOP_REGISTER
  1303  		}
  1304  	} else { // version >= 6
  1305  		if isWithdraw {
  1306  			command = FRR_ZAPI6_NEXTHOP_UNREGISTER
  1307  		} else {
  1308  			command = FRR_ZAPI6_NEXTHOP_REGISTER
  1309  		}
  1310  	}
  1311  	return c.SendCommand(command, vrfId, body)
  1312  }
  1313  
  1314  // for avoiding double close
  1315  func ChannelClose(ch chan *Message) bool {
  1316  	select {
  1317  	case _, ok := <-ch:
  1318  		if ok {
  1319  			close(ch)
  1320  			return true
  1321  		}
  1322  	default:
  1323  	}
  1324  	return false
  1325  }
  1326  
  1327  func (c *Client) Close() error {
  1328  	ChannelClose(c.outgoing)
  1329  	return c.conn.Close()
  1330  }
  1331  
  1332  type Header struct {
  1333  	Len     uint16
  1334  	Marker  uint8
  1335  	Version uint8
  1336  	VrfId   uint32 // ZAPI v4: 16bits, v5: 32bits
  1337  	Command API_TYPE
  1338  }
  1339  
  1340  func (h *Header) Serialize() ([]byte, error) {
  1341  	buf := make([]byte, HeaderSize(h.Version))
  1342  	binary.BigEndian.PutUint16(buf[0:2], h.Len)
  1343  	buf[2] = h.Marker
  1344  	buf[3] = h.Version
  1345  	switch h.Version {
  1346  	case 2:
  1347  		binary.BigEndian.PutUint16(buf[4:6], uint16(h.Command))
  1348  	case 3, 4:
  1349  		binary.BigEndian.PutUint16(buf[4:6], uint16(h.VrfId))
  1350  		binary.BigEndian.PutUint16(buf[6:8], uint16(h.Command))
  1351  	case 5, 6:
  1352  		binary.BigEndian.PutUint32(buf[4:8], uint32(h.VrfId))
  1353  		binary.BigEndian.PutUint16(buf[8:10], uint16(h.Command))
  1354  	default:
  1355  		return nil, fmt.Errorf("Unsupported ZAPI version: %d", h.Version)
  1356  	}
  1357  	return buf, nil
  1358  }
  1359  
  1360  func (h *Header) DecodeFromBytes(data []byte) error {
  1361  	if uint16(len(data)) < 4 {
  1362  		return fmt.Errorf("Not all ZAPI message header")
  1363  	}
  1364  	h.Len = binary.BigEndian.Uint16(data[0:2])
  1365  	h.Marker = data[2]
  1366  	h.Version = data[3]
  1367  	if uint16(len(data)) < HeaderSize(h.Version) {
  1368  		return fmt.Errorf("Not all ZAPI message header")
  1369  	}
  1370  	switch h.Version {
  1371  	case 2:
  1372  		h.Command = API_TYPE(binary.BigEndian.Uint16(data[4:6]))
  1373  	case 3, 4:
  1374  		h.VrfId = uint32(binary.BigEndian.Uint16(data[4:6]))
  1375  		h.Command = API_TYPE(binary.BigEndian.Uint16(data[6:8]))
  1376  	case 5, 6:
  1377  		h.VrfId = binary.BigEndian.Uint32(data[4:8])
  1378  		h.Command = API_TYPE(binary.BigEndian.Uint16(data[8:10]))
  1379  	default:
  1380  		return fmt.Errorf("Unsupported ZAPI version: %d", h.Version)
  1381  	}
  1382  	return nil
  1383  }
  1384  
  1385  type Body interface {
  1386  	DecodeFromBytes([]byte, uint8) error
  1387  	Serialize(uint8) ([]byte, error)
  1388  	String() string
  1389  }
  1390  
  1391  type UnknownBody struct {
  1392  	Data []byte
  1393  }
  1394  
  1395  func (b *UnknownBody) DecodeFromBytes(data []byte, version uint8) error {
  1396  	b.Data = data
  1397  	return nil
  1398  }
  1399  
  1400  func (b *UnknownBody) Serialize(version uint8) ([]byte, error) {
  1401  	return b.Data, nil
  1402  }
  1403  
  1404  func (b *UnknownBody) String() string {
  1405  	return fmt.Sprintf("data: %v", b.Data)
  1406  }
  1407  
  1408  type HelloBody struct {
  1409  	RedistDefault ROUTE_TYPE
  1410  	Instance      uint16
  1411  	ReceiveNotify uint8
  1412  }
  1413  
  1414  // Reference: zread_hello function in zebra/zserv.c of Quagga1.2.x (ZAPI3)
  1415  // Reference: zread_hello function in zebra/zserv.c of FRR3.x (ZAPI4)
  1416  // Reference: zread_hello function in zebra/zapi_msg.c of FRR5.x (ZAPI5)
  1417  func (b *HelloBody) DecodeFromBytes(data []byte, version uint8) error {
  1418  	b.RedistDefault = ROUTE_TYPE(data[0])
  1419  	if version >= 4 {
  1420  		b.Instance = binary.BigEndian.Uint16(data[1:3])
  1421  		if version >= 5 {
  1422  			b.ReceiveNotify = data[3]
  1423  		}
  1424  	}
  1425  	return nil
  1426  }
  1427  
  1428  // Reference: zebra_hello_send function in lib/zclient.c of Quagga1.2.x (ZAPI3)
  1429  // Reference: zebra_hello_send function in lib/zclient.c of FRR3.x (ZAPI4)
  1430  // Reference: zebra_hello_send function in lib/zclient.c of FRR5.x (ZAPI5)
  1431  func (b *HelloBody) Serialize(version uint8) ([]byte, error) {
  1432  	if version <= 3 {
  1433  		return []byte{uint8(b.RedistDefault)}, nil
  1434  	} else { // version >= 4
  1435  		var buf []byte
  1436  		if version == 4 {
  1437  			buf = make([]byte, 3)
  1438  		} else if version >= 5 {
  1439  			buf = make([]byte, 4)
  1440  		}
  1441  		buf[0] = uint8(b.RedistDefault)
  1442  		binary.BigEndian.PutUint16(buf[1:3], b.Instance)
  1443  		if version >= 5 {
  1444  			buf[3] = b.ReceiveNotify
  1445  		}
  1446  		return buf, nil
  1447  	}
  1448  }
  1449  
  1450  func (b *HelloBody) String() string {
  1451  	return fmt.Sprintf(
  1452  		"route_type: %s, instance :%d",
  1453  		b.RedistDefault.String(), b.Instance)
  1454  }
  1455  
  1456  type RedistributeBody struct {
  1457  	Afi      AFI
  1458  	Redist   ROUTE_TYPE
  1459  	Instance uint16
  1460  }
  1461  
  1462  //  Reference: zebra_redistribute_add function in zebra/redistribute.c of Quagga1.2.x (ZAPI3)
  1463  //  Reference: zebra_redistribute_add function in zebra/redistribute.c of FRR3.x (ZAPI4)
  1464  //  Reference: zebra_redistribute_add function in zebra/redistribute.c of FRR5.x (ZAPI5)
  1465  func (b *RedistributeBody) DecodeFromBytes(data []byte, version uint8) error {
  1466  	if version <= 3 {
  1467  		b.Redist = ROUTE_TYPE(data[0])
  1468  	} else { // version >= 4
  1469  		b.Afi = AFI(data[0])
  1470  		b.Redist = ROUTE_TYPE(data[1])
  1471  		b.Instance = binary.BigEndian.Uint16(data[2:4])
  1472  	}
  1473  	return nil
  1474  }
  1475  
  1476  //  Reference: zebra_redistribute_send function in lib/zclient.c of Quagga1.2.x (ZAPI3)
  1477  //  Reference: zebra_redistribute_send function in lib/zclient.c of FRR3.x (ZAPI4)
  1478  //  Reference: zebra_redistribute_send function in lib/zclient.c of FRR5.x (ZAPI5)
  1479  func (b *RedistributeBody) Serialize(version uint8) ([]byte, error) {
  1480  	if version <= 3 {
  1481  		return []byte{uint8(b.Redist)}, nil
  1482  	} else { // version >= 4
  1483  		buf := make([]byte, 4)
  1484  		buf[0] = uint8(b.Afi)
  1485  		buf[1] = uint8(b.Redist)
  1486  		binary.BigEndian.PutUint16(buf[2:4], b.Instance)
  1487  		return buf, nil
  1488  	}
  1489  }
  1490  
  1491  func (b *RedistributeBody) String() string {
  1492  	return fmt.Sprintf(
  1493  		"afi: %s, route_type: %s, instance :%d",
  1494  		b.Afi.String(), b.Redist.String(), b.Instance)
  1495  }
  1496  
  1497  type LinkParam struct {
  1498  	Status      uint32
  1499  	TeMetric    uint32
  1500  	MaxBw       float32
  1501  	MaxRsvBw    float32
  1502  	UnrsvBw     [8]float32
  1503  	BwClassNum  uint32
  1504  	AdminGroup  uint32
  1505  	RemoteAS    uint32
  1506  	RemoteIP    net.IP
  1507  	AveDelay    uint32
  1508  	MinDelay    uint32
  1509  	MaxDelay    uint32
  1510  	DelayVar    uint32
  1511  	PktLoss     float32
  1512  	ResidualBw  float32
  1513  	AvailableBw float32
  1514  	UseBw       float32
  1515  }
  1516  
  1517  type InterfaceUpdateBody struct {
  1518  	Name         string
  1519  	Index        uint32
  1520  	Status       INTERFACE_STATUS
  1521  	Flags        uint64
  1522  	PTMEnable    PTM_ENABLE
  1523  	PTMStatus    PTM_STATUS
  1524  	Metric       uint32
  1525  	Speed        uint32
  1526  	MTU          uint32
  1527  	MTU6         uint32
  1528  	Bandwidth    uint32
  1529  	Linktype     LINK_TYPE
  1530  	HardwareAddr net.HardwareAddr
  1531  	LinkParam    LinkParam
  1532  }
  1533  
  1534  //  Reference: zebra_interface_if_set_value function in lib/zclient.c of Quagga1.2.x (ZAPI4)
  1535  //  Reference: zebra_interface_if_set_value function in lib/zclient.c of FRR3.x (ZAPI4)
  1536  //  Reference: zebra_interface_if_set_value function in lib/zclient.c of FRR5.x (ZAPI5)
  1537  func (b *InterfaceUpdateBody) DecodeFromBytes(data []byte, version uint8) error {
  1538  	if len(data) < INTERFACE_NAMSIZ+29 {
  1539  		return fmt.Errorf("lack of bytes. need %d but %d", INTERFACE_NAMSIZ+29, len(data))
  1540  	}
  1541  
  1542  	b.Name = strings.Trim(string(data[:INTERFACE_NAMSIZ]), "\u0000")
  1543  	data = data[INTERFACE_NAMSIZ:]
  1544  	b.Index = binary.BigEndian.Uint32(data[0:4])
  1545  	b.Status = INTERFACE_STATUS(data[4])
  1546  	b.Flags = binary.BigEndian.Uint64(data[5:13])
  1547  	if version >= 4 {
  1548  		b.PTMEnable = PTM_ENABLE(data[13])
  1549  		b.PTMStatus = PTM_STATUS(data[14])
  1550  		b.Metric = binary.BigEndian.Uint32(data[15:19])
  1551  		b.Speed = binary.BigEndian.Uint32(data[19:23])
  1552  		data = data[23:]
  1553  	} else {
  1554  		b.Metric = binary.BigEndian.Uint32(data[13:17])
  1555  		data = data[17:]
  1556  	}
  1557  	b.MTU = binary.BigEndian.Uint32(data[0:4])
  1558  	b.MTU6 = binary.BigEndian.Uint32(data[4:8])
  1559  	b.Bandwidth = binary.BigEndian.Uint32(data[8:12])
  1560  	if version >= 3 {
  1561  		b.Linktype = LINK_TYPE(binary.BigEndian.Uint32(data[12:16]))
  1562  		data = data[16:]
  1563  	} else {
  1564  		data = data[12:]
  1565  	}
  1566  	l := binary.BigEndian.Uint32(data[:4])
  1567  	if l > 0 {
  1568  		if len(data) < 4+int(l) {
  1569  			return fmt.Errorf("lack of bytes. need %d but %d", 4+l, len(data))
  1570  		}
  1571  		b.HardwareAddr = data[4 : 4+l]
  1572  	}
  1573  	if version >= 5 {
  1574  		LinkParam := data[4+l]
  1575  		if LinkParam > 0 {
  1576  			data = data[5+l:]
  1577  			b.LinkParam.Status = binary.BigEndian.Uint32(data[0:4])
  1578  			b.LinkParam.TeMetric = binary.BigEndian.Uint32(data[4:8])
  1579  			b.LinkParam.MaxBw = math.Float32frombits(binary.BigEndian.Uint32(data[8:12]))
  1580  			b.LinkParam.MaxRsvBw = math.Float32frombits(binary.BigEndian.Uint32(data[12:16]))
  1581  			b.LinkParam.BwClassNum = binary.BigEndian.Uint32(data[16:20])
  1582  			for i := uint32(0); i < b.LinkParam.BwClassNum; i++ {
  1583  				b.LinkParam.UnrsvBw[i] = math.Float32frombits(binary.BigEndian.Uint32(data[20+i*4 : 24+i*4]))
  1584  			}
  1585  			data = data[20+b.LinkParam.BwClassNum*4:]
  1586  			b.LinkParam.AdminGroup = binary.BigEndian.Uint32(data[0:4])
  1587  			b.LinkParam.RemoteAS = binary.BigEndian.Uint32(data[4:8])
  1588  			b.LinkParam.RemoteIP = data[8:12]
  1589  			b.LinkParam.AveDelay = binary.BigEndian.Uint32(data[12:16])
  1590  			b.LinkParam.MinDelay = binary.BigEndian.Uint32(data[16:20])
  1591  			b.LinkParam.MaxDelay = binary.BigEndian.Uint32(data[20:24])
  1592  			b.LinkParam.DelayVar = binary.BigEndian.Uint32(data[24:28])
  1593  			b.LinkParam.PktLoss = math.Float32frombits(binary.BigEndian.Uint32(data[28:32]))
  1594  			b.LinkParam.ResidualBw = math.Float32frombits(binary.BigEndian.Uint32(data[32:36]))
  1595  			b.LinkParam.AvailableBw = math.Float32frombits(binary.BigEndian.Uint32(data[36:40]))
  1596  			b.LinkParam.UseBw = math.Float32frombits(binary.BigEndian.Uint32(data[40:44]))
  1597  		}
  1598  	}
  1599  	return nil
  1600  }
  1601  
  1602  func (b *InterfaceUpdateBody) Serialize(version uint8) ([]byte, error) {
  1603  	return []byte{}, nil
  1604  }
  1605  
  1606  func (b *InterfaceUpdateBody) String() string {
  1607  	s := fmt.Sprintf(
  1608  		"name: %s, idx: %d, status: %s, flags: %s, ptm_enable: %s, ptm_status: %s, metric: %d, speed: %d, mtu: %d, mtu6: %d, bandwidth: %d, linktype: %s",
  1609  		b.Name, b.Index, b.Status.String(), intfflag2string(b.Flags), b.PTMEnable.String(), b.PTMStatus.String(), b.Metric, b.Speed, b.MTU, b.MTU6, b.Bandwidth, b.Linktype.String())
  1610  	if len(b.HardwareAddr) > 0 {
  1611  		return s + fmt.Sprintf(", mac: %s", b.HardwareAddr.String())
  1612  	}
  1613  	return s
  1614  }
  1615  
  1616  type InterfaceAddressUpdateBody struct {
  1617  	Index       uint32
  1618  	Flags       INTERFACE_ADDRESS_FLAG
  1619  	Prefix      net.IP
  1620  	Length      uint8
  1621  	Destination net.IP
  1622  }
  1623  
  1624  //  Reference: zebra_interface_address_read function in lib/zclient.c of Quagga1.2.x (ZAPI4)
  1625  //  Reference: zebra_interface_address_read function in lib/zclient.c of FRR3.x (ZAPI4)
  1626  //  Reference: zebra_interface_address_read function in lib/zclient.c of FRR5.x (ZAPI5)
  1627  func (b *InterfaceAddressUpdateBody) DecodeFromBytes(data []byte, version uint8) error {
  1628  	b.Index = binary.BigEndian.Uint32(data[:4])
  1629  	b.Flags = INTERFACE_ADDRESS_FLAG(data[4])
  1630  	family := data[5]
  1631  	addrlen, err := addressByteLength(family)
  1632  	if err != nil {
  1633  		return err
  1634  	}
  1635  	b.Prefix = data[6 : 6+addrlen]
  1636  	b.Length = data[6+addrlen]
  1637  	b.Destination = data[7+addrlen : 7+addrlen*2]
  1638  	return nil
  1639  }
  1640  
  1641  func (b *InterfaceAddressUpdateBody) Serialize(version uint8) ([]byte, error) {
  1642  	return []byte{}, nil
  1643  }
  1644  
  1645  func (b *InterfaceAddressUpdateBody) String() string {
  1646  	return fmt.Sprintf(
  1647  		"idx: %d, flags: %s, addr: %s/%d",
  1648  		b.Index, b.Flags.String(), b.Prefix.String(), b.Length)
  1649  }
  1650  
  1651  type RouterIDUpdateBody struct {
  1652  	Length uint8
  1653  	Prefix net.IP
  1654  }
  1655  
  1656  //  Reference: zebra_router_id_update_read function in lib/zclient.c of Quagga1.2.x (ZAPI4)
  1657  //  Reference: zebra_router_id_update_read function in lib/zclient.c of FRR3.x (ZAPI4)
  1658  //  Reference: zebra_router_id_update_read function in lib/zclient.c of FRR5.x (ZAPI5)
  1659  func (b *RouterIDUpdateBody) DecodeFromBytes(data []byte, version uint8) error {
  1660  	family := data[0]
  1661  
  1662  	addrlen, err := addressByteLength(family)
  1663  	if err != nil {
  1664  		return err
  1665  	}
  1666  	b.Prefix = data[1 : 1+addrlen]
  1667  	b.Length = data[1+addrlen]
  1668  	return nil
  1669  }
  1670  
  1671  func (b *RouterIDUpdateBody) Serialize(version uint8) ([]byte, error) {
  1672  	return []byte{}, nil
  1673  }
  1674  
  1675  func (b *RouterIDUpdateBody) String() string {
  1676  	return fmt.Sprintf("id: %s/%d", b.Prefix.String(), b.Length)
  1677  }
  1678  
  1679  /*
  1680   Reference: struct zapi_nexthop in lib/zclient.h of FRR5.x (ZAPI5)
  1681  */
  1682  type Nexthop struct {
  1683  	Type          NEXTHOP_TYPE
  1684  	VrfId         uint32
  1685  	Ifindex       uint32
  1686  	Gate          net.IP
  1687  	BlackholeType uint8
  1688  	LabelNum      uint8
  1689  	MplsLabels    []uint32
  1690  }
  1691  
  1692  func (n *Nexthop) String() string {
  1693  	s := fmt.Sprintf(
  1694  		"type: %s, gate: %s, ifindex: %d",
  1695  		n.Type.String(), n.Gate.String(), n.Ifindex)
  1696  	return s
  1697  }
  1698  
  1699  type Prefix struct {
  1700  	Family    uint8
  1701  	PrefixLen uint8
  1702  	Prefix    net.IP
  1703  }
  1704  
  1705  type IPRouteBody struct {
  1706  	Type      ROUTE_TYPE
  1707  	Instance  uint16
  1708  	Flags     FLAG
  1709  	Message   MESSAGE_FLAG
  1710  	SAFI      SAFI
  1711  	Prefix    Prefix
  1712  	SrcPrefix Prefix
  1713  	Nexthops  []Nexthop
  1714  	Distance  uint8
  1715  	Metric    uint32
  1716  	Mtu       uint32
  1717  	Tag       uint32
  1718  	Rmac      [6]byte
  1719  	Api       API_TYPE
  1720  }
  1721  
  1722  func (b *IPRouteBody) RouteFamily(version uint8) bgp.RouteFamily {
  1723  	if b == nil {
  1724  		return bgp.RF_OPAQUE
  1725  	}
  1726  	family := addressFamilyFromApi(b.Api, version)
  1727  	if family == syscall.AF_UNSPEC {
  1728  		if b.Prefix.Prefix.To4() != nil {
  1729  			family = syscall.AF_INET
  1730  		} else if b.Prefix.Prefix.To16() != nil {
  1731  			family = syscall.AF_INET6
  1732  		}
  1733  	}
  1734  	switch family {
  1735  	case syscall.AF_INET:
  1736  		return bgp.RF_IPv4_UC
  1737  	case syscall.AF_INET6:
  1738  		return bgp.RF_IPv6_UC
  1739  	}
  1740  	return bgp.RF_OPAQUE
  1741  }
  1742  
  1743  func (b *IPRouteBody) IsWithdraw(version uint8) bool {
  1744  	if version <= 3 {
  1745  		switch b.Api {
  1746  		case IPV4_ROUTE_DELETE, IPV6_ROUTE_DELETE:
  1747  			return true
  1748  		}
  1749  	} else if version == 4 {
  1750  		switch b.Api {
  1751  		case FRR_IPV4_ROUTE_DELETE, FRR_IPV6_ROUTE_DELETE, FRR_REDISTRIBUTE_IPV4_DEL, FRR_REDISTRIBUTE_IPV6_DEL:
  1752  			return true
  1753  		}
  1754  	} else if version == 5 {
  1755  		switch b.Api {
  1756  		case FRR_ZAPI5_ROUTE_DELETE, FRR_ZAPI5_IPV4_ROUTE_DELETE, FRR_ZAPI5_IPV6_ROUTE_DELETE, FRR_ZAPI5_REDISTRIBUTE_ROUTE_DEL:
  1757  			return true
  1758  		}
  1759  	} else if version >= 6 {
  1760  		switch b.Api {
  1761  		case FRR_ZAPI6_ROUTE_DELETE, FRR_ZAPI6_REDISTRIBUTE_ROUTE_DEL:
  1762  			return true
  1763  		}
  1764  	}
  1765  	return false
  1766  }
  1767  
  1768  // Reference: zapi_ipv4_route function in lib/zclient.c  of Quagga1.2.x (ZAPI3)
  1769  // Reference: zapi_ipv4_route function in lib/zclient.c  of FRR3.x (ZAPI4)
  1770  // Reference: zapi_route_encode function in lib/zclient.c of FRR5.x (ZAPI5)
  1771  func (b *IPRouteBody) Serialize(version uint8) ([]byte, error) {
  1772  	var buf []byte
  1773  	if version <= 3 {
  1774  		buf = make([]byte, 5)
  1775  	} else if version == 4 {
  1776  		buf = make([]byte, 10)
  1777  	} else { // version >= 5
  1778  		buf = make([]byte, 9)
  1779  	}
  1780  	buf[0] = uint8(b.Type)
  1781  	if version <= 3 {
  1782  		buf[1] = uint8(b.Flags)
  1783  		buf[2] = uint8(b.Message)
  1784  		binary.BigEndian.PutUint16(buf[3:5], uint16(b.SAFI))
  1785  	} else { // version >= 4
  1786  		binary.BigEndian.PutUint16(buf[1:3], uint16(b.Instance))
  1787  		binary.BigEndian.PutUint32(buf[3:7], uint32(b.Flags))
  1788  		buf[7] = uint8(b.Message)
  1789  		if version == 4 {
  1790  			binary.BigEndian.PutUint16(buf[8:10], uint16(b.SAFI))
  1791  		} else { // version >= 5
  1792  			buf[8] = uint8(b.SAFI)
  1793  			if b.Flags&FLAG_EVPN_ROUTE > 0 {
  1794  				// size of struct ethaddr is 6 octets defined by ETH_ALEN
  1795  				buf = append(buf, b.Rmac[:6]...)
  1796  			}
  1797  			if b.Prefix.Family == syscall.AF_UNSPEC {
  1798  				if b.Prefix.Prefix.To4() != nil {
  1799  					b.Prefix.Family = syscall.AF_INET
  1800  				} else if b.Prefix.Prefix.To16() != nil {
  1801  					b.Prefix.Family = syscall.AF_INET6
  1802  				}
  1803  			}
  1804  			buf = append(buf, b.Prefix.Family)
  1805  		}
  1806  	}
  1807  	byteLen := (int(b.Prefix.PrefixLen) + 7) / 8
  1808  	buf = append(buf, b.Prefix.PrefixLen)
  1809  	buf = append(buf, b.Prefix.Prefix[:byteLen]...)
  1810  
  1811  	if (version == 4 && b.Message&FRR_MESSAGE_SRCPFX > 0) ||
  1812  		(version >= 5 && b.Message&FRR_ZAPI5_MESSAGE_SRCPFX > 0) {
  1813  		byteLen = (int(b.SrcPrefix.PrefixLen) + 7) / 8
  1814  		buf = append(buf, b.SrcPrefix.PrefixLen)
  1815  		buf = append(buf, b.SrcPrefix.Prefix[:byteLen]...)
  1816  	}
  1817  	if (version <= 3 && b.Message&MESSAGE_NEXTHOP > 0) ||
  1818  		(version == 4 && b.Message&FRR_MESSAGE_NEXTHOP > 0) ||
  1819  		(version >= 5 && b.Message&FRR_ZAPI5_MESSAGE_NEXTHOP > 0) {
  1820  		if version < 5 {
  1821  			if b.Flags&FLAG_BLACKHOLE > 0 {
  1822  				buf = append(buf, []byte{1, uint8(NEXTHOP_TYPE_BLACKHOLE)}...)
  1823  			} else {
  1824  				buf = append(buf, uint8(len(b.Nexthops)))
  1825  			}
  1826  		} else { // version >= 5
  1827  			bbuf := make([]byte, 2)
  1828  			binary.BigEndian.PutUint16(bbuf, uint16(len(b.Nexthops)))
  1829  			buf = append(buf, bbuf...)
  1830  		}
  1831  		for _, nexthop := range b.Nexthops {
  1832  			if version >= 5 {
  1833  				bbuf := make([]byte, 4)
  1834  				binary.BigEndian.PutUint32(bbuf, nexthop.VrfId)
  1835  				buf = append(buf, bbuf...)
  1836  			}
  1837  
  1838  			if nexthop.Type == NEXTHOP_TYPE(0) {
  1839  				if nexthop.Gate.To4() != nil {
  1840  					if version <= 3 {
  1841  						nexthop.Type = NEXTHOP_TYPE_IPV4
  1842  					} else {
  1843  						nexthop.Type = FRR_NEXTHOP_TYPE_IPV4
  1844  					}
  1845  					if version >= 5 && nexthop.Ifindex > 0 {
  1846  						nexthop.Type = FRR_NEXTHOP_TYPE_IPV4_IFINDEX
  1847  					}
  1848  				} else if nexthop.Gate.To16() != nil {
  1849  					if version <= 3 {
  1850  						nexthop.Type = NEXTHOP_TYPE_IPV6
  1851  					} else {
  1852  						nexthop.Type = FRR_NEXTHOP_TYPE_IPV6
  1853  					}
  1854  					if version >= 5 && nexthop.Ifindex > 0 {
  1855  						nexthop.Type = FRR_NEXTHOP_TYPE_IPV6_IFINDEX
  1856  					}
  1857  				} else if nexthop.Ifindex > 0 {
  1858  					if version <= 3 {
  1859  						nexthop.Type = NEXTHOP_TYPE_IFINDEX
  1860  					} else {
  1861  						nexthop.Type = FRR_NEXTHOP_TYPE_IFINDEX
  1862  					}
  1863  				} else if version >= 5 {
  1864  					nexthop.Type = FRR_NEXTHOP_TYPE_BLACKHOLE
  1865  				}
  1866  			}
  1867  
  1868  			buf = append(buf, uint8(nexthop.Type))
  1869  
  1870  			if (version <= 3 && nexthop.Type == NEXTHOP_TYPE_IPV4) ||
  1871  				(version >= 4 && nexthop.Type == FRR_NEXTHOP_TYPE_IPV4) {
  1872  				buf = append(buf, nexthop.Gate.To4()...)
  1873  			} else if (version <= 3 && nexthop.Type == NEXTHOP_TYPE_IPV6) ||
  1874  				(version >= 4 && nexthop.Type == FRR_NEXTHOP_TYPE_IPV6) {
  1875  				buf = append(buf, nexthop.Gate.To16()...)
  1876  			} else if (version <= 3 && nexthop.Type == NEXTHOP_TYPE_IFINDEX) ||
  1877  				(version >= 4 && nexthop.Type == FRR_NEXTHOP_TYPE_IFINDEX) {
  1878  				bbuf := make([]byte, 4)
  1879  				binary.BigEndian.PutUint32(bbuf, nexthop.Ifindex)
  1880  				buf = append(buf, bbuf...)
  1881  			} else if version >= 5 && nexthop.Type == FRR_NEXTHOP_TYPE_IPV4_IFINDEX {
  1882  				buf = append(buf, nexthop.Gate.To4()...)
  1883  				bbuf := make([]byte, 4)
  1884  				binary.BigEndian.PutUint32(bbuf, nexthop.Ifindex)
  1885  				buf = append(buf, bbuf...)
  1886  			} else if version >= 5 && nexthop.Type == FRR_NEXTHOP_TYPE_IPV6_IFINDEX {
  1887  				buf = append(buf, nexthop.Gate.To16()...)
  1888  				bbuf := make([]byte, 4)
  1889  				binary.BigEndian.PutUint32(bbuf, nexthop.Ifindex)
  1890  				buf = append(buf, bbuf...)
  1891  			} else if version >= 5 && nexthop.Type == FRR_NEXTHOP_TYPE_BLACKHOLE {
  1892  				buf = append(buf, uint8(nexthop.BlackholeType))
  1893  			}
  1894  			if version >= 5 && b.Message&FRR_ZAPI5_MESSAGE_LABEL > 0 {
  1895  				buf = append(buf, nexthop.LabelNum)
  1896  				bbuf := make([]byte, 4)
  1897  				binary.BigEndian.PutUint32(bbuf, nexthop.MplsLabels[0])
  1898  				buf = append(buf, bbuf...)
  1899  			}
  1900  		}
  1901  		if (version <= 3 && b.Message&MESSAGE_DISTANCE > 0) ||
  1902  			(version == 4 && b.Message&FRR_MESSAGE_DISTANCE > 0) ||
  1903  			(version >= 5 && b.Message&FRR_ZAPI5_MESSAGE_DISTANCE > 0) {
  1904  			buf = append(buf, b.Distance)
  1905  		}
  1906  		if (version <= 3 && b.Message&MESSAGE_METRIC > 0) ||
  1907  			(version == 4 && b.Message&FRR_MESSAGE_METRIC > 0) ||
  1908  			(version >= 5 && b.Message&FRR_ZAPI5_MESSAGE_METRIC > 0) {
  1909  			bbuf := make([]byte, 4)
  1910  			binary.BigEndian.PutUint32(bbuf, b.Metric)
  1911  			buf = append(buf, bbuf...)
  1912  		}
  1913  		if (version <= 3 && b.Message&MESSAGE_MTU > 0) ||
  1914  			(version == 4 && b.Message&FRR_MESSAGE_MTU > 0) ||
  1915  			(version >= 5 && b.Message&FRR_ZAPI5_MESSAGE_MTU > 0) {
  1916  			bbuf := make([]byte, 4)
  1917  			binary.BigEndian.PutUint32(bbuf, b.Mtu)
  1918  			buf = append(buf, bbuf...)
  1919  		}
  1920  		if (version <= 3 && b.Message&MESSAGE_TAG > 0) ||
  1921  			(version == 4 && b.Message&FRR_MESSAGE_TAG > 0) ||
  1922  			(version >= 5 && b.Message&FRR_ZAPI5_MESSAGE_TAG > 0) {
  1923  			bbuf := make([]byte, 4)
  1924  			binary.BigEndian.PutUint32(bbuf, b.Tag)
  1925  			buf = append(buf, bbuf...)
  1926  		}
  1927  	}
  1928  	return buf, nil
  1929  }
  1930  
  1931  // Reference: zebra_read_ipv4 function in bgpd/bgp_zebra.c of Quagga1.2.x (ZAPI3)
  1932  // Reference: zebra_read_ipv4 function in bgpd/bgp_zebra.c of FRR4.x (ZAPI4)
  1933  // Reference: zapi_route_decode function in lib/zclient.c of FRR5.x (ZAPI5)
  1934  func (b *IPRouteBody) DecodeFromBytes(data []byte, version uint8) error {
  1935  	if b == nil {
  1936  		return fmt.Errorf("[IPRouteBody DecodeFromBytes] IPRouteBody is nil")
  1937  	}
  1938  	b.Prefix.Family = addressFamilyFromApi(b.Api, version)
  1939  	/* REDSTRIBUTE_IPV4_ADD|DEL and REDSITRBUTE_IPV6_ADD|DEL have merged to
  1940  	   REDISTRIBUTE_ROUTE_ADD|DEL in ZAPI version 5.
  1941  	   Therefore it can not judge the protocol famiiy from API. */
  1942  
  1943  	b.Type = ROUTE_TYPE(data[0])
  1944  	if version <= 3 {
  1945  		b.Flags = FLAG(data[1])
  1946  		data = data[2:]
  1947  	} else { // version >= 4
  1948  		b.Instance = binary.BigEndian.Uint16(data[1:3])
  1949  		b.Flags = FLAG(binary.BigEndian.Uint32(data[3:7]))
  1950  		data = data[7:]
  1951  	}
  1952  
  1953  	b.Message = MESSAGE_FLAG(data[0])
  1954  	b.SAFI = SAFI(SAFI_UNICAST)
  1955  	if version >= 5 {
  1956  		b.SAFI = SAFI(data[1])
  1957  		data = data[2:]
  1958  		if b.Flags&FLAG_EVPN_ROUTE > 0 {
  1959  			// size of struct ethaddr is 6 octets defined by ETH_ALEN
  1960  			copy(b.Rmac[0:6], data[0:6])
  1961  			data = data[6:]
  1962  		}
  1963  		b.Prefix.Family = data[0]
  1964  	}
  1965  
  1966  	addrByteLen, err := addressByteLength(b.Prefix.Family)
  1967  	if err != nil {
  1968  		return err
  1969  	}
  1970  
  1971  	addrBitLen := uint8(addrByteLen * 8)
  1972  
  1973  	b.Prefix.PrefixLen = data[1]
  1974  	if b.Prefix.PrefixLen > addrBitLen {
  1975  		return fmt.Errorf("prefix length is greater than %d", addrByteLen*8)
  1976  	}
  1977  	pos := 2
  1978  	rest := len(data[pos:]) + 2
  1979  
  1980  	buf := make([]byte, addrByteLen)
  1981  	byteLen := int((b.Prefix.PrefixLen + 7) / 8)
  1982  	if pos+byteLen > rest {
  1983  		return fmt.Errorf("message length invalid pos:%d rest:%d", pos, rest)
  1984  	}
  1985  	copy(buf, data[pos:pos+byteLen])
  1986  	b.Prefix.Prefix = ipFromFamily(b.Prefix.Family, buf)
  1987  	pos += byteLen
  1988  
  1989  	if (version == 4 && b.Message&FRR_MESSAGE_SRCPFX > 0) ||
  1990  		(version >= 5 && b.Message&FRR_ZAPI5_MESSAGE_SRCPFX > 0) {
  1991  		if pos+1 > rest {
  1992  			return fmt.Errorf("MESSAGE_SRCPFX message length invalid pos:%d rest:%d", pos, rest)
  1993  		}
  1994  		b.SrcPrefix.PrefixLen = data[pos]
  1995  		if b.SrcPrefix.PrefixLen > addrBitLen {
  1996  			return fmt.Errorf("prefix length is greater than %d", addrByteLen*8)
  1997  		}
  1998  		pos += 1
  1999  		buf = make([]byte, addrByteLen)
  2000  		byteLen = int((b.SrcPrefix.PrefixLen + 7) / 8)
  2001  		copy(buf, data[pos:pos+byteLen])
  2002  		if pos+byteLen > rest {
  2003  			return fmt.Errorf("MESSAGE_SRCPFX message length invalid pos:%d rest:%d", pos, rest)
  2004  		}
  2005  		b.SrcPrefix.Prefix = ipFromFamily(b.Prefix.Family, buf)
  2006  		pos += byteLen
  2007  	}
  2008  
  2009  	b.Nexthops = []Nexthop{}
  2010  	if (version <= 3 && b.Message&MESSAGE_NEXTHOP > 0) ||
  2011  		(version == 4 && b.Message&FRR_MESSAGE_NEXTHOP > 0) ||
  2012  		(version >= 5 && b.Message&FRR_ZAPI5_MESSAGE_NEXTHOP > 0) {
  2013  		var numNexthop uint16
  2014  		if version <= 4 {
  2015  			if pos+1 > rest {
  2016  				return fmt.Errorf("MESSAGE_NEXTHOP message length invalid pos:%d rest:%d", pos, rest)
  2017  			}
  2018  			numNexthop = uint16(data[pos])
  2019  			pos += 1
  2020  		} else { // version >= 5
  2021  			if pos+2 > rest {
  2022  				return fmt.Errorf("MESSAGE_NEXTHOP message length invalid pos:%d rest:%d", pos, rest)
  2023  			}
  2024  			numNexthop = binary.BigEndian.Uint16(data[pos : pos+2])
  2025  			pos += 2
  2026  		}
  2027  		for i := 0; i < int(numNexthop); i++ {
  2028  			var nexthop Nexthop
  2029  			if version <= 3 {
  2030  				if b.Prefix.Family == syscall.AF_INET {
  2031  					nexthop.Type = NEXTHOP_TYPE_IPV4
  2032  				} else if b.Prefix.Family == syscall.AF_INET6 {
  2033  					nexthop.Type = NEXTHOP_TYPE_IPV6
  2034  				}
  2035  			} else if version == 4 {
  2036  				if b.Prefix.Family == syscall.AF_INET {
  2037  					nexthop.Type = FRR_NEXTHOP_TYPE_IPV4
  2038  				} else if b.Prefix.Family == syscall.AF_INET6 {
  2039  					nexthop.Type = FRR_NEXTHOP_TYPE_IPV6
  2040  				}
  2041  			} else { // version >= 5
  2042  				if pos+5 > rest {
  2043  					return fmt.Errorf("MESSAGE_NEXTHOP message length invalid pos:%d rest:%d", pos, rest)
  2044  				}
  2045  				nexthop.VrfId = binary.BigEndian.Uint32(data[pos : pos+4])
  2046  				nexthop.Type = NEXTHOP_TYPE(data[pos+4])
  2047  				pos += 5
  2048  			}
  2049  
  2050  			if (version <= 3 && nexthop.Type == NEXTHOP_TYPE_IPV4) ||
  2051  				(version >= 4 && nexthop.Type == FRR_NEXTHOP_TYPE_IPV4) {
  2052  				if pos+4 > rest {
  2053  					return fmt.Errorf("MESSAGE_NEXTHOP NEXTHOP_TYPE_IPV4 message length invalid pos:%d rest:%d", pos, rest)
  2054  				}
  2055  				addr := data[pos : pos+4]
  2056  				nexthop.Gate = net.IP(addr).To4()
  2057  				pos += 4
  2058  			} else if (version <= 3 && nexthop.Type == NEXTHOP_TYPE_IPV6) ||
  2059  				(version >= 4 && nexthop.Type == FRR_NEXTHOP_TYPE_IPV6) {
  2060  				if pos+16 > rest {
  2061  					return fmt.Errorf("MESSAGE_NEXTHOP NEXTHOP_TYPE_IPV6 message length invalid pos:%d rest:%d", pos, rest)
  2062  				}
  2063  				addr := data[pos : pos+16]
  2064  				nexthop.Gate = net.IP(addr).To16()
  2065  				pos += 16
  2066  			} else if version >= 5 && nexthop.Type == FRR_NEXTHOP_TYPE_IFINDEX {
  2067  				if pos+4 > rest {
  2068  					return fmt.Errorf("MESSAGE_NEXTHOP NEXTHOP_TYPE_IFINDEX message length invalid pos:%d rest:%d", pos, rest)
  2069  				}
  2070  				nexthop.Ifindex = binary.BigEndian.Uint32(data[pos : pos+4])
  2071  				pos += 4
  2072  				// barkward compatibility
  2073  				if b.Prefix.Family == syscall.AF_INET {
  2074  					nexthop.Gate = net.ParseIP("0.0.0.0")
  2075  				} else if b.Prefix.Family == syscall.AF_INET6 {
  2076  					nexthop.Gate = net.ParseIP("::")
  2077  				}
  2078  			} else if version >= 5 && nexthop.Type == FRR_NEXTHOP_TYPE_IPV4_IFINDEX {
  2079  				if pos+8 > rest {
  2080  					return fmt.Errorf("MESSAGE_NEXTHOP NEXTHOP_TYPE_IPV4_IFINDEX message length invalid pos:%d rest:%d", pos, rest)
  2081  				}
  2082  				addr := data[pos : pos+4]
  2083  				nexthop.Gate = net.IP(addr).To4()
  2084  				nexthop.Ifindex = binary.BigEndian.Uint32(data[pos+4 : pos+8])
  2085  				pos += 8
  2086  			} else if version >= 5 && nexthop.Type == FRR_NEXTHOP_TYPE_IPV6_IFINDEX {
  2087  				if pos+20 > rest {
  2088  					return fmt.Errorf("MESSAGE_NEXTHOP NEXTHOP_TYPE_IPV6_IFINDEX message length invalid pos:%d rest:%d", pos, rest)
  2089  				}
  2090  				addr := data[pos : pos+16]
  2091  				nexthop.Gate = net.IP(addr).To16()
  2092  				nexthop.Ifindex = binary.BigEndian.Uint32(data[pos+16 : pos+20])
  2093  				pos += 20
  2094  			} else if version >= 5 && nexthop.Type == FRR_NEXTHOP_TYPE_BLACKHOLE {
  2095  				if pos+1 > rest {
  2096  					return fmt.Errorf("MESSAGE_NEXTHOP NEXTHOP_TYPE_BLACKHOLE message length invalid pos:%d rest:%d", pos, rest)
  2097  				}
  2098  				nexthop.BlackholeType = data[pos]
  2099  				pos += 1
  2100  			}
  2101  			b.Nexthops = append(b.Nexthops, nexthop)
  2102  		}
  2103  	}
  2104  
  2105  	if (version <= 3 && b.Message&MESSAGE_IFINDEX > 0) ||
  2106  		(version == 4 && b.Message&FRR_MESSAGE_IFINDEX > 0) {
  2107  		if pos+1 > rest {
  2108  			return fmt.Errorf("MESSAGE_IFINDEX message length invalid pos:%d rest:%d", pos, rest)
  2109  		}
  2110  		numIfIndex := uint8(data[pos])
  2111  		pos += 1
  2112  		for i := 0; i < int(numIfIndex); i++ {
  2113  			if pos+4 > rest {
  2114  				return fmt.Errorf("MESSAGE_IFINDEX message length invalid pos:%d rest:%d", pos, rest)
  2115  			}
  2116  			var nexthop Nexthop
  2117  			nexthop.Ifindex = binary.BigEndian.Uint32(data[pos : pos+4])
  2118  			if version <= 3 {
  2119  				nexthop.Type = NEXTHOP_TYPE_IFINDEX
  2120  			} else if version == 4 {
  2121  				nexthop.Type = FRR_NEXTHOP_TYPE_IFINDEX
  2122  			}
  2123  			b.Nexthops = append(b.Nexthops, nexthop)
  2124  			pos += 4
  2125  		}
  2126  	}
  2127  
  2128  	if (version <= 3 && b.Message&MESSAGE_DISTANCE > 0) ||
  2129  		(version == 4 && b.Message&FRR_MESSAGE_DISTANCE > 0) ||
  2130  		(version >= 5 && b.Message&FRR_ZAPI5_MESSAGE_DISTANCE > 0) {
  2131  		if pos+1 > rest {
  2132  			return fmt.Errorf("MESSAGE_DISTANCE message length invalid pos:%d rest:%d", pos, rest)
  2133  		}
  2134  		b.Distance = data[pos]
  2135  		pos += 1
  2136  	}
  2137  	if (version <= 3 && b.Message&MESSAGE_METRIC > 0) ||
  2138  		(version == 4 && b.Message&FRR_MESSAGE_METRIC > 0) ||
  2139  		(version >= 5 && b.Message&FRR_ZAPI5_MESSAGE_METRIC > 0) {
  2140  		if pos+4 > rest {
  2141  			return fmt.Errorf("MESSAGE_METRIC message length invalid pos:%d rest:%d", pos, rest)
  2142  		}
  2143  		b.Metric = binary.BigEndian.Uint32(data[pos : pos+4])
  2144  		pos += 4
  2145  	}
  2146  	if (version <= 3 && b.Message&MESSAGE_MTU > 0) ||
  2147  		(version == 4 && b.Message&FRR_MESSAGE_MTU > 0) ||
  2148  		(version >= 5 && b.Message&FRR_ZAPI5_MESSAGE_MTU > 0) {
  2149  		if pos+4 > rest {
  2150  			return fmt.Errorf("MESSAGE_MTU message length invalid pos:%d rest:%d", pos, rest)
  2151  		}
  2152  		b.Mtu = binary.BigEndian.Uint32(data[pos : pos+4])
  2153  		pos += 4
  2154  	}
  2155  	if (version <= 3 && b.Message&MESSAGE_TAG > 0) ||
  2156  		(version == 4 && b.Message&FRR_MESSAGE_TAG > 0) ||
  2157  		(version >= 5 && b.Message&FRR_ZAPI5_MESSAGE_TAG > 0) {
  2158  		if pos+4 > rest {
  2159  			return fmt.Errorf("MESSAGE_TAG message length invalid pos:%d rest:%d", pos, rest)
  2160  		}
  2161  		b.Tag = binary.BigEndian.Uint32(data[pos : pos+4])
  2162  		pos += 4
  2163  	}
  2164  	if pos != rest {
  2165  		return fmt.Errorf("message length invalid")
  2166  	}
  2167  
  2168  	return nil
  2169  }
  2170  
  2171  func (b *IPRouteBody) String() string {
  2172  	s := fmt.Sprintf(
  2173  		"type: %s, instance: %d, flags: %s, message: %d, safi: %s, prefix: %s/%d, src_prefix: %s/%d",
  2174  		b.Type.String(), b.Instance, b.Flags.String(), b.Message, b.SAFI.String(), b.Prefix.Prefix.String(), b.Prefix.PrefixLen, b.SrcPrefix.Prefix.String(), b.SrcPrefix.PrefixLen)
  2175  	for i, nh := range b.Nexthops {
  2176  		s += fmt.Sprintf(", nexthops[%d]: %s", i, nh.String())
  2177  		/*
  2178  			s += fmt.Sprintf(", nexthops[%d]: %s", i, nh.Gate.String())
  2179  			s += fmt.Sprintf(", ifindex[%d]: %d", i, nh.Ifindex)
  2180  		*/
  2181  	}
  2182  	return s + fmt.Sprintf(
  2183  		", distance: %d, metric: %d, mtu: %d, tag: %d",
  2184  		b.Distance, b.Metric, b.Mtu, b.Tag)
  2185  }
  2186  
  2187  func decodeNexthopsFromBytes(nexthops *[]Nexthop, data []byte, family uint8, version uint8) (int, error) {
  2188  	addrByteLen, err := addressByteLength(family)
  2189  	if err != nil {
  2190  		return 0, err
  2191  	}
  2192  
  2193  	numNexthop := int(data[0])
  2194  	offset := 1
  2195  
  2196  	for i := 0; i < numNexthop; i++ {
  2197  		nexthop := Nexthop{}
  2198  		nexthop.Type = NEXTHOP_TYPE(data[offset])
  2199  		offset += 1
  2200  
  2201  		// On Quagga, NEXTHOP_TYPE_IFNAME is same as NEXTHOP_TYPE_IFINDEX,
  2202  		// NEXTHOP_TYPE_IPV4_IFNAME is same as NEXTHOP_TYPE_IPV4_IFINDEX,
  2203  		// NEXTHOP_TYPE_IPV6_IFNAME is same as NEXTHOP_TYPE_IPV6_IFINDEX
  2204  
  2205  		// On FRRouting version 3.0 or later, NEXTHOP_TYPE_IPV4 and NEXTHOP_TYPE_IPV6 have
  2206  		// the same structure with NEXTHOP_TYPE_IPV4_IFINDEX and NEXTHOP_TYPE_IPV6_IFINDEX.
  2207  
  2208  		if (version <= 3 && (nexthop.Type == NEXTHOP_TYPE_IFINDEX || nexthop.Type == NEXTHOP_TYPE_IFNAME)) ||
  2209  			(version >= 4 && nexthop.Type == FRR_NEXTHOP_TYPE_IFINDEX) {
  2210  			nexthop.Ifindex = binary.BigEndian.Uint32(data[offset : offset+4])
  2211  			offset += 4
  2212  		} else if version <= 3 && nexthop.Type == NEXTHOP_TYPE_IPV4 {
  2213  			nexthop.Gate = net.IP(data[offset : offset+addrByteLen]).To4()
  2214  			offset += addrByteLen
  2215  		} else if version <= 3 && nexthop.Type == NEXTHOP_TYPE_IPV6 {
  2216  			nexthop.Gate = net.IP(data[offset : offset+addrByteLen]).To16()
  2217  			offset += addrByteLen
  2218  		} else if (version <= 3 && (nexthop.Type == NEXTHOP_TYPE_IPV4_IFINDEX || nexthop.Type == NEXTHOP_TYPE_IPV4_IFNAME)) ||
  2219  			(version >= 4 && (nexthop.Type == FRR_NEXTHOP_TYPE_IPV4 || nexthop.Type == FRR_NEXTHOP_TYPE_IPV4_IFINDEX)) {
  2220  			nexthop.Gate = net.IP(data[offset : offset+addrByteLen]).To4()
  2221  			offset += addrByteLen
  2222  			nexthop.Ifindex = binary.BigEndian.Uint32(data[offset : offset+4])
  2223  			offset += 4
  2224  		} else if (version <= 3 && (nexthop.Type == NEXTHOP_TYPE_IPV6_IFINDEX || nexthop.Type == NEXTHOP_TYPE_IPV6_IFNAME)) ||
  2225  			(version >= 4 && (nexthop.Type == FRR_NEXTHOP_TYPE_IPV6 || nexthop.Type == FRR_NEXTHOP_TYPE_IPV6_IFINDEX)) {
  2226  			nexthop.Gate = net.IP(data[offset : offset+addrByteLen]).To16()
  2227  			offset += addrByteLen
  2228  			nexthop.Ifindex = binary.BigEndian.Uint32(data[offset : offset+4])
  2229  			offset += 4
  2230  		}
  2231  		if version >= 5 {
  2232  			nexthop.LabelNum = data[offset]
  2233  			offset += 1
  2234  			if nexthop.LabelNum > MPLS_MAX_LABEL {
  2235  				nexthop.LabelNum = MPLS_MAX_LABEL
  2236  			}
  2237  			var n uint8
  2238  			for ; n < nexthop.LabelNum; n++ {
  2239  				nexthop.MplsLabels[n] = binary.BigEndian.Uint32(data[offset : offset+4])
  2240  				offset += 4
  2241  			}
  2242  		}
  2243  		*nexthops = append(*nexthops, nexthop)
  2244  	}
  2245  
  2246  	return offset, nil
  2247  }
  2248  
  2249  type NexthopLookupBody struct {
  2250  	Api      API_TYPE
  2251  	Addr     net.IP
  2252  	Distance uint8
  2253  	Metric   uint32
  2254  	Nexthops []Nexthop
  2255  }
  2256  
  2257  // Quagga only. Reference: zread_ipv[4|6]_nexthop_lookup in zebra/zserv.c of Quagga1.2.x (ZAPI3)
  2258  func (b *NexthopLookupBody) Serialize(version uint8) ([]byte, error) {
  2259  	family := addressFamilyFromApi(b.Api, version)
  2260  	buf := make([]byte, 0)
  2261  
  2262  	if family == syscall.AF_INET {
  2263  		buf = append(buf, b.Addr.To4()...)
  2264  	} else if family == syscall.AF_INET6 {
  2265  		buf = append(buf, b.Addr.To16()...)
  2266  	}
  2267  	return buf, nil
  2268  }
  2269  
  2270  // Quagga only. Reference: zsend_ipv[4|6]_nexthop_lookup in zebra/zserv.c of Quagga1.2.x (ZAPI3)
  2271  func (b *NexthopLookupBody) DecodeFromBytes(data []byte, version uint8) error {
  2272  	family := addressFamilyFromApi(b.Api, version)
  2273  	addrByteLen, err := addressByteLength(family)
  2274  	if err != nil {
  2275  		return err
  2276  	}
  2277  
  2278  	if len(data) < addrByteLen {
  2279  		return fmt.Errorf("message length invalid")
  2280  	}
  2281  
  2282  	buf := make([]byte, addrByteLen)
  2283  	copy(buf, data[0:addrByteLen])
  2284  	pos := addrByteLen
  2285  	b.Addr = ipFromFamily(family, buf)
  2286  
  2287  	if version >= 4 {
  2288  		b.Distance = data[pos]
  2289  		pos++
  2290  	}
  2291  
  2292  	if len(data[pos:]) > int(1+addrByteLen) {
  2293  		b.Metric = binary.BigEndian.Uint32(data[pos : pos+4])
  2294  		pos += 4
  2295  		b.Nexthops = []Nexthop{}
  2296  		if nexthopsByteLen, err := decodeNexthopsFromBytes(&b.Nexthops, data[pos:], family, version); err != nil {
  2297  			return err
  2298  		} else {
  2299  			pos += nexthopsByteLen
  2300  		}
  2301  	}
  2302  
  2303  	return nil
  2304  }
  2305  
  2306  func (b *NexthopLookupBody) String() string {
  2307  	s := fmt.Sprintf(
  2308  		"addr: %s, distance:%d, metric: %d",
  2309  		b.Addr.String(), b.Distance, b.Metric)
  2310  	if len(b.Nexthops) > 0 {
  2311  		for _, nh := range b.Nexthops {
  2312  			s = s + fmt.Sprintf(", nexthop:{%s}", nh.String())
  2313  		}
  2314  	}
  2315  	return s
  2316  }
  2317  
  2318  type ImportLookupBody struct {
  2319  	Api          API_TYPE
  2320  	PrefixLength uint8
  2321  	Prefix       net.IP
  2322  	Addr         net.IP
  2323  	Metric       uint32
  2324  	Nexthops     []Nexthop
  2325  }
  2326  
  2327  // Quagga only. Reference: zread_ipv4_import_lookup in zebra/zserv.c of Quagga1.2.x (ZAPI3)
  2328  func (b *ImportLookupBody) Serialize(version uint8) ([]byte, error) {
  2329  	buf := make([]byte, 1)
  2330  	buf[0] = b.PrefixLength
  2331  	buf = append(buf, b.Addr.To4()...)
  2332  	return buf, nil
  2333  }
  2334  
  2335  // Quagga only. Reference: zsend_ipv4_import_lookup in zebra/zserv.c of Quagga1.2.x (ZAPI3)
  2336  func (b *ImportLookupBody) DecodeFromBytes(data []byte, version uint8) error {
  2337  	family := addressFamilyFromApi(b.Api, version)
  2338  	addrByteLen, err := addressByteLength(family)
  2339  	if err != nil {
  2340  		return err
  2341  	}
  2342  
  2343  	if len(data) < addrByteLen {
  2344  		return fmt.Errorf("message length invalid")
  2345  	}
  2346  
  2347  	buf := make([]byte, addrByteLen)
  2348  	copy(buf, data[0:addrByteLen])
  2349  	pos := addrByteLen
  2350  
  2351  	b.Addr = net.IP(buf).To4()
  2352  
  2353  	if len(data[pos:]) > int(1+addrByteLen) {
  2354  		b.Metric = binary.BigEndian.Uint32(data[pos : pos+4])
  2355  		pos += 4
  2356  		b.Nexthops = []Nexthop{}
  2357  		if nexthopsByteLen, err := decodeNexthopsFromBytes(&b.Nexthops, data[pos:], family, version); err != nil {
  2358  			return err
  2359  		} else {
  2360  			pos += nexthopsByteLen
  2361  		}
  2362  	}
  2363  
  2364  	return nil
  2365  }
  2366  
  2367  func (b *ImportLookupBody) String() string {
  2368  	s := fmt.Sprintf(
  2369  		"prefix: %s/%d, addr: %s, metric: %d",
  2370  		b.Prefix.String(), b.PrefixLength, b.Addr.String(), b.Metric)
  2371  	if len(b.Nexthops) > 0 {
  2372  		for _, nh := range b.Nexthops {
  2373  			s = s + fmt.Sprintf(", nexthop:{%s}", nh.String())
  2374  		}
  2375  	}
  2376  	return s
  2377  }
  2378  
  2379  type RegisteredNexthop struct {
  2380  	Connected uint8
  2381  	Family    uint16
  2382  	// Note: Ignores PrefixLength (uint8),
  2383  	// because this field should be always:
  2384  	// - 32 if Address Family is AF_INET
  2385  	// - 128 if Address Family is AF_INET6
  2386  	Prefix net.IP
  2387  }
  2388  
  2389  func (n *RegisteredNexthop) Len() int {
  2390  	// Connected (1 byte) + Address Family (2 bytes) + Prefix Length (1 byte) + Prefix (variable)
  2391  	if n.Family == uint16(syscall.AF_INET) {
  2392  		return 4 + net.IPv4len
  2393  	} else {
  2394  		return 4 + net.IPv6len
  2395  	}
  2396  }
  2397  
  2398  // Reference: sendmsg_nexthop in bgpd/bgp_nht.c of Quagga1.2.x (ZAPI3)
  2399  // Reference: sendmsg_zebra_rnh in bgpd/bgp_nht.c of FRR3.x (ZAPI4)
  2400  // Reference: zclient_send_rnh function in lib/zclient.c of FRR5.x (ZAPI5)
  2401  func (n *RegisteredNexthop) Serialize() ([]byte, error) {
  2402  	// Connected (1 byte)
  2403  	buf := make([]byte, 4)
  2404  	buf[0] = byte(n.Connected)
  2405  
  2406  	// Address Family (2 bytes)
  2407  	binary.BigEndian.PutUint16(buf[1:3], n.Family)
  2408  	// Prefix Length (1 byte)
  2409  	addrByteLen, err := addressByteLength(uint8(n.Family))
  2410  	if err != nil {
  2411  		return nil, err
  2412  	}
  2413  
  2414  	buf[3] = byte(addrByteLen * 8)
  2415  	// Prefix (variable)
  2416  	switch n.Family {
  2417  	case uint16(syscall.AF_INET):
  2418  		buf = append(buf, n.Prefix.To4()...)
  2419  	case uint16(syscall.AF_INET6):
  2420  		buf = append(buf, n.Prefix.To16()...)
  2421  	default:
  2422  		return nil, fmt.Errorf("invalid address family: %d", n.Family)
  2423  	}
  2424  
  2425  	return buf, nil
  2426  }
  2427  
  2428  // Reference: zserv_nexthop_register in zebra/zserv.c of Quagga1.2.x (ZAPI3)
  2429  // Reference: zserv_rnh_register in zebra/zserv.c of FRR3.x (ZAPI4)
  2430  // Reference: zread_rnh_register in zebra/zapi_msg.c of FRR5.x (ZAPI5)
  2431  func (n *RegisteredNexthop) DecodeFromBytes(data []byte) error {
  2432  	// Connected (1 byte)
  2433  	n.Connected = uint8(data[0])
  2434  	// Address Family (2 bytes)
  2435  	n.Family = binary.BigEndian.Uint16(data[1:3])
  2436  	// Note: Ignores Prefix Length (1 byte)
  2437  	addrByteLen := (int(data[3]) + 7) / 8
  2438  	// Prefix (variable)
  2439  	n.Prefix = ipFromFamily(uint8(n.Family), data[4:4+addrByteLen])
  2440  
  2441  	return nil
  2442  }
  2443  
  2444  func (n *RegisteredNexthop) String() string {
  2445  	return fmt.Sprintf(
  2446  		"connected: %d, family: %d, prefix: %s",
  2447  		n.Connected, n.Family, n.Prefix.String())
  2448  }
  2449  
  2450  type NexthopRegisterBody struct {
  2451  	Api      API_TYPE
  2452  	Nexthops []*RegisteredNexthop
  2453  }
  2454  
  2455  // Reference: sendmsg_nexthop in bgpd/bgp_nht.c of Quagga1.2.x (ZAPI3)
  2456  // Reference: sendmsg_zebra_rnh in bgpd/bgp_nht.c of FRR3.x (ZAPI4)
  2457  // Reference: zclient_send_rnh function in lib/zclient.c of FRR5.x (ZAPI5)
  2458  func (b *NexthopRegisterBody) Serialize(version uint8) ([]byte, error) {
  2459  	buf := make([]byte, 0)
  2460  
  2461  	// List of Registered Nexthops
  2462  	for _, nh := range b.Nexthops {
  2463  		nhBuf, err := nh.Serialize()
  2464  		if err != nil {
  2465  			return nil, err
  2466  		}
  2467  		buf = append(buf, nhBuf...)
  2468  	}
  2469  
  2470  	return buf, nil
  2471  }
  2472  
  2473  // Reference: zserv_nexthop_register in zebra/zserv.c of Quagga1.2.x (ZAPI3)
  2474  // Reference: zserv_rnh_register in zebra/zserv.c of FRR3.x (ZAPI4)
  2475  // Reference: zread_rnh_register in zebra/zapi_msg.c of FRR5.x (ZAPI5)
  2476  func (b *NexthopRegisterBody) DecodeFromBytes(data []byte, version uint8) error {
  2477  	offset := 0
  2478  
  2479  	// List of Registered Nexthops
  2480  	b.Nexthops = []*RegisteredNexthop{}
  2481  	for len(data[offset:]) > 0 {
  2482  		nh := new(RegisteredNexthop)
  2483  		err := nh.DecodeFromBytes(data[offset:])
  2484  		if err != nil {
  2485  			return err
  2486  		}
  2487  		b.Nexthops = append(b.Nexthops, nh)
  2488  
  2489  		offset += nh.Len()
  2490  		if len(data) < offset {
  2491  			break
  2492  		}
  2493  	}
  2494  
  2495  	return nil
  2496  }
  2497  
  2498  func (b *NexthopRegisterBody) String() string {
  2499  	s := make([]string, 0)
  2500  	for _, nh := range b.Nexthops {
  2501  		s = append(s, fmt.Sprintf("nexthop:{%s}", nh.String()))
  2502  	}
  2503  	return strings.Join(s, ", ")
  2504  }
  2505  
  2506  /* NEXTHOP_UPDATE message uses same data structure as IPRoute (zapi_route)
  2507     in FRR version 4, 5 (ZApi version 5) */
  2508  type NexthopUpdateBody IPRouteBody
  2509  
  2510  // Reference: send_client function in zebra/zebra_rnh.c of Quagga1.2.x (ZAPI3)
  2511  // Reference: send_client function in zebra/zebra_rnh.c of FRR3.x (ZAPI4)
  2512  // Reference: send_client function in zebra/zebra_rnh.c of FRR5.x (ZAPI5)
  2513  func (b *NexthopUpdateBody) Serialize(version uint8) ([]byte, error) {
  2514  	// Address Family (2 bytes)
  2515  	buf := make([]byte, 3)
  2516  	binary.BigEndian.PutUint16(buf, uint16(b.Prefix.Family))
  2517  	addrByteLen, err := addressByteLength(b.Prefix.Family)
  2518  	if err != nil {
  2519  		return nil, err
  2520  	}
  2521  
  2522  	buf[2] = byte(addrByteLen * 8)
  2523  	// Prefix Length (1 byte) + Prefix (variable)
  2524  	switch b.Prefix.Family {
  2525  	case syscall.AF_INET:
  2526  		buf = append(buf, b.Prefix.Prefix.To4()...)
  2527  	case syscall.AF_INET6:
  2528  		buf = append(buf, b.Prefix.Prefix.To16()...)
  2529  	default:
  2530  		return nil, fmt.Errorf("invalid address family: %d", b.Prefix.Family)
  2531  	}
  2532  	if version >= 5 {
  2533  		// Type (1 byte) (if version>=5)
  2534  		// Instance (2 bytes) (if version>=5)
  2535  		buf = append(buf, byte(b.Type))
  2536  		bbuf := make([]byte, 2)
  2537  		binary.BigEndian.PutUint16(bbuf, b.Instance)
  2538  		buf = append(buf, bbuf...)
  2539  	}
  2540  	if version >= 4 {
  2541  		// Distance (1 byte) (if version>=4)
  2542  		buf = append(buf, b.Distance)
  2543  	}
  2544  	// Metric (4 bytes)
  2545  	bbuf := make([]byte, 4)
  2546  	binary.BigEndian.PutUint32(bbuf, b.Metric)
  2547  	buf = append(buf, bbuf...)
  2548  	// Number of Nexthops (1 byte)
  2549  	buf = append(buf, uint8(0)) // Temporary code
  2550  	// ToDo Processing Route Entry
  2551  
  2552  	return buf, nil
  2553  }
  2554  
  2555  // Reference: bgp_parse_nexthop_update function in bgpd/bgp_nht.c of Quagga1.2.x (ZAPI3)
  2556  // Reference: bgp_parse_nexthop_update function in bgpd/bgp_nht.c of FRR3.x (ZAPI4)
  2557  // Reference: zapi_nexthop_update_decode function in lib/zclient.c of FRR5.x (ZAPI5)
  2558  func (b *NexthopUpdateBody) DecodeFromBytes(data []byte, version uint8) error {
  2559  	// Address Family (2 bytes)
  2560  	prefixFamily := binary.BigEndian.Uint16(data[0:2])
  2561  	b.Prefix.Family = uint8(prefixFamily)
  2562  	b.Prefix.PrefixLen = data[2]
  2563  	offset := 3
  2564  
  2565  	addrByteLen, err := addressByteLength(b.Prefix.Family)
  2566  	if err != nil {
  2567  		return err
  2568  	}
  2569  
  2570  	b.Prefix.Prefix = ipFromFamily(b.Prefix.Family, data[offset:offset+addrByteLen])
  2571  	offset += addrByteLen
  2572  
  2573  	if version >= 5 {
  2574  		b.Type = ROUTE_TYPE(data[offset])
  2575  		b.Instance = binary.BigEndian.Uint16(data[offset+1 : offset+3])
  2576  		offset += 3
  2577  	}
  2578  	// Distance (1 byte) (if version>=4)
  2579  	if version >= 4 {
  2580  		b.Distance = data[offset]
  2581  		offset += 1
  2582  	}
  2583  	// Metric (4 bytes)
  2584  	// Number of Nexthops (1 byte)
  2585  	if len(data[offset:]) < 5 {
  2586  		return fmt.Errorf("invalid message length: missing metric(4 bytes) or nexthops(1 byte): %d<5", len(data[offset:]))
  2587  	}
  2588  	b.Metric = binary.BigEndian.Uint32(data[offset : offset+4])
  2589  	offset += 4
  2590  
  2591  	// List of Nexthops
  2592  	b.Nexthops = []Nexthop{}
  2593  	if nexthopsByteLen, err := decodeNexthopsFromBytes(&b.Nexthops, data[offset:], b.Prefix.Family, version); err != nil {
  2594  		return err
  2595  	} else {
  2596  		offset += nexthopsByteLen
  2597  	}
  2598  	return nil
  2599  }
  2600  
  2601  func (b *NexthopUpdateBody) String() string {
  2602  	s := fmt.Sprintf(
  2603  		"family: %d, prefix: %s, distance: %d, metric: %d",
  2604  		b.Prefix.Family, b.Prefix.Prefix.String(), b.Distance, b.Metric)
  2605  	for _, nh := range b.Nexthops {
  2606  		s = s + fmt.Sprintf(", nexthop:{%s}", nh.String())
  2607  	}
  2608  	return s
  2609  }
  2610  
  2611  type Message struct {
  2612  	Header Header
  2613  	Body   Body
  2614  }
  2615  
  2616  func (m *Message) Serialize() ([]byte, error) {
  2617  	var body []byte
  2618  	if m.Body != nil {
  2619  		var err error
  2620  		body, err = m.Body.Serialize(m.Header.Version)
  2621  		if err != nil {
  2622  			return nil, err
  2623  		}
  2624  	}
  2625  	m.Header.Len = uint16(len(body)) + HeaderSize(m.Header.Version)
  2626  	hdr, err := m.Header.Serialize()
  2627  	if err != nil {
  2628  		return nil, err
  2629  	}
  2630  	return append(hdr, body...), nil
  2631  }
  2632  
  2633  func (m *Message) parseMessage(data []byte) error {
  2634  	switch m.Header.Command {
  2635  	case INTERFACE_ADD, INTERFACE_DELETE, INTERFACE_UP, INTERFACE_DOWN:
  2636  		m.Body = &InterfaceUpdateBody{}
  2637  	case INTERFACE_ADDRESS_ADD, INTERFACE_ADDRESS_DELETE:
  2638  		m.Body = &InterfaceAddressUpdateBody{}
  2639  	case ROUTER_ID_UPDATE:
  2640  		m.Body = &RouterIDUpdateBody{}
  2641  	case IPV4_ROUTE_ADD, IPV6_ROUTE_ADD, IPV4_ROUTE_DELETE, IPV6_ROUTE_DELETE:
  2642  		m.Body = &IPRouteBody{Api: m.Header.Command}
  2643  	case IPV4_NEXTHOP_LOOKUP, IPV6_NEXTHOP_LOOKUP:
  2644  		m.Body = &NexthopLookupBody{Api: m.Header.Command}
  2645  	case IPV4_IMPORT_LOOKUP:
  2646  		m.Body = &ImportLookupBody{Api: m.Header.Command}
  2647  	case NEXTHOP_UPDATE:
  2648  		m.Body = &NexthopUpdateBody{Api: m.Header.Command}
  2649  	default:
  2650  		m.Body = &UnknownBody{}
  2651  	}
  2652  	return m.Body.DecodeFromBytes(data, m.Header.Version)
  2653  }
  2654  
  2655  func (m *Message) parseFrrMessage(data []byte) error {
  2656  	switch m.Header.Command {
  2657  	case FRR_INTERFACE_ADD, FRR_INTERFACE_DELETE, FRR_INTERFACE_UP, FRR_INTERFACE_DOWN:
  2658  		m.Body = &InterfaceUpdateBody{}
  2659  	case FRR_INTERFACE_ADDRESS_ADD, FRR_INTERFACE_ADDRESS_DELETE:
  2660  		m.Body = &InterfaceAddressUpdateBody{}
  2661  	case FRR_ROUTER_ID_UPDATE:
  2662  		m.Body = &RouterIDUpdateBody{}
  2663  	case FRR_NEXTHOP_UPDATE:
  2664  		m.Body = &NexthopUpdateBody{}
  2665  	case FRR_INTERFACE_NBR_ADDRESS_ADD, FRR_INTERFACE_NBR_ADDRESS_DELETE:
  2666  		// TODO
  2667  		m.Body = &UnknownBody{}
  2668  	case FRR_INTERFACE_BFD_DEST_UPDATE:
  2669  		// TODO
  2670  		m.Body = &UnknownBody{}
  2671  	case FRR_IMPORT_CHECK_UPDATE:
  2672  		// TODO
  2673  		m.Body = &UnknownBody{}
  2674  	case FRR_BFD_DEST_REPLAY:
  2675  		// TODO
  2676  		m.Body = &UnknownBody{}
  2677  	case FRR_REDISTRIBUTE_IPV4_ADD, FRR_REDISTRIBUTE_IPV4_DEL, FRR_REDISTRIBUTE_IPV6_ADD, FRR_REDISTRIBUTE_IPV6_DEL:
  2678  		m.Body = &IPRouteBody{Api: m.Header.Command}
  2679  	case FRR_INTERFACE_VRF_UPDATE:
  2680  		// TODO
  2681  		m.Body = &UnknownBody{}
  2682  	case FRR_INTERFACE_LINK_PARAMS:
  2683  		// TODO
  2684  		m.Body = &UnknownBody{}
  2685  	case FRR_PW_STATUS_UPDATE:
  2686  		// TODO
  2687  		m.Body = &UnknownBody{}
  2688  	default:
  2689  		m.Body = &UnknownBody{}
  2690  	}
  2691  	return m.Body.DecodeFromBytes(data, m.Header.Version)
  2692  }
  2693  
  2694  func (m *Message) parseFrrZapi5Message(data []byte) error {
  2695  	switch m.Header.Command {
  2696  	case FRR_ZAPI5_INTERFACE_ADD, FRR_ZAPI5_INTERFACE_DELETE, FRR_ZAPI5_INTERFACE_UP, FRR_ZAPI5_INTERFACE_DOWN:
  2697  		m.Body = &InterfaceUpdateBody{}
  2698  	case FRR_ZAPI5_INTERFACE_ADDRESS_ADD, FRR_ZAPI5_INTERFACE_ADDRESS_DELETE:
  2699  		m.Body = &InterfaceAddressUpdateBody{}
  2700  	case FRR_ZAPI5_ROUTER_ID_UPDATE:
  2701  		m.Body = &RouterIDUpdateBody{}
  2702  	case FRR_ZAPI5_NEXTHOP_UPDATE:
  2703  		m.Body = &NexthopUpdateBody{}
  2704  	case FRR_ZAPI5_INTERFACE_NBR_ADDRESS_ADD, FRR_ZAPI5_INTERFACE_NBR_ADDRESS_DELETE:
  2705  		// TODO
  2706  		m.Body = &UnknownBody{}
  2707  	case FRR_ZAPI5_INTERFACE_BFD_DEST_UPDATE:
  2708  		// TODO
  2709  		m.Body = &UnknownBody{}
  2710  	case FRR_ZAPI5_IMPORT_CHECK_UPDATE:
  2711  		// TODO
  2712  		m.Body = &UnknownBody{}
  2713  	case FRR_ZAPI5_BFD_DEST_REPLAY:
  2714  		// TODO
  2715  		m.Body = &UnknownBody{}
  2716  	case FRR_ZAPI5_REDISTRIBUTE_ROUTE_ADD, FRR_ZAPI5_REDISTRIBUTE_ROUTE_DEL:
  2717  		m.Body = &IPRouteBody{Api: m.Header.Command}
  2718  	case FRR_ZAPI5_INTERFACE_VRF_UPDATE:
  2719  		// TODO
  2720  		m.Body = &UnknownBody{}
  2721  	case FRR_ZAPI5_INTERFACE_LINK_PARAMS:
  2722  		// TODO
  2723  		m.Body = &UnknownBody{}
  2724  	case FRR_ZAPI5_PW_STATUS_UPDATE:
  2725  		// TODO
  2726  		m.Body = &UnknownBody{}
  2727  	default:
  2728  		m.Body = &UnknownBody{}
  2729  	}
  2730  	return m.Body.DecodeFromBytes(data, m.Header.Version)
  2731  }
  2732  
  2733  func (m *Message) parseFrrZapi6Message(data []byte) error {
  2734  	switch m.Header.Command {
  2735  	case FRR_ZAPI6_INTERFACE_ADD, FRR_ZAPI6_INTERFACE_DELETE, FRR_ZAPI6_INTERFACE_UP, FRR_ZAPI6_INTERFACE_DOWN:
  2736  		m.Body = &InterfaceUpdateBody{}
  2737  	case FRR_ZAPI6_INTERFACE_ADDRESS_ADD, FRR_ZAPI6_INTERFACE_ADDRESS_DELETE:
  2738  		m.Body = &InterfaceAddressUpdateBody{}
  2739  	case FRR_ZAPI6_ROUTER_ID_UPDATE:
  2740  		m.Body = &RouterIDUpdateBody{}
  2741  	case FRR_ZAPI6_NEXTHOP_UPDATE:
  2742  		m.Body = &NexthopUpdateBody{}
  2743  	case FRR_ZAPI6_INTERFACE_NBR_ADDRESS_ADD, FRR_ZAPI6_INTERFACE_NBR_ADDRESS_DELETE:
  2744  		// TODO
  2745  		m.Body = &UnknownBody{}
  2746  	case FRR_ZAPI6_INTERFACE_BFD_DEST_UPDATE:
  2747  		// TODO
  2748  		m.Body = &UnknownBody{}
  2749  	case FRR_ZAPI6_IMPORT_CHECK_UPDATE:
  2750  		// TODO
  2751  		m.Body = &UnknownBody{}
  2752  	case FRR_ZAPI6_BFD_DEST_REPLAY:
  2753  		// TODO
  2754  		m.Body = &UnknownBody{}
  2755  	case FRR_ZAPI6_REDISTRIBUTE_ROUTE_ADD, FRR_ZAPI6_REDISTRIBUTE_ROUTE_DEL:
  2756  		m.Body = &IPRouteBody{Api: m.Header.Command}
  2757  	case FRR_ZAPI6_INTERFACE_VRF_UPDATE:
  2758  		// TODO
  2759  		m.Body = &UnknownBody{}
  2760  	case FRR_ZAPI6_INTERFACE_LINK_PARAMS:
  2761  		// TODO
  2762  		m.Body = &UnknownBody{}
  2763  	case FRR_ZAPI6_PW_STATUS_UPDATE:
  2764  		// TODO
  2765  		m.Body = &UnknownBody{}
  2766  	default:
  2767  		m.Body = &UnknownBody{}
  2768  	}
  2769  	return m.Body.DecodeFromBytes(data, m.Header.Version)
  2770  }
  2771  
  2772  func ParseMessage(hdr *Header, data []byte) (m *Message, err error) {
  2773  	m = &Message{Header: *hdr}
  2774  	if m.Header.Version == 4 {
  2775  		err = m.parseFrrMessage(data)
  2776  	} else if m.Header.Version == 5 {
  2777  		err = m.parseFrrZapi5Message(data)
  2778  	} else if m.Header.Version == 6 {
  2779  		err = m.parseFrrZapi6Message(data)
  2780  	} else {
  2781  		err = m.parseMessage(data)
  2782  	}
  2783  	if err != nil {
  2784  		return nil, err
  2785  	}
  2786  	return m, nil
  2787  }