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 static const struct pkttypes supported_types[] = { 25 {"unicast", PACKET_HOST, 1, "to us"}, 26 {"broadcast", PACKET_BROADCAST, 1, "to all"}, 27 {"multicast", PACKET_MULTICAST, 1, "to group"}, 28 /* 29 {"otherhost", PACKET_OTHERHOST, 1, "to someone else"}, 30 {"outgoing", PACKET_OUTGOING, 1, "outgoing of any type"}, 31 */ 32 /* aliases */ 33 {"bcast", PACKET_BROADCAST, 0, NULL}, 34 {"mcast", PACKET_MULTICAST, 0, NULL}, 35 {"host", PACKET_HOST, 0, NULL} 36 }; 37 38 static void print_types(void) 39 { 40 unsigned int i; 41 42 printf("Valid packet types:\n"); 43 for (i = 0; i < ARRAY_SIZE(supported_types); ++i) 44 if(supported_types[i].printhelp == 1) 45 printf("\t%-14s\t\t%s\n", supported_types[i].name, supported_types[i].help); 46 printf("\n"); 47 } 48 49 static void pkttype_help(void) 50 { 51 printf( 52 "pkttype match options:\n" 53 "[!] --pkt-type packettype match packet type\n"); 54 print_types(); 55 } 56 57 static const struct xt_option_entry pkttype_opts[] = { 58 {.name = "pkt-type", .id = O_PKTTYPE, .type = XTTYPE_STRING, 59 .flags = XTOPT_MAND | XTOPT_INVERT}, 60 XTOPT_TABLEEND, 61 }; 62 63 static void parse_pkttype(const char *pkttype, struct xt_pkttype_info *info) 64 { 65 unsigned int i; 66 67 for (i = 0; i < ARRAY_SIZE(supported_types); ++i) 68 if(strcasecmp(pkttype, supported_types[i].name)==0) 69 { 70 info->pkttype=supported_types[i].pkttype; 71 return; 72 } 73 74 xtables_error(PARAMETER_PROBLEM, "Bad packet type '%s'", pkttype); 75 } 76 77 static void pkttype_parse(struct xt_option_call *cb) 78 { 79 struct xt_pkttype_info *info = cb->data; 80 81 xtables_option_parse(cb); 82 parse_pkttype(cb->arg, info); 83 if (cb->invert) 84 info->invert = 1; 85 } 86 87 static void print_pkttype(const struct xt_pkttype_info *info) 88 { 89 unsigned int i; 90 91 for (i = 0; i < ARRAY_SIZE(supported_types); ++i) 92 if(supported_types[i].pkttype==info->pkttype) 93 { 94 printf("%s", supported_types[i].name); 95 return; 96 } 97 98 printf("%d", info->pkttype); /* in case we didn't find an entry in named-packtes */ 99 } 100 101 static void pkttype_print(const void *ip, const struct xt_entry_match *match, 102 int numeric) 103 { 104 const struct xt_pkttype_info *info = (const void *)match->data; 105 106 printf(" PKTTYPE %s= ", info->invert ? "!" : ""); 107 print_pkttype(info); 108 } 109 110 static void pkttype_save(const void *ip, const struct xt_entry_match *match) 111 { 112 const struct xt_pkttype_info *info = (const void *)match->data; 113 114 printf("%s --pkt-type ", info->invert ? " !" : ""); 115 print_pkttype(info); 116 } 117 118 static struct xtables_match pkttype_match = { 119 .family = NFPROTO_UNSPEC, 120 .name = "pkttype", 121 .version = XTABLES_VERSION, 122 .size = XT_ALIGN(sizeof(struct xt_pkttype_info)), 123 .userspacesize = XT_ALIGN(sizeof(struct xt_pkttype_info)), 124 .help = pkttype_help, 125 .print = pkttype_print, 126 .save = pkttype_save, 127 .x6_parse = pkttype_parse, 128 .x6_options = pkttype_opts, 129 }; 130 131 void _init(void) 132 { 133 xtables_register_match(&pkttype_match); 134 } 135