blob: 5371911609a48842d7bd83c8be71ed28c6a4e7d8 [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
63 /* Can't cache this */
64 *nfcache |= NFC_UNKNOWN;
65}
66
67#define IPT_LOG_OPT_NLGROUP 0x01
68#define IPT_LOG_OPT_PREFIX 0x02
Harald Welte015dffb2000-07-31 23:38:14 +000069#define IPT_LOG_OPT_CPRANGE 0x04
Harald Welted3beea32001-01-31 07:30:19 +000070#define IPT_LOG_OPT_QTHRESHOLD 0x08
Harald Weltec5bdb402000-07-31 14:24:57 +000071
72/* Function which parses command options; returns true if it
73 ate an option */
74static int parse(int c, char **argv, int invert, unsigned int *flags,
Harald Welte015dffb2000-07-31 23:38:14 +000075 const struct ipt_entry *entry,
76 struct ipt_entry_target **target)
Harald Weltec5bdb402000-07-31 14:24:57 +000077{
Harald Welte015dffb2000-07-31 23:38:14 +000078 struct ipt_ulog_info *loginfo =
79 (struct ipt_ulog_info *) (*target)->data;
Harald Weltec5bdb402000-07-31 14:24:57 +000080 int group_d;
81
82 switch (c) {
83 case '!':
84 if (*flags & IPT_LOG_OPT_NLGROUP)
85 exit_error(PARAMETER_PROBLEM,
86 "Can't specify --ulog-nlgroup twice");
87
Harald Welteb77f1da2002-03-14 11:35:58 +000088 if (check_inverse(optarg, &invert, NULL, 0))
Harald Weltec5bdb402000-07-31 14:24:57 +000089 exit_error(PARAMETER_PROBLEM,
90 "Unexpected `!' after --ulog-nlgroup");
91 group_d = atoi(optarg);
92 if (group_d > 32 || group_d < 1)
93 exit_error(PARAMETER_PROBLEM,
Harald Welte015dffb2000-07-31 23:38:14 +000094 "--ulog-nlgroup has to be between 1 and 32");
Harald Weltec5bdb402000-07-31 14:24:57 +000095
Harald Welte015dffb2000-07-31 23:38:14 +000096 loginfo->nl_group = (1 << (group_d - 1));
Harald Weltec5bdb402000-07-31 14:24:57 +000097
98 *flags |= IPT_LOG_OPT_NLGROUP;
99 break;
100
101 case '#':
102 if (*flags & IPT_LOG_OPT_PREFIX)
103 exit_error(PARAMETER_PROBLEM,
104 "Can't specify --ulog-prefix twice");
105
Harald Welteb77f1da2002-03-14 11:35:58 +0000106 if (check_inverse(optarg, &invert, NULL, 0))
Harald Weltec5bdb402000-07-31 14:24:57 +0000107 exit_error(PARAMETER_PROBLEM,
108 "Unexpected `!' after --ulog-prefix");
109
110 if (strlen(optarg) > sizeof(loginfo->prefix) - 1)
111 exit_error(PARAMETER_PROBLEM,
112 "Maximum prefix length %u for --ulog-prefix",
113 sizeof(loginfo->prefix) - 1);
114
115 strcpy(loginfo->prefix, optarg);
116 *flags |= IPT_LOG_OPT_PREFIX;
117 break;
Harald Welte015dffb2000-07-31 23:38:14 +0000118 case 'A':
119 if (*flags & IPT_LOG_OPT_CPRANGE)
120 exit_error(PARAMETER_PROBLEM,
121 "Can't specify --ulog-cprange twice");
122 if (atoi(optarg) < 0)
123 exit_error(PARAMETER_PROBLEM,
124 "Negative copy range?");
Martin Josefsson1eb00812004-05-26 15:58:07 +0000125#ifdef KERNEL_64_USERSPACE_32
126 loginfo->copy_range = (unsigned long long)atoll(optarg);
127#else
Harald Welte015dffb2000-07-31 23:38:14 +0000128 loginfo->copy_range = atoi(optarg);
Martin Josefsson1eb00812004-05-26 15:58:07 +0000129#endif
Harald Welte015dffb2000-07-31 23:38:14 +0000130 *flags |= IPT_LOG_OPT_CPRANGE;
131 break;
Harald Welted3beea32001-01-31 07:30:19 +0000132 case 'B':
133 if (*flags & IPT_LOG_OPT_QTHRESHOLD)
134 exit_error(PARAMETER_PROBLEM,
135 "Can't specify --ulog-qthreshold twice");
136 if (atoi(optarg) < 1)
137 exit_error(PARAMETER_PROBLEM,
138 "Negative or zero queue threshold ?");
139 if (atoi(optarg) > ULOG_MAX_QLEN)
140 exit_error(PARAMETER_PROBLEM,
141 "Maximum queue length exceeded");
Martin Josefsson1eb00812004-05-26 15:58:07 +0000142#ifdef KERNEL_64_USERSPACE_32
143 loginfo->qthreshold = (unsigned long long)atoll(optarg);
144#else
Harald Welted3beea32001-01-31 07:30:19 +0000145 loginfo->qthreshold = atoi(optarg);
Martin Josefsson1eb00812004-05-26 15:58:07 +0000146#endif
Harald Welted3beea32001-01-31 07:30:19 +0000147 *flags |= IPT_LOG_OPT_QTHRESHOLD;
148 break;
Harald Weltec5bdb402000-07-31 14:24:57 +0000149 }
150 return 1;
151}
152
153/* Final check; nothing. */
154static void final_check(unsigned int flags)
155{
156}
157
158/* Saves the union ipt_targinfo in parsable form to stdout. */
Harald Welte015dffb2000-07-31 23:38:14 +0000159static void save(const struct ipt_ip *ip,
160 const struct ipt_entry_target *target)
Harald Weltec5bdb402000-07-31 14:24:57 +0000161{
Harald Welte015dffb2000-07-31 23:38:14 +0000162 const struct ipt_ulog_info *loginfo
163 = (const struct ipt_ulog_info *) target->data;
Harald Weltec5bdb402000-07-31 14:24:57 +0000164
Harald Welte015dffb2000-07-31 23:38:14 +0000165 if (strcmp(loginfo->prefix, "") != 0)
Jimmy Hedmanb05758a2002-09-15 11:31:28 +0000166 printf("--ulog-prefix \"%s\" ", loginfo->prefix);
Harald Weltec5bdb402000-07-31 14:24:57 +0000167
Harald Welte015dffb2000-07-31 23:38:14 +0000168 if (loginfo->nl_group != ULOG_DEFAULT_NLGROUP) {
169 printf("--ulog-nlgroup ");
Harald Weltec5bdb402000-07-31 14:24:57 +0000170 print_groups(loginfo->nl_group);
Harald Weltec5bdb402000-07-31 14:24:57 +0000171 }
Martin Josefsson1eb00812004-05-26 15:58:07 +0000172#ifdef KERNEL_64_USERSPACE_32
173 if (loginfo->copy_range)
174 printf("--ulog-cprange %llu ", loginfo->copy_range);
175
176 if (loginfo->qthreshold != ULOG_DEFAULT_QTHRESHOLD)
177 printf("--ulog-qthreshold %llu ", loginfo->qthreshold);
178#else
Harald Welte015dffb2000-07-31 23:38:14 +0000179 if (loginfo->copy_range)
Harald Welted3beea32001-01-31 07:30:19 +0000180 printf("--ulog-cprange %d ", loginfo->copy_range);
181
182 if (loginfo->qthreshold != ULOG_DEFAULT_QTHRESHOLD)
183 printf("--ulog-qthreshold %d ", loginfo->qthreshold);
Martin Josefsson1eb00812004-05-26 15:58:07 +0000184#endif
Harald Weltec5bdb402000-07-31 14:24:57 +0000185}
186
187/* Prints out the targinfo. */
188static void
189print(const struct ipt_ip *ip,
Harald Welte015dffb2000-07-31 23:38:14 +0000190 const struct ipt_entry_target *target, int numeric)
Harald Weltec5bdb402000-07-31 14:24:57 +0000191{
192 const struct ipt_ulog_info *loginfo
Harald Welte015dffb2000-07-31 23:38:14 +0000193 = (const struct ipt_ulog_info *) target->data;
Harald Weltec5bdb402000-07-31 14:24:57 +0000194
195 printf("ULOG ");
Martin Josefsson1eb00812004-05-26 15:58:07 +0000196#ifdef KERNEL_64_USERSPACE_32
197 printf("copy_range %llu nlgroup ", loginfo->copy_range);
198#else
Harald Welte015dffb2000-07-31 23:38:14 +0000199 printf("copy_range %d nlgroup ", loginfo->copy_range);
Martin Josefsson1eb00812004-05-26 15:58:07 +0000200#endif
Harald Weltec5bdb402000-07-31 14:24:57 +0000201 print_groups(loginfo->nl_group);
202 if (strcmp(loginfo->prefix, "") != 0)
203 printf("prefix `%s' ", loginfo->prefix);
Martin Josefsson1eb00812004-05-26 15:58:07 +0000204#ifdef KERNEL_64_USERSPACE_32
205 printf("queue_threshold %llu ", loginfo->qthreshold);
206#else
Harald Welted3beea32001-01-31 07:30:19 +0000207 printf("queue_threshold %d ", loginfo->qthreshold);
Martin Josefsson1eb00812004-05-26 15:58:07 +0000208#endif
Harald Weltec5bdb402000-07-31 14:24:57 +0000209}
210
Harald Welte3efb6ea2001-08-06 18:50:21 +0000211static
Harald Welte015dffb2000-07-31 23:38:14 +0000212struct iptables_target ulog = { NULL,
213 "ULOG",
Harald Welte80fe35d2002-05-29 13:08:15 +0000214 IPTABLES_VERSION,
Harald Welte015dffb2000-07-31 23:38:14 +0000215 IPT_ALIGN(sizeof(struct ipt_ulog_info)),
216 IPT_ALIGN(sizeof(struct ipt_ulog_info)),
217 &help,
218 &init,
219 &parse,
220 &final_check,
221 &print,
222 &save,
223 opts
Harald Weltec5bdb402000-07-31 14:24:57 +0000224};
225
226void _init(void)
227{
228 register_target(&ulog);
229}