libxt_pkttype.c revision 69f564e3890976461de0016cd81171ff8bfa8353
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 < sizeof(supported_types)/sizeof(struct pkttypes); i++)
50	{
51		if(supported_types[i].printhelp == 1)
52			printf("\t%-14s\t\t%s\n", supported_types[i].name, supported_types[i].help);
53	}
54	printf("\n");
55}
56
57static void pkttype_help(void)
58{
59	printf(
60"pkttype match options:\n"
61"[!] --pkt-type packettype    match packet type\n");
62	print_types();
63}
64
65static const struct option pkttype_opts[] = {
66	{"pkt-type", 1, NULL, '1'},
67	{ .name = NULL }
68};
69
70static void parse_pkttype(const char *pkttype, struct xt_pkttype_info *info)
71{
72	unsigned int	i;
73
74	for (i = 0; i < sizeof(supported_types)/sizeof(struct pkttypes); i++)
75	{
76		if(strcasecmp(pkttype, supported_types[i].name)==0)
77		{
78			info->pkttype=supported_types[i].pkttype;
79			return;
80		}
81	}
82
83	xtables_error(PARAMETER_PROBLEM, "Bad packet type '%s'", pkttype);
84}
85
86static int pkttype_parse(int c, char **argv, int invert, unsigned int *flags,
87                         const void *entry, struct xt_entry_match **match)
88{
89	struct xt_pkttype_info *info = (struct xt_pkttype_info *)(*match)->data;
90
91	switch(c)
92	{
93		case '1':
94			xtables_check_inverse(optarg, &invert, &optind, 0);
95			parse_pkttype(argv[optind-1], info);
96			if(invert)
97				info->invert=1;
98			*flags=1;
99			break;
100
101		default:
102			return 0;
103	}
104
105	return 1;
106}
107
108static void pkttype_check(unsigned int flags)
109{
110	if (!flags)
111		xtables_error(PARAMETER_PROBLEM, "You must specify \"--pkt-type\"");
112}
113
114static void print_pkttype(const struct xt_pkttype_info *info)
115{
116	unsigned int	i;
117
118	for (i = 0; i < sizeof(supported_types)/sizeof(struct pkttypes); i++)
119	{
120		if(supported_types[i].pkttype==info->pkttype)
121		{
122			printf("%s ", supported_types[i].name);
123			return;
124		}
125	}
126
127	printf("%d ", info->pkttype);	/* in case we didn't find an entry in named-packtes */
128}
129
130static void pkttype_print(const void *ip, const struct xt_entry_match *match,
131                          int numeric)
132{
133	const struct xt_pkttype_info *info = (const void *)match->data;
134
135	printf("PKTTYPE %s= ", info->invert?"!":"");
136	print_pkttype(info);
137}
138
139static void pkttype_save(const void *ip, const struct xt_entry_match *match)
140{
141	const struct xt_pkttype_info *info = (const void *)match->data;
142
143	printf("%s--pkt-type ", info->invert ? "! " : "");
144	print_pkttype(info);
145}
146
147static struct xtables_match pkttype_match = {
148	.family		= AF_UNSPEC,
149	.name		= "pkttype",
150	.version	= XTABLES_VERSION,
151	.size		= XT_ALIGN(sizeof(struct xt_pkttype_info)),
152	.userspacesize	= XT_ALIGN(sizeof(struct xt_pkttype_info)),
153	.help		= pkttype_help,
154	.parse		= pkttype_parse,
155	.final_check	= pkttype_check,
156	.print		= pkttype_print,
157	.save		= pkttype_save,
158	.extra_opts	= pkttype_opts,
159};
160
161void _init(void)
162{
163	xtables_register_match(&pkttype_match);
164}
165