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 13enum { 14 O_PKTTYPE = 0, 15}; 16 17struct pkttypes { 18 const char *name; 19 unsigned char pkttype; 20 unsigned char printhelp; 21 const char *help; 22}; 23 24struct pkttypes_xlate { 25 const char *name; 26 unsigned char pkttype; 27}; 28 29static 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 43static 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 54static 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 62static 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 68static 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 82static 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 92static 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 106static 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 115static 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 123static const struct pkttypes_xlate supported_types_xlate[] = { 124 {"unicast", PACKET_HOST}, 125 {"broadcast", PACKET_BROADCAST}, 126 {"multicast", PACKET_MULTICAST}, 127}; 128 129static 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 143static 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 154static 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 168void _init(void) 169{ 170 xtables_register_match(&pkttype_match); 171} 172