Annotation of embedaddon/quagga/bgpd/bgp_main.c, revision 1.1.1.4
1.1 misho 1: /* Main routine of bgpd.
2: Copyright (C) 1996, 97, 98, 1999 Kunihiro Ishiguro
3:
4: This file is part of GNU Zebra.
5:
6: GNU Zebra is free software; you can redistribute it and/or modify it
7: under the terms of the GNU General Public License as published by the
8: Free Software Foundation; either version 2, or (at your option) any
9: later version.
10:
11: GNU Zebra is distributed in the hope that it will be useful, but
12: WITHOUT ANY WARRANTY; without even the implied warranty of
13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14: General Public License for more details.
15:
16: You should have received a copy of the GNU General Public License
17: along with GNU Zebra; see the file COPYING. If not, write to the Free
18: Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19: 02111-1307, USA. */
20:
21: #include <zebra.h>
22:
23: #include "vector.h"
24: #include "vty.h"
25: #include "command.h"
26: #include "getopt.h"
27: #include "thread.h"
28: #include <lib/version.h>
29: #include "memory.h"
30: #include "prefix.h"
31: #include "log.h"
32: #include "privs.h"
33: #include "sigevent.h"
34: #include "zclient.h"
35: #include "routemap.h"
36: #include "filter.h"
37: #include "plist.h"
1.1.1.2 misho 38: #include "stream.h"
1.1.1.4 ! misho 39: #include "vrf.h"
! 40: #include "workqueue.h"
1.1 misho 41:
42: #include "bgpd/bgpd.h"
43: #include "bgpd/bgp_attr.h"
44: #include "bgpd/bgp_mplsvpn.h"
45: #include "bgpd/bgp_aspath.h"
46: #include "bgpd/bgp_dump.h"
47: #include "bgpd/bgp_route.h"
48: #include "bgpd/bgp_nexthop.h"
49: #include "bgpd/bgp_regex.h"
50: #include "bgpd/bgp_clist.h"
51: #include "bgpd/bgp_debug.h"
52: #include "bgpd/bgp_filter.h"
1.1.1.2 misho 53: #include "bgpd/bgp_zebra.h"
1.1 misho 54:
55: /* bgpd options, we use GNU getopt library. */
56: static const struct option longopts[] =
57: {
58: { "daemon", no_argument, NULL, 'd'},
59: { "config_file", required_argument, NULL, 'f'},
60: { "pid_file", required_argument, NULL, 'i'},
1.1.1.2 misho 61: { "socket", required_argument, NULL, 'z'},
1.1 misho 62: { "bgp_port", required_argument, NULL, 'p'},
63: { "listenon", required_argument, NULL, 'l'},
64: { "vty_addr", required_argument, NULL, 'A'},
65: { "vty_port", required_argument, NULL, 'P'},
66: { "retain", no_argument, NULL, 'r'},
67: { "no_kernel", no_argument, NULL, 'n'},
68: { "user", required_argument, NULL, 'u'},
69: { "group", required_argument, NULL, 'g'},
70: { "version", no_argument, NULL, 'v'},
71: { "dryrun", no_argument, NULL, 'C'},
72: { "help", no_argument, NULL, 'h'},
73: { 0 }
74: };
75:
76: /* signal definitions */
77: void sighup (void);
78: void sigint (void);
79: void sigusr1 (void);
80:
81: static void bgp_exit (int);
82:
83: static struct quagga_signal_t bgp_signals[] =
84: {
85: {
86: .signal = SIGHUP,
87: .handler = &sighup,
88: },
89: {
90: .signal = SIGUSR1,
91: .handler = &sigusr1,
92: },
93: {
94: .signal = SIGINT,
95: .handler = &sigint,
96: },
97: {
98: .signal = SIGTERM,
99: .handler = &sigint,
100: },
101: };
102:
103: /* Configuration file and directory. */
104: char config_default[] = SYSCONFDIR BGP_DEFAULT_CONFIG;
105:
106: /* Route retain mode flag. */
107: static int retain_mode = 0;
108:
109: /* Manually specified configuration file name. */
110: char *config_file = NULL;
111:
112: /* Process ID saved for use by init system */
113: static const char *pid_file = PATH_BGPD_PID;
114:
115: /* VTY port number and address. */
116: int vty_port = BGP_VTY_PORT;
117: char *vty_addr = NULL;
118:
119: /* privileges */
120: static zebra_capabilities_t _caps_p [] =
121: {
122: ZCAP_BIND,
123: ZCAP_NET_RAW,
1.1.1.2 misho 124: ZCAP_NET_ADMIN,
1.1 misho 125: };
126:
127: struct zebra_privs_t bgpd_privs =
128: {
129: #if defined(QUAGGA_USER) && defined(QUAGGA_GROUP)
130: .user = QUAGGA_USER,
131: .group = QUAGGA_GROUP,
132: #endif
133: #ifdef VTY_GROUP
134: .vty_group = VTY_GROUP,
135: #endif
136: .caps_p = _caps_p,
1.1.1.3 misho 137: .cap_num_p = array_size(_caps_p),
1.1 misho 138: .cap_num_i = 0,
139: };
140:
141: /* Help information display. */
142: static void
143: usage (char *progname, int status)
144: {
145: if (status != 0)
146: fprintf (stderr, "Try `%s --help' for more information.\n", progname);
147: else
148: {
149: printf ("Usage : %s [OPTION...]\n\n\
150: Daemon which manages kernel routing table management and \
151: redistribution between different routing protocols.\n\n\
152: -d, --daemon Runs in daemon mode\n\
153: -f, --config_file Set configuration file name\n\
154: -i, --pid_file Set process identifier file name\n\
1.1.1.2 misho 155: -z, --socket Set path of zebra socket\n\
1.1 misho 156: -p, --bgp_port Set bgp protocol's port number\n\
157: -l, --listenon Listen on specified address (implies -n)\n\
158: -A, --vty_addr Set vty's bind address\n\
159: -P, --vty_port Set vty's port number\n\
160: -r, --retain When program terminates, retain added route by bgpd.\n\
161: -n, --no_kernel Do not install route to kernel.\n\
162: -u, --user User to run as\n\
163: -g, --group Group to run as\n\
164: -v, --version Print program version\n\
165: -C, --dryrun Check configuration for validity and exit\n\
166: -h, --help Display this help and exit\n\
167: \n\
168: Report bugs to %s\n", progname, ZEBRA_BUG_ADDRESS);
169: }
170:
171: exit (status);
172: }
1.1.1.4 ! misho 173:
1.1 misho 174: /* SIGHUP handler. */
175: void
176: sighup (void)
177: {
178: zlog (NULL, LOG_INFO, "SIGHUP received");
179:
180: /* Terminate all thread. */
181: bgp_terminate ();
182: bgp_reset ();
183: zlog_info ("bgpd restarting!");
184:
185: /* Reload config file. */
186: vty_read_config (config_file, config_default);
187:
188: /* Create VTY's socket */
189: vty_serv_sock (vty_addr, vty_port, BGP_VTYSH_PATH);
190:
191: /* Try to return to normal operation. */
192: }
193:
194: /* SIGINT handler. */
195: void
196: sigint (void)
197: {
198: zlog_notice ("Terminating on signal");
199:
1.1.1.4 ! misho 200: if (! retain_mode)
! 201: {
! 202: bgp_terminate ();
! 203: zprivs_terminate (&bgpd_privs);
! 204: }
1.1 misho 205:
206: bgp_exit (0);
207: }
208:
209: /* SIGUSR1 handler. */
210: void
211: sigusr1 (void)
212: {
213: zlog_rotate (NULL);
214: }
215:
216: /*
217: Try to free up allocations we know about so that diagnostic tools such as
218: valgrind are able to better illuminate leaks.
219:
220: Zebra route removal and protocol teardown are not meant to be done here.
221: For example, "retain_mode" may be set.
222: */
223: static void
224: bgp_exit (int status)
225: {
226: struct bgp *bgp;
227: struct listnode *node, *nnode;
228: int *socket;
229: struct interface *ifp;
230: extern struct zclient *zlookup;
231:
232: /* it only makes sense for this to be called on a clean exit */
233: assert (status == 0);
234:
235: /* reverse bgp_master_init */
236: for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
237: bgp_delete (bgp);
238: list_free (bm->bgp);
1.1.1.4 ! misho 239: bm->bgp = NULL;
! 240:
! 241: /*
! 242: * bgp_delete can re-allocate the process queues after they were
! 243: * deleted in bgp_terminate. delete them again.
! 244: *
! 245: * It might be better to ensure the RIBs (including static routes)
! 246: * are cleared by bgp_terminate() during its call to bgp_cleanup_routes(),
! 247: * which currently only deletes the kernel routes.
! 248: */
! 249: if (bm->process_main_queue)
! 250: {
! 251: work_queue_free (bm->process_main_queue);
! 252: bm->process_main_queue = NULL;
! 253: }
! 254: if (bm->process_rsclient_queue)
! 255: {
! 256: work_queue_free (bm->process_rsclient_queue);
! 257: bm->process_rsclient_queue = NULL;
! 258: }
! 259:
1.1 misho 260: /* reverse bgp_master_init */
261: for (ALL_LIST_ELEMENTS_RO(bm->listen_sockets, node, socket))
262: {
263: if (close ((int)(long)socket) == -1)
264: zlog_err ("close (%d): %s", (int)(long)socket, safe_strerror (errno));
265: }
266: list_delete (bm->listen_sockets);
267:
268: /* reverse bgp_zebra_init/if_init */
269: if (retain_mode)
270: if_add_hook (IF_DELETE_HOOK, NULL);
1.1.1.4 ! misho 271: for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
1.1 misho 272: {
273: struct listnode *c_node, *c_nnode;
274: struct connected *c;
275:
276: for (ALL_LIST_ELEMENTS (ifp->connected, c_node, c_nnode, c))
277: bgp_connected_delete (c);
278: }
279:
280: /* reverse bgp_attr_init */
281: bgp_attr_finish ();
282:
283: /* reverse bgp_dump_init */
284: bgp_dump_finish ();
285:
286: /* reverse bgp_route_init */
287: bgp_route_finish ();
288:
289: /* reverse bgp_route_map_init/route_map_init */
290: route_map_finish ();
291:
292: /* reverse bgp_scan_init */
293: bgp_scan_finish ();
294:
295: /* reverse access_list_init */
296: access_list_add_hook (NULL);
297: access_list_delete_hook (NULL);
298: access_list_reset ();
299:
300: /* reverse bgp_filter_init */
301: as_list_add_hook (NULL);
302: as_list_delete_hook (NULL);
303: bgp_filter_reset ();
304:
305: /* reverse prefix_list_init */
306: prefix_list_add_hook (NULL);
307: prefix_list_delete_hook (NULL);
308: prefix_list_reset ();
309:
310: /* reverse community_list_init */
311: community_list_terminate (bgp_clist);
312:
1.1.1.4 ! misho 313: vrf_terminate ();
1.1 misho 314: cmd_terminate ();
315: vty_terminate ();
1.1.1.4 ! misho 316: bgp_address_destroy();
! 317: bgp_scan_destroy();
! 318: bgp_zebra_destroy();
1.1 misho 319: if (zlookup)
320: zclient_free (zlookup);
1.1.1.2 misho 321: if (bgp_nexthop_buf)
322: stream_free (bgp_nexthop_buf);
1.1 misho 323:
324: /* reverse bgp_master_init */
1.1.1.4 ! misho 325: if (bm->master)
! 326: thread_master_free (bm->master);
1.1 misho 327:
328: if (zlog_default)
329: closezlog (zlog_default);
330:
331: if (CONF_BGP_DEBUG (normal, NORMAL))
332: log_memstats_stderr ("bgpd");
333:
334: exit (status);
335: }
1.1.1.4 ! misho 336:
1.1 misho 337: /* Main routine of bgpd. Treatment of argument and start bgp finite
338: state machine is handled at here. */
339: int
340: main (int argc, char **argv)
341: {
342: char *p;
343: int opt;
344: int daemon_mode = 0;
345: int dryrun = 0;
346: char *progname;
347: struct thread thread;
348: int tmp_port;
349:
350: /* Set umask before anything for security */
351: umask (0027);
352:
353: /* Preserve name of myself. */
354: progname = ((p = strrchr (argv[0], '/')) ? ++p : argv[0]);
355:
356: zlog_default = openzlog (progname, ZLOG_BGP,
357: LOG_CONS|LOG_NDELAY|LOG_PID, LOG_DAEMON);
358:
359: /* BGP master init. */
360: bgp_master_init ();
361:
362: /* Command line argument treatment. */
363: while (1)
364: {
1.1.1.2 misho 365: opt = getopt_long (argc, argv, "df:i:z:hp:l:A:P:rnu:g:vC", longopts, 0);
1.1 misho 366:
367: if (opt == EOF)
368: break;
369:
370: switch (opt)
371: {
372: case 0:
373: break;
374: case 'd':
375: daemon_mode = 1;
376: break;
377: case 'f':
378: config_file = optarg;
379: break;
380: case 'i':
381: pid_file = optarg;
382: break;
1.1.1.2 misho 383: case 'z':
384: zclient_serv_path_set (optarg);
385: break;
1.1 misho 386: case 'p':
387: tmp_port = atoi (optarg);
388: if (tmp_port <= 0 || tmp_port > 0xffff)
389: bm->port = BGP_PORT_DEFAULT;
390: else
391: bm->port = tmp_port;
392: break;
393: case 'A':
394: vty_addr = optarg;
395: break;
396: case 'P':
397: /* Deal with atoi() returning 0 on failure, and bgpd not
398: listening on bgp port... */
399: if (strcmp(optarg, "0") == 0)
400: {
401: vty_port = 0;
402: break;
403: }
404: vty_port = atoi (optarg);
405: if (vty_port <= 0 || vty_port > 0xffff)
406: vty_port = BGP_VTY_PORT;
407: break;
408: case 'r':
409: retain_mode = 1;
410: break;
411: case 'l':
412: bm->address = optarg;
413: /* listenon implies -n */
414: case 'n':
415: bgp_option_set (BGP_OPT_NO_FIB);
416: break;
417: case 'u':
418: bgpd_privs.user = optarg;
419: break;
420: case 'g':
421: bgpd_privs.group = optarg;
422: break;
423: case 'v':
424: print_version (progname);
425: exit (0);
426: break;
427: case 'C':
428: dryrun = 1;
429: break;
430: case 'h':
431: usage (progname, 0);
432: break;
433: default:
434: usage (progname, 1);
435: break;
436: }
437: }
438:
439: /* Initializations. */
1.1.1.4 ! misho 440: srandom (time (NULL));
! 441: signal_init (bm->master, array_size(bgp_signals), bgp_signals);
1.1 misho 442: zprivs_init (&bgpd_privs);
443: cmd_init (1);
1.1.1.4 ! misho 444: vty_init (bm->master);
1.1 misho 445: memory_init ();
1.1.1.4 ! misho 446: vrf_init ();
1.1 misho 447:
448: /* BGP related initialization. */
449: bgp_init ();
450:
451: /* Parse config file. */
452: vty_read_config (config_file, config_default);
453:
454: /* Start execution only if not in dry-run mode */
455: if(dryrun)
456: return(0);
457:
458: /* Turn into daemon if daemon_mode is set. */
459: if (daemon_mode && daemon (0, 0) < 0)
460: {
461: zlog_err("BGPd daemon failed: %s", strerror(errno));
462: return (1);
463: }
464:
465:
466: /* Process ID file creation. */
467: pid_output (pid_file);
468:
469: /* Make bgp vty socket. */
470: vty_serv_sock (vty_addr, vty_port, BGP_VTYSH_PATH);
471:
472: /* Print banner. */
1.1.1.4 ! misho 473: zlog_notice ("BGPd %s starting: vty@%d, bgp@%s:%d pid %d", QUAGGA_VERSION,
1.1 misho 474: vty_port,
475: (bm->address ? bm->address : "<all>"),
1.1.1.4 ! misho 476: bm->port,
! 477: getpid ());
1.1 misho 478:
479: /* Start finite state machine, here we go! */
1.1.1.4 ! misho 480: while (thread_fetch (bm->master, &thread))
1.1 misho 481: thread_call (&thread);
482:
483: /* Not reached. */
484: return (0);
485: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>