diff options
Diffstat (limited to 'proto/bgp/packets.c')
-rw-r--r-- | proto/bgp/packets.c | 51 |
1 files changed, 33 insertions, 18 deletions
diff --git a/proto/bgp/packets.c b/proto/bgp/packets.c index 27adc166..ae4906ee 100644 --- a/proto/bgp/packets.c +++ b/proto/bgp/packets.c @@ -619,14 +619,14 @@ bgp_rx_open(struct bgp_conn *conn, byte *pkt, int len) { /* Should close the other connection */ BGP_TRACE(D_EVENTS, "Connection collision, giving up the other connection"); - bgp_error(other, 6, 0, NULL, 0); + bgp_error(other, 6, 7, NULL, 0); break; } /* Fall thru */ case BS_ESTABLISHED: /* Should close this connection */ BGP_TRACE(D_EVENTS, "Connection collision, giving up this connection"); - bgp_error(conn, 6, 0, NULL, 0); + bgp_error(conn, 6, 7, NULL, 0); return; default: bug("bgp_rx_open: Unknown state"); @@ -705,7 +705,7 @@ bgp_do_rx_update(struct bgp_conn *conn, DECODE_PREFIX(withdrawn, withdrawn_len); DBG("Withdraw %I/%d\n", prefix, pxlen); if (n = net_find(p->p.table, prefix, pxlen)) - rte_update(p->p.table, n, &p->p, NULL); + rte_update(p->p.table, n, &p->p, &p->p, NULL); } if (!attr_len && !nlri_len) /* shortcut */ @@ -724,14 +724,20 @@ bgp_do_rx_update(struct bgp_conn *conn, n = net_get(p->p.table, prefix, pxlen); e->net = n; e->pflags = 0; - rte_update(p->p.table, n, &p->p, e); + rte_update(p->p.table, n, &p->p, &p->p, e); + if (bgp_apply_limits(p) < 0) + goto bad2; } + rta_free(a); } -bad: + + return; + + bad: + bgp_error(conn, 3, err, NULL, 0); + bad2: if (a) rta_free(a); - if (err) - bgp_error(conn, 3, err, NULL, 0); return; } @@ -783,7 +789,7 @@ bgp_do_rx_update(struct bgp_conn *conn, DECODE_PREFIX(x, len); DBG("Withdraw %I/%d\n", prefix, pxlen); if (n = net_find(p->p.table, prefix, pxlen)) - rte_update(p->p.table, n, &p->p, NULL); + rte_update(p->p.table, n, &p->p, &p->p, NULL); } } @@ -824,7 +830,9 @@ bgp_do_rx_update(struct bgp_conn *conn, n = net_get(p->p.table, prefix, pxlen); e->net = n; e->pflags = 0; - rte_update(p->p.table, n, &p->p, e); + rte_update(p->p.table, n, &p->p, &p->p, e); + if (bgp_apply_limits(p) < 0) + goto bad2; } rta_free(a); } @@ -832,8 +840,9 @@ bgp_do_rx_update(struct bgp_conn *conn, return; -bad: + bad: bgp_error(conn, 3, 9, start, len0); + bad2: if (a) rta_free(a); return; @@ -948,14 +957,15 @@ bgp_error_dsc(byte *buff, unsigned code, unsigned subcode) } void -bgp_log_error(struct bgp_proto *p, char *msg, unsigned code, unsigned subcode, byte *data, unsigned len) +bgp_log_error(struct bgp_proto *p, u8 class, char *msg, unsigned code, unsigned subcode, byte *data, unsigned len) { const byte *name; byte namebuf[32]; byte *t, argbuf[36]; unsigned i; - if (code == 6 && !subcode) /* Don't report Cease messages */ + /* Don't report Cease messages generated by myself */ + if (code == 6 && class == BE_BGP_TX) return; name = bgp_error_dsc(namebuf, code, subcode); @@ -985,10 +995,10 @@ bgp_rx_notification(struct bgp_conn *conn, byte *pkt, int len) unsigned code = pkt[19]; unsigned subcode = pkt[20]; - int delay = 1; + int err = (code != 6); - bgp_log_error(conn->bgp, "Received error notification", code, subcode, pkt+21, len-21); - bgp_store_error(conn->bgp, conn, BE_BGP_RX, (code << 16) | subcode); + bgp_log_error(p, BE_BGP_RX, "Received", code, subcode, pkt+21, len-21); + bgp_store_error(p, conn, BE_BGP_RX, (code << 16) | subcode); #ifndef IPV6 if ((code == 2) && ((subcode == 4) || (subcode == 7)) @@ -1005,14 +1015,19 @@ bgp_rx_notification(struct bgp_conn *conn, byte *pkt, int len) { /* We try connect without capabilities */ log(L_WARN "%s: Capability related error received, retry with capabilities disabled", p->p.name); - conn->bgp->start_state = BSS_CONNECT_NOCAP; - delay = 0; + p->start_state = BSS_CONNECT_NOCAP; + err = 0; } #endif - if (delay) bgp_update_startup_delay(conn->bgp, conn, code, subcode); bgp_conn_enter_close_state(conn); bgp_schedule_packet(conn, PKT_SCHEDULE_CLOSE); + + if (err) + { + bgp_update_startup_delay(p); + bgp_stop(p, 0); + } } static void |