diff options
author | Kozlov Dmitry <xeb@mail.ru> | 2013-08-28 17:42:10 +0400 |
---|---|---|
committer | Kozlov Dmitry <xeb@mail.ru> | 2013-08-28 17:44:29 +0400 |
commit | 0614a5ed9e54982604f4c1b4a44617625312e5fd (patch) | |
tree | bcccfb25e5e42f49b83387f6e3ffa036864fac54 /accel-pppd/libnetlink | |
parent | b4962f813ecbbed302acee7496fb4f6c27cc39b5 (diff) | |
download | accel-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.c | 149 | ||||
-rw-r--r-- | accel-pppd/libnetlink/ipset.h | 9 |
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 + |