📄 bgp.c
字号:
* DESCRIPTION: process received OPEN msg. */voidbgp_process_open(struct rpcb *bnp){ int i, k; /* tracer */ u_int16_t rcvas, rcvht, negoht; u_int32_t rcvid; /* net-order */ u_int8_t optlen; struct rpcb *ep = NULL; /* eBGP */ struct rpcb *ip = NULL; /* iBGP */ struct rpcb *p = NULL; struct bgphdr *bh; struct timeval t; /* calculation */ task *tsk; extern task *taskhead; bh = (struct bgphdr *)bnp->rp_inpkt; BGP_MARKER_CHECK; if (bnp->rp_state != BGPSTATE_OPENSENT) { bgp_notify(bnp, BGP_ERR_FSM, BGP_ERR_UNSPEC, 0, NULL); return; } /*** OPEN Message Format ***/ i = BGP_HEADER_LEN; /* Version (1-octet) */ /* If the version number contained in the Version field of the received OPEN message is not supported, then the Error Subcode is set to Unsupported Version Number. The Data field is a 2-octet unsigned integer, which indicates the largest locally supported version number less than the version the remote BGP peer bid (as indicated in the received OPEN message). */ if (bnp->rp_inpkt[i++] != BGP_VERSION_4) { u_int16_t version = BGP_VERSION_4; version = htons(version); bgp_notify(bnp, BGP_ERR_OPEN, BGP_ERROPN_VERSION, 2, (byte *)&version); return; } /* My Autonomous System (2-octet) */ rcvas = ntohs(*(u_short *)&bnp->rp_inpkt[i]); i += 2; if ((logflags & LOG_BGPINPUT)) syslog(LOG_DEBUG, "BGP+ RECV\t\tAutonomous System = %d", rcvas); /* Hold Time (2-octet) */ rcvht = ntohs(*(u_short *)&bnp->rp_inpkt[i]); if ( !HOLDTIME_ISCORRECT(rcvht) ) { bgp_notify(bnp, BGP_ERR_OPEN, BGP_ERROPN_BADHOLDTIME, 0, NULL); return; }; i += 2; /* BGP Identifier (4-octet) */ rcvid = *(u_long *)&bnp->rp_inpkt[i]; if ((logflags & LOG_BGPINPUT)) syslog(LOG_DEBUG, "BGP+ RECV\t\tBGP Identifier = %s", inet_ntoa(*(struct in_addr *)&rcvid)); if (rcvid == 0) { bgp_notify(bnp, BGP_ERR_OPEN, BGP_ERROPN_BGPID, 0, NULL);/* Bad BGPID */ return; }; i += 4; /* If the Autonomous System field of the OPEN message is unacceptable, then the Error Subcode is set to Bad Peer AS. The determination of acceptable Autonomous System numbers is outside the scope of this protocol. (See section 6.2 of [I-D bgp4].) */ if (rcvas != my_as_number) { /* EGP ? */ if (bnp->rp_mode & BGPO_PASSIVE) { if ((ep = find_peer_by_as(rcvas))) { /* same AS */ bnp->rp_as = rcvas; /* <<--- important !!! */ bnp->rp_id = rcvid; bnp->rp_adj_ribs_out = ep->rp_adj_ribs_out; /* fixedly */ bnp->rp_ebgp_as_prepends = ep->rp_ebgp_as_prepends; bnp->rp_prefer = ep->rp_prefer; bnp->rp_mode |= (ep->rp_mode & BGPO_EBGPSTATIC); /* copy EBGP static */ } else { bgp_notify(bnp, BGP_ERR_OPEN, BGP_ERROPN_AS, 0, NULL);/*Bad Peer AS*/ return; } } if (!(bnp->rp_mode & BGPO_PASSIVE)) { if (bnp->rp_as != rcvas) { bgp_notify(bnp, BGP_ERR_OPEN, BGP_ERROPN_AS, 0, NULL);/*Bad Peer AS*/ return; } if (bnp->rp_id == 0) bnp->rp_id = rcvid; } } /* end of EGP */ if (rcvas == my_as_number) { /* IGP */ if (bnp->rp_mode & BGPO_PASSIVE) { struct in6_addr llhackaddr; if (!IN6_IS_ADDR_UNSPECIFIED(&bnp->rp_laddr) && bnp->rp_ife) { llhackaddr = bnp->rp_laddr; SET_IN6_LINKLOCAL_IFINDEX(&llhackaddr, bnp->rp_ife->ifi_ifn->if_index); } if ((ip = rpcblookup(bgb, rcvid)) || /* iw97 */ (ip = find_apeer_by_addr(&bnp->rp_gaddr)) || /* (1998/05/25) */ (ip = find_apeer_by_addr(&llhackaddr))) { /* (1998/05/25) */ bnp->rp_as = rcvas; bnp->rp_id = rcvid; bnp->rp_mode |= BGPO_IGP; bnp->rp_mode |= (ip->rp_mode & BGPO_IBGPSTATIC); /* copy IBGP static */ bnp->rp_adj_ribs_out = ip->rp_adj_ribs_out; /* fixedly */ } else { bgp_notify(bnp, BGP_ERR_OPEN, BGP_ERROPN_BGPID, 0, NULL);/*Bad BGPID*/ return; } } if (!(bnp->rp_mode & BGPO_PASSIVE)) { if ((bnp->rp_mode & BGPO_IDSTATIC) && /* BGP-ID wasn't configured */ (bnp->rp_id != rcvid)) { bgp_notify(bnp, BGP_ERR_OPEN, BGP_ERROPN_BGPID, 0, NULL);/*Bad BGPID*/ return; } else bnp->rp_id = rcvid; } } /* end of IGP */ /* Opt Parm Len (1-octet) */ optlen = bnp->rp_inpkt[i++]; k = i; /* Optional Parameters (length is specified by "Opt Parm Len") */ while (i < k + optlen) { struct bgpoptparm *bop; bop = (struct bgpoptparm *)&bnp->rp_inpkt[i]; switch(bop->bop_type) { case BGP_OPTPARAM_AUTH: i += sizeof(struct bgpoptparm) + bop->bop_len; break; /* NO authentification is checked. */ case BGP_OPTPARAM_CAPA: i += sizeof(struct bgpoptparm) + bop->bop_len; break; default: /* If one of the Optional Parameters in the OPEN message is not recognized, then the Error Subcode is set to Unsupported Optional Parameters. [BGP-4] */ bgp_notify(bnp, BGP_ERR_OPEN, BGP_ERROPN_OPTION, 0, NULL); return; break; } } if (i != ntohs(bh->bh_length)) { bgp_notify(bnp, BGP_ERR_HEADER, BGP_ERRHDR_LENGTH, 0, NULL); return; } p = bnp; /* "p" initial */ if (ep) { if (ep->rp_id == bnp->rp_id) switch (ep->rp_state) { case BGPSTATE_OPENCONFIRM: case BGPSTATE_OPENSENT: p = collision_resolv(bnp, ep); if (p != bnp) /* Local "p" is prefered to new "bnp". And, */ return; /* current "bnp" was deleted by collision_resolv() */ break; case BGPSTATE_ESTABLISHED: syslog(LOG_NOTICE, "<bgp_process_open>: Already established peer exists"); bgp_notify(bnp, BGP_CEASE, BGP_ERR_UNSPEC, 0, NULL); return; case BGPSTATE_IDLE: case BGPSTATE_CONNECT: case BGPSTATE_ACTIVE: /* collision cannot be detected in these states */ p = bnp; /* Now "p" is ... */ break; default : fatalx("<bgp_process_open>: not implmntd."); }; } else { if (ip) { switch (ip->rp_state) { case BGPSTATE_OPENCONFIRM: case BGPSTATE_OPENSENT: p = collision_resolv(bnp, ip); if (p != bnp) /* Local "p" is prefered to new "bnp". And, */ return; /* current "bnp" was deleted by collision_resolv() */ break; case BGPSTATE_ESTABLISHED: syslog(LOG_NOTICE, "<bgp_process_open>: Already established peer exists"); bgp_notify(bnp, BGP_CEASE, BGP_ERR_UNSPEC, 0, NULL); return; case BGPSTATE_IDLE: case BGPSTATE_CONNECT: case BGPSTATE_ACTIVE: /* collision cannot be detected in these states */ p = bnp; /* Now "p" is ... */ break; default : fatalx("<bgp_process_open>: not implmntd."); }; } else p = bnp; } /* End of if (ep) */ /** HoldTime negotiation **/ t.tv_sec = rcvht; t.tv_usec = 0; /* If the negotiated Hold Time value is zero, then the Hold Time timer and KeepAlive timers are not started. */ if (rcvht == 0) { taskhead = task_remove(p->rp_hold_timer); p->rp_hold_timer = NULL; } else { if (sub_timeval(&t ,&p->rp_hold_timer->tsk_timefull) > 0) { p->rp_hold_timer->tsk_timefull.tv_sec = rcvht; p->rp_hold_timer->tsk_timefull.tv_usec = 0; task_timer_update(p->rp_hold_timer); } } /* NOTE: If the negotiated Hold Time is 0, then system doesn't send/receive any KeepAlives */ if ((negoht = p->rp_hold_timer->tsk_timefull.tv_sec) == 0) { /* KeepAlive timer not started */ } else { MALLOC(tsk, task); if (taskhead) { insque(tsk, taskhead); /* will be sorted later by task_timer_update() */ } else { tsk->tsk_next = tsk; tsk->tsk_prev = tsk; taskhead = tsk; } tsk->tsk_bgp = p; tsk->tsk_timename = BGP_KEEPALIVE_TIMER; p->rp_keepalive_timer = tsk; /* A reasonable maximum time between KEEPALIVE messages would be one third of the Hold Time interval. KEEPALIVE messages MUST NOT be sent more frequently than one per second. [Page.17]*/ tsk->tsk_timefull.tv_sec = (negoht/3 < 1) ? 1 : negoht/3;/* sec. */ tsk->tsk_timefull.tv_usec = 0; } bgp_send_keepalive(p); /*** Finally, the state is changed to OpenConfirm. ***/ p->rp_state = BGPSTATE_OPENCONFIRM; if ((logflags & LOG_BGPSTATE)) syslog(LOG_NOTICE, "<%s>: BGP state shift[%s] peer: %s", __FUNCTION__, bgp_statestr[p->rp_state], bgp_peerstr(p));}/* * bgp_process_update() * process received UPDATE msg. */voidbgp_process_update(struct rpcb *bnp){ int i,j,k; /* tracer */ struct bgphdr *bh; u_int16_t length; /* Length */ int pa_p; /* start point of Path Attributes */ u_int16_t urlen; /* Unfeasible Routes Length */ u_int16_t tpalen; /* Total Path Attributes Length */ u_int16_t atrlen; /* the length of the attribute */ u_int16_t atrdatalen; /* the length of the attribute data */ byte origin; /* ORIGIN */ struct aspath *asp; /* AS_PATH */ u_int32_t med; /* MULTI_EXIT_DISC (net-order) */ u_int32_t localpref; /* LOCAL_PREF (net-order) */ int aggregated; /* logical */ u_int32_t originatorid;/* [rfc1966] (net-order) */ struct clstrlist *cll; /* [rfc1966] */ struct optatr *optatr = NULL; /* list of unrecognized attributes */ u_int8_t nhnalen; /* Next Hop Network Addresses Length (+) */ struct in6_addr gnhaddr; /* "nexthop" address (+) */ struct in6_addr lnhaddr; /* "nexthop" address (+) */ u_int8_t snpanum; /* Number of SNPAs (+) */ u_int8_t snpalen; /* Length of a SNPA (+) */#ifdef DRAFT_IETF_00 u_int16_t nlrilen; /* NLRI Length (+) */#endif u_int16_t v4nlrilen; /* "traditional" NLRI Length */ /* routes that may be installed and/or redistributed: */ struct rt_entry uprtehead = {&uprtehead, &uprtehead}; /* routes that should be withdrawn: */ struct rt_entry wdrtehead = {&wdrtehead, &wdrtehead}; struct rt_entry *uprte; struct rt_entry *wdrte; char in6txt[INET6_ADDRSTRLEN]; extern struct ifinfo *ifentry; extern struct rt_entry *aggregations; extern char *pa_typestr[], *origin_str[]; bitstr_t bit_decl(parsedflag, PA4_MAXTYPE); bit_nclear(parsedflag, 0, PA4_MAXTYPE); origin = PATH_ORG_XX; /* "incomplete" */ med = aggregated = originatorid = v4nlrilen = 0; localpref = bnp->rp_prefer; /* default */ asp = NULL; cll = NULL; memset(&gnhaddr, 0, sizeof(gnhaddr)); memset(&lnhaddr, 0, sizeof(lnhaddr)); memset(in6txt, 0, INET6_ADDRSTRLEN); bh = (struct bgphdr *)bnp->rp_inpkt; /* if the OPEN message carries no Authentication Information (as an Optional Parameter), then the Marker must be all ones. */ BGP_MARKER_CHECK; /* Length (2-octet) */ /* was checked partially */ length = ntohs(bh->bh_length); if (bnp->rp_state != BGPSTATE_ESTABLISHED) { bgp_notify(bnp, BGP_ERR_FSM, BGP_ERR_UNSPEC, 0, NULL); return; } /* Update Hold Timer */ task_timer_update(bnp->rp_hold_timer); i = BGP_HEADER_LEN; /*** UPDATE Message Format ***/ /* Unfeasible Routes Length (2 octets) */ urlen = ntohs(*(u_short *)&bnp->rp_inpkt[i]); i += 2 ; /* Total Path Attribute Length (2 octets) */ tpalen = ntohs(*(u_short *)&bnp->rp_inpkt[i + urlen]); if (urlen + tpalen + 23 > length ) { /* Malformed Attribute List */ bgp_notify(bnp, BGP_ERR_UPDATE, BGP_ERRUPD_ATTRLIST, 0, NULL); return; } i += urlen; /* IPv6 (BGP4+) ignores this. */ i += 2; /* Total Path Attribute Length (2 octet) */ /* Path Attributes (variable) */ pa_p = i; while (pa_p + tpalen > i) { /* Malformation is detected ASAP */ int error; IFLOG(LOG_BGPINPUT) { struct in_addr peerid; peerid = *(struct in_addr *)&bnp->rp_id; if (PA4_TYPE_VALID(bnp->rp_inpkt[i + 1])) syslog(LOG_DEBUG, "BGP+ RECV flags 0x%x code %s(%d) peerid %s:\\", bnp->rp_inpkt[i], pa_typestr[bnp->rp_inpkt[i + 1]], bnp->rp_inpkt[i + 1], inet_ntoa(peerid)); } #define PA4_TYPE_CODE_CHECK \ { i++;\ if (bit_test(parsedflag, bnp->rp_inpkt[i]))\ { bgp_notify(bnp, BGP_ERR_UPDATE, BGP_ERRUPD_ATTRLIST, 0, NULL);\ goto done;\ }\ bit_set(parsedflag, bnp->rp_inpkt[i]);\ i++;\ }#define PA4_LEN_PARSE \ { if (bnp->rp_inpkt[k] & PA_FLAG_EXTLEN) {\ atrdatalen = ntohs(*(u_int16_t *)&bnp->rp_inpkt[i]);\ i += 2;\ } else {\ atrdatalen = bnp->rp_inpkt[i];\ i += 1;\ }\ atrlen = i + atrdatalen - k;\ if (i + atrdatalen > pa_p + tpalen) {\ syslog(LOG_ERR, "<%s>: invalid attribute length(%d) from %s\n",\ __FUNCTION__, atrdatalen, bgp_peerstr(bnp));\ bgp_notify(bnp, BGP_ERR_UPDATE, BGP_ERRUPD_LENGTH,\ i - k, &bnp->rp_inpkt[k]);\ goto done;\ }\ } k = i; switch(bnp->rp_inpkt[i + 1]) { case PA4_TYPE_ORIGIN: /* ORIGIN (Type Code 1) well-known mandatory */ PA4_TYPE_CODE_CHECK; PA4_LEN_PARSE; /* T */ if ( (bnp->rp_inpkt[k] & PA_FLAG_OPT) || !(bnp->rp_inpkt[k] & PA_FLAG_TRANS) || (bnp->rp_inpkt[k] & PA_FLAG_PARTIAL)) { /* Attribute Flags Error */ bgp_notify(bnp, BGP_ERR_UPDATE, BGP_ERRUPD_FLAGS, atrlen, &bnp->rp_inpkt[k]); goto done; } if (atrdatalen != PA4_LEN_ORIGIN) { /* Attribute Length Error */ bgp_notify(bnp, BGP_ERR_UPDATE, BGP_ERRUPD_LENGTH, atrlen, &bnp->rp_inpkt[k]);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -