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 <iptables.h> 18#include <linux/if_packet.h> 19#include <linux/netfilter_ipv4/ipt_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() 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 57/* Function which prints out usage message. */ 58static void help(void) 59{ 60 printf( 61"pkt_type v%s options:\n" 62" --pkt-type [!] packettype\tmatch packet type\n" 63"\n", PKTTYPE_VERSION); 64 print_types(); 65} 66 67static struct option opts[] = { 68 {"pkt-type", 1, 0, '1'}, 69 {0} 70}; 71 72static void parse_pkttype(const char *pkttype, struct ipt_pkttype_info *info) 73{ 74 unsigned int i; 75 76 for (i = 0; i < sizeof(supported_types)/sizeof(struct pkttypes); i++) 77 { 78 if(strcasecmp(pkttype, supported_types[i].name)==0) 79 { 80 info->pkttype=supported_types[i].pkttype; 81 return; 82 } 83 } 84 85 exit_error(PARAMETER_PROBLEM, "Bad packet type '%s'", pkttype); 86} 87 88static int parse(int c, char **argv, int invert, unsigned int *flags, 89 const struct ipt_entry *entry, 90 unsigned int *nfcache, 91 struct ipt_entry_match **match) 92{ 93 struct ipt_pkttype_info *info = (struct ipt_pkttype_info *)(*match)->data; 94 95 switch(c) 96 { 97 case '1': 98 check_inverse(optarg, &invert, &optind, 0); 99 parse_pkttype(argv[optind-1], info); 100 if(invert) 101 info->invert=1; 102 *flags=1; 103 break; 104 105 default: 106 return 0; 107 } 108 109 return 1; 110} 111 112static void final_check(unsigned int flags) 113{ 114 if (!flags) 115 exit_error(PARAMETER_PROBLEM, "You must specify `--pkt-type'"); 116} 117 118static void print_pkttype(struct ipt_pkttype_info *info) 119{ 120 unsigned int i; 121 122 for (i = 0; i < sizeof(supported_types)/sizeof(struct pkttypes); i++) 123 { 124 if(supported_types[i].pkttype==info->pkttype) 125 { 126 printf("%s ", supported_types[i].name); 127 return; 128 } 129 } 130 131 printf("%d ", info->pkttype); /* in case we didn't find an entry in named-packtes */ 132} 133 134static void print(const struct ipt_ip *ip, const struct ipt_entry_match *match, int numeric) 135{ 136 struct ipt_pkttype_info *info = (struct ipt_pkttype_info *)match->data; 137 138 printf("PKTTYPE %s= ", info->invert?"!":""); 139 print_pkttype(info); 140} 141 142static void save(const struct ipt_ip *ip, const struct ipt_entry_match *match) 143{ 144 struct ipt_pkttype_info *info = (struct ipt_pkttype_info *)match->data; 145 146 printf("--pkt-type %s", info->invert?"! ":""); 147 print_pkttype(info); 148} 149 150static struct iptables_match pkttype = { 151 .next = NULL, 152 .name = "pkttype", 153 .version = IPTABLES_VERSION, 154 .size = IPT_ALIGN(sizeof(struct ipt_pkttype_info)), 155 .userspacesize = IPT_ALIGN(sizeof(struct ipt_pkttype_info)), 156 .help = &help, 157 .parse = &parse, 158 .final_check = &final_check, 159 .print = &print, 160 .save = &save, 161 .extra_opts = opts 162}; 163 164void _init(void) 165{ 166 register_match(&pkttype); 167} 168