iptables-1.3.2-20050720
[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                 strcpy(loginfo->prefix, optarg);
114                 *flags |= IPT_LOG_OPT_PREFIX;
115                 break;
116         case 'A':
117                 if (*flags & IPT_LOG_OPT_CPRANGE)
118                         exit_error(PARAMETER_PROBLEM,
119                                    "Can't specify --ulog-cprange twice");
120                 if (atoi(optarg) < 0)
121                         exit_error(PARAMETER_PROBLEM,
122                                    "Negative copy range?");
123 #ifdef KERNEL_64_USERSPACE_32
124                 loginfo->copy_range = (unsigned long long)atoll(optarg);
125 #else
126                 loginfo->copy_range = atoi(optarg);
127 #endif
128                 *flags |= IPT_LOG_OPT_CPRANGE;
129                 break;
130         case 'B':
131                 if (*flags & IPT_LOG_OPT_QTHRESHOLD)
132                         exit_error(PARAMETER_PROBLEM,
133                                    "Can't specify --ulog-qthreshold twice");
134                 if (atoi(optarg) < 1)
135                         exit_error(PARAMETER_PROBLEM,
136                                    "Negative or zero queue threshold ?");
137                 if (atoi(optarg) > ULOG_MAX_QLEN)
138                         exit_error(PARAMETER_PROBLEM,
139                                    "Maximum queue length exceeded");
140 #ifdef KERNEL_64_USERSPACE_32
141                 loginfo->qthreshold = (unsigned long long)atoll(optarg);
142 #else
143                 loginfo->qthreshold = atoi(optarg);
144 #endif
145                 *flags |= IPT_LOG_OPT_QTHRESHOLD;
146                 break;
147         default:
148                 return 0;
149         }
150         return 1;
151 }
152
153 /* Final check; nothing. */
154 static void final_check(unsigned int flags)
155 {
156 }
157
158 /* Saves the union ipt_targinfo in parsable form to stdout. */
159 static void save(const struct ipt_ip *ip,
160                  const struct ipt_entry_target *target)
161 {
162         const struct ipt_ulog_info *loginfo
163             = (const struct ipt_ulog_info *) target->data;
164
165         if (strcmp(loginfo->prefix, "") != 0)
166                 printf("--ulog-prefix \"%s\" ", loginfo->prefix);
167
168         if (loginfo->nl_group != ULOG_DEFAULT_NLGROUP) {
169                 printf("--ulog-nlgroup ");
170                 print_groups(loginfo->nl_group);
171         }
172 #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
179         if (loginfo->copy_range)
180                 printf("--ulog-cprange %u ", (unsigned int)loginfo->copy_range);
181
182         if (loginfo->qthreshold != ULOG_DEFAULT_QTHRESHOLD)
183                 printf("--ulog-qthreshold %u ", (unsigned int)loginfo->qthreshold);
184 #endif
185 }
186
187 /* Prints out the targinfo. */
188 static void
189 print(const struct ipt_ip *ip,
190       const struct ipt_entry_target *target, int numeric)
191 {
192         const struct ipt_ulog_info *loginfo
193             = (const struct ipt_ulog_info *) target->data;
194
195         printf("ULOG ");
196 #ifdef KERNEL_64_USERSPACE_32
197         printf("copy_range %llu nlgroup ", loginfo->copy_range);
198 #else
199         printf("copy_range %u nlgroup ", (unsigned int)loginfo->copy_range);
200 #endif
201         print_groups(loginfo->nl_group);
202         if (strcmp(loginfo->prefix, "") != 0)
203                 printf("prefix `%s' ", loginfo->prefix);
204 #ifdef KERNEL_64_USERSPACE_32
205         printf("queue_threshold %llu ", loginfo->qthreshold);
206 #else
207         printf("queue_threshold %u ", (unsigned int)loginfo->qthreshold);
208 #endif
209 }
210
211 static struct iptables_target ulog = {
212         .next           = NULL,
213         .name           = "ULOG",
214         .version        = IPTABLES_VERSION,
215         .size           = IPT_ALIGN(sizeof(struct ipt_ulog_info)),
216         .userspacesize  = IPT_ALIGN(sizeof(struct ipt_ulog_info)),
217         .help           = &help,
218         .init           = &init,
219         .parse          = &parse,
220         .final_check    = &final_check,
221         .print          = &print,
222         .save           = &save,
223         .extra_opts     = opts
224 };
225
226 void _init(void)
227 {
228         register_target(&ulog);
229 }