--- /dev/null
+/* tables.c is Copyright (c) 2014 Dohnuts All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 dated June, 1991, or
+ (at your option) version 3 dated 29 June, 2007.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "dnsmasq.h"
+
+#if defined(HAVE_IPSET) && defined(HAVE_BSD_NETWORK)
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+
+#include <net/if.h>
+#include <netinet/in.h>
+#include <net/pfvar.h>
+
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#define UNUSED(x) (void)(x)
+
+static char *pf_device = "/dev/pf";
+static int dev = -1;
+
+static char *pfr_strerror(int errnum)
+{
+ switch (errnum)
+ {
+ case ESRCH:
+ return "Table does not exist";
+ case ENOENT:
+ return "Anchor or Ruleset does not exist";
+ default:
+ return strerror(errnum);
+ }
+}
+
+static int pfr_add_tables(struct pfr_table *tbl, int size, int *nadd, int flags)
+{
+ struct pfioc_table io;
+
+ if (size < 0 || (size && tbl == NULL))
+ {
+ errno = EINVAL;
+ return (-1);
+ }
+ bzero(&io, sizeof io);
+ io.pfrio_flags = flags;
+ io.pfrio_buffer = tbl;
+ io.pfrio_esize = sizeof(*tbl);
+ io.pfrio_size = size;
+ if (ioctl(dev, DIOCRADDTABLES, &io))
+ return (-1);
+ if (nadd != NULL)
+ *nadd = io.pfrio_nadd;
+ return (0);
+}
+
+static int fill_addr(const struct all_addr *ipaddr, int flags, struct pfr_addr* addr) {
+ if ( !addr || !ipaddr)
+ {
+ my_syslog(LOG_ERR, _("error: fill_addr missused"));
+ return -1;
+ }
+ bzero(addr, sizeof(*addr));
+#ifdef HAVE_IPV6
+ if (flags & F_IPV6)
+ {
+ addr->pfra_af = AF_INET6;
+ addr->pfra_net = 0x80;
+ memcpy(&(addr->pfra_ip6addr), &(ipaddr->addr), sizeof(struct in6_addr));
+ }
+ else
+#endif
+ {
+ addr->pfra_af = AF_INET;
+ addr->pfra_net = 0x20;
+ addr->pfra_ip4addr.s_addr = ipaddr->addr.addr4.s_addr;
+ }
+ return 1;
+}
+
+/*****************************************************************************/
+
+void ipset_init(void)
+{
+ dev = open( pf_device, O_RDWR);
+ if (dev == -1)
+ {
+ err(1, "%s", pf_device);
+ die (_("failed to access pf devices: %s"), NULL, EC_MISC);
+ }
+}
+
+int add_to_ipset(const char *setname, const struct all_addr *ipaddr,
+ int flags, int remove)
+{
+ struct pfr_addr addr;
+ struct pfioc_table io;
+ struct pfr_table table;
+ int n = 0, rc = 0;
+
+ if ( dev == -1 )
+ {
+ my_syslog(LOG_ERR, _("warning: no opened pf devices %s"), pf_device);
+ return -1;
+ }
+
+ bzero(&table, sizeof(struct pfr_table));
+ table.pfrt_flags |= PFR_TFLAG_PERSIST;
+ if ( strlen(setname) >= PF_TABLE_NAME_SIZE )
+ {
+ my_syslog(LOG_ERR, _("error: cannot use table name %s"), setname);
+ errno = ENAMETOOLONG;
+ return -1;
+ }
+
+ if ( strlcpy(table.pfrt_name, setname,
+ sizeof(table.pfrt_name)) >= sizeof(table.pfrt_name))
+ {
+ my_syslog(LOG_ERR, _("error: cannot strlcpy table name %s"), setname);
+ return -1;
+ }
+
+ if (rc = pfr_add_tables(&table, 1, &n, 0))
+ {
+ my_syslog(LOG_WARNING, _("warning: pfr_add_tables: %s(%d)"),
+ pfr_strerror(errno),rc);
+ return -1;
+ }
+ table.pfrt_flags &= ~PFR_TFLAG_PERSIST;
+ if (n)
+ my_syslog(LOG_INFO, _("info: table created"));
+
+ fill_addr(ipaddr,flags,&addr);
+ bzero(&io, sizeof(io));
+ io.pfrio_flags = 0;
+ io.pfrio_table = table;
+ io.pfrio_buffer = &addr;
+ io.pfrio_esize = sizeof(addr);
+ io.pfrio_size = 1;
+ if (ioctl(dev, ( remove ? DIOCRDELADDRS : DIOCRADDADDRS ), &io))
+ {
+ my_syslog(LOG_WARNING, _("warning: DIOCR%sADDRS: %s"), ( remove ? "DEL" : "ADD" ), pfr_strerror(errno));
+ return -1;
+ }
+
+ my_syslog(LOG_INFO, _("%d addresses %s"),
+ io.pfrio_nadd, ( remove ? "removed" : "added" ));
+
+ return io.pfrio_nadd;
+}
+
+
+#endif