The branch main has been updated by jlduran:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=7238317403b95a8e35cf0bc7cd66fbd78ecbe521

commit 7238317403b95a8e35cf0bc7cd66fbd78ecbe521
Author:     Jose Luis Duran <[email protected]>
AuthorDate: 2025-10-12 17:14:27 +0000
Commit:     Jose Luis Duran <[email protected]>
CommitDate: 2025-10-12 17:14:27 +0000

    blocklist: Rename blacklist to blocklist
    
    Follow up upstream rename from blacklist to blocklist.
    
    - Old names and rc scripts are still valid, but emitting an ugly warning
    - Old firewall rules and anchor names should work, but emitting an ugly
      warning
    - Old MK_BLACKLIST* knobs are wired to the new ones
    
    Although care has been taken not to break current configurations, this
    is a large patch containing mostly duplicated code.  If issues arise, it
    will be swiftly reverted.
    
    Reviewed by:    ivy (pkgbase)
    Approved by:    emaste (mentor)
    MFC after:      2 days
    Relnotes:       yes
---
 contrib/blocklist/bin/blacklistctl.c               | 170 ++++++
 contrib/blocklist/bin/blacklistd.c                 | 592 +++++++++++++++++++++
 contrib/blocklist/bin/old_internal.c               |  50 ++
 contrib/blocklist/bin/old_internal.h               |  58 ++
 contrib/blocklist/include/blacklist.h              |  65 +++
 contrib/blocklist/include/old_bl.h                 |  80 +++
 contrib/blocklist/lib/blacklist.c                  | 117 ++++
 contrib/blocklist/lib/old_bl.c                     | 554 +++++++++++++++++++
 crypto/openssh/auth-pam.c                          |   4 +-
 crypto/openssh/auth.c                              |   8 +-
 crypto/openssh/{blacklist.c => blocklist.c}        |  16 +-
 .../{blacklist_client.h => blocklist_client.h}     |  30 +-
 crypto/openssh/monitor.c                           |   8 +-
 crypto/openssh/servconf.c                          |  18 +-
 crypto/openssh/servconf.h                          |   2 +-
 crypto/openssh/sshd-session.c                      |  10 +-
 crypto/openssh/sshd_config                         |   2 +-
 crypto/openssh/sshd_config.5                       |  14 +-
 lib/Makefile                                       |   1 +
 lib/libblacklist/Makefile                          |  24 +-
 lib/libblocklist/Makefile                          |  30 ++
 lib/libblocklist/Makefile.depend                   |  16 +
 lib/libsysdecode/Makefile.depend                   |   2 +-
 libexec/Makefile                                   |   6 +-
 libexec/blacklistd-helper/Makefile                 |   7 -
 libexec/blocklistd-helper/Makefile                 |  10 +
 .../Makefile.depend                                |   0
 libexec/blocklistd-helper/blacklistd-helper        | 293 ++++++++++
 libexec/fingerd/Makefile                           |   8 +-
 libexec/fingerd/Makefile.depend.options            |   2 +-
 libexec/fingerd/fingerd.c                          |  16 +-
 libexec/rc/rc.conf                                 |   6 +-
 libexec/rc/rc.d/Makefile                           |   5 +-
 libexec/rc/rc.d/blacklistd                         |  10 +-
 libexec/rc/rc.d/blocklistd                         |  46 ++
 release/packages/ucl/blocklist-all.ucl             |   8 +-
 secure/libexec/sshd-auth/Makefile                  |  10 +-
 secure/libexec/sshd-session/Makefile               |  10 +-
 secure/usr.sbin/sshd/Makefile.depend.options       |   2 +-
 share/man/man5/periodic.conf.5                     |   2 +-
 share/man/man5/src.conf.5                          |  43 +-
 share/mk/bsd.libnames.mk                           |   1 +
 share/mk/local.dirdeps-options.mk                  |   1 +
 share/mk/src.libnames.mk                           |  10 +-
 share/mk/src.opts.mk                               |  10 +
 targets/pseudo/userland/Makefile.depend            |   6 +
 targets/pseudo/userland/lib/Makefile.depend        |   4 +
 targets/pseudo/userland/libexec/Makefile.depend    |   4 +-
 tools/build/mk/OptionalObsoleteFiles.inc           |  21 +-
 tools/build/options/WITHOUT_BLACKLIST              |   6 +-
 tools/build/options/WITHOUT_BLACKLIST_SUPPORT      |   8 +-
 tools/build/options/WITHOUT_BLOCKLIST              |   4 +
 tools/build/options/WITHOUT_BLOCKLIST_SUPPORT      |   6 +
 usr.sbin/Makefile                                  |   2 +
 usr.sbin/blacklistctl/Makefile                     |  10 +-
 usr.sbin/blacklistd/Makefile                       |  13 +-
 usr.sbin/blacklistd/blacklistd.conf                |  10 +-
 usr.sbin/blocklistctl/Makefile                     |  22 +
 usr.sbin/blocklistctl/Makefile.depend              |  18 +
 usr.sbin/blocklistd/Makefile                       |  23 +
 usr.sbin/blocklistd/Makefile.depend                |  18 +
 usr.sbin/blocklistd/blocklistd.conf                |  16 +
 usr.sbin/periodic/etc/security/520.pfdenied        |   2 +-
 63 files changed, 2426 insertions(+), 144 deletions(-)

diff --git a/contrib/blocklist/bin/blacklistctl.c 
b/contrib/blocklist/bin/blacklistctl.c
new file mode 100644
index 000000000000..6298a08b10b4
--- /dev/null
+++ b/contrib/blocklist/bin/blacklistctl.c
@@ -0,0 +1,170 @@
+/*     $NetBSD: blocklistctl.c,v 1.4 2025/02/11 17:48:30 christos Exp $        
*/
+
+/*-
+ * Copyright (c) 2015 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Christos Zoulas.
+ *
+ * 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.
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef HAVE_SYS_CDEFS_H
+#include <sys/cdefs.h>
+#endif
+__RCSID("$NetBSD: blocklistctl.c,v 1.4 2025/02/11 17:48:30 christos Exp $");
+
+#include <stdio.h>
+#include <time.h>
+#ifdef HAVE_LIBUTIL_H
+#include <libutil.h>
+#endif
+#ifdef HAVE_UTIL_H
+#include <util.h>
+#endif
+#include <fcntl.h>
+#include <string.h>
+#include <syslog.h>
+#include <err.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/socket.h>
+
+#include "conf.h"
+#include "state.h"
+#include "old_internal.h"
+#include "support.h"
+
+static __dead void
+usage(int c)
+{
+       if (c == 0)
+               warnx("Missing/unknown command");
+       else if (c != '?')
+               warnx("Unknown option `%c'", (char)c);
+       fprintf(stderr,
+           "Usage: %s dump [-abdnrw] [-D dbname]\n", getprogname());
+       exit(EXIT_FAILURE);
+}
+
+static const char *
+star(char *buf, size_t len, int val)
+{
+       if (val == -1)
+               return "*";
+       snprintf(buf, len, "%d", val);
+       return buf;
+}
+
+int
+main(int argc, char *argv[])
+{
+       const char *dbname = _PATH_BLSTATE;
+       DB *db;
+       struct conf c;
+       struct dbinfo dbi;
+       unsigned int i;
+       struct timespec ts;
+       int all, blocked, remain, wide, noheader;
+       int o;
+
+       noheader = wide = blocked = all = remain = 0;
+       lfun = dlog;
+
+       if (argc == 1 || strcmp(argv[1], "dump") != 0)
+               usage(0);
+
+       argc--;
+       argv++;
+
+       while ((o = getopt(argc, argv, "abD:dnrw")) != -1)
+               switch (o) {
+               case 'a':
+                       all = 1;
+                       blocked = 0;
+                       break;
+               case 'b':
+                       blocked = 1;
+                       break;
+               case 'D':
+                       dbname = optarg;
+                       break;
+               case 'd':
+                       debug++;
+                       break;
+               case 'n':
+                       noheader = 1;
+                       break;
+               case 'r':
+                       remain = 1;
+                       break;
+               case 'w':
+                       wide = 1;
+                       break;
+               default:
+                       usage(o);
+               }
+
+       db = state_open(dbname, O_RDONLY, 0);
+       if (db == NULL)
+               err(EXIT_FAILURE, "Can't open `%s'", dbname);
+
+       clock_gettime(CLOCK_REALTIME, &ts);
+       wide = wide ? 8 * 4 + 7 : 4 * 3 + 3;
+       if (!noheader)
+               printf("%*.*s/ma:port\tid\tnfail\t%s\n", wide, wide,
+                   "address", remain ? "remaining time" : "last access");
+       for (i = 1; state_iterate(db, &c, &dbi, i) != 0; i = 0) {
+               char buf[BUFSIZ];
+               char mbuf[64], pbuf[64];
+               if (!all) {
+                       if (blocked) {
+                               if (c.c_nfail == -1 || dbi.count < c.c_nfail)
+                                       continue;
+                       } else {
+                               if (dbi.count >= c.c_nfail)
+                                       continue;
+                       }
+               }
+               sockaddr_snprintf(buf, sizeof(buf), "%a", (void *)&c.c_ss);
+               printf("%*.*s/%s:%s\t", wide, wide, buf,
+                   star(mbuf, sizeof(mbuf), c.c_lmask),
+                   star(pbuf, sizeof(pbuf), c.c_port));
+               if (c.c_duration == -1) {
+                       strlcpy(buf, "never", sizeof(buf));
+               } else {
+                       if (remain)
+                               fmtydhms(buf, sizeof(buf),
+                                   c.c_duration - (ts.tv_sec - dbi.last));
+                       else
+                               fmttime(buf, sizeof(buf), dbi.last);
+               }
+               printf("%s\t%d/%s\t%-s\n", dbi.id, dbi.count,
+                   star(mbuf, sizeof(mbuf), c.c_nfail), buf);
+       }
+       state_close(db);
+       return EXIT_SUCCESS;
+}
diff --git a/contrib/blocklist/bin/blacklistd.c 
b/contrib/blocklist/bin/blacklistd.c
new file mode 100644
index 000000000000..ded3075ed707
--- /dev/null
+++ b/contrib/blocklist/bin/blacklistd.c
@@ -0,0 +1,592 @@
+/*     $NetBSD: blocklistd.c,v 1.10 2025/03/26 17:09:35 christos Exp $ */
+
+/*-
+ * Copyright (c) 2015 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Christos Zoulas.
+ *
+ * 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.
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef HAVE_SYS_CDEFS_H
+#include <sys/cdefs.h>
+#endif
+__RCSID("$NetBSD: blocklistd.c,v 1.10 2025/03/26 17:09:35 christos Exp $");
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/queue.h>
+
+#ifdef HAVE_LIBUTIL_H
+#include <libutil.h>
+#endif
+#ifdef HAVE_UTIL_H
+#include <util.h>
+#endif
+#include <string.h>
+#include <signal.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <stdbool.h>
+#include <string.h>
+#include <inttypes.h>
+#include <syslog.h>
+#include <ctype.h>
+#include <limits.h>
+#include <errno.h>
+#include <poll.h>
+#include <fcntl.h>
+#include <err.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <time.h>
+#include <ifaddrs.h>
+#include <netinet/in.h>
+
+#include "old_bl.h"
+#include "old_internal.h"
+#include "conf.h"
+#include "run.h"
+#include "state.h"
+#include "support.h"
+
+static const char *configfile = _PATH_BLCONF;
+static DB *state;
+static const char *dbfile = _PATH_BLSTATE;
+static sig_atomic_t readconf;
+static sig_atomic_t done;
+static int vflag;
+
+static void
+sigusr1(int n __unused)
+{
+       debug++;
+}
+
+static void
+sigusr2(int n __unused)
+{
+       debug--;
+}
+
+static void
+sighup(int n __unused)
+{
+       readconf++;
+}
+
+static void
+sigdone(int n __unused)
+{
+       done++;
+}
+
+static __dead void
+usage(int c)
+{
+       if (c != '?')
+               warnx("Unknown option `%c'", (char)c);
+       fprintf(stderr, "Usage: %s [-vdfr] [-c <config>] [-R <rulename>] "
+           "[-P <sockpathsfile>] [-C <controlprog>] [-D <dbfile>] "
+           "[-s <sockpath>] [-t <timeout>]\n", getprogname());
+       exit(EXIT_FAILURE);
+}
+
+static int
+getremoteaddress(bl_info_t *bi, struct sockaddr_storage *rss, socklen_t *rsl)
+{
+       *rsl = sizeof(*rss);
+       memset(rss, 0, *rsl);
+
+       if (getpeername(bi->bi_fd, (void *)rss, rsl) != -1)
+               return 0;
+
+       if (errno != ENOTCONN) {
+               (*lfun)(LOG_ERR, "getpeername failed (%m)");
+               return -1;
+       }
+
+       if (bi->bi_slen == 0) {
+               (*lfun)(LOG_ERR, "unconnected socket with no peer in message");
+               return -1;
+       }
+
+       switch (bi->bi_ss.ss_family) {
+       case AF_INET:
+               *rsl = sizeof(struct sockaddr_in);
+               break;
+       case AF_INET6:
+               *rsl = sizeof(struct sockaddr_in6);
+               break;
+       default:
+               (*lfun)(LOG_ERR, "bad client passed socket family %u",
+                   (unsigned)bi->bi_ss.ss_family);
+               return -1;
+       }
+
+       if (*rsl != bi->bi_slen) {
+               (*lfun)(LOG_ERR, "bad client passed socket length %u != %u",
+                   (unsigned)*rsl, (unsigned)bi->bi_slen);
+               return -1;
+       }
+
+       memcpy(rss, &bi->bi_ss, *rsl);
+
+#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
+       if (*rsl != rss->ss_len) {
+               (*lfun)(LOG_ERR,
+                   "bad client passed socket internal length %u != %u",
+                   (unsigned)*rsl, (unsigned)rss->ss_len);
+               return -1;
+       }
+#endif
+       return 0;
+}
+
+static void
+process(bl_t bl)
+{
+       struct sockaddr_storage rss;
+       socklen_t rsl;
+       char rbuf[BUFSIZ];
+       bl_info_t *bi;
+       struct conf c;
+       struct dbinfo dbi;
+       struct timespec ts;
+
+       memset(&dbi, 0, sizeof(dbi));
+       memset(&c, 0, sizeof(c));
+       if (clock_gettime(CLOCK_REALTIME, &ts) == -1) {
+               (*lfun)(LOG_ERR, "clock_gettime failed (%m)");
+               return;
+       }
+
+       if ((bi = bl_recv(bl)) == NULL) {
+               (*lfun)(LOG_ERR, "no message (%m)");
+               return;
+       }
+
+       if (getremoteaddress(bi, &rss, &rsl) == -1)
+               goto out;
+
+       if (debug || bi->bi_msg[0]) {
+               sockaddr_snprintf(rbuf, sizeof(rbuf), "%a:%p", (void *)&rss);
+               (*lfun)(bi->bi_msg[0] ? LOG_INFO : LOG_DEBUG,
+                   "processing type=%d fd=%d remote=%s msg=%s uid=%lu gid=%lu",
+                   bi->bi_type, bi->bi_fd, rbuf,
+                   bi->bi_msg, (unsigned long)bi->bi_uid,
+                   (unsigned long)bi->bi_gid);
+       }
+
+       if (conf_find(bi->bi_fd, bi->bi_uid, &rss, &c) == NULL) {
+               (*lfun)(LOG_DEBUG, "no rule matched");
+               goto out;
+       }
+
+
+       if (state_get(state, &c, &dbi) == -1)
+               goto out;
+
+       if (debug) {
+               char b1[128], b2[128];
+               (*lfun)(LOG_DEBUG, "%s: initial db state for %s: count=%d/%d "
+                   "last=%s now=%s", __func__, rbuf, dbi.count, c.c_nfail,
+                   fmttime(b1, sizeof(b1), dbi.last),
+                   fmttime(b2, sizeof(b2), ts.tv_sec));
+       }
+
+       switch (bi->bi_type) {
+       case BL_ABUSE:
+               /*
+                * If the application has signaled abusive behavior,
+                * set the number of fails to be one less than the
+                * configured limit.  Fallthrough to the normal BL_ADD
+                * processing, which will increment the failure count
+                * to the threshhold, and block the abusive address.
+                */
+               if (c.c_nfail != -1)
+                       dbi.count = c.c_nfail - 1;
+               /*FALLTHROUGH*/
+       case BL_ADD:
+               dbi.count++;
+               dbi.last = ts.tv_sec;
+               if (c.c_nfail != -1 && dbi.count >= c.c_nfail) {
+                       /*
+                        * No point in re-adding the rule.
+                        * It might exist already due to latency in processing
+                        * and removing the rule is the wrong thing to do as
+                        * it allows a window to attack again.
+                        */
+                       if (dbi.id[0] == '\0') {
+                               int res = run_change("add", &c,
+                                   dbi.id, sizeof(dbi.id));
+                               if (res == -1)
+                                       goto out;
+                       }
+                       sockaddr_snprintf(rbuf, sizeof(rbuf), "%a",
+                           (void *)&rss);
+                       (*lfun)(LOG_INFO,
+                           "blocked %s/%d:%d for %d seconds",
+                           rbuf, c.c_lmask, c.c_port, c.c_duration);
+               }
+               break;
+       case BL_DELETE:
+               if (dbi.last == 0)
+                       goto out;
+               dbi.count = 0;
+               dbi.last = 0;
+               break;
+       case BL_BADUSER:
+               /* ignore for now */
+               break;
+       default:
+               (*lfun)(LOG_ERR, "unknown message %d", bi->bi_type);
+       }
+       state_put(state, &c, &dbi);
+
+out:
+       close(bi->bi_fd);
+
+       if (debug) {
+               char b1[128], b2[128];
+               (*lfun)(LOG_DEBUG, "%s: final db state for %s: count=%d/%d "
+                   "last=%s now=%s", __func__, rbuf, dbi.count, c.c_nfail,
+                   fmttime(b1, sizeof(b1), dbi.last),
+                   fmttime(b2, sizeof(b2), ts.tv_sec));
+       }
+}
+
+static void
+update_interfaces(void)
+{
+       struct ifaddrs *oifas, *nifas;
+
+       if (getifaddrs(&nifas) == -1)
+               return;
+
+       oifas = ifas;
+       ifas = nifas;
+
+       if (oifas)
+               freeifaddrs(oifas);
+}
+
+static void
+update(void)
+{
+       struct timespec ts;
+       struct conf c;
+       struct dbinfo dbi;
+       unsigned int f, n;
+       char buf[128];
+       void *ss = &c.c_ss;
+
+       if (clock_gettime(CLOCK_REALTIME, &ts) == -1) {
+               (*lfun)(LOG_ERR, "clock_gettime failed (%m)");
+               return;
+       }
+
+again:
+       for (n = 0, f = 1; state_iterate(state, &c, &dbi, f) == 1;
+           f = 0, n++)
+       {
+               time_t when = c.c_duration + dbi.last;
+               if (debug > 1) {
+                       char b1[64], b2[64];
+                       sockaddr_snprintf(buf, sizeof(buf), "%a:%p", ss);
+                       (*lfun)(LOG_DEBUG, "%s:[%u] %s count=%d duration=%d "
+                           "last=%s " "now=%s", __func__, n, buf, dbi.count,
+                           c.c_duration, fmttime(b1, sizeof(b1), dbi.last),
+                           fmttime(b2, sizeof(b2), ts.tv_sec));
+               }
+               if (c.c_duration == -1 || when >= ts.tv_sec)
+                       continue;
+               if (dbi.id[0]) {
+                       run_change("rem", &c, dbi.id, 0);
+                       sockaddr_snprintf(buf, sizeof(buf), "%a", ss);
+                       (*lfun)(LOG_INFO, "released %s/%d:%d after %d seconds",
+                           buf, c.c_lmask, c.c_port, c.c_duration);
+               }
+               state_del(state, &c);
+               goto again;
+       }
+}
+
+static void
+addfd(struct pollfd **pfdp, bl_t **blp, size_t *nfd, size_t *maxfd,
+    const char *path)
+{
+       bl_t bl = bl_create(true, path, vflag ? vdlog : vsyslog_r);
+       if (bl == NULL || !bl_isconnected(bl))
+               exit(EXIT_FAILURE);
+       if (*nfd >= *maxfd) {
+               *maxfd += 10;
+               *blp = realloc(*blp, sizeof(**blp) * *maxfd);
+               if (*blp == NULL)
+                       err(EXIT_FAILURE, "malloc");
+               *pfdp = realloc(*pfdp, sizeof(**pfdp) * *maxfd);
+               if (*pfdp == NULL)
+                       err(EXIT_FAILURE, "malloc");
+       }
+
+       (*pfdp)[*nfd].fd = bl_getfd(bl);
+       (*pfdp)[*nfd].events = POLLIN;
+       (*blp)[*nfd] = bl;
+       *nfd += 1;
+}
+
+static void
+uniqueadd(struct conf ***listp, size_t *nlist, size_t *mlist, struct conf *c)
+{
+       struct conf **list = *listp;
+
+       if (c->c_name[0] == '\0')
+               return;
+       for (size_t i = 0; i < *nlist; i++) {
+               if (strcmp(list[i]->c_name, c->c_name) == 0)
+                       return;
+       }
+       if (*nlist == *mlist) {
+               *mlist += 10;
+               void *p = realloc(*listp, *mlist * sizeof(*list));
+               if (p == NULL)
+                       err(EXIT_FAILURE, "Can't allocate for rule list");
+               list = *listp = p;
+       }
+       list[(*nlist)++] = c;
+}
+
+static void
+rules_flush(void)
+{
+       struct conf **list;
+       size_t nlist, mlist;
+
+       list = NULL;
+       mlist = nlist = 0;
+       for (size_t i = 0; i < rconf.cs_n; i++)
+               uniqueadd(&list, &nlist, &mlist, &rconf.cs_c[i]);
+       for (size_t i = 0; i < lconf.cs_n; i++)
+               uniqueadd(&list, &nlist, &mlist, &lconf.cs_c[i]);
+
+       for (size_t i = 0; i < nlist; i++)
+               run_flush(list[i]);
+       free(list);
+}
+
+static void
+rules_restore(void)
+{
+       DB *db;
+       struct conf c;
+       struct dbinfo dbi;
+       unsigned int f;
+
+       db = state_open(dbfile, O_RDONLY, 0);
+       if (db == NULL) {
+               (*lfun)(LOG_ERR, "Can't open `%s' to restore state (%m)",
+                       dbfile);
+               return;
+       }
+       for (f = 1; state_iterate(db, &c, &dbi, f) == 1; f = 0) {
+               if (dbi.id[0] == '\0')
+                       continue;
+               (void)run_change("add", &c, dbi.id, sizeof(dbi.id));
+               state_put(state, &c, &dbi);
+       }
+       state_close(db);
+       state_sync(state);
+}
+
+int
+main(int argc, char *argv[])
+{
+       int c, tout, flags, flush, restore, ret;
+       const char *spath, **blsock;
+       size_t nblsock, maxblsock;
+
+       setprogname(argv[0]);
+
+       spath = NULL;
+       blsock = NULL;
+       maxblsock = nblsock = 0;
+       flush = 0;
+       restore = 0;
+       tout = 0;
+       flags = O_RDWR|O_EXCL|O_CLOEXEC;
+       while ((c = getopt(argc, argv, "C:c:D:dfP:rR:s:t:v")) != -1) {
+               switch (c) {
+               case 'C':
+                       controlprog = optarg;
+                       break;
+               case 'c':
+                       configfile = optarg;
+                       break;
+               case 'D':
+                       dbfile = optarg;
+                       break;
+               case 'd':
+                       debug++;
+                       break;
+               case 'f':
+                       flush++;
+                       break;
+               case 'P':
+                       spath = optarg;
+                       break;
+               case 'R':
+                       rulename = optarg;
+                       break;
+               case 'r':
+                       restore++;
+                       break;
+               case 's':
+                       if (nblsock >= maxblsock) {
+                               maxblsock += 10;
+                               void *p = realloc(blsock,
+                                   sizeof(*blsock) * maxblsock);
+                               if (p == NULL)
+                                   err(EXIT_FAILURE,
+                                       "Can't allocate memory for %zu sockets",
+                                       maxblsock);
+                               blsock = p;
+                       }
+                       blsock[nblsock++] = optarg;
+                       break;
+               case 't':
+                       tout = atoi(optarg) * 1000;
+                       break;
+               case 'v':
+                       vflag++;
+                       break;
+               default:
+                       usage(c);
+               }
+       }
+
+       argc -= optind;
+       if (argc)
+               usage('?');
+
+       signal(SIGHUP, sighup);
+       signal(SIGINT, sigdone);
+       signal(SIGQUIT, sigdone);
+       signal(SIGTERM, sigdone);
+       signal(SIGUSR1, sigusr1);
+       signal(SIGUSR2, sigusr2);
+
+       openlog(getprogname(), LOG_PID, LOG_DAEMON);
+
+       if (debug) {
+               lfun = dlog;
+               if (tout == 0)
+                       tout = 5000;
+       } else {
+               if (tout == 0)
+                       tout = 15000;
+       }
+
+       update_interfaces();
+       conf_parse(configfile);
+       if (flush) {
+               rules_flush();
+               if (!restore)
+                       flags |= O_TRUNC;
+       }
+
+       struct pollfd *pfd = NULL;
+       bl_t *bl = NULL;
+       size_t nfd = 0;
+       size_t maxfd = 0;
+
+       for (size_t i = 0; i < nblsock; i++)
+               addfd(&pfd, &bl, &nfd, &maxfd, blsock[i]);
+       free(blsock);
+
+       if (spath) {
+               FILE *fp = fopen(spath, "r");
+               char *line;
+               if (fp == NULL)
+                       err(EXIT_FAILURE, "Can't open `%s'", spath);
+               for (; (line = fparseln(fp, NULL, NULL, NULL, 0)) != NULL;
+                   free(line))
+                       addfd(&pfd, &bl, &nfd, &maxfd, line);
+               fclose(fp);
+       }
+       if (nfd == 0)
+               addfd(&pfd, &bl, &nfd, &maxfd, _PATH_BLSOCK);
+
+       state = state_open(dbfile, flags, 0600);
+       if (state == NULL)
+               state = state_open(dbfile,  flags | O_CREAT, 0600);
+       if (state == NULL)
+               return EXIT_FAILURE;
+
+       if (restore) {
+               if (!flush)
+                       rules_flush();
+               rules_restore();
+       }
+
+       if (!debug) {
+               if (daemon(0, 0) == -1)
+                       err(EXIT_FAILURE, "daemon failed");
+               if (pidfile(NULL) == -1)
+                       err(EXIT_FAILURE, "Can't create pidfile");
+       }
+
+       for (size_t t = 0; !done; t++) {
+               if (readconf) {
+                       readconf = 0;
+                       conf_parse(configfile);
+               }
+               ret = poll(pfd, (nfds_t)nfd, tout);
+               if (debug)
+                       (*lfun)(LOG_DEBUG, "received %d from poll()", ret);
+               switch (ret) {
+               case -1:
+                       if (errno == EINTR)
+                               continue;
+                       (*lfun)(LOG_ERR, "poll (%m)");
+                       return EXIT_FAILURE;
+               case 0:
+                       state_sync(state);
+                       break;
+               default:
+                       for (size_t i = 0; i < nfd; i++)
+                               if (pfd[i].revents & POLLIN)
+                                       process(bl[i]);
+               }
+               if (t % 100 == 0)
+                       state_sync(state);
+               if (t % 10000 == 0)
+                       update_interfaces();
+               update();
+       }
+       state_close(state);
+       return 0;
+}
diff --git a/contrib/blocklist/bin/old_internal.c 
b/contrib/blocklist/bin/old_internal.c
new file mode 100644
index 000000000000..79093cc8b8ab
--- /dev/null
+++ b/contrib/blocklist/bin/old_internal.c
@@ -0,0 +1,50 @@
+/*     $NetBSD: internal.c,v 1.2 2025/02/11 17:48:30 christos Exp $    */
+
+/*-
+ * Copyright (c) 2015 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Christos Zoulas.
+ *
+ * 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.
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef HAVE_SYS_CDEFS_H
+#include <sys/cdefs.h>
+#endif
+__RCSID("$NetBSD: internal.c,v 1.2 2025/02/11 17:48:30 christos Exp $");
+
+#include <stdio.h>
+#include <syslog.h>
+#include "conf.h"
+#include "old_internal.h"
+
+int debug;
+const char *rulename = "blacklistd";
+const char *controlprog = _PATH_BLCONTROL;
+struct confset lconf, rconf;
+struct ifaddrs *ifas;
+void (*lfun)(int, const char *, ...) = syslog;
diff --git a/contrib/blocklist/bin/old_internal.h 
b/contrib/blocklist/bin/old_internal.h
new file mode 100644
index 000000000000..becee563e81d
--- /dev/null
+++ b/contrib/blocklist/bin/old_internal.h
@@ -0,0 +1,58 @@
+/*     $NetBSD: internal.h,v 1.1.1.1 2020/06/15 01:52:53 christos Exp $        
*/
+
+/*-
+ * Copyright (c) 2015 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Christos Zoulas.
+ *
+ * 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.
+ */
+#ifndef _OLD_INTERNAL_H
+#define _OLD_INTERNAL_H
+
+#ifndef _PATH_BLCONF
+#define        _PATH_BLCONF    "/etc/blacklistd.conf"
+#endif
+#ifndef _PATH_BLCONTROL
+#define        _PATH_BLCONTROL "/usr/libexec/blacklistd-helper"
+#endif
+#ifndef _PATH_BLSTATE
+/* We want the new name, the old one would be incompatible after 24932b6 */
+#define        _PATH_BLSTATE   "/var/db/blocklistd.db"
+#endif
+
+extern struct confset rconf, lconf;
+extern int debug;
+extern const char *rulename;
+extern const char *controlprog;
+extern struct ifaddrs *ifas;
+
+#if !defined(__syslog_attribute__) && !defined(__syslog__)
+#define __syslog__ __printf__
+#endif
+
+extern void (*lfun)(int, const char *, ...)
+    __attribute__((__format__(__syslog__, 2, 3)));
+
*** 2507 LINES SKIPPED ***

Reply via email to