blob: ccfe9ed0419a3f86017c0fb07c14caa1f467a11a [file] [log] [blame]
Simon Kelley4b34f5d2014-06-07 20:05:08 +01001/* tables.c is Copyright (c) 2014 Sven Falempin All Rights Reserved.
Simon Kelleyc4a09372014-06-02 20:30:07 +01002
Simon Kelley6799a462014-06-07 21:23:34 +01003 Author's email: sfalempin@citypassenger.com
4
Simon Kelleyc4a09372014-06-02 20:30:07 +01005 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; version 2 dated June, 1991, or
8 (at your option) version 3 dated 29 June, 2007.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17*/
18
19#include "dnsmasq.h"
20
21#if defined(HAVE_IPSET) && defined(HAVE_BSD_NETWORK)
22
Simon Kelley8d8a54e2015-02-01 21:48:46 +000023#include <string.h>
Simon Kelley6ac3bc02014-10-03 08:48:11 +010024
Simon Kelleyc4a09372014-06-02 20:30:07 +010025#include <sys/types.h>
26#include <sys/ioctl.h>
27
28#include <net/if.h>
29#include <netinet/in.h>
30#include <net/pfvar.h>
31
32#include <err.h>
33#include <errno.h>
34#include <fcntl.h>
35
36#define UNUSED(x) (void)(x)
37
38static char *pf_device = "/dev/pf";
39static int dev = -1;
40
41static char *pfr_strerror(int errnum)
42{
43 switch (errnum)
44 {
45 case ESRCH:
46 return "Table does not exist";
47 case ENOENT:
48 return "Anchor or Ruleset does not exist";
49 default:
50 return strerror(errnum);
51 }
52}
53
Simon Kelleyc4a09372014-06-02 20:30:07 +010054
55void ipset_init(void)
56{
57 dev = open( pf_device, O_RDWR);
58 if (dev == -1)
59 {
60 err(1, "%s", pf_device);
61 die (_("failed to access pf devices: %s"), NULL, EC_MISC);
62 }
63}
64
Simon Kelleycc921df2019-01-02 22:48:59 +000065int add_to_ipset(const char *setname, const union all_addr *ipaddr,
Simon Kelley396750c2016-08-13 22:34:11 +010066 int flags, int remove)
Simon Kelleyc4a09372014-06-02 20:30:07 +010067{
68 struct pfr_addr addr;
69 struct pfioc_table io;
70 struct pfr_table table;
Simon Kelleyc4a09372014-06-02 20:30:07 +010071
Simon Kelley396750c2016-08-13 22:34:11 +010072 if (dev == -1)
Simon Kelleyc4a09372014-06-02 20:30:07 +010073 {
74 my_syslog(LOG_ERR, _("warning: no opened pf devices %s"), pf_device);
75 return -1;
76 }
77
78 bzero(&table, sizeof(struct pfr_table));
79 table.pfrt_flags |= PFR_TFLAG_PERSIST;
Simon Kelley396750c2016-08-13 22:34:11 +010080 if (strlen(setname) >= PF_TABLE_NAME_SIZE)
Simon Kelleyc4a09372014-06-02 20:30:07 +010081 {
82 my_syslog(LOG_ERR, _("error: cannot use table name %s"), setname);
83 errno = ENAMETOOLONG;
84 return -1;
85 }
86
Simon Kelley396750c2016-08-13 22:34:11 +010087 if (strlcpy(table.pfrt_name, setname,
88 sizeof(table.pfrt_name)) >= sizeof(table.pfrt_name))
Simon Kelleyc4a09372014-06-02 20:30:07 +010089 {
90 my_syslog(LOG_ERR, _("error: cannot strlcpy table name %s"), setname);
91 return -1;
92 }
93
Simon Kelley396750c2016-08-13 22:34:11 +010094 bzero(&io, sizeof io);
95 io.pfrio_flags = 0;
96 io.pfrio_buffer = &table;
97 io.pfrio_esize = sizeof(table);
98 io.pfrio_size = 1;
99 if (ioctl(dev, DIOCRADDTABLES, &io))
Simon Kelleyc4a09372014-06-02 20:30:07 +0100100 {
Matthias Andreeb5d1b202021-03-28 00:58:54 +0000101 my_syslog(LOG_WARNING, _("IPset: error: %s"), pfr_strerror(errno));
Simon Kelley396750c2016-08-13 22:34:11 +0100102
Simon Kelleyc4a09372014-06-02 20:30:07 +0100103 return -1;
104 }
Simon Kelleyc4a09372014-06-02 20:30:07 +0100105
Simon Kelley396750c2016-08-13 22:34:11 +0100106 table.pfrt_flags &= ~PFR_TFLAG_PERSIST;
107 if (io.pfrio_nadd)
108 my_syslog(LOG_INFO, _("info: table created"));
109
110 bzero(&addr, sizeof(addr));
Simon Kelleyee875042018-10-23 22:10:17 +0100111
Simon Kelley396750c2016-08-13 22:34:11 +0100112 if (flags & F_IPV6)
113 {
114 addr.pfra_af = AF_INET6;
115 addr.pfra_net = 0x80;
Simon Kelleycc921df2019-01-02 22:48:59 +0000116 memcpy(&(addr.pfra_ip6addr), ipaddr, sizeof(struct in6_addr));
Simon Kelley396750c2016-08-13 22:34:11 +0100117 }
118 else
Simon Kelley396750c2016-08-13 22:34:11 +0100119 {
120 addr.pfra_af = AF_INET;
121 addr.pfra_net = 0x20;
Simon Kelleycc921df2019-01-02 22:48:59 +0000122 addr.pfra_ip4addr.s_addr = ipaddr->addr4.s_addr;
Simon Kelley396750c2016-08-13 22:34:11 +0100123 }
124
Simon Kelleyc4a09372014-06-02 20:30:07 +0100125 bzero(&io, sizeof(io));
126 io.pfrio_flags = 0;
127 io.pfrio_table = table;
128 io.pfrio_buffer = &addr;
129 io.pfrio_esize = sizeof(addr);
130 io.pfrio_size = 1;
131 if (ioctl(dev, ( remove ? DIOCRDELADDRS : DIOCRADDADDRS ), &io))
132 {
133 my_syslog(LOG_WARNING, _("warning: DIOCR%sADDRS: %s"), ( remove ? "DEL" : "ADD" ), pfr_strerror(errno));
134 return -1;
135 }
136
137 my_syslog(LOG_INFO, _("%d addresses %s"),
138 io.pfrio_nadd, ( remove ? "removed" : "added" ));
139
140 return io.pfrio_nadd;
141}
142
143
144#endif