/* tables.c is Copyright (c) 2014 Sven Falempin All Rights Reserved. Author's email: sfalempin@citypassenger.com 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 . */ #include "dnsmasq.h" #if defined(HAVE_IPSET) && defined(HAVE_BSD_NETWORK) #include #include #include #include #include #include #include #include #include #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); } } 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 union all_addr *ipaddr, int flags, int remove) { struct pfr_addr addr; struct pfioc_table io; struct pfr_table table; 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; } bzero(&io, sizeof io); io.pfrio_flags = 0; io.pfrio_buffer = &table; io.pfrio_esize = sizeof(table); io.pfrio_size = 1; if (ioctl(dev, DIOCRADDTABLES, &io)) { my_syslog(LOG_WARNING, _("IPset: error: %s"), pfr_strerror(errno)); return -1; } table.pfrt_flags &= ~PFR_TFLAG_PERSIST; if (io.pfrio_nadd) my_syslog(LOG_INFO, _("info: table created")); bzero(&addr, sizeof(addr)); if (flags & F_IPV6) { addr.pfra_af = AF_INET6; addr.pfra_net = 0x80; memcpy(&(addr.pfra_ip6addr), ipaddr, sizeof(struct in6_addr)); } else { addr.pfra_af = AF_INET; addr.pfra_net = 0x20; addr.pfra_ip4addr.s_addr = ipaddr->addr4.s_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