1/*
2   Shared library add-on to iptables to add layer 7 matching support.
3
4   http://l7-filter.sf.net
5
6   By Matthew Strait <quadong@users.sf.net>, Dec 2003.
7
8   This program is free software; you can redistribute it and/or
9   modify it under the terms of the GNU General Public License
10   as published by the Free Software Foundation; either version
11   2 of the License, or (at your option) any later version.
12   http://www.gnu.org/licenses/gpl.txt
13*/
14
15#define _GNU_SOURCE
16#include <stdio.h>
17#include <netdb.h>
18#include <string.h>
19#include <stdlib.h>
20#include <getopt.h>
21#include <ctype.h>
22#include <dirent.h>
23
24#include <iptables.h>
25#include <linux/netfilter_ipv4/ipt_childlevel.h>
26
27/* Function which prints out usage message. */
28static void help(void)
29{
30	printf(
31	"CHILDLEVEL match v%s options:\n"
32	"--level <n>  : Match childlevel n (0 == master)\n",
33	IPTABLES_VERSION);
34	fputc('\n', stdout);
35}
36
37static struct option opts[] = {
38	{ .name = "level", .has_arg = 1, .flag = 0, .val = '1' },
39	{ .name = 0 }
40};
41
42/* Function which parses command options; returns true if it ate an option */
43static int parse(int c, char **argv, int invert, unsigned int *flags,
44      const struct ipt_entry *entry, unsigned int *nfcache,
45      struct ipt_entry_match **match)
46{
47	struct ipt_childlevel_info *childlevelinfo =
48		(struct ipt_childlevel_info *)(*match)->data;
49
50	switch (c) {
51	case '1':
52		check_inverse(optarg, &invert, &optind, 0);
53		childlevelinfo->childlevel = atoi(argv[optind-1]);
54		if (invert)
55			childlevelinfo->invert = 1;
56		*flags = 1;
57		break;
58	default:
59		return 0;
60	}
61
62	return 1;
63}
64
65/* Final check; must have specified --level. */
66static void final_check(unsigned int flags)
67{
68	if (!flags)
69		exit_error(PARAMETER_PROBLEM,
70			   "CHILDLEVEL match: You must specify `--level'");
71}
72
73static void print_protocol(int n, int invert, int numeric)
74{
75	fputs("childlevel ", stdout);
76	if (invert) fputc('!', stdout);
77	printf("%d ", n);
78}
79
80/* Prints out the matchinfo. */
81static void print(const struct ipt_ip *ip,
82      const struct ipt_entry_match *match,
83      int numeric)
84{
85	printf("CHILDLEVEL ");
86
87	print_protocol(((struct ipt_childlevel_info *)match->data)->childlevel,
88		  ((struct ipt_childlevel_info *)match->data)->invert, numeric);
89}
90/* Saves the union ipt_matchinfo in parsable form to stdout. */
91static void save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
92{
93        const struct ipt_childlevel_info *info =
94            (const struct ipt_childlevel_info*) match->data;
95
96        printf("--childlevel %s%d ", (info->invert) ? "! ": "", info->childlevel);
97}
98
99static struct iptables_match childlevel = {
100	.name		= "childlevel",
101	.version	= IPTABLES_VERSION,
102	.size		= IPT_ALIGN(sizeof(struct ipt_childlevel_info)),
103	.userspacesize	= IPT_ALIGN(sizeof(struct ipt_childlevel_info)),
104	.help		= &help,
105	.parse		= &parse,
106	.final_check	= &final_check,
107	.print		= &print,
108	.save		= &save,
109	.extra_opts	= opts
110};
111
112void _init(void)
113{
114	register_match(&childlevel);
115}
116