1/* Shared library add-on to ip6tables to add NFMARK matching support. */
2#include <stdio.h>
3#include <netdb.h>
4#include <string.h>
5#include <stdlib.h>
6#include <getopt.h>
7
8#include <ip6tables.h>
9#include <linux/netfilter_ipv6/ip6t_mark.h>
10
11/* Function which prints out usage message. */
12static void
13help(void)
14{
15	printf(
16"MARK match v%s options:\n"
17"[!] --mark value[/mask]         Match nfmark value with optional mask\n"
18"\n",
19IPTABLES_VERSION);
20}
21
22static struct option opts[] = {
23	{ "mark", 1, 0, '1' },
24	{0}
25};
26
27/* Initialize the match. */
28static void
29init(struct ip6t_entry_match *m, unsigned int *nfcache)
30{
31	/* Can't cache this. */
32	*nfcache |= NFC_UNKNOWN;
33}
34
35/* Function which parses command options; returns true if it
36   ate an option */
37static int
38parse(int c, char **argv, int invert, unsigned int *flags,
39      const struct ip6t_entry *entry,
40      unsigned int *nfcache,
41      struct ip6t_entry_match **match)
42{
43	struct ip6t_mark_info *markinfo = (struct ip6t_mark_info *)(*match)->data;
44
45	switch (c) {
46		char *end;
47	case '1':
48		check_inverse(optarg, &invert, &optind, 0);
49		markinfo->mark = strtoul(optarg, &end, 0);
50		if (*end == '/') {
51			markinfo->mask = strtoul(end+1, &end, 0);
52		} else
53			markinfo->mask = 0xffffffff;
54		if (*end != '\0' || end == optarg)
55			exit_error(PARAMETER_PROBLEM, "Bad MARK value `%s'", optarg);
56		if (invert)
57			markinfo->invert = 1;
58		*flags = 1;
59		break;
60
61	default:
62		return 0;
63	}
64	return 1;
65}
66
67static void
68print_mark(unsigned long mark, unsigned long mask, int invert, int numeric)
69{
70	if (invert)
71		fputc('!', stdout);
72
73	if(mask != 0xffffffff)
74		printf("0x%lx/0x%lx ", mark, mask);
75	else
76		printf("0x%lx ", mark);
77}
78
79/* Final check; must have specified --mark. */
80static void
81final_check(unsigned int flags)
82{
83	if (!flags)
84		exit_error(PARAMETER_PROBLEM,
85			   "MARK match: You must specify `--mark'");
86}
87
88/* Prints out the matchinfo. */
89static void
90print(const struct ip6t_ip6 *ip,
91      const struct ip6t_entry_match *match,
92      int numeric)
93{
94	printf("MARK match ");
95	print_mark(((struct ip6t_mark_info *)match->data)->mark,
96		  ((struct ip6t_mark_info *)match->data)->mask,
97		  ((struct ip6t_mark_info *)match->data)->invert, numeric);
98}
99
100/* Saves the union ip6t_matchinfo in parsable form to stdout. */
101static void
102save(const struct ip6t_ip6 *ip, const struct ip6t_entry_match *match)
103{
104	printf("--mark ");
105	print_mark(((struct ip6t_mark_info *)match->data)->mark,
106		  ((struct ip6t_mark_info *)match->data)->mask,
107		  ((struct ip6t_mark_info *)match->data)->invert, 0);
108}
109
110static
111struct ip6tables_match mark
112= { NULL,
113    "mark",
114    IPTABLES_VERSION,
115    IP6T_ALIGN(sizeof(struct ip6t_mark_info)),
116    IP6T_ALIGN(sizeof(struct ip6t_mark_info)),
117    &help,
118    &init,
119    &parse,
120    &final_check,
121    &print,
122    &save,
123    opts
124};
125
126void _init(void)
127{
128	register_match6(&mark);
129}
130