Home | History | Annotate | Download | only in extensions
      1 #include <stdlib.h>
      2 #include <stdio.h>
      3 #include <string.h>
      4 #include <getopt.h>
      5 #include <iptables.h>
      6 
      7 #include <linux/netfilter_ipv4/ip_tables.h>
      8 #include <linux/netfilter/xt_NFLOG.h>
      9 
     10 enum {
     11 	NFLOG_GROUP	= 0x1,
     12 	NFLOG_PREFIX	= 0x2,
     13 	NFLOG_RANGE	= 0x4,
     14 	NFLOG_THRESHOLD	= 0x8,
     15 };
     16 
     17 static struct option opts[] = {
     18 	{ "nflog-group",     1, 0, NFLOG_GROUP },
     19 	{ "nflog-prefix",    1, 0, NFLOG_PREFIX },
     20 	{ "nflog-range",     1, 0, NFLOG_RANGE },
     21 	{ "nflog-threshold", 1, 0, NFLOG_THRESHOLD },
     22 };
     23 
     24 static void help(void)
     25 {
     26 	printf("NFLOG v%s options:\n"
     27 	       " --nflog-group NUM		NETLINK group used for logging\n"
     28 	       " --nflog-range NUM		Number of byte to copy\n"
     29 	       " --nflog-threshold NUM		Message threshold of in-kernel queue\n"
     30 	       " --nflog-prefix STRING		Prefix string for log messages\n\n",
     31 	       IPTABLES_VERSION);
     32 }
     33 
     34 static void init(struct xt_entry_target *t, unsigned int *nfcache)
     35 {
     36 	struct xt_nflog_info *info = (struct xt_nflog_info *)t->data;
     37 
     38 	info->group	= XT_NFLOG_DEFAULT_GROUP;
     39 	info->threshold	= XT_NFLOG_DEFAULT_THRESHOLD;
     40 }
     41 
     42 static int parse(int c, char **argv, int invert, unsigned int *flags,
     43 		 const struct ipt_entry *entry,
     44 		 struct xt_entry_target **target)
     45 {
     46 	struct xt_nflog_info *info = (struct xt_nflog_info *)(*target)->data;
     47 	int n;
     48 
     49 	switch (c) {
     50 	case NFLOG_GROUP:
     51 		if (*flags & NFLOG_GROUP)
     52 			exit_error(PARAMETER_PROBLEM,
     53 				   "Can't specify --nflog-group twice");
     54 		if (check_inverse(optarg, &invert, NULL, 0))
     55 			exit_error(PARAMETER_PROBLEM,
     56 				   "Unexpected `!' after --nflog-group");
     57 
     58 		n = atoi(optarg);
     59 		if (n < 1 || n > 32)
     60 			exit_error(PARAMETER_PROBLEM,
     61 				   "--nflog-group has to be between 1 and 32");
     62 		info->group = 1 << (n - 1);
     63 		break;
     64 	case NFLOG_PREFIX:
     65 		if (*flags & NFLOG_PREFIX)
     66 			exit_error(PARAMETER_PROBLEM,
     67 				   "Can't specify --nflog-prefix twice");
     68 		if (check_inverse(optarg, &invert, NULL, 0))
     69 			exit_error(PARAMETER_PROBLEM,
     70 				   "Unexpected `!' after --nflog-prefix");
     71 
     72 		n = strlen(optarg);
     73 		if (n == 0)
     74 			exit_error(PARAMETER_PROBLEM,
     75 				   "No prefix specified for --nflog-prefix");
     76 		if (n >= sizeof(info->prefix))
     77 			exit_error(PARAMETER_PROBLEM,
     78 				   "--nflog-prefix too long, max %Zu characters",
     79 				   sizeof(info->prefix) - 1);
     80 		if (n != strlen(strtok(optarg, "\n")))
     81 			exit_error(PARAMETER_PROBLEM,
     82 				   "Newlines are not allowed in --nflog-prefix");
     83 		strcpy(info->prefix, optarg);
     84 		break;
     85 	case NFLOG_RANGE:
     86 		if (*flags & NFLOG_RANGE)
     87 			exit_error(PARAMETER_PROBLEM,
     88 				   "Can't specify --nflog-range twice");
     89 		n = atoi(optarg);
     90 		if (n < 0)
     91 			exit_error(PARAMETER_PROBLEM,
     92 				   "Invalid --nflog-range, must be >= 0");
     93 		info->len = n;
     94 		break;
     95 	case NFLOG_THRESHOLD:
     96 		if (*flags & NFLOG_THRESHOLD)
     97 			exit_error(PARAMETER_PROBLEM,
     98 				   "Can't specify --nflog-threshold twice");
     99 		n = atoi(optarg);
    100 		if (n < 1)
    101 			exit_error(PARAMETER_PROBLEM,
    102 				   "Invalid --nflog-threshold, must be >= 1");
    103 		info->threshold = n;
    104 		break;
    105 	default:
    106 		return 0;
    107 	}
    108 	*flags |= c;
    109 	return 1;
    110 }
    111 
    112 static void final_check(unsigned int flags)
    113 {
    114 	return;
    115 }
    116 
    117 static void nflog_print(const struct xt_nflog_info *info, char *prefix)
    118 {
    119 	if (info->prefix[0] != '\0')
    120 		printf("%snflog-prefix \"%s\" ", prefix, info->prefix);
    121 	if (info->group != XT_NFLOG_DEFAULT_GROUP)
    122 		printf("%snflog-group %u ", prefix, ffs(info->group));
    123 	if (info->len)
    124 		printf("%snflog-range %u ", prefix, info->len);
    125 	if (info->threshold != XT_NFLOG_DEFAULT_THRESHOLD)
    126 		printf("%snflog-threshold %u ", prefix, info->threshold);
    127 }
    128 
    129 static void print(const struct ipt_ip *ip, const struct xt_entry_target *target,
    130 		  int numeric)
    131 {
    132 	const struct xt_nflog_info *info = (struct xt_nflog_info *)target->data;
    133 
    134 	nflog_print(info, "");
    135 }
    136 
    137 static void save(const struct ipt_ip *ip, const struct xt_entry_target *target)
    138 {
    139 	const struct xt_nflog_info *info = (struct xt_nflog_info *)target->data;
    140 
    141 	nflog_print(info, "--");
    142 }
    143 
    144 static struct iptables_target nflog = {
    145 	.name		= "NFLOG",
    146 	.version	= IPTABLES_VERSION,
    147 	.size		= XT_ALIGN(sizeof(struct xt_nflog_info)),
    148 	.userspacesize	= XT_ALIGN(sizeof(struct xt_nflog_info)),
    149 	.help		= help,
    150 	.init		= init,
    151 	.parse		= parse,
    152 	.final_check	= final_check,
    153 	.print		= print,
    154 	.save		= save,
    155 	.extra_opts	= opts,
    156 };
    157 
    158 void ipt_NFLOG_init(void)
    159 {
    160 	register_target(&nflog);
    161 }
    162