summaryrefslogtreecommitdiff
path: root/sysdep/unix
diff options
context:
space:
mode:
Diffstat (limited to 'sysdep/unix')
-rw-r--r--sysdep/unix/Makefile3
-rw-r--r--sysdep/unix/io.c47
-rw-r--r--sysdep/unix/krt.Y18
-rw-r--r--sysdep/unix/krt.c6
-rw-r--r--sysdep/unix/log.c27
-rw-r--r--sysdep/unix/main.c70
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);
+ }
}
/*