libxt_pkttype.c revision 42979363f3958b4436c6d2503753c182c58e55ea
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 <netdb.h> 9#include <string.h> 10#include <stdlib.h> 11#include <getopt.h> 12#if defined(__GLIBC__) && __GLIBC__ == 2 13#include <net/ethernet.h> 14#else 15#include <linux/if_ether.h> 16#endif 17#include <xtables.h> 18#include <linux/if_packet.h> 19#include <linux/netfilter/xt_pkttype.h> 20 21#define PKTTYPE_VERSION "0.1" 22 23struct pkttypes { 24 const char *name; 25 unsigned char pkttype; 26 unsigned char printhelp; 27 const char *help; 28}; 29 30static const struct pkttypes supported_types[] = { 31 {"unicast", PACKET_HOST, 1, "to us"}, 32 {"broadcast", PACKET_BROADCAST, 1, "to all"}, 33 {"multicast", PACKET_MULTICAST, 1, "to group"}, 34/* 35 {"otherhost", PACKET_OTHERHOST, 1, "to someone else"}, 36 {"outgoing", PACKET_OUTGOING, 1, "outgoing of any type"}, 37*/ 38 /* aliases */ 39 {"bcast", PACKET_BROADCAST, 0, NULL}, 40 {"mcast", PACKET_MULTICAST, 0, NULL}, 41 {"host", PACKET_HOST, 0, NULL} 42}; 43 44static void print_types(void) 45{ 46 unsigned int i; 47 48 printf("Valid packet types:\n"); 49 for (i = 0; i < ARRAY_SIZE(supported_types); ++i) 50 if(supported_types[i].printhelp == 1) 51 printf("\t%-14s\t\t%s\n", supported_types[i].name, supported_types[i].help); 52 printf("\n"); 53} 54 55static void pkttype_help(void) 56{ 57 printf( 58"pkttype match options:\n" 59"[!] --pkt-type packettype match packet type\n"); 60 print_types(); 61} 62 63static const struct option pkttype_opts[] = { 64 {"pkt-type", 1, NULL, '1'}, 65 { .name = NULL } 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 int pkttype_parse(int c, char **argv, int invert, unsigned int *flags, 83 const void *entry, struct xt_entry_match **match) 84{ 85 struct xt_pkttype_info *info = (struct xt_pkttype_info *)(*match)->data; 86 87 switch(c) 88 { 89 case '1': 90 xtables_check_inverse(optarg, &invert, &optind, 0); 91 parse_pkttype(argv[optind-1], info); 92 if(invert) 93 info->invert=1; 94 *flags=1; 95 break; 96 97 default: 98 return 0; 99 } 100 101 return 1; 102} 103 104static void pkttype_check(unsigned int flags) 105{ 106 if (!flags) 107 xtables_error(PARAMETER_PROBLEM, "You must specify \"--pkt-type\""); 108} 109 110static void print_pkttype(const struct xt_pkttype_info *info) 111{ 112 unsigned int i; 113 114 for (i = 0; i < ARRAY_SIZE(supported_types); ++i) 115 if(supported_types[i].pkttype==info->pkttype) 116 { 117 printf("%s ", supported_types[i].name); 118 return; 119 } 120 121 printf("%d ", info->pkttype); /* in case we didn't find an entry in named-packtes */ 122} 123 124static void pkttype_print(const void *ip, const struct xt_entry_match *match, 125 int numeric) 126{ 127 const struct xt_pkttype_info *info = (const void *)match->data; 128 129 printf("PKTTYPE %s= ", info->invert?"!":""); 130 print_pkttype(info); 131} 132 133static void pkttype_save(const void *ip, const struct xt_entry_match *match) 134{ 135 const struct xt_pkttype_info *info = (const void *)match->data; 136 137 printf("%s--pkt-type ", info->invert ? "! " : ""); 138 print_pkttype(info); 139} 140 141static struct xtables_match pkttype_match = { 142 .family = NFPROTO_UNSPEC, 143 .name = "pkttype", 144 .version = XTABLES_VERSION, 145 .size = XT_ALIGN(sizeof(struct xt_pkttype_info)), 146 .userspacesize = XT_ALIGN(sizeof(struct xt_pkttype_info)), 147 .help = pkttype_help, 148 .parse = pkttype_parse, 149 .final_check = pkttype_check, 150 .print = pkttype_print, 151 .save = pkttype_save, 152 .extra_opts = pkttype_opts, 153}; 154 155void _init(void) 156{ 157 xtables_register_match(&pkttype_match); 158} 159