1/*
2 * Shared library add-on to ip6tables to add CONNSECMARK target support.
3 *
4 * Based on the MARK and CONNMARK targets.
5 *
6 * Copyright (C) 2006 Red Hat, Inc., James Morris <jmorris@redhat.com>
7 */
8#include <stdio.h>
9#include <string.h>
10#include <stdlib.h>
11#include <getopt.h>
12#include <ip6tables.h>
13#include <linux/netfilter/xt_CONNSECMARK.h>
14
15#define PFX "CONNSECMARK target: "
16
17static void help(void)
18{
19	printf(
20"CONNSECMARK target v%s options:\n"
21"  --save                   Copy security mark from packet to conntrack\n"
22"  --restore                Copy security mark from connection to packet\n"
23"\n",
24IPTABLES_VERSION);
25}
26
27static struct option opts[] = {
28	{ "save", 0, 0, '1' },
29	{ "restore", 0, 0, '2' },
30	{ 0 }
31};
32
33static int parse(int c, char **argv, int invert, unsigned int *flags,
34                 const struct ip6t_entry *entry, struct ip6t_entry_target **target)
35{
36	struct xt_connsecmark_target_info *info =
37		(struct xt_connsecmark_target_info*)(*target)->data;
38
39	switch (c) {
40	case '1':
41		if (*flags & CONNSECMARK_SAVE)
42			exit_error(PARAMETER_PROBLEM, PFX
43				   "Can't specify --save twice");
44		info->mode = CONNSECMARK_SAVE;
45		*flags |= CONNSECMARK_SAVE;
46		break;
47
48	case '2':
49		if (*flags & CONNSECMARK_RESTORE)
50			exit_error(PARAMETER_PROBLEM, PFX
51				   "Can't specify --restore twice");
52		info->mode = CONNSECMARK_RESTORE;
53		*flags |= CONNSECMARK_RESTORE;
54		break;
55
56	default:
57		return 0;
58	}
59
60	return 1;
61}
62
63static void final_check(unsigned int flags)
64{
65	if (!flags)
66		exit_error(PARAMETER_PROBLEM, PFX "parameter required");
67
68	if (flags == (CONNSECMARK_SAVE|CONNSECMARK_RESTORE))
69		exit_error(PARAMETER_PROBLEM, PFX "only one flag of --save "
70		           "or --restore is allowed");
71}
72
73static void print_connsecmark(struct xt_connsecmark_target_info *info)
74{
75	switch (info->mode) {
76	case CONNSECMARK_SAVE:
77		printf("save ");
78		break;
79
80	case CONNSECMARK_RESTORE:
81		printf("restore ");
82		break;
83
84	default:
85		exit_error(OTHER_PROBLEM, PFX "invalid mode %hhu\n", info->mode);
86	}
87}
88
89static void print(const struct ip6t_ip6 *ip,
90		  const struct ip6t_entry_target *target, int numeric)
91{
92	struct xt_connsecmark_target_info *info =
93		(struct xt_connsecmark_target_info*)(target)->data;
94
95	printf("CONNSECMARK ");
96	print_connsecmark(info);
97}
98
99static void save(const struct ip6t_ip6 *ip, const struct ip6t_entry_target *target)
100{
101	struct xt_connsecmark_target_info *info =
102		(struct xt_connsecmark_target_info*)target->data;
103
104	printf("--");
105	print_connsecmark(info);
106}
107
108static struct ip6tables_target connsecmark = {
109	.name		= "CONNSECMARK",
110	.version	= IPTABLES_VERSION,
111	.size		= IP6T_ALIGN(sizeof(struct xt_connsecmark_target_info)),
112	.userspacesize	= IP6T_ALIGN(sizeof(struct xt_connsecmark_target_info)),
113	.parse		= &parse,
114	.help		= &help,
115	.final_check	= &final_check,
116	.print		= &print,
117	.save		= &save,
118	.extra_opts	= opts
119};
120
121void _init(void)
122{
123	register_target6(&connsecmark);
124}
125