iptables-1.2.9-2.3.1.src.rpm
[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 #include <linux/netfilter_ipv4/ipt_ULOG.h>
21
22 #define ULOG_DEFAULT_NLGROUP 1
23 #define ULOG_DEFAULT_QTHRESHOLD 1
24
25
26 void print_groups(unsigned int gmask)
27 {
28         int b;
29         unsigned int test;
30
31         for (b = 31; b >= 0; b--) {
32                 test = (1 << b);
33                 if (gmask & test)
34                         printf("%d ", b + 1);
35         }
36 }
37
38 /* Function which prints out usage message. */
39 static void help(void)
40 {
41         printf("ULOG v%s options:\n"
42                " --ulog-nlgroup nlgroup         NETLINK group used for logging\n"
43                " --ulog-cprange size            Bytes of each packet to be passed\n"
44                " --ulog-qthreshold              Threshold of in-kernel queue\n"
45                " --ulog-prefix prefix           Prefix log messages with this prefix.\n\n",
46                IPTABLES_VERSION);
47 }
48
49 static struct option opts[] = {
50         {"ulog-nlgroup", 1, 0, '!'},
51         {"ulog-prefix", 1, 0, '#'},
52         {"ulog-cprange", 1, 0, 'A'},
53         {"ulog-qthreshold", 1, 0, 'B'},
54         {0}
55 };
56
57 /* Initialize the target. */
58 static void init(struct ipt_entry_target *t, unsigned int *nfcache)
59 {
60         struct ipt_ulog_info *loginfo = (struct ipt_ulog_info *) t->data;
61
62         loginfo->nl_group = ULOG_DEFAULT_NLGROUP;
63         loginfo->qthreshold = ULOG_DEFAULT_QTHRESHOLD;
64
65         /* Can't cache this */
66         *nfcache |= NFC_UNKNOWN;
67 }
68
69 #define IPT_LOG_OPT_NLGROUP 0x01
70 #define IPT_LOG_OPT_PREFIX 0x02
71 #define IPT_LOG_OPT_CPRANGE 0x04
72 #define IPT_LOG_OPT_QTHRESHOLD 0x08
73
74 /* Function which parses command options; returns true if it
75    ate an option */
76 static int parse(int c, char **argv, int invert, unsigned int *flags,
77                  const struct ipt_entry *entry,
78                  struct ipt_entry_target **target)
79 {
80         struct ipt_ulog_info *loginfo =
81             (struct ipt_ulog_info *) (*target)->data;
82         int group_d;
83
84         switch (c) {
85         case '!':
86                 if (*flags & IPT_LOG_OPT_NLGROUP)
87                         exit_error(PARAMETER_PROBLEM,
88                                    "Can't specify --ulog-nlgroup twice");
89
90                 if (check_inverse(optarg, &invert, NULL, 0))
91                         exit_error(PARAMETER_PROBLEM,
92                                    "Unexpected `!' after --ulog-nlgroup");
93                 group_d = atoi(optarg);
94                 if (group_d > 32 || group_d < 1)
95                         exit_error(PARAMETER_PROBLEM,
96                                    "--ulog-nlgroup has to be between 1 and 32");
97
98                 loginfo->nl_group = (1 << (group_d - 1));
99
100                 *flags |= IPT_LOG_OPT_NLGROUP;
101                 break;
102
103         case '#':
104                 if (*flags & IPT_LOG_OPT_PREFIX)
105                         exit_error(PARAMETER_PROBLEM,
106                                    "Can't specify --ulog-prefix twice");
107
108                 if (check_inverse(optarg, &invert, NULL, 0))
109                         exit_error(PARAMETER_PROBLEM,
110                                    "Unexpected `!' after --ulog-prefix");
111
112                 if (strlen(optarg) > sizeof(loginfo->prefix) - 1)
113                         exit_error(PARAMETER_PROBLEM,
114                                    "Maximum prefix length %u for --ulog-prefix",
115                                    sizeof(loginfo->prefix) - 1);
116
117                 strcpy(loginfo->prefix, optarg);
118                 *flags |= IPT_LOG_OPT_PREFIX;
119                 break;
120         case 'A':
121                 if (*flags & IPT_LOG_OPT_CPRANGE)
122                         exit_error(PARAMETER_PROBLEM,
123                                    "Can't specify --ulog-cprange twice");
124                 if (atoi(optarg) < 0)
125                         exit_error(PARAMETER_PROBLEM,
126                                    "Negative copy range?");
127                 loginfo->copy_range = atoi(optarg);
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                 loginfo->qthreshold = atoi(optarg);
141                 *flags |= IPT_LOG_OPT_QTHRESHOLD;
142                 break;
143         }
144         return 1;
145 }
146
147 /* Final check; nothing. */
148 static void final_check(unsigned int flags)
149 {
150 }
151
152 /* Saves the union ipt_targinfo in parsable form to stdout. */
153 static void save(const struct ipt_ip *ip,
154                  const struct ipt_entry_target *target)
155 {
156         const struct ipt_ulog_info *loginfo
157             = (const struct ipt_ulog_info *) target->data;
158
159         if (strcmp(loginfo->prefix, "") != 0)
160                 printf("--ulog-prefix \"%s\" ", loginfo->prefix);
161
162         if (loginfo->nl_group != ULOG_DEFAULT_NLGROUP) {
163                 printf("--ulog-nlgroup ");
164                 print_groups(loginfo->nl_group);
165         }
166         if (loginfo->copy_range)
167                 printf("--ulog-cprange %d ", loginfo->copy_range);
168
169         if (loginfo->qthreshold != ULOG_DEFAULT_QTHRESHOLD)
170                 printf("--ulog-qthreshold %d ", loginfo->qthreshold);
171 }
172
173 /* Prints out the targinfo. */
174 static void
175 print(const struct ipt_ip *ip,
176       const struct ipt_entry_target *target, int numeric)
177 {
178         const struct ipt_ulog_info *loginfo
179             = (const struct ipt_ulog_info *) target->data;
180
181         printf("ULOG ");
182         printf("copy_range %d nlgroup ", loginfo->copy_range);
183         print_groups(loginfo->nl_group);
184         if (strcmp(loginfo->prefix, "") != 0)
185                 printf("prefix `%s' ", loginfo->prefix);
186         printf("queue_threshold %d ", loginfo->qthreshold);
187 }
188
189 static
190 struct iptables_target ulog = { NULL,
191         "ULOG",
192         IPTABLES_VERSION,
193         IPT_ALIGN(sizeof(struct ipt_ulog_info)),
194         IPT_ALIGN(sizeof(struct ipt_ulog_info)),
195         &help,
196         &init,
197         &parse,
198         &final_check,
199         &print,
200         &save,
201         opts
202 };
203
204 void _init(void)
205 {
206         register_target(&ulog);
207 }