• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <iptables.h>
18 #include <linux/if_packet.h>
19 #include <linux/netfilter_ipv4/ipt_pkttype.h>
20 
21 #define	PKTTYPE_VERSION	"0.1"
22 
23 struct pkttypes {
24 	const char *name;
25 	unsigned char pkttype;
26 	unsigned char printhelp;
27 	const char *help;
28 };
29 
30 static 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 
print_types()44 static void print_types()
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 
57 /* Function which prints out usage message. */
help(void)58 static void help(void)
59 {
60 	printf(
61 "pkt_type v%s options:\n"
62 "  --pkt-type [!] packettype\tmatch packet type\n"
63 "\n", PKTTYPE_VERSION);
64 	print_types();
65 }
66 
67 static struct option opts[] = {
68 	{"pkt-type", 1, 0, '1'},
69 	{0}
70 };
71 
parse_pkttype(const char * pkttype,struct ipt_pkttype_info * info)72 static void parse_pkttype(const char *pkttype, struct ipt_pkttype_info *info)
73 {
74 	unsigned int	i;
75 
76 	for (i = 0; i < sizeof(supported_types)/sizeof(struct pkttypes); i++)
77 	{
78 		if(strcasecmp(pkttype, supported_types[i].name)==0)
79 		{
80 			info->pkttype=supported_types[i].pkttype;
81 			return;
82 		}
83 	}
84 
85 	exit_error(PARAMETER_PROBLEM, "Bad packet type '%s'", pkttype);
86 }
87 
parse(int c,char ** argv,int invert,unsigned int * flags,const struct ipt_entry * entry,unsigned int * nfcache,struct ipt_entry_match ** match)88 static int parse(int c, char **argv, int invert, unsigned int *flags,
89       const struct ipt_entry *entry,
90       unsigned int *nfcache,
91       struct ipt_entry_match **match)
92 {
93 	struct ipt_pkttype_info *info = (struct ipt_pkttype_info *)(*match)->data;
94 
95 	switch(c)
96 	{
97 		case '1':
98 			check_inverse(optarg, &invert, &optind, 0);
99 			parse_pkttype(argv[optind-1], info);
100 			if(invert)
101 				info->invert=1;
102 			*flags=1;
103 			break;
104 
105 		default:
106 			return 0;
107 	}
108 
109 	return 1;
110 }
111 
final_check(unsigned int flags)112 static void final_check(unsigned int flags)
113 {
114 	if (!flags)
115 		exit_error(PARAMETER_PROBLEM, "You must specify `--pkt-type'");
116 }
117 
print_pkttype(struct ipt_pkttype_info * info)118 static void print_pkttype(struct ipt_pkttype_info *info)
119 {
120 	unsigned int	i;
121 
122 	for (i = 0; i < sizeof(supported_types)/sizeof(struct pkttypes); i++)
123 	{
124 		if(supported_types[i].pkttype==info->pkttype)
125 		{
126 			printf("%s ", supported_types[i].name);
127 			return;
128 		}
129 	}
130 
131 	printf("%d ", info->pkttype);	/* in case we didn't find an entry in named-packtes */
132 }
133 
print(const struct ipt_ip * ip,const struct ipt_entry_match * match,int numeric)134 static void print(const struct ipt_ip *ip, const struct ipt_entry_match *match, int numeric)
135 {
136 	struct ipt_pkttype_info *info = (struct ipt_pkttype_info *)match->data;
137 
138 	printf("PKTTYPE %s= ", info->invert?"!":"");
139 	print_pkttype(info);
140 }
141 
save(const struct ipt_ip * ip,const struct ipt_entry_match * match)142 static void save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
143 {
144 	struct ipt_pkttype_info *info = (struct ipt_pkttype_info *)match->data;
145 
146 	printf("--pkt-type %s", info->invert?"! ":"");
147 	print_pkttype(info);
148 }
149 
150 static struct iptables_match pkttype = {
151 	.next		= NULL,
152 	.name		= "pkttype",
153 	.version	= IPTABLES_VERSION,
154 	.size		= IPT_ALIGN(sizeof(struct ipt_pkttype_info)),
155 	.userspacesize	= IPT_ALIGN(sizeof(struct ipt_pkttype_info)),
156 	.help		= &help,
157 	.parse		= &parse,
158 	.final_check	= &final_check,
159 	.print		= &print,
160 	.save		= &save,
161 	.extra_opts	= opts
162 };
163 
ipt_pkttype_init(void)164 void ipt_pkttype_init(void)
165 {
166 	register_match(&pkttype);
167 }
168