1/* Provides a NETLINK target, identical to that of the ipchains -o flag */
2/* AUTHOR: Gianni Tedesco <gianni@ecsc.co.uk> */
3#include <stdio.h>
4#include <netdb.h>
5#include <string.h>
6#include <stdlib.h>
7#include <syslog.h>
8#include <getopt.h>
9#include <iptables.h>
10#include <linux/netfilter_ipv4/ip_tables.h>
11#include <linux/netfilter_ipv4/ipt_NETLINK.h>
12
13static void help(void)
14{
15	printf("NETLINK v%s options:\n"
16		" --nldrop		Drop the packet too\n"
17		" --nlmark <number>	Mark the packet\n"
18		" --nlsize <bytes>	Limit packet size\n",
19	       IPTABLES_VERSION);
20}
21
22static struct option opts[] = {
23	{"nldrop", 0, 0, 'd'},
24	{"nlmark", 1, 0, 'm'},
25	{"nlsize", 1, 0, 's'},
26	{0}
27};
28
29static void init(struct ipt_entry_target *t, unsigned int *nfcache)
30{
31	struct ipt_nldata *nld = (struct ipt_nldata *) t->data;
32
33	nld->flags=0;
34
35	*nfcache |= NFC_UNKNOWN;
36}
37
38/* Parse command options */
39static int parse(int c, char **argv, int invert, unsigned int *flags,
40		 const struct ipt_entry *entry,
41		 struct ipt_entry_target **target)
42{
43	struct ipt_nldata *nld=(struct ipt_nldata *)(*target)->data;
44
45	switch (c) {
46		case 'd':
47			if (MASK(*flags, USE_DROP))
48				exit_error(PARAMETER_PROBLEM,
49				"Can't specify --nldrop twice");
50
51			if ( check_inverse(optarg, &invert, NULL, 0) ) {
52				MASK_UNSET(nld->flags, USE_DROP);
53			} else {
54				MASK_SET(nld->flags, USE_DROP);
55			}
56
57			MASK_SET(*flags, USE_DROP);
58
59			break;
60		case 'm':
61			if (MASK(*flags, USE_MARK))
62				exit_error(PARAMETER_PROBLEM,
63				"Can't specify --nlmark twice");
64
65			if (check_inverse(optarg, &invert, NULL, 0)) {
66				MASK_UNSET(nld->flags, USE_MARK);
67			}else{
68				MASK_SET(nld->flags, USE_MARK);
69				nld->mark=atoi(optarg);
70			}
71
72			MASK_SET(*flags, USE_MARK);
73			break;
74		case 's':
75			if (MASK(*flags, USE_SIZE))
76				exit_error(PARAMETER_PROBLEM,
77				"Can't specify --nlsize twice");
78
79			if ( atoi(optarg) <= 0 )
80				exit_error(PARAMETER_PROBLEM,
81				"--nlsize must be larger than zero");
82
83
84			if (check_inverse(optarg, &invert, NULL, 0)) {
85				MASK_UNSET(nld->flags, USE_SIZE);
86			}else{
87				MASK_SET(nld->flags, USE_SIZE);
88				nld->size=atoi(optarg);
89			}
90			MASK_SET(*flags, USE_SIZE);
91			break;
92
93		default:
94			return 0;
95	}
96	return 1;
97}
98
99static void final_check(unsigned int flags)
100{
101	/* ?? */
102}
103
104/* Saves the union ipt_targinfo in parsable form to stdout. */
105static void save(const struct ipt_ip *ip,
106		 const struct ipt_entry_target *target)
107{
108	const struct ipt_nldata *nld
109	    = (const struct ipt_nldata *) target->data;
110
111	if ( MASK(nld->flags, USE_DROP) )
112		printf("--nldrop ");
113
114	if ( MASK(nld->flags, USE_MARK) )
115		printf("--nlmark %i ", nld->mark);
116
117	if ( MASK(nld->flags, USE_SIZE) )
118		printf("--nlsize %i ", nld->size);
119}
120
121/* Prints out the targinfo. */
122static void
123print(const struct ipt_ip *ip,
124      const struct ipt_entry_target *target, int numeric)
125{
126	const struct ipt_nldata *nld
127	    = (const struct ipt_nldata *) target->data;
128
129	if ( MASK(nld->flags, USE_DROP) )
130		printf("nldrop ");
131
132	if ( MASK(nld->flags, USE_MARK) )
133		printf("nlmark %i ", nld->mark);
134
135	if ( MASK(nld->flags, USE_SIZE) )
136		printf("nlsize %i ", nld->size);
137}
138
139static
140struct iptables_target netlink = { NULL,
141	"NETLINK",
142	IPTABLES_VERSION,
143	IPT_ALIGN(sizeof(struct ipt_nldata)),
144	IPT_ALIGN(sizeof(struct ipt_nldata)),
145	&help,
146	&init,
147	&parse,
148	&final_check,
149	&print,
150	&save,
151	opts
152};
153
154void _init(void)
155{
156	register_target(&netlink);
157}
158
159