Coverage Report

Created: 2026-10-28 07:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/frr/bgpd/bgp_main.c
Line
Count
Source
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
/* Main routine of bgpd.
3
 * Copyright (C) 1996, 97, 98, 1999 Kunihiro Ishiguro
4
 */
5
6
#include <zebra.h>
7
8
#include <pthread.h>
9
#include "vector.h"
10
#include "command.h"
11
#include "getopt.h"
12
#include "frrevent.h"
13
#include <lib/version.h>
14
#include "memory.h"
15
#include "prefix.h"
16
#include "log.h"
17
#include "privs.h"
18
#include "sigevent.h"
19
#include "zclient.h"
20
#include "routemap.h"
21
#include "filter.h"
22
#include "plist.h"
23
#include "stream.h"
24
#include "queue.h"
25
#include "vrf.h"
26
#include "bfd.h"
27
#include "libfrr.h"
28
#include "ns.h"
29
30
#include "bgpd/bgpd.h"
31
#include "bgp_io.h"
32
#include "bgpd/bgp_attr.h"
33
#include "bgpd/bgp_route.h"
34
#include "bgpd/bgp_mplsvpn.h"
35
#include "bgpd/bgp_aspath.h"
36
#include "bgpd/bgp_dump.h"
37
#include "bgpd/bgp_route.h"
38
#include "bgpd/bgp_nexthop.h"
39
#include "bgpd/bgp_regex.h"
40
#include "bgpd/bgp_clist.h"
41
#include "bgpd/bgp_debug.h"
42
#include "bgpd/bgp_errors.h"
43
#include "bgpd/bgp_filter.h"
44
#include "bgpd/bgp_zebra.h"
45
#include "bgpd/bgp_packet.h"
46
#include "bgpd/bgp_keepalives.h"
47
#include "bgpd/bgp_network.h"
48
#include "bgpd/bgp_errors.h"
49
#include "bgpd/bgp_script.h"
50
#include "bgpd/bgp_evpn_mh.h"
51
#include "bgpd/bgp_nht.h"
52
#include "bgpd/bgp_routemap_nb.h"
53
#include "bgpd/bgp_community_alias.h"
54
55
#ifdef ENABLE_BGP_VNC
56
#include "bgpd/rfapi/rfapi_backend.h"
57
#endif
58
59
/* bgpd options, we use GNU getopt library. */
60
static const struct option longopts[] = {
61
  {"bgp_port", required_argument, NULL, 'p'},
62
  {"listenon", required_argument, NULL, 'l'},
63
  {"no_kernel", no_argument, NULL, 'n'},
64
  {"skip_runas", no_argument, NULL, 'S'},
65
  {"ecmp", required_argument, NULL, 'e'},
66
  {"int_num", required_argument, NULL, 'I'},
67
  {"no_zebra", no_argument, NULL, 'Z'},
68
  {"socket_size", required_argument, NULL, 's'},
69
  {0}};
70
71
/* signal definitions */
72
void sighup(void);
73
void sigint(void);
74
void sigusr1(void);
75
76
static void bgp_exit(int);
77
static void bgp_vrf_terminate(void);
78
79
static struct frr_signal_t bgp_signals[] = {
80
  {
81
    .signal = SIGHUP,
82
    .handler = &sighup,
83
  },
84
  {
85
    .signal = SIGUSR1,
86
    .handler = &sigusr1,
87
  },
88
  {
89
    .signal = SIGINT,
90
    .handler = &sigint,
91
  },
92
  {
93
    .signal = SIGTERM,
94
    .handler = &sigint,
95
  },
96
};
97
98
/* privileges */
99
static zebra_capabilities_t _caps_p[] = {ZCAP_BIND, ZCAP_NET_RAW,
100
           ZCAP_NET_ADMIN, ZCAP_SYS_ADMIN};
101
102
struct zebra_privs_t bgpd_privs = {
103
#if defined(FRR_USER) && defined(FRR_GROUP)
104
  .user = FRR_USER,
105
  .group = FRR_GROUP,
106
#endif
107
#ifdef VTY_GROUP
108
  .vty_group = VTY_GROUP,
109
#endif
110
  .caps_p = _caps_p,
111
  .cap_num_p = array_size(_caps_p),
112
  .cap_num_i = 0,
113
};
114
115
static struct frr_daemon_info bgpd_di;
116
117
/* SIGHUP handler. */
118
void sighup(void)
119
0
{
120
0
  zlog_info("SIGHUP received, ignoring");
121
122
0
  return;
123
124
  /*
125
   * This is turned off for the moment.  There is all
126
   * sorts of config turned off by bgp_terminate
127
   * that is not setup properly again in bgp_reset.
128
   * I see no easy way to do this nor do I see that
129
   * this is a desirable way to reload config
130
   * given the yang work.
131
   */
132
  /* Terminate all thread. */
133
  /*
134
   * bgp_terminate();
135
   * bgp_reset();
136
   * zlog_info("bgpd restarting!");
137
138
   * Reload config file.
139
   * vty_read_config(NULL, bgpd_di.config_file, config_default);
140
   */
141
  /* Try to return to normal operation. */
142
0
}
143
144
/* SIGINT handler. */
145
__attribute__((__noreturn__)) void sigint(void)
146
0
{
147
0
  zlog_notice("Terminating on signal");
148
0
  assert(bm->terminating == false);
149
0
  bm->terminating = true; /* global flag that shutting down */
150
151
  /* Disable BFD events to avoid wasting processing. */
152
0
  bfd_protocol_integration_set_shutdown(true);
153
154
0
  bgp_terminate();
155
156
0
  bgp_exit(0);
157
158
0
  exit(0);
159
0
}
160
161
/* SIGUSR1 handler. */
162
void sigusr1(void)
163
0
{
164
0
  zlog_rotate();
165
0
}
166
167
/*
168
  Try to free up allocations we know about so that diagnostic tools such as
169
  valgrind are able to better illuminate leaks.
170
171
  Zebra route removal and protocol teardown are not meant to be done here.
172
  For example, "retain_mode" may be set.
173
*/
174
static __attribute__((__noreturn__)) void bgp_exit(int status)
175
0
{
176
0
  struct bgp *bgp, *bgp_default, *bgp_evpn;
177
0
  struct listnode *node, *nnode;
178
179
  /* it only makes sense for this to be called on a clean exit */
180
0
  assert(status == 0);
181
182
0
  frr_early_fini();
183
184
0
  bgp_close();
185
186
0
  bgp_default = bgp_get_default();
187
0
  bgp_evpn = bgp_get_evpn();
188
189
  /* reverse bgp_master_init */
190
0
  for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
191
0
    if (bgp_default == bgp || bgp_evpn == bgp)
192
0
      continue;
193
0
    bgp_delete(bgp);
194
0
  }
195
0
  if (bgp_evpn && bgp_evpn != bgp_default)
196
0
    bgp_delete(bgp_evpn);
197
0
  if (bgp_default)
198
0
    bgp_delete(bgp_default);
199
200
0
  bgp_evpn_mh_finish();
201
0
  bgp_l3nhg_finish();
202
203
  /* reverse bgp_dump_init */
204
0
  bgp_dump_finish();
205
206
  /* BGP community aliases */
207
0
  bgp_community_alias_finish();
208
209
  /* reverse bgp_route_init */
210
0
  bgp_route_finish();
211
212
  /* cleanup route maps */
213
0
  bgp_route_map_terminate();
214
215
  /* reverse bgp_attr_init */
216
0
  bgp_attr_finish();
217
218
  /* stop pthreads */
219
0
  bgp_pthreads_finish();
220
221
  /* reverse access_list_init */
222
0
  access_list_add_hook(NULL);
223
0
  access_list_delete_hook(NULL);
224
0
  access_list_reset();
225
226
  /* reverse bgp_filter_init */
227
0
  as_list_add_hook(NULL);
228
0
  as_list_delete_hook(NULL);
229
0
  bgp_filter_reset();
230
231
  /* reverse prefix_list_init */
232
0
  prefix_list_add_hook(NULL);
233
0
  prefix_list_delete_hook(NULL);
234
0
  prefix_list_reset();
235
236
  /* reverse community_list_init */
237
0
  community_list_terminate(bgp_clist);
238
239
0
  bgp_vrf_terminate();
240
0
#ifdef ENABLE_BGP_VNC
241
0
  vnc_zebra_destroy();
242
0
#endif
243
0
  bgp_zebra_destroy();
244
245
0
  bf_free(bm->rd_idspace);
246
0
  list_delete(&bm->bgp);
247
0
  list_delete(&bm->addresses);
248
249
0
  bgp_lp_finish();
250
251
0
  memset(bm, 0, sizeof(*bm));
252
253
0
  frr_fini();
254
0
  exit(status);
255
0
}
256
257
static int bgp_vrf_new(struct vrf *vrf)
258
0
{
259
0
  if (BGP_DEBUG(zebra, ZEBRA))
260
0
    zlog_debug("VRF Created: %s(%u)", vrf->name, vrf->vrf_id);
261
0
262
0
  return 0;
263
0
}
264
265
static int bgp_vrf_delete(struct vrf *vrf)
266
0
{
267
0
  if (BGP_DEBUG(zebra, ZEBRA))
268
0
    zlog_debug("VRF Deletion: %s(%u)", vrf->name, vrf->vrf_id);
269
0
270
0
  return 0;
271
0
}
272
273
static int bgp_vrf_enable(struct vrf *vrf)
274
0
{
275
0
  struct bgp *bgp;
276
0
  vrf_id_t old_vrf_id;
277
0
278
0
  if (BGP_DEBUG(zebra, ZEBRA))
279
0
    zlog_debug("VRF enable add %s id %u", vrf->name, vrf->vrf_id);
280
0
281
0
  bgp = bgp_lookup_by_name(vrf->name);
282
0
  if (bgp && bgp->vrf_id != vrf->vrf_id) {
283
0
    old_vrf_id = bgp->vrf_id;
284
0
    /* We have instance configured, link to VRF and make it "up". */
285
0
    bgp_vrf_link(bgp, vrf);
286
0
287
0
    bgp_handle_socket(bgp, vrf, old_vrf_id, true);
288
0
    bgp_instance_up(bgp);
289
0
    vpn_leak_zebra_vrf_label_update(bgp, AFI_IP);
290
0
    vpn_leak_zebra_vrf_label_update(bgp, AFI_IP6);
291
0
    vpn_leak_zebra_vrf_sid_update(bgp, AFI_IP);
292
0
    vpn_leak_zebra_vrf_sid_update(bgp, AFI_IP6);
293
0
    vpn_leak_postchange(BGP_VPN_POLICY_DIR_TOVPN, AFI_IP,
294
0
            bgp_get_default(), bgp);
295
0
    vpn_leak_postchange(BGP_VPN_POLICY_DIR_FROMVPN, AFI_IP,
296
0
            bgp_get_default(), bgp);
297
0
    vpn_leak_postchange(BGP_VPN_POLICY_DIR_TOVPN, AFI_IP6,
298
0
            bgp_get_default(), bgp);
299
0
    vpn_leak_postchange(BGP_VPN_POLICY_DIR_FROMVPN, AFI_IP6,
300
0
            bgp_get_default(), bgp);
301
0
  }
302
0
303
0
  return 0;
304
0
}
305
306
static int bgp_vrf_disable(struct vrf *vrf)
307
0
{
308
0
  struct bgp *bgp;
309
0
310
0
  if (vrf->vrf_id == VRF_DEFAULT)
311
0
    return 0;
312
0
313
0
  if (BGP_DEBUG(zebra, ZEBRA))
314
0
    zlog_debug("VRF disable %s id %d", vrf->name, vrf->vrf_id);
315
0
316
0
  bgp = bgp_lookup_by_name(vrf->name);
317
0
  if (bgp) {
318
0
319
0
    vpn_leak_zebra_vrf_label_withdraw(bgp, AFI_IP);
320
0
    vpn_leak_zebra_vrf_label_withdraw(bgp, AFI_IP6);
321
0
    vpn_leak_prechange(BGP_VPN_POLICY_DIR_TOVPN, AFI_IP,
322
0
           bgp_get_default(), bgp);
323
0
    vpn_leak_prechange(BGP_VPN_POLICY_DIR_FROMVPN, AFI_IP,
324
0
           bgp_get_default(), bgp);
325
0
    vpn_leak_prechange(BGP_VPN_POLICY_DIR_TOVPN, AFI_IP6,
326
0
           bgp_get_default(), bgp);
327
0
    vpn_leak_prechange(BGP_VPN_POLICY_DIR_FROMVPN, AFI_IP6,
328
0
           bgp_get_default(), bgp);
329
0
330
0
    bgp_handle_socket(bgp, vrf, VRF_UNKNOWN, false);
331
0
    /* We have instance configured, unlink from VRF and make it
332
0
     * "down". */
333
0
    bgp_instance_down(bgp);
334
0
    bgp_vrf_unlink(bgp, vrf);
335
0
  }
336
0
337
0
  /* Note: This is a callback, the VRF will be deleted by the caller. */
338
0
  return 0;
339
0
}
340
341
static void bgp_vrf_init(void)
342
0
{
343
0
  vrf_init(bgp_vrf_new, bgp_vrf_enable, bgp_vrf_disable, bgp_vrf_delete);
344
0
}
345
346
static void bgp_vrf_terminate(void)
347
0
{
348
0
  vrf_terminate();
349
0
}
350
351
static const struct frr_yang_module_info *const bgpd_yang_modules[] = {
352
  &frr_filter_info,
353
  &frr_interface_info,
354
  &frr_route_map_info,
355
  &frr_vrf_info,
356
  &frr_bgp_route_map_info,
357
};
358
359
2
FRR_DAEMON_INFO(bgpd, BGP, .vty_port = BGP_VTY_PORT,
360
2
361
2
    .proghelp = "Implementation of the BGP routing protocol.",
362
2
363
2
    .signals = bgp_signals, .n_signals = array_size(bgp_signals),
364
2
365
2
    .privs = &bgpd_privs, .yang_modules = bgpd_yang_modules,
366
2
    .n_yang_modules = array_size(bgpd_yang_modules),
367
2
);
368
2
369
2
#define DEPRECATED_OPTIONS ""
370
2
371
2
#ifdef FUZZING
372
2
#include "lib/ringbuf.h"
373
2
374
2
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
375
2
376
2
static bool FuzzingInit(void) {
377
1
  int bgp_port = BGP_PORT_DEFAULT;
378
1
  struct list *addresses = list_new();
379
1
  int no_fib_flag = 0;
380
1
  int no_zebra_flag = 0;
381
1
  int skip_runas = 0;
382
1
  int instance = 0;
383
1
  int buffer_size = BGP_SOCKET_SNDBUF_SIZE;
384
1
  struct listnode *node;
385
386
1
  addresses->cmp = (int (*)(void *, void *))strcmp;
387
388
1
  const char *name[] = { "bgpd" };
389
390
1
  frr_preinit(&bgpd_di, 1, (char **) name);
391
392
  /* Initialize basic BGP datastructures */
393
1
  bgp_master_init(frr_init_fast(), buffer_size, addresses);
394
1
  bm->port = bgp_port;
395
1
  bgp_option_set(BGP_OPT_NO_LISTEN);
396
397
1
  bgp_option_set(BGP_OPT_NO_FIB);
398
1
  bgp_option_set(BGP_OPT_NO_ZEBRA);
399
1
  bgp_error_init();
400
  // bgp_vrf_init();
401
1
  bgp_init((unsigned short)instance);
402
403
404
  /* Create a default instance and peer */
405
1
  struct bgp *b;
406
1
  as_t as = 65001;
407
1
  bgp_get(&b, &as, "default", BGP_INSTANCE_TYPE_DEFAULT, NULL,
408
1
    ASNOTATION_UNDEFINED);
409
410
1
  return true;
411
1
}
412
413
/*
414
 * Create peer structure that we'll use as the receiver for fuzzed packets.
415
 *
416
 * state
417
 *    BGP FSM state to create the peer in
418
 */
419
static struct peer *FuzzingCreatePeer(int state)
420
1
{
421
1
  union sockunion su;
422
1
  sockunion_init(&su);
423
1
  inet_pton(AF_INET, "10.1.1.1", &su.sin.sin_addr);
424
1
  su.sin.sin_family = AF_INET;
425
1
  su.sin.sin_port = 2001;
426
1
  struct peer *p = peer_create(&su, NULL, bgp_get_default(), 65000, 65001,
427
1
             AS_UNSPECIFIED, NULL, 1, NULL);
428
1
  p->bgp->rpkt_quanta = 1;
429
1
  p->status = state;
430
1
  p->as_type = AS_EXTERNAL;
431
432
  /* set all flags */
433
1
  afi_t afi;
434
1
  safi_t safi;
435
1
  p->cap |= 0xFFFF;
436
21
  FOREACH_AFI_SAFI(afi, safi) {
437
21
    SET_FLAG(p->af_cap[afi][safi], 0x3FFF);
438
21
  }
439
440
1
  peer_activate(p, AFI_L2VPN, SAFI_EVPN);
441
1
  peer_activate(p, AFI_IP, SAFI_MPLS_VPN);
442
443
1
  return p;
444
1
}
445
446
static struct peer *FuzzingPeer;
447
448
static bool FuzzingInitialized;
449
450
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
451
738
{
452
738
  if (!FuzzingInitialized) {
453
1
    FuzzingInit();
454
1
    FuzzingInitialized = true;
455
    /* See comment below */
456
1
    FuzzingPeer = FuzzingCreatePeer(Established);
457
1
  }
458
  //make_route_maps();
459
  /*
460
   * In the AFL standalone case, the peer will already be created for us
461
   * before __AFL_INIT() is called to speed things up. We can't pass it
462
   * as an argument because the function signature must match libFuzzer's
463
   * expectations, so it's saved in a global variable. Even though we'll
464
   * be exiting the program after each run, we still destroy the peer
465
   * because that increases our coverage and is likely to find memory
466
   * leaks when pointers are nulled that would otherwise be "in-use at
467
   * exit".
468
   *
469
   * In the libFuzzer case, we can either create and destroy it each time
470
   * to fuzz single packet rx, or we can keep the peer around, which will
471
   * fuzz a long lived session. Of course, as state accumulates over
472
   * time, memory usage will grow, which imposes some resource
473
   * constraints on the fuzzing host. In practice a reasonable server
474
   * machine with 64gb of memory or so should be able to fuzz
475
   * indefinitely; if bgpd consumes this much memory over time, that
476
   * behavior should probably be considered a bug.
477
   */
478
738
  struct peer *p;
479
738
#ifdef FUZZING_LIBFUZZER
480
  /* For non-persistent mode */
481
  // p = FuzzingCreatePeer();
482
  /* For persistent mode */
483
738
  p = FuzzingPeer;
484
#else
485
  p = FuzzingPeer;
486
#endif /* FUZZING_LIBFUZZER */
487
488
738
  ringbuf_reset(p->ibuf_work);
489
738
  ringbuf_put(p->ibuf_work, data, size);
490
491
738
  int result = 0;
492
738
  unsigned char pktbuf[BGP_MAX_PACKET_SIZE];
493
738
  uint16_t pktsize = 0;
494
495
  /*
496
   * Simulate the read process done by bgp_process_reads().
497
   *
498
   * The actual packet processing code assumes that the size field in the
499
   * BGP message is correct, and this check is performed by the i/o code,
500
   * so we need to make sure that remains true for fuzzed input.
501
   *
502
   * Also, validate_header() assumes that there is at least
503
   * BGP_HEADER_SIZE bytes in ibuf_work.
504
   */
505
738
  if ((size < BGP_HEADER_SIZE) || !validate_header(p)) {
506
28
    goto done;
507
28
  }
508
509
710
  ringbuf_peek(p->ibuf_work, BGP_MARKER_SIZE, &pktsize, sizeof(pktsize));
510
710
  pktsize = ntohs(pktsize);
511
512
710
  assert(pktsize <= p->max_packet_size);
513
514
710
  if (ringbuf_remain(p->ibuf_work) >= pktsize) {
515
703
    struct stream *pkt = stream_new(pktsize);
516
703
    ringbuf_get(p->ibuf_work, pktbuf, pktsize);
517
703
    stream_put(pkt, pktbuf, pktsize);
518
703
    p->curr = pkt;
519
520
703
    struct event t = {};
521
703
    t.arg = p;
522
703
    bgp_process_packet(&t);
523
703
  }
524
525
738
done:
526
  //peer_delete(p);
527
528
738
  return 0;
529
710
};
530
#endif /* FUZZING */
531
532
#ifndef FUZZING_LIBFUZZER
533
/* Main routine of bgpd. Treatment of argument and start bgp finite
534
   state machine is handled at here. */
535
int main(int argc, char **argv)
536
{
537
  int opt;
538
  int tmp_port;
539
540
  int bgp_port = BGP_PORT_DEFAULT;
541
  struct list *addresses = list_new();
542
  int no_fib_flag = 0;
543
  int no_zebra_flag = 0;
544
  int skip_runas = 0;
545
  int instance = 0;
546
  int buffer_size = BGP_SOCKET_SNDBUF_SIZE;
547
  char *address;
548
  struct listnode *node;
549
  //char *bgp_address = NULL;
550
551
  //addresses->cmp = (int (*)(void *, void *))strcmp;
552
553
  frr_preinit(&bgpd_di, argc, argv);
554
555
#ifdef FUZZING
556
  FuzzingInit();
557
  FuzzingPeer = FuzzingCreatePeer(Established);
558
  FuzzingInitialized = true;
559
560
#ifdef __AFL_HAVE_MANUAL_CONTROL
561
  __AFL_INIT();
562
#endif /* __AFL_HAVE_MANUAL_CONTROL */
563
  uint8_t *input;
564
  int r = frrfuzz_read_input(&input);
565
566
  if (!input)
567
    return 0;
568
569
  return LLVMFuzzerTestOneInput(input, r);
570
#endif /* FUZZING */
571
572
  frr_opt_add(
573
    "p:l:SnZe:I:s:" DEPRECATED_OPTIONS, longopts,
574
    "  -p, --bgp_port     Set BGP listen port number (0 means do not listen).\n"
575
    "  -l, --listenon     Listen on specified address (implies -n)\n"
576
    "  -n, --no_kernel    Do not install route to kernel.\n"
577
    "  -Z, --no_zebra     Do not communicate with Zebra.\n"
578
    "  -S, --skip_runas   Skip capabilities checks, and changing user and group IDs.\n"
579
    "  -e, --ecmp         Specify ECMP to use.\n"
580
    "  -I, --int_num      Set instance number (label-manager)\n"
581
    "  -s, --socket_size  Set BGP peer socket send buffer size\n");
582
583
  /* Command line argument treatment. */
584
  while (1) {
585
    opt = frr_getopt(argc, argv, 0);
586
587
    if (opt && opt < 128 && strchr(DEPRECATED_OPTIONS, opt)) {
588
      fprintf(stderr,
589
        "The -%c option no longer exists.\nPlease refer to the manual.\n",
590
        opt);
591
      continue;
592
    }
593
594
    if (opt == EOF)
595
      break;
596
597
    switch (opt) {
598
    case 0:
599
      break;
600
    case 'p':
601
      tmp_port = atoi(optarg);
602
      if (tmp_port < 0 || tmp_port > 0xffff)
603
        bgp_port = BGP_PORT_DEFAULT;
604
      else
605
        bgp_port = tmp_port;
606
      break;
607
    case 'e': {
608
      unsigned long int parsed_multipath =
609
        strtoul(optarg, NULL, 10);
610
      if (parsed_multipath == 0
611
          || parsed_multipath > MULTIPATH_NUM
612
          || parsed_multipath > UINT_MAX) {
613
        flog_err(
614
          EC_BGP_MULTIPATH,
615
          "Multipath Number specified must be less than %u and greater than 0",
616
          MULTIPATH_NUM);
617
        return 1;
618
      }
619
      multipath_num = parsed_multipath;
620
      break;
621
    }
622
    case 'l':
623
      listnode_add_sort_nodup(addresses, optarg);
624
      break;
625
    case 'n':
626
      no_fib_flag = 1;
627
      break;
628
    case 'Z':
629
      no_zebra_flag = 1;
630
      break;
631
    case 'S':
632
      skip_runas = 1;
633
      break;
634
    case 'I':
635
      instance = atoi(optarg);
636
      if (instance > (unsigned short)-1)
637
        zlog_err("Instance %i out of range (0..%u)",
638
           instance, (unsigned short)-1);
639
      break;
640
    case 's':
641
      buffer_size = atoi(optarg);
642
      break;
643
    default:
644
      frr_help_exit(1);
645
    }
646
  }
647
  if (skip_runas)
648
    memset(&bgpd_privs, 0, sizeof(bgpd_privs));
649
650
  /* BGP master init. */
651
  bgp_master_init(frr_init(), buffer_size, addresses);
652
  bm->port = bgp_port;
653
  if (bgp_port == 0)
654
    bgp_option_set(BGP_OPT_NO_LISTEN);
655
  if (no_fib_flag || no_zebra_flag)
656
    bgp_option_set(BGP_OPT_NO_FIB);
657
  if (no_zebra_flag)
658
    bgp_option_set(BGP_OPT_NO_ZEBRA);
659
  bgp_error_init();
660
  /* Initializations. */
661
  bgp_vrf_init();
662
663
#ifdef HAVE_SCRIPTING
664
  bgp_script_init();
665
#endif
666
667
  /* BGP related initialization.  */
668
  bgp_init((unsigned short)instance);
669
670
  if (list_isempty(bm->addresses)) {
671
    snprintf(bgpd_di.startinfo, sizeof(bgpd_di.startinfo),
672
       ", bgp@<all>:%d", bm->port);
673
  } else {
674
    for (ALL_LIST_ELEMENTS_RO(bm->addresses, node, address))
675
      snprintf(bgpd_di.startinfo + strlen(bgpd_di.startinfo),
676
         sizeof(bgpd_di.startinfo)
677
           - strlen(bgpd_di.startinfo),
678
         ", bgp@%s:%d", address, bm->port);
679
  }
680
681
  bgp_if_init();
682
683
  frr_config_fork();
684
  /* must be called after fork() */
685
  bgp_gr_apply_running_config();
686
  bgp_pthreads_run();
687
  frr_run(bm->master);
688
689
  /* Not reached. */
690
  return 0;
691
}
692
#endif /* FUZZING_LIBFUZZER */