iptables-1.2.9-2.3.1.src.rpm
[iptables.git] / extensions / libipt_pkttype.c
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
23 struct pkttypes {
24         const char *name;
25         unsigned char pkttype;
26         unsigned char printhelp;
27         const char *help;
28 };
29
30 static 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
44 static 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. */
58 static 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
67 static struct option opts[] = {
68         {"pkt-type", 1, 0, '1'},
69         {0}
70 };
71
72 static void init(struct ipt_entry_match *m, unsigned int *nfcache)
73 {
74         *nfcache |= NFC_UNKNOWN;
75 }
76
77 static void parse_pkttype(const char *pkttype, struct ipt_pkttype_info *info)
78 {
79         unsigned int    i;
80         
81         for (i = 0; i < sizeof(supported_types)/sizeof(struct pkttypes); i++)
82         {
83                 if(strcasecmp(pkttype, supported_types[i].name)==0)
84                 {
85                         info->pkttype=supported_types[i].pkttype;
86                         return;
87                 }
88         }
89         
90         exit_error(PARAMETER_PROBLEM, "Bad packet type '%s'", pkttype);
91 }
92
93 static int parse(int c, char **argv, int invert, unsigned int *flags,
94       const struct ipt_entry *entry,
95       unsigned int *nfcache,
96       struct ipt_entry_match **match)
97 {
98         struct ipt_pkttype_info *info = (struct ipt_pkttype_info *)(*match)->data;
99         
100         switch(c)
101         {
102                 case '1':
103                         check_inverse(optarg, &invert, &optind, 0);
104                         parse_pkttype(argv[optind-1], info);
105                         if(invert)
106                                 info->invert=1;
107                         *flags=1;
108                         break;
109
110                 default: 
111                         return 0;
112         }
113
114         return 1;
115 }
116
117 static void final_check(unsigned int flags)
118 {
119         if (!flags)
120                 exit_error(PARAMETER_PROBLEM, "You must specify `--pkt-type'");
121 }
122
123 static void print_pkttype(struct ipt_pkttype_info *info)
124 {
125         unsigned int    i;
126         
127         for (i = 0; i < sizeof(supported_types)/sizeof(struct pkttypes); i++)
128         {
129                 if(supported_types[i].pkttype==info->pkttype)
130                 {
131                         printf("%s ", supported_types[i].name);
132                         return;
133                 }
134         }
135
136         printf("%d ", info->pkttype);   /* in case we didn't find an entry in named-packtes */
137 }
138
139 static void print(const struct ipt_ip *ip, const struct ipt_entry_match *match, int numeric)
140 {
141         struct ipt_pkttype_info *info = (struct ipt_pkttype_info *)match->data;
142         
143         printf("PKTTYPE %s= ", info->invert?"!":"");
144         print_pkttype(info);
145 }
146
147 static void save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
148 {
149         struct ipt_pkttype_info *info = (struct ipt_pkttype_info *)match->data;
150         
151         printf("--pkt-type %s", info->invert?"! ":"");
152         print_pkttype(info);
153 }
154
155 static
156 struct iptables_match pkttype = {
157     NULL,
158     "pkttype",
159     IPTABLES_VERSION,
160     IPT_ALIGN(sizeof(struct ipt_pkttype_info)),
161     IPT_ALIGN(sizeof(struct ipt_pkttype_info)),
162     &help,
163     &init,
164     &parse, 
165     &final_check, 
166     &print,
167     &save, 
168     opts
169 };
170
171 void _init(void)
172 {
173         register_match(&pkttype);
174 }