dnsmasq: re-apply original Tomato specific code
[tomato.git] / release / src / router / dnsmasq / src / tables.c
blobaae1252708db689626f284b2051de7fa505fede0
1 /* tables.c is Copyright (c) 2014 Sven Falempin All Rights Reserved.
3 Author's email: sfalempin@citypassenger.com
5 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.
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.
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/>.
19 #include "dnsmasq.h"
21 #if defined(HAVE_IPSET) && defined(HAVE_BSD_NETWORK)
23 #ifndef __FreeBSD__
24 #include <string.h>
25 #endif
27 #include <sys/types.h>
28 #include <sys/ioctl.h>
30 #include <net/if.h>
31 #include <netinet/in.h>
32 #include <net/pfvar.h>
34 #include <err.h>
35 #include <errno.h>
36 #include <fcntl.h>
38 #define UNUSED(x) (void)(x)
40 static char *pf_device = "/dev/pf";
41 static int dev = -1;
43 static char *pfr_strerror(int errnum)
45 switch (errnum)
47 case ESRCH:
48 return "Table does not exist";
49 case ENOENT:
50 return "Anchor or Ruleset does not exist";
51 default:
52 return strerror(errnum);
56 static int pfr_add_tables(struct pfr_table *tbl, int size, int *nadd, int flags)
58 struct pfioc_table io;
60 if (size < 0 || (size && tbl == NULL))
62 errno = EINVAL;
63 return (-1);
65 bzero(&io, sizeof io);
66 io.pfrio_flags = flags;
67 io.pfrio_buffer = tbl;
68 io.pfrio_esize = sizeof(*tbl);
69 io.pfrio_size = size;
70 if (ioctl(dev, DIOCRADDTABLES, &io))
71 return (-1);
72 if (nadd != NULL)
73 *nadd = io.pfrio_nadd;
74 return (0);
77 static int fill_addr(const struct all_addr *ipaddr, int flags, struct pfr_addr* addr) {
78 if ( !addr || !ipaddr)
80 my_syslog(LOG_ERR, _("error: fill_addr missused"));
81 return -1;
83 bzero(addr, sizeof(*addr));
84 #ifdef HAVE_IPV6
85 if (flags & F_IPV6)
87 addr->pfra_af = AF_INET6;
88 addr->pfra_net = 0x80;
89 memcpy(&(addr->pfra_ip6addr), &(ipaddr->addr), sizeof(struct in6_addr));
91 else
92 #endif
94 addr->pfra_af = AF_INET;
95 addr->pfra_net = 0x20;
96 addr->pfra_ip4addr.s_addr = ipaddr->addr.addr4.s_addr;
98 return 1;
101 /*****************************************************************************/
103 void ipset_init(void)
105 dev = open( pf_device, O_RDWR);
106 if (dev == -1)
108 err(1, "%s", pf_device);
109 die (_("failed to access pf devices: %s"), NULL, EC_MISC);
113 int add_to_ipset(const char *setname, const struct all_addr *ipaddr,
114 int flags, int remove)
116 struct pfr_addr addr;
117 struct pfioc_table io;
118 struct pfr_table table;
119 int n = 0, rc = 0;
121 if ( dev == -1 )
123 my_syslog(LOG_ERR, _("warning: no opened pf devices %s"), pf_device);
124 return -1;
127 bzero(&table, sizeof(struct pfr_table));
128 table.pfrt_flags |= PFR_TFLAG_PERSIST;
129 if ( strlen(setname) >= PF_TABLE_NAME_SIZE )
131 my_syslog(LOG_ERR, _("error: cannot use table name %s"), setname);
132 errno = ENAMETOOLONG;
133 return -1;
136 if ( strlcpy(table.pfrt_name, setname,
137 sizeof(table.pfrt_name)) >= sizeof(table.pfrt_name))
139 my_syslog(LOG_ERR, _("error: cannot strlcpy table name %s"), setname);
140 return -1;
143 if ((rc = pfr_add_tables(&table, 1, &n, 0)))
145 my_syslog(LOG_WARNING, _("warning: pfr_add_tables: %s(%d)"),
146 pfr_strerror(errno),rc);
147 return -1;
149 table.pfrt_flags &= ~PFR_TFLAG_PERSIST;
150 if (n)
151 my_syslog(LOG_INFO, _("info: table created"));
153 fill_addr(ipaddr,flags,&addr);
154 bzero(&io, sizeof(io));
155 io.pfrio_flags = 0;
156 io.pfrio_table = table;
157 io.pfrio_buffer = &addr;
158 io.pfrio_esize = sizeof(addr);
159 io.pfrio_size = 1;
160 if (ioctl(dev, ( remove ? DIOCRDELADDRS : DIOCRADDADDRS ), &io))
162 my_syslog(LOG_WARNING, _("warning: DIOCR%sADDRS: %s"), ( remove ? "DEL" : "ADD" ), pfr_strerror(errno));
163 return -1;
166 my_syslog(LOG_INFO, _("%d addresses %s"),
167 io.pfrio_nadd, ( remove ? "removed" : "added" ));
169 return io.pfrio_nadd;
173 #endif