libxt_pkttype.c revision 42979363f3958b4436c6d2503753c182c58e55ea
1/*
2 * Shared library add-on to iptables to match
3 * packets by their type (BROADCAST, UNICAST, MULTICAST).
4 *
5 * Michal Ludvig <michal@logix.cz>
6 */
7#include <stdio.h>
8#include <netdb.h>
9#include <string.h>
10#include <stdlib.h>
11#include <getopt.h>
12#if defined(__GLIBC__) && __GLIBC__ == 2
13#include <net/ethernet.h>
14#else
15#include <linux/if_ether.h>
16#endif
17#include <xtables.h>
18#include <linux/if_packet.h>
19#include <linux/netfilter/xt_pkttype.h>
20
21#define	PKTTYPE_VERSION	"0.1"
22
23struct pkttypes {
24	const char *name;
25	unsigned char pkttype;
26	unsigned char printhelp;
27	const char *help;
28};
29
30static const struct pkttypes supported_types[] = {
31	{"unicast", PACKET_HOST, 1, "to us"},
32	{"broadcast", PACKET_BROADCAST, 1, "to all"},
33	{"multicast", PACKET_MULTICAST, 1, "to group"},
34/*
35	{"otherhost", PACKET_OTHERHOST, 1, "to someone else"},
36	{"outgoing", PACKET_OUTGOING, 1, "outgoing of any type"},
37*/
38	/* aliases */
39	{"bcast", PACKET_BROADCAST, 0, NULL},
40	{"mcast", PACKET_MULTICAST, 0, NULL},
41	{"host", PACKET_HOST, 0, NULL}
42};
43
44static void print_types(void)
45{
46	unsigned int	i;
47
48	printf("Valid packet types:\n");
49	for (i = 0; i < ARRAY_SIZE(supported_types); ++i)
50		if(supported_types[i].printhelp == 1)
51			printf("\t%-14s\t\t%s\n", supported_types[i].name, supported_types[i].help);
52	printf("\n");
53}
54
55static void pkttype_help(void)
56{
57	printf(
58"pkttype match options:\n"
59"[!] --pkt-type packettype    match packet type\n");
60	print_types();
61}
62
63static const struct option pkttype_opts[] = {
64	{"pkt-type", 1, NULL, '1'},
65	{ .name = NULL }
66};
67
68static void parse_pkttype(const char *pkttype, struct xt_pkttype_info *info)
69{
70	unsigned int	i;
71
72	for (i = 0; i < ARRAY_SIZE(supported_types); ++i)
73		if(strcasecmp(pkttype, supported_types[i].name)==0)
74		{
75			info->pkttype=supported_types[i].pkttype;
76			return;
77		}
78
79	xtables_error(PARAMETER_PROBLEM, "Bad packet type '%s'", pkttype);
80}
81
82static int pkttype_parse(int c, char **argv, int invert, unsigned int *flags,
83                         const void *entry, struct xt_entry_match **match)
84{
85	struct xt_pkttype_info *info = (struct xt_pkttype_info *)(*match)->data;
86
87	switch(c)
88	{
89		case '1':
90			xtables_check_inverse(optarg, &invert, &optind, 0);
91			parse_pkttype(argv[optind-1], info);
92			if(invert)
93				info->invert=1;
94			*flags=1;
95			break;
96
97		default:
98			return 0;
99	}
100
101	return 1;
102}
103
104static void pkttype_check(unsigned int flags)
105{
106	if (!flags)
107		xtables_error(PARAMETER_PROBLEM, "You must specify \"--pkt-type\"");
108}
109
110static void print_pkttype(const struct xt_pkttype_info *info)
111{
112	unsigned int	i;
113
114	for (i = 0; i < ARRAY_SIZE(supported_types); ++i)
115		if(supported_types[i].pkttype==info->pkttype)
116		{
117			printf("%s ", supported_types[i].name);
118			return;
119		}
120
121	printf("%d ", info->pkttype);	/* in case we didn't find an entry in named-packtes */
122}
123
124static void pkttype_print(const void *ip, const struct xt_entry_match *match,
125                          int numeric)
126{
127	const struct xt_pkttype_info *info = (const void *)match->data;
128
129	printf("PKTTYPE %s= ", info->invert?"!":"");
130	print_pkttype(info);
131}
132
133static void pkttype_save(const void *ip, const struct xt_entry_match *match)
134{
135	const struct xt_pkttype_info *info = (const void *)match->data;
136
137	printf("%s--pkt-type ", info->invert ? "! " : "");
138	print_pkttype(info);
139}
140
141static struct xtables_match pkttype_match = {
142	.family		= NFPROTO_UNSPEC,
143	.name		= "pkttype",
144	.version	= XTABLES_VERSION,
145	.size		= XT_ALIGN(sizeof(struct xt_pkttype_info)),
146	.userspacesize	= XT_ALIGN(sizeof(struct xt_pkttype_info)),
147	.help		= pkttype_help,
148	.parse		= pkttype_parse,
149	.final_check	= pkttype_check,
150	.print		= pkttype_print,
151	.save		= pkttype_save,
152	.extra_opts	= pkttype_opts,
153};
154
155void _init(void)
156{
157	xtables_register_match(&pkttype_match);
158}
159