/* Copyright 2004 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
 *
 * 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; either version 2 of the License, or      
 * (at your option) any later version.                                    
 *                                                                         
 * 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, write to the Free Software            
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */


#include <stdio.h>			/* *printf */
#include <string.h>			/* mem* */

#include "ipset.h"

#include <linux/netfilter_ipv4/ip_set_webcategory.h>

static const char* webcategory_type[] = {
"None", "Advertisement-And-Pop-Ups", "Alcohol-And-Tobacco", "Anonymizers", "Arts", //0~4
"Business", "Transportation", "Chat", "Forums-And-Newsgroups", "Compromised", //5~9
"Compromised", "Computers-And-Technology", "Criminal-And-Activity", "Dating-And-Personals", "Down-sites", //10~14
"Education", "Entertainment", "Finance", "Gambling", "Games", //15~19
"Government", "Hate-And-Intolerance", "Health-And-Medicine", "Illegal-Drug", "Job-Search", //20~24
"", "Streaming-Media-And-Downloads", "News", "Non-profits-And-NGOs", "Nudity", //25~29
"Personal-Sites", "Phishing-And-Fraud", "Politics", "Pornography-And-Sexually-explicit", "Real-Estate", //30~34
"Religion", "Restaurants-And-Dining", "Search-engines-And-Portals", "Shopping", "Social-Networking", //35~39
"Spam-sites", "Sports", "Malware", "", "Translators", //40~44
"Travel", "Violence", "Weapons", "Web-Based-Email", "General", //45~49
"Leisure-And-Recreation", "", "", "", "", //50~54
"", "", "", "", "", //55~59
"", "Botnets", "Cults", "Fashion-And-Beauty", "Greeting-Cards", //60~64
"Hacking", "", "Illegal-Softwares", "Image-Sharing", "Information-Security", //65~69
"Instant-Messaging", "Network-Errors", "Parked-Domains", "Peer-to-Peer", "Private-IP-Address", //70~74
"School-Cheating", "Sex-Education", "Tasteless", "Child-Abuse-Images", "Uncategorised-Sites"}; //75~79

/* Initialize the create. */
static void
webcategory_create_init(void *data UNUSED)
{
	struct ip_set_req_webcategory_create *mydata = data;
	
	DP("create INIT");

	mydata->from = WEBCATEGORY_FROM;
	mydata->to = WEBCATEGORY_TO;
	
	/* Nothing */
}

/* Function which parses command options; returns true if it ate an option */
static int
webcategory_create_parse(int c, char *argv[] UNUSED, void *data, unsigned *flags)
{
	DP("create_parse");	
	return 1;
}

/* Final check; exit if not ok. */
static void
webcategory_create_final(void *data, unsigned int flags)
{
	return;
}

/* Create commandline options */
static const struct option create_opts[] = {
	{NULL},
};

/* Add, del, test parser */
static ip_set_ip_t
webcategory_adt_parser(int cmd UNUSED, const char *arg, void *data)
{
	struct ip_set_req_webcategory *mydata = data;

	DP("%s", arg);

	if (strings_to_index(webcategory_type, WEBCATEGORY_NUM, arg, &mydata->ip) != 0)
	{
		exit_error(PARAMETER_PROBLEM, 
		           "Invalid protcol `%s' specified", arg);
		return 0;
	}
	return 1;	
}

/*
 * Print and save
 */

static void
webcategory_initheader(struct set *set, const void *data)
{
	const struct ip_set_req_webcategory_create *header = data;
	struct ip_set_webcategory *map = set->settype->header;

	memset(map, 0, sizeof(struct ip_set_webcategory));
	map->first_ip = header->from;
	map->last_ip = header->to;
}

static void
webcategory_printheader(struct set *set, unsigned options)
{

	printf("%s %s\n", 
	       set->name,
	       set->settype->typename);

}

static inline void
__webcategory_printips_sorted(struct set *set, void *data,
			  u_int32_t len UNUSED, unsigned options)
{
	struct ip_set_webcategory *mysetdata = set->settype->header;
	ip_set_ip_t addr = mysetdata->first_ip;

	DP("%u -- %u", mysetdata->first_ip, mysetdata->last_ip);
	while (addr <= mysetdata->last_ip) {
		if (test_bit(addr - mysetdata->first_ip, data))
			printf("%s\n", webcategory_type[addr]);
		addr++;
	}
}

static void
webcategory_printips_sorted(struct set *set, void *data,
			u_int32_t len, unsigned options,
			char dont_align)
{
	ip_set_ip_t *ip;
	size_t offset = 0;
	
	if (dont_align)
		return __webcategory_printips_sorted(set, data, len, options);
	
	while (offset < len) {
		ip = data + offset;
		printf("%s\n", webcategory_type[*ip]);
		offset += IPSET_ALIGN(sizeof(ip_set_ip_t));
	}
}

static void
webcategory_saveheader(struct set *set, unsigned options)
{

	printf("-N %s %s\n", 
	       set->name,
	       set->settype->typename);
}

static inline void
__webcategory_saveips(struct set *set, void *data,
		  u_int32_t len UNUSED, unsigned options)
{
	struct ip_set_webcategory *mysetdata = set->settype->header;
	ip_set_ip_t addr = mysetdata->first_ip;

	while (addr <= mysetdata->last_ip) {
		DP("addr: %lu, last_ip %lu", (long unsigned)addr, (long unsigned)mysetdata->last_ip);
		if (test_bit(addr - mysetdata->first_ip, data))
			printf("-A %s %s\n",
			       set->name,
			       webcategory_type[addr]);
		addr++;
	}
}

static void
webcategory_saveips(struct set *set, void *data,
		u_int32_t len, unsigned options,
		char dont_align)
{
	ip_set_ip_t *ip;
	size_t offset = 0;
	
	if (dont_align)
		return __webcategory_saveips(set, data, len, options);
	
	while (offset < len) {
		ip = data + offset;
		printf("-A %s %s\n", set->name, port_tostring(*ip, options));
		offset += IPSET_ALIGN(sizeof(ip_set_ip_t));
	}
}

static void
webcategory_usage(void)
{
	printf
	    ("-N set webcategory\n");
	strings_print(webcategory_type, WEBCATEGORY_NUM, "-ADT %s\n");
}

static struct settype settype_webcategory = {
	.typename = SETTYPE_NAME,
	.protocol_version = IP_SET_PROTOCOL_VERSION,

	/* Create */
	.create_size = sizeof(struct ip_set_req_webcategory_create),
	.create_init = webcategory_create_init,
	.create_parse = webcategory_create_parse,
	.create_final = webcategory_create_final,
	.create_opts = create_opts,

	/* Add/del/test */
	.adt_size = sizeof(struct ip_set_req_webcategory),
	.adt_parser = webcategory_adt_parser,

	/* Printing */
	.header_size = sizeof(struct ip_set_webcategory),
	.initheader = webcategory_initheader,
	.printheader = webcategory_printheader,
	.printips = webcategory_printips_sorted,
	.printips_sorted = webcategory_printips_sorted,
	.saveheader = webcategory_saveheader,
	.saveips = webcategory_saveips,
	
	.usage = webcategory_usage,
};

CONSTRUCTOR(webcategory)
{
	settype_register(&settype_webcategory);

}
