Correct PPTP server firewall rules chain.
[tomato/davidwu.git] / release / src / router / ebtables / extensions / ebt_ip.c
blob4e0b7f0780302c8fc5f60128c8c614f6636955e0
1 /* ebt_ip
2 *
3 * Authors:
4 * Bart De Schuymer <bdschuym@pandora.be>
6 * Changes:
7 * added ip-sport and ip-dport; parsing of port arguments is
8 * based on code from iptables-1.2.7a
9 * Innominate Security Technologies AG <mhopf@innominate.com>
10 * September, 2002
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <getopt.h>
17 #include <netdb.h>
18 #include "../include/ebtables_u.h"
19 #include <linux/netfilter_bridge/ebt_ip.h>
21 #define IP_SOURCE '1'
22 #define IP_DEST '2'
23 #define IP_myTOS '3' /* include/bits/in.h seems to already define IP_TOS */
24 #define IP_PROTO '4'
25 #define IP_SPORT '5'
26 #define IP_DPORT '6'
28 static struct option opts[] =
30 { "ip-source" , required_argument, 0, IP_SOURCE },
31 { "ip-src" , required_argument, 0, IP_SOURCE },
32 { "ip-destination" , required_argument, 0, IP_DEST },
33 { "ip-dst" , required_argument, 0, IP_DEST },
34 { "ip-tos" , required_argument, 0, IP_myTOS },
35 { "ip-protocol" , required_argument, 0, IP_PROTO },
36 { "ip-proto" , required_argument, 0, IP_PROTO },
37 { "ip-source-port" , required_argument, 0, IP_SPORT },
38 { "ip-sport" , required_argument, 0, IP_SPORT },
39 { "ip-destination-port" , required_argument, 0, IP_DPORT },
40 { "ip-dport" , required_argument, 0, IP_DPORT },
41 { 0 }
44 /* put the mask into 4 bytes */
45 /* transform a protocol and service name into a port number */
46 static uint16_t parse_port(const char *protocol, const char *name)
48 struct servent *service;
49 char *end;
50 int port;
52 port = strtol(name, &end, 10);
53 if (*end != '\0') {
54 if (protocol &&
55 (service = getservbyname(name, protocol)) != NULL)
56 return ntohs(service->s_port);
58 else if (port >= 0 || port <= 0xFFFF) {
59 return port;
61 ebt_print_error("Problem with specified %s port '%s'",
62 protocol?protocol:"", name);
63 return 0;
66 static void
67 parse_port_range(const char *protocol, const char *portstring, uint16_t *ports)
69 char *buffer;
70 char *cp;
72 buffer = strdup(portstring);
73 if ((cp = strchr(buffer, ':')) == NULL)
74 ports[0] = ports[1] = parse_port(protocol, buffer);
75 else {
76 *cp = '\0';
77 cp++;
78 ports[0] = buffer[0] ? parse_port(protocol, buffer) : 0;
79 if (ebt_errormsg[0] != '\0')
80 return;
81 ports[1] = cp[0] ? parse_port(protocol, cp) : 0xFFFF;
82 if (ebt_errormsg[0] != '\0')
83 return;
85 if (ports[0] > ports[1])
86 ebt_print_error("Invalid portrange (min > max)");
88 free(buffer);
91 static void print_port_range(uint16_t *ports)
93 if (ports[0] == ports[1])
94 printf("%d ", ports[0]);
95 else
96 printf("%d:%d ", ports[0], ports[1]);
99 static void print_help()
101 printf(
102 "ip options:\n"
103 "--ip-src [!] address[/mask]: ip source specification\n"
104 "--ip-dst [!] address[/mask]: ip destination specification\n"
105 "--ip-tos [!] tos : ip tos specification\n"
106 "--ip-proto [!] protocol : ip protocol specification\n"
107 "--ip-sport [!] port[:port] : tcp/udp source port or port range\n"
108 "--ip-dport [!] port[:port] : tcp/udp destination port or port range\n");
111 static void init(struct ebt_entry_match *match)
113 struct ebt_ip_info *ipinfo = (struct ebt_ip_info *)match->data;
115 ipinfo->invflags = 0;
116 ipinfo->bitmask = 0;
119 #define OPT_SOURCE 0x01
120 #define OPT_DEST 0x02
121 #define OPT_TOS 0x04
122 #define OPT_PROTO 0x08
123 #define OPT_SPORT 0x10
124 #define OPT_DPORT 0x20
125 static int parse(int c, char **argv, int argc, const struct ebt_u_entry *entry,
126 unsigned int *flags, struct ebt_entry_match **match)
128 struct ebt_ip_info *ipinfo = (struct ebt_ip_info *)(*match)->data;
129 char *end;
130 long int i;
132 switch (c) {
133 case IP_SOURCE:
134 ebt_check_option2(flags, OPT_SOURCE);
135 ipinfo->bitmask |= EBT_IP_SOURCE;
137 case IP_DEST:
138 if (c == IP_DEST) {
139 ebt_check_option2(flags, OPT_DEST);
140 ipinfo->bitmask |= EBT_IP_DEST;
142 if (ebt_check_inverse2(optarg)) {
143 if (c == IP_SOURCE)
144 ipinfo->invflags |= EBT_IP_SOURCE;
145 else
146 ipinfo->invflags |= EBT_IP_DEST;
148 if (c == IP_SOURCE)
149 ebt_parse_ip_address(optarg, &ipinfo->saddr, &ipinfo->smsk);
150 else
151 ebt_parse_ip_address(optarg, &ipinfo->daddr, &ipinfo->dmsk);
152 break;
154 case IP_SPORT:
155 case IP_DPORT:
156 if (c == IP_SPORT) {
157 ebt_check_option2(flags, OPT_SPORT);
158 ipinfo->bitmask |= EBT_IP_SPORT;
159 if (ebt_check_inverse2(optarg))
160 ipinfo->invflags |= EBT_IP_SPORT;
161 } else {
162 ebt_check_option2(flags, OPT_DPORT);
163 ipinfo->bitmask |= EBT_IP_DPORT;
164 if (ebt_check_inverse2(optarg))
165 ipinfo->invflags |= EBT_IP_DPORT;
167 if (c == IP_SPORT)
168 parse_port_range(NULL, optarg, ipinfo->sport);
169 else
170 parse_port_range(NULL, optarg, ipinfo->dport);
171 break;
173 case IP_myTOS:
174 ebt_check_option2(flags, OPT_TOS);
175 if (ebt_check_inverse2(optarg))
176 ipinfo->invflags |= EBT_IP_TOS;
177 i = strtol(optarg, &end, 16);
178 if (i < 0 || i > 255 || *end != '\0')
179 ebt_print_error2("Problem with specified IP tos");
180 ipinfo->tos = i;
181 ipinfo->bitmask |= EBT_IP_TOS;
182 break;
184 case IP_PROTO:
185 ebt_check_option2(flags, OPT_PROTO);
186 if (ebt_check_inverse2(optarg))
187 ipinfo->invflags |= EBT_IP_PROTO;
188 i = strtoul(optarg, &end, 10);
189 if (*end != '\0') {
190 struct protoent *pe;
192 pe = getprotobyname(optarg);
193 if (pe == NULL)
194 ebt_print_error("Unknown specified IP protocol - %s", argv[optind - 1]);
195 ipinfo->protocol = pe->p_proto;
196 } else {
197 ipinfo->protocol = (unsigned char) i;
199 ipinfo->bitmask |= EBT_IP_PROTO;
200 break;
201 default:
202 return 0;
204 return 1;
207 static void final_check(const struct ebt_u_entry *entry,
208 const struct ebt_entry_match *match, const char *name,
209 unsigned int hookmask, unsigned int time)
211 struct ebt_ip_info *ipinfo = (struct ebt_ip_info *)match->data;
213 if (entry->ethproto != ETH_P_IP || entry->invflags & EBT_IPROTO) {
214 ebt_print_error("For IP filtering the protocol must be "
215 "specified as IPv4");
216 } else if (ipinfo->bitmask & (EBT_IP_SPORT|EBT_IP_DPORT) &&
217 (!(ipinfo->bitmask & EBT_IP_PROTO) ||
218 ipinfo->invflags & EBT_IP_PROTO ||
219 (ipinfo->protocol!=IPPROTO_TCP &&
220 ipinfo->protocol!=IPPROTO_UDP &&
221 ipinfo->protocol!=IPPROTO_SCTP &&
222 ipinfo->protocol!=IPPROTO_DCCP)))
223 ebt_print_error("For port filtering the IP protocol must be "
224 "either 6 (tcp), 17 (udp), 33 (dccp) or "
225 "132 (sctp)");
228 static void print(const struct ebt_u_entry *entry,
229 const struct ebt_entry_match *match)
231 struct ebt_ip_info *ipinfo = (struct ebt_ip_info *)match->data;
232 int j;
234 if (ipinfo->bitmask & EBT_IP_SOURCE) {
235 printf("--ip-src ");
236 if (ipinfo->invflags & EBT_IP_SOURCE)
237 printf("! ");
238 for (j = 0; j < 4; j++)
239 printf("%d%s",((unsigned char *)&ipinfo->saddr)[j],
240 (j == 3) ? "" : ".");
241 printf("%s ", ebt_mask_to_dotted(ipinfo->smsk));
243 if (ipinfo->bitmask & EBT_IP_DEST) {
244 printf("--ip-dst ");
245 if (ipinfo->invflags & EBT_IP_DEST)
246 printf("! ");
247 for (j = 0; j < 4; j++)
248 printf("%d%s", ((unsigned char *)&ipinfo->daddr)[j],
249 (j == 3) ? "" : ".");
250 printf("%s ", ebt_mask_to_dotted(ipinfo->dmsk));
252 if (ipinfo->bitmask & EBT_IP_TOS) {
253 printf("--ip-tos ");
254 if (ipinfo->invflags & EBT_IP_TOS)
255 printf("! ");
256 printf("0x%02X ", ipinfo->tos);
258 if (ipinfo->bitmask & EBT_IP_PROTO) {
259 struct protoent *pe;
261 printf("--ip-proto ");
262 if (ipinfo->invflags & EBT_IP_PROTO)
263 printf("! ");
264 pe = getprotobynumber(ipinfo->protocol);
265 if (pe == NULL) {
266 printf("%d ", ipinfo->protocol);
267 } else {
268 printf("%s ", pe->p_name);
271 if (ipinfo->bitmask & EBT_IP_SPORT) {
272 printf("--ip-sport ");
273 if (ipinfo->invflags & EBT_IP_SPORT)
274 printf("! ");
275 print_port_range(ipinfo->sport);
277 if (ipinfo->bitmask & EBT_IP_DPORT) {
278 printf("--ip-dport ");
279 if (ipinfo->invflags & EBT_IP_DPORT)
280 printf("! ");
281 print_port_range(ipinfo->dport);
285 static int compare(const struct ebt_entry_match *m1,
286 const struct ebt_entry_match *m2)
288 struct ebt_ip_info *ipinfo1 = (struct ebt_ip_info *)m1->data;
289 struct ebt_ip_info *ipinfo2 = (struct ebt_ip_info *)m2->data;
291 if (ipinfo1->bitmask != ipinfo2->bitmask)
292 return 0;
293 if (ipinfo1->invflags != ipinfo2->invflags)
294 return 0;
295 if (ipinfo1->bitmask & EBT_IP_SOURCE) {
296 if (ipinfo1->saddr != ipinfo2->saddr)
297 return 0;
298 if (ipinfo1->smsk != ipinfo2->smsk)
299 return 0;
301 if (ipinfo1->bitmask & EBT_IP_DEST) {
302 if (ipinfo1->daddr != ipinfo2->daddr)
303 return 0;
304 if (ipinfo1->dmsk != ipinfo2->dmsk)
305 return 0;
307 if (ipinfo1->bitmask & EBT_IP_TOS) {
308 if (ipinfo1->tos != ipinfo2->tos)
309 return 0;
311 if (ipinfo1->bitmask & EBT_IP_PROTO) {
312 if (ipinfo1->protocol != ipinfo2->protocol)
313 return 0;
315 if (ipinfo1->bitmask & EBT_IP_SPORT) {
316 if (ipinfo1->sport[0] != ipinfo2->sport[0] ||
317 ipinfo1->sport[1] != ipinfo2->sport[1])
318 return 0;
320 if (ipinfo1->bitmask & EBT_IP_DPORT) {
321 if (ipinfo1->dport[0] != ipinfo2->dport[0] ||
322 ipinfo1->dport[1] != ipinfo2->dport[1])
323 return 0;
325 return 1;
328 static struct ebt_u_match ip_match =
330 .name = "ip",
331 .size = sizeof(struct ebt_ip_info),
332 .help = print_help,
333 .init = init,
334 .parse = parse,
335 .final_check = final_check,
336 .print = print,
337 .compare = compare,
338 .extra_ops = opts,
341 void _init(void)
343 ebt_register_match(&ip_match);