/* ipset.c is Copyright (c) 2013 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.

   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_LINUX_NETWORK)

#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <linux/netlink.h>
#include <linux/netfilter/ipset/ip_set.h>
#include <linux/netfilter/nfnetlink.h>

/* data structure size in here is fixed */
#define BUFF_SZ 256

static const struct sockaddr_nl snl = { .nl_family = AF_NETLINK };
static int ipset_sock, old_kernel;
static char *buffer;

static inline struct nlattr *add_attr(struct nlmsghdr *nlh, uint16_t type, size_t len, const void *data)
{
  struct nlattr *attr = (void *)nlh + NLA_ALIGN(nlh->nlmsg_len);
  uint16_t payload_len = NLA_ALIGN(sizeof(struct nlattr)) + len;
  attr->nla_type = type;
  attr->nla_len = payload_len;
  if (len > 0) {
    memcpy((void *)attr + NLA_ALIGN(sizeof(struct nlattr)), data, len);
  }
  nlh->nlmsg_len += NLA_ALIGN(payload_len);
  return attr;
}

void ipset_init(void)
{
  old_kernel = (daemon->kernel_version < KERNEL_VERSION(2,6,32));
  
  if (old_kernel && (ipset_sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) != -1)
    return;
  
  if (!old_kernel && 
      (buffer = safe_malloc(BUFF_SZ)) &&
      (ipset_sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_NETFILTER)) != -1 &&
      (bind(ipset_sock, (struct sockaddr *)&snl, sizeof(snl)) != -1))
    return;
  
  die (_("failed to create IPset control socket: %s"), NULL, EC_MISC);
}

/*
 *  <------- NLA_HDRLEN ------> <-- NLA_ALIGN(payload)-->
 * +---------------------+- - -+- - - - - - - - - -+- - -+
 * |        Header       | Pad |     Payload       | Pad |
 * |   (struct nlattr)   | ing |                   | ing |
 * +---------------------+- - -+- - - - - - - - - -+- - -+
 *  <-------------- nlattr->nla_len -------------->
 *
 * For nested attributes, nla_len of IPSET_ATTR_DATA nlattr
 * need to be updated appropriately after adding each attribute
 *
 * nla_type (16 bits)
 * +---+---+-------------------------------+
 * | N | O | Attribute Type                |
 * +---+---+-------------------------------+
 * N := Carries nested attributes
 * O := Payload stored in network byte order
 *
 * Note: The N and O flag are mutually exclusive.
 */

static int new_add_to_ipset(const char *setname, const union all_addr *ipaddr, int af, int remove)
{
  struct nlmsghdr *nlh;
  struct nfgenmsg *nfg;
  uint8_t proto;
  int addrsz = (af == AF_INET6) ? IN6ADDRSZ : INADDRSZ;
  struct nlattr *ipset_attr_data_ptr = NULL;
  struct nlattr *ipset_attr_ip_ptr = NULL;
  struct nlattr *ipset_attr_ip_addr_ptr = NULL;

  if (strlen(setname) >= IPSET_MAXNAMELEN) 
    {
      errno = ENAMETOOLONG;
      return -1;
    }
  
  memset(buffer, 0, BUFF_SZ);

  nlh = (struct nlmsghdr *)buffer;
  nlh->nlmsg_len = NLA_ALIGN(sizeof(struct nlmsghdr));
  nlh->nlmsg_type = (remove ? IPSET_CMD_DEL : IPSET_CMD_ADD) | (NFNL_SUBSYS_IPSET << 8);
  nlh->nlmsg_flags = NLM_F_REQUEST;
  
  nfg = (struct nfgenmsg *)(buffer + nlh->nlmsg_len);
  nlh->nlmsg_len += NLA_ALIGN(sizeof(struct nfgenmsg));
  nfg->nfgen_family = af;
  nfg->version = NFNETLINK_V0;
  nfg->res_id = htons(0);
  
  proto = IPSET_PROTOCOL;
  add_attr(nlh, IPSET_ATTR_PROTOCOL, sizeof(proto), &proto);
  add_attr(nlh, IPSET_ATTR_SETNAME, strlen(setname) + 1, setname);
  ipset_attr_data_ptr = add_attr(nlh, NLA_F_NESTED | IPSET_ATTR_DATA,  0, NULL);
  ipset_attr_ip_ptr = add_attr(nlh, NLA_F_NESTED | IPSET_ATTR_IP,  0, NULL);
  ipset_attr_data_ptr->nla_len += ipset_attr_ip_ptr->nla_len;
  ipset_attr_ip_addr_ptr = add_attr(nlh,
	   (af == AF_INET ? IPSET_ATTR_IPADDR_IPV4 : IPSET_ATTR_IPADDR_IPV6) | NLA_F_NET_BYTEORDER,
	   addrsz, ipaddr);
  ipset_attr_ip_ptr->nla_len += ipset_attr_ip_addr_ptr->nla_len;
  ipset_attr_data_ptr->nla_len += ipset_attr_ip_addr_ptr->nla_len;
	
  while (retry_send(sendto(ipset_sock, buffer, nlh->nlmsg_len, 0,
			   (struct sockaddr *)&snl, sizeof(snl))));
								    
  return errno == 0 ? 0 : -1;
}


static int old_add_to_ipset(const char *setname, const union all_addr *ipaddr, int remove)
{
  socklen_t size;
  struct ip_set_req_adt_get {
    unsigned op;
    unsigned version;
    union {
      char name[IPSET_MAXNAMELEN];
      uint16_t index;
    } set;
    char typename[IPSET_MAXNAMELEN];
  } req_adt_get;
  struct ip_set_req_adt {
    unsigned op;
    uint16_t index;
    uint32_t ip;
  } req_adt;
  
  if (strlen(setname) >= sizeof(req_adt_get.set.name)) 
    {
      errno = ENAMETOOLONG;
      return -1;
    }
  
  req_adt_get.op = 0x10;
  req_adt_get.version = 3;
  strcpy(req_adt_get.set.name, setname);
  size = sizeof(req_adt_get);
  if (getsockopt(ipset_sock, SOL_IP, 83, &req_adt_get, &size) < 0)
    return -1;
  req_adt.op = remove ? 0x102 : 0x101;
  req_adt.index = req_adt_get.set.index;
  req_adt.ip = ntohl(ipaddr->addr4.s_addr);
  if (setsockopt(ipset_sock, SOL_IP, 83, &req_adt, sizeof(req_adt)) < 0)
    return -1;
  
  return 0;
}



int add_to_ipset(const char *setname, const union all_addr *ipaddr, int flags, int remove)
{
  int ret = 0, af = AF_INET;

  if (flags & F_IPV6)
    {
      af = AF_INET6;
      /* old method only supports IPv4 */
      if (old_kernel)
	{
	  errno = EAFNOSUPPORT ;
	  ret = -1;
	}
    }
  
  if (ret != -1) 
    ret = old_kernel ? old_add_to_ipset(setname, ipaddr, remove) : new_add_to_ipset(setname, ipaddr, af, remove);

  if (ret == -1)
     my_syslog(LOG_ERR, _("failed to update ipset %s: %s"), setname, strerror(errno));

  return ret;
}

#endif
