#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/fcntl.h>
#include <net/if.h>
#include <netinet/in.h>
#include <net/pfvar.h>
#include <err.h>
#include <stdio.h>
#include <stdlib.h>

struct pfr_buffer {
	int	 pfrb_type;	/* type of content, see enum above */
	int	 pfrb_size;	/* number of objects in buffer */
	int	 pfrb_msize;	/* maximum number of objects in buffer */
	void	*pfrb_caddr;	/* malloc'ated memory area */
};

#define RVTEST(fct) do {				\
		if ((!(opts & PF_OPT_NOACTION) ||	\
		    (opts & PF_OPT_DUMMYACTION)) &&	\
		    (fct)) {				\
			radix_perror();			\
			goto _error;			\
		}					\
	} while (0)

#define CREATE_TABLE do {						\
		table.pfrt_flags |= PFR_TFLAG_PERSIST;			\
		if ((!(opts & PF_OPT_NOACTION) ||			\
		    (opts & PF_OPT_DUMMYACTION)) &&			\
		    (pfr_add_tables(&table, 1, &nadd, flags)) &&	\
		    (errno != EPERM)) {					\
			radix_perror();					\
			goto _error;					\
		}							\
		if (nadd) {						\
			warn_namespace_collision(table.pfrt_name);	\
			xprintf(opts, "%d table created", nadd);	\
			if (opts & PF_OPT_NOACTION)			\
				return (0);				\
		}							\
		table.pfrt_flags &= ~PFR_TFLAG_PERSIST;			\
	} while(0)

int main(int argc, char *argv[]) {
  int dev, ret;
  struct pfioc_table io;
  struct pfr_table   table;
  struct pfr_addr    addr;
  struct pfr_buffer  b2;
  int a, b, c, d;


  if (argc != 2) {
    printf("%s <addr>\n", argv[0]);
    return 1;
  }

  bzero(&b2, sizeof(b2));
  bzero(&table, sizeof(table));

  strncpy(table.pfrt_name, "cleared", MAXPATHLEN);

  /* manpage says:

     DIOCRADDADDRS struct pfioc_table *io
             Add one or more addresses to a table.  On entry, pfrio_table con-
             tains the table ID and pfrio_buffer must point to an array of
             struct pfr_addr containing at least pfrio_size elements to add to
             the table.  pfrio_esize must be the size of struct pfr_addr.  On
             exit, pfrio_nadd contains the number of addresses effectively
             added.

             struct pfr_addr {
                     union {
                             struct in_addr   _pfra_ip4addr;
                             struct in6_addr  _pfra_ip6addr;
                     }                pfra_u;
                     u_int8_t         pfra_af;
                     u_int8_t         pfra_net;
                     u_int8_t         pfra_not;
                     u_int8_t         pfra_fback;
             };
             #define pfra_ip4addr    pfra_u._pfra_ip4addr
             #define pfra_ip6addr    pfra_u._pfra_ip6addr

   */
  dev = open("/dev/pf", O_RDWR);
  if (dev == -1)
    err(1, "open(\"/dev/pf\") failed");

  sscanf(argv[1], "%i.%i.%i.%i", &a, &b, &c, &d);
  addr.pfra_ip4addr.s_addr = htonl(a << 24 | b << 16 | c << 8 | d);

  bzero(&io, sizeof io);
  io.pfrio_flags = PFR_FLAG_FEEDBACK;
  io.pfrio_table = table;
  io.pfrio_buffer = &addr;
  io.pfrio_esize = sizeof(addr);
  io.pfrio_size = 1;
  if (ioctl(dev, DIOCRADDADDRS, &io))
    err(1, "DIOCRADDADDRS failed");
  return 0;
}
