blob: cc65bba973e37939a817e74d3cf43017a0a572f2 [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
Jan Engelhardt661f1122007-07-30 14:46:51 +000047static const 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. */
Yasuyuki KOZAKAI193df8e2007-07-24 05:57:28 +000056static void init(struct xt_entry_target *t, unsigned int *nfcache)
Harald Weltec5bdb402000-07-31 14:24:57 +000057{
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,
Yasuyuki KOZAKAIc0a9ab92007-07-24 06:02:05 +000073 const void *entry,
Yasuyuki KOZAKAI193df8e2007-07-24 05:57:28 +000074 struct xt_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?");
131 loginfo->copy_range = atoi(optarg);
132 *flags |= IPT_LOG_OPT_CPRANGE;
133 break;
Harald Welted3beea32001-01-31 07:30:19 +0000134 case 'B':
135 if (*flags & IPT_LOG_OPT_QTHRESHOLD)
136 exit_error(PARAMETER_PROBLEM,
137 "Can't specify --ulog-qthreshold twice");
138 if (atoi(optarg) < 1)
139 exit_error(PARAMETER_PROBLEM,
140 "Negative or zero queue threshold ?");
141 if (atoi(optarg) > ULOG_MAX_QLEN)
142 exit_error(PARAMETER_PROBLEM,
143 "Maximum queue length exceeded");
144 loginfo->qthreshold = atoi(optarg);
145 *flags |= IPT_LOG_OPT_QTHRESHOLD;
146 break;
Patrick McHardye5568002005-05-02 20:37:39 +0000147 default:
148 return 0;
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. */
Yasuyuki KOZAKAIc0a9ab92007-07-24 06:02:05 +0000159static void save(const void *ip,
Yasuyuki KOZAKAI193df8e2007-07-24 05:57:28 +0000160 const struct xt_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 }
Harald Welte015dffb2000-07-31 23:38:14 +0000172 if (loginfo->copy_range)
Martin Josefssona28d4952004-05-26 16:04:48 +0000173 printf("--ulog-cprange %u ", (unsigned int)loginfo->copy_range);
Harald Welted3beea32001-01-31 07:30:19 +0000174
175 if (loginfo->qthreshold != ULOG_DEFAULT_QTHRESHOLD)
Martin Josefssona28d4952004-05-26 16:04:48 +0000176 printf("--ulog-qthreshold %u ", (unsigned int)loginfo->qthreshold);
Harald Weltec5bdb402000-07-31 14:24:57 +0000177}
178
179/* Prints out the targinfo. */
180static void
Yasuyuki KOZAKAIc0a9ab92007-07-24 06:02:05 +0000181print(const void *ip,
Yasuyuki KOZAKAI193df8e2007-07-24 05:57:28 +0000182 const struct xt_entry_target *target, int numeric)
Harald Weltec5bdb402000-07-31 14:24:57 +0000183{
184 const struct ipt_ulog_info *loginfo
Harald Welte015dffb2000-07-31 23:38:14 +0000185 = (const struct ipt_ulog_info *) target->data;
Harald Weltec5bdb402000-07-31 14:24:57 +0000186
187 printf("ULOG ");
Martin Josefssona28d4952004-05-26 16:04:48 +0000188 printf("copy_range %u nlgroup ", (unsigned int)loginfo->copy_range);
Harald Weltec5bdb402000-07-31 14:24:57 +0000189 print_groups(loginfo->nl_group);
190 if (strcmp(loginfo->prefix, "") != 0)
191 printf("prefix `%s' ", loginfo->prefix);
Martin Josefssona28d4952004-05-26 16:04:48 +0000192 printf("queue_threshold %u ", (unsigned int)loginfo->qthreshold);
Harald Weltec5bdb402000-07-31 14:24:57 +0000193}
194
Pablo Neira8caee8b2004-12-28 13:11:59 +0000195static struct iptables_target ulog = {
Pablo Neira8caee8b2004-12-28 13:11:59 +0000196 .name = "ULOG",
197 .version = IPTABLES_VERSION,
198 .size = IPT_ALIGN(sizeof(struct ipt_ulog_info)),
199 .userspacesize = IPT_ALIGN(sizeof(struct ipt_ulog_info)),
200 .help = &help,
201 .init = &init,
202 .parse = &parse,
203 .final_check = &final_check,
204 .print = &print,
205 .save = &save,
206 .extra_opts = opts
Harald Weltec5bdb402000-07-31 14:24:57 +0000207};
208
209void _init(void)
210{
211 register_target(&ulog);
212}