static void bgp_active(struct bgp_proto *p) { int delay = MAX(1, p->cf->start_delay_time); struct bgp_conn *conn = &p->outgoing_conn; BGP_TRACE(D_EVENTS, "Connect delayed by %d seconds", delay); bgp_setup_conn(p, conn); bgp_conn_set_state(conn, BS_ACTIVE); bgp_start_timer(conn->connect_retry_timer, delay); }
/** * bgp_incoming_connection - handle an incoming connection * @sk: TCP socket * @dummy: unused * * This function serves as a socket hook for accepting of new BGP * connections. It searches a BGP instance corresponding to the peer * which has connected and if such an instance exists, it creates a * &bgp_conn structure, attaches it to the instance and either sends * an Open message or (if there already is an active connection) it * closes the new connection by sending a Notification message. */ static int bgp_incoming_connection(sock *sk, int dummy UNUSED) { struct proto_config *pc; DBG("BGP: Incoming connection from %I port %d\n", sk->daddr, sk->dport); WALK_LIST(pc, config->protos) if (pc->protocol == &proto_bgp && pc->proto) { struct bgp_proto *p = (struct bgp_proto *) pc->proto; if (ipa_equal(p->cf->remote_ip, sk->daddr) && (!ipa_has_link_scope(sk->daddr) || (p->cf->iface == sk->iface))) { /* We are in proper state and there is no other incoming connection */ int acc = (p->p.proto_state == PS_START || p->p.proto_state == PS_UP) && (p->start_state >= BSS_CONNECT) && (!p->incoming_conn.sk); if (p->conn && (p->conn->state == BS_ESTABLISHED) && p->gr_ready) { bgp_store_error(p, NULL, BE_MISC, BEM_GRACEFUL_RESTART); bgp_handle_graceful_restart(p); bgp_conn_enter_idle_state(p->conn); acc = 1; } BGP_TRACE(D_EVENTS, "Incoming connection from %I%J (port %d) %s", sk->daddr, ipa_has_link_scope(sk->daddr) ? sk->iface : NULL, sk->dport, acc ? "accepted" : "rejected"); if (!acc) goto reject; int hops = p->cf->multihop ? : 1; if (sk_set_ttl(sk, p->cf->ttl_security ? 255 : hops) < 0) goto err; if (p->cf->ttl_security) if (sk_set_min_ttl(sk, 256 - hops) < 0) goto err; bgp_setup_conn(p, &p->incoming_conn); bgp_setup_sk(&p->incoming_conn, sk); bgp_send_open(&p->incoming_conn); return 0; err: sk_log_error(sk, p->p.name); log(L_ERR "%s: Incoming connection aborted", p->p.name); rfree(sk); return 0; } }
/** * bgp_connect - initiate an outgoing connection * @p: BGP instance * * The bgp_connect() function creates a new &bgp_conn and initiates * a TCP connection to the peer. The rest of connection setup is governed * by the BGP state machine as described in the standard. */ static void bgp_connect(struct bgp_proto *p) /* Enter Connect state and start establishing connection */ { sock *s; struct bgp_conn *conn = &p->outgoing_conn; int hops = p->cf->multihop ? : 1; DBG("BGP: Connecting\n"); s = sk_new(p->p.pool); s->type = SK_TCP_ACTIVE; s->saddr = p->source_addr; s->daddr = p->cf->remote_ip; s->iface = p->neigh ? p->neigh->iface : NULL; s->dport = BGP_PORT; s->ttl = p->cf->ttl_security ? 255 : hops; s->rbsize = BGP_RX_BUFFER_SIZE; s->tbsize = BGP_TX_BUFFER_SIZE; s->tos = IP_PREC_INTERNET_CONTROL; s->password = p->cf->password; s->tx_hook = bgp_connected; BGP_TRACE(D_EVENTS, "Connecting to %I%J from local address %I%J", s->daddr, p->cf->iface, s->saddr, ipa_has_link_scope(s->saddr) ? s->iface : NULL); bgp_setup_conn(p, conn); bgp_setup_sk(conn, s); bgp_conn_set_state(conn, BS_CONNECT); if (sk_open(s) < 0) { bgp_sock_err(s, 0); return; } /* Set minimal receive TTL if needed */ if (p->cf->ttl_security) { DBG("Setting minimum received TTL to %d", 256 - hops); if (sk_set_min_ttl(s, 256 - hops) < 0) { log(L_ERR "TTL security configuration failed, closing session"); bgp_sock_err(s, 0); return; } } DBG("BGP: Waiting for connect success\n"); bgp_start_timer(conn->connect_retry_timer, p->cf->connect_retry_time); }
/** * bgp_incoming_connection - handle an incoming connection * @sk: TCP socket * @dummy: unused * * This function serves as a socket hook for accepting of new BGP * connections. It searches a BGP instance corresponding to the peer * which has connected and if such an instance exists, it creates a * &bgp_conn structure, attaches it to the instance and either sends * an Open message or (if there already is an active connection) it * closes the new connection by sending a Notification message. */ static int bgp_incoming_connection(sock *sk, int dummy UNUSED) { struct proto_config *pc; DBG("BGP: Incoming connection from %I port %d\n", sk->daddr, sk->dport); WALK_LIST(pc, config->protos) if (pc->protocol == &proto_bgp && pc->proto) { struct bgp_proto *p = (struct bgp_proto *) pc->proto; if (ipa_equal(p->cf->remote_ip, sk->daddr) && (!ipa_has_link_scope(sk->daddr) || (p->cf->iface == sk->iface))) { /* We are in proper state and there is no other incoming connection */ int acc = (p->p.proto_state == PS_START || p->p.proto_state == PS_UP) && (p->start_state >= BSS_CONNECT) && (!p->incoming_conn.sk); BGP_TRACE(D_EVENTS, "Incoming connection from %I%J (port %d) %s", sk->daddr, ipa_has_link_scope(sk->daddr) ? sk->iface : NULL, sk->dport, acc ? "accepted" : "rejected"); if (!acc) goto err; int hops = p->cf->multihop ? : 1; if (p->cf->ttl_security) { /* TTL security support */ if ((sk_set_ttl(sk, 255) < 0) || (sk_set_min_ttl(sk, 256 - hops) < 0)) { log(L_ERR "TTL security configuration failed, closing session"); goto err; } } else sk_set_ttl(sk, hops); bgp_setup_conn(p, &p->incoming_conn); bgp_setup_sk(&p->incoming_conn, sk); bgp_send_open(&p->incoming_conn); return 0; } }
/** * bgp_connect - initiate an outgoing connection * @p: BGP instance * * The bgp_connect() function creates a new &bgp_conn and initiates * a TCP connection to the peer. The rest of connection setup is governed * by the BGP state machine as described in the standard. */ static void bgp_connect(struct bgp_proto *p) /* Enter Connect state and start establishing connection */ { sock *s; struct bgp_conn *conn = &p->outgoing_conn; int hops = p->cf->multihop ? : 1; DBG("BGP: Connecting\n"); s = sk_new(p->p.pool); s->type = SK_TCP_ACTIVE; s->saddr = p->source_addr; s->daddr = p->cf->remote_ip; s->dport = p->cf->remote_port; s->iface = p->neigh ? p->neigh->iface : NULL; s->ttl = p->cf->ttl_security ? 255 : hops; s->rbsize = p->cf->enable_extended_messages ? BGP_RX_BUFFER_EXT_SIZE : BGP_RX_BUFFER_SIZE; s->tbsize = p->cf->enable_extended_messages ? BGP_TX_BUFFER_EXT_SIZE : BGP_TX_BUFFER_SIZE; s->tos = IP_PREC_INTERNET_CONTROL; s->password = p->cf->password; s->tx_hook = bgp_connected; BGP_TRACE(D_EVENTS, "Connecting to %I%J from local address %I%J", s->daddr, p->cf->iface, s->saddr, ipa_is_link_local(s->saddr) ? s->iface : NULL); bgp_setup_conn(p, conn); bgp_setup_sk(conn, s); bgp_conn_set_state(conn, BS_CONNECT); if (sk_open(s) < 0) goto err; /* Set minimal receive TTL if needed */ if (p->cf->ttl_security) if (sk_set_min_ttl(s, 256 - hops) < 0) goto err; DBG("BGP: Waiting for connect success\n"); bgp_start_timer(conn->connect_retry_timer, p->cf->connect_retry_time); return; err: sk_log_error(s, p->p.name); bgp_sock_err(s, 0); return; }
/** * bgp_incoming_connection - handle an incoming connection * @sk: TCP socket * @dummy: unused * * This function serves as a socket hook for accepting of new BGP * connections. It searches a BGP instance corresponding to the peer * which has connected and if such an instance exists, it creates a * &bgp_conn structure, attaches it to the instance and either sends * an Open message or (if there already is an active connection) it * closes the new connection by sending a Notification message. */ static int bgp_incoming_connection(sock *sk, int dummy UNUSED) { struct bgp_proto *p; int acc, hops; DBG("BGP: Incoming connection from %I port %d\n", sk->daddr, sk->dport); p = bgp_find_proto(sk); if (!p) { log(L_WARN "BGP: Unexpected connect from unknown address %I%J (port %d)", sk->daddr, ipa_is_link_local(sk->daddr) ? sk->iface : NULL, sk->dport); rfree(sk); return 0; } /* We are in proper state and there is no other incoming connection */ acc = (p->p.proto_state == PS_START || p->p.proto_state == PS_UP) && (p->start_state >= BSS_CONNECT) && (!p->incoming_conn.sk); if (p->conn && (p->conn->state == BS_ESTABLISHED) && p->gr_ready) { bgp_store_error(p, NULL, BE_MISC, BEM_GRACEFUL_RESTART); bgp_handle_graceful_restart(p); bgp_conn_enter_idle_state(p->conn); acc = 1; } BGP_TRACE(D_EVENTS, "Incoming connection from %I%J (port %d) %s", sk->daddr, ipa_is_link_local(sk->daddr) ? sk->iface : NULL, sk->dport, acc ? "accepted" : "rejected"); if (!acc) { rfree(sk); return 0; } hops = p->cf->multihop ? : 1; if (sk_set_ttl(sk, p->cf->ttl_security ? 255 : hops) < 0) goto err; if (p->cf->ttl_security) if (sk_set_min_ttl(sk, 256 - hops) < 0) goto err; if (p->cf->enable_extended_messages) { sk->rbsize = BGP_RX_BUFFER_EXT_SIZE; sk->tbsize = BGP_TX_BUFFER_EXT_SIZE; sk_reallocate(sk); } bgp_setup_conn(p, &p->incoming_conn); bgp_setup_sk(&p->incoming_conn, sk); bgp_send_open(&p->incoming_conn); return 0; err: sk_log_error(sk, p->p.name); log(L_ERR "%s: Incoming connection aborted", p->p.name); rfree(sk); return 0; }