fix for f12, gcc4.4
[iptables.git] / extensions / libipt_ULOG.c
1 /* Shared library add-on to iptables to add ULOG support.
2  * 
3  * (C) 2000 by Harald Welte <laforge@gnumonks.org>
4  *
5  * multipart netlink support based on ideas by Sebastian Zander 
6  *                                              <zander@fokus.gmd.de>
7  *
8  * This software is released under the terms of GNU GPL
9  * 
10  * libipt_ULOG.c,v 1.7 2001/01/30 11:55:02 laforge Exp
11  */
12 #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>
20 /* For 64bit kernel / 32bit userspace */
21 #include "../include/linux/netfilter_ipv4/ipt_ULOG.h"
22
23
24 void print_groups(unsigned int gmask)
25 {
26         int b;
27         unsigned int test;
28
29         for (b = 31; b >= 0; b--) {
30                 test = (1 << b);
31                 if (gmask & test)
32                         printf("%d ", b + 1);
33         }
34 }
35
36 /* Function which prints out usage message. */
37 static void help(void)
38 {
39         printf("ULOG v%s options:\n"
40                " --ulog-nlgroup nlgroup         NETLINK group used for logging\n"
41                " --ulog-cprange size            Bytes of each packet to be passed\n"
42                " --ulog-qthreshold              Threshold of in-kernel queue\n"
43                " --ulog-prefix prefix           Prefix log messages with this prefix.\n\n",
44                IPTABLES_VERSION);
45 }
46
47 static struct option opts[] = {
48         {"ulog-nlgroup", 1, 0, '!'},
49         {"ulog-prefix", 1, 0, '#'},
50         {"ulog-cprange", 1, 0, 'A'},
51         {"ulog-qthreshold", 1, 0, 'B'},
52         {0}
53 };
54
55 /* Initialize the target. */
56 static 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 */
72 static 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. */
162 static void final_check(unsigned int flags)
163 {
164 }
165
166 /* Saves the union ipt_targinfo in parsable form to stdout. */
167 static 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. */
196 static void
197 print(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
219 static 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
234 void _init(void)
235 {
236         register_target(&ulog);
237 }