summaryrefslogtreecommitdiff
path: root/proto/bgp/bgp.c
diff options
context:
space:
mode:
Diffstat (limited to 'proto/bgp/bgp.c')
-rw-r--r--proto/bgp/bgp.c84
1 files changed, 58 insertions, 26 deletions
diff --git a/proto/bgp/bgp.c b/proto/bgp/bgp.c
index c52e8bd0..6007b3cc 100644
--- a/proto/bgp/bgp.c
+++ b/proto/bgp/bgp.c
@@ -22,7 +22,6 @@ static sock *bgp_listen_sk; /* Global listening socket */
static int bgp_counter; /* Number of protocol instances using the listening socket */
static list bgp_list; /* List of active BGP instances */
-static void bgp_close_conn(struct bgp_conn *conn);
static void bgp_connect(struct bgp_proto *p);
static void bgp_setup_sk(struct bgp_proto *p, struct bgp_conn *conn, sock *s);
@@ -63,19 +62,20 @@ bgp_close(struct bgp_proto *p)
/* FIXME: Automatic restart after errors? */
}
-static void
+static void /* FIXME: Nobody uses */
bgp_reset(struct bgp_proto *p)
{
bgp_close(p);
proto_notify_state(&p->p, PS_DOWN);
}
-static void
+void
bgp_start_timer(timer *t, int value)
{
/* FIXME: Randomize properly */
/* FIXME: Check if anybody uses tm_start directly */
- tm_start(t, value);
+ if (value)
+ tm_start(t, value);
}
static void
@@ -86,36 +86,34 @@ bgp_send_open(struct bgp_conn *conn)
tm_stop(conn->connect_retry_timer);
bgp_schedule_packet(conn, PKT_OPEN);
conn->state = BS_OPENSENT;
+ bgp_start_timer(conn->hold_timer, conn->bgp->cf->initial_hold_time);
}
-static int
-bgp_connected(sock *sk, int dummy)
+static void
+bgp_connected(sock *sk)
{
struct bgp_conn *conn = sk->data;
DBG("BGP: Connected\n");
bgp_send_open(conn);
- return 0;
}
static void
bgp_connect_timeout(timer *t)
{
- struct bgp_proto *p = t->data;
- struct bgp_conn *conn = &p->conn;
+ struct bgp_conn *conn = t->data;
DBG("BGP: Connect timeout, retrying\n");
bgp_close_conn(conn);
- bgp_connect(p);
+ bgp_connect(conn->bgp);
}
static void
-bgp_err(sock *sk, int err)
+bgp_sock_err(sock *sk, int err)
{
struct bgp_conn *conn = sk->data;
DBG("BGP: Socket error %d in state %d\n", err, conn->state);
- sk->type = SK_DELETED; /* FIXME: Need to do this always! */
switch (conn->state)
{
case BS_CONNECT:
@@ -125,10 +123,11 @@ bgp_err(sock *sk, int err)
break;
case BS_OPENCONFIRM:
case BS_ESTABLISHED:
- /* FIXME: Should close the connection and go to Idle state */
+ /* FIXME */
default:
- bug("bgp_err called in invalid state %d", conn->state);
+ bug("bgp_sock_err called in invalid state %d", conn->state);
}
+ bgp_close_conn(conn);
}
static int
@@ -159,6 +158,24 @@ bgp_incoming_connection(sock *sk, int dummy)
}
static void
+bgp_hold_timeout(timer *t)
+{
+ struct bgp_conn *conn = t->data;
+
+ DBG("BGP: Hold timeout, closing connection\n"); /* FIXME: Check states? */
+ bgp_error(conn, 4, 0, 0, 0);
+}
+
+static void
+bgp_keepalive_timeout(timer *t)
+{
+ struct bgp_conn *conn = t->data;
+
+ DBG("BGP: Keepalive timer\n");
+ bgp_schedule_packet(conn, PKT_KEEPALIVE);
+}
+
+static void
bgp_setup_sk(struct bgp_proto *p, struct bgp_conn *conn, sock *s)
{
timer *t;
@@ -168,7 +185,7 @@ bgp_setup_sk(struct bgp_proto *p, struct bgp_conn *conn, sock *s)
s->rbsize = BGP_RX_BUFFER_SIZE;
s->tbsize = BGP_TX_BUFFER_SIZE;
s->tx_hook = bgp_tx;
- s->err_hook = bgp_err;
+ s->err_hook = bgp_sock_err;
s->tos = IP_PREC_INTERNET_CONTROL;
conn->bgp = p;
@@ -177,27 +194,27 @@ bgp_setup_sk(struct bgp_proto *p, struct bgp_conn *conn, sock *s)
t = conn->connect_retry_timer = tm_new(p->p.pool);
t->hook = bgp_connect_timeout;
- t->data = p;
-#if 0
- t = p->hold_timer = tm_new(p->p.pool);
+ t->data = conn;
+ t = conn->hold_timer = tm_new(p->p.pool);
t->hook = bgp_hold_timeout;
- t->data = p;
- t = p->keepalive_timer = tm_new(p->p.pool);
+ t->data = conn;
+ t = conn->keepalive_timer = tm_new(p->p.pool);
t->hook = bgp_keepalive_timeout;
- t->data = p;
-#endif
+ t->data = conn;
}
-static void
+void
bgp_close_conn(struct bgp_conn *conn)
{
+ DBG("BGP: Closing connection\n");
+ conn->packets_to_send = 0;
rfree(conn->connect_retry_timer);
conn->connect_retry_timer = NULL;
rfree(conn->keepalive_timer);
conn->keepalive_timer = NULL;
rfree(conn->hold_timer);
conn->hold_timer = NULL;
- rfree(conn->sk);
+ sk_close(conn->sk);
conn->sk = NULL;
conn->state = BS_IDLE;
}
@@ -217,12 +234,12 @@ bgp_connect(struct bgp_proto *p) /* Enter Connect state and start establishing c
s->sport = /* FIXME */
#endif
s->dport = BGP_PORT;
- s->rx_hook = bgp_connected;
bgp_setup_sk(p, conn, s);
+ s->tx_hook = bgp_connected;
conn->state = BS_CONNECT;
if (sk_open(s))
{
- bgp_err(s, 0);
+ bgp_sock_err(s, 0);
return;
}
DBG("BGP: Waiting for connect success\n");
@@ -295,6 +312,21 @@ bgp_shutdown(struct proto *P)
}
void
+bgp_error(struct bgp_conn *c, unsigned code, unsigned subcode, unsigned data, unsigned len)
+{
+ DBG("BGP: Error %d,%d,%d,%d\n", code, subcode, data, len); /* FIXME: Better messages */
+ if (c->error_flag)
+ return;
+ c->error_flag = 1;
+ c->notify_code = code;
+ c->notify_subcode = subcode;
+ c->notify_arg = data;
+ c->notify_arg_size = len;
+ proto_notify_state(&c->bgp->p, PS_STOP);
+ bgp_schedule_packet(c, PKT_NOTIFICATION);
+}
+
+void
bgp_check(struct bgp_config *c)
{
if (!c->local_as)