blob: a73b685fcde32ce75f0c6425e3a46cd71ad31c17 [file] [log] [blame]
Harald Welte015dffb2000-07-31 23:38:14 +00001/* Shared library add-on to iptables to add ULOG support.
2 *
Harald Welted3beea32001-01-31 07:30:19 +00003 * (C) 2000 by Harald Welte <laforge@gnumonks.org>
4 *
5 * multipart netlink support based on ideas by Sebastian Zander
6 * <zander@fokus.gmd.de>
Harald Welte015dffb2000-07-31 23:38:14 +00007 *
8 * This software is released under the terms of GNU GPL
9 *
Harald Welted3beea32001-01-31 07:30:19 +000010 * libipt_ULOG.c,v 1.7 2001/01/30 11:55:02 laforge Exp
Harald Welte015dffb2000-07-31 23:38:14 +000011 */
Harald Weltec5bdb402000-07-31 14:24:57 +000012#include <stdio.h>
13#include <netdb.h>
14#include <string.h>
15#include <stdlib.h>
16#include <syslog.h>
17#include <getopt.h>
18#include <iptables.h>
19#include <linux/netfilter_ipv4/ip_tables.h>
Martin Josefsson1eb00812004-05-26 15:58:07 +000020/* For 64bit kernel / 32bit userspace */
21#include "../include/linux/netfilter_ipv4/ipt_ULOG.h"
Harald Weltec5bdb402000-07-31 14:24:57 +000022
23
24void print_groups(unsigned int gmask)
25{
26 int b;
27 unsigned int test;
28
Harald Welte015dffb2000-07-31 23:38:14 +000029 for (b = 31; b >= 0; b--) {
Harald Weltec5bdb402000-07-31 14:24:57 +000030 test = (1 << b);
31 if (gmask & test)
32 printf("%d ", b + 1);
33 }
34}
35
36/* Function which prints out usage message. */
37static void help(void)
38{
Harald Welte015dffb2000-07-31 23:38:14 +000039 printf("ULOG v%s options:\n"
Marc Boucher44540942000-09-12 01:39:41 +000040 " --ulog-nlgroup nlgroup NETLINK group used for logging\n"
Harald Welte015dffb2000-07-31 23:38:14 +000041 " --ulog-cprange size Bytes of each packet to be passed\n"
Harald Welted3beea32001-01-31 07:30:19 +000042 " --ulog-qthreshold Threshold of in-kernel queue\n"
Harald Welte015dffb2000-07-31 23:38:14 +000043 " --ulog-prefix prefix Prefix log messages with this prefix.\n\n",
Harald Welte80fe35d2002-05-29 13:08:15 +000044 IPTABLES_VERSION);
Harald Weltec5bdb402000-07-31 14:24:57 +000045}
46
47static struct option opts[] = {
Harald Welte015dffb2000-07-31 23:38:14 +000048 {"ulog-nlgroup", 1, 0, '!'},
49 {"ulog-prefix", 1, 0, '#'},
50 {"ulog-cprange", 1, 0, 'A'},
Harald Welted3beea32001-01-31 07:30:19 +000051 {"ulog-qthreshold", 1, 0, 'B'},
Harald Welte015dffb2000-07-31 23:38:14 +000052 {0}
Harald Weltec5bdb402000-07-31 14:24:57 +000053};
54
55/* Initialize the target. */
56static void init(struct ipt_entry_target *t, unsigned int *nfcache)
57{
Harald Welte015dffb2000-07-31 23:38:14 +000058 struct ipt_ulog_info *loginfo = (struct ipt_ulog_info *) t->data;
Harald Weltec5bdb402000-07-31 14:24:57 +000059
60 loginfo->nl_group = ULOG_DEFAULT_NLGROUP;
Harald Welted3beea32001-01-31 07:30:19 +000061 loginfo->qthreshold = ULOG_DEFAULT_QTHRESHOLD;
Harald Weltec5bdb402000-07-31 14:24:57 +000062
Harald Weltec5bdb402000-07-31 14:24:57 +000063}
64
65#define IPT_LOG_OPT_NLGROUP 0x01
66#define IPT_LOG_OPT_PREFIX 0x02
Harald Welte015dffb2000-07-31 23:38:14 +000067#define IPT_LOG_OPT_CPRANGE 0x04
Harald Welted3beea32001-01-31 07:30:19 +000068#define IPT_LOG_OPT_QTHRESHOLD 0x08
Harald Weltec5bdb402000-07-31 14:24:57 +000069
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,
Harald Welte015dffb2000-07-31 23:38:14 +000073 const struct ipt_entry *entry,
74 struct ipt_entry_target **target)
Harald Weltec5bdb402000-07-31 14:24:57 +000075{
Harald Welte015dffb2000-07-31 23:38:14 +000076 struct ipt_ulog_info *loginfo =
77 (struct ipt_ulog_info *) (*target)->data;
Harald Weltec5bdb402000-07-31 14:24:57 +000078 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
Harald Welteb77f1da2002-03-14 11:35:58 +000086 if (check_inverse(optarg, &invert, NULL, 0))
Harald Weltec5bdb402000-07-31 14:24:57 +000087 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,
Harald Welte015dffb2000-07-31 23:38:14 +000092 "--ulog-nlgroup has to be between 1 and 32");
Harald Weltec5bdb402000-07-31 14:24:57 +000093
Harald Welte015dffb2000-07-31 23:38:14 +000094 loginfo->nl_group = (1 << (group_d - 1));
Harald Weltec5bdb402000-07-31 14:24:57 +000095
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
Harald Welteb77f1da2002-03-14 11:35:58 +0000104 if (check_inverse(optarg, &invert, NULL, 0))
Harald Weltec5bdb402000-07-31 14:24:57 +0000105 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",
Martin Josefssona28d4952004-05-26 16:04:48 +0000111 (unsigned int)sizeof(loginfo->prefix) - 1);
Harald Weltec5bdb402000-07-31 14:24:57 +0000112
Mike Frysingered26b7b2006-10-10 06:18:40 +0000113 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
Harald Weltec5bdb402000-07-31 14:24:57 +0000121 strcpy(loginfo->prefix, optarg);
122 *flags |= IPT_LOG_OPT_PREFIX;
123 break;
Harald Welte015dffb2000-07-31 23:38:14 +0000124 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?");
Martin Josefsson1eb00812004-05-26 15:58:07 +0000131#ifdef KERNEL_64_USERSPACE_32
132 loginfo->copy_range = (unsigned long long)atoll(optarg);
133#else
Harald Welte015dffb2000-07-31 23:38:14 +0000134 loginfo->copy_range = atoi(optarg);
Martin Josefsson1eb00812004-05-26 15:58:07 +0000135#endif
Harald Welte015dffb2000-07-31 23:38:14 +0000136 *flags |= IPT_LOG_OPT_CPRANGE;
137 break;
Harald Welted3beea32001-01-31 07:30:19 +0000138 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");
Martin Josefsson1eb00812004-05-26 15:58:07 +0000148#ifdef KERNEL_64_USERSPACE_32
149 loginfo->qthreshold = (unsigned long long)atoll(optarg);
150#else
Harald Welted3beea32001-01-31 07:30:19 +0000151 loginfo->qthreshold = atoi(optarg);
Martin Josefsson1eb00812004-05-26 15:58:07 +0000152#endif
Harald Welted3beea32001-01-31 07:30:19 +0000153 *flags |= IPT_LOG_OPT_QTHRESHOLD;
154 break;
Patrick McHardye5568002005-05-02 20:37:39 +0000155 default:
156 return 0;
Harald Weltec5bdb402000-07-31 14:24:57 +0000157 }
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. */
Harald Welte015dffb2000-07-31 23:38:14 +0000167static void save(const struct ipt_ip *ip,
168 const struct ipt_entry_target *target)
Harald Weltec5bdb402000-07-31 14:24:57 +0000169{
Harald Welte015dffb2000-07-31 23:38:14 +0000170 const struct ipt_ulog_info *loginfo
171 = (const struct ipt_ulog_info *) target->data;
Harald Weltec5bdb402000-07-31 14:24:57 +0000172
Harald Welte015dffb2000-07-31 23:38:14 +0000173 if (strcmp(loginfo->prefix, "") != 0)
Jimmy Hedmanb05758a2002-09-15 11:31:28 +0000174 printf("--ulog-prefix \"%s\" ", loginfo->prefix);
Harald Weltec5bdb402000-07-31 14:24:57 +0000175
Harald Welte015dffb2000-07-31 23:38:14 +0000176 if (loginfo->nl_group != ULOG_DEFAULT_NLGROUP) {
177 printf("--ulog-nlgroup ");
Harald Weltec5bdb402000-07-31 14:24:57 +0000178 print_groups(loginfo->nl_group);
Harald Weltec5bdb402000-07-31 14:24:57 +0000179 }
Martin Josefsson1eb00812004-05-26 15:58:07 +0000180#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
Harald Welte015dffb2000-07-31 23:38:14 +0000187 if (loginfo->copy_range)
Martin Josefssona28d4952004-05-26 16:04:48 +0000188 printf("--ulog-cprange %u ", (unsigned int)loginfo->copy_range);
Harald Welted3beea32001-01-31 07:30:19 +0000189
190 if (loginfo->qthreshold != ULOG_DEFAULT_QTHRESHOLD)
Martin Josefssona28d4952004-05-26 16:04:48 +0000191 printf("--ulog-qthreshold %u ", (unsigned int)loginfo->qthreshold);
Martin Josefsson1eb00812004-05-26 15:58:07 +0000192#endif
Harald Weltec5bdb402000-07-31 14:24:57 +0000193}
194
195/* Prints out the targinfo. */
196static void
197print(const struct ipt_ip *ip,
Harald Welte015dffb2000-07-31 23:38:14 +0000198 const struct ipt_entry_target *target, int numeric)
Harald Weltec5bdb402000-07-31 14:24:57 +0000199{
200 const struct ipt_ulog_info *loginfo
Harald Welte015dffb2000-07-31 23:38:14 +0000201 = (const struct ipt_ulog_info *) target->data;
Harald Weltec5bdb402000-07-31 14:24:57 +0000202
203 printf("ULOG ");
Martin Josefsson1eb00812004-05-26 15:58:07 +0000204#ifdef KERNEL_64_USERSPACE_32
205 printf("copy_range %llu nlgroup ", loginfo->copy_range);
206#else
Martin Josefssona28d4952004-05-26 16:04:48 +0000207 printf("copy_range %u nlgroup ", (unsigned int)loginfo->copy_range);
Martin Josefsson1eb00812004-05-26 15:58:07 +0000208#endif
Harald Weltec5bdb402000-07-31 14:24:57 +0000209 print_groups(loginfo->nl_group);
210 if (strcmp(loginfo->prefix, "") != 0)
211 printf("prefix `%s' ", loginfo->prefix);
Martin Josefsson1eb00812004-05-26 15:58:07 +0000212#ifdef KERNEL_64_USERSPACE_32
213 printf("queue_threshold %llu ", loginfo->qthreshold);
214#else
Martin Josefssona28d4952004-05-26 16:04:48 +0000215 printf("queue_threshold %u ", (unsigned int)loginfo->qthreshold);
Martin Josefsson1eb00812004-05-26 15:58:07 +0000216#endif
Harald Weltec5bdb402000-07-31 14:24:57 +0000217}
218
Pablo Neira8caee8b2004-12-28 13:11:59 +0000219static 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
Harald Weltec5bdb402000-07-31 14:24:57 +0000232};
233
234void _init(void)
235{
236 register_target(&ulog);
237}