summaryrefslogtreecommitdiffstats
path: root/proto/bgp/packets.c
diff options
context:
space:
mode:
Diffstat (limited to 'proto/bgp/packets.c')
-rw-r--r--proto/bgp/packets.c51
1 files changed, 33 insertions, 18 deletions
diff --git a/proto/bgp/packets.c b/proto/bgp/packets.c
index 27adc16..ae4906e 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