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