iptables-1.2.9-2.3.1.src.rpm
[iptables.git] / extensions / libipt_addrtype.c
1 /* Shared library add-on to iptables to add addrtype matching support 
2  * 
3  * This program is released under the terms of GNU GPL */
4
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <string.h>
8 #include <getopt.h>
9 #include <iptables.h>
10
11 #include <linux/netfilter_ipv4/ip_tables.h>
12 #include <linux/netfilter_ipv4/ipt_addrtype.h>
13
14 /* from linux/rtnetlink.h, must match order of enumeration */
15 static char *rtn_names[] = {
16         "UNSPEC",
17         "UNICAST",
18         "LOCAL",
19         "BROADCAST",
20         "ANYCAST",
21         "MULTICAST",
22         "BLACKHOLE",
23         "UNREACHABLE",
24         "PROHIBIT",
25         "THROW",
26         "NAT",
27         "XRESOLVE",
28         NULL
29 };
30
31 static void help_types(void)
32 {
33         int i;
34
35         for (i = 0; rtn_names[i]; i++)
36                 printf("                                %s\n", rtn_names[i]);
37 }
38
39 static void help(void) 
40 {
41         printf(
42 "Address type match v%s options:\n"
43 " [!] --src-type type[,...]      Match source address type\n"
44 " [!] --dst-type type[,...]      Match destination address type\n"
45 "\n"
46 "Valid types:           \n"
47 , IPTABLES_VERSION);
48         help_types();
49 }
50
51 static void init(struct ipt_entry_match *m, unsigned int *nfcache)
52 {
53         /* caching not yet implemented */
54         *nfcache |= NFC_UNKNOWN;
55 }
56
57 static int
58 parse_type(const char *name, size_t strlen, u_int16_t *mask)
59 {
60         int i;
61
62         for (i = 0; rtn_names[i]; i++)
63                 if (strncasecmp(name, rtn_names[i], strlen) == 0) {
64                         /* build up bitmask for kernel module */
65                         *mask |= (1 << i);
66                         return 1;
67                 }
68
69         return 0;
70 }
71
72 static void parse_types(const char *arg, u_int16_t *mask)
73 {
74         const char *comma;
75
76         while ((comma = strchr(arg, ',')) != NULL) {
77                 if (comma == arg || !parse_type(arg, comma-arg, mask))
78                         exit_error(PARAMETER_PROBLEM,
79                                    "addrtype: bad type `%s'", arg);
80                 arg = comma + 1;
81         }
82
83         if (strlen(arg) == 0 || !parse_type(arg, strlen(arg), mask))
84                 exit_error(PARAMETER_PROBLEM, "addrtype: bad type `%s'", arg);
85 }
86         
87 #define IPT_ADDRTYPE_OPT_SRCTYPE        0x1
88 #define IPT_ADDRTYPE_OPT_DSTTYPE        0x2
89
90 static int parse(int c, char **argv, int invert, unsigned int *flags,
91                 const struct ipt_entry *entry, unsigned int *nfcache,
92                 struct ipt_entry_match **match)
93 {
94         struct ipt_addrtype_info *info =
95                 (struct ipt_addrtype_info *) (*match)->data;
96
97         switch (c) {
98         case '1':
99                 if (*flags&IPT_ADDRTYPE_OPT_SRCTYPE)
100                         exit_error(PARAMETER_PROBLEM,
101                                    "addrtype: can't specify src-type twice");
102                 check_inverse(optarg, &invert, &optind, 0);
103                 parse_types(argv[optind-1], &info->source);
104                 if (invert)
105                         info->invert_source = 1;
106                 *flags |= IPT_ADDRTYPE_OPT_SRCTYPE;
107                 break;
108         case '2':
109                 if (*flags&IPT_ADDRTYPE_OPT_DSTTYPE)
110                         exit_error(PARAMETER_PROBLEM,
111                                    "addrtype: can't specify dst-type twice");
112                 check_inverse(optarg, &invert, &optind, 0);
113                 parse_types(argv[optind-1], &info->dest);
114                 if (invert)
115                         info->invert_dest = 1;
116                 *flags |= IPT_ADDRTYPE_OPT_DSTTYPE;
117                 break;
118         default:
119                 return 0;
120         }
121         
122         return 1;
123 }
124
125 static void final_check(unsigned int flags)
126 {
127         if (!(flags & (IPT_ADDRTYPE_OPT_SRCTYPE|IPT_ADDRTYPE_OPT_DSTTYPE)))
128                 exit_error(PARAMETER_PROBLEM,
129                            "addrtype: you must specify --src-type or --dst-type");
130 }
131
132 static void print_types(u_int16_t mask)
133 {
134         const char *sep = "";
135         int i;
136
137         for (i = 0; rtn_names[i]; i++)
138                 if (mask & (1 << i)) {
139                         printf("%s%s", sep, rtn_names[i]);
140                         sep = ",";
141                 }
142
143         printf(" ");
144 }
145
146 static void print(const struct ipt_ip *ip, 
147                 const struct ipt_entry_match *match,
148                 int numeric)
149 {
150         const struct ipt_addrtype_info *info = 
151                 (struct ipt_addrtype_info *) match->data;
152
153         printf("ADDRTYPE match ");
154         if (info->source) {
155                 printf("src-type ");
156                 if (info->invert_source)
157                         printf("!");
158                 print_types(info->source);
159         }
160         if (info->dest) {
161                 printf("dst-type ");
162                 if (info->invert_dest)
163                         printf("!");
164                 print_types(info->dest);
165         }
166 }
167
168 static void save(const struct ipt_ip *ip, 
169                 const struct ipt_entry_match *match)
170 {
171         const struct ipt_addrtype_info *info =
172                 (struct ipt_addrtype_info *) match->data;
173
174         if (info->source) {
175                 printf("--src-type ");
176                 if (info->invert_source)
177                         printf("! ");
178                 print_types(info->source);
179         }
180         if (info->dest) {
181                 printf("--dst-type ");
182                 if (info->invert_dest)
183                         printf("! ");
184                 print_types(info->dest);
185         }
186 }
187
188 static struct option opts[] = {
189         { "src-type", 1, 0, '1' },
190         { "dst-type", 1, 0, '2' },
191         { 0 }
192 };
193
194 static
195 struct iptables_match addrtype = {
196         NULL,
197         "addrtype",
198         IPTABLES_VERSION,
199         IPT_ALIGN(sizeof(struct ipt_addrtype_info)),
200         IPT_ALIGN(sizeof(struct ipt_addrtype_info)),
201         &help,
202         &init,
203         &parse,
204         &final_check,
205         &print,
206         &save,
207         opts
208 };
209
210
211 void _init(void) 
212 {
213         register_match(&addrtype);
214 }