Home | History | Annotate | Download | only in extensions
      1 /*
      2  * Shared library add-on to iptables to match
      3  * packets by their type (BROADCAST, UNICAST, MULTICAST).
      4  *
      5  * Michal Ludvig <michal (at) 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 
     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 
     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 
     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 
     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 
     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 
    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 
    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 
    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 
    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 
    168 void _init(void)
    169 {
    170 	xtables_register_match(&pkttype_match);
    171 }
    172