📄 bgp_open.c
字号:
} restart_pnt = pnt + 4; restart_end = pnt + cap.length + 2; while (restart_pnt < restart_end) { memcpy (&graf, restart_pnt, sizeof (struct graceful_restart_af)); afi = ntohs(graf.afi); safi = graf.safi; if (CHECK_FLAG (graf.flag, RESTART_F_BIT)) SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_RESTART_AF_PRESERVE_RCV); if (strcmp (afi_safi_print (afi, safi), "Unknown") == 0) { if (BGP_DEBUG (normal, NORMAL)) zlog_info ("%s Addr-family %d/%d(afi/safi) not supported. Ignore the Graceful Restart capability", peer->host, afi, safi); } else if (! peer->afc[afi][safi]) { if (BGP_DEBUG (normal, NORMAL)) zlog_info ("%s Addr-family %d/%d(afi/safi) not enabled. Ignore the Graceful Restart capability", peer->host, afi, safi); } else { if (BGP_DEBUG (normal, NORMAL)) zlog_info ("%s Address family %s is%spreserved", peer->host, afi_safi_print (afi, safi), CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_RESTART_AF_PRESERVE_RCV) ? " " : " not "); SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_RESTART_AF_RCV); } restart_pnt += 4; } } else if (cap.code == CAPABILITY_CODE_DYNAMIC) { /* Check length. */ if (cap.length != CAPABILITY_CODE_DYNAMIC_LEN) { zlog_info ("%s Dynamic Capability length error %d", peer->host, cap.length); bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0); return -1; } if (BGP_DEBUG (normal, NORMAL)) zlog_info ("%s OPEN has DYNAMIC capability", peer->host); SET_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV); } else if (cap.code > 128) { /* We don't send Notification for unknown vendor specific capabilities. It seems reasonable for now... */ zlog_warn ("%s Vendor specific capability %d", peer->host, cap.code); } else { zlog_warn ("%s unrecognized capability code: %d - ignored", peer->host, cap.code); memcpy (*error, &cap, cap.length + 2); *error += cap.length + 2; } pnt += cap.length + 2; } return 0;}intbgp_auth_parse (struct peer *peer, u_char *pnt, size_t length){ bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR, BGP_NOTIFY_OPEN_AUTH_FAILURE); return -1;}intstrict_capability_same (struct peer *peer){ int i, j; for (i = AFI_IP; i < AFI_MAX; i++) for (j = SAFI_UNICAST; j < SAFI_MAX; j++) if (peer->afc[i][j] != peer->afc_nego[i][j]) return 0; return 1;}/* Parse open option */intbgp_open_option_parse (struct peer *peer, u_char length, int *capability){ int ret; u_char *end; u_char opt_type; u_char opt_length; u_char *pnt; u_char *error; u_char error_data[BGP_MAX_PACKET_SIZE]; /* Fetch pointer. */ pnt = stream_pnt (peer->ibuf); ret = 0; opt_type = 0; opt_length = 0; end = pnt + length; error = error_data; if (BGP_DEBUG (normal, NORMAL)) zlog_info ("%s rcv OPEN w/ OPTION parameter len: %u", peer->host, length); while (pnt < end) { /* Check the length. */ if (pnt + 2 > end) { zlog_info ("%s Option length error", peer->host); bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0); return -1; } /* Fetch option type and length. */ opt_type = *pnt++; opt_length = *pnt++; /* Option length check. */ if (pnt + opt_length > end) { zlog_info ("%s Option length error", peer->host); bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0); return -1; } if (BGP_DEBUG (normal, NORMAL)) zlog_info ("%s rcvd OPEN w/ optional parameter type %u (%s) len %u", peer->host, opt_type, opt_type == BGP_OPEN_OPT_AUTH ? "Authentication" : opt_type == BGP_OPEN_OPT_CAP ? "Capability" : "Unknown", opt_length); switch (opt_type) { case BGP_OPEN_OPT_AUTH: ret = bgp_auth_parse (peer, pnt, opt_length); break; case BGP_OPEN_OPT_CAP: ret = bgp_capability_parse (peer, pnt, opt_length, &error); *capability = 1; break; default: bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR, BGP_NOTIFY_OPEN_UNSUP_PARAM); ret = -1; break; } /* Parse error. To accumulate all unsupported capability codes, bgp_capability_parse does not return -1 when encounter unsupported capability code. To detect that, please check error and erro_data pointer, like below. */ if (ret < 0) return -1; /* Forward pointer. */ pnt += opt_length; } /* All OPEN option is parsed. Check capability when strict compare flag is enabled.*/ if (CHECK_FLAG (peer->flags, PEER_FLAG_STRICT_CAP_MATCH)) { /* If Unsupported Capability exists. */ if (error != error_data) { bgp_notify_send_with_data (peer, BGP_NOTIFY_OPEN_ERR, BGP_NOTIFY_OPEN_UNSUP_CAPBL, error_data, error - error_data); return -1; } /* Check local capability does not negotiated with remote peer. */ if (! strict_capability_same (peer)) { bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR, BGP_NOTIFY_OPEN_UNSUP_CAPBL); return -1; } } /* Check there is no common capability send Unsupported Capability error. */ if (*capability && ! CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY)) { if (! peer->afc_nego[AFI_IP][SAFI_UNICAST] && ! peer->afc_nego[AFI_IP][SAFI_MULTICAST] && ! peer->afc_nego[AFI_IP][SAFI_MPLS_VPN] && ! peer->afc_nego[AFI_IP6][SAFI_UNICAST] && ! peer->afc_nego[AFI_IP6][SAFI_MULTICAST]) { plog_err (peer->log, "%s [Error] No common capability", peer->host); if (error != error_data) bgp_notify_send_with_data (peer, BGP_NOTIFY_OPEN_ERR, BGP_NOTIFY_OPEN_UNSUP_CAPBL, error_data, error - error_data); else bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR, BGP_NOTIFY_OPEN_UNSUP_CAPBL); return -1; } } return 0;}voidbgp_open_capability_orf (struct stream *s, struct peer *peer, afi_t afi, safi_t safi, u_char code){ u_char cap_len; u_char orf_len; unsigned long capp; unsigned long orfp; unsigned long numberp; int number_of_orfs = 0; if (safi == SAFI_MPLS_VPN) safi = BGP_SAFI_VPNV4; stream_putc (s, BGP_OPEN_OPT_CAP); capp = stream_get_putp (s); /* Set Capability Len Pointer */ stream_putc (s, 0); /* Capability Length */ stream_putc (s, code); /* Capability Code */ orfp = stream_get_putp (s); /* Set ORF Len Pointer */ stream_putc (s, 0); /* ORF Length */ stream_putw (s, afi); stream_putc (s, 0); stream_putc (s, safi); numberp = stream_get_putp (s); /* Set Number Pointer */ stream_putc (s, 0); /* Number of ORFs */ /* Address Prefix ORF */ if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM) || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM)) { stream_putc (s, (code == CAPABILITY_CODE_ORF ? ORF_TYPE_PREFIX : ORF_TYPE_PREFIX_OLD)); if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM) && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM)) { SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV); SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV); stream_putc (s, ORF_MODE_BOTH); } else if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)) { SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV); stream_putc (s, ORF_MODE_SEND); } else { SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV); stream_putc (s, ORF_MODE_RECEIVE); } number_of_orfs++; } /* Total Number of ORFs. */ stream_putc_at (s, numberp, number_of_orfs); /* Total ORF Len. */ orf_len = stream_get_putp (s) - orfp - 1; stream_putc_at (s, orfp, orf_len); /* Total Capability Len. */ cap_len = stream_get_putp (s) - capp - 1; stream_putc_at (s, capp, cap_len);}/* Fill in capability open option to the packet. */voidbgp_open_capability (struct stream *s, struct peer *peer){ u_char len; unsigned long cp; afi_t afi; safi_t safi; /* Remember current pointer for Opt Parm Len. */ cp = stream_get_putp (s); /* Opt Parm Len. */ stream_putc (s, 0); /* Do not send capability. */ if (! CHECK_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN) || CHECK_FLAG (peer->flags, PEER_FLAG_DONT_CAPABILITY)) return; /* IPv4 unicast. */ if (peer->afc[AFI_IP][SAFI_UNICAST]) { peer->afc_adv[AFI_IP][SAFI_UNICAST] = 1; stream_putc (s, BGP_OPEN_OPT_CAP); stream_putc (s, CAPABILITY_CODE_MP_LEN + 2); stream_putc (s, CAPABILITY_CODE_MP); stream_putc (s, CAPABILITY_CODE_MP_LEN); stream_putw (s, AFI_IP); stream_putc (s, 0); stream_putc (s, SAFI_UNICAST); } /* IPv4 multicast. */ if (peer->afc[AFI_IP][SAFI_MULTICAST]) { peer->afc_adv[AFI_IP][SAFI_MULTICAST] = 1; stream_putc (s, BGP_OPEN_OPT_CAP); stream_putc (s, CAPABILITY_CODE_MP_LEN + 2); stream_putc (s, CAPABILITY_CODE_MP); stream_putc (s, CAPABILITY_CODE_MP_LEN); stream_putw (s, AFI_IP); stream_putc (s, 0); stream_putc (s, SAFI_MULTICAST); } /* IPv4 VPN */ if (peer->afc[AFI_IP][SAFI_MPLS_VPN]) { peer->afc_adv[AFI_IP][SAFI_MPLS_VPN] = 1; stream_putc (s, BGP_OPEN_OPT_CAP); stream_putc (s, CAPABILITY_CODE_MP_LEN + 2); stream_putc (s, CAPABILITY_CODE_MP); stream_putc (s, CAPABILITY_CODE_MP_LEN); stream_putw (s, AFI_IP); stream_putc (s, 0); stream_putc (s, BGP_SAFI_VPNV4); }#ifdef HAVE_IPV6 /* IPv6 unicast. */ if (peer->afc[AFI_IP6][SAFI_UNICAST]) { peer->afc_adv[AFI_IP6][SAFI_UNICAST] = 1; stream_putc (s, BGP_OPEN_OPT_CAP); stream_putc (s, CAPABILITY_CODE_MP_LEN + 2); stream_putc (s, CAPABILITY_CODE_MP); stream_putc (s, CAPABILITY_CODE_MP_LEN); stream_putw (s, AFI_IP6); stream_putc (s, 0); stream_putc (s, SAFI_UNICAST); } /* IPv6 multicast. */ if (peer->afc[AFI_IP6][SAFI_MULTICAST]) { peer->afc_adv[AFI_IP6][SAFI_MULTICAST] = 1; stream_putc (s, BGP_OPEN_OPT_CAP); stream_putc (s, CAPABILITY_CODE_MP_LEN + 2); stream_putc (s, CAPABILITY_CODE_MP); stream_putc (s, CAPABILITY_CODE_MP_LEN); stream_putw (s, AFI_IP6); stream_putc (s, 0); stream_putc (s, SAFI_MULTICAST); }#endif /* HAVE_IPV6 */ /* Route refresh. */ SET_FLAG (peer->cap, PEER_CAP_REFRESH_ADV); stream_putc (s, BGP_OPEN_OPT_CAP); stream_putc (s, CAPABILITY_CODE_REFRESH_LEN + 2); stream_putc (s, CAPABILITY_CODE_REFRESH_OLD); stream_putc (s, CAPABILITY_CODE_REFRESH_LEN); stream_putc (s, BGP_OPEN_OPT_CAP); stream_putc (s, CAPABILITY_CODE_REFRESH_LEN + 2); stream_putc (s, CAPABILITY_CODE_REFRESH); stream_putc (s, CAPABILITY_CODE_REFRESH_LEN); /* ORF capability. */ for (afi = AFI_IP ; afi < AFI_MAX ; afi++) for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++) if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM) || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM)) { bgp_open_capability_orf (s, peer, afi, safi, CAPABILITY_CODE_ORF_OLD); bgp_open_capability_orf (s, peer, afi, safi, CAPABILITY_CODE_ORF); } /* Dynamic capability. */ if (CHECK_FLAG (peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY)) { SET_FLAG (peer->cap, PEER_CAP_DYNAMIC_ADV); stream_putc (s, BGP_OPEN_OPT_CAP); stream_putc (s, CAPABILITY_CODE_DYNAMIC_LEN + 2); stream_putc (s, CAPABILITY_CODE_DYNAMIC); stream_putc (s, CAPABILITY_CODE_DYNAMIC_LEN); } /* Graceful restart capability */ if (bgp_flag_check (peer->bgp, BGP_FLAG_GRACEFUL_RESTART)) { SET_FLAG (peer->cap, PEER_CAP_RESTART_ADV); stream_putc (s, BGP_OPEN_OPT_CAP); stream_putc (s, CAPABILITY_CODE_RESTART_LEN + 2); stream_putc (s, CAPABILITY_CODE_RESTART); stream_putc (s, CAPABILITY_CODE_RESTART_LEN); stream_putw (s, peer->bgp->restart_time); } /* Total Opt Parm Len. */ len = stream_get_putp (s) - cp - 1; stream_putc_at (s, cp, len);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -