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 }