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