libxt_pkttype.c revision 69f564e3890976461de0016cd81171ff8bfa8353
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 < sizeof(supported_types)/sizeof(struct pkttypes); i++) 50 { 51 if(supported_types[i].printhelp == 1) 52 printf("\t%-14s\t\t%s\n", supported_types[i].name, supported_types[i].help); 53 } 54 printf("\n"); 55} 56 57static void pkttype_help(void) 58{ 59 printf( 60"pkttype match options:\n" 61"[!] --pkt-type packettype match packet type\n"); 62 print_types(); 63} 64 65static const struct option pkttype_opts[] = { 66 {"pkt-type", 1, NULL, '1'}, 67 { .name = NULL } 68}; 69 70static void parse_pkttype(const char *pkttype, struct xt_pkttype_info *info) 71{ 72 unsigned int i; 73 74 for (i = 0; i < sizeof(supported_types)/sizeof(struct pkttypes); i++) 75 { 76 if(strcasecmp(pkttype, supported_types[i].name)==0) 77 { 78 info->pkttype=supported_types[i].pkttype; 79 return; 80 } 81 } 82 83 xtables_error(PARAMETER_PROBLEM, "Bad packet type '%s'", pkttype); 84} 85 86static int pkttype_parse(int c, char **argv, int invert, unsigned int *flags, 87 const void *entry, struct xt_entry_match **match) 88{ 89 struct xt_pkttype_info *info = (struct xt_pkttype_info *)(*match)->data; 90 91 switch(c) 92 { 93 case '1': 94 xtables_check_inverse(optarg, &invert, &optind, 0); 95 parse_pkttype(argv[optind-1], info); 96 if(invert) 97 info->invert=1; 98 *flags=1; 99 break; 100 101 default: 102 return 0; 103 } 104 105 return 1; 106} 107 108static void pkttype_check(unsigned int flags) 109{ 110 if (!flags) 111 xtables_error(PARAMETER_PROBLEM, "You must specify \"--pkt-type\""); 112} 113 114static void print_pkttype(const struct xt_pkttype_info *info) 115{ 116 unsigned int i; 117 118 for (i = 0; i < sizeof(supported_types)/sizeof(struct pkttypes); i++) 119 { 120 if(supported_types[i].pkttype==info->pkttype) 121 { 122 printf("%s ", supported_types[i].name); 123 return; 124 } 125 } 126 127 printf("%d ", info->pkttype); /* in case we didn't find an entry in named-packtes */ 128} 129 130static void pkttype_print(const void *ip, const struct xt_entry_match *match, 131 int numeric) 132{ 133 const struct xt_pkttype_info *info = (const void *)match->data; 134 135 printf("PKTTYPE %s= ", info->invert?"!":""); 136 print_pkttype(info); 137} 138 139static void pkttype_save(const void *ip, const struct xt_entry_match *match) 140{ 141 const struct xt_pkttype_info *info = (const void *)match->data; 142 143 printf("%s--pkt-type ", info->invert ? "! " : ""); 144 print_pkttype(info); 145} 146 147static struct xtables_match pkttype_match = { 148 .family = AF_UNSPEC, 149 .name = "pkttype", 150 .version = XTABLES_VERSION, 151 .size = XT_ALIGN(sizeof(struct xt_pkttype_info)), 152 .userspacesize = XT_ALIGN(sizeof(struct xt_pkttype_info)), 153 .help = pkttype_help, 154 .parse = pkttype_parse, 155 .final_check = pkttype_check, 156 .print = pkttype_print, 157 .save = pkttype_save, 158 .extra_opts = pkttype_opts, 159}; 160 161void _init(void) 162{ 163 xtables_register_match(&pkttype_match); 164} 165