libipt_ULOG.c revision 4008138e2b5248940265b160fae001d8954fae21
11e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o/* Shared library add-on to iptables to add ULOG support. 21e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o * 319c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * (C) 2000 by Harald Welte <laforge@gnumonks.org> 419c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * 519c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * multipart netlink support based on ideas by Sebastian Zander 619c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * <zander@fokus.gmd.de> 73030daa8aba89830fb0623be01e507bffd636399Theodore Ts'o * 83030daa8aba89830fb0623be01e507bffd636399Theodore Ts'o * This software is released under the terms of GNU GPL 919c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * 101e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o * libipt_ULOG.c,v 1.7 2001/01/30 11:55:02 laforge Exp 111e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o */ 1219c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o#include <stdio.h> 131e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o#include <netdb.h> 1419c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o#include <string.h> 15b1416db3227b4b7192ee0d2d3ff6e00e92e9d3e2Theodore Ts'o#include <stdlib.h> 161e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o#include <syslog.h> 171e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o#include <getopt.h> 181e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o#include <iptables.h> 19ce2722f86de298ad1a8965f55a453b5723d2b2b9Theodore Ts'o#include <linux/netfilter_ipv4/ip_tables.h> 201e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o/* For 64bit kernel / 32bit userspace */ 21ce2722f86de298ad1a8965f55a453b5723d2b2b9Theodore Ts'o#include "../include/linux/netfilter_ipv4/ipt_ULOG.h" 22ce2722f86de298ad1a8965f55a453b5723d2b2b9Theodore Ts'o 23ce2722f86de298ad1a8965f55a453b5723d2b2b9Theodore Ts'o 24ce2722f86de298ad1a8965f55a453b5723d2b2b9Theodore Ts'ovoid print_groups(unsigned int gmask) 251e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o{ 261e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o int b; 271e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o unsigned int test; 281e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o 291e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o for (b = 31; b >= 0; b--) { 301e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o test = (1 << b); 311e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o if (gmask & test) 321e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o printf("%d ", b + 1); 331e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o } 341e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o} 351e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o 361e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o/* Function which prints out usage message. */ 371e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'ostatic void help(void) 381e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o{ 391e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o printf("ULOG v%s options:\n" 401e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o " --ulog-nlgroup nlgroup NETLINK group used for logging\n" 411e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o " --ulog-cprange size Bytes of each packet to be passed\n" 421e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o " --ulog-qthreshold Threshold of in-kernel queue\n" 431e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o " --ulog-prefix prefix Prefix log messages with this prefix.\n\n", 441e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o IPTABLES_VERSION); 451e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o} 461e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o 471e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'ostatic struct option opts[] = { 481e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o {"ulog-nlgroup", 1, 0, '!'}, 491e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o {"ulog-prefix", 1, 0, '#'}, 501e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o {"ulog-cprange", 1, 0, 'A'}, 511e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o {"ulog-qthreshold", 1, 0, 'B'}, 521e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o {0} 531e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o}; 54 55/* Initialize the target. */ 56static void init(struct ipt_entry_target *t, unsigned int *nfcache) 57{ 58 struct ipt_ulog_info *loginfo = (struct ipt_ulog_info *) t->data; 59 60 loginfo->nl_group = ULOG_DEFAULT_NLGROUP; 61 loginfo->qthreshold = ULOG_DEFAULT_QTHRESHOLD; 62 63} 64 65#define IPT_LOG_OPT_NLGROUP 0x01 66#define IPT_LOG_OPT_PREFIX 0x02 67#define IPT_LOG_OPT_CPRANGE 0x04 68#define IPT_LOG_OPT_QTHRESHOLD 0x08 69 70/* Function which parses command options; returns true if it 71 ate an option */ 72static int parse(int c, char **argv, int invert, unsigned int *flags, 73 const struct ipt_entry *entry, 74 struct ipt_entry_target **target) 75{ 76 struct ipt_ulog_info *loginfo = 77 (struct ipt_ulog_info *) (*target)->data; 78 int group_d; 79 80 switch (c) { 81 case '!': 82 if (*flags & IPT_LOG_OPT_NLGROUP) 83 exit_error(PARAMETER_PROBLEM, 84 "Can't specify --ulog-nlgroup twice"); 85 86 if (check_inverse(optarg, &invert, NULL, 0)) 87 exit_error(PARAMETER_PROBLEM, 88 "Unexpected `!' after --ulog-nlgroup"); 89 group_d = atoi(optarg); 90 if (group_d > 32 || group_d < 1) 91 exit_error(PARAMETER_PROBLEM, 92 "--ulog-nlgroup has to be between 1 and 32"); 93 94 loginfo->nl_group = (1 << (group_d - 1)); 95 96 *flags |= IPT_LOG_OPT_NLGROUP; 97 break; 98 99 case '#': 100 if (*flags & IPT_LOG_OPT_PREFIX) 101 exit_error(PARAMETER_PROBLEM, 102 "Can't specify --ulog-prefix twice"); 103 104 if (check_inverse(optarg, &invert, NULL, 0)) 105 exit_error(PARAMETER_PROBLEM, 106 "Unexpected `!' after --ulog-prefix"); 107 108 if (strlen(optarg) > sizeof(loginfo->prefix) - 1) 109 exit_error(PARAMETER_PROBLEM, 110 "Maximum prefix length %u for --ulog-prefix", 111 (unsigned int)sizeof(loginfo->prefix) - 1); 112 113 if (strlen(optarg) == 0) 114 exit_error(PARAMETER_PROBLEM, 115 "No prefix specified for --ulog-prefix"); 116 117 if (strlen(optarg) != strlen(strtok(optarg, "\n"))) 118 exit_error(PARAMETER_PROBLEM, 119 "Newlines not allowed in --ulog-prefix"); 120 121 strcpy(loginfo->prefix, optarg); 122 *flags |= IPT_LOG_OPT_PREFIX; 123 break; 124 case 'A': 125 if (*flags & IPT_LOG_OPT_CPRANGE) 126 exit_error(PARAMETER_PROBLEM, 127 "Can't specify --ulog-cprange twice"); 128 if (atoi(optarg) < 0) 129 exit_error(PARAMETER_PROBLEM, 130 "Negative copy range?"); 131#ifdef KERNEL_64_USERSPACE_32 132 loginfo->copy_range = (unsigned long long)atoll(optarg); 133#else 134 loginfo->copy_range = atoi(optarg); 135#endif 136 *flags |= IPT_LOG_OPT_CPRANGE; 137 break; 138 case 'B': 139 if (*flags & IPT_LOG_OPT_QTHRESHOLD) 140 exit_error(PARAMETER_PROBLEM, 141 "Can't specify --ulog-qthreshold twice"); 142 if (atoi(optarg) < 1) 143 exit_error(PARAMETER_PROBLEM, 144 "Negative or zero queue threshold ?"); 145 if (atoi(optarg) > ULOG_MAX_QLEN) 146 exit_error(PARAMETER_PROBLEM, 147 "Maximum queue length exceeded"); 148#ifdef KERNEL_64_USERSPACE_32 149 loginfo->qthreshold = (unsigned long long)atoll(optarg); 150#else 151 loginfo->qthreshold = atoi(optarg); 152#endif 153 *flags |= IPT_LOG_OPT_QTHRESHOLD; 154 break; 155 default: 156 return 0; 157 } 158 return 1; 159} 160 161/* Final check; nothing. */ 162static void final_check(unsigned int flags) 163{ 164} 165 166/* Saves the union ipt_targinfo in parsable form to stdout. */ 167static void save(const struct ipt_ip *ip, 168 const struct ipt_entry_target *target) 169{ 170 const struct ipt_ulog_info *loginfo 171 = (const struct ipt_ulog_info *) target->data; 172 173 if (strcmp(loginfo->prefix, "") != 0) 174 printf("--ulog-prefix \"%s\" ", loginfo->prefix); 175 176 if (loginfo->nl_group != ULOG_DEFAULT_NLGROUP) { 177 printf("--ulog-nlgroup "); 178 print_groups(loginfo->nl_group); 179 } 180#ifdef KERNEL_64_USERSPACE_32 181 if (loginfo->copy_range) 182 printf("--ulog-cprange %llu ", loginfo->copy_range); 183 184 if (loginfo->qthreshold != ULOG_DEFAULT_QTHRESHOLD) 185 printf("--ulog-qthreshold %llu ", loginfo->qthreshold); 186#else 187 if (loginfo->copy_range) 188 printf("--ulog-cprange %u ", (unsigned int)loginfo->copy_range); 189 190 if (loginfo->qthreshold != ULOG_DEFAULT_QTHRESHOLD) 191 printf("--ulog-qthreshold %u ", (unsigned int)loginfo->qthreshold); 192#endif 193} 194 195/* Prints out the targinfo. */ 196static void 197print(const struct ipt_ip *ip, 198 const struct ipt_entry_target *target, int numeric) 199{ 200 const struct ipt_ulog_info *loginfo 201 = (const struct ipt_ulog_info *) target->data; 202 203 printf("ULOG "); 204#ifdef KERNEL_64_USERSPACE_32 205 printf("copy_range %llu nlgroup ", loginfo->copy_range); 206#else 207 printf("copy_range %u nlgroup ", (unsigned int)loginfo->copy_range); 208#endif 209 print_groups(loginfo->nl_group); 210 if (strcmp(loginfo->prefix, "") != 0) 211 printf("prefix `%s' ", loginfo->prefix); 212#ifdef KERNEL_64_USERSPACE_32 213 printf("queue_threshold %llu ", loginfo->qthreshold); 214#else 215 printf("queue_threshold %u ", (unsigned int)loginfo->qthreshold); 216#endif 217} 218 219static struct iptables_target ulog = { 220 .next = NULL, 221 .name = "ULOG", 222 .version = IPTABLES_VERSION, 223 .size = IPT_ALIGN(sizeof(struct ipt_ulog_info)), 224 .userspacesize = IPT_ALIGN(sizeof(struct ipt_ulog_info)), 225 .help = &help, 226 .init = &init, 227 .parse = &parse, 228 .final_check = &final_check, 229 .print = &print, 230 .save = &save, 231 .extra_opts = opts 232}; 233 234void ipt_ULOG_init(void) 235{ 236 register_target(&ulog); 237} 238