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 <string.h>
9 #include <xtables.h>
10 #include <linux/if_packet.h>
11 #include <linux/netfilter/xt_pkttype.h>
12
13 enum {
14 O_PKTTYPE = 0,
15 };
16
17 struct pkttypes {
18 const char *name;
19 unsigned char pkttype;
20 unsigned char printhelp;
21 const char *help;
22 };
23
24 struct pkttypes_xlate {
25 const char *name;
26 unsigned char pkttype;
27 };
28
29 static const struct pkttypes supported_types[] = {
30 {"unicast", PACKET_HOST, 1, "to us"},
31 {"broadcast", PACKET_BROADCAST, 1, "to all"},
32 {"multicast", PACKET_MULTICAST, 1, "to group"},
33 /*
34 {"otherhost", PACKET_OTHERHOST, 1, "to someone else"},
35 {"outgoing", PACKET_OUTGOING, 1, "outgoing of any type"},
36 */
37 /* aliases */
38 {"bcast", PACKET_BROADCAST, 0, NULL},
39 {"mcast", PACKET_MULTICAST, 0, NULL},
40 {"host", PACKET_HOST, 0, NULL}
41 };
42
print_types(void)43 static void print_types(void)
44 {
45 unsigned int i;
46
47 printf("Valid packet types:\n");
48 for (i = 0; i < ARRAY_SIZE(supported_types); ++i)
49 if(supported_types[i].printhelp == 1)
50 printf("\t%-14s\t\t%s\n", supported_types[i].name, supported_types[i].help);
51 printf("\n");
52 }
53
pkttype_help(void)54 static void pkttype_help(void)
55 {
56 printf(
57 "pkttype match options:\n"
58 "[!] --pkt-type packettype match packet type\n");
59 print_types();
60 }
61
62 static const struct xt_option_entry pkttype_opts[] = {
63 {.name = "pkt-type", .id = O_PKTTYPE, .type = XTTYPE_STRING,
64 .flags = XTOPT_MAND | XTOPT_INVERT},
65 XTOPT_TABLEEND,
66 };
67
parse_pkttype(const char * pkttype,struct xt_pkttype_info * info)68 static 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
pkttype_parse(struct xt_option_call * cb)82 static void pkttype_parse(struct xt_option_call *cb)
83 {
84 struct xt_pkttype_info *info = cb->data;
85
86 xtables_option_parse(cb);
87 parse_pkttype(cb->arg, info);
88 if (cb->invert)
89 info->invert = 1;
90 }
91
print_pkttype(const struct xt_pkttype_info * info)92 static void print_pkttype(const struct xt_pkttype_info *info)
93 {
94 unsigned int i;
95
96 for (i = 0; i < ARRAY_SIZE(supported_types); ++i)
97 if(supported_types[i].pkttype==info->pkttype)
98 {
99 printf("%s", supported_types[i].name);
100 return;
101 }
102
103 printf("%d", info->pkttype); /* in case we didn't find an entry in named-packtes */
104 }
105
pkttype_print(const void * ip,const struct xt_entry_match * match,int numeric)106 static void pkttype_print(const void *ip, const struct xt_entry_match *match,
107 int numeric)
108 {
109 const struct xt_pkttype_info *info = (const void *)match->data;
110
111 printf(" PKTTYPE %s= ", info->invert ? "!" : "");
112 print_pkttype(info);
113 }
114
pkttype_save(const void * ip,const struct xt_entry_match * match)115 static void pkttype_save(const void *ip, const struct xt_entry_match *match)
116 {
117 const struct xt_pkttype_info *info = (const void *)match->data;
118
119 printf("%s --pkt-type ", info->invert ? " !" : "");
120 print_pkttype(info);
121 }
122
123 static const struct pkttypes_xlate supported_types_xlate[] = {
124 {"unicast", PACKET_HOST},
125 {"broadcast", PACKET_BROADCAST},
126 {"multicast", PACKET_MULTICAST},
127 };
128
print_pkttype_xlate(const struct xt_pkttype_info * info,struct xt_xlate * xl)129 static void print_pkttype_xlate(const struct xt_pkttype_info *info,
130 struct xt_xlate *xl)
131 {
132 unsigned int i;
133
134 for (i = 0; i < ARRAY_SIZE(supported_types_xlate); ++i) {
135 if (supported_types_xlate[i].pkttype == info->pkttype) {
136 xt_xlate_add(xl, "%s", supported_types_xlate[i].name);
137 return;
138 }
139 }
140 xt_xlate_add(xl, "%d", info->pkttype);
141 }
142
pkttype_xlate(struct xt_xlate * xl,const struct xt_xlate_mt_params * params)143 static int pkttype_xlate(struct xt_xlate *xl,
144 const struct xt_xlate_mt_params *params)
145 {
146 const struct xt_pkttype_info *info = (const void *)params->match->data;
147
148 xt_xlate_add(xl, "pkttype%s ", info->invert ? " !=" : "");
149 print_pkttype_xlate(info, xl);
150
151 return 1;
152 }
153
154 static struct xtables_match pkttype_match = {
155 .family = NFPROTO_UNSPEC,
156 .name = "pkttype",
157 .version = XTABLES_VERSION,
158 .size = XT_ALIGN(sizeof(struct xt_pkttype_info)),
159 .userspacesize = XT_ALIGN(sizeof(struct xt_pkttype_info)),
160 .help = pkttype_help,
161 .print = pkttype_print,
162 .save = pkttype_save,
163 .x6_parse = pkttype_parse,
164 .x6_options = pkttype_opts,
165 .xlate = pkttype_xlate,
166 };
167
_init(void)168 void _init(void)
169 {
170 xtables_register_match(&pkttype_match);
171 }
172