| /* 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 <http://www.gnu.org/licenses/>. |
| */ |
| |
| #include "dnsmasq.h" |
| |
| #if defined(HAVE_IPSET) && defined(HAVE_BSD_NETWORK) |
| |
| #include <string.h> |
| |
| #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); |
| } |
| } |
| |
| |
| 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 |