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