blob: f05a2316c45ea72e950473f881bb507f57a6ff42 [file] [log] [blame]
Harald Welteb5166472001-04-19 16:35:39 +00001/*
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
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 {"host", 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 {"for-us", PACKET_HOST, 0, NULL}
42};
43
44static 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. */
58static 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
67static struct option opts[] = {
68 {"pkt-type", 1, 0, '1'},
69 {0}
70};
71
72static void init(struct ipt_entry_match *m, unsigned int *nfcache)
73{
74 *nfcache |= NFC_UNKNOWN;
75}
76
77static void parse_pkttype(const char *pkttype, struct ipt_pkttype_info *info)
78{
79 unsigned int i;
80
81 for (i = 0; i < sizeof(supported_types)/sizeof(struct pkttypes); i++)
82 {
83 if(strcasecmp(pkttype, supported_types[i].name)==0)
84 {
85 info->pkttype=supported_types[i].pkttype;
86 return;
87 }
88 }
89
90 exit_error(PARAMETER_PROBLEM, "Bad packet type '%s'", pkttype);
91}
92
93static int parse(int c, char **argv, int invert, unsigned int *flags,
94 const struct ipt_entry *entry,
95 unsigned int *nfcache,
96 struct ipt_entry_match **match)
97{
98 struct ipt_pkttype_info *info = (struct ipt_pkttype_info *)(*match)->data;
99
100 switch(c)
101 {
102 case '1':
103 if(check_inverse(optarg, &invert))
104 optind++;
105 parse_pkttype(argv[optind-1], info);
106 if(invert)
107 info->invert=1;
108 *flags=1;
109 break;
110
111 default:
112 return 0;
113 }
114
115 return 1;
116}
117
118static void final_check(unsigned int flags)
119{
120 if (!flags)
121 exit_error(PARAMETER_PROBLEM, "You must specify `--pkt-type'");
122}
123
124static void print_pkttype(struct ipt_pkttype_info *info)
125{
126 unsigned int i;
127
128 for (i = 0; i < sizeof(supported_types)/sizeof(struct pkttypes); i++)
129 {
130 if(supported_types[i].pkttype==info->pkttype)
131 {
132 printf("%s ", supported_types[i].name);
133 return;
134 }
135 }
136
137 printf("%d ", info->pkttype); /* in case we didn't find an entry in named-packtes */
138}
139
140static void print(const struct ipt_ip *ip, const struct ipt_entry_match *match, int numeric)
141{
142 struct ipt_pkttype_info *info = (struct ipt_pkttype_info *)match->data;
143
144 printf("PKTTYPE %s= ", info->invert?"!":"");
145 print_pkttype(info);
146}
147
148static void save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
149{
150 struct ipt_pkttype_info *info = (struct ipt_pkttype_info *)match->data;
151
152 printf("--pkt-type %s", info->invert?"! ":"");
153 print_pkttype(info);
154}
155
156struct iptables_match pkttype = {
157 NULL,
158 "pkttype",
159 NETFILTER_VERSION,
160 IPT_ALIGN(sizeof(struct ipt_pkttype_info)),
161 IPT_ALIGN(sizeof(struct ipt_pkttype_info)),
162 &help,
163 &init,
164 &parse,
165 &final_check,
166 &print,
167 &save,
168 opts
169};
170
171void _init(void)
172{
173 register_match(&pkttype);
174}