summaryrefslogtreecommitdiff
path: root/accel-pppd/libnetlink
diff options
context:
space:
mode:
authorKozlov Dmitry <xeb@mail.ru>2013-08-28 17:42:10 +0400
committerKozlov Dmitry <xeb@mail.ru>2013-08-28 17:44:29 +0400
commit0614a5ed9e54982604f4c1b4a44617625312e5fd (patch)
treebcccfb25e5e42f49b83387f6e3ffa036864fac54 /accel-pppd/libnetlink
parentb4962f813ecbbed302acee7496fb4f6c27cc39b5 (diff)
downloadaccel-ppp-0614a5ed9e54982604f4c1b4a44617625312e5fd.tar.gz
accel-ppp-0614a5ed9e54982604f4c1b4a44617625312e5fd.zip
ipoe: add ipset support for l4 redirect
Diffstat (limited to 'accel-pppd/libnetlink')
-rw-r--r--accel-pppd/libnetlink/ipset.c149
-rw-r--r--accel-pppd/libnetlink/ipset.h9
2 files changed, 158 insertions, 0 deletions
diff --git a/accel-pppd/libnetlink/ipset.c b/accel-pppd/libnetlink/ipset.c
new file mode 100644
index 00000000..24f72a11
--- /dev/null
+++ b/accel-pppd/libnetlink/ipset.c
@@ -0,0 +1,149 @@
+#include "config.h"
+
+#ifdef HAVE_IPSET
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <syslog.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <net/if_arp.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <string.h>
+#include <errno.h>
+#include <time.h>
+#include <sys/uio.h>
+#include <linux/netfilter/nfnetlink.h>
+#include <linux/netfilter/ipset/ip_set.h>
+
+#include "triton.h"
+#include "log.h"
+
+#include "libnetlink.h"
+#include "ipset.h"
+
+#include "memdebug.h"
+
+static int __ipset_cmd(const char *name, in_addr_t addr, int cmd, int flags)
+{
+ struct rtnl_handle rth;
+ struct req {
+ struct nlmsghdr n;
+ struct nfgenmsg nf;
+ char buf[1024];
+ } req;
+ struct rtattr *tail1, *tail2;
+ uint8_t protocol = IPSET_PROTOCOL;
+
+ if (rtnl_open_byproto(&rth, 0, NETLINK_NETFILTER)) {
+ log_error("ipset: cannot open rtnetlink\n");
+ return -1;
+ }
+
+ memset(&req, 0, sizeof(req) - 1024);
+
+ req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct nfgenmsg));
+ req.n.nlmsg_flags = flags;
+ req.n.nlmsg_type = cmd | (NFNL_SUBSYS_IPSET << 8);
+ req.nf.nfgen_family = AF_INET;
+ req.nf.version = NFNETLINK_V0;
+ req.nf.res_id = 0;
+
+ addattr_l(&req.n, 1024, IPSET_ATTR_PROTOCOL, &protocol, 1);
+ addattr_l(&req.n, 1024, IPSET_ATTR_SETNAME, name, strlen(name) + 1);
+
+ tail1 = addattr_nest(&req.n, MAX_MSG, IPSET_ATTR_DATA | NLA_F_NESTED);
+
+ tail2 = addattr_nest(&req.n, MAX_MSG, IPSET_ATTR_IP | NLA_F_NESTED);
+ addattr32(&req.n, 1024, IPSET_ATTR_IPADDR_IPV4 | NLA_F_NET_BYTEORDER, addr);
+ addattr_nest_end(&req.n, tail2);
+
+ addattr_nest_end(&req.n, tail1);
+
+ if (rtnl_talk(&rth, &req.n, 0, 0, NULL, NULL, NULL, 0) < 0)
+ goto out_err;
+
+ rtnl_close(&rth);
+
+ return 0;
+
+out_err:
+ rtnl_close(&rth);
+
+ return -1;
+
+}
+
+int __export ipset_add(const char *name, in_addr_t addr)
+{
+ return __ipset_cmd(name, addr, IPSET_CMD_ADD, NLM_F_REQUEST | NLM_F_ACK | NLM_F_EXCL);
+}
+
+int __export ipset_del(const char *name, in_addr_t addr)
+{
+ return __ipset_cmd(name, addr, IPSET_CMD_DEL, NLM_F_REQUEST | NLM_F_ACK);
+}
+
+int __export ipset_flush(const char *name)
+{
+ struct rtnl_handle rth;
+ struct req {
+ struct nlmsghdr n;
+ struct nfgenmsg nf;
+ char buf[1024];
+ } req;
+ uint8_t protocol = IPSET_PROTOCOL;
+
+ if (rtnl_open_byproto(&rth, 0, NETLINK_NETFILTER)) {
+ log_error("ipset: cannot open rtnetlink\n");
+ return -1;
+ }
+
+ memset(&req, 0, sizeof(req) - 1024);
+
+ req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct nfgenmsg));
+ req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
+ req.n.nlmsg_type = IPSET_CMD_FLUSH | (NFNL_SUBSYS_IPSET << 8);
+ req.nf.nfgen_family = AF_INET;
+ req.nf.version = NFNETLINK_V0;
+ req.nf.res_id = 0;
+
+ addattr_l(&req.n, 1024, IPSET_ATTR_PROTOCOL, &protocol, 1);
+ addattr_l(&req.n, 1024, IPSET_ATTR_SETNAME, name, strlen(name) + 1);
+
+ if (rtnl_talk(&rth, &req.n, 0, 0, NULL, NULL, NULL, 0) < 0)
+ goto out_err;
+
+ rtnl_close(&rth);
+
+ return 0;
+
+out_err:
+ rtnl_close(&rth);
+
+ return -1;
+}
+
+#else
+
+#include <netinet/in.h>
+#include "triton.h"
+
+int __export ipset_add(const char *name, in_addr_t addr)
+{
+ return -1;
+}
+
+int __export ipset_del(const char *name, in_addr_t addr)
+{
+ return -1;
+}
+
+int __export ipset_flush(const char *name)
+{
+ return -1;
+}
+
+#endif
diff --git a/accel-pppd/libnetlink/ipset.h b/accel-pppd/libnetlink/ipset.h
new file mode 100644
index 00000000..cd5523dc
--- /dev/null
+++ b/accel-pppd/libnetlink/ipset.h
@@ -0,0 +1,9 @@
+#ifndef __IPSET_H
+#define __IPSET_H
+
+int ipset_add(const char *name, in_addr_t addr);
+int ipset_del(const char *name, in_addr_t addr);
+int ipset_flush(const char *name);
+
+#endif
+