diff options
Diffstat (limited to 'sysdep/unix')
-rw-r--r-- | sysdep/unix/Makefile | 3 | ||||
-rw-r--r-- | sysdep/unix/io.c | 47 | ||||
-rw-r--r-- | sysdep/unix/krt.Y | 18 | ||||
-rw-r--r-- | sysdep/unix/krt.c | 6 | ||||
-rw-r--r-- | sysdep/unix/log.c | 27 | ||||
-rw-r--r-- | sysdep/unix/main.c | 70 |
6 files changed, 131 insertions, 40 deletions
diff --git a/sysdep/unix/Makefile b/sysdep/unix/Makefile index c5d55431..f592399c 100644 --- a/sysdep/unix/Makefile +++ b/sysdep/unix/Makefile @@ -3,3 +3,6 @@ obj := $(src-o-files) $(all-daemon) $(cf-local) $(conf-y-targets): $(s)krt.Y + +src := $(filter-out main.c, $(src)) +tests_objs := $(tests_objs) $(src-o-files) diff --git a/sysdep/unix/io.c b/sysdep/unix/io.c index e3e2f5f8..c8916378 100644 --- a/sysdep/unix/io.c +++ b/sysdep/unix/io.c @@ -9,7 +9,9 @@ /* Unfortunately, some glibc versions hide parts of RFC 3542 API if _GNU_SOURCE is not defined. */ -#define _GNU_SOURCE 1 +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif #include <stdio.h> #include <stdlib.h> @@ -507,11 +509,11 @@ tm_format_datetime(char *x, struct timeformat *fmt_spec, bird_clock_t t) * Sockaddr helper functions */ -static inline int sockaddr_length(int af) +static inline int UNUSED sockaddr_length(int af) { return (af == AF_INET) ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6); } static inline void -sockaddr_fill4(struct sockaddr_in *sa, ip_addr a, struct iface *ifa, uint port) +sockaddr_fill4(struct sockaddr_in *sa, ip_addr a, uint port) { memset(sa, 0, sizeof(struct sockaddr_in)); #ifdef HAVE_SIN_LEN @@ -542,7 +544,7 @@ void sockaddr_fill(sockaddr *sa, int af, ip_addr a, struct iface *ifa, uint port) { if (af == AF_INET) - sockaddr_fill4((struct sockaddr_in *) sa, a, ifa, port); + sockaddr_fill4((struct sockaddr_in *) sa, a, port); else if (af == AF_INET6) sockaddr_fill6((struct sockaddr_in6 *) sa, a, ifa, port); else @@ -550,7 +552,7 @@ sockaddr_fill(sockaddr *sa, int af, ip_addr a, struct iface *ifa, uint port) } static inline void -sockaddr_read4(struct sockaddr_in *sa, ip_addr *a, struct iface **ifa, uint *port) +sockaddr_read4(struct sockaddr_in *sa, ip_addr *a, uint *port) { *port = ntohs(sa->sin_port); *a = ipa_from_in4(sa->sin_addr); @@ -573,7 +575,7 @@ sockaddr_read(sockaddr *sa, int af, ip_addr *a, struct iface **ifa, uint *port) goto fail; if (af == AF_INET) - sockaddr_read4((struct sockaddr_in *) sa, a, ifa, port); + sockaddr_read4((struct sockaddr_in *) sa, a, port); else if (af == AF_INET6) sockaddr_read6((struct sockaddr_in6 *) sa, a, ifa, port); else @@ -770,7 +772,7 @@ sk_set_tos6(sock *s, int tos) } static inline int -sk_set_high_port(sock *s) +sk_set_high_port(sock *s UNUSED) { /* Port range setting is optional, ignore it if not supported */ @@ -1293,7 +1295,7 @@ sk_setup(sock *s) if (sk_is_ipv6(s)) { - if (s->type != SK_IP) + if ((s->type == SK_TCP_PASSIVE) || (s->type == SK_TCP_ACTIVE) || (s->type == SK_UDP)) if (setsockopt(fd, SOL_IPV6, IPV6_V6ONLY, &y, sizeof(y)) < 0) ERR("IPV6_V6ONLY"); @@ -2247,6 +2249,20 @@ int sk_is_ipv6(sock *s) { return s->af == AF_INET6; } void +sk_err(sock *s, int revents) +{ + int se = 0, sse = sizeof(se); + if ((s->type != SK_MAGIC) && (revents & POLLERR)) + if (getsockopt(s->fd, SOL_SOCKET, SO_ERROR, &se, &sse) < 0) + { + log(L_ERR "IO: Socket error: SO_ERROR: %m"); + se = 0; + } + + s->err_hook(s, se); +} + +void sk_dump_all(void) { node *n; @@ -2557,7 +2573,7 @@ io_loop(void) int steps; steps = MAX_STEPS; - if (s->fast_rx && (pfd[s->index].revents & (POLLIN | POLLHUP | POLLERR)) && s->rx_hook) + if (s->fast_rx && (pfd[s->index].revents & POLLIN) && s->rx_hook) do { steps--; @@ -2579,6 +2595,7 @@ io_loop(void) goto next; } while (e && steps); + current_sock = sk_next(s); next: ; } @@ -2602,18 +2619,26 @@ io_loop(void) goto next2; } - if (!s->fast_rx && (pfd[s->index].revents & (POLLIN | POLLHUP | POLLERR)) && s->rx_hook) + if (!s->fast_rx && (pfd[s->index].revents & POLLIN) && s->rx_hook) { count++; io_log_event(s->rx_hook, s->data); sk_read(s, pfd[s->index].revents); if (s != current_sock) - goto next2; + goto next2; } + + if (pfd[s->index].revents & (POLLHUP | POLLERR)) + { + sk_err(s, pfd[s->index].revents); + goto next2; + } + current_sock = sk_next(s); next2: ; } + stored_sock = current_sock; } } diff --git a/sysdep/unix/krt.Y b/sysdep/unix/krt.Y index 91317d97..33dc4a19 100644 --- a/sysdep/unix/krt.Y +++ b/sysdep/unix/krt.Y @@ -29,6 +29,8 @@ CF_DECLS CF_KEYWORDS(KERNEL, PERSIST, SCAN, TIME, LEARN, DEVICE, ROUTES, GRACEFUL, RESTART, KRT_SOURCE, KRT_METRIC, MERGE, PATHS) +%type <i> kern_mp_limit + CF_GRAMMAR /* Kernel syncer protocol */ @@ -43,6 +45,11 @@ kern_proto_start: proto_start KERNEL { CF_ADDTO(kern_proto, kern_proto_start proto_name '{') CF_ADDTO(kern_proto, kern_proto kern_item ';') +kern_mp_limit: + /* empty */ { $$ = KRT_DEFAULT_ECMP_LIMIT; } + | LIMIT expr { $$ = $2; if (($2 <= 0) || ($2 > 255)) cf_error("Merge paths limit must be in range 1-255"); } + ; + kern_item: proto_item | proto_channel { this_proto->net_type = $1->net_type; } @@ -55,13 +62,18 @@ kern_item: THIS_KRT->learn = $2; #ifndef KRT_ALLOW_LEARN if ($2) - cf_error("Learning of kernel routes not supported in this configuration"); + cf_error("Learning of kernel routes not supported on this platform"); #endif } | DEVICE ROUTES bool { THIS_KRT->devroutes = $3; } | GRACEFUL RESTART bool { THIS_KRT->graceful_restart = $3; } - | MERGE PATHS bool { krt_set_merge_paths(this_channel, $3, KRT_DEFAULT_ECMP_LIMIT); } - | MERGE PATHS bool LIMIT expr { krt_set_merge_paths(this_channel, $3, $5); } + | MERGE PATHS bool kern_mp_limit { + krt_set_merge_paths(this_channel, $3, $4); +#ifndef KRT_ALLOW_MERGE_PATHS + if ($3) + cf_error("Path merging not supported on this platform"); +#endif + } ; /* Kernel interface protocol */ diff --git a/sysdep/unix/krt.c b/sysdep/unix/krt.c index 6531bb28..e899671d 100644 --- a/sysdep/unix/krt.c +++ b/sysdep/unix/krt.c @@ -604,7 +604,7 @@ krt_export_net(struct krt_proto *p, net *net, rte **rt_free, ea_list **tmpa) rte *rt; if (c->ra_mode == RA_MERGED) - return rt_export_merged(c, net, rt_free, tmpa, 1); + return rt_export_merged(c, net, rt_free, tmpa, krt_filter_lp, 1); rt = net->routes; *rt_free = NULL; @@ -899,7 +899,7 @@ krt_scan_timer_start(struct krt_proto *p) } static void -krt_scan_timer_stop(struct krt_proto *p) +krt_scan_timer_stop(struct krt_proto *p UNUSED) { krt_scan_count--; @@ -988,7 +988,7 @@ krt_store_tmp_attrs(rte *rt, struct ea_list *attrs) } static int -krt_import_control(struct proto *P, rte **new, ea_list **attrs, struct linpool *pool) +krt_import_control(struct proto *P, rte **new, ea_list **attrs UNUSED, struct linpool *pool UNUSED) { struct krt_proto *p = (struct krt_proto *) P; rte *e = *new; diff --git a/sysdep/unix/log.c b/sysdep/unix/log.c index 9c56eb24..42c933ef 100644 --- a/sysdep/unix/log.c +++ b/sysdep/unix/log.c @@ -20,6 +20,7 @@ #include <stdarg.h> #include <time.h> #include <unistd.h> +#include <errno.h> #include "nest/bird.h" #include "nest/cli.h" @@ -209,6 +210,7 @@ bug(const char *msg, ...) va_start(args, msg); vlog(L_BUG[0], msg, args); + va_end(args); abort(); } @@ -226,6 +228,7 @@ die(const char *msg, ...) va_start(args, msg); vlog(L_FATAL[0], msg, args); + va_end(args); exit(1); } @@ -285,18 +288,22 @@ log_switch(int debug, list *l, char *new_syslog_name) current_log_list = l; #ifdef HAVE_SYSLOG - char *old_syslog_name = current_syslog_name; - current_syslog_name = new_syslog_name; - - if (old_syslog_name && new_syslog_name && - !strcmp(old_syslog_name, new_syslog_name)) + if (current_syslog_name && new_syslog_name && + !strcmp(current_syslog_name, new_syslog_name)) return; - if (old_syslog_name) + if (current_syslog_name) + { closelog(); + xfree(current_syslog_name); + current_syslog_name = NULL; + } if (new_syslog_name) - openlog(new_syslog_name, LOG_CONS | LOG_NDELAY, LOG_DAEMON); + { + current_syslog_name = xstrdup(new_syslog_name); + openlog(current_syslog_name, LOG_CONS | LOG_NDELAY, LOG_DAEMON); + } #endif } @@ -312,7 +319,11 @@ log_init_debug(char *f) else if (!*f) dbgf = stderr; else if (!(dbgf = fopen(f, "a"))) - log(L_ERR "Error opening debug file `%s': %m", f); + { + /* Cannot use die() nor log() here, logging is not yet initialized */ + fprintf(stderr, "bird: Unable to open debug file %s: %s\n", f, strerror(errno)); + exit(1); + } if (dbgf) setvbuf(dbgf, NULL, _IONBF, 0); } diff --git a/sysdep/unix/main.c b/sysdep/unix/main.c index 1f47680e..c1b92b7e 100644 --- a/sysdep/unix/main.c +++ b/sysdep/unix/main.c @@ -8,7 +8,9 @@ #undef LOCAL_DEBUG -#define _GNU_SOURCE 1 +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif #include <stdio.h> #include <stdlib.h> @@ -73,7 +75,7 @@ async_dump(void) #else static inline void -drop_uid(uid_t uid) +drop_uid(uid_t uid UNUSED) { die("Cannot change user on this platform"); } @@ -419,7 +421,7 @@ cli_get_command(cli *c) } static int -cli_rx(sock *s, int size UNUSED) +cli_rx(sock *s, uint size UNUSED) { cli_kick(s->data); return 0; @@ -439,7 +441,7 @@ cli_err(sock *s, int err) } static int -cli_connect(sock *s, int size UNUSED) +cli_connect(sock *s, uint size UNUSED) { cli *c; @@ -621,7 +623,7 @@ signal_init(void) * Parsing of command-line arguments */ -static char *opt_list = "c:dD:ps:P:u:g:flR"; +static char *opt_list = "c:dD:ps:P:u:g:flRh"; static int parse_and_exit; char *bird_name; static char *use_user; @@ -629,10 +631,43 @@ static char *use_group; static int run_in_foreground = 0; static void -usage(void) +display_usage(void) +{ + fprintf(stderr, "Usage: %s [--version] [--help] [-c <config-file>] [OPTIONS]\n", bird_name); +} + +static void +display_help(void) +{ + display_usage(); + + fprintf(stderr, + "\n" + "Options: \n" + " -c <config-file> Use given configuration file instead\n" + " of prefix/etc/bird.conf\n" + " -d Enable debug messages and run bird in foreground\n" + " -D <debug-file> Log debug messages to given file instead of stderr\n" + " -f Run bird in foreground\n" + " -g <group> Use given group ID\n" + " -h, --help Display this information\n" + " -l Look for a configuration file and a communication socket\n" + " file in the current working directory\n" + " -p Test configuration file and exit without start\n" + " -P <pid-file> Create a PID file with given filename\n" + " -R Apply graceful restart recovery after start\n" + " -s <control-socket> Use given filename for a control socket\n" + " -u <user> Drop privileges and use given user ID\n" + " --version Display version of BIRD\n"); + + exit(0); +} + +static void +display_version(void) { - fprintf(stderr, "Usage: %s [-c <config-file>] [-d] [-D <debug-file>] [-p] [-s <control-socket>] [-P <pid-file>] [-u <user>] [-g <group>] [-f] [-l] [-R]\n", bird_name); - exit(1); + fprintf(stderr, "BIRD version " BIRD_VERSION "\n"); + exit(0); } static inline char * @@ -706,12 +741,9 @@ parse_args(int argc, char **argv) if (argc == 2) { if (!strcmp(argv[1], "--version")) - { - fprintf(stderr, "BIRD version " BIRD_VERSION "\n"); - exit(0); - } + display_version(); if (!strcmp(argv[1], "--help")) - usage(); + display_help(); } while ((c = getopt(argc, argv, opt_list)) >= 0) switch (c) @@ -755,11 +787,19 @@ parse_args(int argc, char **argv) case 'R': graceful_restart_recovery(); break; + case 'h': + display_help(); + break; default: - usage(); + fputc('\n', stderr); + display_usage(); + exit(1); } if (optind < argc) - usage(); + { + display_usage(); + exit(1); + } } /* |