Statistics
| Branch: | Revision:

iof-bird-daemon / proto / bgp / bgp.c @ 4a591d4b

History | View | Annotate | Download (39.5 KB)

1 2638249d Martin Mares
/*
2
 *        BIRD -- The Border Gateway Protocol
3
 *
4
 *        (c) 2000 Martin Mares <mj@ucw.cz>
5
 *
6
 *        Can be freely distributed and used under the terms of the GNU GPL.
7
 */
8
9 54e55169 Martin Mares
/**
10
 * DOC: Border Gateway Protocol
11
 *
12
 * The BGP protocol is implemented in three parts: |bgp.c| which takes care of the
13
 * connection and most of the interface with BIRD core, |packets.c| handling
14
 * both incoming and outgoing BGP packets and |attrs.c| containing functions for
15
 * manipulation with BGP attribute lists.
16
 *
17
 * As opposed to the other existing routing daemons, BIRD has a sophisticated core
18
 * architecture which is able to keep all the information needed by BGP in the
19
 * primary routing table, therefore no complex data structures like a central
20
 * BGP table are needed. This increases memory footprint of a BGP router with
21
 * many connections, but not too much and, which is more important, it makes
22
 * BGP much easier to implement.
23
 *
24 58f7d004 Martin Mares
 * Each instance of BGP (corresponding to a single BGP peer) is described by a &bgp_proto
25 54e55169 Martin Mares
 * structure to which are attached individual connections represented by &bgp_connection
26
 * (usually, there exists only one connection, but during BGP session setup, there
27
 * can be more of them). The connections are handled according to the BGP state machine
28
 * defined in the RFC with all the timers and all the parameters configurable.
29
 *
30
 * In incoming direction, we listen on the connection's socket and each time we receive
31
 * some input, we pass it to bgp_rx(). It decodes packet headers and the markers and
32
 * passes complete packets to bgp_rx_packet() which distributes the packet according
33
 * to its type.
34
 *
35
 * In outgoing direction, we gather all the routing updates and sort them to buckets
36
 * (&bgp_bucket) according to their attributes (we keep a hash table for fast comparison
37
 * of &rta's and a &fib which helps us to find if we already have another route for
38
 * the same destination queued for sending, so that we can replace it with the new one
39
 * immediately instead of sending both updates). There also exists a special bucket holding
40
 * all the route withdrawals which cannot be queued anywhere else as they don't have any
41
 * attributes. If we have any packet to send (due to either new routes or the connection
42 58f7d004 Martin Mares
 * tracking code wanting to send a Open, Keepalive or Notification message), we call
43 54e55169 Martin Mares
 * bgp_schedule_packet() which sets the corresponding bit in a @packet_to_send
44
 * bit field in &bgp_conn and as soon as the transmit socket buffer becomes empty,
45
 * we call bgp_fire_tx(). It inspects state of all the packet type bits and calls
46
 * the corresponding bgp_create_xx() functions, eventually rescheduling the same packet
47
 * type if we have more data of the same type to send.
48
 *
49
 * The processing of attributes consists of two functions: bgp_decode_attrs() for checking
50
 * of the attribute blocks and translating them to the language of BIRD's extended attributes
51
 * and bgp_encode_attrs() which does the converse. Both functions are built around a
52
 * @bgp_attr_table array describing all important characteristics of all known attributes.
53
 * Unknown transitive attributes are attached to the route as %EAF_TYPE_OPAQUE byte streams.
54 6eda3f13 Ondrej Zajicek
 *
55
 * BGP protocol implements graceful restart in both restarting (local restart)
56
 * and receiving (neighbor restart) roles. The first is handled mostly by the
57
 * graceful restart code in the nest, BGP protocol just handles capabilities,
58
 * sets @gr_wait and locks graceful restart until end-of-RIB mark is received.
59
 * The second is implemented by internal restart of the BGP state to %BS_IDLE
60
 * and protocol state to %PS_START, but keeping the protocol up from the core
61
 * point of view and therefore maintaining received routes. Routing table
62
 * refresh cycle (rt_refresh_begin(), rt_refresh_end()) is used for removing
63
 * stale routes after reestablishment of BGP session during graceful restart.
64 54e55169 Martin Mares
 */
65
66 48d79d52 Ondrej Zajicek
#undef LOCAL_DEBUG
67 2638249d Martin Mares
68
#include "nest/bird.h"
69
#include "nest/iface.h"
70
#include "nest/protocol.h"
71
#include "nest/route.h"
72 b8113a5e Ondrej Zajicek
#include "nest/cli.h"
73 1ec52253 Ondrej Zajicek
#include "nest/locks.h"
74 2638249d Martin Mares
#include "conf/conf.h"
75 c01e3741 Martin Mares
#include "lib/socket.h"
76 973399ae Martin Mares
#include "lib/resource.h"
77 7d875e09 Martin Mares
#include "lib/string.h"
78 2638249d Martin Mares
79
#include "bgp.h"
80
81 e7d2ac44 Ondrej Zajicek
82 973399ae Martin Mares
struct linpool *bgp_linpool;                /* Global temporary pool */
83 c01e3741 Martin Mares
static sock *bgp_listen_sk;                /* Global listening socket */
84
static int bgp_counter;                        /* Number of protocol instances using the listening socket */
85
86 11b32d91 Ondrej Zajicek
static void bgp_close(struct bgp_proto *p, int apply_md5);
87 c01e3741 Martin Mares
static void bgp_connect(struct bgp_proto *p);
88 dd91e467 Ondrej Zajicek
static void bgp_active(struct bgp_proto *p);
89 789772ed Ondrej Zajicek
static sock *bgp_setup_listen_sk(ip_addr addr, unsigned port, u32 flags);
90 1ec52253 Ondrej Zajicek
static void bgp_update_bfd(struct bgp_proto *p, int use_bfd);
91 2638249d Martin Mares
92 11cb6202 Ondrej Zajicek
93 11b32d91 Ondrej Zajicek
/**
94
 * bgp_open - open a BGP instance
95
 * @p: BGP instance
96
 *
97
 * This function allocates and configures shared BGP resources.
98
 * Should be called as the last step during initialization
99
 * (when lock is acquired and neighbor is ready).
100
 * When error, state changed to PS_DOWN, -1 is returned and caller
101
 * should return immediately.
102
 */
103
static int
104
bgp_open(struct bgp_proto *p)
105
{
106 789772ed Ondrej Zajicek
  struct config *cfg = p->cf->c.global;
107 b1b19433 Ondrej Zajicek
  int errcode;
108
109 11b32d91 Ondrej Zajicek
  if (!bgp_listen_sk)
110 d72cdff4 Ondrej Zajicek
    bgp_listen_sk = bgp_setup_listen_sk(cfg->listen_bgp_addr, cfg->listen_bgp_port, cfg->listen_bgp_flags);
111 11b32d91 Ondrej Zajicek
112 a34b0934 Ondrej Zajicek
  if (!bgp_listen_sk)
113
    {
114 b1b19433 Ondrej Zajicek
      errcode = BEM_NO_SOCKET;
115
      goto err;
116 a34b0934 Ondrej Zajicek
    }
117
118 11b32d91 Ondrej Zajicek
  if (!bgp_linpool)
119
    bgp_linpool = lp_new(&root_pool, 4080);
120
121 05476c4d Ondrej Zajicek
  bgp_counter++;
122
123 11b32d91 Ondrej Zajicek
  if (p->cf->password)
124 05476c4d Ondrej Zajicek
    if (sk_set_md5_auth(bgp_listen_sk, p->cf->remote_ip, p->cf->iface, p->cf->password) < 0)
125
      {
126
        sk_log_error(bgp_listen_sk, p->p.name);
127
        bgp_close(p, 0);
128
        errcode = BEM_INVALID_MD5;
129
        goto err;
130
      }
131 11b32d91 Ondrej Zajicek
132
  return 0;
133 b1b19433 Ondrej Zajicek
134
err:
135
  p->p.disabled = 1;
136
  bgp_store_error(p, NULL, BE_MISC, errcode);
137
  proto_notify_state(&p->p, PS_DOWN);
138
  return -1;
139 11b32d91 Ondrej Zajicek
}
140
141 dd91e467 Ondrej Zajicek
static void
142
bgp_startup(struct bgp_proto *p)
143
{
144
  BGP_TRACE(D_EVENTS, "Started");
145
  p->start_state = p->cf->capabilities ? BSS_CONNECT : BSS_CONNECT_NOCAP;
146 be6e39eb Ondrej Zajicek
147
  if (!p->cf->passive)
148
    bgp_active(p);
149 dd91e467 Ondrej Zajicek
}
150
151
static void
152
bgp_startup_timeout(timer *t)
153
{
154
  bgp_startup(t->data);
155
}
156
157
158
static void
159
bgp_initiate(struct bgp_proto *p)
160
{
161 9be9a264 Ondrej Zajicek
  int rv = bgp_open(p);
162
  if (rv < 0)
163
    return;
164
165 1ec52253 Ondrej Zajicek
  if (p->cf->bfd)
166
    bgp_update_bfd(p, p->cf->bfd);
167
168 dd91e467 Ondrej Zajicek
  if (p->startup_delay)
169
    {
170 1ec52253 Ondrej Zajicek
      p->start_state = BSS_DELAY;
171 dd91e467 Ondrej Zajicek
      BGP_TRACE(D_EVENTS, "Startup delayed by %d seconds", p->startup_delay);
172
      bgp_start_timer(p->startup_timer, p->startup_delay);
173
    }
174
  else
175
    bgp_startup(p);
176
}
177
178 11b32d91 Ondrej Zajicek
/**
179
 * bgp_close - close a BGP instance
180
 * @p: BGP instance
181
 * @apply_md5: 0 to disable unsetting MD5 auth
182
 *
183
 * This function frees and deconfigures shared BGP resources.
184
 * @apply_md5 is set to 0 when bgp_close is called as a cleanup
185
 * from failed bgp_open().
186
 */
187 9831e591 Martin Mares
static void
188 11b32d91 Ondrej Zajicek
bgp_close(struct bgp_proto *p, int apply_md5)
189 c01e3741 Martin Mares
{
190
  ASSERT(bgp_counter);
191
  bgp_counter--;
192 d51aa281 Ondrej Zajicek
193 11b32d91 Ondrej Zajicek
  if (p->cf->password && apply_md5)
194 05476c4d Ondrej Zajicek
    if (sk_set_md5_auth(bgp_listen_sk, p->cf->remote_ip, p->cf->iface, NULL) < 0)
195
      sk_log_error(bgp_listen_sk, p->p.name);
196 d51aa281 Ondrej Zajicek
197 c01e3741 Martin Mares
  if (!bgp_counter)
198
    {
199
      rfree(bgp_listen_sk);
200
      bgp_listen_sk = NULL;
201 973399ae Martin Mares
      rfree(bgp_linpool);
202
      bgp_linpool = NULL;
203 c01e3741 Martin Mares
    }
204
}
205
206 54e55169 Martin Mares
/**
207
 * bgp_start_timer - start a BGP timer
208
 * @t: timer
209
 * @value: time to fire (0 to disable the timer)
210
 *
211
 * This functions calls tm_start() on @t with time @value and the
212
 * amount of randomization suggested by the BGP standard. Please use
213
 * it for all BGP timers.
214
 */
215 3fdbafb6 Martin Mares
void
216 c01e3741 Martin Mares
bgp_start_timer(timer *t, int value)
217
{
218 3fdbafb6 Martin Mares
  if (value)
219 b3155b33 Martin Mares
    {
220
      /* The randomization procedure is specified in RFC 1771: 9.2.3.3 */
221
      t->randomize = value / 4;
222
      tm_start(t, value - t->randomize);
223
    }
224 b552ecc4 Martin Mares
  else
225
    tm_stop(t);
226
}
227
228 54e55169 Martin Mares
/**
229
 * bgp_close_conn - close a BGP connection
230
 * @conn: connection to close
231
 *
232
 * This function takes a connection described by the &bgp_conn structure,
233
 * closes its socket and frees all resources associated with it.
234
 */
235 b552ecc4 Martin Mares
void
236
bgp_close_conn(struct bgp_conn *conn)
237
{
238 e81b440f Ondrej Zajicek
  // struct bgp_proto *p = conn->bgp;
239 b552ecc4 Martin Mares
240
  DBG("BGP: Closing connection\n");
241
  conn->packets_to_send = 0;
242
  rfree(conn->connect_retry_timer);
243
  conn->connect_retry_timer = NULL;
244
  rfree(conn->keepalive_timer);
245
  conn->keepalive_timer = NULL;
246
  rfree(conn->hold_timer);
247
  conn->hold_timer = NULL;
248 38a608c5 Martin Mares
  rfree(conn->sk);
249 b552ecc4 Martin Mares
  conn->sk = NULL;
250 11b32d91 Ondrej Zajicek
  rfree(conn->tx_ev);
251
  conn->tx_ev = NULL;
252
}
253
254
255
/**
256
 * bgp_update_startup_delay - update a startup delay
257
 * @p: BGP instance
258
 *
259
 * This function updates a startup delay that is used to postpone next BGP connect.
260
 * It also handles disable_after_error and might stop BGP instance when error
261
 * happened and disable_after_error is on.
262
 *
263
 * It should be called when BGP protocol error happened.
264
 */
265
void
266 b99d3786 Ondrej Zajicek
bgp_update_startup_delay(struct bgp_proto *p)
267 11b32d91 Ondrej Zajicek
{
268
  struct bgp_config *cf = p->cf;
269
270 b99d3786 Ondrej Zajicek
  DBG("BGP: Updating startup delay\n");
271 11b32d91 Ondrej Zajicek
272 e81b440f Ondrej Zajicek
  if (p->last_proto_error && ((now - p->last_proto_error) >= (int) cf->error_amnesia_time))
273 72382626 Ondrej Zajicek
    p->startup_delay = 0;
274
275 11b32d91 Ondrej Zajicek
  p->last_proto_error = now;
276
277
  if (cf->disable_after_error)
278
    {
279
      p->startup_delay = 0;
280
      p->p.disabled = 1;
281
      return;
282 6fd766c1 Martin Mares
    }
283 11b32d91 Ondrej Zajicek
284
  if (!p->startup_delay)
285
    p->startup_delay = cf->error_delay_time_min;
286
  else
287 b99d3786 Ondrej Zajicek
    p->startup_delay = MIN(2 * p->startup_delay, cf->error_delay_time_max);
288 c01e3741 Martin Mares
}
289
290 11b32d91 Ondrej Zajicek
static void
291 b99d3786 Ondrej Zajicek
bgp_graceful_close_conn(struct bgp_conn *conn, unsigned subcode)
292 48e842cc Martin Mares
{
293 11b32d91 Ondrej Zajicek
  switch (conn->state)
294 48e842cc Martin Mares
    {
295
    case BS_IDLE:
296 11b32d91 Ondrej Zajicek
    case BS_CLOSE:
297
      return;
298 48e842cc Martin Mares
    case BS_CONNECT:
299
    case BS_ACTIVE:
300 11b32d91 Ondrej Zajicek
      bgp_conn_enter_idle_state(conn);
301
      return;
302 48e842cc Martin Mares
    case BS_OPENSENT:
303
    case BS_OPENCONFIRM:
304
    case BS_ESTABLISHED:
305 b99d3786 Ondrej Zajicek
      bgp_error(conn, 6, subcode, NULL, 0);
306 11b32d91 Ondrej Zajicek
      return;
307 48e842cc Martin Mares
    default:
308 11b32d91 Ondrej Zajicek
      bug("bgp_graceful_close_conn: Unknown state %d", conn->state);
309 48e842cc Martin Mares
    }
310
}
311
312 c01e3741 Martin Mares
static void
313 11b32d91 Ondrej Zajicek
bgp_down(struct bgp_proto *p)
314
{
315
  if (p->start_state > BSS_PREPARE)
316
    bgp_close(p, 1);
317
318 b99d3786 Ondrej Zajicek
  BGP_TRACE(D_EVENTS, "Down");
319 11b32d91 Ondrej Zajicek
  proto_notify_state(&p->p, PS_DOWN);
320
}
321
322
static void
323
bgp_decision(void *vp)
324
{
325
  struct bgp_proto *p = vp;
326
327
  DBG("BGP: Decision start\n");
328
  if ((p->p.proto_state == PS_START)
329 be6e39eb Ondrej Zajicek
      && (p->outgoing_conn.state == BS_IDLE)
330 0c791f87 Ondrej Zajicek
      && (p->incoming_conn.state != BS_OPENCONFIRM)
331 be6e39eb Ondrej Zajicek
      && (!p->cf->passive))
332 dd91e467 Ondrej Zajicek
    bgp_active(p);
333 11b32d91 Ondrej Zajicek
334
  if ((p->p.proto_state == PS_STOP)
335
      && (p->outgoing_conn.state == BS_IDLE)
336
      && (p->incoming_conn.state == BS_IDLE))
337
    bgp_down(p);
338
}
339
340 b99d3786 Ondrej Zajicek
void
341
bgp_stop(struct bgp_proto *p, unsigned subcode)
342 11b32d91 Ondrej Zajicek
{
343
  proto_notify_state(&p->p, PS_STOP);
344 b99d3786 Ondrej Zajicek
  bgp_graceful_close_conn(&p->outgoing_conn, subcode);
345
  bgp_graceful_close_conn(&p->incoming_conn, subcode);
346 11b32d91 Ondrej Zajicek
  ev_schedule(p->event);
347
}
348
349 cf31112f Ondrej Zajicek
static inline void
350
bgp_conn_set_state(struct bgp_conn *conn, unsigned new_state)
351
{
352
  if (conn->bgp->p.mrtdump & MD_STATES)
353
    mrt_dump_bgp_state_change(conn, conn->state, new_state);
354
355
  conn->state = new_state;
356
}
357
358
void
359
bgp_conn_enter_openconfirm_state(struct bgp_conn *conn)
360
{
361
  /* Really, most of the work is done in bgp_rx_open(). */
362
  bgp_conn_set_state(conn, BS_OPENCONFIRM);
363
}
364
365 11b32d91 Ondrej Zajicek
void
366
bgp_conn_enter_established_state(struct bgp_conn *conn)
367
{
368
  struct bgp_proto *p = conn->bgp;
369 523f020b Ondrej Zajicek
370 11b32d91 Ondrej Zajicek
  BGP_TRACE(D_EVENTS, "BGP session established");
371
  DBG("BGP: UP!!!\n");
372
373 9be9a264 Ondrej Zajicek
  /* For multi-hop BGP sessions */
374
  if (ipa_zero(p->source_addr))
375 0c791f87 Ondrej Zajicek
    p->source_addr = conn->sk->saddr;
376 9be9a264 Ondrej Zajicek
377 11b32d91 Ondrej Zajicek
  p->conn = conn;
378
  p->last_error_class = 0;
379
  p->last_error_code = 0;
380 094d2bdb Ondrej Zajicek
  bgp_init_bucket_table(p);
381
  bgp_init_prefix_table(p, 8);
382
383 0c791f87 Ondrej Zajicek
  int peer_gr_ready = conn->peer_gr_aware && !(conn->peer_gr_flags & BGP_GRF_RESTART);
384
385
  if (p->p.gr_recovery && !peer_gr_ready)
386
    proto_graceful_restart_unlock(&p->p);
387
388
  if (p->p.gr_recovery && (p->cf->gr_mode == BGP_GR_ABLE) && peer_gr_ready)
389
    p->p.gr_wait = 1;
390
391
  if (p->gr_active)
392
    tm_stop(p->gr_timer);
393
394
  if (p->gr_active && (!conn->peer_gr_able || !(conn->peer_gr_aflags & BGP_GRF_FORWARDING)))
395
    bgp_graceful_restart_done(p);
396
397 cf31112f Ondrej Zajicek
  bgp_conn_set_state(conn, BS_ESTABLISHED);
398 11b32d91 Ondrej Zajicek
  proto_notify_state(&p->p, PS_UP);
399
}
400
401
static void
402
bgp_conn_leave_established_state(struct bgp_proto *p)
403
{
404
  BGP_TRACE(D_EVENTS, "BGP session closed");
405
  p->conn = NULL;
406
407
  if (p->p.proto_state == PS_UP)
408 b99d3786 Ondrej Zajicek
    bgp_stop(p, 0);
409 11b32d91 Ondrej Zajicek
}
410
411
void
412
bgp_conn_enter_close_state(struct bgp_conn *conn)
413
{
414
  struct bgp_proto *p = conn->bgp;
415
  int os = conn->state;
416
417 cf31112f Ondrej Zajicek
  bgp_conn_set_state(conn, BS_CLOSE);
418 11b32d91 Ondrej Zajicek
  tm_stop(conn->keepalive_timer);
419
  conn->sk->rx_hook = NULL;
420
421 48b15ef1 Ondrej Zajicek
  /* Timeout for CLOSE state, if we cannot send notification soon then we just hangup */
422
  bgp_start_timer(conn->hold_timer, 10);
423
424 11b32d91 Ondrej Zajicek
  if (os == BS_ESTABLISHED)
425
    bgp_conn_leave_established_state(p);
426
}
427
428
void
429
bgp_conn_enter_idle_state(struct bgp_conn *conn)
430
{
431
  struct bgp_proto *p = conn->bgp;
432
  int os = conn->state;
433
434
  bgp_close_conn(conn);
435 cf31112f Ondrej Zajicek
  bgp_conn_set_state(conn, BS_IDLE);
436 11b32d91 Ondrej Zajicek
  ev_schedule(p->event);
437
438
  if (os == BS_ESTABLISHED)
439
    bgp_conn_leave_established_state(p);
440
}
441
442 6eda3f13 Ondrej Zajicek
/**
443
 * bgp_handle_graceful_restart - handle detected BGP graceful restart
444
 * @p: BGP instance
445
 *
446
 * This function is called when a BGP graceful restart of the neighbor is
447
 * detected (when the TCP connection fails or when a new TCP connection
448
 * appears). The function activates processing of the restart - starts routing
449
 * table refresh cycle and activates BGP restart timer. The protocol state goes
450
 * back to %PS_START, but changing BGP state back to %BS_IDLE is left for the
451
 * caller.
452
 */
453 0c791f87 Ondrej Zajicek
void
454
bgp_handle_graceful_restart(struct bgp_proto *p)
455
{
456
  ASSERT(p->conn && (p->conn->state == BS_ESTABLISHED) && p->gr_ready);
457
458
  BGP_TRACE(D_EVENTS, "Neighbor graceful restart detected%s",
459
            p->gr_active ? " - already pending" : "");
460
  proto_notify_state(&p->p, PS_START);
461
462
  if (p->gr_active)
463
    rt_refresh_end(p->p.main_ahook->table, p->p.main_ahook);
464
465
  p->gr_active = 1;
466
  bgp_start_timer(p->gr_timer, p->conn->peer_gr_time);
467
  rt_refresh_begin(p->p.main_ahook->table, p->p.main_ahook);
468
}
469
470 6eda3f13 Ondrej Zajicek
/**
471
 * bgp_graceful_restart_done - finish active BGP graceful restart
472
 * @p: BGP instance
473
 *
474
 * This function is called when the active BGP graceful restart of the neighbor
475
 * should be finished - either successfully (the neighbor sends all paths and
476
 * reports end-of-RIB on the new session) or unsuccessfully (the neighbor does
477
 * not support BGP graceful restart on the new session). The function ends
478
 * routing table refresh cycle and stops BGP restart timer.
479
 */
480 0c791f87 Ondrej Zajicek
void
481
bgp_graceful_restart_done(struct bgp_proto *p)
482
{
483
  BGP_TRACE(D_EVENTS, "Neighbor graceful restart done");
484
  p->gr_active = 0;
485
  tm_stop(p->gr_timer);
486
  rt_refresh_end(p->p.main_ahook->table, p->p.main_ahook);
487
}
488
489 6eda3f13 Ondrej Zajicek
/**
490
 * bgp_graceful_restart_timeout - timeout of graceful restart 'restart timer'
491
 * @t: timer
492
 *
493
 * This function is a timeout hook for @gr_timer, implementing BGP restart time
494
 * limit for reestablisment of the BGP session after the graceful restart. When
495
 * fired, we just proceed with the usual protocol restart.
496
 */
497
498 0c791f87 Ondrej Zajicek
static void
499
bgp_graceful_restart_timeout(timer *t)
500
{
501
  struct bgp_proto *p = t->data;
502
503
  BGP_TRACE(D_EVENTS, "Neighbor graceful restart timeout");
504
  bgp_stop(p, 0);
505
}
506
507 11b32d91 Ondrej Zajicek
static void
508 c01e3741 Martin Mares
bgp_send_open(struct bgp_conn *conn)
509
{
510 165a6227 Ondrej Zajicek
  conn->start_state = conn->bgp->start_state;
511 094d2bdb Ondrej Zajicek
512
  // Default values, possibly changed by receiving capabilities.
513 0c791f87 Ondrej Zajicek
  conn->advertised_as = 0;
514 094d2bdb Ondrej Zajicek
  conn->peer_refresh_support = 0;
515
  conn->peer_as4_support = 0;
516
  conn->peer_add_path = 0;
517 0c791f87 Ondrej Zajicek
  conn->peer_gr_aware = 0;
518
  conn->peer_gr_able = 0;
519
  conn->peer_gr_time = 0;
520
  conn->peer_gr_flags = 0;
521
  conn->peer_gr_aflags = 0;
522 165a6227 Ondrej Zajicek
523 c01e3741 Martin Mares
  DBG("BGP: Sending open\n");
524
  conn->sk->rx_hook = bgp_rx;
525 b552ecc4 Martin Mares
  conn->sk->tx_hook = bgp_tx;
526 c01e3741 Martin Mares
  tm_stop(conn->connect_retry_timer);
527 72a6ef11 Martin Mares
  bgp_schedule_packet(conn, PKT_OPEN);
528 cf31112f Ondrej Zajicek
  bgp_conn_set_state(conn, BS_OPENSENT);
529 3fdbafb6 Martin Mares
  bgp_start_timer(conn->hold_timer, conn->bgp->cf->initial_hold_time);
530 c01e3741 Martin Mares
}
531
532 3fdbafb6 Martin Mares
static void
533
bgp_connected(sock *sk)
534 c01e3741 Martin Mares
{
535
  struct bgp_conn *conn = sk->data;
536 85368cd4 Martin Mares
  struct bgp_proto *p = conn->bgp;
537 c01e3741 Martin Mares
538 85368cd4 Martin Mares
  BGP_TRACE(D_EVENTS, "Connected");
539 c01e3741 Martin Mares
  bgp_send_open(conn);
540
}
541
542
static void
543
bgp_connect_timeout(timer *t)
544
{
545 3fdbafb6 Martin Mares
  struct bgp_conn *conn = t->data;
546 85368cd4 Martin Mares
  struct bgp_proto *p = conn->bgp;
547 c01e3741 Martin Mares
548 85368cd4 Martin Mares
  DBG("BGP: connect_timeout\n");
549 11b32d91 Ondrej Zajicek
  if (p->p.proto_state == PS_START)
550
    {
551
      bgp_close_conn(conn);
552
      bgp_connect(p);
553
    }
554
  else
555
    bgp_conn_enter_idle_state(conn);
556 c01e3741 Martin Mares
}
557
558
static void
559 3fdbafb6 Martin Mares
bgp_sock_err(sock *sk, int err)
560 c01e3741 Martin Mares
{
561
  struct bgp_conn *conn = sk->data;
562 85368cd4 Martin Mares
  struct bgp_proto *p = conn->bgp;
563 c01e3741 Martin Mares
564 47597724 Ondrej Zajicek
  /*
565
   * This error hook may be called either asynchronously from main
566
   * loop, or synchronously from sk_send().  But sk_send() is called
567
   * only from bgp_tx() and bgp_kick_tx(), which are both called
568
   * asynchronously from main loop. Moreover, they end if err hook is
569
   * called. Therefore, we could suppose that it is always called
570
   * asynchronously.
571
   */
572
573 11b32d91 Ondrej Zajicek
  bgp_store_error(p, conn, BE_SOCKET, err);
574
575 53943a00 Martin Mares
  if (err)
576
    BGP_TRACE(D_EVENTS, "Connection lost (%M)", err);
577
  else
578
    BGP_TRACE(D_EVENTS, "Connection closed");
579 11b32d91 Ondrej Zajicek
580 0c791f87 Ondrej Zajicek
  if ((conn->state == BS_ESTABLISHED) && p->gr_ready)
581
    bgp_handle_graceful_restart(p);
582
583 11b32d91 Ondrej Zajicek
  bgp_conn_enter_idle_state(conn);
584 c01e3741 Martin Mares
}
585
586
static void
587 3fdbafb6 Martin Mares
bgp_hold_timeout(timer *t)
588
{
589
  struct bgp_conn *conn = t->data;
590 48b15ef1 Ondrej Zajicek
  struct bgp_proto *p = conn->bgp;
591 3fdbafb6 Martin Mares
592 ea89da38 Ondrej Zajicek
  DBG("BGP: Hold timeout\n");
593
594 48b15ef1 Ondrej Zajicek
  /* We are already closing the connection - just do hangup */
595
  if (conn->state == BS_CLOSE)
596
  {
597
    BGP_TRACE(D_EVENTS, "Connection stalled");
598
    bgp_conn_enter_idle_state(conn);
599
    return;
600
  }
601
602 ea89da38 Ondrej Zajicek
  /* If there is something in input queue, we are probably congested
603
     and perhaps just not processed BGP packets in time. */
604
605
  if (sk_rx_ready(conn->sk) > 0)
606
    bgp_start_timer(conn->hold_timer, 10);
607
  else
608
    bgp_error(conn, 4, 0, NULL, 0);
609 3fdbafb6 Martin Mares
}
610
611
static void
612
bgp_keepalive_timeout(timer *t)
613
{
614
  struct bgp_conn *conn = t->data;
615
616
  DBG("BGP: Keepalive timer\n");
617
  bgp_schedule_packet(conn, PKT_KEEPALIVE);
618
}
619
620
static void
621 6fd766c1 Martin Mares
bgp_setup_conn(struct bgp_proto *p, struct bgp_conn *conn)
622 c01e3741 Martin Mares
{
623
  timer *t;
624
625 6fd766c1 Martin Mares
  conn->sk = NULL;
626 c01e3741 Martin Mares
  conn->bgp = p;
627 72a6ef11 Martin Mares
  conn->packets_to_send = 0;
628 c01e3741 Martin Mares
629
  t = conn->connect_retry_timer = tm_new(p->p.pool);
630
  t->hook = bgp_connect_timeout;
631 3fdbafb6 Martin Mares
  t->data = conn;
632
  t = conn->hold_timer = tm_new(p->p.pool);
633 c01e3741 Martin Mares
  t->hook = bgp_hold_timeout;
634 3fdbafb6 Martin Mares
  t->data = conn;
635
  t = conn->keepalive_timer = tm_new(p->p.pool);
636 c01e3741 Martin Mares
  t->hook = bgp_keepalive_timeout;
637 3fdbafb6 Martin Mares
  t->data = conn;
638 11b32d91 Ondrej Zajicek
  conn->tx_ev = ev_new(p->p.pool);
639
  conn->tx_ev->hook = bgp_kick_tx;
640
  conn->tx_ev->data = conn;
641 c01e3741 Martin Mares
}
642
643
static void
644 e81b440f Ondrej Zajicek
bgp_setup_sk(struct bgp_conn *conn, sock *s)
645 6fd766c1 Martin Mares
{
646
  s->data = conn;
647
  s->err_hook = bgp_sock_err;
648
  conn->sk = s;
649
}
650
651 11b32d91 Ondrej Zajicek
static void
652 dd91e467 Ondrej Zajicek
bgp_active(struct bgp_proto *p)
653 11b32d91 Ondrej Zajicek
{
654 b99d3786 Ondrej Zajicek
  int delay = MAX(1, p->cf->start_delay_time);
655 11b32d91 Ondrej Zajicek
  struct bgp_conn *conn = &p->outgoing_conn;
656
657
  BGP_TRACE(D_EVENTS, "Connect delayed by %d seconds", delay);
658
  bgp_setup_conn(p, conn);
659 cf31112f Ondrej Zajicek
  bgp_conn_set_state(conn, BS_ACTIVE);
660 11b32d91 Ondrej Zajicek
  bgp_start_timer(conn->connect_retry_timer, delay);
661
}
662
663 54e55169 Martin Mares
/**
664
 * bgp_connect - initiate an outgoing connection
665
 * @p: BGP instance
666
 *
667
 * The bgp_connect() function creates a new &bgp_conn and initiates
668
 * a TCP connection to the peer. The rest of connection setup is governed
669
 * by the BGP state machine as described in the standard.
670
 */
671 6fd766c1 Martin Mares
static void
672 c01e3741 Martin Mares
bgp_connect(struct bgp_proto *p)        /* Enter Connect state and start establishing connection */
673
{
674
  sock *s;
675 b552ecc4 Martin Mares
  struct bgp_conn *conn = &p->outgoing_conn;
676 b1b19433 Ondrej Zajicek
  int hops = p->cf->multihop ? : 1;
677 c01e3741 Martin Mares
678
  DBG("BGP: Connecting\n");
679
  s = sk_new(p->p.pool);
680
  s->type = SK_TCP_ACTIVE;
681 ad440a57 Ondrej Zajicek
  s->saddr = p->source_addr;
682 c01e3741 Martin Mares
  s->daddr = p->cf->remote_ip;
683 dcde7ae5 Ondrej Zajicek
  s->dport = p->cf->remote_port;
684 53ffbff3 Ondrej Zajicek
  s->iface = p->neigh ? p->neigh->iface : NULL;
685 b1b19433 Ondrej Zajicek
  s->ttl = p->cf->ttl_security ? 255 : hops;
686 a39b165e Ondrej Zajicek
  s->rbsize = BGP_RX_BUFFER_SIZE;
687
  s->tbsize = BGP_TX_BUFFER_SIZE;
688
  s->tos = IP_PREC_INTERNET_CONTROL;
689
  s->password = p->cf->password;
690
  s->tx_hook = bgp_connected;
691 53ffbff3 Ondrej Zajicek
  BGP_TRACE(D_EVENTS, "Connecting to %I%J from local address %I%J", s->daddr, p->cf->iface,
692 88a183c6 Ondrej Zajicek
            s->saddr, ipa_is_link_local(s->saddr) ? s->iface : NULL);
693 6fd766c1 Martin Mares
  bgp_setup_conn(p, conn);
694 e81b440f Ondrej Zajicek
  bgp_setup_sk(conn, s);
695 cf31112f Ondrej Zajicek
  bgp_conn_set_state(conn, BS_CONNECT);
696 b1b19433 Ondrej Zajicek
697
  if (sk_open(s) < 0)
698 05476c4d Ondrej Zajicek
    goto err;
699 b1b19433 Ondrej Zajicek
700
  /* Set minimal receive TTL if needed */
701
  if (p->cf->ttl_security)
702
    if (sk_set_min_ttl(s, 256 - hops) < 0)
703 05476c4d Ondrej Zajicek
      goto err;
704 b1b19433 Ondrej Zajicek
705 c01e3741 Martin Mares
  DBG("BGP: Waiting for connect success\n");
706
  bgp_start_timer(conn->connect_retry_timer, p->cf->connect_retry_time);
707 05476c4d Ondrej Zajicek
  return;
708
709
 err:
710
  sk_log_error(s, p->p.name);
711
  bgp_sock_err(s, 0);
712
  return;
713 c01e3741 Martin Mares
}
714
715 54e55169 Martin Mares
/**
716
 * bgp_incoming_connection - handle an incoming connection
717
 * @sk: TCP socket
718
 * @dummy: unused
719
 *
720
 * This function serves as a socket hook for accepting of new BGP
721
 * connections. It searches a BGP instance corresponding to the peer
722
 * which has connected and if such an instance exists, it creates a
723
 * &bgp_conn structure, attaches it to the instance and either sends
724
 * an Open message or (if there already is an active connection) it
725
 * closes the new connection by sending a Notification message.
726
 */
727 48e842cc Martin Mares
static int
728 e21423ba Martin Mares
bgp_incoming_connection(sock *sk, int dummy UNUSED)
729 c01e3741 Martin Mares
{
730 93d6bf38 Martin Mares
  struct proto_config *pc;
731 c01e3741 Martin Mares
732 48e842cc Martin Mares
  DBG("BGP: Incoming connection from %I port %d\n", sk->daddr, sk->dport);
733 93d6bf38 Martin Mares
  WALK_LIST(pc, config->protos)
734
    if (pc->protocol == &proto_bgp && pc->proto)
735
      {
736
        struct bgp_proto *p = (struct bgp_proto *) pc->proto;
737 53ffbff3 Ondrej Zajicek
        if (ipa_equal(p->cf->remote_ip, sk->daddr) &&
738 88a183c6 Ondrej Zajicek
            (!ipa_is_link_local(sk->daddr) || (p->cf->iface == sk->iface)))
739 93d6bf38 Martin Mares
          {
740 dd91e467 Ondrej Zajicek
            /* We are in proper state and there is no other incoming connection */
741
            int acc = (p->p.proto_state == PS_START || p->p.proto_state == PS_UP) &&
742
              (p->start_state >= BSS_CONNECT) && (!p->incoming_conn.sk);
743
744 0c791f87 Ondrej Zajicek
            if (p->conn && (p->conn->state == BS_ESTABLISHED) && p->gr_ready)
745
            {
746
              bgp_store_error(p, NULL, BE_MISC, BEM_GRACEFUL_RESTART);
747
              bgp_handle_graceful_restart(p);
748
              bgp_conn_enter_idle_state(p->conn);
749
              acc = 1;
750
            }
751
752 53ffbff3 Ondrej Zajicek
            BGP_TRACE(D_EVENTS, "Incoming connection from %I%J (port %d) %s",
753 88a183c6 Ondrej Zajicek
                      sk->daddr, ipa_is_link_local(sk->daddr) ? sk->iface : NULL,
754 53ffbff3 Ondrej Zajicek
                      sk->dport, acc ? "accepted" : "rejected");
755 dd91e467 Ondrej Zajicek
756
            if (!acc)
757 05476c4d Ondrej Zajicek
              goto reject;
758 dd91e467 Ondrej Zajicek
759 b1b19433 Ondrej Zajicek
            int hops = p->cf->multihop ? : 1;
760 05476c4d Ondrej Zajicek
761
            if (sk_set_ttl(sk, p->cf->ttl_security ? 255 : hops) < 0)
762
              goto err;
763
764 b1b19433 Ondrej Zajicek
            if (p->cf->ttl_security)
765 05476c4d Ondrej Zajicek
              if (sk_set_min_ttl(sk, 256 - hops) < 0)
766 b1b19433 Ondrej Zajicek
                goto err;
767
768 dd91e467 Ondrej Zajicek
            bgp_setup_conn(p, &p->incoming_conn);
769 e81b440f Ondrej Zajicek
            bgp_setup_sk(&p->incoming_conn, sk);
770 dd91e467 Ondrej Zajicek
            bgp_send_open(&p->incoming_conn);
771
            return 0;
772 05476c4d Ondrej Zajicek
773
          err:
774
            sk_log_error(sk, p->p.name);
775
            log(L_ERR "%s: Incoming connection aborted", p->p.name);
776
            rfree(sk);
777
            return 0;
778 93d6bf38 Martin Mares
          }
779
      }
780 dd91e467 Ondrej Zajicek
781 53ffbff3 Ondrej Zajicek
  log(L_WARN "BGP: Unexpected connect from unknown address %I%J (port %d)",
782 88a183c6 Ondrej Zajicek
      sk->daddr, ipa_is_link_local(sk->daddr) ? sk->iface : NULL, sk->dport);
783 05476c4d Ondrej Zajicek
 reject:
784 48e842cc Martin Mares
  rfree(sk);
785
  return 0;
786
}
787
788 2af25a97 Ondrej Zajicek
static void
789 e81b440f Ondrej Zajicek
bgp_listen_sock_err(sock *sk UNUSED, int err)
790 2af25a97 Ondrej Zajicek
{
791
  if (err == ECONNABORTED)
792
    log(L_WARN "BGP: Incoming connection aborted");
793
  else
794 a34b0934 Ondrej Zajicek
    log(L_ERR "BGP: Error on listening socket: %M", err);
795 2af25a97 Ondrej Zajicek
}
796
797 11b32d91 Ondrej Zajicek
static sock *
798 789772ed Ondrej Zajicek
bgp_setup_listen_sk(ip_addr addr, unsigned port, u32 flags)
799 48e842cc Martin Mares
{
800 11b32d91 Ondrej Zajicek
  sock *s = sk_new(&root_pool);
801 a34b0934 Ondrej Zajicek
  DBG("BGP: Creating listening socket\n");
802 11b32d91 Ondrej Zajicek
  s->type = SK_TCP_PASSIVE;
803 b1b19433 Ondrej Zajicek
  s->ttl = 255;
804 789772ed Ondrej Zajicek
  s->saddr = addr;
805
  s->sport = port ? port : BGP_PORT;
806 fcf5a4f4 Ondrej Zajicek
  s->flags = flags ? 0 : SKF_V6ONLY;
807 11b32d91 Ondrej Zajicek
  s->tos = IP_PREC_INTERNET_CONTROL;
808
  s->rbsize = BGP_RX_BUFFER_SIZE;
809
  s->tbsize = BGP_TX_BUFFER_SIZE;
810
  s->rx_hook = bgp_incoming_connection;
811 2af25a97 Ondrej Zajicek
  s->err_hook = bgp_listen_sock_err;
812 b1b19433 Ondrej Zajicek
813
  if (sk_open(s) < 0)
814 05476c4d Ondrej Zajicek
    goto err;
815 b1b19433 Ondrej Zajicek
816
  return s;
817 05476c4d Ondrej Zajicek
818
 err:
819
  sk_log_error(s, "BGP");
820
  log(L_ERR "BGP: Cannot open listening socket");
821
  rfree(s);
822
  return NULL;
823 acfce55c Martin Mares
}
824
825
static void
826
bgp_start_neighbor(struct bgp_proto *p)
827
{
828 9be9a264 Ondrej Zajicek
  /* Called only for single-hop BGP sessions */
829
830
  if (ipa_zero(p->source_addr))
831 523f020b Ondrej Zajicek
    p->source_addr = p->neigh->ifa->ip;
832 ad440a57 Ondrej Zajicek
833 11d4474c Martin Mares
#ifdef IPV6
834
  {
835
    struct ifa *a;
836 4827b69f Ondrej Zajicek
    p->local_link = IPA_NONE;
837 11d4474c Martin Mares
    WALK_LIST(a, p->neigh->iface->addrs)
838
      if (a->scope == SCOPE_LINK)
839
        {
840
          p->local_link = a->ip;
841
          break;
842
        }
843 4827b69f Ondrej Zajicek
844
    if (! ipa_nonzero(p->local_link))
845
      log(L_WARN "%s: Missing link local address on interface %s", p->p.name,  p->neigh->iface->name);
846
847 11d4474c Martin Mares
    DBG("BGP: Selected link-level address %I\n", p->local_link);
848
  }
849
#endif
850 11b32d91 Ondrej Zajicek
851 6fd766c1 Martin Mares
  bgp_initiate(p);
852 48e842cc Martin Mares
}
853
854
static void
855
bgp_neigh_notify(neighbor *n)
856
{
857
  struct bgp_proto *p = (struct bgp_proto *) n->proto;
858 523f020b Ondrej Zajicek
  int ps = p->p.proto_state;
859
860
  if (n != p->neigh)
861
    return;
862 48e842cc Martin Mares
863 523f020b Ondrej Zajicek
  if ((ps == PS_DOWN) || (ps == PS_STOP))
864 b21955e0 Ondrej Zajicek
    return;
865
866 523f020b Ondrej Zajicek
  int prepare = (ps == PS_START) && (p->start_state == BSS_PREPARE);
867
868
  if (n->scope <= 0)
869 48e842cc Martin Mares
    {
870 523f020b Ondrej Zajicek
      if (!prepare)
871
        {
872
          BGP_TRACE(D_EVENTS, "Neighbor lost");
873
          bgp_store_error(p, NULL, BE_MISC, BEM_NEIGHBOR_LOST);
874
          /* Perhaps also run bgp_update_startup_delay(p)? */
875
          bgp_stop(p, 0);
876
        }
877
    }
878
  else if (p->cf->check_link && !(n->iface->flags & IF_LINK_UP))
879
    {
880
      if (!prepare)
881
        {
882
          BGP_TRACE(D_EVENTS, "Link down");
883
          bgp_store_error(p, NULL, BE_MISC, BEM_LINK_DOWN);
884
          if (ps == PS_UP)
885
            bgp_update_startup_delay(p);
886
          bgp_stop(p, 0);
887 11b32d91 Ondrej Zajicek
        }
888 48e842cc Martin Mares
    }
889
  else
890
    {
891 523f020b Ondrej Zajicek
      if (prepare)
892 11b32d91 Ondrej Zajicek
        {
893 523f020b Ondrej Zajicek
          BGP_TRACE(D_EVENTS, "Neighbor ready");
894
          bgp_start_neighbor(p);
895 11b32d91 Ondrej Zajicek
        }
896 48e842cc Martin Mares
    }
897
}
898
899 1ec52253 Ondrej Zajicek
static void
900
bgp_bfd_notify(struct bfd_request *req)
901
{
902
  struct bgp_proto *p = req->data;
903
  int ps = p->p.proto_state;
904
905
  if (req->down && ((ps == PS_START) || (ps == PS_UP)))
906
    {
907
      BGP_TRACE(D_EVENTS, "BFD session down");
908
      bgp_store_error(p, NULL, BE_MISC, BEM_BFD_DOWN);
909
      if (ps == PS_UP)
910
        bgp_update_startup_delay(p);
911
      bgp_stop(p, 0);
912
    }
913
}
914
915
static void
916
bgp_update_bfd(struct bgp_proto *p, int use_bfd)
917
{
918
  if (use_bfd && !p->bfd_req)
919
    p->bfd_req = bfd_request_session(p->p.pool, p->cf->remote_ip, p->source_addr,
920
                                     p->cf->multihop ? NULL : p->neigh->iface,
921
                                     bgp_bfd_notify, p);
922
923
  if (!use_bfd && p->bfd_req)
924
    {
925
      rfree(p->bfd_req);
926
      p->bfd_req = NULL;
927
    }
928
}
929
930 bf47fe4b Ondrej Zajicek
static int
931
bgp_reload_routes(struct proto *P)
932
{
933
  struct bgp_proto *p = (struct bgp_proto *) P;
934
  if (!p->conn || !p->conn->peer_refresh_support)
935
    return 0;
936
937
  bgp_schedule_packet(p->conn, PKT_ROUTE_REFRESH);
938
  return 1;
939
}
940
941 48e842cc Martin Mares
static void
942 0c791f87 Ondrej Zajicek
bgp_feed_done(struct proto *P)
943
{
944
  struct bgp_proto *p = (struct bgp_proto *) P;
945 227af309 Ondrej Zajicek
  if (!p->conn || !p->cf->gr_mode || p->p.refeeding)
946 0c791f87 Ondrej Zajicek
    return;
947
948
  p->send_end_mark = 1;
949
  bgp_schedule_packet(p->conn, PKT_UPDATE);
950
}
951
952
static void
953 48e842cc Martin Mares
bgp_start_locked(struct object_lock *lock)
954
{
955
  struct bgp_proto *p = lock->data;
956
  struct bgp_config *cf = p->cf;
957
958 11b32d91 Ondrej Zajicek
  if (p->p.proto_state != PS_START)
959
    {
960
      DBG("BGP: Got lock in different state %d\n", p->p.proto_state);
961 9be9a264 Ondrej Zajicek
      return;
962 11b32d91 Ondrej Zajicek
    }
963
964 48e842cc Martin Mares
  DBG("BGP: Got lock\n");
965 4847a894 Ondrej Zajicek
966 9be9a264 Ondrej Zajicek
  if (cf->multihop)
967 4847a894 Ondrej Zajicek
    {
968 9be9a264 Ondrej Zajicek
      /* Multi-hop sessions do not use neighbor entries */
969
      bgp_initiate(p);
970
      return;
971 4847a894 Ondrej Zajicek
    }
972
973 523f020b Ondrej Zajicek
  neighbor *n = neigh_find2(&p->p, &cf->remote_ip, cf->iface, NEF_STICKY);
974
  if (!n)
975 48e842cc Martin Mares
    {
976 53ffbff3 Ondrej Zajicek
      log(L_ERR "%s: Invalid remote address %I%J", p->p.name, cf->remote_ip, cf->iface);
977 11b32d91 Ondrej Zajicek
      /* As we do not start yet, we can just disable protocol */
978 48e842cc Martin Mares
      p->p.disabled = 1;
979 11b32d91 Ondrej Zajicek
      bgp_store_error(p, NULL, BE_MISC, BEM_INVALID_NEXT_HOP);
980 48e842cc Martin Mares
      proto_notify_state(&p->p, PS_DOWN);
981 11b32d91 Ondrej Zajicek
      return;
982 48e842cc Martin Mares
    }
983 523f020b Ondrej Zajicek
984
  p->neigh = n;
985
986
  if (n->scope <= 0)
987 53ffbff3 Ondrej Zajicek
    BGP_TRACE(D_EVENTS, "Waiting for %I%J to become my neighbor", cf->remote_ip, cf->iface);
988 523f020b Ondrej Zajicek
  else if (p->cf->check_link && !(n->iface->flags & IF_LINK_UP))
989
    BGP_TRACE(D_EVENTS, "Waiting for link on %s", n->iface->name);
990
  else
991
    bgp_start_neighbor(p);
992 c01e3741 Martin Mares
}
993
994 2638249d Martin Mares
static int
995
bgp_start(struct proto *P)
996
{
997 c01e3741 Martin Mares
  struct bgp_proto *p = (struct bgp_proto *) P;
998
  struct object_lock *lock;
999
1000 b552ecc4 Martin Mares
  DBG("BGP: Startup.\n");
1001 11b32d91 Ondrej Zajicek
  p->start_state = BSS_PREPARE;
1002 b552ecc4 Martin Mares
  p->outgoing_conn.state = BS_IDLE;
1003
  p->incoming_conn.state = BS_IDLE;
1004 bcbdcbb6 Martin Mares
  p->neigh = NULL;
1005 1ec52253 Ondrej Zajicek
  p->bfd_req = NULL;
1006 0c791f87 Ondrej Zajicek
  p->gr_ready = 0;
1007
  p->gr_active = 0;
1008 b552ecc4 Martin Mares
1009 cfe34a31 Ondrej Zajicek
  rt_lock_table(p->igp_table);
1010
1011 11b32d91 Ondrej Zajicek
  p->event = ev_new(p->p.pool);
1012
  p->event->hook = bgp_decision;
1013
  p->event->data = p;
1014 79681f4a Martin Mares
1015 dd91e467 Ondrej Zajicek
  p->startup_timer = tm_new(p->p.pool);
1016
  p->startup_timer->hook = bgp_startup_timeout;
1017
  p->startup_timer->data = p;
1018
1019 0c791f87 Ondrej Zajicek
  p->gr_timer = tm_new(p->p.pool);
1020
  p->gr_timer->hook = bgp_graceful_restart_timeout;
1021
  p->gr_timer->data = p;
1022
1023 4ef09506 Ondrej Zajicek
  p->local_id = proto_get_router_id(P->cf);
1024
  if (p->rr_client)
1025
    p->rr_cluster_id = p->cf->rr_cluster_id ? p->cf->rr_cluster_id : p->local_id;
1026
1027 9be9a264 Ondrej Zajicek
  p->remote_id = 0;
1028
  p->source_addr = p->cf->source_addr;
1029
1030 6eda3f13 Ondrej Zajicek
  if (p->p.gr_recovery && p->cf->gr_mode)
1031 0c791f87 Ondrej Zajicek
    proto_graceful_restart_lock(P);
1032
1033 c01e3741 Martin Mares
  /*
1034
   *  Before attempting to create the connection, we need to lock the
1035
   *  port, so that are sure we're the only instance attempting to talk
1036
   *  with that neighbor.
1037
   */
1038
1039
  lock = p->lock = olock_new(P->pool);
1040
  lock->addr = p->cf->remote_ip;
1041 dcde7ae5 Ondrej Zajicek
  lock->port = p->cf->remote_port;
1042 53ffbff3 Ondrej Zajicek
  lock->iface = p->cf->iface;
1043 c01e3741 Martin Mares
  lock->type = OBJLOCK_TCP;
1044
  lock->hook = bgp_start_locked;
1045
  lock->data = p;
1046
  olock_acquire(lock);
1047 d51aa281 Ondrej Zajicek
1048 c01e3741 Martin Mares
  return PS_START;
1049 2638249d Martin Mares
}
1050
1051 d9b77cc2 Ondrej Zajicek
extern int proto_restart;
1052
1053 2638249d Martin Mares
static int
1054
bgp_shutdown(struct proto *P)
1055
{
1056 c01e3741 Martin Mares
  struct bgp_proto *p = (struct bgp_proto *) P;
1057 ebecb6f6 Ondrej Zajicek
  unsigned subcode = 0;
1058 c01e3741 Martin Mares
1059 85368cd4 Martin Mares
  BGP_TRACE(D_EVENTS, "Shutdown requested");
1060 b99d3786 Ondrej Zajicek
1061 ebecb6f6 Ondrej Zajicek
  switch (P->down_code)
1062 b99d3786 Ondrej Zajicek
    {
1063 ebecb6f6 Ondrej Zajicek
    case PDC_CF_REMOVE:
1064
    case PDC_CF_DISABLE:
1065
      subcode = 3; // Errcode 6, 3 - peer de-configured
1066
      break;
1067
1068
    case PDC_CF_RESTART:
1069
      subcode = 6; // Errcode 6, 6 - other configuration change
1070
      break;
1071
1072
    case PDC_CMD_DISABLE:
1073 5400c0e7 Ondrej Zajicek
    case PDC_CMD_SHUTDOWN:
1074 ebecb6f6 Ondrej Zajicek
      subcode = 2; // Errcode 6, 2 - administrative shutdown
1075
      break;
1076
1077
    case PDC_CMD_RESTART:
1078
      subcode = 4; // Errcode 6, 4 - administrative reset
1079
      break;
1080
1081 b662290f Ondrej Zajicek
    case PDC_RX_LIMIT_HIT:
1082 ebecb6f6 Ondrej Zajicek
    case PDC_IN_LIMIT_HIT:
1083
      subcode = 1; // Errcode 6, 1 - max number of prefixes reached
1084 d9b77cc2 Ondrej Zajicek
      /* log message for compatibility */
1085 ebecb6f6 Ondrej Zajicek
      log(L_WARN "%s: Route limit exceeded, shutting down", p->p.name);
1086 d9b77cc2 Ondrej Zajicek
      goto limit;
1087
1088
    case PDC_OUT_LIMIT_HIT:
1089
      subcode = proto_restart ? 4 : 2; // Administrative reset or shutdown
1090 ebecb6f6 Ondrej Zajicek
1091 d9b77cc2 Ondrej Zajicek
    limit:
1092 ebecb6f6 Ondrej Zajicek
      bgp_store_error(p, NULL, BE_AUTO_DOWN, BEA_ROUTE_LIMIT_EXCEEDED);
1093 d9b77cc2 Ondrej Zajicek
      if (proto_restart)
1094 ebecb6f6 Ondrej Zajicek
        bgp_update_startup_delay(p);
1095 b99d3786 Ondrej Zajicek
      else
1096 ebecb6f6 Ondrej Zajicek
        p->startup_delay = 0;
1097
      goto done;
1098 b99d3786 Ondrej Zajicek
    }
1099
1100 ebecb6f6 Ondrej Zajicek
  bgp_store_error(p, NULL, BE_MAN_DOWN, 0);
1101 11b32d91 Ondrej Zajicek
  p->startup_delay = 0;
1102 c01e3741 Martin Mares
1103 ebecb6f6 Ondrej Zajicek
 done:
1104
  bgp_stop(p, subcode);
1105 11b32d91 Ondrej Zajicek
  return p->p.proto_state;
1106 2638249d Martin Mares
}
1107
1108 cfe34a31 Ondrej Zajicek
static void
1109
bgp_cleanup(struct proto *P)
1110
{
1111
  struct bgp_proto *p = (struct bgp_proto *) P;
1112
  rt_unlock_table(p->igp_table);
1113
}
1114
1115
static rtable *
1116
get_igp_table(struct bgp_config *cf)
1117
{
1118
  return cf->igp_table ? cf->igp_table->table : cf->c.table->table;
1119
}
1120
1121 48e842cc Martin Mares
static struct proto *
1122
bgp_init(struct proto_config *C)
1123
{
1124
  struct proto *P = proto_new(C, sizeof(struct bgp_proto));
1125 094d2bdb Ondrej Zajicek
  struct bgp_config *c = (struct bgp_config *) C;
1126 48e842cc Martin Mares
  struct bgp_proto *p = (struct bgp_proto *) P;
1127
1128 00a09f3c Ondrej Zajicek
  P->accept_ra_types = c->secondary ? RA_ACCEPTED : RA_OPTIMAL;
1129 48e842cc Martin Mares
  P->rt_notify = bgp_rt_notify;
1130
  P->import_control = bgp_import_control;
1131
  P->neigh_notify = bgp_neigh_notify;
1132 bf47fe4b Ondrej Zajicek
  P->reload_routes = bgp_reload_routes;
1133 0c791f87 Ondrej Zajicek
  P->feed_done = bgp_feed_done;
1134 094d2bdb Ondrej Zajicek
  P->rte_better = bgp_rte_better;
1135
  P->rte_recalculate = c->deterministic_med ? bgp_rte_recalculate : NULL;
1136 be4cd99a Ondrej Zajicek
1137 48e842cc Martin Mares
  p->cf = c;
1138
  p->local_as = c->local_as;
1139
  p->remote_as = c->remote_as;
1140
  p->is_internal = (c->local_as == c->remote_as);
1141 9be9a264 Ondrej Zajicek
  p->rs_client = c->rs_client;
1142
  p->rr_client = c->rr_client;
1143 cfe34a31 Ondrej Zajicek
  p->igp_table = get_igp_table(c);
1144 9be9a264 Ondrej Zajicek
1145 48e842cc Martin Mares
  return P;
1146
}
1147
1148 a7f23f58 Ondrej Zajicek
1149
void
1150
bgp_check_config(struct bgp_config *c)
1151
{
1152
  int internal = (c->local_as == c->remote_as);
1153
1154
  /* Do not check templates at all */
1155
  if (c->c.class == SYM_TEMPLATE)
1156
    return;
1157
1158 f3e59178 Ondrej Zajicek
1159
  /* EBGP direct by default, IBGP multihop by default */
1160
  if (c->multihop < 0)
1161
    c->multihop = internal ? 64 : 0;
1162
1163
  /* Different default for gw_mode */
1164
  if (!c->gw_mode)
1165
    c->gw_mode = c->multihop ? GW_RECURSIVE : GW_DIRECT;
1166
1167
  /* Different default based on rs_client */
1168
  if (!c->missing_lladdr)
1169
    c->missing_lladdr = c->rs_client ? MLL_IGNORE : MLL_SELF;
1170
1171
  /* Disable after error incompatible with restart limit action */
1172
  if (c->c.in_limit && (c->c.in_limit->action == PLA_RESTART) && c->disable_after_error)
1173
    c->c.in_limit->action = PLA_DISABLE;
1174
1175
1176 a7f23f58 Ondrej Zajicek
  if (!c->local_as)
1177
    cf_error("Local AS number must be set");
1178
1179
  if (!c->remote_as)
1180
    cf_error("Neighbor must be configured");
1181
1182
  if (!(c->capabilities && c->enable_as4) && (c->remote_as > 0xFFFF))
1183
    cf_error("Neighbor AS number out of range (AS4 not available)");
1184
1185
  if (!internal && c->rr_client)
1186
    cf_error("Only internal neighbor can be RR client");
1187
1188
  if (internal && c->rs_client)
1189
    cf_error("Only external neighbor can be RS client");
1190
1191
  if (c->multihop && (c->gw_mode == GW_DIRECT))
1192
    cf_error("Multihop BGP cannot use direct gateway mode");
1193
1194 88a183c6 Ondrej Zajicek
  if (c->multihop && (ipa_is_link_local(c->remote_ip) ||
1195
                      ipa_is_link_local(c->source_addr)))
1196 53ffbff3 Ondrej Zajicek
    cf_error("Multihop BGP cannot be used with link-local addresses");
1197
1198 523f020b Ondrej Zajicek
  if (c->multihop && c->check_link)
1199
    cf_error("Multihop BGP cannot depend on link state");
1200
1201 1ec52253 Ondrej Zajicek
  if (c->multihop && c->bfd && ipa_zero(c->source_addr))
1202
    cf_error("Multihop BGP with BFD requires specified source address");
1203
1204 26822d8f Ondrej Zajicek
  if ((c->gw_mode == GW_RECURSIVE) && c->c.table->sorted)
1205
    cf_error("BGP in recursive mode prohibits sorted table");
1206
1207
  if (c->deterministic_med && c->c.table->sorted)
1208
    cf_error("BGP with deterministic MED prohibits sorted table");
1209
1210
  if (c->secondary && !c->c.table->sorted)
1211
    cf_error("BGP with secondary option requires sorted table");
1212 a7f23f58 Ondrej Zajicek
}
1213
1214
static int
1215
bgp_reconfigure(struct proto *P, struct proto_config *C)
1216
{
1217
  struct bgp_config *new = (struct bgp_config *) C;
1218
  struct bgp_proto *p = (struct bgp_proto *) P;
1219
  struct bgp_config *old = p->cf;
1220
1221 79b4e12e Ondrej Zajicek
  if (proto_get_router_id(C) != p->local_id)
1222
    return 0;
1223
1224 a7f23f58 Ondrej Zajicek
  int same = !memcmp(((byte *) old) + sizeof(struct proto_config),
1225
                     ((byte *) new) + sizeof(struct proto_config),
1226
                     // password item is last and must be checked separately
1227
                     OFFSETOF(struct bgp_config, password) - sizeof(struct proto_config))
1228
    && ((!old->password && !new->password)
1229
        || (old->password && new->password && !strcmp(old->password, new->password)))
1230
    && (get_igp_table(old) == get_igp_table(new));
1231
1232 1ec52253 Ondrej Zajicek
  if (same && (p->start_state > BSS_PREPARE))
1233
    bgp_update_bfd(p, new->bfd);
1234
1235 a7f23f58 Ondrej Zajicek
  /* We should update our copy of configuration ptr as old configuration will be freed */
1236
  if (same)
1237
    p->cf = new;
1238
1239
  return same;
1240
}
1241
1242
static void
1243
bgp_copy_config(struct proto_config *dest, struct proto_config *src)
1244
{
1245
  /* Just a shallow copy */
1246
  proto_copy_rest(dest, src, sizeof(struct bgp_config));
1247
}
1248
1249
1250 54e55169 Martin Mares
/**
1251
 * bgp_error - report a protocol error
1252
 * @c: connection
1253
 * @code: error code (according to the RFC)
1254 2e9b2421 Martin Mares
 * @subcode: error sub-code
1255 54e55169 Martin Mares
 * @data: data to be passed in the Notification message
1256
 * @len: length of the data
1257
 *
1258
 * bgp_error() sends a notification packet to tell the other side that a protocol
1259 2e9b2421 Martin Mares
 * error has occurred (including the data considered erroneous if possible) and
1260 54e55169 Martin Mares
 * closes the connection.
1261
 */
1262 2638249d Martin Mares
void
1263 efcece2d Martin Mares
bgp_error(struct bgp_conn *c, unsigned code, unsigned subcode, byte *data, int len)
1264 3fdbafb6 Martin Mares
{
1265 b99d3786 Ondrej Zajicek
  struct bgp_proto *p = c->bgp;
1266
1267 11b32d91 Ondrej Zajicek
  if (c->state == BS_CLOSE)
1268 3fdbafb6 Martin Mares
    return;
1269 11b32d91 Ondrej Zajicek
1270 b99d3786 Ondrej Zajicek
  bgp_log_error(p, BE_BGP_TX, "Error", code, subcode, data, (len > 0) ? len : -len);
1271
  bgp_store_error(p, c, BE_BGP_TX, (code << 16) | subcode);
1272 11b32d91 Ondrej Zajicek
  bgp_conn_enter_close_state(c);
1273
1274 3fdbafb6 Martin Mares
  c->notify_code = code;
1275
  c->notify_subcode = subcode;
1276 efcece2d Martin Mares
  c->notify_data = data;
1277
  c->notify_size = (len > 0) ? len : 0;
1278 3fdbafb6 Martin Mares
  bgp_schedule_packet(c, PKT_NOTIFICATION);
1279 b99d3786 Ondrej Zajicek
1280
  if (code != 6)
1281
    {
1282
      bgp_update_startup_delay(p);
1283
      bgp_stop(p, 0);
1284
    }
1285 3fdbafb6 Martin Mares
}
1286
1287 11b32d91 Ondrej Zajicek
/**
1288
 * bgp_store_error - store last error for status report
1289
 * @p: BGP instance
1290
 * @c: connection
1291
 * @class: error class (BE_xxx constants)
1292
 * @code: error code (class specific)
1293
 *
1294
 * bgp_store_error() decides whether given error is interesting enough
1295
 * and store that error to last_error variables of @p
1296
 */
1297
void
1298
bgp_store_error(struct bgp_proto *p, struct bgp_conn *c, u8 class, u32 code)
1299
{
1300
  /* During PS_UP, we ignore errors on secondary connection */
1301
  if ((p->p.proto_state == PS_UP) && c && (c != p->conn))
1302
    return;
1303
1304
  /* During PS_STOP, we ignore any errors, as we want to report
1305
   * the error that caused transition to PS_STOP
1306
   */
1307
  if (p->p.proto_state == PS_STOP)
1308
    return;
1309
1310
  p->last_error_class = class;
1311
  p->last_error_code = code;
1312
}
1313
1314
static char *bgp_state_names[] = { "Idle", "Connect", "Active", "OpenSent", "OpenConfirm", "Established", "Close" };
1315 72b28a04 Ondrej Zajicek
static char *bgp_err_classes[] = { "", "Error: ", "Socket: ", "Received: ", "BGP Error: ", "Automatic shutdown: ", ""};
1316 523f020b Ondrej Zajicek
static char *bgp_misc_errors[] = { "", "Neighbor lost", "Invalid next hop", "Kernel MD5 auth failed", "No listening socket", "Link down", "BFD session down", "Graceful restart"};
1317 72b28a04 Ondrej Zajicek
static char *bgp_auto_errors[] = { "", "Route limit exceeded"};
1318 11b32d91 Ondrej Zajicek
1319 b8113a5e Ondrej Zajicek
static const char *
1320
bgp_last_errmsg(struct bgp_proto *p)
1321 973399ae Martin Mares
{
1322 11b32d91 Ondrej Zajicek
  switch (p->last_error_class)
1323
    {
1324
    case BE_MISC:
1325 b8113a5e Ondrej Zajicek
      return bgp_misc_errors[p->last_error_code];
1326 11b32d91 Ondrej Zajicek
    case BE_SOCKET:
1327 b8113a5e Ondrej Zajicek
      return (p->last_error_code == 0) ? "Connection closed" : strerror(p->last_error_code);
1328 11b32d91 Ondrej Zajicek
    case BE_BGP_RX:
1329
    case BE_BGP_TX:
1330 b8113a5e Ondrej Zajicek
      return bgp_error_dsc(p->last_error_code >> 16, p->last_error_code & 0xFF);
1331 72b28a04 Ondrej Zajicek
    case BE_AUTO_DOWN:
1332 b8113a5e Ondrej Zajicek
      return bgp_auto_errors[p->last_error_code];
1333
    default:
1334
      return "";
1335 11b32d91 Ondrej Zajicek
    }
1336 b8113a5e Ondrej Zajicek
}
1337
1338
static const char *
1339
bgp_state_dsc(struct bgp_proto *p)
1340
{
1341 51947659 Ondrej Zajicek
  if (p->p.proto_state == PS_DOWN)
1342
    return "Down";
1343 b8113a5e Ondrej Zajicek
1344
  int state = MAX(p->incoming_conn.state, p->outgoing_conn.state);
1345
  if ((state == BS_IDLE) && (p->start_state >= BSS_CONNECT) && p->cf->passive)
1346
    return "Passive";
1347
1348
  return bgp_state_names[state];
1349
}
1350
1351
static void
1352
bgp_get_status(struct proto *P, byte *buf)
1353
{
1354
  struct bgp_proto *p = (struct bgp_proto *) P;
1355
1356
  const char *err1 = bgp_err_classes[p->last_error_class];
1357
  const char *err2 = bgp_last_errmsg(p);
1358 11b32d91 Ondrej Zajicek
1359 f4ab2317 Martin Mares
  if (P->proto_state == PS_DOWN)
1360 11b32d91 Ondrej Zajicek
    bsprintf(buf, "%s%s", err1, err2);
1361 f4ab2317 Martin Mares
  else
1362 b8113a5e Ondrej Zajicek
    bsprintf(buf, "%-14s%s%s", bgp_state_dsc(p), err1, err2);
1363
}
1364
1365
static void
1366
bgp_show_proto_info(struct proto *P)
1367
{
1368
  struct bgp_proto *p = (struct bgp_proto *) P;
1369
  struct bgp_conn *c = p->conn;
1370
1371 c0adf7e9 Ondrej Zajicek
  proto_show_basic_info(P);
1372
1373 b8113a5e Ondrej Zajicek
  cli_msg(-1006, "  BGP state:          %s", bgp_state_dsc(p));
1374 53ffbff3 Ondrej Zajicek
  cli_msg(-1006, "    Neighbor address: %I%J", p->cf->remote_ip, p->cf->iface);
1375 51947659 Ondrej Zajicek
  cli_msg(-1006, "    Neighbor AS:      %u", p->remote_as);
1376 b8113a5e Ondrej Zajicek
1377 0c791f87 Ondrej Zajicek
  if (p->gr_active)
1378
    cli_msg(-1006, "    Neighbor graceful restart active");
1379
1380 b8113a5e Ondrej Zajicek
  if (P->proto_state == PS_START)
1381
    {
1382
      struct bgp_conn *oc = &p->outgoing_conn;
1383
1384
      if ((p->start_state < BSS_CONNECT) &&
1385
          (p->startup_timer->expires))
1386 0c791f87 Ondrej Zajicek
        cli_msg(-1006, "    Error wait:       %d/%d",
1387 b8113a5e Ondrej Zajicek
                p->startup_timer->expires - now, p->startup_delay);
1388
1389
      if ((oc->state == BS_ACTIVE) &&
1390
          (oc->connect_retry_timer->expires))
1391 0c791f87 Ondrej Zajicek
        cli_msg(-1006, "    Start delay:      %d/%d",
1392 b8113a5e Ondrej Zajicek
                oc->connect_retry_timer->expires - now, p->cf->start_delay_time);
1393 0c791f87 Ondrej Zajicek
1394
      if (p->gr_active && p->gr_timer->expires)
1395
        cli_msg(-1006, "    Restart timer:    %d/-", p->gr_timer->expires - now);
1396 b8113a5e Ondrej Zajicek
    }
1397
  else if (P->proto_state == PS_UP)
1398
    {
1399 51947659 Ondrej Zajicek
      cli_msg(-1006, "    Neighbor ID:      %R", p->remote_id);
1400 0c791f87 Ondrej Zajicek
      cli_msg(-1006, "    Neighbor caps:   %s%s%s%s%s",
1401 51947659 Ondrej Zajicek
              c->peer_refresh_support ? " refresh" : "",
1402 0c791f87 Ondrej Zajicek
              c->peer_gr_able ? " restart-able" : (c->peer_gr_aware ? " restart-aware" : ""),
1403 094d2bdb Ondrej Zajicek
              c->peer_as4_support ? " AS4" : "",
1404
              (c->peer_add_path & ADD_PATH_RX) ? " add-path-rx" : "",
1405
              (c->peer_add_path & ADD_PATH_TX) ? " add-path-tx" : "");
1406
      cli_msg(-1006, "    Session:          %s%s%s%s%s%s%s",
1407 b8113a5e Ondrej Zajicek
              p->is_internal ? "internal" : "external",
1408 51947659 Ondrej Zajicek
              p->cf->multihop ? " multihop" : "",
1409 b8113a5e Ondrej Zajicek
              p->rr_client ? " route-reflector" : "",
1410
              p->rs_client ? " route-server" : "",
1411 094d2bdb Ondrej Zajicek
              p->as4_session ? " AS4" : "",
1412
              p->add_path_rx ? " add-path-rx" : "",
1413
              p->add_path_tx ? " add-path-tx" : "");
1414 b8113a5e Ondrej Zajicek
      cli_msg(-1006, "    Source address:   %I", p->source_addr);
1415 7d0a31de Ondrej Zajicek
      if (P->cf->in_limit)
1416 b8113a5e Ondrej Zajicek
        cli_msg(-1006, "    Route limit:      %d/%d",
1417 15550957 Ondrej Zajicek
                p->p.stats.imp_routes + p->p.stats.filt_routes, P->cf->in_limit->limit);
1418 35f8c731 Ondrej Zajicek
      cli_msg(-1006, "    Hold timer:       %d/%d",
1419
              tm_remains(c->hold_timer), c->hold_time);
1420
      cli_msg(-1006, "    Keepalive timer:  %d/%d",
1421
              tm_remains(c->keepalive_timer), c->keepalive_time);
1422 b8113a5e Ondrej Zajicek
    }
1423
1424 523f020b Ondrej Zajicek
  if ((p->last_error_class != BE_NONE) &&
1425 b8113a5e Ondrej Zajicek
      (p->last_error_class != BE_MAN_DOWN))
1426
    {
1427
      const char *err1 = bgp_err_classes[p->last_error_class];
1428
      const char *err2 = bgp_last_errmsg(p);
1429
      cli_msg(-1006, "    Last error:       %s%s", err1, err2);
1430
    }
1431 973399ae Martin Mares
}
1432
1433 2638249d Martin Mares
struct protocol proto_bgp = {
1434 4a591d4b Pavel Tvrdik
  .name =                 "BGP",
1435
  .template =                 "bgp%d",
1436
  .attr_class =         EAP_BGP,
1437
  .preference =         DEF_PREF_BGP,
1438
  .init =                 bgp_init,
1439
  .start =                 bgp_start,
1440
  .shutdown =                 bgp_shutdown,
1441
  .cleanup =                 bgp_cleanup,
1442
  .reconfigure =         bgp_reconfigure,
1443
  .copy_config =         bgp_copy_config,
1444
  .get_status =         bgp_get_status,
1445
  .get_attr =                 bgp_get_attr,
1446
  .get_route_info =         bgp_get_route_info,
1447
  .show_proto_info =         bgp_show_proto_info
1448 2638249d Martin Mares
};