• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
print_groups(unsigned int gmask)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. */
help(void)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. */
init(struct ipt_entry_target * t,unsigned int * nfcache)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 */
parse(int c,char ** argv,int invert,unsigned int * flags,const struct ipt_entry * entry,struct ipt_entry_target ** target)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. */
final_check(unsigned int flags)162 static void final_check(unsigned int flags)
163 {
164 }
165 
166 /* Saves the union ipt_targinfo in parsable form to stdout. */
save(const struct ipt_ip * ip,const struct ipt_entry_target * target)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
print(const struct ipt_ip * ip,const struct ipt_entry_target * target,int numeric)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 
ipt_ULOG_init(void)234 void ipt_ULOG_init(void)
235 {
236 	register_target(&ulog);
237 }
238