tech-userlevel archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
blacklisting nodes that probe non-existant nodes
Hi
So I have an IPv6 capable interface on my router.
When I run route monitor, I get a lot of RTM_MISS for non-existant nodes on my
prefix. Logging this to the ERLITE takes a fair chunk of CPU time.
I added a small patch to the kernel to add the source address of the requesting
node here:
https://mail-index.netbsd.org/source-changes/2020/03/09/msg114961.html
I would like to move this to the next level - blacklisting the source address!
I've added two patches to blacklistd:
https://mail-index.netbsd.org/source-changes/2020/03/11/msg114980.html
https://mail-index.netbsd.org/source-changes/2020/03/11/msg114981.html
This now allows a userland application to poll route(4) messages for RTM_MISS
and blacklist the RTA_AUTHOR if his address does not belong to a prefix on our
network.
I have authored such an application, routemissd (although I'm not beholden to
the name).
Patch against current attached, comments welcome.
For the record, I have one node probing my network in random burst lengths,
maybe two or three times a minute, sometimes nothing for a few minutes.
Currently the smallest gap is about 8 minutes.
When routemissd is running, my load averages are pratically zero on my ERLITE,
even with route monitor constantly logging.
I doubt this will be of any use for systems that are not routers, but I would
still like to include it in NetBSD base system.
Comments, as ever, welcome.
Roy
diff -r 4403ed553577 distrib/sets/lists/base/mi
--- a/distrib/sets/lists/base/mi Tue Mar 10 22:38:41 2020 +0000
+++ b/distrib/sets/lists/base/mi Wed Mar 11 05:29:04 2020 +0000
@@ -1960,6 +1960,7 @@
./usr/sbin/rndc base-bind-bin
./usr/sbin/rndc-confgen base-bind-bin
./usr/sbin/route6d base-router-bin use_inet6
+./usr/sbin/routemissd base-router-root
./usr/sbin/rpc.bootparamd base-bootserver-bin
./usr/sbin/rpc.lockd base-nfsserver-bin
./usr/sbin/rpc.pcnfsd base-nfsserver-bin
diff -r 4403ed553577 distrib/sets/lists/etc/mi
--- a/distrib/sets/lists/etc/mi Tue Mar 10 22:38:41 2020 +0000
+++ b/distrib/sets/lists/etc/mi Wed Mar 11 05:29:04 2020 +0000
@@ -290,6 +290,7 @@
./etc/rc.d/root etc-sys-rc
./etc/rc.d/route6d etc-router-rc
./etc/rc.d/routed etc-router-rc
+./etc/rc.d/routemissd etc-router-rc
./etc/rc.d/rpcbind etc-rpcbind-rc
./etc/rc.d/rtadvd etc-net-rc
./etc/rc.d/rtclocaltime etc-sys-rc
diff -r 4403ed553577 distrib/sets/lists/man/mi
--- a/distrib/sets/lists/man/mi Tue Mar 10 22:38:41 2020 +0000
+++ b/distrib/sets/lists/man/mi Wed Mar 11 05:29:04 2020 +0000
@@ -3048,6 +3048,7 @@
./usr/share/man/cat8/route.0 man-netutil-catman .cat
./usr/share/man/cat8/route6d.0 man-router-catman use_inet6,.cat
./usr/share/man/cat8/routed.0 man-router-catman .cat
+./usr/share/man/cat8/routemissd.0 man-router-catman .cat
./usr/share/man/cat8/rpc.bootparamd.0 man-bootserver-catman .cat
./usr/share/man/cat8/rpc.lockd.0 man-nfsserver-catman .cat
./usr/share/man/cat8/rpc.pcnfsd.0 man-nfsserver-catman .cat
@@ -6012,6 +6013,7 @@
./usr/share/man/html8/route.html man-netutil-htmlman html
./usr/share/man/html8/route6d.html man-router-htmlman use_inet6,html
./usr/share/man/html8/routed.html man-router-htmlman html
+./usr/share/man/html8/routemissd.html man-router-htmlman html
./usr/share/man/html8/rpc.bootparamd.html man-bootserver-htmlman html
./usr/share/man/html8/rpc.lockd.html man-nfsserver-htmlman html
./usr/share/man/html8/rpc.pcnfsd.html man-nfsserver-htmlman html
@@ -9049,6 +9051,7 @@
./usr/share/man/man8/moused.8 man-sysutil-man .man
./usr/share/man/man8/mrinfo.8 man-netutil-man .man
./usr/share/man/man8/mrouted.8 man-router-man .man
+./usr/share/man/man8/routemissd.8 man-router-man .man
./usr/share/man/man8/mscdlabel.8 man-sysutil-man .man
./usr/share/man/man8/mtrace.8 man-netutil-man .man
./usr/share/man/man8/mtrace6.8 man-obsolete obsolete
diff -r 4403ed553577 etc/defaults/rc.conf
--- a/etc/defaults/rc.conf Tue Mar 10 22:38:41 2020 +0000
+++ b/etc/defaults/rc.conf Wed Mar 11 05:29:04 2020 +0000
@@ -266,6 +266,7 @@
gated=NO
mrouted=NO mrouted_flags=""
route6d=NO route6d_flags=""
+routemissd=NO
ldpd=NO
# Daemons used to boot other hosts over a network.
diff -r 4403ed553577 etc/rc.d/Makefile
--- a/etc/rc.d/Makefile Tue Mar 10 22:38:41 2020 +0000
+++ b/etc/rc.d/Makefile Wed Mar 11 05:29:04 2020 +0000
@@ -35,7 +35,8 @@
perusertmp pf pf_boot pflogd postfix powerd ppp pwcheck \
quota \
racoon rpcbind raidframe raidframeparity random_seed rarpd \
- rbootd resize_root rndctl root route6d routed rtadvd \
+ rbootd resize_root rndctl root route6d routed routemissd \
+ rtadvd \
rtclocaltime rwho \
savecore screenblank securelevel smtoff sshd \
staticroute swap1 swap2 sysctl sysdb syslogd \
diff -r 4403ed553577 usr.sbin/Makefile
--- a/usr.sbin/Makefile Tue Mar 10 22:38:41 2020 +0000
+++ b/usr.sbin/Makefile Wed Mar 11 05:29:04 2020 +0000
@@ -22,7 +22,7 @@
paxctl pcictl perfused psrset pstat pwd_mkdb postinstall \
powerd puffs \
quot quotacheck quotaon quotarestore \
- rarpd rbootd rdate repquota rmt rpc.bootparamd rpc.lockd \
+ rarpd rbootd rdate repquota rmt routemissd rpc.bootparamd rpc.lockd \
rpc.pcnfsd rpc.statd rpcbind rwhod \
sa screenblank sdpd service services_mkdb sesd schedctl \
sliplogin spray \
diff -r 4403ed553577 usr.sbin/routemissd/Makefile
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr.sbin/routemissd/Makefile Wed Mar 11 05:29:04 2020 +0000
@@ -0,0 +1,12 @@
+# $NetBSD: $
+#
+
+WARNS?= 6
+
+PROG= routemissd
+MAN= routemissd.8
+
+LDADD+= -lblacklist
+DPADD+= ${LIBBLACKLIST}
+
+.include <bsd.prog.mk>
diff -r 4403ed553577 usr.sbin/routemissd/routemissd.8
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr.sbin/routemissd/routemissd.8 Wed Mar 11 05:29:04 2020 +0000
@@ -0,0 +1,65 @@
+.\" $NetBSD: $
+.\"
+.\" Copyright (c) 2020 The NetBSD Foundation, Inc.
+.\" All rights reserved.
+.\"
+.\" This code is derived from software contributed to The NetBSD Foundation
+.\" by Roy Marples.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+.\" POSSIBILITY OF SUCH DAMAGE.
+.\"
+.Dd March 10, 2020
+.Dt ROUTEMISSD 8
+.Os
+.Sh NAME
+.Nm routemissd
+.Nd blacklists nodes who probe non-existant nodes on our prefix
+.Sh SYNOPSIS
+.Nm routemissd
+.Op Fl dfu
+.Sh DESCRIPTION
+With the emergence of IPv6, edge routers are seeing OS finger-printing
+probes to random addresses within their allocated prefix in the hope
+of finding a victim to attack.
+.Pp
+.Nm
+works by reading RTM_MISS messages from a
+.Xr route 4
+socket and extracting RTA_AUTHOR as the source address.
+If the source address does not match any of our on-link prefixes then
+.Nm
+sends it to
+.Xr blacklistd 8 ,
+which will then block the source address at the firewall.
+.Pp
+The command line options are:
+.Bl -tag -width indent
+.It Fl d
+Log debugging informaton.
+.It Fl f
+Run in foreground mode.
+Useful when debugging.
+.It Fl u Ar username
+Run as this user and chroot to their home directory.
+.El
+.Sh AUTHORS
+.An Roy Marples Aq Mt roy%marples.name@localhost
diff -r 4403ed553577 usr.sbin/routemissd/routemissd.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr.sbin/routemissd/routemissd.c Wed Mar 11 05:29:04 2020 +0000
@@ -0,0 +1,457 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (c) 2020 The NetBSD Foundation, Inc.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Roy Marples.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+
+#include <net/if_dl.h>
+#include <net/route.h>
+
+#include <arpa/inet.h>
+
+#include <blacklist.h>
+#include <err.h>
+#include <errno.h>
+#include <pwd.h>
+#include <signal.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <unistd.h>
+
+#ifndef __STRING
+#define __STRING(x) #x
+#endif
+
+/* Allow for AF_INET, AF_INET6 and AF_LINK */
+#define MAX_ADDRSTRLEN (20 * 3)
+static const char opts[] = "dfu";
+
+static bool exit_now = false;
+static int exit_code = EXIT_FAILURE;
+static int rtm_seq = 0;
+
+static struct blacklist *bl;
+
+static const char *
+hwaddr_ntoa(const void *hwaddr, size_t hwlen, char *buf, size_t buflen)
+{
+ const unsigned char *hp, *ep;
+ char *p;
+
+ if (buf == NULL)
+ return NULL;
+
+ if (hwlen * 3 > buflen) {
+ errno = ENOBUFS;
+ return NULL;
+ }
+
+ hp = hwaddr;
+ ep = hp + hwlen;
+ p = buf;
+
+ while (hp < ep) {
+ if (hp != hwaddr)
+ *p ++= ':';
+ p += snprintf(p, 3, "%.2x", *hp++);
+ }
+ *p ++= '\0';
+ return buf;
+}
+
+static const char *
+sa_addrtop(const struct sockaddr *sa, char *buf, socklen_t len)
+{
+ const void *addr;
+
+ if (sa == NULL || sa->sa_family == 0) {
+ *buf = '\0';
+ return NULL;
+ }
+
+#ifndef CLLADDR
+#define CLLADDR(sdl) (const void *)((sdl)->sdl_data + (sdl)->sdl_nlen)
+#endif
+ if (sa->sa_family == AF_LINK) {
+ const struct sockaddr_dl *sdl;
+
+ sdl = (const void *)sa;
+ if (sdl->sdl_alen == 0) {
+ if (snprintf(buf, len, "link#%d", sdl->sdl_index) == -1)
+ return NULL;
+ return buf;
+ }
+ return hwaddr_ntoa(CLLADDR(sdl), sdl->sdl_alen, buf, len);
+ }
+
+ switch (sa->sa_family) {
+ case AF_INET:
+ addr = &((const struct sockaddr_in *)sa)->sin_addr;
+ break;
+ case AF_INET6:
+ addr = &((const struct sockaddr_in6 *)sa)->sin6_addr;
+ break;
+ default:
+ errno = EAFNOSUPPORT;
+ return NULL;
+ }
+ return inet_ntop(sa->sa_family, addr, buf, len);
+}
+
+static bool
+sa_is_unspecified(const struct sockaddr *sa)
+{
+
+ switch(sa->sa_family) {
+ case AF_UNSPEC:
+ return true;
+#ifdef INET
+ case AF_INET:
+ return satocsin(sa)->sin_addr.s_addr == INADDR_ANY;
+#endif /* INET */
+#ifdef INET6
+ case AF_INET6:
+ return IN6_IS_ADDR_UNSPECIFIED(&satocsin6(sa)->sin6_addr);
+#endif /* INET6 */
+ default:
+ errno = EAFNOSUPPORT;
+ return false;
+ }
+}
+
+static int
+extract_addrs(const char *cp, size_t msglen,
+ int addrs, const struct sockaddr *sa[])
+{
+ int i;
+ const char *ep = cp + msglen;
+
+ for (i = 0; i < RTAX_MAX; i++) {
+ if ((1 << i) & addrs) {
+ if (cp >= ep) {
+ errno = EINVAL;
+ return -1;
+ }
+ sa[i] = (const struct sockaddr *)cp;
+ RT_ADVANCE(cp, sa[i]);
+ } else
+ sa[i] = NULL;
+ }
+
+ return 0;
+}
+
+static int
+route_is_default(const struct sockaddr *dst)
+{
+ union {
+ char buf[2048];
+ struct rt_msghdr hdr;
+ } u;
+ struct rt_msghdr *rtm = &u.hdr;
+ pid_t pid = getpid();
+ char *cp = u.buf + sizeof(*rtm);
+ int s;
+ ssize_t msglen;
+ const struct sockaddr *sa[RTAX_MAX];
+
+ memset(&u, 0, sizeof(u));
+ rtm->rtm_version = RTM_VERSION;
+ rtm->rtm_seq = ++rtm_seq;
+ rtm->rtm_pid = pid;
+ rtm->rtm_type = RTM_GET;
+ rtm->rtm_addrs = RTA_DST;
+
+ memcpy(cp, dst, dst->sa_len);
+ cp += RT_ROUNDUP(dst->sa_len);
+
+ rtm->rtm_msglen = (unsigned short)(cp - (char *)rtm);
+
+ s = socket(PF_ROUTE, SOCK_RAW, 0);
+ if (s == -1)
+ return -1;
+ if (write(s, rtm, rtm->rtm_msglen) == -1) {
+ int serrno = errno;
+
+ close(s);
+ /* If we didn't find any route, pretend it
+ * belongs to the default route. */
+ return serrno == ESRCH ? 1 : -1;
+ }
+ do {
+ msglen = read(s, &u, sizeof(u));
+ } while (msglen >= (ssize_t)
+ MAX(offsetof(struct rt_msghdr, rtm_pid),
+ offsetof(struct rt_msghdr, rtm_seq)) &&
+ rtm->rtm_pid != pid && rtm->rtm_seq != rtm_seq);
+ close(s);
+ if (msglen == -1)
+ return -1;
+
+ if (extract_addrs((char *)rtm + sizeof(*rtm),
+ (size_t)msglen - sizeof(*rtm), rtm->rtm_addrs, sa) == -1)
+ return -1;
+
+ if (sa[RTAX_DST] == NULL) {
+ errno = ENOENT;
+ return -1;
+ }
+
+ return sa_is_unspecified(sa[RTAX_DST]) ? 1 : 0;
+}
+
+static void
+dispatch_rtm(struct rt_msghdr *rtm, size_t msglen)
+{
+ const struct sockaddr *sa[RTAX_MAX];
+ char dst[MAX_ADDRSTRLEN], gate[MAX_ADDRSTRLEN], author[MAX_ADDRSTRLEN];
+ char msg[256];
+ int is_default_route;
+
+ if ((size_t)msglen < sizeof(*rtm)) {
+ syslog(LOG_ERR, "truncated route message of %zd", msglen);
+ return;
+ }
+
+ if (rtm->rtm_type != RTM_MISS || rtm->rtm_pid == getpid())
+ return;
+
+ if (extract_addrs((char *)rtm + sizeof(*rtm), msglen - sizeof(*rtm),
+ rtm->rtm_addrs, sa) == -1)
+ {
+ syslog(LOG_ERR, "extract_addrs: %m");
+ return;
+ }
+
+ if (sa[RTAX_DST] == NULL) {
+ syslog(LOG_ERR, "no destination address");
+ return;
+ }
+
+ if (sa_addrtop(sa[RTAX_DST], dst, sizeof(dst)) == NULL)
+ syslog(LOG_ERR, "sa_addrtop: RTAX_DST: %m");
+ if (sa_addrtop(sa[RTAX_GATEWAY], gate, sizeof(gate)) == NULL &&
+ sa[RTAX_GATEWAY] != NULL)
+ syslog(LOG_ERR, "sa_addrtop: RTAX_GATEWAY: %m");
+
+ if (sa[RTAX_AUTHOR] == NULL) {
+ syslog(LOG_DEBUG, "RTM_MISS %s on %s", dst, gate);
+ return;
+ }
+
+ if (sa_addrtop(sa[RTAX_AUTHOR], author, sizeof(author)) == NULL)
+ syslog(LOG_ERR, "sa_addrtop: RTAX_AUTHOR: %m");
+
+ is_default_route = route_is_default(sa[RTAX_AUTHOR]);
+ if (is_default_route == -1)
+ syslog(LOG_ERR, "route_is_default: %m");
+ if (is_default_route != 0) {
+ /* This address exists on a prefix we have, ignore it. */
+ syslog(LOG_DEBUG, "RTM_MISS %s on %s from %s",
+ dst, gate, author);
+ return;
+ }
+
+ if (snprintf(msg, sizeof(msg),
+ "RTM_MISS %s on %s, blacklisting %s",
+ dst, gate, author) >= (int)sizeof(msg))
+ syslog(LOG_ERR, "snprintf: %m");
+ syslog(LOG_INFO, "%s", msg);
+
+ /* BLACKLIST_AUTH_FAIL isn't really an authentication failure, but it's
+ * the best message type we can work with. */
+ if (blacklist_sa_r(bl, BLACKLIST_AUTH_FAIL, -1,
+ sa[RTAX_AUTHOR], sa[RTAX_AUTHOR]->sa_len, msg) == -1)
+ syslog(LOG_ERR, "blacklist_sa_r: %m");
+}
+
+static void
+dispatch_signal(int sig)
+{
+
+ if (sig == SIGTERM)
+ exit_code = EXIT_SUCCESS;
+ if (sig != SIGHUP)
+ exit_now = true;
+}
+
+static void
+setup_signals(void)
+{
+ struct sigaction sa = { .sa_handler = dispatch_signal };
+
+ if (sigaction(SIGHUP, &sa, NULL) == -1)
+ warn("sigaction: SIGHUP");
+ if (sigaction(SIGINT, &sa, NULL) == -1)
+ warn("sigaction: SIGINT");
+ if (sigaction(SIGTERM, &sa, NULL) == -1)
+ warn("sigaction: SIGTERM");
+}
+
+static int
+setup_overflow(int s)
+{
+#if defined(SO_RERROR)
+ int on = 1;
+
+ return setsockopt(s, SOL_SOCKET, SO_RERROR, &on, sizeof(on));
+#else
+#warning No socket receive buffer overflow detection
+ return 0;
+#endif
+}
+
+static int
+setup_msgfilter(int s)
+{
+#if defined(RO_MSGFILTER)
+ unsigned char msgfilter[] = { RTM_MISS };
+
+ return setsockopt(s, PF_ROUTE, RO_MSGFILTER,
+ &msgfilter, sizeof(msgfilter));
+#elif defined(ROUTE_MSGFILTER)
+ unsigned int msgfilter_mask = ROUTE_FILTER(RTM_MISS);
+
+ return setsockopt(s, PF_ROUTE, ROUTE_MSGFILTER,
+ &msgfilter_mask, sizeof(msgfilter_mask));
+#else
+#warning No route(4) message filtering
+ return 0;
+#endif
+}
+
+static void
+usage(void)
+{
+
+ fprintf(stderr, "usage: %s [-%s]\n", getprogname(), opts);
+ exit(EXIT_FAILURE);
+}
+
+int
+main(int argc, char * const *argv)
+{
+ bool foreground = false, debug = false;
+ int ch, s, logopts = 0;
+ struct passwd *pw;
+ const char *username;
+ ssize_t msglen;
+ union {
+ char buf[2048];
+ struct rt_msghdr hdr;
+ } rtm;
+
+#ifdef ROUTEMISSD_USER
+ username = __STRING(ROUTEMISSD_USER);
+#else
+ username = NULL;
+#endif
+
+ while ((ch = getopt(argc, argv, opts)) != -1) {
+ switch (ch) {
+ case 'd':
+ debug = true;
+ break;
+ case 'f':
+ foreground = true;
+ logopts |= LOG_PERROR;
+ break;
+ case 'u':
+ username = argv[optind];
+ break;
+ case '?': /* FALLTHROUGH */
+ default:
+ usage();
+ /* NOTREACHED */
+ }
+ }
+
+ setup_signals();
+
+ if (username != NULL) {
+ pw = getpwnam(username);
+ if (pw == NULL) {
+ if (errno != 0)
+ err(EXIT_FAILURE, "getpwnam");
+ errx(EXIT_FAILURE, "no such user %s", username);
+ }
+ if (setgroups(1, &pw->pw_gid) == -1 ||
+ setgid(pw->pw_gid) == -1 ||
+ setuid(pw->pw_uid) == -1)
+ err(EXIT_FAILURE, "failed to drop privileges");
+ } else
+ pw = NULL;
+
+ bl = blacklist_open();
+ if (bl == NULL)
+ err(EXIT_FAILURE, "blacklist_open");
+
+ s = socket(PF_ROUTE, SOCK_RAW, 0);
+ if (s == -1)
+ err(EXIT_FAILURE, "socket");
+
+ if (setup_msgfilter(s) == -1)
+ warn("setup_msgfilter");
+ if (setup_overflow(s) == -1)
+ warn("setup_overflow");
+
+ openlog(getprogname(), LOG_PID | logopts, LOG_DAEMON);
+ if (!debug)
+ setlogmask(LOG_UPTO(LOG_INFO));
+
+ if (!foreground) {
+ if (daemon(0, 0) == -1)
+ err(EXIT_FAILURE, "daemon");
+ }
+
+ if (pw != NULL) {
+ if (chroot(pw->pw_dir) == -1)
+ err(EXIT_FAILURE, "chroot: %s:", pw->pw_dir);
+ if (chdir("/") == -1)
+ err(EXIT_FAILURE, "chdir: /:");
+ }
+
+ for (exit_now = false; !exit_now ;) {
+ msglen = read(s, &rtm, sizeof(rtm));
+ if (msglen == -1) {
+ if (errno != EINTR)
+ syslog(LOG_WARNING, "read: %m");
+ continue;
+ }
+ dispatch_rtm(&rtm.hdr, (size_t)msglen);
+ }
+
+ close(s);
+ blacklist_close(bl);
+ closelog();
+ return exit_code;
+}
Home |
Main Index |
Thread Index |
Old Index